After the valuable feedback I received, it’s clear to me that the oversight was in the tests showing the benefits of the patch. In the test file, I added functions f5 and f6, which now generate more efficient code with fewer instructions.
Before the patch: f5: li a4,2097152 addi a4,a4,-2048 li a5,1167360 and a0,a0,a4 addi a5,a5,-2048 beq a0,a5,.L4 f6: li a5,3407872 addi a5,a5,-2048 and a0,a0,a5 li a5,1114112 beq a0,a5,.L7 After the patch: f5: srli a5,a0,11 andi a5,a5,1023 li a4,569 beq a5,a4,.L5 f6: srli a5,a0,11 andi a5,a5,1663 li a4,544 beq a5,a4,.L9 2024-10-09 Jovan Vukic <jovan.vu...@rt-rk.com> PR target/115921 gcc/ChangeLog: * config/riscv/iterators.md (any_eq): New code iterator. * config/riscv/riscv.h (COMMON_TRAILING_ZEROS): New macro. (SMALL_AFTER_COMMON_TRAILING_SHIFT): Ditto. * config/riscv/riscv.md (*branch<ANYI:mode>_shiftedarith_<optab>_shifted): New pattern. gcc/testsuite/ChangeLog: * gcc.target/riscv/branch-1.c: Additional tests. CONFIDENTIALITY: The contents of this e-mail are confidential and intended only for the above addressee(s). If you are not the intended recipient, or the person responsible for delivering it to the intended recipient, copying or delivering it to anyone else or using it in any unauthorized manner is prohibited and may be unlawful. If you receive this e-mail by mistake, please notify the sender and the systems administrator at straym...@rt-rk.com immediately.
--- gcc/config/riscv/iterators.md | 4 +++ gcc/config/riscv/riscv.h | 12 +++++++++ gcc/config/riscv/riscv.md | 32 +++++++++++++++++++++++ gcc/testsuite/gcc.target/riscv/branch-1.c | 18 ++++++++++--- 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md index 872c542e906..081659499a9 100644 --- a/gcc/config/riscv/iterators.md +++ b/gcc/config/riscv/iterators.md @@ -233,6 +233,8 @@ (define_code_iterator any_ge [ge geu]) (define_code_iterator any_lt [lt ltu]) (define_code_iterator any_le [le leu]) +(define_code_iterator any_eq [eq ne]) + ;; Iterators for conditions we can emit a sCC against 0 or a reg directly (define_code_iterator scc_0 [eq ne gt gtu]) @@ -285,6 +287,8 @@ (le "le") (gt "gt") (lt "lt") + (eq "eq") + (ne "ne") (ior "ior") (xor "xor") (and "and") diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 53b7b2a40ed..ca1b8329cdc 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -667,6 +667,18 @@ enum reg_class /* True if bit BIT is set in VALUE. */ #define BITSET_P(VALUE, BIT) (((VALUE) & (1ULL << (BIT))) != 0) +/* Returns the smaller (common) number of trailing zeros for VAL1 and VAL2. */ +#define COMMON_TRAILING_ZEROS(VAL1, VAL2) \ + (ctz_hwi (VAL1) < ctz_hwi (VAL2) \ + ? ctz_hwi (VAL1) \ + : ctz_hwi (VAL2)) + +/* Returns true if both VAL1 and VAL2 are SMALL_OPERANDs after shifting by + the common number of trailing zeros. */ +#define SMALL_AFTER_COMMON_TRAILING_SHIFT(VAL1, VAL2) \ + (SMALL_OPERAND ((VAL1) >> COMMON_TRAILING_ZEROS (VAL1, VAL2)) \ + && SMALL_OPERAND ((VAL2) >> COMMON_TRAILING_ZEROS (VAL1, VAL2))) + /* Stack layout; function entry, exit and calling. */ #define STACK_GROWS_DOWNWARD 1 diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 688c07df46c..78112afbb26 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -3129,6 +3129,38 @@ } [(set_attr "type" "branch")]) +(define_insn_and_split "*branch<ANYI:mode>_shiftedarith_<optab>_shifted" + [(set (pc) + (if_then_else (any_eq + (and:ANYI (match_operand:ANYI 1 "register_operand" "r") + (match_operand 2 "shifted_const_arith_operand" "i")) + (match_operand 3 "shifted_const_arith_operand" "i")) + (label_ref (match_operand 0 "" "")) + (pc))) + (clobber (match_scratch:X 4 "=&r")) + (clobber (match_scratch:X 5 "=&r"))] + "!SMALL_OPERAND (INTVAL (operands[2])) + && !SMALL_OPERAND (INTVAL (operands[3])) + && SMALL_AFTER_COMMON_TRAILING_SHIFT (INTVAL (operands[2]), + INTVAL (operands[3]))" + "#" + "&& reload_completed" + [(set (match_dup 4) (lshiftrt:X (match_dup 1) (match_dup 7))) + (set (match_dup 4) (and:X (match_dup 4) (match_dup 8))) + (set (match_dup 5) (match_dup 9)) + (set (pc) (if_then_else (any_eq (match_dup 4) (match_dup 5)) + (label_ref (match_dup 0)) (pc)))] +{ + HOST_WIDE_INT mask1 = INTVAL (operands[2]); + HOST_WIDE_INT mask2 = INTVAL (operands[3]); + int trailing_shift = COMMON_TRAILING_ZEROS (mask1, mask2); + + operands[7] = GEN_INT (trailing_shift); + operands[8] = GEN_INT (mask1 >> trailing_shift); + operands[9] = GEN_INT (mask2 >> trailing_shift); +} +[(set_attr "type" "branch")]) + (define_insn_and_split "*branch<ANYI:mode>_shiftedmask_equals_zero" [(set (pc) (if_then_else (match_operator 1 "equality_operator" diff --git a/gcc/testsuite/gcc.target/riscv/branch-1.c b/gcc/testsuite/gcc.target/riscv/branch-1.c index b4a3a946379..7fa87832484 100644 --- a/gcc/testsuite/gcc.target/riscv/branch-1.c +++ b/gcc/testsuite/gcc.target/riscv/branch-1.c @@ -28,10 +28,22 @@ void f4(long long a) g(); } +void f5(long long a) +{ + if ((a & 0x1ff800) == 0x11c800) + g(); +} + +void f6(long long a) +{ + if ((a & 0x33f800) == 0x110000) + g(); +} + /* { dg-final { scan-assembler-times "slli\t" 2 } } */ -/* { dg-final { scan-assembler-times "srli\t" 3 } } */ -/* { dg-final { scan-assembler-times "andi\t" 1 } } */ -/* { dg-final { scan-assembler-times "\tli\t" 1 } } */ +/* { dg-final { scan-assembler-times "srli\t" 5 } } */ +/* { dg-final { scan-assembler-times "andi\t" 3 } } */ +/* { dg-final { scan-assembler-times "\tli\t" 3 } } */ /* { dg-final { scan-assembler-not "addi\t" } } */ /* { dg-final { scan-assembler-not "and\t" } } */ -- 2.43.0