Commit d642405d authored by yb9976's avatar yb9976
Browse files

Always sign extend the left operand of an Shrs.

This fixes backend/shift.c.
parent 22628abe
......@@ -40,16 +40,19 @@ typedef enum {
* 32bit equivalents, they just don't care about the upper bits (they can be
* arbitrary before the insn and are unknown after the instruction). */
match_mode_neutral = 1 << 6,
/** for 8/16 bit modes, sign_ext operations can be emulated by their
* 32bit equivalents, however the upper bits must be sign extended. */
match_sign_ext = 1 << 7,
/** for 8/16 bit modes, zero_ext operations can be emulated by their
* 32bit equivalents, however the upper bits must be zero extended. */
match_zero_ext = 1 << 7,
match_zero_ext = 1 << 8,
/** for 8/16 bit modes, upconv operations can be emulated by their
* 32bit equivalents, however the upper bits have to sign/zero extended
* based on the operations mode. */
match_upconv = 1 << 8,
match_try_am = 1 << 9, /**< only try to produce AM node, don't
match_upconv = 1 << 9,
match_try_am = 1 << 10, /**< only try to produce AM node, don't
do anything if AM isn't possible */
match_two_users = 1 << 10,/**< the instruction uses a load two times ... */
match_two_users = 1 << 11,/**< the instruction uses a load two times ... */
} match_flags_t;
ENUM_BITSET(match_flags_t)
......
......@@ -700,6 +700,13 @@ static ir_node *transform_sext(ir_node *node, ir_node *orig_node)
ir_mode *mode = get_irn_mode(node);
ir_node *block = get_nodes_block(node);
dbg_info *dbgi = get_irn_dbg_info(node);
/* normalize to an signed mode */
switch (get_mode_size_bits(mode)) {
case 8: mode = mode_Bs; break;
case 16: mode = mode_Hs; break;
default:
panic("ia32: invalid mode in sest: %+F", node);
}
return create_I2I_Conv(mode, ia32_mode_gp, dbgi, block, node, orig_node);
}
......@@ -1077,7 +1084,7 @@ static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2,
assert(!mode_is_float(mode));
assert(flags & match_immediate);
assert((flags & ~(match_mode_neutral | match_zero_ext | match_upconv | match_immediate)) == 0);
assert((flags & ~(match_mode_neutral | match_sign_ext | match_zero_ext | match_upconv | match_immediate)) == 0);
if (get_mode_modulo_shift(mode) != 32) {
/* TODO: implement special cases for non-modulo shifts */
......@@ -1093,6 +1100,8 @@ static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2,
if (get_mode_size_bits(mode) != 32) {
if (flags & match_upconv) {
new_op1 = transform_upconv(op1, node);
} else if (flags & match_sign_ext) {
new_op1 = transform_sext(op1, node);
} else if (flags & match_zero_ext) {
new_op1 = transform_zext(op1, node);
} else {
......@@ -1844,7 +1853,7 @@ static ir_node *gen_Shrs(ir_node *node)
}
return gen_shift_binop(node, left, right, new_bd_ia32_Sar,
match_immediate | match_upconv);
match_immediate | match_sign_ext);
}
/**
......
......@@ -155,11 +155,13 @@ static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
}
typedef enum {
MATCH_NONE = 0,
MATCH_COMMUTATIVE = 1U << 0, /**< commutative operation. */
MATCH_MODE_NEUTRAL = 1U << 1, /**< the higher bits of the inputs don't
influence the significant lower bit at
all (for cases where mode < 32bit) */
MATCH_NONE = 0,
MATCH_COMMUTATIVE = 1U << 0, /**< commutative operation. */
MATCH_MODE_NEUTRAL = 1U << 1, /**< the higher bits of the inputs don't
influence the significant lower bit at
all (for cases where mode < 32bit) */
MATCH_SIGN_EXT_LEFT = 1U << 7, /**< we need to sign_extend the left operand
(for cases wheew mode < 32bit) */
} match_flags_t;
ENUM_BITSET(match_flags_t)
......@@ -606,7 +608,12 @@ static ir_node *gen_helper_binop_args(ir_node *node,
int32_t immediate = get_tarval_long(get_Const_tarval(op2));
ir_node *new_op1 = be_transform_node(op1);
if (! (flags & MATCH_MODE_NEUTRAL) && needs_extension(op1)) {
new_op1 = gen_extension(dbgi, block, new_op1, mode1);
if (flags & MATCH_SIGN_EXT_LEFT) {
int bits = get_mode_size_bits(mode1);
new_op1 = gen_sign_extension(dbgi, block, new_op1, bits);
} else {
new_op1 = gen_extension(dbgi, block, new_op1, mode1);
}
}
return new_imm(dbgi, block, new_op1, NULL, immediate);
}
......@@ -622,7 +629,12 @@ static ir_node *gen_helper_binop_args(ir_node *node,
ir_node *new_op1 = be_transform_node(op1);
if (! (flags & MATCH_MODE_NEUTRAL) && needs_extension(op1)) {
new_op1 = gen_extension(dbgi, block, new_op1, mode1);
if (flags & MATCH_SIGN_EXT_LEFT) {
int bits = get_mode_size_bits(mode1);
new_op1 = gen_sign_extension(dbgi, block, new_op1, bits);
} else {
new_op1 = gen_extension(dbgi, block, new_op1, mode1);
}
}
return new_reg(dbgi, block, new_op1, new_op2);
}
......@@ -1315,7 +1327,7 @@ static ir_node *gen_Shrs(ir_node *node)
ir_mode *mode = get_irn_mode(node);
if (get_mode_modulo_shift(mode) != 32)
panic("modulo_shift!=32 not supported");
return gen_helper_binop(node, MATCH_NONE, new_bd_sparc_Sra_reg, new_bd_sparc_Sra_imm);
return gen_helper_binop(node, MATCH_SIGN_EXT_LEFT, new_bd_sparc_Sra_reg, new_bd_sparc_Sra_imm);
}
static ir_node *gen_fneg(ir_node *node, ir_mode *mode)
......
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