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;
> +}
> 
> 
> 




Reply via email to