https://gcc.gnu.org/g:b2e7fd2c4fa3a8a094d03d71cdb2526f2a2dcbff

commit b2e7fd2c4fa3a8a094d03d71cdb2526f2a2dcbff
Author: Shreya Munnangi <smunnan...@ventanamicro.com>
Date:   Sat May 24 13:52:55 2025 -0600

    [RISC-V] shift+and+shift for logical and synthesis
    
    The next chunk of Shreya's work.
    
    For this expansion we want to detect cases when the mask fits in a simm12 
after
    shifting right by the number of trailing zeros in the mask.
    
    In that case we can synthesize the AND with a shift right, andi and shift 
left.
    I saw this case come up when doing some experimentation with 
mvconst_internal
    removed.
    
    This doesn't make any difference in spec right now, mvconst_internal will 
turn
    the sequence back into a constant load + and with register. But Shreya and I
    have reviewed the .expand dump on hand written tests and verified we're 
getting
    the synthesis we want.
    
    Tested on riscv32-elf and riscv64-elf.  Waiting on upstream CI's verdict 
before
    moving forward.
    
    gcc/
            * config/riscv/riscv.cc (synthesize_and): Use a srl+andi+sll
            sequence when the mask fits in a simm12 after shifting by the
            number of trailing zeros.
    
            Co-authored-by: Jeff Law <j...@ventanamicro.com>
    
    (cherry picked from commit 2e2557d160cc0b893a7bcad1bee1683ad948dc60)

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

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 18c8e188f23b..eaaca3649835 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -14563,6 +14563,36 @@ synthesize_and (rtx operands[3])
       return true;
     }
 
+  /* If we shift right to eliminate the trailing zeros and
+     the result is a SMALL_OPERAND, then it's a shift right,
+     andi and shift left.  */
+  t = INTVAL (operands[2]);
+  t >>= ctz_hwi (t);
+  if (budget >= 3 && SMALL_OPERAND (t) && popcount_hwi (t) > 2)
+    {
+      /* Shift right to clear the low order bits.  */
+      unsigned HOST_WIDE_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;
+
+      /* Now emit the ANDI.  */
+      unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
+      mask >>= ctz_hwi (mask);
+      x = gen_rtx_AND (word_mode, input, GEN_INT (mask));
+      output = gen_reg_rtx (word_mode);
+      emit_insn (gen_rtx_SET (output, x));
+      input = output;
+
+      /* Shift left to move bits into position.  */
+      count = INTVAL (operands[2]);
+      count = ctz_hwi (count);
+      x = gen_rtx_ASHIFT (word_mode, input, GEN_INT (count));
+      emit_insn (gen_rtx_SET (operands[0], x));
+      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]);

Reply via email to