Skip to content

Commit d693fd2

Browse files
committed
[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
1 parent 28b1ba1 commit d693fd2

File tree

5 files changed

+66
-18
lines changed

5 files changed

+66
-18
lines changed

llvm/include/llvm/IR/IntrinsicInst.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1381,7 +1381,7 @@ class GCProjectionInst : public IntrinsicInst {
13811381
}
13821382

13831383
/// The statepoint with which this gc.relocate is associated.
1384-
const GCStatepointInst *getStatepoint() const;
1384+
const Value *getStatepoint() const;
13851385
};
13861386

13871387
/// Represents calls to the gc.relocate intrinsic.

llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,14 @@ static Optional<int> findPreviousSpillSlot(const Value *Val,
169169

170170
// Spill location is known for gc relocates
171171
if (const auto *Relocate = dyn_cast<GCRelocateInst>(Val)) {
172-
const auto &RelocationMap =
173-
Builder.FuncInfo.StatepointRelocationMaps[Relocate->getStatepoint()];
172+
const Value *Statepoint = Relocate->getStatepoint();
173+
assert((isa<GCStatepointInst>(Statepoint) || isa<UndefValue>(Statepoint)) &&
174+
"GetStatepoint must return one of two types");
175+
if (isa<UndefValue>(Statepoint))
176+
return None;
177+
178+
const auto &RelocationMap = Builder.FuncInfo.StatepointRelocationMaps
179+
[cast<GCStatepointInst>(Statepoint)];
174180

175181
auto It = RelocationMap.find(Relocate);
176182
if (It == RelocationMap.end())
@@ -1196,9 +1202,13 @@ void SelectionDAGBuilder::LowerCallSiteWithDeoptBundle(
11961202
void SelectionDAGBuilder::visitGCResult(const GCResultInst &CI) {
11971203
// The result value of the gc_result is simply the result of the actual
11981204
// call. We've already emitted this, so just grab the value.
1199-
const GCStatepointInst *SI = CI.getStatepoint();
1205+
const Value *SI = CI.getStatepoint();
1206+
assert((isa<GCStatepointInst>(SI) || isa<UndefValue>(SI)) &&
1207+
"GetStatepoint must return one of two types");
1208+
if (isa<UndefValue>(SI))
1209+
return;
12001210

1201-
if (SI->getParent() == CI.getParent()) {
1211+
if (cast<GCStatepointInst>(SI)->getParent() == CI.getParent()) {
12021212
setValue(&CI, getValue(SI));
12031213
return;
12041214
}
@@ -1221,7 +1231,13 @@ void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) {
12211231
// We skip this check for relocates not in the same basic block as their
12221232
// statepoint. It would be too expensive to preserve validation info through
12231233
// different basic blocks.
1224-
if (Relocate.getStatepoint()->getParent() == Relocate.getParent())
1234+
const Value *Statepoint = Relocate.getStatepoint();
1235+
assert((isa<GCStatepointInst>(Statepoint) || isa<UndefValue>(Statepoint)) &&
1236+
"GetStatepoint must return one of two types");
1237+
if (isa<UndefValue>(Statepoint))
1238+
return;
1239+
1240+
if (cast<GCStatepointInst>(Statepoint)->getParent() == Relocate.getParent())
12251241
StatepointLowering.relocCallVisited(Relocate);
12261242

12271243
auto *Ty = Relocate.getType()->getScalarType();
@@ -1231,14 +1247,15 @@ void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) {
12311247

12321248
const Value *DerivedPtr = Relocate.getDerivedPtr();
12331249
auto &RelocationMap =
1234-
FuncInfo.StatepointRelocationMaps[Relocate.getStatepoint()];
1250+
FuncInfo.StatepointRelocationMaps[cast<GCStatepointInst>(Statepoint)];
12351251
auto SlotIt = RelocationMap.find(&Relocate);
12361252
assert(SlotIt != RelocationMap.end() && "Relocating not lowered gc value");
12371253
const RecordType &Record = SlotIt->second;
12381254

12391255
// If relocation was done via virtual register..
12401256
if (Record.type == RecordType::SDValueNode) {
1241-
assert(Relocate.getStatepoint()->getParent() == Relocate.getParent() &&
1257+
assert(cast<GCStatepointInst>(Statepoint)->getParent() ==
1258+
Relocate.getParent() &&
12421259
"Nonlocal gc.relocate mapped via SDValue");
12431260
SDValue SDV = StatepointLowering.getLocation(getValue(DerivedPtr));
12441261
assert(SDV.getNode() && "empty SDValue");

llvm/lib/IR/IntrinsicInst.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -694,8 +694,10 @@ unsigned BinaryOpIntrinsic::getNoWrapKind() const {
694694
return OverflowingBinaryOperator::NoUnsignedWrap;
695695
}
696696

697-
const GCStatepointInst *GCProjectionInst::getStatepoint() const {
697+
const Value *GCProjectionInst::getStatepoint() const {
698698
const Value *Token = getArgOperand(0);
699+
if (isa<UndefValue>(Token))
700+
return Token;
699701

700702
// This takes care both of relocates for call statepoints and relocates
701703
// on normal path of invoke statepoint.
@@ -714,13 +716,23 @@ const GCStatepointInst *GCProjectionInst::getStatepoint() const {
714716
}
715717

716718
Value *GCRelocateInst::getBasePtr() const {
717-
if (auto Opt = getStatepoint()->getOperandBundle(LLVMContext::OB_gc_live))
719+
auto Statepoint = getStatepoint();
720+
if (isa<UndefValue>(Statepoint))
721+
return UndefValue::get(Statepoint->getType());
722+
723+
auto *GCInst = cast<GCStatepointInst>(Statepoint);
724+
if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live))
718725
return *(Opt->Inputs.begin() + getBasePtrIndex());
719-
return *(getStatepoint()->arg_begin() + getBasePtrIndex());
726+
return *(GCInst->arg_begin() + getBasePtrIndex());
720727
}
721728

722729
Value *GCRelocateInst::getDerivedPtr() const {
723-
if (auto Opt = getStatepoint()->getOperandBundle(LLVMContext::OB_gc_live))
730+
auto *Statepoint = getStatepoint();
731+
if (isa<UndefValue>(Statepoint))
732+
return UndefValue::get(Statepoint->getType());
733+
734+
auto *GCInst = cast<GCStatepointInst>(Statepoint);
735+
if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live))
724736
return *(Opt->Inputs.begin() + getDerivedPtrIndex());
725-
return *(getStatepoint()->arg_begin() + getDerivedPtrIndex());
737+
return *(GCInst->arg_begin() + getDerivedPtrIndex());
726738
}

llvm/lib/IR/Verifier.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5156,14 +5156,13 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
51565156
// In all other cases relocate should be tied to the statepoint directly.
51575157
// This covers relocates on a normal return path of invoke statepoint and
51585158
// relocates of a call statepoint.
5159-
auto Token = Call.getArgOperand(0);
5160-
Check(isa<GCStatepointInst>(Token),
5159+
auto *Token = Call.getArgOperand(0);
5160+
Check(isa<GCStatepointInst>(Token) || isa<UndefValue>(Token),
51615161
"gc relocate is incorrectly tied to the statepoint", Call, Token);
51625162
}
51635163

51645164
// Verify rest of the relocate arguments.
5165-
const CallBase &StatepointCall =
5166-
*cast<GCRelocateInst>(Call).getStatepoint();
5165+
const Value &StatepointCall = *cast<GCRelocateInst>(Call).getStatepoint();
51675166

51685167
// Both the base and derived must be piped through the safepoint.
51695168
Value *Base = Call.getArgOperand(1);
@@ -5178,7 +5177,10 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
51785177
const uint64_t DerivedIndex = cast<ConstantInt>(Derived)->getZExtValue();
51795178

51805179
// Check the bounds
5181-
if (auto Opt = StatepointCall.getOperandBundle(LLVMContext::OB_gc_live)) {
5180+
if (isa<UndefValue>(StatepointCall))
5181+
break;
5182+
if (auto Opt = cast<GCStatepointInst>(StatepointCall)
5183+
.getOperandBundle(LLVMContext::OB_gc_live)) {
51825184
Check(BaseIndex < Opt->Inputs.size(),
51835185
"gc.relocate: statepoint base index out of bounds", Call);
51845186
Check(DerivedIndex < Opt->Inputs.size(),
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; RUN: opt -S -passes=verify < %s | FileCheck %s
2+
3+
target triple = "x86_64-unknown-linux-gnu"
4+
5+
define i32 @check_verify_undef_token() gc "statepoint-example" {
6+
7+
entry:
8+
; CHECK: ret i32 0
9+
ret i32 0
10+
11+
unreach:
12+
; CHECK: token undef
13+
%token_call = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token undef, i32 0, i32 0)
14+
ret i32 1
15+
}
16+
17+
declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32)

0 commit comments

Comments
 (0)