diff options
author | Oliver Kozul <Oliver.Kozul@rt-rk.com> | 2024-12-17 07:44:33 -0700 |
---|---|---|
committer | Jeff Law <jlaw@ventanamicro.com> | 2024-12-17 07:44:33 -0700 |
commit | d17b09c07a1da0e3950718aabc2cbdb90cae402b (patch) | |
tree | 5e943a12f18f19bb67ba9ef024d0ff420a4c5f96 | |
parent | d24a5e2d381b290d4def659ed83e969b65d07f02 (diff) | |
download | gcc-d17b09c07a1da0e3950718aabc2cbdb90cae402b.zip gcc-d17b09c07a1da0e3950718aabc2cbdb90cae402b.tar.gz gcc-d17b09c07a1da0e3950718aabc2cbdb90cae402b.tar.bz2 |
[PATCH] RISC-V: optimization on checking certain bits set ((x & mask) == val)
The patch optimizes code generation for comparisons of the form
X & C1 == C2 by converting them to (X | ~C1) == (C2 | ~C1).
C1 is a constant that requires li and addi to be loaded,
while ~C1 requires a single lui instruction.
As the values of C1 and C2 are not visible within
the equality expression, a plus pattern is matched instead.
PR target/114087
gcc/ChangeLog:
* config/riscv/riscv.md (*lui_constraint<ANYI:mode>_and_to_or): New pattern
gcc/testsuite/ChangeLog:
* gcc.target/riscv/pr114087-1.c: New test.
-rw-r--r-- | gcc/config/riscv/riscv.md | 28 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/pr114087-1.c | 16 |
2 files changed, 44 insertions, 0 deletions
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 1eec51c..6c6155c 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -858,6 +858,34 @@ [(set_attr "type" "arith") (set_attr "mode" "SI")]) +;; Transform (X & C1) + C2 into (X | ~C1) - (-C2 | ~C1) +;; Where C1 is not a LUI operand, but ~C1 is a LUI operand + +(define_insn_and_split "*lui_constraint<ANYI:mode>_and_to_or" + [(set (match_operand:ANYI 0 "register_operand" "=r") + (plus:ANYI (and:ANYI (match_operand:ANYI 1 "register_operand" "r") + (match_operand 2 "const_int_operand")) + (match_operand 3 "const_int_operand"))) + (clobber (match_scratch:X 4 "=&r"))] + "LUI_OPERAND (~INTVAL (operands[2])) + && ((INTVAL (operands[2]) & (-INTVAL (operands[3]))) + == (-INTVAL (operands[3]))) + && riscv_const_insns (operands[3], false) + && (riscv_const_insns + (GEN_INT (~INTVAL (operands[2]) | -INTVAL (operands[3])), false) + <= riscv_const_insns (operands[3], false))" + "#" + "&& reload_completed" + [(set (match_dup 4) (match_dup 5)) + (set (match_dup 0) (ior:X (match_dup 1) (match_dup 4))) + (set (match_dup 4) (match_dup 6)) + (set (match_dup 0) (minus:X (match_dup 0) (match_dup 4)))] + { + operands[5] = GEN_INT (~INTVAL (operands[2])); + operands[6] = GEN_INT ((~INTVAL (operands[2])) | (-INTVAL (operands[3]))); + } + [(set_attr "type" "arith")]) + ;; ;; .................... ;; diff --git a/gcc/testsuite/gcc.target/riscv/pr114087-1.c b/gcc/testsuite/gcc.target/riscv/pr114087-1.c new file mode 100644 index 0000000..9df02db --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr114087-1.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" } } */ +/* { dg-options "-march=rv64gc -mabi=lp64d" } */ + +#include <stdbool.h> +#include <stdint.h> + +static uint32_t mask1 = 0x55555FFF; +static uint32_t val1 = 0x14501DEF; + +bool pred1a(uint32_t x) { + return ((x & mask1) == val1); +} + +/* { dg-final { scan-assembler {or\s*[a-x0-9]+,\s*[a-x0-9]+,\s*[a-x0-9]+} } } */ |