From: Roger Sayle Date: Tue, 10 May 2022 08:44:34 +0000 (+0100) Subject: Avoid andb %dil when optimizing for size. X-Git-Tag: basepoints/gcc-14~6952 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5b7a9751f55bcdb7d9a69345e02f62aaa7035d6b;p=thirdparty%2Fgcc.git 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 Roger Sayle 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. --- diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b321cda1f22..f9c06ff302a 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_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 a8cc17a054d..848a79a8d16 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 00000000000..11890d8fba3 --- /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" } } */