aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/GlobalISel
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/GlobalISel')
-rw-r--r--llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp66
-rw-r--r--llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp20
-rw-r--r--llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp6
3 files changed, 71 insertions, 21 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 1286af8..974fc40 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -1884,6 +1884,14 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
}
break;
}
+ case TargetOpcode::G_ASHR: {
+ Register Src1 = MI.getOperand(1).getReg();
+ Register Src2 = MI.getOperand(2).getReg();
+ FirstAnswer = computeNumSignBits(Src1, DemandedElts, Depth + 1);
+ if (auto C = getValidMinimumShiftAmount(Src2, DemandedElts, Depth + 1))
+ FirstAnswer = std::min<uint64_t>(FirstAnswer + *C, TyBits);
+ break;
+ }
case TargetOpcode::G_TRUNC: {
Register Src = MI.getOperand(1).getReg();
LLT SrcTy = MRI.getType(Src);
@@ -2053,6 +2061,64 @@ unsigned GISelValueTracking::computeNumSignBits(Register R, unsigned Depth) {
return computeNumSignBits(R, DemandedElts, Depth);
}
+std::optional<ConstantRange> GISelValueTracking::getValidShiftAmountRange(
+ Register R, const APInt &DemandedElts, unsigned Depth) {
+ // Shifting more than the bitwidth is not valid.
+ MachineInstr &MI = *MRI.getVRegDef(R);
+ unsigned Opcode = MI.getOpcode();
+
+ LLT Ty = MRI.getType(R);
+ unsigned BitWidth = Ty.getScalarSizeInBits();
+
+ if (Opcode == TargetOpcode::G_CONSTANT) {
+ const APInt &ShAmt = MI.getOperand(1).getCImm()->getValue();
+ if (ShAmt.uge(BitWidth))
+ return std::nullopt;
+ return ConstantRange(ShAmt);
+ }
+
+ if (Opcode == TargetOpcode::G_BUILD_VECTOR) {
+ const APInt *MinAmt = nullptr, *MaxAmt = nullptr;
+ for (unsigned I = 0, E = MI.getNumOperands() - 1; I != E; ++I) {
+ if (!DemandedElts[I])
+ continue;
+ MachineInstr *Op = MRI.getVRegDef(MI.getOperand(I + 1).getReg());
+ if (Op->getOpcode() != TargetOpcode::G_CONSTANT) {
+ MinAmt = MaxAmt = nullptr;
+ break;
+ }
+
+ const APInt &ShAmt = Op->getOperand(1).getCImm()->getValue();
+ if (ShAmt.uge(BitWidth))
+ return std::nullopt;
+ if (!MinAmt || MinAmt->ugt(ShAmt))
+ MinAmt = &ShAmt;
+ if (!MaxAmt || MaxAmt->ult(ShAmt))
+ MaxAmt = &ShAmt;
+ }
+ assert(((!MinAmt && !MaxAmt) || (MinAmt && MaxAmt)) &&
+ "Failed to find matching min/max shift amounts");
+ if (MinAmt && MaxAmt)
+ return ConstantRange(*MinAmt, *MaxAmt + 1);
+ }
+
+ // Use computeKnownBits to find a hidden constant/knownbits (usually type
+ // legalized). e.g. Hidden behind multiple bitcasts/build_vector/casts etc.
+ KnownBits KnownAmt = getKnownBits(R, DemandedElts, Depth);
+ if (KnownAmt.getMaxValue().ult(BitWidth))
+ return ConstantRange::fromKnownBits(KnownAmt, /*IsSigned=*/false);
+
+ return std::nullopt;
+}
+
+std::optional<uint64_t> GISelValueTracking::getValidMinimumShiftAmount(
+ Register R, const APInt &DemandedElts, unsigned Depth) {
+ if (std::optional<ConstantRange> AmtRange =
+ getValidShiftAmountRange(R, DemandedElts, Depth))
+ return AmtRange->getUnsignedMin().getZExtValue();
+ return std::nullopt;
+}
+
void GISelValueTrackingAnalysisLegacy::getAnalysisUsage(
AnalysisUsage &AU) const {
AU.setPreservesAll();
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index d7280ea..dc5dfab 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -2189,23 +2189,11 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
unsigned Op = ID == Intrinsic::lifetime_start ? TargetOpcode::LIFETIME_START
: TargetOpcode::LIFETIME_END;
- // Get the underlying objects for the location passed on the lifetime
- // marker.
- SmallVector<const Value *, 4> Allocas;
- getUnderlyingObjects(CI.getArgOperand(1), Allocas);
-
- // Iterate over each underlying object, creating lifetime markers for each
- // static alloca. Quit if we find a non-static alloca.
- for (const Value *V : Allocas) {
- const AllocaInst *AI = dyn_cast<AllocaInst>(V);
- if (!AI)
- continue;
-
- if (!AI->isStaticAlloca())
- return true;
+ const AllocaInst *AI = cast<AllocaInst>(CI.getArgOperand(1));
+ if (!AI->isStaticAlloca())
+ return true;
- MIRBuilder.buildInstr(Op).addFrameIndex(getOrCreateFrameIndex(*AI));
- }
+ MIRBuilder.buildInstr(Op).addFrameIndex(getOrCreateFrameIndex(*AI));
return true;
}
case Intrinsic::fake_use: {
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 11b3ac8..ed7b07f 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -10120,14 +10120,10 @@ LegalizerHelper::lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen) {
return Legalized;
}
- bool IsVolatile = MemOp->isVolatile();
- // Don't try to optimize volatile.
- if (IsVolatile)
- return UnableToLegalize;
-
if (MaxLen && KnownLen > MaxLen)
return UnableToLegalize;
+ bool IsVolatile = MemOp->isVolatile();
if (Opc == TargetOpcode::G_MEMCPY) {
auto &MF = *MI.getParent()->getParent();
const auto &TLI = *MF.getSubtarget().getTargetLowering();