diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h --- a/llvm/include/llvm/IR/Instructions.h +++ b/llvm/include/llvm/IR/Instructions.h @@ -106,7 +106,7 @@ /// Get allocation size in bits. Returns None if size can't be determined, /// e.g. in case of a VLA. - Optional getAllocationSizeInBits(const DataLayout &DL) const; + Optional getAllocationSizeInBits(const DataLayout &DL) const; /// Return the type that is being allocated by the instruction. Type *getAllocatedType() const { return AllocatedType; } diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -49,13 +49,14 @@ // AllocaInst Class //===----------------------------------------------------------------------===// -Optional +Optional AllocaInst::getAllocationSizeInBits(const DataLayout &DL) const { - uint64_t Size = DL.getTypeAllocSizeInBits(getAllocatedType()); + TypeSize Size = DL.getTypeAllocSizeInBits(getAllocatedType()); if (isArrayAllocation()) { auto *C = dyn_cast(getArraySize()); if (!C) return None; + assert(!Size.isScalable() && "Array elements cannot have a scalable size"); Size *= C->getZExtValue(); } return Size; diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -576,9 +576,10 @@ StackLifetimeAnalyzer.getLiveRange(AI2)); }; auto GetAllocaSize = [&](const AllocaInfo &A) { - Optional RetSize = A.Alloca->getAllocationSizeInBits(DL); - assert(RetSize && "We can't handle scalable type now.\n"); - return RetSize.getValue(); + Optional RetSize = A.Alloca->getAllocationSizeInBits(DL); + assert(RetSize && "Variable Length Arrays (VLA) are not supported.\n"); + assert(!RetSize->isScalable() && "Scalable vectors are not yet supported"); + return RetSize->getFixedSize(); }; // Put larger allocas in the front. So the larger allocas have higher // priority to merge, which can save more space potentially. Also each diff --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp --- a/llvm/unittests/IR/InstructionsTest.cpp +++ b/llvm/unittests/IR/InstructionsTest.cpp @@ -1400,5 +1400,45 @@ ASSERT_EQ(ProfWeight, UINT32_MAX); } +TEST(InstructionsTest, AllocaInst) { + LLVMContext Ctx; + std::unique_ptr M = parseIR(Ctx, R"( + %T = type { i64, [3 x i32]} + define void @f(i32 %n) { + entry: + %A = alloca i32, i32 1 + %B = alloca i32, i32 4 + %C = alloca i32, i32 %n + %D = alloca <8 x double> + %E = alloca + %F = alloca [2 x half] + %G = alloca [2 x [3 x i128]] + %H = alloca %T + ret void + } + )"); + const DataLayout &DL = M->getDataLayout(); + ASSERT_TRUE(M); + Function *Fun = cast(M->getNamedValue("f")); + BasicBlock &BB = Fun->front(); + auto It = BB.begin(); + AllocaInst &A = cast(*It++); + AllocaInst &B = cast(*It++); + AllocaInst &C = cast(*It++); + AllocaInst &D = cast(*It++); + AllocaInst &E = cast(*It++); + AllocaInst &F = cast(*It++); + AllocaInst &G = cast(*It++); + AllocaInst &H = cast(*It++); + EXPECT_EQ(A.getAllocationSizeInBits(DL), TypeSize::getFixed(32)); + EXPECT_EQ(B.getAllocationSizeInBits(DL), TypeSize::getFixed(128)); + EXPECT_FALSE(C.getAllocationSizeInBits(DL)); + EXPECT_EQ(D.getAllocationSizeInBits(DL), TypeSize::getFixed(512)); + EXPECT_EQ(E.getAllocationSizeInBits(DL), TypeSize::getScalable(512)); + EXPECT_EQ(F.getAllocationSizeInBits(DL), TypeSize::getFixed(32)); + EXPECT_EQ(G.getAllocationSizeInBits(DL), TypeSize::getFixed(768)); + EXPECT_EQ(H.getAllocationSizeInBits(DL), TypeSize::getFixed(160)); +} + } // end anonymous namespace } // end namespace llvm