The original subject doesn't catch the key point, so I changed the subject to get more people noticed.
My question is essentially is "May I really use REG_EXPR in back-end code?" like the patch I gave below? Thanks, -Jiangning > -----Original Message----- > From: gcc-patches-ow...@gcc.gnu.org [mailto:gcc-patches- > ow...@gcc.gnu.org] On Behalf Of Jiangning Liu > Sent: Monday, November 21, 2011 10:18 AM > To: gcc-patches@gcc.gnu.org > Cc: 'Richard Guenther'; Richard Henderson > Subject: [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; > +} > > >