summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kazantsev <mkazantsev@azul.com>2022-07-18 16:13:58 +0700
committerMax Kazantsev <mkazantsev@azul.com>2022-07-18 16:26:06 +0700
commitd693fd29f1885e72b90428999aee92573abb9c2d (patch)
tree00091cb97def49b8c2f74515a79a024951ee5300
parent28b1ba1c0742a521037df7ef3a45cc969863eb06 (diff)
[Verifier] Make Verifier recognize undef tokens as correct IR
Undef tokens may appear in unreached code as result of RAUW of some optimization, and it should not be considered as bad IR. Patch by Dmitry Bakunevich! Differential Revision: https://reviews.llvm.org/D128904 Reviewed By: mkazantsev
-rw-r--r--llvm/include/llvm/IR/IntrinsicInst.h2
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp31
-rw-r--r--llvm/lib/IR/IntrinsicInst.cpp22
-rw-r--r--llvm/lib/IR/Verifier.cpp12
-rw-r--r--llvm/test/Transforms/InstCombine/gc.relocate-verify.ll17
5 files changed, 66 insertions, 18 deletions
diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h
index 06d2335821d3..fc9111a4f512 100644
--- a/llvm/include/llvm/IR/IntrinsicInst.h
+++ b/llvm/include/llvm/IR/IntrinsicInst.h
@@ -1381,7 +1381,7 @@ public:
}
/// The statepoint with which this gc.relocate is associated.
- const GCStatepointInst *getStatepoint() const;
+ const Value *getStatepoint() const;
};
/// Represents calls to the gc.relocate intrinsic.
diff --git a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
index 0d0adcd79e04..efa9a09eab3b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
@@ -169,8 +169,14 @@ static Optional<int> findPreviousSpillSlot(const Value *Val,
// Spill location is known for gc relocates
if (const auto *Relocate = dyn_cast<GCRelocateInst>(Val)) {
- const auto &RelocationMap =
- Builder.FuncInfo.StatepointRelocationMaps[Relocate->getStatepoint()];
+ const Value *Statepoint = Relocate->getStatepoint();
+ assert((isa<GCStatepointInst>(Statepoint) || isa<UndefValue>(Statepoint)) &&
+ "GetStatepoint must return one of two types");
+ if (isa<UndefValue>(Statepoint))
+ return None;
+
+ const auto &RelocationMap = Builder.FuncInfo.StatepointRelocationMaps
+ [cast<GCStatepointInst>(Statepoint)];
auto It = RelocationMap.find(Relocate);
if (It == RelocationMap.end())
@@ -1196,9 +1202,13 @@ void SelectionDAGBuilder::LowerCallSiteWithDeoptBundle(
void SelectionDAGBuilder::visitGCResult(const GCResultInst &CI) {
// The result value of the gc_result is simply the result of the actual
// call. We've already emitted this, so just grab the value.
- const GCStatepointInst *SI = CI.getStatepoint();
+ const Value *SI = CI.getStatepoint();
+ assert((isa<GCStatepointInst>(SI) || isa<UndefValue>(SI)) &&
+ "GetStatepoint must return one of two types");
+ if (isa<UndefValue>(SI))
+ return;
- if (SI->getParent() == CI.getParent()) {
+ if (cast<GCStatepointInst>(SI)->getParent() == CI.getParent()) {
setValue(&CI, getValue(SI));
return;
}
@@ -1221,7 +1231,13 @@ void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) {
// We skip this check for relocates not in the same basic block as their
// statepoint. It would be too expensive to preserve validation info through
// different basic blocks.
- if (Relocate.getStatepoint()->getParent() == Relocate.getParent())
+ const Value *Statepoint = Relocate.getStatepoint();
+ assert((isa<GCStatepointInst>(Statepoint) || isa<UndefValue>(Statepoint)) &&
+ "GetStatepoint must return one of two types");
+ if (isa<UndefValue>(Statepoint))
+ return;
+
+ if (cast<GCStatepointInst>(Statepoint)->getParent() == Relocate.getParent())
StatepointLowering.relocCallVisited(Relocate);
auto *Ty = Relocate.getType()->getScalarType();
@@ -1231,14 +1247,15 @@ void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) {
const Value *DerivedPtr = Relocate.getDerivedPtr();
auto &RelocationMap =
- FuncInfo.StatepointRelocationMaps[Relocate.getStatepoint()];
+ FuncInfo.StatepointRelocationMaps[cast<GCStatepointInst>(Statepoint)];
auto SlotIt = RelocationMap.find(&Relocate);
assert(SlotIt != RelocationMap.end() && "Relocating not lowered gc value");
const RecordType &Record = SlotIt->second;
// If relocation was done via virtual register..
if (Record.type == RecordType::SDValueNode) {
- assert(Relocate.getStatepoint()->getParent() == Relocate.getParent() &&
+ assert(cast<GCStatepointInst>(Statepoint)->getParent() ==
+ Relocate.getParent() &&
"Nonlocal gc.relocate mapped via SDValue");
SDValue SDV = StatepointLowering.getLocation(getValue(DerivedPtr));
assert(SDV.getNode() && "empty SDValue");
diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp
index 65a9a32ad2c5..c50d6901c9da 100644
--- a/llvm/lib/IR/IntrinsicInst.cpp
+++ b/llvm/lib/IR/IntrinsicInst.cpp
@@ -694,8 +694,10 @@ unsigned BinaryOpIntrinsic::getNoWrapKind() const {
return OverflowingBinaryOperator::NoUnsignedWrap;
}
-const GCStatepointInst *GCProjectionInst::getStatepoint() const {
+const Value *GCProjectionInst::getStatepoint() const {
const Value *Token = getArgOperand(0);
+ if (isa<UndefValue>(Token))
+ return Token;
// This takes care both of relocates for call statepoints and relocates
// on normal path of invoke statepoint.
@@ -714,13 +716,23 @@ const GCStatepointInst *GCProjectionInst::getStatepoint() const {
}
Value *GCRelocateInst::getBasePtr() const {
- if (auto Opt = getStatepoint()->getOperandBundle(LLVMContext::OB_gc_live))
+ auto Statepoint = getStatepoint();
+ if (isa<UndefValue>(Statepoint))
+ return UndefValue::get(Statepoint->getType());
+
+ auto *GCInst = cast<GCStatepointInst>(Statepoint);
+ if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live))
return *(Opt->Inputs.begin() + getBasePtrIndex());
- return *(getStatepoint()->arg_begin() + getBasePtrIndex());
+ return *(GCInst->arg_begin() + getBasePtrIndex());
}
Value *GCRelocateInst::getDerivedPtr() const {
- if (auto Opt = getStatepoint()->getOperandBundle(LLVMContext::OB_gc_live))
+ auto *Statepoint = getStatepoint();
+ if (isa<UndefValue>(Statepoint))
+ return UndefValue::get(Statepoint->getType());
+
+ auto *GCInst = cast<GCStatepointInst>(Statepoint);
+ if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live))
return *(Opt->Inputs.begin() + getDerivedPtrIndex());
- return *(getStatepoint()->arg_begin() + getDerivedPtrIndex());
+ return *(GCInst->arg_begin() + getDerivedPtrIndex());
}
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index c540b01392fc..806bce7c8fc0 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5156,14 +5156,13 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
// In all other cases relocate should be tied to the statepoint directly.
// This covers relocates on a normal return path of invoke statepoint and
// relocates of a call statepoint.
- auto Token = Call.getArgOperand(0);
- Check(isa<GCStatepointInst>(Token),
+ auto *Token = Call.getArgOperand(0);
+ Check(isa<GCStatepointInst>(Token) || isa<UndefValue>(Token),
"gc relocate is incorrectly tied to the statepoint", Call, Token);
}
// Verify rest of the relocate arguments.
- const CallBase &StatepointCall =
- *cast<GCRelocateInst>(Call).getStatepoint();
+ const Value &StatepointCall = *cast<GCRelocateInst>(Call).getStatepoint();
// Both the base and derived must be piped through the safepoint.
Value *Base = Call.getArgOperand(1);
@@ -5178,7 +5177,10 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
const uint64_t DerivedIndex = cast<ConstantInt>(Derived)->getZExtValue();
// Check the bounds
- if (auto Opt = StatepointCall.getOperandBundle(LLVMContext::OB_gc_live)) {
+ if (isa<UndefValue>(StatepointCall))
+ break;
+ if (auto Opt = cast<GCStatepointInst>(StatepointCall)
+ .getOperandBundle(LLVMContext::OB_gc_live)) {
Check(BaseIndex < Opt->Inputs.size(),
"gc.relocate: statepoint base index out of bounds", Call);
Check(DerivedIndex < Opt->Inputs.size(),
diff --git a/llvm/test/Transforms/InstCombine/gc.relocate-verify.ll b/llvm/test/Transforms/InstCombine/gc.relocate-verify.ll
new file mode 100644
index 000000000000..b338b3785e20
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/gc.relocate-verify.ll
@@ -0,0 +1,17 @@
+; RUN: opt -S -passes=verify < %s | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @check_verify_undef_token() gc "statepoint-example" {
+
+entry:
+ ; CHECK: ret i32 0
+ ret i32 0
+
+unreach:
+ ; CHECK: token undef
+ %token_call = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token undef, i32 0, i32 0)
+ ret i32 1
+}
+
+declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32)