Hi, This fixes PR 67126 by updating the patterns to match new combine behavior. Tested on sh-elf with make -k check RUNTESTFLAGS="--target_board=sh-sim \{-m2/-ml,-m2/-mb,-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}" and no new failures. Committed as r227957.
Cheers, Oleg gcc/ChangeLog: PR target/67126 * config/sh/sh.md (*reg_lsb_t): Emit bld insn on SH2A. (*mov_t_msb_neg): Rewrite negc pattern. gcc/testsuite/ChangeLog: PR target/67126 * gcc.target/sh/pr51244-12.c: Adjust testcase. * gcc.target/sh/pr54236-2.c: Likewise.
Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 227931) +++ gcc/config/sh/sh.md (working copy) @@ -4204,7 +4204,7 @@ ;; Let combine see that we can get the MSB and LSB into the T bit ;; via shll and shlr. This allows it to plug it into insns that can have ;; the T bit as an input (e.g. addc). -;; FIXME: On SH2A use bld #0,Rn instead of shlr to avoid mutating the input. +;; On SH2A use bld #0,Rn instead of shlr to avoid mutating the input. (define_insn_and_split "*reg_lsb_t" [(set (reg:SI T_REG) (and:SI (match_operand:SI 0 "arith_reg_operand") @@ -4214,7 +4214,8 @@ "&& 1" [(const_int 0)] { - emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[0])); + emit_insn (TARGET_SH2A ? gen_bldsi_reg (operands[0], const0_rtx) + : gen_shlr (gen_reg_rtx (SImode), operands[0])); }) (define_insn_and_split "*reg_msb_t" @@ -11979,41 +11980,31 @@ [(set (match_dup 0) (reg:SI T_REG)) (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))]) -;; Use negc to store the T bit in a MSB of a reg in the following way: -;; T = 0: 0x80000000 -> reg -;; T = 1: 0x7FFFFFFF -> reg -;; This works because 0 - 0x80000000 = 0x80000000. +;; 0x7fffffff + T +;; 0x7fffffff + (1-T) = 0 - 0x80000000 - T +;; +;; Notice that 0 - 0x80000000 = 0x80000000. + +;; Single bit tests are usually done with zero_extract. On non-SH2A this +;; will use a tst-negc sequence. On SH2A it will use a bld-addc sequence. +;; The zeroth bit requires a special pattern, otherwise we get a shlr-addc. +;; This is a special case of the generic treg_set_expr pattern and thus has +;; to come first or it will never match. (define_insn_and_split "*mov_t_msb_neg" [(set (match_operand:SI 0 "arith_reg_dest") - (minus:SI (const_int -2147483648) ;; 0x80000000 - (match_operand 1 "treg_set_expr"))) + (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 1)) + (const_int 2147483647))) (clobber (reg:SI T_REG))] - "TARGET_SH1 && can_create_pseudo_p ()" + "TARGET_SH1" "#" - "&& 1" - [(const_int 0)] -{ - if (negt_reg_operand (operands[1], VOIDmode)) - { - emit_insn (gen_addc (operands[0], - force_reg (SImode, const0_rtx), - force_reg (SImode, GEN_INT (2147483647)))); - DONE; - } + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) + (plus:SI (zero_extract:SI (match_dup 1) + (const_int 1) (const_int 0)) + (const_int 2147483647))) + (clobber (reg:SI T_REG))])]) - sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn); - if (ti.remove_trailing_nott ()) - emit_insn (gen_addc (operands[0], - force_reg (SImode, const0_rtx), - force_reg (SImode, GEN_INT (2147483647)))); - else - emit_insn (gen_negc (operands[0], - force_reg (SImode, GEN_INT (-2147483648LL)))); - DONE; -}) - -;; 0x7fffffff + T -;; 0x7fffffff + (1-T) = 0 - 0x80000000 - T (define_insn_and_split "*mov_t_msb_neg" [(set (match_operand:SI 0 "arith_reg_dest") (plus:SI (match_operand 1 "treg_set_expr") Index: gcc/testsuite/gcc.target/sh/pr51244-12.c =================================================================== --- gcc/testsuite/gcc.target/sh/pr51244-12.c (revision 227931) +++ gcc/testsuite/gcc.target/sh/pr51244-12.c (working copy) @@ -4,8 +4,14 @@ /* { dg-do compile } */ /* { dg-options "-O1" } */ /* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */ -/* { dg-final { scan-assembler-times "negc" 15 } } */ -/* { dg-final { scan-assembler-times "addc" 3 } } */ + +/* { dg-final { scan-assembler-times "negc" 15 { target { ! sh2a } } } } */ +/* { dg-final { scan-assembler-times "addc" 3 { target { ! sh2a } } } } */ + +/* { dg-final { scan-assembler-times "negc" 13 { target { sh2a } } } } */ +/* { dg-final { scan-assembler-times "addc" 5 { target { sh2a } } } } */ +/* { dg-final { scan-assembler-times "bld" 2 { target { sh2a } } } } */ + /* { dg-final { scan-assembler-not "movrt|#-1|add\t|sub\t|movt" } } */ int Index: gcc/testsuite/gcc.target/sh/pr54236-2.c =================================================================== --- gcc/testsuite/gcc.target/sh/pr54236-2.c (revision 227931) +++ gcc/testsuite/gcc.target/sh/pr54236-2.c (working copy) @@ -5,7 +5,6 @@ /* { dg-options "-O1" } */ /* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ /* { dg-final { scan-assembler-times "addc" 36 } } */ -/* { dg-final { scan-assembler-times "shlr" 22 } } */ /* { dg-final { scan-assembler-times "shll" 14 } } */ /* { dg-final { scan-assembler-times "add\tr" 12 } } */ /* { dg-final { scan-assembler-not "movt" } } */ @@ -17,10 +16,13 @@ /* { dg-final { scan-assembler-times "bclr\t#0" 1 { target { sh2a } } } } */ +/* { dg-final { scan-assembler-times "shlr" 22 { target { ! sh2a } } } } */ +/* { dg-final { scan-assembler-not "shlr" { target { sh2a } } } } */ + int test_000 (int a, int c, int b, int d) { - // 1x shlr, 1x addc + // 1x shlr/bld, 1x addc return a + (b & 1); } @@ -27,7 +29,7 @@ int test_001 (int a, int c, int b, int d) { - // 1x shlr, 1x addc + // 1x shlr/bld, 1x addc return a + b + (c & 1); } @@ -34,7 +36,7 @@ int test_002 (int a, int c, int b, int d) { - // 1x shlr, 1x add, 1x addc + // 1x shlr/bld, 1x add, 1x addc return a + b + c + (d & 1); } @@ -41,7 +43,7 @@ int test_003 (int a, int c, int b, int d) { - // 1x shlr, 1x addc + // 1x shlr/bld, 1x addc return (b & 1) + a; } @@ -48,7 +50,7 @@ int test_004 (int a, int c, int b, int d) { - // 1x shlr, 1x addc + // 1x shlr/bld, 1x addc return a + (c & 1) + b; } @@ -55,7 +57,7 @@ int test_005 (int a, int c, int b, int d) { - // 1x shlr, 1x add, 1x addc + // 1x shlr/bld, 1x add, 1x addc return a + b + (d & 1) + c; } @@ -62,7 +64,7 @@ int test_006 (int a, int c, int b, int d) { - // 1x shlr, 1x addc + // 1x shlr/bld, 1x addc return (c & 1) + a + b; } @@ -69,7 +71,7 @@ int test_007 (int a, int c, int b, int d) { - // 1x shlr, 1x add, 1x addc + // 1x shlr/bld, 1x add, 1x addc return a + (d & 1) + b + c; } @@ -76,7 +78,7 @@ int test_008 (int a, int c, int b, int d) { - // 1x shlr, 1x add, 1x addc + // 1x shlr/bld, 1x add, 1x addc return (d & 1) + a + b + c; } @@ -83,7 +85,7 @@ int test_009 (int a, int c, int b, int d) { - // 1x shlr, 1x addc + // 1x shlr/bld, 1x addc return a + b + (b & 1); } @@ -90,7 +92,7 @@ int test_010 (int a, int c, int b, int d) { - // 1x shlr, 1x addc + // 1x shlr/bld, 1x addc return a + (b & 1) + b; } @@ -97,7 +99,7 @@ int test_011 (int a, int c, int b, int d) { - // 1x shlr, 1x addc + // 1x shlr/bld, 1x addc return (b & 1) + a + b; } @@ -104,7 +106,7 @@ int test_012 (int a, int c, int b, int d) { - // 1x shlr, 1x add, 1x addc + // 1x shlr/bld, 1x add, 1x addc return a + b + d + (b & 1); } @@ -111,7 +113,7 @@ int test_013 (int a, int c, int b, int d) { - // 1x shlr, 1x add, 1x addc + // 1x shlr/bld, 1x add, 1x addc return a + d + (b & 1) + b; } @@ -118,7 +120,7 @@ int test_014 (int a, int c, int b, int d) { - // 1x shlr, 1x add, 1x addc + // 1x shlr/bld, 1x add, 1x addc return a + (b & 1) + d + b; } @@ -125,7 +127,7 @@ int test_015 (int a, int c, int b, int d) { - // 1x shlr, 1x add, 1x addc + // 1x shlr/bld, 1x add, 1x addc return (b & 1) + a + d + b; } @@ -140,7 +142,7 @@ int test_017 (int a, int b, int c, int d) { - // 1x shlr, 1x addc + // 1x shlr/bld, 1x addc return a + a + (a & 1); } @@ -147,7 +149,7 @@ int test_018 (int a, int b, int c, int d) { - // 1x shlr, 1x addc + // 1x shlr/bld, 1x addc return a + (a & 1) + a; } @@ -154,7 +156,7 @@ int test_019 (int a, int b, int c, int d) { - // 1x shlr, 1x addc + // 1x shlr/bld, 1x addc return (a & 1) + a + a; } @@ -161,7 +163,7 @@ int test_020 (int a, int b, int c, int d) { - // 1x shlr, 1x addc + // 1x shlr/bld, 1x addc return b + b + (a & 1); } @@ -168,7 +170,7 @@ int test_021 (int a, int b, int c, int d) { - // 1x shlr, 1x addc + // 1x shlr/bld, 1x addc return b + (a & 1) + b; } @@ -175,7 +177,7 @@ int test_022 (int a, int b, int c, int d) { - // 1x shlr, 1x addc + // 1x shlr/bld, 1x addc return (a & 1) + b + b; }