aboutsummaryrefslogtreecommitdiff
path: root/gcc/ifcvt.c
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2003-11-02 13:56:42 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2003-11-02 13:56:42 +0000
commit31f0f571e61d1d7f8ff67a4f6a741173dfc4161c (patch)
tree3b7c1888d9ed7fad3b4bf1b5208f5a4d7e6b11cf /gcc/ifcvt.c
parent2077750a864920bb1f80a1b6998142d2b3c80dc8 (diff)
downloadgcc-31f0f571e61d1d7f8ff67a4f6a741173dfc4161c.zip
gcc-31f0f571e61d1d7f8ff67a4f6a741173dfc4161c.tar.gz
gcc-31f0f571e61d1d7f8ff67a4f6a741173dfc4161c.tar.bz2
re PR rtl-optimization/10817 (gcc does not optimize result=0;if(t!=0)result=t; to result=t;)
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. * gcc.c-torture/compile/20031102-1.c: New test case. From-SVN: r73200
Diffstat (limited to 'gcc/ifcvt.c')
-rw-r--r--gcc/ifcvt.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index fe38060..9844bf4 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -602,6 +602,7 @@ struct noce_if_info
};
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 *);
@@ -674,7 +675,9 @@ noce_emit_store_flag (struct noce_if_info *if_info, rtx x, int reversep,
|| 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)
{
@@ -697,6 +700,49 @@ 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
@@ -1894,6 +1940,8 @@ noce_process_if_block (struct ce_if_block * ce_info)
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))