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  <malts...@gmail.com>

        * gcc.dg/ifcvt-6.c: New test.


gcc/ChangeLog:

2016-05-23  Mikhail Maltsev  <malts...@gmail.com>

        * ifcvt.c (noce_try_store_flag_constants): Add new pattern.
From 32ef17083d1ca6222e4befb1e1d8bae42d71db3b Mon Sep 17 00:00:00 2001
From: Mikhail Maltsev <maltsevm@gmail.com>
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

Reply via email to