aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>2015-08-13 17:06:14 +0000
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>2015-08-13 17:06:14 +0000
commitc4f855e939f4d5ec5f0689148416c4e5a9c65f12 (patch)
treee685ff24cb587d4b60da1a55d574e0caa47ee177
parent42b7febc53cac744c7d0c0ae6e2dae0876b7d896 (diff)
downloadgcc-c4f855e939f4d5ec5f0689148416c4e5a9c65f12.zip
gcc-c4f855e939f4d5ec5f0689148416c4e5a9c65f12.tar.gz
gcc-c4f855e939f4d5ec5f0689148416c4e5a9c65f12.tar.bz2
[RTL-ifcvt] Allow PLUS+immediate expression in noce_try_store_flag_constants
* ifcvt.c (noce_try_store_flag_constants): Handle PLUS-immediate expressions in A and B. * gcc.target/aarch64/cinc_common_1.c: New test. From-SVN: r226869
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/ifcvt.c68
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/cinc_common_1.c64
4 files changed, 133 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 477335d..f3262e5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2015-08-13 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * ifcvt.c (noce_try_store_flag_constants): Handle PLUS-immediate
+ expressions in A and B.
+
2015-08-13 Richard Biener <rguenther@suse.de>
* tree.c (nonnull_arg_p): Move from ...
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 9b6f682..a46efec 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -1152,7 +1152,9 @@ noce_try_store_flag (struct noce_if_info *if_info)
}
}
-/* Convert "if (test) x = a; else x = b", for A and B constant. */
+/* Convert "if (test) x = a; else x = b", for A and B constant.
+ Also allow A = y + c1, B = y + c2, with a common y between A
+ and B. */
static int
noce_try_store_flag_constants (struct noce_if_info *if_info)
@@ -1163,14 +1165,31 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
HOST_WIDE_INT itrue, ifalse, diff, tmp;
int normalize;
bool can_reverse;
- machine_mode mode;
+ machine_mode mode = GET_MODE (if_info->x);;
+ rtx common = NULL_RTX;
+
+ rtx a = if_info->a;
+ rtx b = if_info->b;
+
+ /* Handle cases like x := test ? y + 3 : y + 4. */
+ if (GET_CODE (a) == PLUS
+ && GET_CODE (b) == PLUS
+ && CONST_INT_P (XEXP (a, 1))
+ && CONST_INT_P (XEXP (b, 1))
+ && rtx_equal_p (XEXP (a, 0), XEXP (b, 0))
+ && noce_operand_ok (XEXP (a, 0))
+ && if_info->branch_cost >= 2)
+ {
+ common = XEXP (a, 0);
+ a = XEXP (a, 1);
+ b = XEXP (b, 1);
+ }
- if (CONST_INT_P (if_info->a)
- && CONST_INT_P (if_info->b))
+ if (CONST_INT_P (a)
+ && CONST_INT_P (b))
{
- mode = GET_MODE (if_info->x);
- ifalse = INTVAL (if_info->a);
- itrue = INTVAL (if_info->b);
+ ifalse = INTVAL (a);
+ itrue = INTVAL (b);
bool subtract_flag_p = false;
diff = (unsigned HOST_WIDE_INT) itrue - ifalse;
@@ -1203,6 +1222,11 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
{
reversep = can_reverse;
subtract_flag_p = !can_reverse;
+ /* If we need to subtract the flag and we have PLUS-immediate
+ A and B then it is unlikely to be beneficial to play tricks
+ here. */
+ if (subtract_flag_p && common)
+ return FALSE;
}
/* test ? 3 : 4
=> can_reverse | 3 + (test == 0)
@@ -1211,6 +1235,11 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
{
reversep = can_reverse;
subtract_flag_p = !can_reverse;
+ /* If we need to subtract the flag and we have PLUS-immediate
+ A and B then it is unlikely to be beneficial to play tricks
+ here. */
+ if (subtract_flag_p && common)
+ return FALSE;
}
/* test ? 4 : 3
=> 4 + (test != 0). */
@@ -1249,6 +1278,15 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
}
start_sequence ();
+
+ /* If we have x := test ? x + 3 : x + 4 then move the original
+ x out of the way while we store flags. */
+ if (common && rtx_equal_p (common, if_info->x))
+ {
+ common = gen_reg_rtx (mode);
+ noce_emit_move_insn (common, if_info->x);
+ }
+
target = noce_emit_store_flag (if_info, if_info->x, reversep, normalize);
if (! target)
{
@@ -1260,13 +1298,27 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
=> x = 3 + (test == 0); */
if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
{
+ /* Add the common part now. This may allow combine to merge this
+ with the store flag operation earlier into some sort of conditional
+ increment/decrement if the target allows it. */
+ if (common)
+ target = expand_simple_binop (mode, PLUS,
+ target, common,
+ target, 0, OPTAB_WIDEN);
+
/* Always use ifalse here. It should have been swapped with itrue
when appropriate when reversep is true. */
target = expand_simple_binop (mode, subtract_flag_p ? MINUS : PLUS,
gen_int_mode (ifalse, mode), target,
if_info->x, 0, OPTAB_WIDEN);
}
-
+ /* Other cases are not beneficial when the original A and B are PLUS
+ expressions. */
+ else if (common)
+ {
+ end_sequence ();
+ return FALSE;
+ }
/* if (test) x = 8; else x = 0;
=> x = (test != 0) << 3; */
else if (ifalse == 0 && (tmp = exact_log2 (itrue)) >= 0)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ef2d567..4561032 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2015-08-13 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/cinc_common_1.c: New test.
+
2015-08-13 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/53421
diff --git a/gcc/testsuite/gcc.target/aarch64/cinc_common_1.c b/gcc/testsuite/gcc.target/aarch64/cinc_common_1.c
new file mode 100644
index 0000000..d041263
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/cinc_common_1.c
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+/* { dg-options "-save-temps -O2 -fno-inline" } */
+
+extern void abort (void);
+
+int
+foosi (int x)
+{
+ return x > 100 ? x - 2 : x - 1;
+}
+
+int
+barsi (int x)
+{
+ return x > 100 ? x + 4 : x + 3;
+}
+
+long
+foodi (long x)
+{
+ return x > 100 ? x - 2 : x - 1;
+}
+
+long
+bardi (long x)
+{
+ return x > 100 ? x + 4 : x + 3;
+}
+
+/* { dg-final { scan-assembler-times "cs?inc\tw\[0-9\]*" 2 } } */
+/* { dg-final { scan-assembler-times "cs?inc\tx\[0-9\]*" 2 } } */
+
+int
+main (void)
+{
+ if (foosi (105) != 103)
+ abort ();
+
+ if (foosi (95) != 94)
+ abort ();
+
+ if (barsi (105) != 109)
+ abort ();
+
+ if (barsi (95) != 98)
+ abort ();
+
+ if (foodi (105) != 103)
+ abort ();
+
+ if (foodi (95) != 94)
+ abort ();
+
+ if (bardi (105) != 109)
+ abort ();
+
+ if (bardi (95) != 98)
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "csel\tx\[0-9\]*.*" } } */
+/* { dg-final { scan-assembler-not "csel\tw\[0-9\]*.*" } } */