From 310eade1450995b55d9f8120561022fbf164b2ec Mon Sep 17 00:00:00 2001
From: Pronin Alexander 00812787 <pronin.alexander@huawei.com>
Date: Thu, 12 Jan 2023 14:52:49 +0300
Subject: [PATCH 03/18] Perform early if-conversion of simple arithmetic

---
 gcc/common.opt                      |  4 ++++
 gcc/match.pd                        | 25 +++++++++++++++++++
 gcc/testsuite/gcc.dg/ifcvt-gimple.c | 37 +++++++++++++++++++++++++++++
 3 files changed, 66 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/ifcvt-gimple.c

diff --git a/gcc/common.opt b/gcc/common.opt
index aa00fb7b0..dac477c04 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1821,6 +1821,10 @@ fif-conversion2
 Common Var(flag_if_conversion2) Optimization
 Perform conversion of conditional jumps to conditional execution.
 
+fif-conversion-gimple
+Common Var(flag_if_conversion_gimple) Optimization
+Perform conversion of conditional jumps to branchless equivalents during gimple transformations.
+
 fstack-reuse=
 Common Joined RejectNegative Enum(stack_reuse_level) Var(flag_stack_reuse) Init(SR_ALL) Optimization
 -fstack-reuse=[all|named_vars|none]	Set stack reuse level for local variables.
diff --git a/gcc/match.pd b/gcc/match.pd
index 6f24d5079..3cbaf2a5b 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4278,6 +4278,31 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   )
  )
 )
+
+(if (flag_if_conversion_gimple)
+ (for simple_op (plus minus bit_and bit_ior bit_xor)
+  (simplify
+   (cond @0 (simple_op @1 INTEGER_CST@2) @1)
+   (switch
+    /* a = cond ? a + 1 : a -> a = a + ((int) cond) */
+    (if (integer_onep (@2))
+     (simple_op @1 (convert (convert:boolean_type_node @0))))
+    /* a = cond ? a + powerof2cst : a ->
+       a = a + ((int) cond) << log2 (powerof2cst) */
+    (if (INTEGRAL_TYPE_P (type) && integer_pow2p (@2))
+     (with
+      {
+	tree shift = build_int_cst (integer_type_node, tree_log2 (@2));
+      }
+      (simple_op @1 (lshift (convert (convert:boolean_type_node @0))
+			    { shift; })
+      )
+     )
+    )
+   )
+  )
+ )
+)
 #endif
 
 #if GIMPLE
diff --git a/gcc/testsuite/gcc.dg/ifcvt-gimple.c b/gcc/testsuite/gcc.dg/ifcvt-gimple.c
new file mode 100644
index 000000000..0f7c87e5c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ifcvt-gimple.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fif-conversion-gimple -fdump-tree-optimized" } */
+
+int test_int (int optimizable_int) {
+    if (optimizable_int > 5)
+	++optimizable_int;
+    return optimizable_int;
+}
+
+int test_int_pow2 (int optimizable_int_pow2) {
+    if (optimizable_int_pow2 <= 4)
+	optimizable_int_pow2 += 1024;
+    return optimizable_int_pow2;
+}
+
+int test_int_non_pow2 (int not_optimizable_int_non_pow2) {
+    if (not_optimizable_int_non_pow2 == 1)
+	not_optimizable_int_non_pow2 += 513;
+    return not_optimizable_int_non_pow2;
+}
+
+float test_float (float not_optimizable_float) {
+    if (not_optimizable_float > 5)
+	not_optimizable_float += 1;
+    return not_optimizable_float;
+}
+
+/* Expecting if-else block in test_float and test_int_non_pow2 only. */
+/* { dg-final { scan-tree-dump-not "if \\(optimizable" "optimized" } } */
+/* { dg-final { scan-tree-dump "if \\(not_optimizable_int_non_pow2" "optimized" } } */
+/* { dg-final { scan-tree-dump "if \\(not_optimizable_float" "optimized" } } */
+/* { dg-final { scan-tree-dump-times "if " 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "else" 2 "optimized" } } */
+
+/* Expecting shifted result only for optimizable_int_pow2. */
+/* { dg-final { scan-tree-dump-times " << " 1 "optimized" } } */
+/* { dg-final { scan-tree-dump " << 10;" "optimized" } } */
-- 
2.33.0