+2003-11-02 Roger Sayle <roger@eyesopen.com>
+
+ PR optimization/10817
+ * ifcvt.c (noce_emit_move_insn): Improve documentation comment.
+ (noce_try_move): New function to optimize an if-the-else into an
+ unconditional move, i.e. "if (a!=b) x=a; else x=b" into "x=a".
+ (noce_process_if_block): Attempt simplification with noce_try_move.
+
+ * simplify-rtx.c (simplify_ternary_operation): Some minor fixes
+ and improvements to the optimizations of IF_THEN_ELSE expressions.
+ (simplify_subreg): Silence signed/unsigned comparison warning.
+
2003-11-02 Richard Sandiford <rsandifo@redhat.com>
* Makefile.in (targhooks.o, reload.o): Update dependencies.
};
static rtx noce_emit_store_flag (struct noce_if_info *, rtx, int, int);
+static int noce_try_move (struct noce_if_info *);
static int noce_try_store_flag (struct noce_if_info *);
static int noce_try_addcc (struct noce_if_info *);
static int noce_try_store_flag_constants (struct noce_if_info *);
|| code == GEU || code == GTU), normalize);
}
-/* Emit instruction to move an rtx into STRICT_LOW_PART. */
+/* Emit instruction to move an rtx, possibly into STRICT_LOW_PART.
+ X is the destination/target and Y is the value to copy. */
+
static void
noce_emit_move_insn (rtx x, rtx y)
{
GET_MODE_BITSIZE (inmode));
}
+/* Convert "if (a != b) x = a; else x = b" into "x = a" and
+ "if (a == b) x = a; else x = b" into "x = b". */
+
+static int
+noce_try_move (struct noce_if_info *if_info)
+{
+ rtx cond = if_info->cond;
+ enum rtx_code code = GET_CODE (cond);
+ rtx y, seq;
+
+ if (code != NE && code != EQ)
+ return FALSE;
+
+ /* This optimization isn't valid if either A or B could be a NaN
+ or a signed zero. */
+ if (HONOR_NANS (GET_MODE (if_info->x))
+ || HONOR_SIGNED_ZEROS (GET_MODE (if_info->x)))
+ return FALSE;
+
+ /* Check whether the operands of the comparison are A and in
+ either order. */
+ if ((rtx_equal_p (if_info->a, XEXP (cond, 0))
+ && rtx_equal_p (if_info->b, XEXP (cond, 1)))
+ || (rtx_equal_p (if_info->a, XEXP (cond, 1))
+ && rtx_equal_p (if_info->b, XEXP (cond, 0))))
+ {
+ y = (code == EQ) ? if_info->a : if_info->b;
+
+ /* Avoid generating the move if the source is the destination. */
+ if (! rtx_equal_p (if_info->x, y))
+ {
+ start_sequence ();
+ noce_emit_move_insn (if_info->x, y);
+ seq = get_insns ();
+ end_sequence ();
+ emit_insn_before_setloc (seq, if_info->jump,
+ INSN_LOCATOR (if_info->insn_a));
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
/* Convert "if (test) x = 1; else x = 0".
Only try 0 and STORE_FLAG_VALUE here. Other combinations will be
goto success;
}
+ if (noce_try_move (&if_info))
+ goto success;
if (noce_try_store_flag (&if_info))
goto success;
if (noce_try_minmax (&if_info))
if (GET_CODE (op0) == CONST_INT)
return op0 != const0_rtx ? op1 : op2;
- /* Convert a == b ? b : a to "a". */
- if (GET_CODE (op0) == NE && ! side_effects_p (op0)
- && !HONOR_NANS (mode)
- && rtx_equal_p (XEXP (op0, 0), op1)
- && rtx_equal_p (XEXP (op0, 1), op2))
+ /* Convert c ? a : a into "a". */
+ if (rtx_equal_p (op1, op2) && ! side_effects_p (op0))
return op1;
- else if (GET_CODE (op0) == EQ && ! side_effects_p (op0)
- && !HONOR_NANS (mode)
- && rtx_equal_p (XEXP (op0, 1), op1)
- && rtx_equal_p (XEXP (op0, 0), op2))
+
+ /* Convert a != b ? a : b into "a". */
+ if (GET_CODE (op0) == NE
+ && ! side_effects_p (op0)
+ && ! HONOR_NANS (mode)
+ && ! HONOR_SIGNED_ZEROS (mode)
+ && ((rtx_equal_p (XEXP (op0, 0), op1)
+ && rtx_equal_p (XEXP (op0, 1), op2))
+ || (rtx_equal_p (XEXP (op0, 0), op2)
+ && rtx_equal_p (XEXP (op0, 1), op1))))
+ return op1;
+
+ /* Convert a == b ? a : b into "b". */
+ if (GET_CODE (op0) == EQ
+ && ! side_effects_p (op0)
+ && ! HONOR_NANS (mode)
+ && ! HONOR_SIGNED_ZEROS (mode)
+ && ((rtx_equal_p (XEXP (op0, 0), op1)
+ && rtx_equal_p (XEXP (op0, 1), op2))
+ || (rtx_equal_p (XEXP (op0, 0), op2)
+ && rtx_equal_p (XEXP (op0, 1), op1))))
return op2;
- else if (GET_RTX_CLASS (GET_CODE (op0)) == '<' && ! side_effects_p (op0))
+
+ if (GET_RTX_CLASS (GET_CODE (op0)) == '<' && ! side_effects_p (op0))
{
enum machine_mode cmp_mode = (GET_MODE (XEXP (op0, 0)) == VOIDmode
? GET_MODE (XEXP (op0, 1))
}
}
break;
+
case VEC_MERGE:
if (GET_MODE (op0) != mode
|| GET_MODE (op1) != mode
of real and imaginary part. */
if (GET_CODE (op) == CONCAT)
{
- int is_realpart = byte < GET_MODE_UNIT_SIZE (innermode);
+ int is_realpart = byte < (unsigned int) GET_MODE_UNIT_SIZE (innermode);
rtx part = is_realpart ? XEXP (op, 0) : XEXP (op, 1);
unsigned int final_offset;
rtx res;
+2003-11-02 Roger Sayle <roger@eyesopen.com>
+
+ PR optimization/10817
+ * gcc.c-torture/compile/20031102-1.c: New test case.
+
2003-11-02 Kazu Hirata <kazu@cs.umass.edu>
* gcc.c-torture/execute/va-arg-25.c: Enable only if INT_MAX ==
--- /dev/null
+/* PR optimization/10817.
+ Check that the following code doesn't cause any problems
+ for GCC's if-conversion passes. */
+
+int foo(int t)
+{
+ int result = 0;
+ if (t != 0)
+ result = t;
+ return result;
+}
+