Skip to content

[SandboxIR] Implement ConstantDataArray functions #134729

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 66 additions & 1 deletion llvm/include/llvm/SandboxIR/Constant.h
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,72 @@ class ConstantDataArray final : public ConstantDataSequential {
friend class Context;

public:
// TODO: Add missing functions.
static bool classof(const Value *From) {
return From->getSubclassID() == ClassID::ConstantDataArray;
}
/// get() constructor - Return a constant with array type with an element
/// count and element type matching the ArrayRef passed in. Note that this
/// can return a ConstantAggregateZero object.
template <typename ElementTy>
static Constant *get(Context &Ctx, ArrayRef<ElementTy> Elts) {
auto *NewLLVMC = llvm::ConstantDataArray::get(Ctx.LLVMCtx, Elts);
return Ctx.getOrCreateConstant(NewLLVMC);
}

/// get() constructor - ArrayTy needs to be compatible with
/// ArrayRef<ElementTy>.
template <typename ArrayTy>
static Constant *get(Context &Ctx, ArrayTy &Elts) {
return ConstantDataArray::get(Ctx, ArrayRef(Elts));
}

/// getRaw() constructor - Return a constant with array type with an element
/// count and element type matching the NumElements and ElementTy parameters
/// passed in. Note that this can return a ConstantAggregateZero object.
/// ElementTy must be one of i8/i16/i32/i64/half/bfloat/float/double. Data is
/// the buffer containing the elements. Be careful to make sure Data uses the
/// right endianness, the buffer will be used as-is.
static Constant *getRaw(StringRef Data, uint64_t NumElements,
Type *ElementTy) {
auto *LLVMC =
llvm::ConstantDataArray::getRaw(Data, NumElements, ElementTy->LLVMTy);
return ElementTy->getContext().getOrCreateConstant(LLVMC);
}
/// getFP() constructors - Return a constant of array type with a float
/// element type taken from argument `ElementType', and count taken from
/// argument `Elts'. The amount of bits of the contained type must match the
/// number of bits of the type contained in the passed in ArrayRef.
/// (i.e. half or bfloat for 16bits, float for 32bits, double for 64bits) Note
/// that this can return a ConstantAggregateZero object.
static Constant *getFP(Type *ElementType, ArrayRef<uint16_t> Elts) {
auto *LLVMC = llvm::ConstantDataArray::getFP(ElementType->LLVMTy, Elts);
return ElementType->getContext().getOrCreateConstant(LLVMC);
}
static Constant *getFP(Type *ElementType, ArrayRef<uint32_t> Elts) {
auto *LLVMC = llvm::ConstantDataArray::getFP(ElementType->LLVMTy, Elts);
return ElementType->getContext().getOrCreateConstant(LLVMC);
}
static Constant *getFP(Type *ElementType, ArrayRef<uint64_t> Elts) {
auto *LLVMC = llvm::ConstantDataArray::getFP(ElementType->LLVMTy, Elts);
return ElementType->getContext().getOrCreateConstant(LLVMC);
}
/// This method constructs a CDS and initializes it with a text string.
/// The default behavior (AddNull==true) causes a null terminator to
/// be placed at the end of the array (increasing the length of the string by
/// one more than the StringRef would normally indicate. Pass AddNull=false
/// to disable this behavior.
static Constant *getString(Context &Ctx, StringRef Initializer,
bool AddNull = true) {
auto *LLVMC =
llvm::ConstantDataArray::getString(Ctx.LLVMCtx, Initializer, AddNull);
return Ctx.getOrCreateConstant(LLVMC);
}

/// Specialize the getType() method to always return an ArrayType,
/// which reduces the amount of casting needed in parts of the compiler.
inline ArrayType *getType() const {
return cast<ArrayType>(Value::getType());
}
};

/// A vector constant whose element type is a simple 1/2/4/8-byte integer or
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/SandboxIR/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ class Type {
static Type *getInt1Ty(Context &Ctx);
static Type *getDoubleTy(Context &Ctx);
static Type *getFloatTy(Context &Ctx);
static Type *getHalfTy(Context &Ctx);
// TODO: missing get*

/// Get the address space of this pointer or pointer vector type.
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/SandboxIR/Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ class Value {
// expose metadata in sandboxir.
friend class Region;
friend class ScoreBoard; // Needs access to `Val` for the instruction cost.
friend class ConstantDataArray; // For `Val`

/// All values point to the context.
Context &Ctx;
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/SandboxIR/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ Type *Type::getDoubleTy(Context &Ctx) {
Type *Type::getFloatTy(Context &Ctx) {
return Ctx.getType(llvm::Type::getFloatTy(Ctx.LLVMCtx));
}
Type *Type::getHalfTy(Context &Ctx) {
return Ctx.getType(llvm::Type::getHalfTy(Ctx.LLVMCtx));
}

#ifndef NDEBUG
void Type::dumpOS(raw_ostream &OS) { LLVMTy->print(OS); }
Expand Down
51 changes: 49 additions & 2 deletions llvm/unittests/SandboxIR/SandboxIRTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,10 @@ define void @foo(i32 %v0) {

TEST_F(SandboxIRTest, ConstantFP) {
parseIR(C, R"IR(
define void @foo(float %v0, double %v1) {
define void @foo(float %v0, double %v1, half %v2) {
%fadd0 = fadd float %v0, 42.0
%fadd1 = fadd double %v1, 43.0
%fadd2 = fadd half %v2, 44.0
ret void
}
)IR");
Expand All @@ -312,12 +313,16 @@ define void @foo(float %v0, double %v1) {
auto It = BB.begin();
auto *FAdd0 = cast<sandboxir::BinaryOperator>(&*It++);
auto *FAdd1 = cast<sandboxir::BinaryOperator>(&*It++);
auto *FAdd2 = cast<sandboxir::BinaryOperator>(&*It++);
auto *FortyTwo = cast<sandboxir::ConstantFP>(FAdd0->getOperand(1));
[[maybe_unused]] auto *FortyThree =
cast<sandboxir::ConstantFP>(FAdd1->getOperand(1));

auto *FloatTy = sandboxir::Type::getFloatTy(Ctx);
auto *DoubleTy = sandboxir::Type::getDoubleTy(Ctx);
auto *HalfTy = sandboxir::Type::getHalfTy(Ctx);
EXPECT_EQ(HalfTy, Ctx.getType(llvm::Type::getHalfTy(C)));
EXPECT_EQ(FAdd2->getType(), HalfTy);
auto *LLVMFloatTy = Type::getFloatTy(C);
auto *LLVMDoubleTy = Type::getDoubleTy(C);
// Check that creating an identical constant gives us the same object.
Expand Down Expand Up @@ -616,6 +621,7 @@ define void @foo() {
%farray = extractvalue [2 x float] [float 0.0, float 1.0], 0
%fvector = extractelement <2 x double> <double 0.0, double 1.0>, i32 0
%string = extractvalue [6 x i8] [i8 72, i8 69, i8 76, i8 76, i8 79, i8 0], 0
%stringNoNull = extractvalue [5 x i8] [i8 72, i8 69, i8 76, i8 76, i8 79], 0
ret void
}
)IR");
Expand All @@ -630,16 +636,19 @@ define void @foo() {
auto *I2 = &*It++;
auto *I3 = &*It++;
auto *I4 = &*It++;
auto *I5 = &*It++;
auto *Array = cast<sandboxir::ConstantDataArray>(I0->getOperand(0));
EXPECT_TRUE(isa<sandboxir::ConstantDataSequential>(Array));
auto *Vector = cast<sandboxir::ConstantDataVector>(I1->getOperand(0));
EXPECT_TRUE(isa<sandboxir::ConstantDataVector>(Vector));
auto *FArray = cast<sandboxir::ConstantDataArray>(I2->getOperand(0));
EXPECT_TRUE(isa<sandboxir::ConstantDataSequential>(FArray));
auto *FVector = cast<sandboxir::ConstantDataArray>(I3->getOperand(0));
auto *FVector = cast<sandboxir::ConstantDataVector>(I3->getOperand(0));
EXPECT_TRUE(isa<sandboxir::ConstantDataVector>(FVector));
auto *String = cast<sandboxir::ConstantDataArray>(I4->getOperand(0));
EXPECT_TRUE(isa<sandboxir::ConstantDataArray>(String));
auto *StringNoNull = cast<sandboxir::ConstantDataArray>(I5->getOperand(0));
EXPECT_TRUE(isa<sandboxir::ConstantDataArray>(StringNoNull));

auto *Zero8 = sandboxir::ConstantInt::get(sandboxir::Type::getInt8Ty(Ctx), 0);
auto *One8 = sandboxir::ConstantInt::get(sandboxir::Type::getInt8Ty(Ctx), 1);
Expand Down Expand Up @@ -706,6 +715,44 @@ define void @foo() {
EXPECT_EQ(String->getAsCString(), "HELLO");
// Check getRawDataValues().
EXPECT_EQ(String->getRawDataValues(), HelloWithNull);

// Check ConstantDataArray member functions
// ----------------------------------------
// Check get<ElementTy>().
EXPECT_EQ(sandboxir::ConstantDataArray::get<char>(Ctx, {0, 1}), Array);
// Check get<ArrayTy>().
SmallVector<char> Elmts({0, 1});
EXPECT_EQ(sandboxir::ConstantDataArray::get<SmallVector<char>>(Ctx, Elmts),
Array);
// Check getRaw().
EXPECT_EQ(sandboxir::ConstantDataArray::getRaw(StringRef("HELLO"), 5,
Zero8->getType()),
StringNoNull);
// Check getFP().
SmallVector<uint16_t> Elts16({42, 43});
SmallVector<uint32_t> Elts32({42, 43});
SmallVector<uint64_t> Elts64({42, 43});
auto *F16Ty = sandboxir::Type::getHalfTy(Ctx);
auto *F32Ty = sandboxir::Type::getFloatTy(Ctx);
auto *F64Ty = sandboxir::Type::getDoubleTy(Ctx);

auto *CDA16 = sandboxir::ConstantDataArray::getFP(F16Ty, Elts16);
EXPECT_EQ(CDA16, cast<sandboxir::ConstantDataArray>(
Ctx.getValue(llvm::ConstantDataArray::getFP(
llvm::Type::getHalfTy(C), Elts16))));
auto *CDA32 = sandboxir::ConstantDataArray::getFP(F32Ty, Elts32);
EXPECT_EQ(CDA32, cast<sandboxir::ConstantDataArray>(
Ctx.getValue(llvm::ConstantDataArray::getFP(
llvm::Type::getFloatTy(C), Elts32))));
auto *CDA64 = sandboxir::ConstantDataArray::getFP(F64Ty, Elts64);
EXPECT_EQ(CDA64, cast<sandboxir::ConstantDataArray>(
Ctx.getValue(llvm::ConstantDataArray::getFP(
llvm::Type::getDoubleTy(C), Elts64))));
// Check getString().
EXPECT_EQ(sandboxir::ConstantDataArray::getString(Ctx, "HELLO"), String);
EXPECT_EQ(sandboxir::ConstantDataArray::getString(Ctx, "HELLO",
/*AddNull=*/false),
StringNoNull);
}

TEST_F(SandboxIRTest, ConstantPointerNull) {
Expand Down