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

2011-11-22 Thread Jiangning Liu


 -Original Message-
 From: Andrew Pinski [mailto:pins...@gmail.com]
 Sent: Tuesday, November 22, 2011 1:14 PM
 To: Jiangning Liu
 Cc: gcc-patches@gcc.gnu.org; Richard Guenther; Richard Henderson
 Subject: Re: [RFC] Optimization to conditional and/or in ARM back-end
 
 On Sun, Nov 20, 2011 at 6:17 PM, Jiangning Liu jiangning@arm.com
 wrote:
  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,
 
 So this is the same as:
 int f1(int r1, int r3)
 {
   if (((r3 != 0)  r1) != 0)
 return g();
   return 1;
 }
 --- CUT ---
 Can't you do this instead:
 Combine the following two instructions:
 (insn 17 15 18 2 (parallel [
 (set (reg:SI 150)
 (and:SI (ne:SI (reg:SI 0 r0 [ r1 ])
 (const_int 0 [0]))
 (reg:SI 1 r1 [ r3 ])))
 (clobber (reg:CC 24 cc))
 ]) t24.c:11 274 {*cond_arith}
  (expr_list:REG_UNUSED (reg:CC 24 cc)
 (expr_list:REG_DEAD (reg:SI 1 r1 [ r3 ])
 (expr_list:REG_DEAD (reg:SI 0 r0 [ r1 ])
 (nil)
 
 (insn 18 17 19 2 (set (reg:CC 24 cc)
 (compare:CC (reg:SI 150)
 (const_int 0 [0]))) t24.c:11 211 {*arm_cmpsi_insn}
  (expr_list:REG_DEAD (reg:SI 150)
 (nil)))
 
 And then have a pattern which expands it to (note the r3 here is the
 r3 in the function, likewise for r1):
 andi r1, r1, #1
 cmp r3, #0
 it  ne
 cmpne   r1, #0
 
 Yes it is one extra instruction but it is still better than before
 right?

Hi Andrew,

Yes, and even the code generated can be like

cmp r3, #0
itt ne
andine  r1, r1, #1
cmpne   r1, #0

But this is not what I want. For performance purpose, I want to remove that 
andi instruction as well.

Also, actually if we don't modify r1, there might be other more optimization 
opportunities, for example register pressure can be reduced for some cases, I 
guess.

Thanks,
-Jiangning





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

2011-11-21 Thread Andrew Pinski
On Sun, Nov 20, 2011 at 6:17 PM, Jiangning Liu jiangning@arm.com wrote:
 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,

So this is the same as:
int f1(int r1, int r3)
{
  if (((r3 != 0)  r1) != 0)
return g();
  return 1;
}
--- CUT ---
Can't you do this instead:
Combine the following two instructions:
(insn 17 15 18 2 (parallel [
(set (reg:SI 150)
(and:SI (ne:SI (reg:SI 0 r0 [ r1 ])
(const_int 0 [0]))
(reg:SI 1 r1 [ r3 ])))
(clobber (reg:CC 24 cc))
]) t24.c:11 274 {*cond_arith}
 (expr_list:REG_UNUSED (reg:CC 24 cc)
(expr_list:REG_DEAD (reg:SI 1 r1 [ r3 ])
(expr_list:REG_DEAD (reg:SI 0 r0 [ r1 ])
(nil)

(insn 18 17 19 2 (set (reg:CC 24 cc)
(compare:CC (reg:SI 150)
(const_int 0 [0]))) t24.c:11 211 {*arm_cmpsi_insn}
 (expr_list:REG_DEAD (reg:SI 150)
(nil)))

And then have a pattern which expands it to (note the r3 here is the
r3 in the function, likewise for r1):
andi r1, r1, #1
cmp r3, #0
it  ne
cmpne   r1, #0

Yes it is one extra instruction but it is still better than before right?


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

2011-11-20 Thread Jiangning Liu
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