The patch optimizes code generation for comparisons of the form X & C1 == C2. When the bitwise AND mask is stored in the lower 20 bits it can be left shifted so it behaves as a LUI operand instead, saving an addi instruction while loading.
2024-12-13 Oliver Kozul <oliver.ko...@rt-rk.com> PR target/114087 gcc/ChangeLog: * config/riscv/riscv.h (COMMON_LEADING_ZEROS): New macro. (LUI_AFTER_COMMON_LEADING_SHIFT): New macro. * config/riscv/riscv.md (*lui_constraint<ANYI:mode>_ashift): New pattern. gcc/testsuite/ChangeLog: * gcc.target/riscv/pr114087-3.c: New test. 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/riscv.h | 18 +++++++++++ gcc/config/riscv/riscv.md | 35 +++++++++++++++++++++ gcc/testsuite/gcc.target/riscv/pr114087-3.c | 10 ++++++ 3 files changed, 63 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/pr114087-3.c diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 09de74667a9..92850a52251 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -677,6 +677,24 @@ enum reg_class (SMALL_OPERAND ((VAL1) >> COMMON_TRAILING_ZEROS (VAL1, VAL2)) \ && SMALL_OPERAND ((VAL2) >> COMMON_TRAILING_ZEROS (VAL1, VAL2))) +/* Returns the smaller (common) number of leading zeros for VAL1 and VAL2. */ +#define COMMON_LEADING_ZEROS(VAL1, VAL2) \ + (clz_hwi (VAL1) < clz_hwi (VAL2) \ + ? clz_hwi (VAL1) \ + : clz_hwi (VAL2)) + +/* Returns true if both VAL1 and VAL2 are LUI_OPERANDs after shifting by + the common number of leading zeros (-1 to account for sign). */ +#define LUI_AFTER_COMMON_LEADING_SHIFT(VAL1, VAL2) \ + ((LUI_OPERAND \ + ((VAL1) << (COMMON_LEADING_ZEROS (VAL1, VAL2) - 1)) \ + && LUI_OPERAND \ + ((VAL2) << (COMMON_LEADING_ZEROS (VAL1, VAL2) - 1))) \ + || ((LUI_OPERAND \ + ((VAL1) << (COMMON_LEADING_ZEROS (VAL1, VAL2) - 33)) \ + && LUI_OPERAND \ + ((VAL2) << (COMMON_LEADING_ZEROS (VAL1, VAL2) - 33))))) + /* 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 3a4cd1d93a0..a44caa6908d 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -858,6 +858,41 @@ [(set_attr "type" "arith") (set_attr "mode" "SI")]) +(define_insn_and_split "*lui_constraint<ANYI:mode>_ashift" + [(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])) + && !LUI_OPERAND (-INTVAL (operands[3])) + && !SMALL_OPERAND (INTVAL (operands[2])) + && !SMALL_OPERAND (-INTVAL (operands[3])) + && LUI_AFTER_COMMON_LEADING_SHIFT (INTVAL (operands[2]), + -INTVAL (operands[3]))" + "#" + "&& reload_completed" + [(set (match_dup 0) (ashift:X (match_dup 1) (match_dup 5))) + (set (match_dup 4) (match_dup 6)) + (set (match_dup 0) (and:X (match_dup 0) (match_dup 4))) + (set (match_dup 4) (match_dup 7)) + (set (match_dup 0) (minus:X (match_dup 0) (match_dup 4)))] + { + HOST_WIDE_INT mask = INTVAL (operands[2]); + HOST_WIDE_INT val = -INTVAL (operands[3]); + int leading_shift = COMMON_LEADING_ZEROS (mask, val) - 1; + + if (TARGET_64BIT && leading_shift > 32) + { + leading_shift -= 32; + } + + operands[5] = GEN_INT (leading_shift); + operands[6] = GEN_INT (mask << leading_shift); + operands[7] = GEN_INT (val << leading_shift); + } +[(set_attr "type" "arith")]) + ;; ;; .................... ;; diff --git a/gcc/testsuite/gcc.target/riscv/pr114087-3.c b/gcc/testsuite/gcc.target/riscv/pr114087-3.c new file mode 100644 index 00000000000..d93fb354c25 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr114087-3.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" } } */ +/* { dg-options "-march=rv64gc -mabi=lp64d" } */ + +int pred3a(int x) { + return ((x & 0x00055555) == 0x00045014); +} + +/* { dg-final { scan-assembler {slli\s*[a-x0-9]+,\s*[a-x0-9]+,\s*12}} } */ \ No newline at end of file -- 2.43.0