Commit 21762fc6 authored by Matthias Braun's avatar Matthias Braun
Browse files

sparc: redo and improve sparc immediate handling (low-part after sethi is now omitted if it is 0)

[r27918]
parent 0651be96
......@@ -111,9 +111,15 @@ static const arch_register_t *get_out_reg(const ir_node *node, int pos)
void sparc_emit_immediate(const ir_node *node)
{
int const val = get_sparc_attr_const(node)->immediate_value;
assert(-4096 <= val && val < 4096);
be_emit_irprintf("%d", val);
int32_t value = get_sparc_attr_const(node)->immediate_value;
assert(-4096 <= value && value < 4096);
be_emit_irprintf("%d", value);
}
void sparc_emit_high_immediate(const ir_node *node)
{
uint32_t value = (uint32_t) get_sparc_attr_const(node)->immediate_value;
be_emit_irprintf("%%hi(0x%X)", value);
}
void sparc_emit_source_register(const ir_node *node, int pos)
......@@ -329,31 +335,6 @@ static void emit_sparc_Save(const ir_node *irn)
be_emit_finish_line_gas(irn);
}
/**
* emits code to load hi 22 bit of a constant
*/
static void emit_sparc_HiImm(const ir_node *irn)
{
const sparc_attr_t *attr = get_sparc_attr_const(irn);
be_emit_cstring("\tsethi ");
be_emit_irprintf("%%hi(%d), ", attr->immediate_value);
sparc_emit_dest_register(irn, 0);
be_emit_finish_line_gas(irn);
}
/**
* emits code to load lo 10bits of a constant
*/
static void emit_sparc_LoImm(const ir_node *irn)
{
const sparc_attr_t *attr = get_sparc_attr_const(irn);
be_emit_cstring("\tor ");
sparc_emit_source_register(irn, 0);
be_emit_irprintf(", %%lo(%d), ", attr->immediate_value);
sparc_emit_dest_register(irn, 0);
be_emit_finish_line_gas(irn);
}
/**
* emits code for mulh
*/
......@@ -849,8 +830,6 @@ static void sparc_register_emitters(void)
set_emitter(op_sparc_Call, emit_sparc_Call);
set_emitter(op_sparc_fbfcc, emit_sparc_fbfcc);
set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr);
set_emitter(op_sparc_HiImm, emit_sparc_HiImm);
set_emitter(op_sparc_LoImm, emit_sparc_LoImm);
set_emitter(op_sparc_Mulh, emit_sparc_Mulh);
set_emitter(op_sparc_Save, emit_sparc_Save);
set_emitter(op_sparc_SDiv, emit_sparc_SDiv);
......
......@@ -35,6 +35,7 @@
#include "bearch_sparc_t.h"
void sparc_emit_immediate(const ir_node *node);
void sparc_emit_high_immediate(const ir_node *node);
void sparc_emit_mode(const ir_node *node);
void sparc_emit_source_register(const ir_node *node, int pos);
void sparc_emit_reg_or_imm(const ir_node *node, int pos);
......
......@@ -147,7 +147,7 @@ static void sparc_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
}
}
static void sparc_set_attr_imm(ir_node *res, int immediate_value)
static void sparc_set_attr_imm(ir_node *res, int32_t immediate_value)
{
sparc_attr_t *attr = get_irn_generic_attr(res);
attr->immediate_value = immediate_value;
......
......@@ -26,6 +26,7 @@
#define FIRM_BE_SPARC_SPARC_NODES_ATTR_H
#include "../bearch.h"
#include <stdint.h>
typedef struct sparc_attr_t sparc_attr_t;
......@@ -36,7 +37,7 @@ struct sparc_attr_t
{
except_attr exc; /**< the exception attribute. MUST be the first one. */
const arch_register_req_t **in_req; /**< register requirements for arguments */
int immediate_value; /* immediate values */
int32_t immediate_value; /* immediate values */
bool is_load_store;
ir_entity *immediate_value_entity; /* hack for now */
......
......@@ -130,6 +130,7 @@ $state = 32; # register represents a state
D5 => "${arch}_emit_dest_register(node, 4);",
D6 => "${arch}_emit_dest_register(node, 5);",
IM => "${arch}_emit_immediate(node);",
HIM => "${arch}_emit_high_immediate(node);",
LM => "${arch}_emit_load_mode(node);",
SM => "${arch}_emit_store_mode(node);",
FLSM => "${arch}_emit_float_load_store_mode(node);",
......@@ -179,7 +180,7 @@ $default_copy_attr = "sparc_copy_attr";
my %cmp_operand_constructors = (
imm => {
attr => "int immediate_value",
attr => "int32_t immediate_value",
custominit => "sparc_set_attr_imm(res, immediate_value);",
reg_req => { in => [ "gp" ], out => [ "flags" ] },
ins => [ "left" ],
......@@ -192,7 +193,7 @@ my %cmp_operand_constructors = (
my %unop_operand_constructors = (
imm => {
attr => "int immediate_value",
attr => "int32_t immediate_value",
custominit => "sparc_set_attr_imm(res, immediate_value);",
reg_req => { in => [], out => [ "gp" ] },
},
......@@ -203,7 +204,7 @@ my %unop_operand_constructors = (
my %binop_operand_constructors = (
imm => {
attr => "int immediate_value",
attr => "int32_t immediate_value",
custominit => "sparc_set_attr_imm(res, immediate_value);",
reg_req => { in => [ "gp" ], out => [ "gp" ] },
ins => [ "left" ],
......@@ -286,25 +287,14 @@ Ld => {
emit => '. ld%LM [%S1%O], %D1'
},
HiImm => {
irn_flags => [ "rematerializable" ],
state => "exc_pinned",
outs => [ "res" ],
mode => $mode_gp,
reg_req => { in => [], out => [ "gp" ] },
attr => "int immediate_value",
custominit => "sparc_set_attr_imm(res, immediate_value);",
},
LoImm => {
irn_flags => [ "rematerializable" ],
state => "exc_pinned",
ins => [ "hireg" ],
outs => [ "res" ],
mode => $mode_gp,
reg_req => { in => [ "gp" ], out => [ "gp" ] },
attr => "int immediate_value",
SetHi => {
irn_flags => [ "rematerializable" ],
outs => [ "res" ],
mode => $mode_gp,
reg_req => { in => [], out => [ "gp" ] },
attr => "int32_t immediate_value",
custominit => "sparc_set_attr_imm(res, immediate_value);",
emit => '. sethi %HIM, %D1'
},
St => {
......@@ -326,14 +316,6 @@ St => {
emit => '. st%SM %S2, [%S1%O]'
},
Mov => {
irn_flags => [ "rematerializable" ],
arity => "variable",
emit => '. mov %R1I, %D1',
mode => $mode_gp,
constructors => \%unop_operand_constructors,
},
Save => {
reg_req => {
in => [ "sp", "none"],
......
......@@ -33,6 +33,7 @@
#include "iredges.h"
#include "ircons.h"
#include "irprintf.h"
#include "iroptimize.h"
#include "dbginfo.h"
#include "iropt_t.h"
#include "debug.h"
......@@ -151,50 +152,6 @@ static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
}
}
/**
* Creates a possible DAG for a constant.
*/
static ir_node *create_const_graph_value(dbg_info *dbgi, ir_node *block,
long value)
{
ir_node *result;
/* we need to load hi & lo separately */
if (value < -4096 || value > 4095) {
ir_node *hi = new_bd_sparc_HiImm(dbgi, block, (int) value);
result = new_bd_sparc_LoImm(dbgi, block, hi, value);
be_dep_on_frame(hi);
} else {
result = new_bd_sparc_Mov_imm(dbgi, block, (int) value);
be_dep_on_frame(result);
}
return result;
}
/**
* Create a DAG constructing a given Const.
*
* @param irn a Firm const
*/
static ir_node *create_const_graph(ir_node *irn, ir_node *block)
{
tarval *tv = get_Const_tarval(irn);
ir_mode *mode = get_tarval_mode(tv);
dbg_info *dbgi = get_irn_dbg_info(irn);
long value;
if (mode_is_reference(mode)) {
/* SPARC V8 is 32bit, so we can safely convert a reference tarval into Iu */
assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_gp));
tv = tarval_convert_to(tv, mode_gp);
}
value = get_tarval_long(tv);
return create_const_graph_value(dbgi, block, value);
}
typedef enum {
MATCH_NONE = 0,
MATCH_COMMUTATIVE = 1 << 0, /**< commutative operation. */
......@@ -202,7 +159,7 @@ typedef enum {
typedef ir_node* (*new_binop_reg_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2);
typedef ir_node* (*new_binop_fp_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode);
typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, int simm13);
typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, int32_t immediate);
typedef ir_node* (*new_unop_fp_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_mode *mode);
/**
......@@ -211,14 +168,12 @@ typedef ir_node* (*new_unop_fp_func) (dbg_info *dbgi, ir_node *block, ir_node *o
*/
static bool is_imm_encodeable(const ir_node *node)
{
long val;
long value;
if (!is_Const(node))
return false;
val = get_tarval_long(get_Const_tarval(node));
return -4096 <= val && val <= 4095;
value = get_tarval_long(get_Const_tarval(node));
return -4096 <= value && value <= 4095;
}
/**
......@@ -710,19 +665,15 @@ static ir_entity *create_float_const_entity(tarval *tv)
return entity;
}
/**
* Transforms a Const node.
*
* @param node the ir Const node
* @return The transformed sparc node.
*/
static ir_node *gen_Const(ir_node *node)
{
ir_node *block = be_transform_node(get_nodes_block(node));
ir_mode *mode = get_irn_mode(node);
ir_node *block = be_transform_node(get_nodes_block(node));
ir_mode *mode = get_irn_mode(node);
dbg_info *dbgi = get_irn_dbg_info(node);
tarval *tv;
long value;
if (mode_is_float(mode)) {
dbg_info *dbgi = get_irn_dbg_info(node);
tarval *tv = get_Const_tarval(node);
ir_entity *entity = create_float_const_entity(tv);
ir_node *addr = make_addr(dbgi, entity);
......@@ -735,12 +686,21 @@ static ir_node *gen_Const(ir_node *node)
return proj;
}
/* use the 0 register instead of a 0-constant */
if (is_Const_null(node)) {
tv = get_Const_tarval(node);
value = get_tarval_long(tv);
if (value == 0) {
return get_g0();
} else if (-4096 <= value && value <= 4095) {
return new_bd_sparc_Or_imm(dbgi, block, get_g0(), value);
} else {
ir_node *hi = new_bd_sparc_SetHi(dbgi, block, value);
be_dep_on_frame(hi);
if ((value & 0x3ff) != 0) {
return new_bd_sparc_Or_imm(dbgi, block, hi, value & 0x3ff);
} else {
return hi;
}
}
return create_const_graph(node, block);
}
static ir_mode *get_cmp_mode(ir_node *b_value)
......@@ -773,7 +733,7 @@ static ir_node *gen_Cond(ir_node *node)
// switch/case jumps
if (mode != mode_b) {
panic("SwitchJmp not supported yet");
panic("SwitchJump not implemented yet");
}
// regular if/else jumps
......@@ -965,10 +925,6 @@ static ir_node *gen_Conv(ir_node *node)
static ir_node *gen_Unknown(ir_node *node)
{
ir_node *block = get_nodes_block(node);
ir_node *new_block = be_transform_node(block);
dbg_info *dbgi = get_irn_dbg_info(node);
/* just produce a 0 */
ir_mode *mode = get_irn_mode(node);
if (mode_is_float(mode)) {
......@@ -976,7 +932,7 @@ static ir_node *gen_Unknown(ir_node *node)
be_dep_on_frame(node);
return node;
} else if (mode_needs_gp_reg(mode)) {
return create_const_graph_value(dbgi, new_block, 0);
return get_g0();
}
panic("Unexpected Unknown mode");
......@@ -1899,6 +1855,9 @@ void sparc_transform_graph(sparc_code_gen_t *cg)
node_to_stack = NULL;
be_add_missing_keeps(irg);
/* do code placement, to optimize the position of constants */
place_code(cg->irg);
}
void sparc_init_transform(void)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment