From 44fef04ab18f57111e7d9f7dcd88d76a3c7bfc09 Mon Sep 17 00:00:00 2001 From: Kyrylo Tkachov Date: Mon, 3 Aug 2015 08:14:42 +0000 Subject: [PATCH] [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 --- gcc/ChangeLog | 8 +++ gcc/ifcvt.c | 63 +++++++++++++++---- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.target/aarch64/csel_bfx_1.c | 11 ++++ .../gcc.target/aarch64/csel_imms_inc_1.c | 42 +++++++++++++ 5 files changed, 118 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/csel_bfx_1.c create mode 100644 gcc/testsuite/gcc.target/aarch64/csel_imms_inc_1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3a3012a89e5..dac24ddd44f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2015-08-03 Kyrylo Tkachov + + * 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 * genmatch.c (struct sinfo, struct sinfo_hashmap_traits, sinfo_map_t): diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 2d97cc57845..1f2964651f8 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 55bfb355cd8..640289c2c4d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-08-03 Kyrylo Tkachov + + * gcc.target/aarch64/csel_bfx_1.c: New test. + * gcc.target/aarch64/csel_imms_inc_1.c: Likewise. + 2015-08-02 Martin Sebor * 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 00000000000..c20597f5f7e --- /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 00000000000..2ae434da5a0 --- /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\]*.*" } } */ -- 2.30.2