Combine tries to combine AND RTX with memory operand:

Trying 12 -> 13:
   12: {r106:DI=r99:DI&[r100:DI*0x8+r103:DI];clobber flags:CC;}
      REG_UNUSED flags:CC
   13: flags:CCZ=cmp(r106:DI,0)
      REG_DEAD r106:DI

but fails to match instruction:

(set (reg:CCZ 17 flags)
    (compare:CCZ (and:DI (reg:DI 99 [ shifttmp_6 ])
            (mem:DI (plus:DI (mult:DI (reg/v:DI 100 [ i ])
                        (const_int 8 [0x8]))
                    (reg/v/f:DI 103 [ p ])) [1 MEM[(long unsigned int
*)p_8(D) + i_14 * 8]+0 S8 A64]))
        (const_int 0 [0])))

because corresponding *test<mode>_1 pattern doesn't allow memory operand 1.

Allow memory operand 1 by matching operand predicates of *test<mode>_1 family
of insns with corresponding *and<mode>_2 insn patterns.

The testcase improves from:

    movl    %esi, %ecx
    movl    $1, %eax
    salq    %cl, %rax
    movq    %rax, %rcx
    xorl    %eax, %eax
.L4:
    movq    %rcx, %rdx
    andq    (%rdi,%rax,8), %rdx
    jne    .L1
    ...

to:
    movl    $1, %edx
    movl    %esi, %ecx
    xorl    %eax, %eax
    salq    %cl, %rdx
.L4:
    testq    %rdx, (%rdi,%rax,8)
    jne    .L1
    ...

Also improve pentium pairing in *testqi_1_maybe_si insn pattern.

    PR target/122534

gcc/ChangeLog:

    * config/i386/i386.md (@test<mode>_ccno_1):
    Use <general_szext_operand> as operand 1 predicate.
    (testqi_ccz_1): Use general_operand as operand 1 predicate.
    (*testdi_1): Use x86_64_szext_general_operand as operand 1 predicate.
    (*testqi_1_maybe_si): Use general_operand as operand 1 predicate.
    Add (n,*a) alternative to allow UV pairing for pentium processor.
    (*test<mode>_1): Use <general_operand> as operand 1 predicate.

gcc/testsuite/ChangeLog:

    * gcc.target/i386/pr122534.c: New test.

Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.

Uros.
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 7ec028c8264..4a2232e4023 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -12213,7 +12213,7 @@ (define_expand "@test<mode>_ccno_1"
        (compare:CCNO
          (and:SWI48
            (match_operand:SWI48 0 "nonimmediate_operand")
-           (match_operand:SWI48 1 "<nonmemory_szext_operand>"))
+           (match_operand:SWI48 1 "<general_szext_operand>"))
          (const_int 0)))])
 
 (define_expand "testqi_ccz_1"
@@ -12221,7 +12221,7 @@ (define_expand "testqi_ccz_1"
        (compare:CCZ
          (and:QI
            (match_operand:QI 0 "nonimmediate_operand")
-           (match_operand:QI 1 "nonmemory_operand"))
+           (match_operand:QI 1 "general_operand"))
          (const_int 0)))])
 
 (define_insn "*testdi_1"
@@ -12229,7 +12229,7 @@ (define_insn "*testdi_1"
        (compare
          (and:DI
            (match_operand:DI 0 "nonimmediate_operand" "%r,rm")
-           (match_operand:DI 1 "x86_64_szext_nonmemory_operand" "Z,re"))
+           (match_operand:DI 1 "x86_64_szext_general_operand" "Z,re"))
         (const_int 0)))]
   "TARGET_64BIT
    && ix86_match_ccmode
@@ -12242,7 +12242,8 @@ (define_insn "*testdi_1"
         (satisfies_constraint_Z (operands[1])
          && (!CONST_INT_P (operands[1])
              || val_signbit_known_set_p (SImode, INTVAL (operands[1]))))
-        ? CCZmode : CCNOmode)"
+        ? CCZmode : CCNOmode)
+   && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
   "@
    test{l}\t{%k1, %k0|%k0, %k1}
    test{q}\t{%1, %0|%0, %1}"
@@ -12253,12 +12254,13 @@ (define_insn "*testqi_1_maybe_si"
   [(set (reg FLAGS_REG)
        (compare
          (and:QI
-           (match_operand:QI 0 "nonimmediate_operand" "%qm,qm,r")
-           (match_operand:QI 1 "nonmemory_operand" "q,n,n"))
+           (match_operand:QI 0 "nonimmediate_operand" "%qm,*a,qm,r")
+           (match_operand:QI 1 "general_operand" "q,n,n,n"))
          (const_int 0)))]
   "ix86_match_ccmode (insn,
                      CONST_INT_P (operands[1])
-                     && INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)"
+                     && INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)
+   && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
 {
   if (get_attr_mode (insn) == MODE_SI)
     {
@@ -12270,7 +12272,7 @@ (define_insn "*testqi_1_maybe_si"
 }
   [(set_attr "type" "test")
    (set (attr "mode")
-     (cond [(eq_attr "alternative" "2")
+     (cond [(eq_attr "alternative" "3")
              (const_string "SI")
            (and (match_test "optimize_insn_for_size_p ()")
                 (and (match_operand 0 "ext_QIreg_operand")
@@ -12278,16 +12280,17 @@ (define_insn "*testqi_1_maybe_si"
              (const_string "SI")
           ]
           (const_string "QI")))
-   (set_attr "pent_pair" "uv,np,np")])
+   (set_attr "pent_pair" "uv,uv,np,np")])
 
 (define_insn "*test<mode>_1"
   [(set (reg FLAGS_REG)
        (compare
          (and:SWI124
            (match_operand:SWI124 0 "nonimmediate_operand" "%<r>m,*a,<r>m")
-           (match_operand:SWI124 1 "<nonmemory_szext_operand>" "<r>,<i>,<i>"))
-        (const_int 0)))]
-  "ix86_match_ccmode (insn, CCNOmode)"
+           (match_operand:SWI124 1 "<general_operand>" "<r>,<i>,<i>"))
+         (const_int 0)))]
+  "ix86_match_ccmode (insn, CCNOmode)
+   && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
   "test{<imodesuffix>}\t{%1, %0|%0, %1}"
   [(set_attr "type" "test")
    (set_attr "mode" "<MODE>")
diff --git a/gcc/testsuite/gcc.target/i386/pr122534.c 
b/gcc/testsuite/gcc.target/i386/pr122534.c
new file mode 100644
index 00000000000..b1988fb7286
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr122534.c
@@ -0,0 +1,15 @@
+/* PR target/122534 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int test (unsigned long p[6], int index)
+{
+  __SIZE_TYPE__ i;
+
+  for (i = 0; i < 6; i++)
+    if (p[i] & (1UL << index))
+      return i;
+  return 0;
+}
+
+/* { dg-final { scan-assembler-not "and" } } */

Reply via email to