aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUros Bizjak <ubizjak@gmail.com>2023-04-19 17:00:52 +0200
committerUros Bizjak <ubizjak@gmail.com>2023-04-19 17:04:10 +0200
commit0df6d181230f0480547ed08b4e4354db68242724 (patch)
tree2c1206c133e3bed786b37652e28e4263ca42f6ff
parenta30078d5d974c3b2c784c522a84fd12df74767dd (diff)
downloadgcc-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.md94
-rw-r--r--gcc/testsuite/gcc.target/i386/pr78952-3.c40
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" } } */