[gcc(refs/vendors/riscv/heads/gcc-15-with-riscv-opts)] [RISC-V] Clear both upper and lower bits using 3 shifts

Jeff Law law@gcc.gnu.org
Sat Sep 13 16:09:17 GMT 2025


https://gcc.gnu.org/g:60b781c72813322cd7cbe6c04ce839321ea2fccf

commit 60b781c72813322cd7cbe6c04ce839321ea2fccf
Author: Shreya Munnangi <smunnangi1@ventanamicro.com>
Date:   Thu May 22 11:51:01 2025 -0600

    [RISC-V] Clear both upper and lower bits using 3 shifts
    
    So the next step in Shreya's work.  In the prior patch we used two shifts to
    clear bits at the high or low end of an object.  In this patch we use 3 shifts
    to clear bits on both ends.
    
    Nothing really special here.  With mvconst_internal still in the tree it's of
    marginal value, though Shreya and I have confirmed the code coming out of
    expand looks good.  It's just that combine reconstitutes the operation via
    mvconst_internal+and which looks cheaper.
    
    When I was playing in this space earlier I definitely saw testsuite cases that
    need this case handled to not regress with mvconst_internal removed.
    
    This has spun in my tester on rv32 and rv64 and it's bootstrap + testing on my
    BPI with a mere 23 hours to go.  Waiting on pre-commit testing to render a
    verdict before moving forward.
    
    gcc/
            * config/riscv/riscv.cc (synthesize_and): When profitable, use a three
            shift sequence to clear bits at both upper and lower bits rather than
            synthesizing the constant mask.
    
    (cherry picked from commit 65f27c18e349e2ccdfac34cef8640d8c6ca1d3c1)

Diff:
---
 gcc/config/riscv/riscv.cc | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 38ee47a6c722..047b86116cd5 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -14572,6 +14572,34 @@ synthesize_and (rtx operands[3])
       return true;
     }
 
+  /* If there are all zeros, except for a run of 1s somewhere in the middle
+     of the constant, then this is at worst 3 shifts.  */
+  t = INTVAL (operands[2]);
+  if (budget >= 3
+      && consecutive_bits_operand (GEN_INT (t), word_mode)
+      && popcount_hwi (t) > 3)
+    {
+      /* Shift right to clear the low order bits.  */
+      int count = ctz_hwi (INTVAL (operands[2]));
+      rtx x = gen_rtx_LSHIFTRT (word_mode, operands[1], GEN_INT (count));
+      output = gen_reg_rtx (word_mode);
+      emit_insn (gen_rtx_SET (output, x));
+      input = output;
+
+      /* Shift left to clear the high order bits.  */
+      count += clz_hwi (INTVAL (operands[2])) % BITS_PER_WORD;
+      x = gen_rtx_ASHIFT (word_mode, input, GEN_INT (count));
+      output = gen_reg_rtx (word_mode);
+      emit_insn (gen_rtx_SET (output, x));
+      input = output;
+
+      /* And shift back right to put the bits into position.  */
+      count = clz_hwi (INTVAL (operands[2])) % BITS_PER_WORD;
+      x = gen_rtx_LSHIFTRT (word_mode, input, GEN_INT (count));
+      emit_insn (gen_rtx_SET (operands[0], x));
+      return true;
+    }
+
   /* If the remaining budget has gone to less than zero, it
      forces the value into a register and performs the AND
      operation.  It returns TRUE to the caller so the caller


More information about the Gcc-cvs mailing list