[llvm] a391b49 - [RISCV] Prevent constant hoisting for (and (shl X, C), mask<<C)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 21 19:22:46 PST 2022


Author: Craig Topper
Date: 2022-11-21T19:16:40-08:00
New Revision: a391b49ce8524ddb6283d6605544a354d187a9d4

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

LOG: [RISCV] Prevent constant hoisting for (and (shl X, C), mask<<C)

If the immediate is a shifted mask, we will use a pair of shifts
and never materialize the immediate. Consider the immediate free.

Reviewed By: reames, luismarques

Differential Revision: https://reviews.llvm.org/D138260

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
    llvm/test/Transforms/ConstantHoisting/RISCV/immediates.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
index 3fb714dea319..e85eda5dc7c4 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
@@ -46,6 +46,33 @@ InstructionCost RISCVTTIImpl::getIntImmCost(const APInt &Imm, Type *Ty,
                                     getST()->getFeatureBits());
 }
 
+// Look for patterns of shift followed by AND that can be turned into a pair of
+// shifts. We won't need to materialize an immediate for the AND so these can
+// be considered free.
+static bool canUseShiftPair(Instruction *Inst, const APInt &Imm) {
+  uint64_t Mask = Imm.getZExtValue();
+  auto *BO = dyn_cast<BinaryOperator>(Inst->getOperand(0));
+  if (!BO || !BO->hasOneUse())
+    return false;
+
+  if (BO->getOpcode() != Instruction::Shl)
+    return false;
+
+  if (!isa<ConstantInt>(BO->getOperand(1)))
+    return false;
+
+  unsigned ShAmt = cast<ConstantInt>(BO->getOperand(1))->getZExtValue();
+  // (and (shl x, c2), c1) will be matched to (srli (slli x, c2+c3), c3) if c1
+  // is a mask shifted by c2 bits with c3 leading zeros.
+  if (isShiftedMask_64(Mask)) {
+    unsigned Trailing = countTrailingZeros(Mask);
+    if (ShAmt == Trailing)
+      return true;
+  }
+
+  return false;
+}
+
 InstructionCost RISCVTTIImpl::getIntImmCostInst(unsigned Opcode, unsigned Idx,
                                                 const APInt &Imm, Type *Ty,
                                                 TTI::TargetCostKind CostKind,
@@ -75,6 +102,9 @@ InstructionCost RISCVTTIImpl::getIntImmCostInst(unsigned Opcode, unsigned Idx,
     // zext.w
     if (Imm == UINT64_C(0xffffffff) && ST->hasStdExtZba())
       return TTI::TCC_Free;
+    if (Inst && Idx == 1 && Imm.getBitWidth() <= ST->getXLen() &&
+        canUseShiftPair(Inst, Imm))
+      return TTI::TCC_Free;
     [[fallthrough]];
   case Instruction::Add:
   case Instruction::Or:

diff  --git a/llvm/test/Transforms/ConstantHoisting/RISCV/immediates.ll b/llvm/test/Transforms/ConstantHoisting/RISCV/immediates.ll
index e1badcb3545d..fe705fc4acc1 100644
--- a/llvm/test/Transforms/ConstantHoisting/RISCV/immediates.ll
+++ b/llvm/test/Transforms/ConstantHoisting/RISCV/immediates.ll
@@ -81,3 +81,17 @@ define i64 @test9(i64 %a) nounwind {
   %2 = mul i64 %1, -4294967296
   ret i64 %2
 }
+
+define i32 @test10(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: @test10(
+; CHECK: shl i32 %a, 8
+; CHECK: and i32 %1, 65280
+; CHECK: shl i32 %b, 8
+; CHECK: and i32 %3, 65280
+  %1 = shl i32 %a, 8
+  %2 = and i32 %1, 65280
+  %3 = shl i32 %b, 8
+  %4 = and i32 %3, 65280
+  %5 = mul i32 %2, %4
+  ret i32 %5
+}


        


More information about the llvm-commits mailing list