Skip to content

Commit ae02211

Browse files
authored
[SandboxIR] Implement UndefValue (#107628)
This patch implements sandboxir::UndefValue mirroring llvm::UndefValue.
1 parent 33c1325 commit ae02211

File tree

4 files changed

+145
-6
lines changed

4 files changed

+145
-6
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ class Value {
321321
friend class ConstantStruct; // For `Val`.
322322
friend class ConstantAggregateZero; // For `Val`.
323323
friend class ConstantPointerNull; // For `Val`.
324+
friend class UndefValue; // For `Val`.
324325
friend class PoisonValue; // For `Val`.
325326

326327
/// All values point to the context.
@@ -1020,10 +1021,61 @@ class ConstantPointerNull final : public Constant {
10201021
#endif
10211022
};
10221023

1023-
// TODO: Inherit from UndefValue.
1024-
class PoisonValue final : public Constant {
1024+
// TODO: Inherit from ConstantData.
1025+
class UndefValue : public Constant {
1026+
protected:
1027+
UndefValue(llvm::UndefValue *C, Context &Ctx)
1028+
: Constant(ClassID::UndefValue, C, Ctx) {}
1029+
UndefValue(ClassID ID, llvm::Constant *C, Context &Ctx)
1030+
: Constant(ID, C, Ctx) {}
1031+
friend class Context; // For constructor.
1032+
1033+
public:
1034+
/// Static factory methods - Return an 'undef' object of the specified type.
1035+
static UndefValue *get(Type *T);
1036+
1037+
/// If this Undef has array or vector type, return a undef with the right
1038+
/// element type.
1039+
UndefValue *getSequentialElement() const;
1040+
1041+
/// If this undef has struct type, return a undef with the right element type
1042+
/// for the specified element.
1043+
UndefValue *getStructElement(unsigned Elt) const;
1044+
1045+
/// Return an undef of the right value for the specified GEP index if we can,
1046+
/// otherwise return null (e.g. if C is a ConstantExpr).
1047+
UndefValue *getElementValue(Constant *C) const;
1048+
1049+
/// Return an undef of the right value for the specified GEP index.
1050+
UndefValue *getElementValue(unsigned Idx) const;
1051+
1052+
/// Return the number of elements in the array, vector, or struct.
1053+
unsigned getNumElements() const {
1054+
return cast<llvm::UndefValue>(Val)->getNumElements();
1055+
}
1056+
1057+
/// For isa/dyn_cast.
1058+
static bool classof(const sandboxir::Value *From) {
1059+
return From->getSubclassID() == ClassID::UndefValue ||
1060+
From->getSubclassID() == ClassID::PoisonValue;
1061+
}
1062+
unsigned getUseOperandNo(const Use &Use) const final {
1063+
llvm_unreachable("UndefValue has no operands!");
1064+
}
1065+
#ifndef NDEBUG
1066+
void verify() const override {
1067+
assert(isa<llvm::UndefValue>(Val) && "Expected an UndefValue!");
1068+
}
1069+
void dumpOS(raw_ostream &OS) const override {
1070+
dumpCommonPrefix(OS);
1071+
dumpCommonSuffix(OS);
1072+
}
1073+
#endif
1074+
};
1075+
1076+
class PoisonValue final : public UndefValue {
10251077
PoisonValue(llvm::PoisonValue *C, Context &Ctx)
1026-
: Constant(ClassID::PoisonValue, C, Ctx) {}
1078+
: UndefValue(ClassID::PoisonValue, C, Ctx) {}
10271079
friend class Context; // For constructor.
10281080

10291081
public:
@@ -1049,9 +1101,6 @@ class PoisonValue final : public Constant {
10491101
static bool classof(const sandboxir::Value *From) {
10501102
return From->getSubclassID() == ClassID::PoisonValue;
10511103
}
1052-
unsigned getUseOperandNo(const Use &Use) const final {
1053-
llvm_unreachable("PoisonValue has no operands!");
1054-
}
10551104
#ifndef NDEBUG
10561105
void verify() const override {
10571106
assert(isa<llvm::PoisonValue>(Val) && "Expected a PoisonValue!");

llvm/include/llvm/SandboxIR/SandboxIRValues.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ DEF_CONST(ConstantStruct, ConstantStruct)
3232
DEF_CONST(ConstantVector, ConstantVector)
3333
DEF_CONST(ConstantAggregateZero, ConstantAggregateZero)
3434
DEF_CONST(ConstantPointerNull, ConstantPointerNull)
35+
DEF_CONST(UndefValue, UndefValue)
3536
DEF_CONST(PoisonValue, PoisonValue)
3637

3738
#ifndef DEF_INSTR

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2437,6 +2437,32 @@ PointerType *ConstantPointerNull::getType() const {
24372437
Ctx.getType(cast<llvm::ConstantPointerNull>(Val)->getType()));
24382438
}
24392439

2440+
UndefValue *UndefValue::get(Type *T) {
2441+
auto *LLVMC = llvm::UndefValue::get(T->LLVMTy);
2442+
return cast<UndefValue>(T->getContext().getOrCreateConstant(LLVMC));
2443+
}
2444+
2445+
UndefValue *UndefValue::getSequentialElement() const {
2446+
return cast<UndefValue>(Ctx.getOrCreateConstant(
2447+
cast<llvm::UndefValue>(Val)->getSequentialElement()));
2448+
}
2449+
2450+
UndefValue *UndefValue::getStructElement(unsigned Elt) const {
2451+
return cast<UndefValue>(Ctx.getOrCreateConstant(
2452+
cast<llvm::UndefValue>(Val)->getStructElement(Elt)));
2453+
}
2454+
2455+
UndefValue *UndefValue::getElementValue(Constant *C) const {
2456+
return cast<UndefValue>(
2457+
Ctx.getOrCreateConstant(cast<llvm::UndefValue>(Val)->getElementValue(
2458+
cast<llvm::Constant>(C->Val))));
2459+
}
2460+
2461+
UndefValue *UndefValue::getElementValue(unsigned Idx) const {
2462+
return cast<UndefValue>(Ctx.getOrCreateConstant(
2463+
cast<llvm::UndefValue>(Val)->getElementValue(Idx)));
2464+
}
2465+
24402466
PoisonValue *PoisonValue::get(Type *T) {
24412467
auto *LLVMC = llvm::PoisonValue::get(T->LLVMTy);
24422468
return cast<PoisonValue>(T->getContext().getOrCreateConstant(LLVMC));
@@ -2580,6 +2606,10 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
25802606
It->second = std::unique_ptr<PoisonValue>(
25812607
new PoisonValue(cast<llvm::PoisonValue>(C), *this));
25822608
return It->second.get();
2609+
case llvm::Value::UndefValueVal:
2610+
It->second = std::unique_ptr<UndefValue>(
2611+
new UndefValue(cast<llvm::UndefValue>(C), *this));
2612+
return It->second.get();
25832613
case llvm::Value::ConstantArrayVal:
25842614
It->second = std::unique_ptr<ConstantArray>(
25852615
new ConstantArray(cast<llvm::ConstantArray>(C), *this));

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,7 @@ define void @foo() {
642642
// Check classof() and creation.
643643
auto *Poison = cast<sandboxir::PoisonValue>(I0->getOperand(0));
644644
EXPECT_EQ(Poison->getType(), Int32Ty);
645+
EXPECT_TRUE(isa<sandboxir::UndefValue>(Poison)); // Poison is Undef
645646
// Check get().
646647
auto *NewPoison = sandboxir::PoisonValue::get(Int32Ty);
647648
EXPECT_EQ(NewPoison, Poison);
@@ -670,6 +671,64 @@ define void @foo() {
670671
sandboxir::PoisonValue::get(Int8Ty));
671672
}
672673

674+
TEST_F(SandboxIRTest, UndefValue) {
675+
parseIR(C, R"IR(
676+
define void @foo() {
677+
%i0 = add i32 undef, undef
678+
%i1 = add <2 x i32> undef, undef
679+
%i2 = extractvalue {i32, i8} undef, 0
680+
ret void
681+
}
682+
)IR");
683+
Function &LLVMF = *M->getFunction("foo");
684+
sandboxir::Context Ctx(C);
685+
686+
auto &F = *Ctx.createFunction(&LLVMF);
687+
auto &BB = *F.begin();
688+
auto It = BB.begin();
689+
auto *I0 = &*It++;
690+
auto *I1 = &*It++;
691+
auto *I2 = &*It++;
692+
auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx);
693+
auto *Int8Ty = sandboxir::Type::getInt8Ty(Ctx);
694+
auto *Zero32 = sandboxir::ConstantInt::get(Int32Ty, 0u);
695+
auto *One32 = sandboxir::ConstantInt::get(Int32Ty, 1u);
696+
697+
// Check classof() and creation.
698+
auto *Undef = cast<sandboxir::UndefValue>(I0->getOperand(0));
699+
EXPECT_EQ(Undef->getType(), Int32Ty);
700+
EXPECT_FALSE(isa<sandboxir::PoisonValue>(Undef)); // Undef is not Poison
701+
// Check get().
702+
auto *NewUndef = sandboxir::UndefValue::get(Int32Ty);
703+
EXPECT_EQ(NewUndef, Undef);
704+
auto *NewUndef2 =
705+
sandboxir::UndefValue::get(sandboxir::PointerType::get(Ctx, 0u));
706+
EXPECT_NE(NewUndef2, Undef);
707+
// Check getSequentialElement().
708+
auto *UndefVector = cast<sandboxir::UndefValue>(I1->getOperand(0));
709+
auto *SeqElm = UndefVector->getSequentialElement();
710+
EXPECT_EQ(SeqElm->getType(), Int32Ty);
711+
// Check getStructElement().
712+
auto *UndefStruct = cast<sandboxir::UndefValue>(I2->getOperand(0));
713+
auto *StrElm0 = UndefStruct->getStructElement(0);
714+
auto *StrElm1 = UndefStruct->getStructElement(1);
715+
EXPECT_EQ(StrElm0->getType(), Int32Ty);
716+
EXPECT_EQ(StrElm1->getType(), Int8Ty);
717+
// Check getElementValue(Constant)
718+
EXPECT_EQ(UndefStruct->getElementValue(Zero32),
719+
sandboxir::UndefValue::get(Int32Ty));
720+
EXPECT_EQ(UndefStruct->getElementValue(One32),
721+
sandboxir::UndefValue::get(Int8Ty));
722+
// Check getElementValue(unsigned)
723+
EXPECT_EQ(UndefStruct->getElementValue(0u),
724+
sandboxir::UndefValue::get(Int32Ty));
725+
EXPECT_EQ(UndefStruct->getElementValue(1u),
726+
sandboxir::UndefValue::get(Int8Ty));
727+
// Check getNumElements().
728+
EXPECT_EQ(UndefVector->getNumElements(), 2u);
729+
EXPECT_EQ(UndefStruct->getNumElements(), 2u);
730+
}
731+
673732
TEST_F(SandboxIRTest, Use) {
674733
parseIR(C, R"IR(
675734
define i32 @foo(i32 %v0, i32 %v1) {

0 commit comments

Comments
 (0)