A right shift of 31 will become 0 or 1, this can be checked for treg_set_expr_not_const01 to avoid matching addc_t_r as this can expand to a 3 insn sequence instead. This improves tests 023 to 026 from gcc.target/sh/pr54236-2.c, e.g.: test_023: shll r5 mov #0,r1 mov r4,r0 rts addc r1,r0
With this change: test_023: shll r5 movt r0 rts add r4,r0 We noticed this while evaluating a patch to improve how we handle selecting between two constants based on the output of a LT/GE 0 test. gcc/ChangeLog: * config/sh/predicates.md (treg_set_expr_not_const01): call sh_recog_treg_set_expr_not_01 * config/sh/sh-protos.h (sh_recog_treg_set_expr_not_01): New function config/sh/sh.cc (sh_recog_treg_set_expr_not_01): Likewise gcc/testsuite/ChangeLog: * gcc.target/sh/pr54236-2.c: Fix comments and expected output --- gcc/config/sh/predicates.md | 4 +--- gcc/config/sh/sh-protos.h | 1 + gcc/config/sh/sh.cc | 17 +++++++++++++++++ gcc/testsuite/gcc.target/sh/pr54236-2.c | 14 +++++++------- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md index 7349c97a2b5..e67ec8a2320 100644 --- a/gcc/config/sh/predicates.md +++ b/gcc/config/sh/predicates.md @@ -630,9 +630,7 @@ ;; Same as treg_set_expr but disallow constants 0 and 1 which can be loaded ;; into the T bit. (define_predicate "treg_set_expr_not_const01" - (and (match_test "op != const0_rtx") - (match_test "op != const1_rtx") - (match_operand 0 "treg_set_expr"))) + (match_test "sh_recog_treg_set_expr_not_01 (op, mode)")) ;; A predicate describing the T bit register in any form. (define_predicate "t_reg_operand" diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index c8cc19f4dc7..e78b6697a2b 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -261,6 +261,7 @@ extern rtx_insn* sh_peephole_emit_move_insn (rtx dst, rtx src); extern bool sh_in_recog_treg_set_expr (void); extern bool sh_recog_treg_set_expr (rtx op, machine_mode mode); +extern bool sh_recog_treg_set_expr_not_01 (rtx op, machine_mode mode); /* Result value of sh_split_treg_set_expr. Contains the first insn emitted and the optional trailing nott insn. */ diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc index 1bc34e0a3e3..09e4ff77c20 100644 --- a/gcc/config/sh/sh.cc +++ b/gcc/config/sh/sh.cc @@ -12348,6 +12348,23 @@ sh_recog_treg_set_expr (rtx op, machine_mode mode) return result >= 0; } +/* Return TRUE if OP is an expression for which there is a pattern to + set the T bit unless the expression is trivially loadable into + the T bit, FALSE otherwise. */ +bool +sh_recog_treg_set_expr_not_01 (rtx op, machine_mode mode) +{ + if (op == const0_rtx || op == const1_rtx) + return false; + + /* A right shift of 31 will return 0 or 1. */ + if ((GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ASHIFTRT) + && INTVAL (XEXP (op, 1)) == 31) + return false; + + return sh_recog_treg_set_expr (op, mode); +} + /* Returns true when recog of a 'treg_set_expr' is currently in progress. This can be used as a condition for insn/split patterns to allow certain T bit setting patters only to be matched as sub expressions of other diff --git a/gcc/testsuite/gcc.target/sh/pr54236-2.c b/gcc/testsuite/gcc.target/sh/pr54236-2.c index 1e2f3bbcb56..78befe43770 100644 --- a/gcc/testsuite/gcc.target/sh/pr54236-2.c +++ b/gcc/testsuite/gcc.target/sh/pr54236-2.c @@ -4,10 +4,10 @@ /* { dg-do compile } */ /* { dg-options "-O1" } */ -/* { dg-final { scan-assembler-times "addc" 36 } } */ +/* { dg-final { scan-assembler-times "addc" 32 } } */ /* { dg-final { scan-assembler-times "shll" 14 } } */ -/* { dg-final { scan-assembler-times "add\tr" 12 } } */ -/* { dg-final { scan-assembler-not "movt" } } */ +/* { dg-final { scan-assembler-times "add\tr" 16 } } */ +/* { dg-final { scan-assembler-times "movt" 4 } } */ /* { dg-final { scan-assembler-times "add\t#1" 1 } } */ @@ -184,28 +184,28 @@ test_022 (int a, int b, int c, int d) int test_023 (int a, int b, int c, int d) { - // 1x shll, 1x addc + // 1x shll, 1x add return a + ((b >> 31) & 1); } int test_024 (int a, int b, int c, int d) { - // 1x shll, 1x addc + // 1x shll, 1x add return ((b >> 31) & 1) + a; } int test_025 (int a, int b, int c, int d) { - // 1x shll, 1x addc + // 1x shll, 1x add return ((a >> 31) & 1) + a; } int test_026 (int a, int b, int c, int d) { - // 1x shll, 1x addc + // 1x shll, 1x add return a + ((a >> 31) & 1); } -- 2.47.0