[llvm] e25eb61 - [RISCV] Enable (srl (and X, C2), C) to form SRLIW in more cases.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 29 15:56:46 PDT 2022


Author: Craig Topper
Date: 2022-08-29T15:52:08-07:00
New Revision: e25eb61d031bc01940aca1481adc05ad28f72628

URL: https://github.com/llvm/llvm-project/commit/e25eb61d031bc01940aca1481adc05ad28f72628
DIFF: https://github.com/llvm/llvm-project/commit/e25eb61d031bc01940aca1481adc05ad28f72628.diff

LOG: [RISCV] Enable (srl (and X, C2), C) to form SRLIW in more cases.

Don't require the AND has one use and don't depend on
targetShrinkDemandedConstant turning C2 into 0xffffffff. Instead,
check that the constant is 0xffffffff after replacing any bits
that will be shifted out with 1s.

Another way to fix this might be to prevent SimplifyDemandedBits
from destroying the ANDI after type legalization using
targetShrinkDemandedBits. That would prevent the CSE that created
this mess. targetShrinkDemandedBits is currently only enable after
legalize ops. Quick experiment shows we can't just change when it
runs, we would need to try a different heuristic for post type
legalization.

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
    llvm/test/CodeGen/RISCV/rv64i-demanded-bits.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 14103857df66..ac57716d5add 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -730,15 +730,14 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
     if (!N1C)
       break;
     SDValue N0 = Node->getOperand(0);
-    if (N0.getOpcode() != ISD::AND || !N0.hasOneUse() ||
-        !isa<ConstantSDNode>(N0.getOperand(1)))
+    if (N0.getOpcode() != ISD::AND || !isa<ConstantSDNode>(N0.getOperand(1)))
       break;
     unsigned ShAmt = N1C->getZExtValue();
     uint64_t Mask = N0.getConstantOperandVal(1);
 
     // Optimize (srl (and X, C2), C) -> (slli (srliw X, C3), C3-C) where C2 has
     // 32 leading zeros and C3 trailing zeros.
-    if (isShiftedMask_64(Mask)) {
+    if (isShiftedMask_64(Mask) && N0.hasOneUse()) {
       unsigned XLen = Subtarget->getXLen();
       unsigned LeadingZeros = XLen - (64 - countLeadingZeros(Mask));
       unsigned TrailingZeros = countTrailingZeros(Mask);
@@ -765,9 +764,21 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
     if (!isMask_64(Mask))
       break;
     unsigned TrailingOnes = countTrailingOnes(Mask);
-    // 32 trailing ones should use srliw via tablegen pattern.
-    if (TrailingOnes == 32 || ShAmt >= TrailingOnes)
+    if (ShAmt >= TrailingOnes)
       break;
+    // If the mask has 32 trailing ones, use SRLIW.
+    if (TrailingOnes == 32) {
+      SDNode *SRLIW =
+          CurDAG->getMachineNode(RISCV::SRLIW, DL, VT, N0->getOperand(0),
+                                 CurDAG->getTargetConstant(ShAmt, DL, VT));
+      ReplaceNode(Node, SRLIW);
+      return;
+    }
+
+    // Only do the remaining transforms if the shift has one use.
+    if (!N0.hasOneUse())
+      break;
+
     // If C2 is (1 << ShAmt) use bexti if possible.
     if (Subtarget->hasStdExtZbs() && ShAmt + 1 == TrailingOnes) {
       SDNode *BEXTI =

diff  --git a/llvm/test/CodeGen/RISCV/rv64i-demanded-bits.ll b/llvm/test/CodeGen/RISCV/rv64i-demanded-bits.ll
index f12fc4a915b7..90c982ec0b9e 100644
--- a/llvm/test/CodeGen/RISCV/rv64i-demanded-bits.ll
+++ b/llvm/test/CodeGen/RISCV/rv64i-demanded-bits.ll
@@ -123,18 +123,16 @@ define signext i32 @andi_sub_cse(i32 signext %0, i32 signext %1, ptr %2) {
 ; the use count of the AND with 0xfffffff8 making TargetShrinkDemandedConstant
 ; unable to restore it to 0xffffffff for the lshr and -8 for the AND to use
 ; ANDI.
-; FIXME: To fix this we need to allow srliw to be formed if the AND is not
-; 0xffffffff and has more than 1 use.
+; Instead we rely on ISel to form srliw even though the AND has multiple uses
+; and the mask has missing 1s where bits will be shifted out. This reduces the
+; use count of the AND and we can use hasAllWUsers to form ANDI.
 define signext i32 @andi_srliw(i32 signext %0, ptr %1, i32 signext %2) {
 ; CHECK-LABEL: andi_srliw:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    li a3, 1
-; CHECK-NEXT:    slli a3, a3, 32
-; CHECK-NEXT:    addi a3, a3, -8
-; CHECK-NEXT:    and a0, a0, a3
-; CHECK-NEXT:    srli a3, a0, 3
-; CHECK-NEXT:    addw a0, a0, a2
-; CHECK-NEXT:    sw a3, 0(a1)
+; CHECK-NEXT:    andi a3, a0, -8
+; CHECK-NEXT:    srliw a4, a0, 3
+; CHECK-NEXT:    addw a0, a3, a2
+; CHECK-NEXT:    sw a4, 0(a1)
 ; CHECK-NEXT:    ret
   %4 = and i32 %0, -8
   %5 = lshr i32 %0, 3


        


More information about the llvm-commits mailing list