aboutsummaryrefslogtreecommitdiff
path: root/gcc/combine.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/combine.c')
-rw-r--r--gcc/combine.c228
1 files changed, 123 insertions, 105 deletions
diff --git a/gcc/combine.c b/gcc/combine.c
index 662f05f2240..4bf07179054 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -86,26 +86,11 @@ Boston, MA 02111-1307, USA. */
#include "function.h"
/* Include expr.h after insn-config.h so we get HAVE_conditional_move. */
#include "expr.h"
-#include "insn-flags.h"
-#include "insn-codes.h"
#include "insn-attr.h"
#include "recog.h"
#include "real.h"
#include "toplev.h"
-#ifndef ACCUMULATE_OUTGOING_ARGS
-#define ACCUMULATE_OUTGOING_ARGS 0
-#endif
-
-/* Supply a default definition for PUSH_ARGS. */
-#ifndef PUSH_ARGS
-#ifdef PUSH_ROUNDING
-#define PUSH_ARGS !ACCUMULATE_OUTGOING_ARGS
-#else
-#define PUSH_ARGS 0
-#endif
-#endif
-
/* It is not safe to use ordinary gen_lowpart in combine.
Use gen_lowpart_for_combine instead. See comments there. */
#define gen_lowpart dont_use_gen_lowpart_you_dummy
@@ -146,6 +131,12 @@ static int max_uid_cuid;
#define INSN_CUID(INSN) \
(INSN_UID (INSN) > max_uid_cuid ? insn_cuid (INSN) : uid_cuid[INSN_UID (INSN)])
+/* In case BITS_PER_WORD == HOST_BITS_PER_WIDE_INT, shifting by
+ BITS_PER_WORD would invoke undefined behavior. Work around it. */
+
+#define UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD(val) \
+ (((unsigned HOST_WIDE_INT)(val) << (BITS_PER_WORD - 1)) << 1)
+
/* Maximum register number, which is the size of the tables below. */
static unsigned int combine_max_regno;
@@ -1477,7 +1468,7 @@ cant_combine_insn_p (insn)
Here I1 and I2 appear earlier than I3.
I1 can be zero; then we combine just I2 into I3.
- It we are combining three insns and the resulting insn is not recognized,
+ If we are combining three insns and the resulting insn is not recognized,
try splitting it into two insns. If that happens, I2 and I3 are retained
and I1 is pseudo-deleted by turning it into a NOTE. Otherwise, I1 and I2
are pseudo-deleted.
@@ -1667,7 +1658,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
if (HOST_BITS_PER_WIDE_INT < BITS_PER_WORD)
abort ();
- lo &= ~(((unsigned HOST_WIDE_INT)1 << BITS_PER_WORD) - 1);
+ lo &= ~(UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD (1) - 1);
lo |= INTVAL (SET_SRC (PATTERN (i3)));
}
else if (HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
@@ -1677,9 +1668,10 @@ try_combine (i3, i2, i1, new_direct_jump_p)
int sign = -(int) ((unsigned HOST_WIDE_INT) lo
>> (HOST_BITS_PER_WIDE_INT - 1));
- lo &= ~((((unsigned HOST_WIDE_INT)1 << BITS_PER_WORD) - 1)
- << BITS_PER_WORD);
- lo |= INTVAL (SET_SRC (PATTERN (i3))) << BITS_PER_WORD;
+ lo &= ~ (UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD
+ (UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD (1) - 1));
+ lo |= (UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD
+ (INTVAL (SET_SRC (PATTERN (i3)))));
if (hi == sign)
hi = lo < 0 ? -1 : 0;
}
@@ -3602,15 +3594,15 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
&& (GET_RTX_CLASS (GET_CODE (SUBREG_REG (XEXP (x, 0))))
== 'o'))))))
{
- rtx cond, true, false;
+ rtx cond, true_rtx, false_rtx;
- cond = if_then_else_cond (x, &true, &false);
+ cond = if_then_else_cond (x, &true_rtx, &false_rtx);
if (cond != 0
/* If everything is a comparison, what we have is highly unlikely
to be simpler, so don't use it. */
&& ! (GET_RTX_CLASS (code) == '<'
- && (GET_RTX_CLASS (GET_CODE (true)) == '<'
- || GET_RTX_CLASS (GET_CODE (false)) == '<')))
+ && (GET_RTX_CLASS (GET_CODE (true_rtx)) == '<'
+ || GET_RTX_CLASS (GET_CODE (false_rtx)) == '<')))
{
rtx cop1 = const0_rtx;
enum rtx_code cond_code = simplify_comparison (NE, &cond, &cop1);
@@ -3620,35 +3612,35 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
/* Simplify the alternative arms; this may collapse the true and
false arms to store-flag values. */
- true = subst (true, pc_rtx, pc_rtx, 0, 0);
- false = subst (false, pc_rtx, pc_rtx, 0, 0);
+ true_rtx = subst (true_rtx, pc_rtx, pc_rtx, 0, 0);
+ false_rtx = subst (false_rtx, pc_rtx, pc_rtx, 0, 0);
- /* If true and false are not general_operands, an if_then_else
+ /* If true_rtx and false_rtx are not general_operands, an if_then_else
is unlikely to be simpler. */
- if (general_operand (true, VOIDmode)
- && general_operand (false, VOIDmode))
+ if (general_operand (true_rtx, VOIDmode)
+ && general_operand (false_rtx, VOIDmode))
{
/* Restarting if we generate a store-flag expression will cause
us to loop. Just drop through in this case. */
/* If the result values are STORE_FLAG_VALUE and zero, we can
just make the comparison operation. */
- if (true == const_true_rtx && false == const0_rtx)
+ if (true_rtx == const_true_rtx && false_rtx == const0_rtx)
x = gen_binary (cond_code, mode, cond, cop1);
- else if (true == const0_rtx && false == const_true_rtx)
+ else if (true_rtx == const0_rtx && false_rtx == const_true_rtx)
x = gen_binary (reverse_condition (cond_code),
mode, cond, cop1);
/* Likewise, we can make the negate of a comparison operation
if the result values are - STORE_FLAG_VALUE and zero. */
- else if (GET_CODE (true) == CONST_INT
- && INTVAL (true) == - STORE_FLAG_VALUE
- && false == const0_rtx)
+ else if (GET_CODE (true_rtx) == CONST_INT
+ && INTVAL (true_rtx) == - STORE_FLAG_VALUE
+ && false_rtx == const0_rtx)
x = gen_unary (NEG, mode, mode,
gen_binary (cond_code, mode, cond, cop1));
- else if (GET_CODE (false) == CONST_INT
- && INTVAL (false) == - STORE_FLAG_VALUE
- && true == const0_rtx)
+ else if (GET_CODE (false_rtx) == CONST_INT
+ && INTVAL (false_rtx) == - STORE_FLAG_VALUE
+ && true_rtx == const0_rtx)
x = gen_unary (NEG, mode, mode,
gen_binary (reverse_condition (cond_code),
mode, cond, cop1));
@@ -3656,7 +3648,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
return gen_rtx_IF_THEN_ELSE (mode,
gen_binary (cond_code, VOIDmode,
cond, cop1),
- true, false);
+ true_rtx, false_rtx);
code = GET_CODE (x);
op0_mode = VOIDmode;
@@ -4642,8 +4634,8 @@ simplify_if_then_else (x)
{
enum machine_mode mode = GET_MODE (x);
rtx cond = XEXP (x, 0);
- rtx true = XEXP (x, 1);
- rtx false = XEXP (x, 2);
+ rtx true_rtx = XEXP (x, 1);
+ rtx false_rtx = XEXP (x, 2);
enum rtx_code true_code = GET_CODE (cond);
int comparison_p = GET_RTX_CLASS (true_code) == '<';
rtx temp;
@@ -4652,12 +4644,12 @@ simplify_if_then_else (x)
rtx reversed;
/* Simplify storing of the truth value. */
- if (comparison_p && true == const_true_rtx && false == const0_rtx)
+ if (comparison_p && true_rtx == const_true_rtx && false_rtx == const0_rtx)
return gen_binary (true_code, mode, XEXP (cond, 0), XEXP (cond, 1));
/* Also when the truth value has to be reversed. */
if (comparison_p
- && true == const0_rtx && false == const_true_rtx
+ && true_rtx == const0_rtx && false_rtx == const_true_rtx
&& (reversed = reversed_comparison (cond, mode, XEXP (cond, 0),
XEXP (cond, 1))))
return reversed;
@@ -4682,7 +4674,7 @@ simplify_if_then_else (x)
if (false_code == EQ)
{
swapped = 1, true_code = EQ, false_code = NE;
- temp = true, true = false, false = temp;
+ temp = true_rtx, true_rtx = false_rtx, false_rtx = temp;
}
/* If we are comparing against zero and the expression being tested has
@@ -4701,18 +4693,21 @@ simplify_if_then_else (x)
branch and it is used in the arm. Be careful due to the potential
of locally-shared RTL. */
- if (reg_mentioned_p (from, true))
- true = subst (known_cond (copy_rtx (true), true_code, from, true_val),
+ if (reg_mentioned_p (from, true_rtx))
+ true_rtx = subst (known_cond (copy_rtx (true_rtx), true_code,
+ from, true_val),
pc_rtx, pc_rtx, 0, 0);
- if (reg_mentioned_p (from, false))
- false = subst (known_cond (copy_rtx (false), false_code,
+ if (reg_mentioned_p (from, false_rtx))
+ false_rtx = subst (known_cond (copy_rtx (false_rtx), false_code,
from, false_val),
pc_rtx, pc_rtx, 0, 0);
- SUBST (XEXP (x, 1), swapped ? false : true);
- SUBST (XEXP (x, 2), swapped ? true : false);
+ SUBST (XEXP (x, 1), swapped ? false_rtx : true_rtx);
+ SUBST (XEXP (x, 2), swapped ? true_rtx : false_rtx);
- true = XEXP (x, 1), false = XEXP (x, 2), true_code = GET_CODE (cond);
+ true_rtx = XEXP (x, 1);
+ false_rtx = XEXP (x, 2);
+ true_code = GET_CODE (cond);
}
/* If we have (if_then_else FOO (pc) (label_ref BAR)) and FOO can be
@@ -4723,27 +4718,28 @@ simplify_if_then_else (x)
if (comparison_p
&& combine_reversed_comparison_code (cond) != UNKNOWN
- && (true == pc_rtx
- || (CONSTANT_P (true)
- && GET_CODE (false) != CONST_INT && false != pc_rtx)
- || true == const0_rtx
- || (GET_RTX_CLASS (GET_CODE (true)) == 'o'
- && GET_RTX_CLASS (GET_CODE (false)) != 'o')
- || (GET_CODE (true) == SUBREG
- && GET_RTX_CLASS (GET_CODE (SUBREG_REG (true))) == 'o'
- && GET_RTX_CLASS (GET_CODE (false)) != 'o')
- || reg_mentioned_p (true, false)
- || rtx_equal_p (false, XEXP (cond, 0))))
+ && (true_rtx == pc_rtx
+ || (CONSTANT_P (true_rtx)
+ && GET_CODE (false_rtx) != CONST_INT && false_rtx != pc_rtx)
+ || true_rtx == const0_rtx
+ || (GET_RTX_CLASS (GET_CODE (true_rtx)) == 'o'
+ && GET_RTX_CLASS (GET_CODE (false_rtx)) != 'o')
+ || (GET_CODE (true_rtx) == SUBREG
+ && GET_RTX_CLASS (GET_CODE (SUBREG_REG (true_rtx))) == 'o'
+ && GET_RTX_CLASS (GET_CODE (false_rtx)) != 'o')
+ || reg_mentioned_p (true_rtx, false_rtx)
+ || rtx_equal_p (false_rtx, XEXP (cond, 0))))
{
true_code = reversed_comparison_code (cond, NULL);
SUBST (XEXP (x, 0),
reversed_comparison (cond, GET_MODE (cond), XEXP (cond, 0),
XEXP (cond, 1)));
- SUBST (XEXP (x, 1), false);
- SUBST (XEXP (x, 2), true);
+ SUBST (XEXP (x, 1), false_rtx);
+ SUBST (XEXP (x, 2), true_rtx);
- temp = true, true = false, false = temp, cond = XEXP (x, 0);
+ temp = true_rtx, true_rtx = false_rtx, false_rtx = temp;
+ cond = XEXP (x, 0);
/* It is possible that the conditional has been simplified out. */
true_code = GET_CODE (cond);
@@ -4752,37 +4748,38 @@ simplify_if_then_else (x)
/* If the two arms are identical, we don't need the comparison. */
- if (rtx_equal_p (true, false) && ! side_effects_p (cond))
- return true;
+ if (rtx_equal_p (true_rtx, false_rtx) && ! side_effects_p (cond))
+ return true_rtx;
/* Convert a == b ? b : a to "a". */
if (true_code == EQ && ! side_effects_p (cond)
&& (! FLOAT_MODE_P (mode) || flag_fast_math)
- && rtx_equal_p (XEXP (cond, 0), false)
- && rtx_equal_p (XEXP (cond, 1), true))
- return false;
+ && rtx_equal_p (XEXP (cond, 0), false_rtx)
+ && rtx_equal_p (XEXP (cond, 1), true_rtx))
+ return false_rtx;
else if (true_code == NE && ! side_effects_p (cond)
&& (! FLOAT_MODE_P (mode) || flag_fast_math)
- && rtx_equal_p (XEXP (cond, 0), true)
- && rtx_equal_p (XEXP (cond, 1), false))
- return true;
+ && rtx_equal_p (XEXP (cond, 0), true_rtx)
+ && rtx_equal_p (XEXP (cond, 1), false_rtx))
+ return true_rtx;
/* Look for cases where we have (abs x) or (neg (abs X)). */
if (GET_MODE_CLASS (mode) == MODE_INT
- && GET_CODE (false) == NEG
- && rtx_equal_p (true, XEXP (false, 0))
+ && GET_CODE (false_rtx) == NEG
+ && rtx_equal_p (true_rtx, XEXP (false_rtx, 0))
&& comparison_p
- && rtx_equal_p (true, XEXP (cond, 0))
- && ! side_effects_p (true))
+ && rtx_equal_p (true_rtx, XEXP (cond, 0))
+ && ! side_effects_p (true_rtx))
switch (true_code)
{
case GT:
case GE:
- return gen_unary (ABS, mode, mode, true);
+ return gen_unary (ABS, mode, mode, true_rtx);
case LT:
case LE:
- return gen_unary (NEG, mode, mode, gen_unary (ABS, mode, mode, true));
+ return gen_unary (NEG, mode, mode,
+ gen_unary (ABS, mode, mode, true_rtx));
default:
break;
}
@@ -4791,23 +4788,23 @@ simplify_if_then_else (x)
if ((! FLOAT_MODE_P (mode) || flag_fast_math)
&& comparison_p
- && rtx_equal_p (XEXP (cond, 0), true)
- && rtx_equal_p (XEXP (cond, 1), false)
+ && rtx_equal_p (XEXP (cond, 0), true_rtx)
+ && rtx_equal_p (XEXP (cond, 1), false_rtx)
&& ! side_effects_p (cond))
switch (true_code)
{
case GE:
case GT:
- return gen_binary (SMAX, mode, true, false);
+ return gen_binary (SMAX, mode, true_rtx, false_rtx);
case LE:
case LT:
- return gen_binary (SMIN, mode, true, false);
+ return gen_binary (SMIN, mode, true_rtx, false_rtx);
case GEU:
case GTU:
- return gen_binary (UMAX, mode, true, false);
+ return gen_binary (UMAX, mode, true_rtx, false_rtx);
case LEU:
case LTU:
- return gen_binary (UMIN, mode, true, false);
+ return gen_binary (UMIN, mode, true_rtx, false_rtx);
default:
break;
}
@@ -4822,8 +4819,8 @@ simplify_if_then_else (x)
if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
&& comparison_p && mode != VOIDmode && ! side_effects_p (x))
{
- rtx t = make_compound_operation (true, SET);
- rtx f = make_compound_operation (false, SET);
+ rtx t = make_compound_operation (true_rtx, SET);
+ rtx f = make_compound_operation (false_rtx, SET);
rtx cond_op0 = XEXP (cond, 0);
rtx cond_op1 = XEXP (cond, 1);
enum rtx_code op = NIL, extend_op = NIL;
@@ -4936,12 +4933,12 @@ simplify_if_then_else (x)
can actually do this more generally, but it doesn't seem worth it. */
if (true_code == NE && XEXP (cond, 1) == const0_rtx
- && false == const0_rtx && GET_CODE (true) == CONST_INT
+ && false_rtx == const0_rtx && GET_CODE (true_rtx) == CONST_INT
&& ((1 == nonzero_bits (XEXP (cond, 0), mode)
- && (i = exact_log2 (INTVAL (true))) >= 0)
+ && (i = exact_log2 (INTVAL (true_rtx))) >= 0)
|| ((num_sign_bit_copies (XEXP (cond, 0), mode)
== GET_MODE_BITSIZE (mode))
- && (i = exact_log2 (-INTVAL (true))) >= 0)))
+ && (i = exact_log2 (-INTVAL (true_rtx))) >= 0)))
return
simplify_shift_const (NULL_RTX, ASHIFT, mode,
gen_lowpart_for_combine (mode, XEXP (cond, 0)), i);
@@ -5190,29 +5187,31 @@ simplify_set (x)
== GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (src, 0), 0))))
&& ! side_effects_p (src))
{
- rtx true = (GET_CODE (XEXP (src, 0)) == NE
+ rtx true_rtx = (GET_CODE (XEXP (src, 0)) == NE
? XEXP (src, 1) : XEXP (src, 2));
- rtx false = (GET_CODE (XEXP (src, 0)) == NE
+ rtx false_rtx = (GET_CODE (XEXP (src, 0)) == NE
? XEXP (src, 2) : XEXP (src, 1));
rtx term1 = const0_rtx, term2, term3;
- if (GET_CODE (true) == IOR && rtx_equal_p (XEXP (true, 0), false))
- term1 = false, true = XEXP (true, 1), false = const0_rtx;
- else if (GET_CODE (true) == IOR
- && rtx_equal_p (XEXP (true, 1), false))
- term1 = false, true = XEXP (true, 0), false = const0_rtx;
- else if (GET_CODE (false) == IOR
- && rtx_equal_p (XEXP (false, 0), true))
- term1 = true, false = XEXP (false, 1), true = const0_rtx;
- else if (GET_CODE (false) == IOR
- && rtx_equal_p (XEXP (false, 1), true))
- term1 = true, false = XEXP (false, 0), true = const0_rtx;
-
- term2 = gen_binary (AND, GET_MODE (src), XEXP (XEXP (src, 0), 0), true);
+ if (GET_CODE (true_rtx) == IOR
+ && rtx_equal_p (XEXP (true_rtx, 0), false_rtx))
+ term1 = false_rtx, true_rtx = XEXP(true_rtx, 1), false_rtx = const0_rtx;
+ else if (GET_CODE (true_rtx) == IOR
+ && rtx_equal_p (XEXP (true_rtx, 1), false_rtx))
+ term1 = false_rtx, true_rtx = XEXP(true_rtx, 0), false_rtx = const0_rtx;
+ else if (GET_CODE (false_rtx) == IOR
+ && rtx_equal_p (XEXP (false_rtx, 0), true_rtx))
+ term1 = true_rtx, false_rtx = XEXP(false_rtx, 1), true_rtx = const0_rtx;
+ else if (GET_CODE (false_rtx) == IOR
+ && rtx_equal_p (XEXP (false_rtx, 1), true_rtx))
+ term1 = true_rtx, false_rtx = XEXP(false_rtx, 0), true_rtx = const0_rtx;
+
+ term2 = gen_binary (AND, GET_MODE (src),
+ XEXP (XEXP (src, 0), 0), true_rtx);
term3 = gen_binary (AND, GET_MODE (src),
gen_unary (NOT, GET_MODE (src), GET_MODE (src),
XEXP (XEXP (src, 0), 0)),
- false);
+ false_rtx);
SUBST (SET_SRC (x),
gen_binary (IOR, GET_MODE (src),
@@ -12212,6 +12211,25 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
break;
case REG_EH_REGION:
+ /* These notes must remain with the call or trapping instruction. */
+ if (GET_CODE (i3) == CALL_INSN)
+ place = i3;
+ else if (i2 && GET_CODE (i2) == CALL_INSN)
+ place = i2;
+ else if (flag_non_call_exceptions)
+ {
+ if (may_trap_p (i3))
+ place = i3;
+ else if (i2 && may_trap_p (i2))
+ place = i2;
+ /* ??? Otherwise assume we've combined things such that we
+ can now prove that the instructions can't trap. Drop the
+ note in this case. */
+ }
+ else
+ abort ();
+ break;
+
case REG_EH_RETHROW:
case REG_NORETURN:
/* These notes must remain with the call. It should not be