[llvm] [SandboxIR] Implement ConstantDataArray functions (PR #134729)

via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 7 13:58:00 PDT 2025


https://github.com/vporpo created https://github.com/llvm/llvm-project/pull/134729

Mirrors LLVM IR.

>From ae0c9d3eaf72ba7c583748fc138ec676d01316cd Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Mon, 17 Mar 2025 10:12:52 -0700
Subject: [PATCH] [SandboxIR] Implement ConstantDataArray functions

Mirrors LLVM IR.
---
 llvm/include/llvm/SandboxIR/Constant.h     | 67 +++++++++++++++++++++-
 llvm/include/llvm/SandboxIR/Type.h         |  1 +
 llvm/include/llvm/SandboxIR/Value.h        |  1 +
 llvm/lib/SandboxIR/Type.cpp                |  3 +
 llvm/unittests/SandboxIR/SandboxIRTest.cpp | 50 +++++++++++++++-
 5 files changed, 119 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/SandboxIR/Constant.h b/llvm/include/llvm/SandboxIR/Constant.h
index ddd90291c509b..fa00b29dbd803 100644
--- a/llvm/include/llvm/SandboxIR/Constant.h
+++ b/llvm/include/llvm/SandboxIR/Constant.h
@@ -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
diff --git a/llvm/include/llvm/SandboxIR/Type.h b/llvm/include/llvm/SandboxIR/Type.h
index 7d90168c06576..4acd9260e5c19 100644
--- a/llvm/include/llvm/SandboxIR/Type.h
+++ b/llvm/include/llvm/SandboxIR/Type.h
@@ -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.
diff --git a/llvm/include/llvm/SandboxIR/Value.h b/llvm/include/llvm/SandboxIR/Value.h
index 508978709f96c..d45aa4059de69 100644
--- a/llvm/include/llvm/SandboxIR/Value.h
+++ b/llvm/include/llvm/SandboxIR/Value.h
@@ -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;
diff --git a/llvm/lib/SandboxIR/Type.cpp b/llvm/lib/SandboxIR/Type.cpp
index 51128bf307e9f..dfb54df0c9ce8 100644
--- a/llvm/lib/SandboxIR/Type.cpp
+++ b/llvm/lib/SandboxIR/Type.cpp
@@ -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); }
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index 690e9a521c168..3d9afd631ed10 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -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");
@@ -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.
@@ -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");
@@ -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);
@@ -706,6 +715,43 @@ 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);
+  EXPECT_EQ(
+      sandboxir::ConstantDataArray::getFP(F16Ty, Elts16),
+      cast<sandboxir::ConstantDataArray>(Ctx.getValue(
+          llvm::ConstantDataArray::getFP(llvm::Type::getHalfTy(C), Elts16))));
+  EXPECT_EQ(
+      sandboxir::ConstantDataArray::getFP(F32Ty, Elts32),
+      cast<sandboxir::ConstantDataArray>(Ctx.getValue(
+          llvm::ConstantDataArray::getFP(llvm::Type::getFloatTy(C), Elts32))));
+  EXPECT_EQ(
+      sandboxir::ConstantDataArray::getFP(F64Ty, Elts64),
+      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) {



More information about the llvm-commits mailing list