diff --git a/llvm/lib/Analysis/IVDescriptors.cpp b/llvm/lib/Analysis/IVDescriptors.cpp index 44b1d94ebdc80..74b0d6751023a 100644 --- a/llvm/lib/Analysis/IVDescriptors.cpp +++ b/llvm/lib/Analysis/IVDescriptors.cpp @@ -1428,10 +1428,14 @@ bool InductionDescriptor::isInductionPHI( ConstantInt *CV = ConstStep->getValue(); const DataLayout &DL = Phi->getModule()->getDataLayout(); - int64_t Size = static_cast(DL.getTypeAllocSize(ElementType)); - if (!Size) + TypeSize TySize = DL.getTypeAllocSize(ElementType); + // TODO: We could potentially support this for scalable vectors if we can + // prove at compile time that the constant step is always a multiple of + // the scalable type. + if (TySize.isZero() || TySize.isScalable()) return false; + int64_t Size = static_cast(TySize.getFixedSize()); int64_t CVSize = CV->getSExtValue(); if (CVSize % Size) return false; diff --git a/llvm/unittests/Analysis/IVDescriptorsTest.cpp b/llvm/unittests/Analysis/IVDescriptorsTest.cpp index 1f63db3ff31cd..e7948db10ae66 100644 --- a/llvm/unittests/Analysis/IVDescriptorsTest.cpp +++ b/llvm/unittests/Analysis/IVDescriptorsTest.cpp @@ -97,6 +97,47 @@ for.end: }); } +TEST(IVDescriptorsTest, LoopWithScalableTypes) { + // Parse the module. + LLVMContext Context; + + std::unique_ptr M = + parseIR(Context, + R"(define void @foo(* %ptr) { +entry: + br label %for.body + +for.body: + %lsr.iv1 = phi * [ %0, %for.body ], [ %ptr, %entry ] + %j.0117 = phi i64 [ %inc, %for.body ], [ 0, %entry ] + %lsr.iv12 = bitcast * %lsr.iv1 to i8* + %inc = add nuw nsw i64 %j.0117, 1 + %uglygep = getelementptr i8, i8* %lsr.iv12, i64 4 + %0 = bitcast i8* %uglygep to * + %cmp = icmp ne i64 %inc, 1024 + br i1 %cmp, label %for.body, label %end + +end: + ret void +})"); + + runWithLoopInfoAndSE( + *M, "foo", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { + Function::iterator FI = F.begin(); + // First basic block is entry - skip it. + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + PHINode *Inst_iv = dyn_cast(&Header->front()); + assert(Inst_iv->getName() == "lsr.iv1"); + InductionDescriptor IndDesc; + bool IsInductionPHI = + InductionDescriptor::isInductionPHI(Inst_iv, L, &SE, IndDesc); + EXPECT_FALSE(IsInductionPHI); + }); +} + // Depending on how SCEV deals with ptrtoint cast, the step of a phi could be // a pointer, and InductionDescriptor used to fail with an assertion. // So just check that it doesn't assert.