This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] Optimization to conditional and/or in ARM back-end


Hi,

This patch is to implement a peephole like optimization in ARM back-end.

If we have an if condition expression like "((r3 != 0) & r1) != 0",
originally the binary code to be generated is like,

        cmp     r3, #0
        ite     eq
        moveq   r1, #0
        andne   r1, r1, #1
        cmp     r1, #0

But actually this expression could be transformed into "((r3 != x) & (r1 !=
0)) != 0", if we know r2 is with bool type. This way we could generate new
binary code like,

        cmp     r3, #0
        it      ne
        cmpne   r1, #0

The question is how to judge r2 is a bool variable in back-end. I'm using
REG_EXPR in function arm_check_logic_with_bool_reg to check if r2 is a bool,
this function is being invoked in pattern "*cond_<code>". 

May I really use REG_EXPR this way in GCC back-end code? I posted a related
topic at http://gcc.gnu.org/ml/gcc/2011-11/msg00417.html.

If the answer is No, is there any suggestions about either how to judge this
bool type or how to implement this optimization?

Appreciate your comments in advance!

Thanks,
-Jiangning


diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 23a29c6..8b12d48
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -114,6 +114,7 @@ extern rtx arm_gen_load_multiple (int *, int, rtx, int,
rtx, HOST_WIDE_INT *);
 extern rtx arm_gen_store_multiple (int *, int, rtx, int, rtx, HOST_WIDE_INT
*);
 extern int arm_gen_movmemqi (rtx *);
 extern enum machine_mode arm_select_cc_mode (RTX_CODE, rtx, rtx);
+extern bool arm_check_logic_with_bool_reg (RTX_CODE, rtx, rtx);
 extern enum machine_mode arm_select_dominance_cc_mode (rtx, rtx,
 						       HOST_WIDE_INT);
 extern rtx arm_gen_compare_reg (RTX_CODE, rtx, rtx);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index a429c19..e96f24a
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -10910,6 +10910,41 @@ arm_gen_movmemqi (rtx *operands)
   return 1;
 }
 
+/* Check whether the expression "rc <cmp1> <bool_reg>" can be transformed
+   to use conditional comparison or not.  */
+bool
+arm_check_logic_with_bool_reg (RTX_CODE rc, rtx bool_reg, rtx cmp1) {
+  rtx cmp2;
+  HOST_WIDE_INT dom_cc;
+
+  if (!REG_P (bool_reg))
+    return false;
+
+  if (REG_EXPR (bool_reg) == NULL)
+    return false;
+
+  if (TREE_CODE (REG_EXPR (bool_reg)) != VAR_DECL)
+    return false;
+
+  if (TREE_CODE (TREE_TYPE (REG_EXPR (bool_reg))) != BOOLEAN_TYPE)
+    return false;
+
+  cmp2 = gen_rtx_NE (GET_MODE (bool_reg), bool_reg, const0_rtx);
+
+  if (rc == AND)
+    dom_cc = DOM_CC_X_AND_Y;
+  else if (rc == IOR)
+    dom_cc = DOM_CC_X_OR_Y;
+  else
+    gcc_unreachable ();
+
+  if (arm_select_dominance_cc_mode (cmp1, cmp2, dom_cc) == CCmode)
+    return false;
+
+  return true;
+}
+
+
 /* Select a dominance comparison mode if possible for a test of the general
    form (OP (COND_OR (X) (Y)) (const_int 0)).  We support three forms.
    COND_OR == DOM_CC_X_AND_Y => (X && Y)
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index a78ba88..e90a78e
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -9172,6 +9172,64 @@
    (set_attr "length" "4,4,8")]
 )
 
+; This pattern matches expression like example "((r1 != x) & r2) != 0".
+; Here r2 is a register with data type boolean.
+; This pattern can transform to code matching patterns cmp_and.
+; Likewise, code matching pattern cmp_ior could be generated, if it is |
+; rather than & in the example.
+(define_insn_and_split "*cond_<code>"
+  [(set (match_operand 0 "cc_register" "")
+	(compare
+         (ior_and:SI
+	  (match_operator:SI 4 "arm_comparison_operator"
+           [(match_operand:SI 2 "s_register_operand" "r,r")
+	    (match_operand:SI 3 "arm_add_operand" "rI,L")])
+          (match_operand:SI 1 "s_register_operand" "r,r"))
+	 (const_int 0)))]
+  "TARGET_32BIT
+   && arm_check_logic_with_bool_reg (<CODE>, operands[1], operands[4])"
+  "#"
+  "&& 1"
+  [(set (match_dup 7)
+	(compare
+	 (match_op_dup 5
+	  [(match_op_dup 4 [(match_dup 2) (match_dup 3)])
+	   (match_op_dup 6 [(match_dup 1) (const_int 0)])])
+	 (const_int 0)))]
+  "
+  {
+    HOST_WIDE_INT dom_cc;
+
+    operands[6] = gen_rtx_NE (SImode, operands[1], const0_rtx);
+
+    if (<CODE> == AND)
+      {
+        dom_cc = DOM_CC_X_AND_Y;
+        operands[5] = gen_rtx_fmt_ee (<CODE>, SImode,
+                                      operands[4], operands[6]);
+      }
+    else if (<CODE> == IOR)
+      {
+        dom_cc = DOM_CC_X_OR_Y;
+        operands[5] = gen_rtx_fmt_ee (<CODE>, SImode,
+                                      operands[4], operands[6]);
+      }
+    else
+      gcc_unreachable ();
+
+    operands[7]
+      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[4],
+                                                   operands[6],
+						   dom_cc),
+		     CC_REGNUM);
+  }"
+  [(set_attr "conds" "clob")
+   (set (attr "length")
+	(if_then_else (eq_attr "is_thumb" "yes")
+		      (const_int 10)
+		      (const_int 8)))]
+)
+
 (define_insn "*cond_arith"
   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
         (match_operator:SI 5 "shiftable_operator" 
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index 85dd641..f0a7c7e
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -173,6 +173,9 @@
 ;; A list of ...
 (define_code_iterator ior_xor [ior xor])
 
+;; A list of ...
+(define_code_iterator ior_and [ior and])
+
 ;; Operations on two halves of a quadword vector.
 (define_code_iterator vqh_ops [plus smin smax umin umax])
 
diff --git a/gcc/testsuite/gcc.target/arm/cond-and.c
b/gcc/testsuite/gcc.target/arm/cond-and.c
new file mode 100644
index 0000000..1320dcb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/cond-and.c
@@ -0,0 +1,27 @@
+/* Simplify code generation for conditional and.  */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "andne" } } */
+
+int f(char *t) {
+    int s=0;
+
+    while (*t && s != 1)
+      {
+        switch (s)
+          {
+          case 0:
+            s = 2;
+            break;
+          case 2:
+            s = 3;
+            break;
+          default:
+            if (*t == '-')
+                s = 2;
+            break;
+          }
+        t++;
+      }
+
+    return s;
+}




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]