[llvm] [SandboxVec][LoadStoreVec] Support constant vectors of mixed types (PR #224890)

Vasileios Porpodas via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 21 14:51:31 PDT 2026


================
@@ -82,42 +83,108 @@ LoadInst *LoadStoreVec::createVectorLoad(BndlRef<Instruction *> Loads) {
   return LoadInst::create(Ty, LdPtr, LdAlign, LdWhereIt, *Ctx, "VecIinitL");
 }
 
-Value *LoadStoreVec::createConstantVector(BndlRef<Value *> Operands) {
-  SmallVector<Constant *, 8> Constants;
-  Constants.reserve(Operands.size());
+Constant *LoadStoreVec::createEquivalentConstantWithType(Constant *C,
+                                                         Type *DestTy) {
+  Type *SrcTy = C->getType();
+  if (SrcTy == DestTy)
+    return C;
+  auto IsNonIntegralPtr = [this](Type *Ty) {
+    return Ty->isPointerTy() &&
+           DL->isNonIntegralAddressSpace(Ty->getPointerAddressSpace());
+  };
+  if (IsNonIntegralPtr(SrcTy) || IsNonIntegralPtr(DestTy))
+    return nullptr;
+
+  Constant *AsInt = C;
+  if (!SrcTy->isIntegerTy()) {
+    Type *IntTy = IntegerType::get(*Ctx, Utils::getNumBits(SrcTy, *DL));
+    AsInt = SrcTy->isPointerTy() ? ConstantExpr::getPtrToInt(C, IntTy)
+                                 : ConstantExpr::getBitCast(C, IntTy);
+  }
+  if (DestTy->isIntegerTy())
+    return AsInt;
+  return DestTy->isPointerTy() ? ConstantExpr::getIntToPtr(AsInt, DestTy)
+                               : ConstantExpr::getBitCast(AsInt, DestTy);
+}
+
+Value *LoadStoreVec::createConstantVector(ArrayRef<Value *> Operands,
+                                          Type *LaneTy) {
+  SmallVector<Constant *, 8> ConstantElements;
+  ConstantElements.reserve(Operands.size());
   for (Value *Op : Operands) {
     auto *COp = cast<Constant>(Op);
     if (auto *AggrCOp = dyn_cast<ConstantAggregate>(COp)) {
       // If the operand is a constant aggregate, then append all its elements.
       for (Value *Elm : AggrCOp->operands())
-        Constants.push_back(cast<Constant>(Elm));
+        ConstantElements.push_back(cast<Constant>(Elm));
     } else if (auto *SeqCOp = dyn_cast<ConstantDataSequential>(COp)) {
       for (auto ElmIdx : seq<unsigned>(SeqCOp->getNumElements()))
-        Constants.push_back(SeqCOp->getElementAsConstant(ElmIdx));
+        ConstantElements.push_back(SeqCOp->getElementAsConstant(ElmIdx));
     } else if (auto *Zero = dyn_cast<ConstantAggregateZero>(COp)) {
       auto *ZeroElm = Zero->getSequentialElement();
       for ([[maybe_unused]] auto Cnt :
            seq<unsigned>(Zero->getElementCount().getFixedValue()))
-        Constants.push_back(ZeroElm);
+        ConstantElements.push_back(ZeroElm);
     } else if (isa<ConstantInt>(COp) && isa<VectorType>(COp->getType())) {
       auto *Elm = ConstantInt::get(*Ctx, cast<ConstantInt>(COp)->getValue());
       for ([[maybe_unused]] auto Cnt :
            seq<unsigned>(cast<VectorType>(COp->getType())
                              ->getElementCount()
                              .getFixedValue()))
-        Constants.push_back(Elm);
+        ConstantElements.push_back(Elm);
     } else if (isa<ConstantFP>(COp) && isa<VectorType>(COp->getType())) {
       auto *Elm = ConstantFP::get(cast<ConstantFP>(COp)->getValue(), *Ctx);
       for ([[maybe_unused]] auto Cnt :
            seq<unsigned>(cast<VectorType>(COp->getType())
                              ->getElementCount()
                              .getFixedValue()))
-        Constants.push_back(Elm);
+        ConstantElements.push_back(Elm);
+    } else if (isa<VectorType>(COp->getType())) {
+      // TODO: Flatten the remaining vector constants, e.g. undef or poison.
+      return nullptr;
     } else {
-      Constants.push_back(COp);
+      ConstantElements.push_back(COp);
     }
   }
-  return ConstantVector::get(Constants);
+
+  // Stores may mix types, e.g. i32 and float. Convert each constant to LaneTy.
+  // A wider constant is split into multiple LaneTy-sized pieces, in memory
+  // order.
+  unsigned LaneBits = Utils::getNumBits(LaneTy, *DL);
+  SmallVector<Constant *, 8> ConstantLanes;
+  ConstantLanes.reserve(ConstantElements.size());
+  for (Constant *C : ConstantElements) {
+    unsigned Bits = Utils::getNumBits(C->getType(), *DL);
+    if (Bits == LaneBits) {
+      Constant *Lane = createEquivalentConstantWithType(C, LaneTy);
+      if (Lane == nullptr)
+        return nullptr;
+      ConstantLanes.push_back(Lane);
+    } else if (Bits > LaneBits && Bits % LaneBits == 0) {
+      // Only integer bit patterns can be split, so this bails out on constants
+      // like the address of a global.
+      auto *CI = dyn_cast_or_null<ConstantInt>(
+          createEquivalentConstantWithType(C, IntegerType::get(*Ctx, Bits)));
+      if (CI == nullptr)
+        return nullptr;
+      const APInt &Val = CI->getValue();
+      unsigned NumLanes = Bits / LaneBits;
+      for (unsigned Idx : seq<unsigned>(NumLanes)) {
+        unsigned Part = DL->isLittleEndian() ? Idx : NumLanes - 1 - Idx;
----------------
vporpo wrote:

EnidanAwareSlice  instead of Part ?

https://github.com/llvm/llvm-project/pull/224890


More information about the llvm-commits mailing list