[llvm] [SandboxIR] Implement UndefValue (PR #107628)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 6 12:59:30 PDT 2024
https://github.com/vporpo updated https://github.com/llvm/llvm-project/pull/107628
>From 197dad40c0f702869ee4aeda5ffdcc1170fcd686 Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Wed, 21 Aug 2024 15:04:45 -0700
Subject: [PATCH 1/2] [SandboxIR] Implement UndefValue
This patch implements sandboxir::UndefValue mirroring llvm::UndefValue.
---
llvm/include/llvm/SandboxIR/SandboxIR.h | 58 +++++++++++++++++-
.../llvm/SandboxIR/SandboxIRValues.def | 1 +
llvm/lib/SandboxIR/SandboxIR.cpp | 30 ++++++++++
llvm/unittests/SandboxIR/SandboxIRTest.cpp | 59 +++++++++++++++++++
4 files changed, 145 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index bede697670a281..ebbb82cf81b392 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -321,6 +321,7 @@ class Value {
friend class ConstantStruct; // For `Val`.
friend class ConstantAggregateZero; // For `Val`.
friend class ConstantPointerNull; // For `Val`.
+ friend class UndefValue; // For `Val`.
friend class PoisonValue; // For `Val`.
/// All values point to the context.
@@ -1020,10 +1021,61 @@ class ConstantPointerNull final : public Constant {
#endif
};
-// TODO: Inherit from UndefValue.
-class PoisonValue final : public Constant {
+// TODO: Inherit from ConstantData.
+class UndefValue : public Constant {
+protected:
+ UndefValue(llvm::UndefValue *C, Context &Ctx)
+ : Constant(ClassID::UndefValue, C, Ctx) {}
+ UndefValue(ClassID ID, llvm::Constant *C, Context &Ctx)
+ : Constant(ID, C, Ctx) {}
+ friend class Context; // For constructor.
+
+public:
+ /// Static factory methods - Return an 'undef' object of the specified type.
+ static UndefValue *get(Type *T);
+
+ /// If this Undef has array or vector type, return a undef with the right
+ /// element type.
+ UndefValue *getSequentialElement() const;
+
+ /// If this undef has struct type, return a undef with the right element type
+ /// for the specified element.
+ UndefValue *getStructElement(unsigned Elt) const;
+
+ /// Return an undef of the right value for the specified GEP index if we can,
+ /// otherwise return null (e.g. if C is a ConstantExpr).
+ UndefValue *getElementValue(Constant *C) const;
+
+ /// Return an undef of the right value for the specified GEP index.
+ UndefValue *getElementValue(unsigned Idx) const;
+
+ /// Return the number of elements in the array, vector, or struct.
+ unsigned getNumElements() const {
+ return cast<llvm::UndefValue>(Val)->getNumElements();
+ }
+
+ /// For isa/dyn_cast.
+ static bool classof(const sandboxir::Value *From) {
+ return From->getSubclassID() == ClassID::UndefValue ||
+ From->getSubclassID() == ClassID::PoisonValue;
+ }
+ unsigned getUseOperandNo(const Use &Use) const final {
+ llvm_unreachable("UndefValue has no operands!");
+ }
+#ifndef NDEBUG
+ void verify() const override {
+ assert(isa<llvm::UndefValue>(Val) && "Expected an UndefValue!");
+ }
+ void dumpOS(raw_ostream &OS) const override {
+ dumpCommonPrefix(OS);
+ dumpCommonSuffix(OS);
+ }
+#endif
+};
+
+class PoisonValue final : public UndefValue {
PoisonValue(llvm::PoisonValue *C, Context &Ctx)
- : Constant(ClassID::PoisonValue, C, Ctx) {}
+ : UndefValue(ClassID::PoisonValue, C, Ctx) {}
friend class Context; // For constructor.
public:
diff --git a/llvm/include/llvm/SandboxIR/SandboxIRValues.def b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
index 5acf7bfe08f5ae..459226216703d9 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIRValues.def
+++ b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
@@ -32,6 +32,7 @@ DEF_CONST(ConstantStruct, ConstantStruct)
DEF_CONST(ConstantVector, ConstantVector)
DEF_CONST(ConstantAggregateZero, ConstantAggregateZero)
DEF_CONST(ConstantPointerNull, ConstantPointerNull)
+DEF_CONST(UndefValue, UndefValue)
DEF_CONST(PoisonValue, PoisonValue)
#ifndef DEF_INSTR
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index 4ba3ab7a0ce43b..07472d1bff47be 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -2437,6 +2437,32 @@ PointerType *ConstantPointerNull::getType() const {
Ctx.getType(cast<llvm::ConstantPointerNull>(Val)->getType()));
}
+UndefValue *UndefValue::get(Type *T) {
+ auto *LLVMC = llvm::UndefValue::get(T->LLVMTy);
+ return cast<UndefValue>(T->getContext().getOrCreateConstant(LLVMC));
+}
+
+UndefValue *UndefValue::getSequentialElement() const {
+ return cast<UndefValue>(Ctx.getOrCreateConstant(
+ cast<llvm::UndefValue>(Val)->getSequentialElement()));
+}
+
+UndefValue *UndefValue::getStructElement(unsigned Elt) const {
+ return cast<UndefValue>(Ctx.getOrCreateConstant(
+ cast<llvm::UndefValue>(Val)->getStructElement(Elt)));
+}
+
+UndefValue *UndefValue::getElementValue(Constant *C) const {
+ return cast<UndefValue>(
+ Ctx.getOrCreateConstant(cast<llvm::UndefValue>(Val)->getElementValue(
+ cast<llvm::Constant>(C->Val))));
+}
+
+UndefValue *UndefValue::getElementValue(unsigned Idx) const {
+ return cast<UndefValue>(Ctx.getOrCreateConstant(
+ cast<llvm::UndefValue>(Val)->getElementValue(Idx)));
+}
+
PoisonValue *PoisonValue::get(Type *T) {
auto *LLVMC = llvm::PoisonValue::get(T->LLVMTy);
return cast<PoisonValue>(T->getContext().getOrCreateConstant(LLVMC));
@@ -2580,6 +2606,10 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
It->second = std::unique_ptr<PoisonValue>(
new PoisonValue(cast<llvm::PoisonValue>(C), *this));
return It->second.get();
+ case llvm::Value::UndefValueVal:
+ It->second = std::unique_ptr<UndefValue>(
+ new UndefValue(cast<llvm::UndefValue>(C), *this));
+ return It->second.get();
case llvm::Value::ConstantArrayVal:
It->second = std::unique_ptr<ConstantArray>(
new ConstantArray(cast<llvm::ConstantArray>(C), *this));
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index 1c0b9f83ab629a..1b939b4d047aaf 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -642,6 +642,7 @@ define void @foo() {
// Check classof() and creation.
auto *Poison = cast<sandboxir::PoisonValue>(I0->getOperand(0));
EXPECT_EQ(Poison->getType(), Int32Ty);
+ EXPECT_TRUE(isa<sandboxir::UndefValue>(Poison)); // Poison is Undef
// Check get().
auto *NewPoison = sandboxir::PoisonValue::get(Int32Ty);
EXPECT_EQ(NewPoison, Poison);
@@ -670,6 +671,64 @@ define void @foo() {
sandboxir::PoisonValue::get(Int8Ty));
}
+TEST_F(SandboxIRTest, UndefValue) {
+ parseIR(C, R"IR(
+define void @foo() {
+ %i0 = add i32 undef, undef
+ %i1 = add <2 x i32> undef, undef
+ %i2 = extractvalue {i32, i8} undef, 0
+ ret void
+}
+)IR");
+ Function &LLVMF = *M->getFunction("foo");
+ sandboxir::Context Ctx(C);
+
+ auto &F = *Ctx.createFunction(&LLVMF);
+ auto &BB = *F.begin();
+ auto It = BB.begin();
+ auto *I0 = &*It++;
+ auto *I1 = &*It++;
+ auto *I2 = &*It++;
+ auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx);
+ auto *Int8Ty = sandboxir::Type::getInt8Ty(Ctx);
+ auto *Zero32 = sandboxir::ConstantInt::get(Int32Ty, 0u);
+ auto *One32 = sandboxir::ConstantInt::get(Int32Ty, 1u);
+
+ // Check classof() and creation.
+ auto *Undef = cast<sandboxir::UndefValue>(I0->getOperand(0));
+ EXPECT_EQ(Undef->getType(), Int32Ty);
+ EXPECT_FALSE(isa<sandboxir::PoisonValue>(Undef)); // Undef is not Poison
+ // Check get().
+ auto *NewUndef = sandboxir::UndefValue::get(Int32Ty);
+ EXPECT_EQ(NewUndef, Undef);
+ auto *NewUndef2 =
+ sandboxir::UndefValue::get(sandboxir::PointerType::get(Ctx, 0u));
+ EXPECT_NE(NewUndef2, Undef);
+ // Check getSequentialElement().
+ auto *UndefVector = cast<sandboxir::UndefValue>(I1->getOperand(0));
+ auto *SeqElm = UndefVector->getSequentialElement();
+ EXPECT_EQ(SeqElm->getType(), Int32Ty);
+ // Check getStructElement().
+ auto *UndefStruct = cast<sandboxir::UndefValue>(I2->getOperand(0));
+ auto *StrElm0 = UndefStruct->getStructElement(0);
+ auto *StrElm1 = UndefStruct->getStructElement(1);
+ EXPECT_EQ(StrElm0->getType(), Int32Ty);
+ EXPECT_EQ(StrElm1->getType(), Int8Ty);
+ // Check getElementValue(Constant)
+ EXPECT_EQ(UndefStruct->getElementValue(Zero32),
+ sandboxir::UndefValue::get(Int32Ty));
+ EXPECT_EQ(UndefStruct->getElementValue(One32),
+ sandboxir::UndefValue::get(Int8Ty));
+ // Check getElementValue(unsigned)
+ EXPECT_EQ(UndefStruct->getElementValue(0u),
+ sandboxir::UndefValue::get(Int32Ty));
+ EXPECT_EQ(UndefStruct->getElementValue(1u),
+ sandboxir::UndefValue::get(Int8Ty));
+ // Check getNumElements().
+ EXPECT_EQ(UndefVector->getNumElements(), 2u);
+ EXPECT_EQ(UndefStruct->getNumElements(), 2u);
+}
+
TEST_F(SandboxIRTest, Use) {
parseIR(C, R"IR(
define i32 @foo(i32 %v0, i32 %v1) {
>From 245533f0657cbb20b830d852ca2ac6cfefe336a2 Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Fri, 6 Sep 2024 12:58:56 -0700
Subject: [PATCH 2/2] fixup! [SandboxIR] Implement UndefValue
---
llvm/include/llvm/SandboxIR/SandboxIR.h | 3 ---
1 file changed, 3 deletions(-)
diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index ebbb82cf81b392..8f025f7257b39f 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -1101,9 +1101,6 @@ class PoisonValue final : public UndefValue {
static bool classof(const sandboxir::Value *From) {
return From->getSubclassID() == ClassID::PoisonValue;
}
- unsigned getUseOperandNo(const Use &Use) const final {
- llvm_unreachable("PoisonValue has no operands!");
- }
#ifndef NDEBUG
void verify() const override {
assert(isa<llvm::PoisonValue>(Val) && "Expected a PoisonValue!");
More information about the llvm-commits
mailing list