This patch adds a new if-conversion pattern for the following case:
if (test) x = A; else x = B;
A and B are constants, abs(A - B) == 2^N, A != 0, B != 0
Bootstrapped and regtested on x86_64-linux. OK for trunk?
--
Regards,
Mikhail Maltsev
gcc/testsuite/ChangeLog:
2016-05-23 Mikhail Maltsev <[email protected]>
* gcc.dg/ifcvt-6.c: New test.
gcc/ChangeLog:
2016-05-23 Mikhail Maltsev <[email protected]>
* ifcvt.c (noce_try_store_flag_constants): Add new pattern.
From 32ef17083d1ca6222e4befb1e1d8bae42d71db3b Mon Sep 17 00:00:00 2001
From: Mikhail Maltsev <[email protected]>
Date: Thu, 12 May 2016 15:23:03 +0300
Subject: [PATCH 2/2] Add ifcvt pattern
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index a9c146b..f06b05d 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -1260,6 +1260,7 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
{
ST_ADD_FLAG,
ST_SHIFT_FLAG,
+ ST_SHIFT_ADD_FLAG,
ST_IOR_FLAG
};
@@ -1384,6 +1385,12 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
normalize = -1;
reversep = true;
}
+ else if (exact_log2 (abs_hwi (diff)) >= 0
+ && (STORE_FLAG_VALUE == 1 || if_info->branch_cost >= 2))
+ {
+ strategy = ST_SHIFT_ADD_FLAG;
+ normalize = 1;
+ }
else
return FALSE;
@@ -1453,6 +1460,19 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
gen_int_mode (ifalse, mode), if_info->x,
0, OPTAB_WIDEN);
break;
+ case ST_SHIFT_ADD_FLAG:
+ {
+ /* if (test) x = 5; else x = 1;
+ => x = (test != 0) << 2 + 1; */
+ HOST_WIDE_INT diff_log = exact_log2 (abs_hwi (diff));
+ rtx diff_rtx
+ = expand_simple_binop (mode, ASHIFT, target, GEN_INT (diff_log),
+ if_info->x, 0, OPTAB_WIDEN);
+ target = expand_simple_binop (mode, (diff < 0) ? MINUS : PLUS,
+ gen_int_mode (ifalse, mode), diff_rtx,
+ if_info->x, 0, OPTAB_WIDEN);
+ break;
+ }
}
if (! target)
diff --git a/gcc/testsuite/gcc.dg/ifcvt-6.c b/gcc/testsuite/gcc.dg/ifcvt-6.c
new file mode 100644
index 0000000..c2cfb17
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ifcvt-6.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target x86_64-*-* } } */
+/* { dg-options "-fdump-rtl-ce1 -O2" } */
+
+int
+test1 (int a)
+{
+ return a % 2 != 0 ? 7 : 3;
+}
+
+/* { dg-final { scan-rtl-dump "3 true changes made" "ce1" } } */
+/* { dg-final { scan-assembler-not "sbbl" } } */
--
2.1.4