aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>2015-08-03 08:14:42 +0000
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>2015-08-03 08:14:42 +0000
commit44fef04ab18f57111e7d9f7dcd88d76a3c7bfc09 (patch)
tree826e24effa94dee676cf043a311912c2d3c9f2ce /gcc
parent03038b8b7ad8e68a203cecdc43a44ee5ddbb7f6f (diff)
downloadgcc-44fef04ab18f57111e7d9f7dcd88d76a3c7bfc09.zip
gcc-44fef04ab18f57111e7d9f7dcd88d76a3c7bfc09.tar.gz
gcc-44fef04ab18f57111e7d9f7dcd88d76a3c7bfc09.tar.bz2
[RTL-ifcvt] Improve conditional select ops on immediates
* ifcvt.c (noce_try_store_flag_constants): Make logic of the case when diff == STORE_FLAG_VALUE or diff == -STORE_FLAG_VALUE more explicit. Prefer to add the flag whenever possible. (noce_process_if_block): Try noce_try_store_flag_constants before noce_try_cmove. * gcc.target/aarch64/csel_bfx_1.c: New test. * gcc.target/aarch64/csel_imms_inc_1.c: Likewise. From-SVN: r226491
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/ifcvt.c63
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/aarch64/csel_bfx_1.c11
-rw-r--r--gcc/testsuite/gcc.target/aarch64/csel_imms_inc_1.c42
5 files changed, 118 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3a3012a..dac24dd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2015-08-03 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * ifcvt.c (noce_try_store_flag_constants): Make logic of the case
+ when diff == STORE_FLAG_VALUE or diff == -STORE_FLAG_VALUE more
+ explicit. Prefer to add the flag whenever possible.
+ (noce_process_if_block): Try noce_try_store_flag_constants before
+ noce_try_cmove.
+
2015-08-03 Richard Biener <rguenther@suse.de>
* genmatch.c (struct sinfo, struct sinfo_hashmap_traits, sinfo_map_t):
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 2d97cc5..1f29646 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -1159,9 +1159,10 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
{
rtx target;
rtx_insn *seq;
- int reversep;
+ bool reversep;
HOST_WIDE_INT itrue, ifalse, diff, tmp;
- int normalize, can_reverse;
+ int normalize;
+ bool can_reverse;
machine_mode mode;
if (CONST_INT_P (if_info->a)
@@ -1170,6 +1171,7 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
mode = GET_MODE (if_info->x);
ifalse = INTVAL (if_info->a);
itrue = INTVAL (if_info->b);
+ bool subtract_flag_p = false;
diff = (unsigned HOST_WIDE_INT) itrue - ifalse;
/* Make sure we can represent the difference between the two values. */
@@ -1182,23 +1184,61 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
can_reverse = (reversed_comparison_code (if_info->cond, if_info->jump)
!= UNKNOWN);
- reversep = 0;
+ reversep = false;
if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
- normalize = 0;
+ {
+ normalize = 0;
+ /* We could collapse these cases but it is easier to follow the
+ diff/STORE_FLAG_VALUE combinations when they are listed
+ explicitly. */
+
+ /* test ? 3 : 4
+ => 4 + (test != 0). */
+ if (diff < 0 && STORE_FLAG_VALUE < 0)
+ reversep = false;
+ /* test ? 4 : 3
+ => can_reverse | 4 + (test == 0)
+ !can_reverse | 3 - (test != 0). */
+ else if (diff > 0 && STORE_FLAG_VALUE < 0)
+ {
+ reversep = can_reverse;
+ subtract_flag_p = !can_reverse;
+ }
+ /* test ? 3 : 4
+ => can_reverse | 3 + (test == 0)
+ !can_reverse | 4 - (test != 0). */
+ else if (diff < 0 && STORE_FLAG_VALUE > 0)
+ {
+ reversep = can_reverse;
+ subtract_flag_p = !can_reverse;
+ }
+ /* test ? 4 : 3
+ => 4 + (test != 0). */
+ else if (diff > 0 && STORE_FLAG_VALUE > 0)
+ reversep = false;
+ else
+ gcc_unreachable ();
+ }
else if (ifalse == 0 && exact_log2 (itrue) >= 0
&& (STORE_FLAG_VALUE == 1
|| if_info->branch_cost >= 2))
normalize = 1;
else if (itrue == 0 && exact_log2 (ifalse) >= 0 && can_reverse
&& (STORE_FLAG_VALUE == 1 || if_info->branch_cost >= 2))
- normalize = 1, reversep = 1;
+ {
+ normalize = 1;
+ reversep = true;
+ }
else if (itrue == -1
&& (STORE_FLAG_VALUE == -1
|| if_info->branch_cost >= 2))
normalize = -1;
else if (ifalse == -1 && can_reverse
&& (STORE_FLAG_VALUE == -1 || if_info->branch_cost >= 2))
- normalize = -1, reversep = 1;
+ {
+ normalize = -1;
+ reversep = true;
+ }
else if ((if_info->branch_cost >= 2 && STORE_FLAG_VALUE == -1)
|| if_info->branch_cost >= 3)
normalize = -1;
@@ -1223,9 +1263,9 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
=> x = 3 + (test == 0); */
if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
{
- target = expand_simple_binop (mode,
- (diff == STORE_FLAG_VALUE
- ? PLUS : MINUS),
+ /* 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);
}
@@ -2731,13 +2771,14 @@ noce_process_if_block (struct noce_if_info *if_info)
goto success;
if (noce_try_abs (if_info))
goto success;
+ if (!targetm.have_conditional_execution ()
+ && noce_try_store_flag_constants (if_info))
+ goto success;
if (HAVE_conditional_move
&& noce_try_cmove (if_info))
goto success;
if (! targetm.have_conditional_execution ())
{
- if (noce_try_store_flag_constants (if_info))
- goto success;
if (noce_try_addcc (if_info))
goto success;
if (noce_try_store_flag_mask (if_info))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 55bfb35..640289c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2015-08-03 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/csel_bfx_1.c: New test.
+ * gcc.target/aarch64/csel_imms_inc_1.c: Likewise.
+
2015-08-02 Martin Sebor <msebor@redhat.com>
* g++.dg/Wframe-address-in-Wall.C: New test.
diff --git a/gcc/testsuite/gcc.target/aarch64/csel_bfx_1.c b/gcc/testsuite/gcc.target/aarch64/csel_bfx_1.c
new file mode 100644
index 0000000..c20597f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/csel_bfx_1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-save-temps -O2" } */
+
+int
+foo (int a, int b)
+{
+ return ((a & (1 << 25)) ? 5 : 4);
+}
+
+/* { dg-final { scan-assembler "ubfx\t\[xw\]\[0-9\]*.*" } } */
+/* { dg-final { scan-assembler-not "csel\tw\[0-9\]*.*" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/csel_imms_inc_1.c b/gcc/testsuite/gcc.target/aarch64/csel_imms_inc_1.c
new file mode 100644
index 0000000..2ae434d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/csel_imms_inc_1.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-save-temps -O2 -fno-inline" } */
+
+extern void abort (void);
+
+int
+fooinc (int x)
+{
+ if (x)
+ return 1025;
+ else
+ return 1026;
+}
+
+int
+fooinc2 (int x)
+{
+ if (x)
+ return 1026;
+ else
+ return 1025;
+}
+
+int
+main (void)
+{
+ if (fooinc (0) != 1026)
+ abort ();
+
+ if (fooinc (1) != 1025)
+ abort ();
+
+ if (fooinc2 (0) != 1025)
+ abort ();
+
+ if (fooinc2 (1) != 1026)
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "csel\tw\[0-9\]*.*" } } */