diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h --- a/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -655,6 +655,11 @@ /// Return a SCEV for the constant 1 of a specific type. const SCEV *getOne(Type *Ty) { return getConstant(Ty, 1); } + /// Return a SCEV for the constant 2 with \p Degree power of a specific type. + const SCEV *getPowerOfTwo(Type *Ty, long long Degree) { + return getConstant(Ty, 1 << Degree); + } + /// Return a SCEV for the constant -1 of a specific type. const SCEV *getMinusOne(Type *Ty) { return getConstant(Ty, -1, /*isSigned=*/true); diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp --- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp +++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp @@ -1744,4 +1744,27 @@ }); } +TEST_F(ScalarEvolutionsTest, CheckGetPowerOfTwo) { + LLVMContext C; + SMDiagnostic Err; + std::unique_ptr M = parseAssemblyString("define void @foo(i32 %x) { " + " ret void " + "} ", + Err, C); + + ASSERT_TRUE(M && "Could not parse module?"); + ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!"); + + runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) { + auto *X = SE.getSCEV(getArgByName(F, "x")); + Type *Ty = X->getType(); + const SCEV *TwoPowerThree = SE.getPowerOfTwo(Ty, 3); + const SCEV *TwoPowerFour = SE.getPowerOfTwo(Ty, 4); + auto *Sum = SE.getAddExpr(TwoPowerThree, TwoPowerThree, SCEV::FlagNUW); + EXPECT_TRUE( + SE.isKnownPredicate(ICmpInst::ICMP_ULT, TwoPowerThree, TwoPowerFour)); + EXPECT_TRUE(SE.isKnownPredicate(ICmpInst::ICMP_EQ, Sum, TwoPowerFour)); + }); +} + } // end namespace llvm