mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-16 02:20:27 +08:00
expmed.c (emit_store_flag_1): New function.
* expmed.c (emit_store_flag_1): New function. (emit_store_flag): Call it. If we can't find a suitable scc insn, try a cstore insn. * expr.c (do_store_flag): If we can't find a scc insn, try cstore. Use do_compare_rtx_and_jump. * arm.h (BRANCH_COST): Increase to 2 on Thumb. * arm.md (cstoresi4): New define_expand. (cstoresi_eq0_thumb, cstoresi_ne0_thumb): Likewise. (cstoresi_eq0_thumb_insn, cstore_ne0_thumb_insn): New patterns. (cstoresi_nltu_thumb, thumb_addsi3_addgeu): New patterns. From-SVN: r118829
This commit is contained in:
parent
75dc0b383d
commit
a41a56b62d
@ -1,3 +1,16 @@
|
||||
2006-11-14 Richard Earnshaw <rearnsha@arm.com>
|
||||
|
||||
* expmed.c (emit_store_flag_1): New function.
|
||||
(emit_store_flag): Call it. If we can't find a suitable scc insn,
|
||||
try a cstore insn.
|
||||
* expr.c (do_store_flag): If we can't find a scc insn, try cstore.
|
||||
Use do_compare_rtx_and_jump.
|
||||
* arm.h (BRANCH_COST): Increase to 2 on Thumb.
|
||||
* arm.md (cstoresi4): New define_expand.
|
||||
(cstoresi_eq0_thumb, cstoresi_ne0_thumb): Likewise.
|
||||
(cstoresi_eq0_thumb_insn, cstore_ne0_thumb_insn): New patterns.
|
||||
(cstoresi_nltu_thumb, thumb_addsi3_addgeu): New patterns.
|
||||
|
||||
2006-11-14 Caroline Tice <ctice@apple.com>
|
||||
|
||||
* dwarf2out.c (debug_pubtypes_section): New static global variable.
|
||||
|
@ -2091,7 +2091,7 @@ do { \
|
||||
/* Try to generate sequences that don't involve branches, we can then use
|
||||
conditional instructions */
|
||||
#define BRANCH_COST \
|
||||
(TARGET_ARM ? 4 : (optimize > 1 ? 1 : 0))
|
||||
(TARGET_ARM ? 4 : (optimize > 0 ? 2 : 0))
|
||||
|
||||
/* Position Independent Code. */
|
||||
/* We decide which register to use based on the compilation options and
|
||||
|
@ -7460,6 +7460,198 @@
|
||||
(set_attr "length" "8")]
|
||||
)
|
||||
|
||||
(define_expand "cstoresi4"
|
||||
[(set (match_operand:SI 0 "s_register_operand" "")
|
||||
(match_operator:SI 1 "arm_comparison_operator"
|
||||
[(match_operand:SI 2 "s_register_operand" "")
|
||||
(match_operand:SI 3 "reg_or_int_operand" "")]))]
|
||||
"TARGET_THUMB"
|
||||
"{
|
||||
rtx op3, scratch, scratch2;
|
||||
|
||||
if (operands[3] == const0_rtx)
|
||||
{
|
||||
switch (GET_CODE (operands[1]))
|
||||
{
|
||||
case EQ:
|
||||
emit_insn (gen_cstoresi_eq0_thumb (operands[0], operands[2]));
|
||||
break;
|
||||
|
||||
case NE:
|
||||
emit_insn (gen_cstoresi_ne0_thumb (operands[0], operands[2]));
|
||||
break;
|
||||
|
||||
case LE:
|
||||
scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
|
||||
NULL_RTX, 0, OPTAB_WIDEN);
|
||||
scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
|
||||
NULL_RTX, 0, OPTAB_WIDEN);
|
||||
expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
|
||||
operands[0], 1, OPTAB_WIDEN);
|
||||
break;
|
||||
|
||||
case GE:
|
||||
scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
|
||||
NULL_RTX, 1);
|
||||
expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
|
||||
NULL_RTX, 1, OPTAB_WIDEN);
|
||||
break;
|
||||
|
||||
case GT:
|
||||
scratch = expand_binop (SImode, ashr_optab, operands[2],
|
||||
GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
|
||||
scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
|
||||
NULL_RTX, 0, OPTAB_WIDEN);
|
||||
expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
|
||||
0, OPTAB_WIDEN);
|
||||
break;
|
||||
|
||||
/* LT is handled by generic code. No need for unsigned with 0. */
|
||||
default:
|
||||
FAIL;
|
||||
}
|
||||
DONE;
|
||||
}
|
||||
|
||||
switch (GET_CODE (operands[1]))
|
||||
{
|
||||
case EQ:
|
||||
scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
|
||||
NULL_RTX, 0, OPTAB_WIDEN);
|
||||
emit_insn (gen_cstoresi_eq0_thumb (operands[0], scratch));
|
||||
break;
|
||||
|
||||
case NE:
|
||||
scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
|
||||
NULL_RTX, 0, OPTAB_WIDEN);
|
||||
emit_insn (gen_cstoresi_ne0_thumb (operands[0], scratch));
|
||||
break;
|
||||
|
||||
case LE:
|
||||
op3 = force_reg (SImode, operands[3]);
|
||||
|
||||
scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
|
||||
NULL_RTX, 1, OPTAB_WIDEN);
|
||||
scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
|
||||
NULL_RTX, 0, OPTAB_WIDEN);
|
||||
emit_insn (gen_thumb_addsi3_addgeu (operands[0], scratch, scratch2,
|
||||
op3, operands[2]));
|
||||
break;
|
||||
|
||||
case GE:
|
||||
op3 = operands[3];
|
||||
if (!thumb_cmp_operand (op3, SImode))
|
||||
op3 = force_reg (SImode, op3);
|
||||
scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
|
||||
NULL_RTX, 0, OPTAB_WIDEN);
|
||||
scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
|
||||
NULL_RTX, 1, OPTAB_WIDEN);
|
||||
emit_insn (gen_thumb_addsi3_addgeu (operands[0], scratch, scratch2,
|
||||
operands[2], op3));
|
||||
break;
|
||||
|
||||
case LEU:
|
||||
op3 = force_reg (SImode, operands[3]);
|
||||
scratch = force_reg (SImode, const0_rtx);
|
||||
emit_insn (gen_thumb_addsi3_addgeu (operands[0], scratch, scratch,
|
||||
op3, operands[2]));
|
||||
break;
|
||||
|
||||
case GEU:
|
||||
op3 = operands[3];
|
||||
if (!thumb_cmp_operand (op3, SImode))
|
||||
op3 = force_reg (SImode, op3);
|
||||
scratch = force_reg (SImode, const0_rtx);
|
||||
emit_insn (gen_thumb_addsi3_addgeu (operands[0], scratch, scratch,
|
||||
operands[2], op3));
|
||||
break;
|
||||
|
||||
case LTU:
|
||||
op3 = operands[3];
|
||||
if (!thumb_cmp_operand (op3, SImode))
|
||||
op3 = force_reg (SImode, op3);
|
||||
scratch = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_cstoresi_nltu_thumb (scratch, operands[2], op3));
|
||||
emit_insn (gen_negsi2 (operands[0], scratch));
|
||||
break;
|
||||
|
||||
case GTU:
|
||||
op3 = force_reg (SImode, operands[3]);
|
||||
scratch = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_cstoresi_nltu_thumb (scratch, op3, operands[2]));
|
||||
emit_insn (gen_negsi2 (operands[0], scratch));
|
||||
break;
|
||||
|
||||
/* No good sequences for GT, LT. */
|
||||
default:
|
||||
FAIL;
|
||||
}
|
||||
DONE;
|
||||
}")
|
||||
|
||||
(define_expand "cstoresi_eq0_thumb"
|
||||
[(parallel
|
||||
[(set (match_operand:SI 0 "s_register_operand" "")
|
||||
(eq:SI (match_operand:SI 1 "s_register_operand" "")
|
||||
(const_int 0)))
|
||||
(clobber (match_dup:SI 2))])]
|
||||
"TARGET_THUMB"
|
||||
"operands[2] = gen_reg_rtx (SImode);"
|
||||
)
|
||||
|
||||
(define_expand "cstoresi_ne0_thumb"
|
||||
[(parallel
|
||||
[(set (match_operand:SI 0 "s_register_operand" "")
|
||||
(ne:SI (match_operand:SI 1 "s_register_operand" "")
|
||||
(const_int 0)))
|
||||
(clobber (match_dup:SI 2))])]
|
||||
"TARGET_THUMB"
|
||||
"operands[2] = gen_reg_rtx (SImode);"
|
||||
)
|
||||
|
||||
(define_insn "*cstoresi_eq0_thumb_insn"
|
||||
[(set (match_operand:SI 0 "s_register_operand" "=&l,l")
|
||||
(eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
|
||||
(const_int 0)))
|
||||
(clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
|
||||
"TARGET_THUMB"
|
||||
"@
|
||||
neg\\t%0, %1\;adc\\t%0, %0, %1
|
||||
neg\\t%2, %1\;adc\\t%0, %1, %2"
|
||||
[(set_attr "length" "4")]
|
||||
)
|
||||
|
||||
(define_insn "*cstoresi_ne0_thumb_insn"
|
||||
[(set (match_operand:SI 0 "s_register_operand" "=l")
|
||||
(ne:SI (match_operand:SI 1 "s_register_operand" "0")
|
||||
(const_int 0)))
|
||||
(clobber (match_operand:SI 2 "s_register_operand" "=l"))]
|
||||
"TARGET_THUMB"
|
||||
"sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
|
||||
[(set_attr "length" "4")]
|
||||
)
|
||||
|
||||
(define_insn "cstoresi_nltu_thumb"
|
||||
[(set (match_operand:SI 0 "s_register_operand" "=l,l")
|
||||
(neg:SI (gtu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
|
||||
(match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r"))))]
|
||||
"TARGET_THUMB"
|
||||
"cmp\\t%1, %2\;sbc\\t%0, %0, %0"
|
||||
[(set_attr "length" "4")]
|
||||
)
|
||||
|
||||
;; Used as part of the expansion of thumb les sequence.
|
||||
(define_insn "thumb_addsi3_addgeu"
|
||||
[(set (match_operand:SI 0 "s_register_operand" "=l")
|
||||
(plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
|
||||
(match_operand:SI 2 "s_register_operand" "l"))
|
||||
(geu:SI (match_operand:SI 3 "s_register_operand" "l")
|
||||
(match_operand:SI 4 "thumb_cmp_operand" "lI"))))]
|
||||
"TARGET_THUMB"
|
||||
"cmp\\t%3, %4\;adc\\t%0, %1, %2"
|
||||
[(set_attr "length" "4")]
|
||||
)
|
||||
|
||||
|
||||
;; Conditional move insns
|
||||
|
||||
|
193
gcc/expmed.c
193
gcc/expmed.c
@ -5091,6 +5091,77 @@ expand_and (enum machine_mode mode, rtx op0, rtx op1, rtx target)
|
||||
return target;
|
||||
}
|
||||
|
||||
/* Helper function for emit_store_flag. */
|
||||
static rtx
|
||||
emit_store_flag_1 (rtx target, rtx subtarget, enum machine_mode mode,
|
||||
int normalizep)
|
||||
{
|
||||
rtx op0;
|
||||
enum machine_mode target_mode = GET_MODE (target);
|
||||
|
||||
/* If we are converting to a wider mode, first convert to
|
||||
TARGET_MODE, then normalize. This produces better combining
|
||||
opportunities on machines that have a SIGN_EXTRACT when we are
|
||||
testing a single bit. This mostly benefits the 68k.
|
||||
|
||||
If STORE_FLAG_VALUE does not have the sign bit set when
|
||||
interpreted in MODE, we can do this conversion as unsigned, which
|
||||
is usually more efficient. */
|
||||
if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (mode))
|
||||
{
|
||||
convert_move (target, subtarget,
|
||||
(GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
|
||||
&& 0 == (STORE_FLAG_VALUE
|
||||
& ((HOST_WIDE_INT) 1
|
||||
<< (GET_MODE_BITSIZE (mode) -1))));
|
||||
op0 = target;
|
||||
mode = target_mode;
|
||||
}
|
||||
else
|
||||
op0 = subtarget;
|
||||
|
||||
/* If we want to keep subexpressions around, don't reuse our last
|
||||
target. */
|
||||
if (optimize)
|
||||
subtarget = 0;
|
||||
|
||||
/* Now normalize to the proper value in MODE. Sometimes we don't
|
||||
have to do anything. */
|
||||
if (normalizep == 0 || normalizep == STORE_FLAG_VALUE)
|
||||
;
|
||||
/* STORE_FLAG_VALUE might be the most negative number, so write
|
||||
the comparison this way to avoid a compiler-time warning. */
|
||||
else if (- normalizep == STORE_FLAG_VALUE)
|
||||
op0 = expand_unop (mode, neg_optab, op0, subtarget, 0);
|
||||
|
||||
/* We don't want to use STORE_FLAG_VALUE < 0 below since this makes
|
||||
it hard to use a value of just the sign bit due to ANSI integer
|
||||
constant typing rules. */
|
||||
else if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
|
||||
&& (STORE_FLAG_VALUE
|
||||
& ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))))
|
||||
op0 = expand_shift (RSHIFT_EXPR, mode, op0,
|
||||
size_int (GET_MODE_BITSIZE (mode) - 1), subtarget,
|
||||
normalizep == 1);
|
||||
else
|
||||
{
|
||||
gcc_assert (STORE_FLAG_VALUE & 1);
|
||||
|
||||
op0 = expand_and (mode, op0, const1_rtx, subtarget);
|
||||
if (normalizep == -1)
|
||||
op0 = expand_unop (mode, neg_optab, op0, op0, 0);
|
||||
}
|
||||
|
||||
/* If we were converting to a smaller mode, do the conversion now. */
|
||||
if (target_mode != mode)
|
||||
{
|
||||
convert_move (target, op0, 0);
|
||||
return target;
|
||||
}
|
||||
else
|
||||
return op0;
|
||||
}
|
||||
|
||||
/* Emit a store-flags instruction for comparison CODE on OP0 and OP1
|
||||
and storing in TARGET. Normally return TARGET.
|
||||
Return 0 if that cannot be done.
|
||||
@ -5180,12 +5251,14 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
|
||||
{
|
||||
rtx op00, op01, op0both;
|
||||
|
||||
/* Do a logical OR or AND of the two words and compare the result. */
|
||||
/* Do a logical OR or AND of the two words and compare the
|
||||
result. */
|
||||
op00 = simplify_gen_subreg (word_mode, op0, mode, 0);
|
||||
op01 = simplify_gen_subreg (word_mode, op0, mode, UNITS_PER_WORD);
|
||||
op0both = expand_binop (word_mode,
|
||||
op1 == const0_rtx ? ior_optab : and_optab,
|
||||
op00, op01, NULL_RTX, unsignedp, OPTAB_DIRECT);
|
||||
op00, op01, NULL_RTX, unsignedp,
|
||||
OPTAB_DIRECT);
|
||||
|
||||
if (op0both != 0)
|
||||
return emit_store_flag (target, code, op0both, op1, word_mode,
|
||||
@ -5197,15 +5270,13 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
|
||||
|
||||
/* If testing the sign bit, can just test on high word. */
|
||||
op0h = simplify_gen_subreg (word_mode, op0, mode,
|
||||
subreg_highpart_offset (word_mode, mode));
|
||||
subreg_highpart_offset (word_mode,
|
||||
mode));
|
||||
return emit_store_flag (target, code, op0h, op1, word_mode,
|
||||
unsignedp, normalizep);
|
||||
}
|
||||
}
|
||||
|
||||
/* From now on, we won't change CODE, so set ICODE now. */
|
||||
icode = setcc_gen_code[(int) code];
|
||||
|
||||
/* If this is A < 0 or A >= 0, we can do this by taking the ones
|
||||
complement of A (for GE) and shifting the sign bit to the low bit. */
|
||||
if (op1 == const0_rtx && (code == LT || code == GE)
|
||||
@ -5213,7 +5284,8 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
|
||||
&& (normalizep || STORE_FLAG_VALUE == 1
|
||||
|| (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
|
||||
&& ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
|
||||
== (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)))))
|
||||
== ((unsigned HOST_WIDE_INT) 1
|
||||
<< (GET_MODE_BITSIZE (mode) - 1))))))
|
||||
{
|
||||
subtarget = target;
|
||||
|
||||
@ -5248,6 +5320,8 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
|
||||
return op0;
|
||||
}
|
||||
|
||||
icode = setcc_gen_code[(int) code];
|
||||
|
||||
if (icode != CODE_FOR_nothing)
|
||||
{
|
||||
insn_operand_predicate_fn pred;
|
||||
@ -5305,72 +5379,65 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
|
||||
if (pattern)
|
||||
{
|
||||
emit_insn (pattern);
|
||||
return emit_store_flag_1 (target, subtarget, compare_mode,
|
||||
normalizep);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We don't have an scc insn, so try a cstore insn. */
|
||||
|
||||
/* If we are converting to a wider mode, first convert to
|
||||
TARGET_MODE, then normalize. This produces better combining
|
||||
opportunities on machines that have a SIGN_EXTRACT when we are
|
||||
testing a single bit. This mostly benefits the 68k.
|
||||
for (compare_mode = mode; compare_mode != VOIDmode;
|
||||
compare_mode = GET_MODE_WIDER_MODE (compare_mode))
|
||||
{
|
||||
icode = cstore_optab->handlers[(int) compare_mode].insn_code;
|
||||
if (icode != CODE_FOR_nothing)
|
||||
break;
|
||||
}
|
||||
|
||||
If STORE_FLAG_VALUE does not have the sign bit set when
|
||||
interpreted in COMPARE_MODE, we can do this conversion as
|
||||
unsigned, which is usually more efficient. */
|
||||
if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (compare_mode))
|
||||
if (icode != CODE_FOR_nothing)
|
||||
{
|
||||
enum machine_mode result_mode
|
||||
= insn_data[(int) icode].operand[0].mode;
|
||||
rtx cstore_op0 = op0;
|
||||
rtx cstore_op1 = op1;
|
||||
|
||||
do_pending_stack_adjust ();
|
||||
last = get_last_insn ();
|
||||
|
||||
if (compare_mode != mode)
|
||||
{
|
||||
convert_move (target, subtarget,
|
||||
(GET_MODE_BITSIZE (compare_mode)
|
||||
<= HOST_BITS_PER_WIDE_INT)
|
||||
&& 0 == (STORE_FLAG_VALUE
|
||||
& ((HOST_WIDE_INT) 1
|
||||
<< (GET_MODE_BITSIZE (compare_mode) -1))));
|
||||
op0 = target;
|
||||
compare_mode = target_mode;
|
||||
cstore_op0 = convert_modes (compare_mode, mode, cstore_op0,
|
||||
unsignedp);
|
||||
cstore_op1 = convert_modes (compare_mode, mode, cstore_op1,
|
||||
unsignedp);
|
||||
}
|
||||
else
|
||||
op0 = subtarget;
|
||||
|
||||
if (!insn_data[(int) icode].operand[2].predicate (cstore_op0,
|
||||
compare_mode))
|
||||
cstore_op0 = copy_to_mode_reg (compare_mode, cstore_op0);
|
||||
|
||||
/* If we want to keep subexpressions around, don't reuse our
|
||||
last target. */
|
||||
if (!insn_data[(int) icode].operand[3].predicate (cstore_op1,
|
||||
compare_mode))
|
||||
cstore_op1 = copy_to_mode_reg (compare_mode, cstore_op1);
|
||||
|
||||
if (optimize)
|
||||
subtarget = 0;
|
||||
comparison = gen_rtx_fmt_ee (code, result_mode, cstore_op0,
|
||||
cstore_op1);
|
||||
subtarget = target;
|
||||
|
||||
/* Now normalize to the proper value in COMPARE_MODE. Sometimes
|
||||
we don't have to do anything. */
|
||||
if (normalizep == 0 || normalizep == STORE_FLAG_VALUE)
|
||||
;
|
||||
/* STORE_FLAG_VALUE might be the most negative number, so write
|
||||
the comparison this way to avoid a compiler-time warning. */
|
||||
else if (- normalizep == STORE_FLAG_VALUE)
|
||||
op0 = expand_unop (compare_mode, neg_optab, op0, subtarget, 0);
|
||||
if (optimize || !(insn_data[(int) icode].operand[0].predicate
|
||||
(subtarget, result_mode)))
|
||||
subtarget = gen_reg_rtx (result_mode);
|
||||
|
||||
/* We don't want to use STORE_FLAG_VALUE < 0 below since this
|
||||
makes it hard to use a value of just the sign bit due to
|
||||
ANSI integer constant typing rules. */
|
||||
else if (GET_MODE_BITSIZE (compare_mode) <= HOST_BITS_PER_WIDE_INT
|
||||
&& (STORE_FLAG_VALUE
|
||||
& ((HOST_WIDE_INT) 1
|
||||
<< (GET_MODE_BITSIZE (compare_mode) - 1))))
|
||||
op0 = expand_shift (RSHIFT_EXPR, compare_mode, op0,
|
||||
size_int (GET_MODE_BITSIZE (compare_mode) - 1),
|
||||
subtarget, normalizep == 1);
|
||||
else
|
||||
pattern = GEN_FCN (icode) (subtarget, comparison, cstore_op0,
|
||||
cstore_op1);
|
||||
|
||||
if (pattern)
|
||||
{
|
||||
gcc_assert (STORE_FLAG_VALUE & 1);
|
||||
|
||||
op0 = expand_and (compare_mode, op0, const1_rtx, subtarget);
|
||||
if (normalizep == -1)
|
||||
op0 = expand_unop (compare_mode, neg_optab, op0, op0, 0);
|
||||
emit_insn (pattern);
|
||||
return emit_store_flag_1 (target, subtarget, result_mode,
|
||||
normalizep);
|
||||
}
|
||||
|
||||
/* If we were converting to a smaller mode, do the
|
||||
conversion now. */
|
||||
if (target_mode != compare_mode)
|
||||
{
|
||||
convert_move (target, op0, 0);
|
||||
return target;
|
||||
}
|
||||
else
|
||||
return op0;
|
||||
}
|
||||
}
|
||||
|
||||
|
32
gcc/expr.c
32
gcc/expr.c
@ -9155,6 +9155,17 @@ do_store_flag (tree exp, rtx target, enum machine_mode mode, int only_cheap)
|
||||
return 0;
|
||||
|
||||
icode = setcc_gen_code[(int) code];
|
||||
|
||||
if (icode == CODE_FOR_nothing)
|
||||
{
|
||||
enum machine_mode wmode;
|
||||
|
||||
for (wmode = operand_mode;
|
||||
icode == CODE_FOR_nothing && wmode != VOIDmode;
|
||||
wmode = GET_MODE_WIDER_MODE (wmode))
|
||||
icode = cstore_optab->handlers[(int) wmode].insn_code;
|
||||
}
|
||||
|
||||
if (icode == CODE_FOR_nothing
|
||||
|| (only_cheap && insn_data[(int) icode].operand[0].mode != mode))
|
||||
{
|
||||
@ -9200,25 +9211,10 @@ do_store_flag (tree exp, rtx target, enum machine_mode mode, int only_cheap)
|
||||
target = gen_reg_rtx (GET_MODE (target));
|
||||
|
||||
emit_move_insn (target, invert ? const0_rtx : const1_rtx);
|
||||
result = compare_from_rtx (op0, op1, code, unsignedp,
|
||||
operand_mode, NULL_RTX);
|
||||
if (GET_CODE (result) == CONST_INT)
|
||||
return (((result == const0_rtx && ! invert)
|
||||
|| (result != const0_rtx && invert))
|
||||
? const0_rtx : const1_rtx);
|
||||
|
||||
/* The code of RESULT may not match CODE if compare_from_rtx
|
||||
decided to swap its operands and reverse the original code.
|
||||
|
||||
We know that compare_from_rtx returns either a CONST_INT or
|
||||
a new comparison code, so it is safe to just extract the
|
||||
code from RESULT. */
|
||||
code = GET_CODE (result);
|
||||
|
||||
label = gen_label_rtx ();
|
||||
gcc_assert (bcc_gen_fctn[(int) code]);
|
||||
|
||||
emit_jump_insn ((*bcc_gen_fctn[(int) code]) (label));
|
||||
do_compare_rtx_and_jump (op0, op1, code, unsignedp, operand_mode, NULL_RTX,
|
||||
NULL_RTX, label);
|
||||
|
||||
emit_move_insn (target, invert ? const1_rtx : const0_rtx);
|
||||
emit_label (label);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user