Following code: typedef __SIZE_TYPE__ size_t;
struct S1s { char pad1; char val; short pad2; }; extern char ts[256]; _Bool foo (struct S1s a, size_t i) { return (ts[i] > a.val); } compiles with -O2 to: movl %edi, %eax movsbl %ah, %edi cmpb %dil, ts(%rsi) setg %al ret the compare could use high register %ah instead of %dil: movl %edi, %eax cmpb ts(%rsi), %ah setl %al ret Use any_extract code iterator to handle signed and unsigned extracts from high register and introduce peephole2 patterns to propagate norex memory operand into the compare insn. gcc/ChangeLog: PR target/78904 PR target/78952 * config/i386/i386.md (*cmpqi_ext<mode>_1_mem_rex64): New insn pattern. (*cmpqi_ext<mode>_1): Use nonimmediate_operand predicate for operand 0. Use any_extract code iterator. (*cmpqi_ext<mode>_1 peephole2): New peephole2 pattern. (*cmpqi_ext<mode>_2): Use any_extract code iterator. (*cmpqi_ext<mode>_3_mem_rex64): New insn pattern. (*cmpqi_ext<mode>_1): Use general_operand predicate for operand 1. Use any_extract code iterator. (*cmpqi_ext<mode>_3 peephole2): New peephole2 pattern. (*cmpqi_ext<mode>_4): Use any_extract code iterator. gcc/testsuite/ChangeLog: PR target/78904 PR target/78952 * gcc.target/i386/pr78952-3.c: New test. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Pushed to master. Uros.
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 1419ea4cff3..0f95d8e8918 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1005,6 +1005,9 @@ (define_code_attr absneg_mnemonic [(abs "fabs") (neg "fchs")]) ;; Mapping of extend operators (define_code_iterator any_extend [sign_extend zero_extend]) +;; Mapping of extract operators +(define_code_iterator any_extract [sign_extract zero_extract]) + ;; Mapping of highpart multiply operators (define_code_iterator any_mul_highpart [smul_highpart umul_highpart]) @@ -1454,12 +1457,27 @@ (define_insn "*cmp<mode>_minus_1" [(set_attr "type" "icmp") (set_attr "mode" "<MODE>")]) +(define_insn "*cmpqi_ext<mode>_1_mem_rex64" + [(set (reg FLAGS_REG) + (compare + (match_operand:QI 0 "norex_memory_operand" "Bn") + (subreg:QI + (any_extract:SWI248 + (match_operand 1 "int248_register_operand" "Q") + (const_int 8) + (const_int 8)) 0)))] + "TARGET_64BIT && reload_completed + && ix86_match_ccmode (insn, CCmode)" + "cmp{b}\t{%h1, %0|%0, %h1}" + [(set_attr "type" "icmp") + (set_attr "mode" "QI")]) + (define_insn "*cmpqi_ext<mode>_1" [(set (reg FLAGS_REG) (compare - (match_operand:QI 0 "nonimm_x64constmem_operand" "QBc,m") + (match_operand:QI 0 "nonimmediate_operand" "QBc,m") (subreg:QI - (zero_extract:SWI248 + (any_extract:SWI248 (match_operand 1 "int248_register_operand" "Q,Q") (const_int 8) (const_int 8)) 0)))] @@ -1469,11 +1487,33 @@ (define_insn "*cmpqi_ext<mode>_1" (set_attr "type" "icmp") (set_attr "mode" "QI")]) +(define_peephole2 + [(set (match_operand:QI 0 "register_operand") + (match_operand:QI 1 "norex_memory_operand")) + (set (match_operand 3 "flags_reg_operand") + (match_operator 4 "compare_operator" + [(match_dup 0) + (subreg:QI + (any_extract:SWI248 + (match_operand 2 "int248_register_operand") + (const_int 8) + (const_int 8)) 0)]))] + "TARGET_64BIT + && peep2_reg_dead_p (2, operands[0])" + [(set (match_dup 3) + (match_op_dup 4 + [(match_dup 1) + (subreg:QI + (any_extract:SWI248 + (match_dup 2) + (const_int 8) + (const_int 8)) 0)]))]) + (define_insn "*cmpqi_ext<mode>_2" [(set (reg FLAGS_REG) (compare (subreg:QI - (zero_extract:SWI248 + (any_extract:SWI248 (match_operand 0 "int248_register_operand" "Q") (const_int 8) (const_int 8)) 0) @@ -1494,31 +1534,68 @@ (define_expand "cmpqi_ext_3" (const_int 8)) 0) (match_operand:QI 1 "const_int_operand")))]) +(define_insn "*cmpqi_ext<mode>_3_mem_rex64" + [(set (reg FLAGS_REG) + (compare + (subreg:QI + (any_extract:SWI248 + (match_operand 0 "int248_register_operand" "Q") + (const_int 8) + (const_int 8)) 0) + (match_operand:QI 1 "norex_memory_operand" "Bn")))] + "TARGET_64BIT && reload_completed + && ix86_match_ccmode (insn, CCmode)" + "cmp{b}\t{%1, %h0|%h0, %1}" + [(set_attr "type" "icmp") + (set_attr "mode" "QI")]) + (define_insn "*cmpqi_ext<mode>_3" [(set (reg FLAGS_REG) (compare (subreg:QI - (zero_extract:SWI248 + (any_extract:SWI248 (match_operand 0 "int248_register_operand" "Q,Q") (const_int 8) (const_int 8)) 0) - (match_operand:QI 1 "general_x64constmem_operand" "QnBc,m")))] + (match_operand:QI 1 "general_operand" "QnBc,m")))] "ix86_match_ccmode (insn, CCmode)" "cmp{b}\t{%1, %h0|%h0, %1}" [(set_attr "isa" "*,nox64") (set_attr "type" "icmp") (set_attr "mode" "QI")]) +(define_peephole2 + [(set (match_operand:QI 0 "register_operand") + (match_operand:QI 1 "norex_memory_operand")) + (set (match_operand 3 "flags_reg_operand") + (match_operator 4 "compare_operator" + [(subreg:QI + (any_extract:SWI248 + (match_operand 2 "int248_register_operand") + (const_int 8) + (const_int 8)) 0) + (match_dup 0)]))] + "TARGET_64BIT + && peep2_reg_dead_p (2, operands[0])" + [(set (match_dup 3) + (match_op_dup 4 + [(subreg:QI + (any_extract:SWI248 + (match_dup 2) + (const_int 8) + (const_int 8)) 0) + (match_dup 1)]))]) + (define_insn "*cmpqi_ext<mode>_4" [(set (reg FLAGS_REG) (compare (subreg:QI - (zero_extract:SWI248 + (any_extract:SWI248 (match_operand 0 "int248_register_operand" "Q") (const_int 8) (const_int 8)) 0) (subreg:QI - (zero_extract:SWI248 + (any_extract:SWI248 (match_operand 1 "int248_register_operand" "Q") (const_int 8) (const_int 8)) 0)))] @@ -3374,9 +3451,6 @@ (define_peephole2 operands[4] = gen_int_mode (tmp, <SWI48:MODE>mode); }) - -(define_code_iterator any_extract [sign_extract zero_extract]) - (define_insn "*insvqi_2" [(set (zero_extract:SWI248 (match_operand 0 "int248_register_operand" "+Q") diff --git a/gcc/testsuite/gcc.target/i386/pr78952-3.c b/gcc/testsuite/gcc.target/i386/pr78952-3.c new file mode 100644 index 00000000000..ab00c55b370 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr78952-3.c @@ -0,0 +1,40 @@ +/* PR target/78952 */ +/* { dg-do compile } */ +/* { dg-require-effective-target nonpic } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-additional-options "-mregparm=1" { target ia32 } } */ +/* { dg-final { scan-assembler-not "mov\[sz]bl" } } */ + +typedef __SIZE_TYPE__ size_t; + +struct S1s +{ + char pad1; + char val; + short pad2; +}; + +extern char ts[256]; + +_Bool foo (struct S1s a, size_t i) +{ + return (ts[i] > a.val); +} + +/* { dg-final { scan-assembler "cmpb\[ \\t]+ts\[^\n]*%.h" } } */ + +struct S1u +{ + unsigned char pad1; + unsigned char val; + unsigned short pad2; +}; + +extern unsigned char tu[256]; + +_Bool bar (struct S1u a, size_t i) +{ + return (tu[i] > a.val); +} + +/* { dg-final { scan-assembler "cmpb\[ \\t]+tu\[^\n]*%.h" } } */