diff options
author | Uros Bizjak <ubizjak@gmail.com> | 2023-04-19 17:00:52 +0200 |
---|---|---|
committer | Uros Bizjak <ubizjak@gmail.com> | 2023-04-19 17:04:10 +0200 |
commit | 0df6d181230f0480547ed08b4e4354db68242724 (patch) | |
tree | 2c1206c133e3bed786b37652e28e4263ca42f6ff | |
parent | a30078d5d974c3b2c784c522a84fd12df74767dd (diff) | |
download | gcc-0df6d181230f0480547ed08b4e4354db68242724.zip gcc-0df6d181230f0480547ed08b4e4354db68242724.tar.gz gcc-0df6d181230f0480547ed08b4e4354db68242724.tar.bz2 |
i386: Emit compares between high registers and memory
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 opeerand 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.
-rw-r--r-- | gcc/config/i386/i386.md | 94 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr78952-3.c | 40 |
2 files changed, 124 insertions, 10 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 1419ea4..0f95d8e 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1005,6 +1005,9 @@ ;; 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 @@ [(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 @@ (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 @@ (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 @@ 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 0000000..ab00c55 --- /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" } } */ |