From 584f50a6e405f057ab41fb5416aea5820f15c9cd Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Mon, 3 Nov 2025 20:22:10 +0100 Subject: [PATCH] i386: Allow memory op in operand 1 predicate of *test_1 insn patterns [PR122534] 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_1 pattern doesn't allow memory operand 1. Allow memory operand 1 by matching operand predicates of *test_1 family of insns with corresponding *and_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_ccno_1): Use 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_1): Use as operand 1 predicate. gcc/testsuite/ChangeLog: * gcc.target/i386/pr122534.c: New test. --- gcc/config/i386/i386.md | 27 +++++++++++++----------- gcc/testsuite/gcc.target/i386/pr122534.c | 15 +++++++++++++ 2 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr122534.c 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 @@ (compare:CCNO (and:SWI48 (match_operand:SWI48 0 "nonimmediate_operand") - (match_operand:SWI48 1 "")) + (match_operand:SWI48 1 "")) (const_int 0)))]) (define_expand "testqi_ccz_1" @@ -12221,7 +12221,7 @@ (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 @@ (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 @@ (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 @@ [(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 @@ } [(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 @@ (const_string "SI") ] (const_string "QI"))) - (set_attr "pent_pair" "uv,np,np")]) + (set_attr "pent_pair" "uv,uv,np,np")]) (define_insn "*test_1" [(set (reg FLAGS_REG) (compare (and:SWI124 (match_operand:SWI124 0 "nonimmediate_operand" "%m,*a,m") - (match_operand:SWI124 1 "" ",,")) - (const_int 0)))] - "ix86_match_ccmode (insn, CCNOmode)" + (match_operand:SWI124 1 "" ",,")) + (const_int 0)))] + "ix86_match_ccmode (insn, CCNOmode) + && !(MEM_P (operands[0]) && MEM_P (operands[1]))" "test{}\t{%1, %0|%0, %1}" [(set_attr "type" "test") (set_attr "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" } } */ -- 2.47.3