diff options
author | Roger Sayle <roger@nextmovesoftware.com> | 2022-05-10 09:44:34 +0100 |
---|---|---|
committer | Roger Sayle <roger@nextmovesoftware.com> | 2022-05-10 09:44:34 +0100 |
commit | 5b7a9751f55bcdb7d9a69345e02f62aaa7035d6b (patch) | |
tree | d09f6d7423de293ca33821a440e5b0663f6b1406 /gcc | |
parent | dd3c7873a61019e993ee8b79e3695722b13cf945 (diff) | |
download | gcc-5b7a9751f55bcdb7d9a69345e02f62aaa7035d6b.zip gcc-5b7a9751f55bcdb7d9a69345e02f62aaa7035d6b.tar.gz gcc-5b7a9751f55bcdb7d9a69345e02f62aaa7035d6b.tar.bz2 |
Avoid andb %dil when optimizing for size.
The simple test case below has the unfortunate property that on x86_64,
it is larger when compiled with -Os than when compiled with -O2.
int foo(char x)
{
return (x & 123) != 0;
}
The issue is x86's complex instruction encoding, where andb $XX,%dil
requires more bytes than andl $XX,%edi. This patch adds logic to
i386.md's *testqi_1_maybe_si and *andqi_2_maybe_si define_insn patterns
to prefer the shorter SImode alternative when optimizing for size.
2022-05-10 Uroš Bizjak <ubizjak@gmail.com>
Roger Sayle <roger@nextmovesoftware.com>
gcc/ChangeLog
* config/i386/i386.md (*testqi_1_maybe_si): Prefer shorter SImode
alternative when optimizing for size and the immediate operand is
const_0_to_127_operand.
(*andqi_2_maybe_si): Likewise.
* config/i386/predicates.md (const_0_to_127_operand): New predicate.
gcc/testsuite/ChangeLog
* gcc.target/i386/and-1.c: New test case.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/i386/i386.md | 30 | ||||
-rw-r--r-- | gcc/config/i386/predicates.md | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/and-1.c | 9 |
3 files changed, 37 insertions, 7 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b321cda..f9c06ff 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -9502,14 +9502,14 @@ [(set (reg FLAGS_REG) (compare (and:QI - (match_operand:QI 0 "nonimmediate_operand" "%qm,*a,qm,r") - (match_operand:QI 1 "nonmemory_operand" "q,n,n,n")) + (match_operand:QI 0 "nonimmediate_operand" "%qm,qm,r") + (match_operand:QI 1 "nonmemory_operand" "q,n,n")) (const_int 0)))] "ix86_match_ccmode (insn, CONST_INT_P (operands[1]) && INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)" { - if (which_alternative == 3) + if (get_attr_mode (insn) == MODE_SI) { if (CONST_INT_P (operands[1]) && INTVAL (operands[1]) < 0) operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff); @@ -9518,8 +9518,16 @@ return "test{b}\t{%1, %0|%0, %1}"; } [(set_attr "type" "test") - (set_attr "mode" "QI,QI,QI,SI") - (set_attr "pent_pair" "uv,uv,np,np")]) + (set (attr "mode") + (cond [(eq_attr "alternative" "2") + (const_string "SI") + (and (match_test "optimize_insn_for_size_p ()") + (and (match_operand 0 "ext_QIreg_operand") + (match_operand 1 "const_0_to_127_operand"))) + (const_string "SI") + ] + (const_string "QI"))) + (set_attr "pent_pair" "uv,np,np")]) (define_insn "*test<mode>_1" [(set (reg FLAGS_REG) @@ -10110,7 +10118,7 @@ CONST_INT_P (operands[2]) && INTVAL (operands[2]) >= 0 ? CCNOmode : CCZmode)" { - if (which_alternative == 2) + if (get_attr_mode (insn) == MODE_SI) { if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff); @@ -10119,7 +10127,15 @@ return "and{b}\t{%2, %0|%0, %2}"; } [(set_attr "type" "alu") - (set_attr "mode" "QI,QI,SI") + (set (attr "mode") + (cond [(eq_attr "alternative" "2") + (const_string "SI") + (and (match_test "optimize_insn_for_size_p ()") + (and (match_operand 0 "ext_QIreg_operand") + (match_operand 2 "const_0_to_127_operand"))) + (const_string "SI") + ] + (const_string "QI"))) ;; Potential partial reg stall on alternative 2. (set (attr "preferred_for_speed") (cond [(eq_attr "alternative" "2") diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index a8cc17a..848a79a 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -906,6 +906,11 @@ (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), 0, 63)"))) +;; Match 0 to 127. +(define_predicate "const_0_to_127_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 0, 127)"))) + ;; Match 0 to 255. (define_predicate "const_0_to_255_operand" (and (match_code "const_int") diff --git a/gcc/testsuite/gcc.target/i386/and-1.c b/gcc/testsuite/gcc.target/i386/and-1.c new file mode 100644 index 0000000..11890d8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/and-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-Os" } */ + +int foo(char x) +{ + return (x & 123) != 0; +} + +/* { dg-final { scan-assembler-not "%dil" } } */ |