Commit aa5427e4 authored by Matthias Braun's avatar Matthias Braun
Browse files

panic instead of wrong results for Set and CMov with float compare. Rename Set...

panic instead of wrong results for Set and CMov with float compare. Rename Set to Setcc and CMov to CMovcc

[r26950]
parent f949afd0
......@@ -556,6 +556,7 @@ static void ia32_emit_cmp_suffix(int pnc)
be_emit_char('p');
return;
}
if (pnc & ia32_pn_Cmp_float || pnc & ia32_pn_Cmp_unsigned) {
str = cmp2condition_u[pnc & 7];
} else {
......@@ -772,7 +773,7 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...)
case 'R': {
const arch_register_t *reg = va_arg(ap, const arch_register_t*);
emit_register(reg, NULL);
emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL);
break;
}
......@@ -1083,37 +1084,37 @@ static void emit_ia32_Jcc(const ir_node *node)
if (pnc & ia32_pn_Cmp_float) {
/* Some floating point comparisons require a test of the parity flag,
* which indicates that the result is unordered */
switch (pnc & 15) {
case pn_Cmp_Uo: {
ia32_emitf(proj_true, "\tjp %L\n");
break;
}
switch (pnc & 0x0f) {
case pn_Cmp_Uo: {
ia32_emitf(proj_true, "\tjp %L\n");
break;
}
case pn_Cmp_Leg:
ia32_emitf(proj_true, "\tjnp %L\n");
break;
case pn_Cmp_Leg:
ia32_emitf(proj_true, "\tjnp %L\n");
break;
case pn_Cmp_Eq:
case pn_Cmp_Lt:
case pn_Cmp_Le:
/* we need a local label if the false proj is a fallthrough
* as the falseblock might have no label emitted then */
if (can_be_fallthrough(proj_false)) {
need_parity_label = 1;
ia32_emitf(proj_false, "\tjp 1f\n");
} else {
ia32_emitf(proj_false, "\tjp %L\n");
}
goto emit_jcc;
case pn_Cmp_Eq:
case pn_Cmp_Lt:
case pn_Cmp_Le:
/* we need a local label if the false proj is a fallthrough
* as the falseblock might have no label emitted then */
if (can_be_fallthrough(proj_false)) {
need_parity_label = 1;
ia32_emitf(proj_false, "\tjp 1f\n");
} else {
ia32_emitf(proj_false, "\tjp %L\n");
}
goto emit_jcc;
case pn_Cmp_Ug:
case pn_Cmp_Uge:
case pn_Cmp_Ne:
ia32_emitf(proj_true, "\tjp %L\n");
goto emit_jcc;
case pn_Cmp_Ug:
case pn_Cmp_Uge:
case pn_Cmp_Ne:
ia32_emitf(proj_true, "\tjp %L\n");
goto emit_jcc;
default:
goto emit_jcc;
default:
goto emit_jcc;
}
} else {
emit_jcc:
......@@ -1132,7 +1133,42 @@ emit_jcc:
}
}
static void emit_ia32_CMov(const ir_node *node)
/**
* Emits an ia32 Setcc. This is mostly easy but some floating point compares
* are tricky.
*/
static void emit_ia32_Setcc(const ir_node *node)
{
const arch_register_t *dreg = get_out_reg(node, pn_ia32_Setcc_res);
pn_Cmp pnc = get_ia32_condcode(node);
pnc = determine_final_pnc(node, n_ia32_Setcc_eflags, pnc);
if (pnc & ia32_pn_Cmp_float) {
switch (pnc & 0x0f) {
case pn_Cmp_Uo:
ia32_emitf(node, "\tsetp %#R\n", dreg);
break;
case pn_Cmp_Leg:
ia32_emitf(node, "\tsetnp %#R\n", dreg);
break;
case pn_Cmp_Eq:
case pn_Cmp_Lt:
case pn_Cmp_Le:
case pn_Cmp_Ug:
case pn_Cmp_Uge:
case pn_Cmp_Ne:
panic("No handling for set with parity bit yet in ia32_Setcc");
default:
break;
}
}
ia32_emitf(node, "\tset%P %#R\n", pnc, dreg);
}
static void emit_ia32_CMovcc(const ir_node *node)
{
const ia32_attr_t *attr = get_ia32_attr_const(node);
int ins_permuted = attr->data.ins_permuted;
......@@ -1141,10 +1177,10 @@ static void emit_ia32_CMov(const ir_node *node)
const arch_register_t *in_true;
const arch_register_t *in_false;
pnc = determine_final_pnc(node, n_ia32_CMov_eflags, pnc);
pnc = determine_final_pnc(node, n_ia32_CMovcc_eflags, pnc);
in_true = arch_get_irn_register(get_irn_n(node, n_ia32_CMov_val_true));
in_false = arch_get_irn_register(get_irn_n(node, n_ia32_CMov_val_false));
in_true = arch_get_irn_register(get_irn_n(node, n_ia32_CMovcc_val_true));
in_false = arch_get_irn_register(get_irn_n(node, n_ia32_CMovcc_val_false));
/* should be same constraint fullfilled? */
if (out == in_false) {
......@@ -1871,7 +1907,7 @@ static void ia32_register_emitters(void)
/* other ia32 emitter functions */
IA32_EMIT2(Conv_I2I8Bit, Conv_I2I);
IA32_EMIT(Asm);
IA32_EMIT(CMov);
IA32_EMIT(CMovcc);
IA32_EMIT(Call);
IA32_EMIT(Const);
IA32_EMIT(Conv_FP2FP);
......@@ -1883,6 +1919,7 @@ static void ia32_register_emitters(void)
IA32_EMIT(GetEIP);
IA32_EMIT(IMul);
IA32_EMIT(Jcc);
IA32_EMIT(Setcc);
IA32_EMIT(LdTls);
IA32_EMIT(Minus64Bit);
IA32_EMIT(SwitchJmp);
......@@ -2862,7 +2899,7 @@ static void bemit_shrd(const ir_node *node)
}
}
static void bemit_cmov(const ir_node *node)
static void bemit_cmovcc(const ir_node *node)
{
const ia32_attr_t *attr = get_ia32_attr_const(node);
int ins_permuted = attr->data.ins_permuted;
......@@ -2871,10 +2908,10 @@ static void bemit_cmov(const ir_node *node)
const arch_register_t *in_true;
const arch_register_t *in_false;
pnc = determine_final_pnc(node, n_ia32_CMov_eflags, pnc);
pnc = determine_final_pnc(node, n_ia32_CMovcc_eflags, pnc);
in_true = arch_get_irn_register(get_irn_n(node, n_ia32_CMov_val_true));
in_false = arch_get_irn_register(get_irn_n(node, n_ia32_CMov_val_false));
in_true = arch_get_irn_register(get_irn_n(node, n_ia32_CMovcc_val_true));
in_false = arch_get_irn_register(get_irn_n(node, n_ia32_CMovcc_val_false));
/* should be same constraint fullfilled? */
if (out == in_false) {
......@@ -3072,19 +3109,21 @@ UNOPMEM(negmem, 0xF6, 3)
UNOPMEM(incmem, 0xFE, 0)
UNOPMEM(decmem, 0xFE, 1)
static void bemit_set(const ir_node *node)
static void bemit_setcc(const ir_node *node)
{
pn_Cmp pnc;
bemit8(0x0F);
pnc = get_ia32_condcode(node);
pnc = determine_final_pnc(node, n_ia32_Set_eflags, pnc);
if (get_ia32_attr_const(node)->data.ins_permuted)
pnc = ia32_get_negated_pnc(pnc);
pnc = determine_final_pnc(node, n_ia32_Setcc_eflags, pnc);
/* TODO: all the special casing for float compares is missing */
if (pnc & ia32_pn_Cmp_float)
panic("binary setcc from float compare not implemented yet");
bemit8(0x90 + pnc2cc(pnc));
bemit_modru(get_out_reg(node, pn_ia32_Set_res), 2);
bemit_modru(get_out_reg(node, pn_ia32_Setcc_res), 2);
}
static void bemit_ldtls(const ir_node *node)
......@@ -4032,7 +4071,7 @@ static void ia32_register_binary_emitters(void)
register_emitter(op_ia32_AndMem, bemit_andmem);
register_emitter(op_ia32_AndMem8Bit, bemit_andmem8bit);
register_emitter(op_ia32_Breakpoint, bemit_int3);
register_emitter(op_ia32_CMov, bemit_cmov);
register_emitter(op_ia32_CMovcc, bemit_cmovcc);
register_emitter(op_ia32_Call, bemit_call);
register_emitter(op_ia32_Cltd, bemit_cltd);
register_emitter(op_ia32_Cmc, bemit_cmc);
......@@ -4088,7 +4127,7 @@ static void ia32_register_binary_emitters(void)
register_emitter(op_ia32_Sar, bemit_sar);
register_emitter(op_ia32_SarMem, bemit_sarmem);
register_emitter(op_ia32_Sbb, bemit_sbb);
register_emitter(op_ia32_Set, bemit_set);
register_emitter(op_ia32_Setcc, bemit_setcc);
register_emitter(op_ia32_Shl, bemit_shl);
register_emitter(op_ia32_ShlD, bemit_shld);
register_emitter(op_ia32_ShlMem, bemit_shlmem);
......
......@@ -218,7 +218,7 @@ static inline int need_constraint_copy(ir_node *irn)
case iro_ia32_Lea:
case iro_ia32_Conv_I2I:
case iro_ia32_Conv_I2I8Bit:
case iro_ia32_CMov:
case iro_ia32_CMovcc:
return 0;
default:
......
......@@ -197,7 +197,7 @@ static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
/* dump pn code */
if (is_ia32_SwitchJmp(n)) {
fprintf(F, "pn_code = %ld\n", get_ia32_condcode(n));
} else if (is_ia32_CMov(n) || is_ia32_Set(n) || is_ia32_Jcc(n)) {
} else if (is_ia32_CMovcc(n) || is_ia32_Setcc(n) || is_ia32_Jcc(n)) {
ia32_attr_t *attr = get_ia32_attr(n);
long pnc = get_ia32_condcode(n);
fprintf(F, "pn_code = 0x%lX (%s)\n", pnc, get_pnc_string(pnc & pn_Cmp_True));
......
......@@ -1090,37 +1090,34 @@ Test8Bit => {
modified_flags => $status_flags
},
Set => {
Setcc => {
#irn_flags => "R",
reg_req => { in => [ "eflags" ], out => [ "eax ebx ecx edx" ] },
ins => [ "eflags" ],
outs => [ "res" ],
attr_type => "ia32_condcode_attr_t",
attr => "pn_Cmp pnc, int ins_permuted",
init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
"\tset_ia32_ls_mode(res, mode_Bu);\n",
emit => '. set%CMP0 %DB0',
attr => "pn_Cmp pnc",
init_attr => "set_ia32_ls_mode(res, mode_Bu);\n",
latency => 1,
units => [ "GP" ],
mode => $mode_gp,
},
SetMem => {
SetccMem => {
#irn_flags => "R",
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none", "eflags" ], out => [ "none" ] },
ins => [ "base", "index", "mem","eflags" ],
attr_type => "ia32_condcode_attr_t",
attr => "pn_Cmp pnc, int ins_permuted",
init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
"\tset_ia32_ls_mode(res, mode_Bu);\n",
attr => "pn_Cmp pnc",
init_attr => "set_ia32_ls_mode(res, mode_Bu);\n",
emit => '. set%CMP3 %AM',
latency => 1,
units => [ "GP" ],
mode => 'mode_M',
},
CMov => {
CMovcc => {
#irn_flags => "R",
# (note: leave the false,true order intact to make it compatible with other
# ia32_binary ops)
......
......@@ -1809,7 +1809,7 @@ static ir_node *gen_Minus(ir_node *node)
*/
static ir_node *gen_Not(ir_node *node)
{
ir_node *op = get_Not_op(node);
ir_node *op = get_Not_op(node);
assert(get_irn_mode(node) != mode_b); /* should be lowered already */
assert (! mode_is_float(get_irn_mode(node)));
......@@ -2176,41 +2176,47 @@ static ir_node *dest_am_unop(ir_node *node, ir_node *op, ir_node *mem,
static ir_node *try_create_SetMem(ir_node *node, ir_node *ptr, ir_node *mem)
{
ir_mode *mode = get_irn_mode(node);
ir_node *mux_true = get_Mux_true(node);
ir_node *mux_false = get_Mux_false(node);
ir_node *cond;
ir_node *new_mem;
dbg_info *dbgi;
ir_node *block;
ir_node *new_block;
ir_node *flags;
ir_node *new_node;
int negated;
pn_Cmp pnc;
ia32_address_t addr;
ir_mode *mode = get_irn_mode(node);
ir_node *mux_true = get_Mux_true(node);
ir_node *mux_false = get_Mux_false(node);
ir_node *cond;
ir_node *new_mem;
dbg_info *dbgi;
ir_node *block;
ir_node *new_block;
ir_node *flags;
ir_node *new_node;
bool negated;
pn_Cmp pnc;
ia32_address_t addr;
if (get_mode_size_bits(mode) != 8)
return NULL;
if (is_Const_1(mux_true) && is_Const_0(mux_false)) {
negated = 0;
negated = false;
} else if (is_Const_0(mux_true) && is_Const_1(mux_false)) {
negated = 1;
negated = true;
} else {
return NULL;
}
cond = get_Mux_sel(node);
flags = get_flags_node(cond, &pnc);
/* we can't handle the float special cases with SetM */
if (pnc & ia32_pn_Cmp_float)
return NULL;
if (negated)
pnc = get_negated_pnc(pnc, pnc & ia32_pn_Cmp_float ? mode_F : mode_Is);
build_address_ptr(&addr, ptr, mem);
dbgi = get_irn_dbg_info(node);
block = get_nodes_block(node);
new_block = be_transform_node(block);
cond = get_Mux_sel(node);
flags = get_flags_node(cond, &pnc);
new_mem = be_transform_node(mem);
new_node = new_bd_ia32_SetMem(dbgi, new_block, addr.base,
addr.index, addr.mem, flags, pnc, negated);
new_node = new_bd_ia32_SetccMem(dbgi, new_block, addr.base,
addr.index, addr.mem, flags, pnc);
set_address(new_node, &addr);
set_ia32_op_type(new_node, ia32_AddrModeD);
set_ia32_ls_mode(new_node, mode);
......@@ -2336,6 +2342,7 @@ static ir_node *try_create_dest_am(ir_node *node)
case iro_Mux:
new_node = try_create_SetMem(val, ptr, mem);
break;
case iro_Minus:
op1 = get_Minus_op(val);
new_node = dest_am_unop(val, op1, mem, ptr, mode, new_bd_ia32_NegMem);
......@@ -2960,9 +2967,9 @@ static ir_node *create_CMov(ir_node *node, ir_node *flags, ir_node *new_flags,
match_arguments(&am, block, val_false, val_true, flags,
match_commutative | match_am | match_16bit_am | match_mode_neutral);
new_node = new_bd_ia32_CMov(dbgi, new_block, addr->base, addr->index,
addr->mem, am.new_op1, am.new_op2, new_flags,
am.ins_permuted, pnc);
new_node = new_bd_ia32_CMovcc(dbgi, new_block, addr->base, addr->index,
addr->mem, am.new_op1, am.new_op2, new_flags,
am.ins_permuted, pnc);
set_am_attributes(new_node, &am);
SET_IA32_ORIG_NODE(new_node, node);
......@@ -2976,13 +2983,12 @@ static ir_node *create_CMov(ir_node *node, ir_node *flags, ir_node *new_flags,
* Creates a ia32 Setcc instruction.
*/
static ir_node *create_set_32bit(dbg_info *dbgi, ir_node *new_block,
ir_node *flags, pn_Cmp pnc, ir_node *orig_node,
int ins_permuted)
ir_node *flags, pn_Cmp pnc, ir_node *orig_node)
{
ir_mode *mode = get_irn_mode(orig_node);
ir_node *new_node;
new_node = new_bd_ia32_Set(dbgi, new_block, flags, pnc, ins_permuted);
new_node = new_bd_ia32_Setcc(dbgi, new_block, flags, pnc);
SET_IA32_ORIG_NODE(new_node, orig_node);
/* we might need to conv the result up */
......@@ -3144,7 +3150,7 @@ static ir_node *gen_Mux(ir_node *node)
unsigned scale;
flags = get_flags_node(cond, &pnc);
new_node = create_set_32bit(dbgi, new_block, flags, pnc, node, /*is_permuted=*/0);
new_node = create_set_32bit(dbgi, new_block, flags, pnc, node);
if (ia32_cg_config.use_sse2) {
/* cannot load from different mode on SSE */
......@@ -3241,9 +3247,10 @@ static ir_node *gen_Mux(ir_node *node)
if (is_Const(mux_true) && is_Const(mux_false)) {
/* both are const, good */
if (is_Const_1(mux_true) && is_Const_0(mux_false)) {
new_node = create_set_32bit(dbgi, new_block, flags, pnc, node, /*is_premuted=*/0);
new_node = create_set_32bit(dbgi, new_block, flags, pnc, node);
} else if (is_Const_0(mux_true) && is_Const_1(mux_false)) {
new_node = create_set_32bit(dbgi, new_block, flags, pnc, node, /*is_premuted=*/1);
pnc = get_negated_pnc(pnc, pnc & ia32_pn_Cmp_float ? mode_F : mode_Is);
new_node = create_set_32bit(dbgi, new_block, flags, pnc, node);
} else {
/* Not that simple. */
goto need_cmov;
......@@ -4782,7 +4789,7 @@ static ir_node *gen_ffs(ir_node *node)
flag = new_r_Proj(block, real, mode_b, pn_ia32_flags);
/* sete */
set = new_bd_ia32_Set(dbgi, block, flag, pn_Cmp_Eq, 0);
set = new_bd_ia32_Setcc(dbgi, block, flag, pn_Cmp_Eq);
SET_IA32_ORIG_NODE(set, node);
/* conv to 32bit */
......@@ -4852,7 +4859,7 @@ static ir_node *gen_parity(ir_node *node)
cmp = fix_mem_proj(cmp, &am);
/* setp */
new_node = new_bd_ia32_Set(dbgi, new_block, cmp, ia32_pn_Cmp_parity, 0);
new_node = new_bd_ia32_Setcc(dbgi, new_block, cmp, ia32_pn_Cmp_parity);
SET_IA32_ORIG_NODE(new_node, node);
/* conv to 32bit */
......
......@@ -1473,9 +1473,9 @@ static int sim_Fucom(x87_state *state, ir_node *n)
int reg_index_1 = arch_register_get_index(op1);
int reg_index_2 = arch_register_get_index(op2);
unsigned live = vfp_live_args_after(sim, n, 0);
int permuted = attr->attr.data.ins_permuted;
int xchg = 0;
int pops = 0;
bool permuted = attr->attr.data.ins_permuted;
bool xchg = false;
int pops = 0;
DB((dbg, LEVEL_1, ">>> %+F %s, %s\n", n,
arch_register_get_name(op1), arch_register_get_name(op2)));
......@@ -1503,7 +1503,7 @@ static int sim_Fucom(x87_state *state, ir_node *n)
} else if (op2_idx == 0) {
/* res = op X tos */
permuted = !permuted;
xchg = 1;
xchg = true;
} else {
/* bring the first one to tos */
x87_create_fxch(state, n, op1_idx);
......@@ -1538,9 +1538,9 @@ static int sim_Fucom(x87_state *state, ir_node *n)
op2_idx = 0;
}
/* res = op X tos, pop */
pops = 1;
pops = 1;
permuted = !permuted;
xchg = 1;
xchg = true;
} else {
/* both operands are dead here, check first for identity. */
if (op1_idx == op2_idx) {
......@@ -1575,8 +1575,8 @@ static int sim_Fucom(x87_state *state, ir_node *n)
}
/* res = op X tos, pop, pop */
permuted = !permuted;
xchg = 1;
pops = 2;
xchg = true;
pops = 2;
} else {
/* if one is already the TOS, we need two fxch */
if (op1_idx == 0) {
......@@ -1587,9 +1587,9 @@ static int sim_Fucom(x87_state *state, ir_node *n)
x87_create_fxch(state, n, op2_idx);
op2_idx = 0;
/* res = op X tos, pop, pop */
pops = 2;
pops = 2;
permuted = !permuted;
xchg = 1;
xchg = true;
} else if (op2_idx == 0) {
/* second one is TOS, move to st(1) */
x87_create_fxch(state, n, 1);
......
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