Commit 975ab11f authored by Matthias Braun's avatar Matthias Braun
Browse files

kill the concept of an unknown register - it just heavily complicates code for nearly no gain

[r27297]
parent a9b27435
......@@ -162,24 +162,6 @@ ir_node *ia32_new_NoReg_xmm(ia32_code_gen_t *cg)
&ia32_xmm_regs[REG_XMM_NOREG]);
}
ir_node *ia32_new_Unknown_gp(ia32_code_gen_t *cg)
{
return create_const(cg, &cg->unknown_gp, new_bd_ia32_Unknown_GP,
&ia32_gp_regs[REG_GP_UKNWN]);
}
ir_node *ia32_new_Unknown_vfp(ia32_code_gen_t *cg)
{
return create_const(cg, &cg->unknown_vfp, new_bd_ia32_Unknown_VFP,
&ia32_vfp_regs[REG_VFP_UKNWN]);
}
ir_node *ia32_new_Unknown_xmm(ia32_code_gen_t *cg)
{
return create_const(cg, &cg->unknown_xmm, new_bd_ia32_Unknown_XMM,
&ia32_xmm_regs[REG_XMM_UKNWN]);
}
ir_node *ia32_new_Fpu_truncate(ia32_code_gen_t *cg)
{
return create_const(cg, &cg->fpu_trunc_mode, new_bd_ia32_ChangeCW,
......@@ -894,23 +876,25 @@ static void ia32_prepare_graph(void *self)
{
ia32_code_gen_t *cg = self;
#ifdef FIRM_GRGEN_BE
switch (be_transformer) {
case TRANSFORMER_DEFAULT:
/* transform remaining nodes into assembler instructions */
ia32_transform_graph(cg);
break;
#ifdef FIRM_GRGEN_BE
case TRANSFORMER_PBQP:
case TRANSFORMER_RAND:
/* transform nodes into assembler instructions by PBQP magic */
ia32_transform_graph_by_pbqp(cg);
break;
#endif
default:
panic("invalid transformer");
}
#else
ia32_transform_graph(cg);
#endif
/* do local optimizations (mainly CSE) */
optimize_graph_df(cg->irg);
......@@ -1122,18 +1106,6 @@ static void transform_to_Store(ia32_code_gen_t *cg, ir_node *node)
sched_point = sched_prev(node);
}
/* No need to spill unknown values... */
if (is_ia32_Unknown_GP(val) ||
is_ia32_Unknown_VFP(val) ||
is_ia32_Unknown_XMM(val)) {
store = nomem;
if (sched_point)
sched_remove(node);
exchange(node, store);
return;
}
if (mode_is_float(mode)) {
if (ia32_cg_config.use_sse2)
store = new_bd_ia32_xStore(dbg, block, ptr, noreg, nomem, val);
......@@ -1992,9 +1964,7 @@ static int ia32_to_appear_in_schedule(void *block_env, const ir_node *irn)
}
if (is_ia32_NoReg_GP(irn) || is_ia32_NoReg_VFP(irn) || is_ia32_NoReg_XMM(irn)
|| is_ia32_Unknown_GP(irn) || is_ia32_Unknown_XMM(irn)
|| is_ia32_Unknown_VFP(irn) || is_ia32_ChangeCW(irn)
|| is_ia32_Immediate(irn))
|| is_ia32_ChangeCW(irn) || is_ia32_Immediate(irn))
return 0;
return 1;
......
......@@ -66,9 +66,6 @@ struct ia32_code_gen_t {
unsigned do_x87_sim:1; /**< set to 1 if x87 simulation should be enforced */
unsigned dump:1; /**< set to 1 if graphs should be dumped */
unsigned gprof:1; /**< set to 1 grof profiling is in use */
ir_node *unknown_gp; /**< unique Unknown_GP node */
ir_node *unknown_vfp; /**< unique Unknown_VFP node */
ir_node *unknown_xmm; /**< unique Unknown_XMM node */
ir_node *noreg_gp; /**< unique NoReg_GP node */
ir_node *noreg_vfp; /**< unique NoReg_VFP node */
ir_node *noreg_xmm; /**< unique NoReg_XMM node */
......@@ -137,14 +134,6 @@ ir_node *ia32_new_NoReg_gp(ia32_code_gen_t *cg);
ir_node *ia32_new_NoReg_xmm(ia32_code_gen_t *cg);
ir_node *ia32_new_NoReg_vfp(ia32_code_gen_t *cg);
/**
* Returns the unique per irg GP Unknown node.
* (warning: cse has to be activated)
*/
ir_node *ia32_new_Unknown_gp(ia32_code_gen_t *cg);
ir_node *ia32_new_Unknown_xmm(ia32_code_gen_t *cg);
ir_node *ia32_new_Unknown_vfp(ia32_code_gen_t *cg);
/**
* Returns the unique per irg FPU truncation mode node.
*/
......
......@@ -87,6 +87,9 @@ static int do_is_immediate(const ir_node *node, int *symconsts, int negate)
return 0;
return 1;
case iro_Unknown:
/* we can use '0' for Unknowns */
return 1;
case iro_Add:
case iro_Sub:
/* Add's and Sub's are typically supported as long as both operands are
......@@ -173,6 +176,8 @@ static void eat_immediate(ia32_address_t *addr, ir_node *node, int negate)
#endif
addr->symconst_sign = negate;
break;
case iro_Unknown:
break;
case iro_Add:
assert(!ia32_is_non_address_mode_node(node));
left = get_Add_left(node);
......
......@@ -448,10 +448,23 @@ static bool can_match(const arch_register_req_t *in,
return (*in->limited & *out->limited) != 0;
}
static inline ir_node *get_new_node(ir_node *node)
{
#ifdef FIRM_GRGEN_BE
if (be_transformer == TRANSFORMER_DEFAULT) {
return be_transform_node(node);
} else {
return node;
}
#else
return be_transform_node(node);
#endif
}
ir_node *gen_ASM(ir_node *node)
{
ir_node *block = NULL;
ir_node *new_block = NULL;
ir_node *block = get_nodes_block(node);
ir_node *new_block = get_new_node(block);
dbg_info *dbgi = get_irn_dbg_info(node);
int i, arity;
int out_idx;
......@@ -475,23 +488,6 @@ ir_node *gen_ASM(ir_node *node)
memset(&clobber_bits, 0, sizeof(clobber_bits));
switch (be_transformer) {
case TRANSFORMER_DEFAULT:
block = get_nodes_block(node);
new_block = be_transform_node(block);
break;
#ifdef FIRM_GRGEN_BE
case TRANSFORMER_PBQP:
case TRANSFORMER_RAND:
new_block = get_nodes_block(node);
break;
#endif
default:
panic("invalid transformer");
}
/* workaround for lots of buggy code out there as most people think volatile
* asm is enough for everything and forget the flags (linux kernel, etc.)
*/
......@@ -604,22 +600,8 @@ ir_node *gen_ASM(ir_node *node)
}
if (input == NULL) {
ir_node *pred = NULL;
switch (be_transformer) {
case TRANSFORMER_DEFAULT:
pred = get_irn_n(node, i);
input = be_transform_node(pred);
break;
#ifdef FIRM_GRGEN_BE
case TRANSFORMER_PBQP:
case TRANSFORMER_RAND:
input = get_irn_n(node, i);
break;
#endif
default: panic("invalid transformer");
}
ir_node *pred = get_irn_n(node, i);
input = get_new_node(pred);
if (parsed_constraint.cls == NULL
&& parsed_constraint.same_as < 0) {
......@@ -792,42 +774,18 @@ ir_node *gen_ASM(ir_node *node)
ir_node *gen_CopyB(ir_node *node)
{
ir_node *block = NULL;
ir_node *src = NULL;
ir_node *new_src = NULL;
ir_node *dst = NULL;
ir_node *new_dst = NULL;
ir_node *mem = NULL;
ir_node *new_mem = NULL;
ir_node *block = get_new_node(get_nodes_block(node));
ir_node *src = get_CopyB_src(node);
ir_node *new_src = get_new_node(src);
ir_node *dst = get_CopyB_dst(node);
ir_node *new_dst = get_new_node(dst);
ir_node *mem = get_CopyB_mem(node);
ir_node *new_mem = get_new_node(mem);
ir_node *res = NULL;
dbg_info *dbgi = get_irn_dbg_info(node);
int size = get_type_size_bytes(get_CopyB_type(node));
int rem;
switch (be_transformer) {
case TRANSFORMER_DEFAULT:
block = be_transform_node(get_nodes_block(node));
src = get_CopyB_src(node);
new_src = be_transform_node(src);
dst = get_CopyB_dst(node);
new_dst = be_transform_node(dst);
mem = get_CopyB_mem(node);
new_mem = be_transform_node(mem);
break;
#ifdef FIRM_GRGEN_BE
case TRANSFORMER_PBQP:
case TRANSFORMER_RAND:
block = get_nodes_block(node);
new_src = get_CopyB_src(node);
new_dst = get_CopyB_dst(node);
new_mem = get_CopyB_mem(node);
break;
#endif
default: panic("invalid transformer");
}
/* If we have to copy more than 32 bytes, we use REP MOVSx and */
/* then we need the size explicitly in ECX. */
if (size >= 32 * 4) {
......@@ -853,53 +811,36 @@ ir_node *gen_CopyB(ir_node *node)
ir_node *gen_Proj_tls(ir_node *node)
{
ir_node *block = NULL;
dbg_info *dbgi = NULL;
ir_node *res = NULL;
switch (be_transformer) {
case TRANSFORMER_DEFAULT:
block = be_transform_node(get_nodes_block(node));
break;
ir_node *block = get_new_node(get_nodes_block(node));
ir_node *res = NULL;
#ifdef FIRM_GRGEN_BE
case TRANSFORMER_PBQP:
case TRANSFORMER_RAND:
block = get_nodes_block(node);
break;
#endif
default:
panic("invalid transformer");
}
res = new_bd_ia32_LdTls(dbgi, block, mode_Iu);
res = new_bd_ia32_LdTls(NULL, block, mode_Iu);
return res;
}
ir_node *gen_Unknown(ir_node *node)
{
ir_mode *mode = get_irn_mode(node);
ir_mode *mode = get_irn_mode(node);
ir_graph *irg = current_ir_graph;
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *block = get_irg_start_block(irg);
ir_node *res = NULL;
if (mode_is_float(mode)) {
if (ia32_cg_config.use_sse2) {
return ia32_new_Unknown_xmm(env_cg);
res = new_bd_ia32_xZero(dbgi, block);
} else {
/* Unknown nodes are buggy in x87 simulator, use zero for now... */
ir_graph *irg = current_ir_graph;
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *block = get_irg_start_block(irg);
ir_node *ret = new_bd_ia32_vfldz(dbgi, block);
be_dep_on_frame(ret);
return ret;
res = new_bd_ia32_vfldz(dbgi, block);
}
} else if (ia32_mode_needs_gp_reg(mode)) {
return ia32_new_Unknown_gp(env_cg);
res = new_bd_ia32_Const(dbgi, block, NULL, 0, 0, 0);
} else {
panic("unsupported Unknown-Mode");
}
be_dep_on_frame(res);
return res;
}
const arch_register_req_t *make_register_req(const constraint_t *constraint,
......
......@@ -157,20 +157,6 @@ static const arch_register_t *get_in_reg(const ir_node *irn, int pos)
if (reg == &ia32_gp_regs[REG_GP_NOREG])
panic("trying to emit noreg for %+F input %d", irn, pos);
/* in case of unknown register: just return a valid register */
if (reg == &ia32_gp_regs[REG_GP_UKNWN]) {
const arch_register_req_t *req = arch_get_register_req(irn, pos);
if (arch_register_req_is(req, limited)) {
/* in case of limited requirements: get the first allowed register */
unsigned idx = rbitset_next(req->limited, 0, 1);
reg = arch_register_for_index(req->cls, idx);
} else {
/* otherwise get first register in class */
reg = arch_register_for_index(req->cls, 0);
}
}
return reg;
}
......@@ -1683,16 +1669,6 @@ static void emit_be_IncSP(const ir_node *node)
}
}
static inline bool is_unknown_reg(const arch_register_t *reg)
{
if (reg == &ia32_gp_regs[REG_GP_UKNWN]
|| reg == &ia32_xmm_regs[REG_XMM_UKNWN]
|| reg == &ia32_vfp_regs[REG_VFP_UKNWN])
return true;
return false;
}
/**
* Emits code for Copy/CopyKeep.
*/
......@@ -1704,8 +1680,6 @@ static void Copy_emitter(const ir_node *node, const ir_node *op)
if (in == out) {
return;
}
if (is_unknown_reg(in))
return;
/* copies of vf nodes aren't real... */
if (arch_register_get_class(in) == &ia32_reg_classes[CLASS_ia32_vfp])
return;
......@@ -2726,7 +2700,7 @@ static void bemit_copy(const ir_node *copy)
const arch_register_t *in = get_in_reg(copy, 0);
const arch_register_t *out = get_out_reg(copy, 0);
if (in == out || is_unknown_reg(in))
if (in == out)
return;
/* copies of vf nodes aren't real... */
if (arch_register_get_class(in) == &ia32_reg_classes[CLASS_ia32_vfp])
......
......@@ -243,16 +243,6 @@ static int get_first_same(const arch_register_req_t* req)
panic("same position not found");
}
static inline bool is_unknown_reg(const arch_register_t *reg)
{
if (reg == &ia32_gp_regs[REG_GP_UKNWN]
|| reg == &ia32_xmm_regs[REG_XMM_UKNWN]
|| reg == &ia32_vfp_regs[REG_VFP_UKNWN])
return true;
return false;
}
/**
* Insert copies for all ia32 nodes where the should_be_same requirement
* is not fulfilled.
......@@ -293,9 +283,6 @@ static void assure_should_be_same_requirements(ir_node *node)
/* requirement already fulfilled? */
if (in_reg == out_reg)
continue;
/* unknowns can be changed to any register we want on emitting */
if (is_unknown_reg(in_reg))
continue;
cls = arch_register_get_class(in_reg);
assert(cls == arch_register_get_class(out_reg));
......
......@@ -232,12 +232,8 @@ static void peephole_ia32_Test(ir_node *node)
left = get_Proj_pred(left);
}
/* happens rarely, but if it does code will panic' */
if (is_ia32_Unknown_GP(left))
return;
/* walk schedule up and abort when we find left or some other node destroys
the flags */
/* walk schedule up and abort when we find left or some other node
* destroys the flags */
schedpoint = node;
for (;;) {
schedpoint = sched_prev(schedpoint);
......@@ -862,7 +858,7 @@ static ir_node *create_push(dbg_info *dbgi, ir_node *block,
{
const arch_register_t *esp = &ia32_gp_regs[REG_ESP];
ir_node *val = ia32_new_Unknown_gp(cg);
ir_node *val = ia32_new_NoReg_gp(cg);
ir_node *noreg = ia32_new_NoReg_gp(cg);
ir_node *nomem = new_NoMem();
ir_node *push = new_bd_ia32_Push(dbgi, block, noreg, noreg, nomem, val, stack);
......
......@@ -117,7 +117,6 @@ $arch = "ia32";
{ name => "ebp", type => 2 },
{ name => "esp", type => 4 },
{ name => "gp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
{ name => "gp_UKNWN", type => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes
{ mode => "mode_Iu" }
],
mmx => [
......@@ -141,7 +140,6 @@ $arch = "ia32";
{ name => "xmm6", type => 1 },
{ name => "xmm7", type => 1 },
{ name => "xmm_NOREG", type => 4 | 16 }, # we need a dummy register for NoReg nodes
{ name => "xmm_UKNWN", type => 4 | 8 | 16}, # we need a dummy register for Unknown nodes
{ mode => "mode_E" }
],
vfp => [
......@@ -154,7 +152,6 @@ $arch = "ia32";
{ name => "vf6", type => 1 },
{ name => "vf7", type => 1 },
{ name => "vfp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
{ name => "vfp_UKNWN", type => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes
{ mode => "mode_E" }
],
st => [
......@@ -1208,37 +1205,6 @@ GetEIP => {
modified_flags => $status_flags,
},
Unknown_GP => {
state => "pinned",
op_flags => "c|NB",
reg_req => { out => [ "gp_UKNWN:I" ] },
units => [],
emit => "",
latency => 0,
mode => $mode_gp
},
Unknown_VFP => {
state => "pinned",
op_flags => "c|NB",
reg_req => { out => [ "vfp_UKNWN:I" ] },
units => [],
emit => "",
mode => "mode_E",
latency => 0,
attr_type => "ia32_x87_attr_t",
},
Unknown_XMM => {
state => "pinned",
op_flags => "c|NB",
reg_req => { out => [ "xmm_UKNWN:I" ] },
units => [],
emit => "",
latency => 0,
mode => $mode_xmm
},
NoReg_GP => {
state => "pinned",
op_flags => "c|NB|NI",
......
......@@ -5783,9 +5783,6 @@ static void ia32_pretransform_node(void)
{
ia32_code_gen_t *cg = env_cg;
cg->unknown_gp = be_pre_transform_node(cg->unknown_gp);
cg->unknown_vfp = be_pre_transform_node(cg->unknown_vfp);
cg->unknown_xmm = be_pre_transform_node(cg->unknown_xmm);
cg->noreg_gp = be_pre_transform_node(cg->noreg_gp);
cg->noreg_vfp = be_pre_transform_node(cg->noreg_vfp);
cg->noreg_xmm = be_pre_transform_node(cg->noreg_xmm);
......
......@@ -726,30 +726,6 @@ static ir_node *x87_create_fpop(x87_state *state, ir_node *n, int num)
return fpop;
} /* x87_create_fpop */
/**
* Creates an fldz before node n
*
* @param state the x87 state
* @param n the node after the fldz
*
* @return the fldz node
*/
static ir_node *x87_create_fldz(x87_state *state, ir_node *n, int regidx)
{
ir_node *block = get_nodes_block(n);
ir_node *fldz;
fldz = new_bd_ia32_fldz(NULL, block, ia32_reg_classes[CLASS_ia32_st].mode);
sched_add_before(n, fldz);
DB((dbg, LEVEL_1, "<<< %s\n", get_irn_opname(fldz)));
keep_alive(fldz);
x87_push(state, regidx, fldz);
return fldz;
}
/* --------------------------------- liveness ------------------------------------------ */
/**
......@@ -941,14 +917,9 @@ static int sim_binop(x87_state *state, ir_node *n, const exchange_tmpl *tmpl)
DB((dbg, LEVEL_1, "Stack before: "));
DEBUG_ONLY(x87_dump_stack(state));
if (reg_index_1 == REG_VFP_UKNWN) {
op1_idx = 0;
op1_live_after = 1;
} else {
op1_idx = x87_on_stack(state, reg_index_1);
assert(op1_idx >= 0);
op1_live_after = is_vfp_live(arch_register_get_index(op1_reg), live);
}
op1_idx = x87_on_stack(state, reg_index_1);
assert(op1_idx >= 0);
op1_live_after = is_vfp_live(arch_register_get_index(op1_reg), live);
attr = get_ia32_x87_attr(n);
permuted = attr->attr.data.ins_permuted;
......@@ -956,16 +927,10 @@ static int sim_binop(x87_state *state, ir_node *n, const exchange_tmpl *tmpl)
if (reg_index_2 != REG_VFP_NOREG) {
assert(!permuted);
if (reg_index_2 == REG_VFP_UKNWN) {
op2_idx = 0;
op2_live_after = 1;
} else {
/* second operand is a vfp register */
op2_idx = x87_on_stack(state, reg_index_2);
assert(op2_idx >= 0);
op2_live_after
= is_vfp_live(arch_register_get_index(op2_reg), live);
}
/* second operand is a vfp register */
op2_idx = x87_on_stack(state, reg_index_2);
assert(op2_idx >= 0);
op2_live_after = is_vfp_live(arch_register_get_index(op2_reg), live);
if (op2_live_after) {
/* Second operand is live. */
......@@ -1209,25 +1174,10 @@ static int sim_store(x87_state *state, ir_node *n, ir_op *op, ir_op *op_p)
ir_mode *mode;
op2_reg_idx = arch_register_get_index(op2);
if (op2_reg_idx == REG_VFP_UKNWN) {
/* just take any value from stack */
if (state->depth > 0) {
op2_idx = 0;
DEBUG_ONLY(op2 = NULL);
live_after_node = 1;
} else {
/* produce a new value which we will consume immediately */
x87_create_fldz(state, n, op2_reg_idx);
live_after_node = 0;
op2_idx = x87_on_stack(state, op2_reg_idx);
assert(op2_idx >= 0);
}
} else {
op2_idx = x87_on_stack(state, op2_reg_idx);
live_after_node = is_vfp_live(arch_register_get_index(op2), live);
DB((dbg, LEVEL_1, ">>> %+F %s ->\n", n, arch_register_get_name(op2)));
assert(op2_idx >= 0);
}
op2_idx = x87_on_stack(state, op2_reg_idx);
live_after_node = is_vfp_live(arch_register_get_index(op2), live);
DB((dbg, LEVEL_1, ">>> %+F %s ->\n", n, arch_register_get_name(op2)));
assert(op2_idx >= 0);
mode = get_ia32_ls_mode(n);
depth = x87_get_depth(state);
......@@ -1371,22 +1321,9 @@ static int sim_fisttp(x87_state *state, ir_node *n)
int op2_reg_idx, op2_idx, depth;
op2_reg_idx = arch_register_get_index(op2);
if (op2_reg_idx == REG_VFP_UKNWN) {
/* just take any value from stack */
if (state->depth > 0) {
op2_idx = 0;
DEBUG_ONLY(op2 = NULL);
} else {
/* produce a new value which we will consume immediately */
x87_create_fldz(state, n, op2_reg_idx);
op2_idx = x87_on_stack(state, op2_reg_idx);
assert(op2_idx >= 0);
}
} else {
op2_idx = x87_on_stack(state, op2_reg_idx);
DB((dbg, LEVEL_1, ">>> %+F %s ->\n", n, arch_register_get_name(op2)));
assert(op2_idx >= 0);