diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -5446,6 +5446,12 @@ if (auto *CI = dyn_cast(Cond)) return getSCEV(CI->isOne() ? TrueVal : FalseVal); + // Don't handle instructions with pointer type. The true/false values might + // have different pointer bases. We could handle cases where the values have + // the same pointer base if it turns out to be useful. + if (I->getType()->isPointerTy()) + return getUnknown(I); + // Try to match some simple smax or umax patterns. auto *ICI = dyn_cast(Cond); if (!ICI) @@ -5454,6 +5460,11 @@ Value *LHS = ICI->getOperand(0); Value *RHS = ICI->getOperand(1); + // Don't handle pointer icmps. We could add code to convert the operands to + // integers if it turns out to be useful. + if (LHS->getType()->isPointerTy()) + return getUnknown(I); + switch (ICI->getPredicate()) { case ICmpInst::ICMP_SLT: case ICmpInst::ICMP_SLE: diff --git a/llvm/test/Analysis/ScalarEvolution/pr46786.ll b/llvm/test/Analysis/ScalarEvolution/pr46786.ll --- a/llvm/test/Analysis/ScalarEvolution/pr46786.ll +++ b/llvm/test/Analysis/ScalarEvolution/pr46786.ll @@ -16,11 +16,11 @@ ; CHECK-NEXT: %i5 = getelementptr inbounds i8, i8* %i, i32 %i4 ; CHECK-NEXT: --> ((-1 * %arg1) + %arg2 + %arg) U: full-set S: full-set ; CHECK-NEXT: %i7 = select i1 %i6, i32 %arg2, i32 %arg1 -; CHECK-NEXT: --> ((-1 * %arg) + (((-1 * %arg1) + %arg2 + %arg) umin %arg) + %arg1) U: full-set S: full-set +; CHECK-NEXT: --> %i7 U: full-set S: full-set ; CHECK-NEXT: %i8 = sub i32 %arg3, %i7 -; CHECK-NEXT: --> ((-1 * (((-1 * %arg1) + %arg2 + %arg) umin %arg)) + (-1 * %arg1) + %arg3 + %arg) U: full-set S: full-set +; CHECK-NEXT: --> ((-1 * %i7) + %arg3) U: full-set S: full-set ; CHECK-NEXT: %i9 = getelementptr inbounds i8, i8* %arg, i32 %i8 -; CHECK-NEXT: --> ((2 * %arg) + (-1 * (((-1 * %arg1) + %arg2 + %arg) umin %arg)) + (-1 * %arg1) + %arg3) U: full-set S: full-set +; CHECK-NEXT: --> ((-1 * %i7) + %arg3 + %arg) U: full-set S: full-set ; CHECK-NEXT: Determining loop execution counts for: @FSE_decompress_usingDTable ; bb: @@ -42,11 +42,11 @@ ; CHECK-NEXT: %p2 = getelementptr i8, i8* %p, i32 1 ; CHECK-NEXT: --> (1 + %p) U: full-set S: full-set ; CHECK-NEXT: %index = select i1 %cmp, i32 2, i32 1 -; CHECK-NEXT: --> ((-1 * %p) + ((1 + %p) umax (2 + %p))) U: full-set S: full-set +; CHECK-NEXT: --> %index U: [0,4) S: [0,4) ; CHECK-NEXT: %neg_index = sub i32 0, %index -; CHECK-NEXT: --> ((-1 * ((1 + %p) umax (2 + %p))) + %p) U: full-set S: full-set +; CHECK-NEXT: --> (-1 * %index) U: [-3,1) S: [-3,1) ; CHECK-NEXT: %gep = getelementptr i8, i8* %p, i32 %neg_index -; CHECK-NEXT: --> ((2 * %p) + (-1 * ((1 + %p) umax (2 + %p)))) U: full-set S: full-set +; CHECK-NEXT: --> ((-1 * %index) + %p) U: full-set S: full-set ; CHECK-NEXT: Determining loop execution counts for: @test_01 ; %p1 = getelementptr i8, i8* %p, i32 2 @@ -66,11 +66,11 @@ ; CHECK-NEXT: %p2 = getelementptr i8, i8* %p, i32 1 ; CHECK-NEXT: --> (1 + %p) U: full-set S: full-set ; CHECK-NEXT: %index = select i1 %cmp, i32 2, i32 1 -; CHECK-NEXT: --> ((-1 * %p) + ((1 + %p) smax (2 + %p))) U: full-set S: full-set +; CHECK-NEXT: --> %index U: [0,4) S: [0,4) ; CHECK-NEXT: %neg_index = sub i32 0, %index -; CHECK-NEXT: --> ((-1 * ((1 + %p) smax (2 + %p))) + %p) U: full-set S: full-set +; CHECK-NEXT: --> (-1 * %index) U: [-3,1) S: [-3,1) ; CHECK-NEXT: %gep = getelementptr i8, i8* %p, i32 %neg_index -; CHECK-NEXT: --> ((2 * %p) + (-1 * ((1 + %p) smax (2 + %p)))) U: full-set S: full-set +; CHECK-NEXT: --> ((-1 * %index) + %p) U: full-set S: full-set ; CHECK-NEXT: Determining loop execution counts for: @test_02 ; %p1 = getelementptr i8, i8* %p, i32 2 @@ -90,11 +90,11 @@ ; CHECK-NEXT: %p2 = getelementptr i8, i8* %p, i32 1 ; CHECK-NEXT: --> (1 + %p) U: full-set S: full-set ; CHECK-NEXT: %index = select i1 %cmp, i32 2, i32 1 -; CHECK-NEXT: --> ((-1 * %p) + ((1 + %p) umin (2 + %p))) U: full-set S: full-set +; CHECK-NEXT: --> %index U: [0,4) S: [0,4) ; CHECK-NEXT: %neg_index = sub i32 0, %index -; CHECK-NEXT: --> ((-1 * ((1 + %p) umin (2 + %p))) + %p) U: full-set S: full-set +; CHECK-NEXT: --> (-1 * %index) U: [-3,1) S: [-3,1) ; CHECK-NEXT: %gep = getelementptr i8, i8* %p, i32 %neg_index -; CHECK-NEXT: --> ((2 * %p) + (-1 * ((1 + %p) umin (2 + %p)))) U: full-set S: full-set +; CHECK-NEXT: --> ((-1 * %index) + %p) U: full-set S: full-set ; CHECK-NEXT: Determining loop execution counts for: @test_03 ; %p1 = getelementptr i8, i8* %p, i32 2 @@ -114,11 +114,11 @@ ; CHECK-NEXT: %p2 = getelementptr i8, i8* %p, i32 1 ; CHECK-NEXT: --> (1 + %p) U: full-set S: full-set ; CHECK-NEXT: %index = select i1 %cmp, i32 2, i32 1 -; CHECK-NEXT: --> ((-1 * %p) + ((1 + %p) smin (2 + %p))) U: full-set S: full-set +; CHECK-NEXT: --> %index U: [0,4) S: [0,4) ; CHECK-NEXT: %neg_index = sub i32 0, %index -; CHECK-NEXT: --> ((-1 * ((1 + %p) smin (2 + %p))) + %p) U: full-set S: full-set +; CHECK-NEXT: --> (-1 * %index) U: [-3,1) S: [-3,1) ; CHECK-NEXT: %gep = getelementptr i8, i8* %p, i32 %neg_index -; CHECK-NEXT: --> ((2 * %p) + (-1 * ((1 + %p) smin (2 + %p)))) U: full-set S: full-set +; CHECK-NEXT: --> ((-1 * %index) + %p) U: full-set S: full-set ; CHECK-NEXT: Determining loop execution counts for: @test_04 ; %p1 = getelementptr i8, i8* %p, i32 2 diff --git a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll --- a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll +++ b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll @@ -278,17 +278,17 @@ ; X64-LABEL: 'ptrtoint_of_umax' ; X64-NEXT: Classifying expressions for: @ptrtoint_of_umax ; X64-NEXT: %s = select i1 %c, i8* %in0, i8* %in1 -; X64-NEXT: --> (%in0 umax %in1) U: full-set S: full-set +; X64-NEXT: --> %s U: full-set S: full-set ; X64-NEXT: %p0 = ptrtoint i8* %s to i64 -; X64-NEXT: --> ((ptrtoint i8* %in0 to i64) umax (ptrtoint i8* %in1 to i64)) U: full-set S: full-set +; X64-NEXT: --> (ptrtoint i8* %s to i64) U: full-set S: full-set ; X64-NEXT: Determining loop execution counts for: @ptrtoint_of_umax ; ; X32-LABEL: 'ptrtoint_of_umax' ; X32-NEXT: Classifying expressions for: @ptrtoint_of_umax ; X32-NEXT: %s = select i1 %c, i8* %in0, i8* %in1 -; X32-NEXT: --> (%in0 umax %in1) U: full-set S: full-set +; X32-NEXT: --> %s U: full-set S: full-set ; X32-NEXT: %p0 = ptrtoint i8* %s to i64 -; X32-NEXT: --> (zext i32 ((ptrtoint i8* %in0 to i32) umax (ptrtoint i8* %in1 to i32)) to i64) U: [0,4294967296) S: [0,4294967296) +; X32-NEXT: --> (zext i32 (ptrtoint i8* %s to i32) to i64) U: [0,4294967296) S: [0,4294967296) ; X32-NEXT: Determining loop execution counts for: @ptrtoint_of_umax ; %c = icmp uge i8* %in0, %in1 @@ -302,17 +302,17 @@ ; X64-LABEL: 'ptrtoint_of_smax' ; X64-NEXT: Classifying expressions for: @ptrtoint_of_smax ; X64-NEXT: %s = select i1 %c, i8* %in0, i8* %in1 -; X64-NEXT: --> (%in0 smax %in1) U: full-set S: full-set +; X64-NEXT: --> %s U: full-set S: full-set ; X64-NEXT: %p0 = ptrtoint i8* %s to i64 -; X64-NEXT: --> ((ptrtoint i8* %in0 to i64) smax (ptrtoint i8* %in1 to i64)) U: full-set S: full-set +; X64-NEXT: --> (ptrtoint i8* %s to i64) U: full-set S: full-set ; X64-NEXT: Determining loop execution counts for: @ptrtoint_of_smax ; ; X32-LABEL: 'ptrtoint_of_smax' ; X32-NEXT: Classifying expressions for: @ptrtoint_of_smax ; X32-NEXT: %s = select i1 %c, i8* %in0, i8* %in1 -; X32-NEXT: --> (%in0 smax %in1) U: full-set S: full-set +; X32-NEXT: --> %s U: full-set S: full-set ; X32-NEXT: %p0 = ptrtoint i8* %s to i64 -; X32-NEXT: --> (zext i32 ((ptrtoint i8* %in0 to i32) smax (ptrtoint i8* %in1 to i32)) to i64) U: [0,4294967296) S: [0,4294967296) +; X32-NEXT: --> (zext i32 (ptrtoint i8* %s to i32) to i64) U: [0,4294967296) S: [0,4294967296) ; X32-NEXT: Determining loop execution counts for: @ptrtoint_of_smax ; %c = icmp sge i8* %in0, %in1 @@ -326,17 +326,17 @@ ; X64-LABEL: 'ptrtoint_of_umin' ; X64-NEXT: Classifying expressions for: @ptrtoint_of_umin ; X64-NEXT: %s = select i1 %c, i8* %in0, i8* %in1 -; X64-NEXT: --> (%in0 umin %in1) U: full-set S: full-set +; X64-NEXT: --> %s U: full-set S: full-set ; X64-NEXT: %p0 = ptrtoint i8* %s to i64 -; X64-NEXT: --> ((ptrtoint i8* %in0 to i64) umin (ptrtoint i8* %in1 to i64)) U: full-set S: full-set +; X64-NEXT: --> (ptrtoint i8* %s to i64) U: full-set S: full-set ; X64-NEXT: Determining loop execution counts for: @ptrtoint_of_umin ; ; X32-LABEL: 'ptrtoint_of_umin' ; X32-NEXT: Classifying expressions for: @ptrtoint_of_umin ; X32-NEXT: %s = select i1 %c, i8* %in0, i8* %in1 -; X32-NEXT: --> (%in0 umin %in1) U: full-set S: full-set +; X32-NEXT: --> %s U: full-set S: full-set ; X32-NEXT: %p0 = ptrtoint i8* %s to i64 -; X32-NEXT: --> (zext i32 ((ptrtoint i8* %in0 to i32) umin (ptrtoint i8* %in1 to i32)) to i64) U: [0,4294967296) S: [0,4294967296) +; X32-NEXT: --> (zext i32 (ptrtoint i8* %s to i32) to i64) U: [0,4294967296) S: [0,4294967296) ; X32-NEXT: Determining loop execution counts for: @ptrtoint_of_umin ; %c = icmp ule i8* %in0, %in1 @@ -350,17 +350,17 @@ ; X64-LABEL: 'ptrtoint_of_smin' ; X64-NEXT: Classifying expressions for: @ptrtoint_of_smin ; X64-NEXT: %s = select i1 %c, i8* %in0, i8* %in1 -; X64-NEXT: --> (%in0 smin %in1) U: full-set S: full-set +; X64-NEXT: --> %s U: full-set S: full-set ; X64-NEXT: %p0 = ptrtoint i8* %s to i64 -; X64-NEXT: --> ((ptrtoint i8* %in0 to i64) smin (ptrtoint i8* %in1 to i64)) U: full-set S: full-set +; X64-NEXT: --> (ptrtoint i8* %s to i64) U: full-set S: full-set ; X64-NEXT: Determining loop execution counts for: @ptrtoint_of_smin ; ; X32-LABEL: 'ptrtoint_of_smin' ; X32-NEXT: Classifying expressions for: @ptrtoint_of_smin ; X32-NEXT: %s = select i1 %c, i8* %in0, i8* %in1 -; X32-NEXT: --> (%in0 smin %in1) U: full-set S: full-set +; X32-NEXT: --> %s U: full-set S: full-set ; X32-NEXT: %p0 = ptrtoint i8* %s to i64 -; X32-NEXT: --> (zext i32 ((ptrtoint i8* %in0 to i32) smin (ptrtoint i8* %in1 to i32)) to i64) U: [0,4294967296) S: [0,4294967296) +; X32-NEXT: --> (zext i32 (ptrtoint i8* %s to i32) to i64) U: [0,4294967296) S: [0,4294967296) ; X32-NEXT: Determining loop execution counts for: @ptrtoint_of_smin ; %c = icmp sle i8* %in0, %in1 diff --git a/llvm/test/Transforms/IndVarSimplify/pr45835.ll b/llvm/test/Transforms/IndVarSimplify/pr45835.ll --- a/llvm/test/Transforms/IndVarSimplify/pr45835.ll +++ b/llvm/test/Transforms/IndVarSimplify/pr45835.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -indvars -replexitval=always -S | FileCheck %s --check-prefix=ALWAYS +; RUN: opt < %s -indvars -replexitval=always -S | FileCheck %s --check-prefix=NEVER ; RUN: opt < %s -indvars -replexitval=never -S | FileCheck %s --check-prefix=NEVER ; RUN: opt < %s -indvars -replexitval=cheap -scev-cheap-expansion-budget=1 -S | FileCheck %s --check-prefix=CHEAP diff --git a/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp b/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp --- a/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp +++ b/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp @@ -68,72 +68,6 @@ llvm_unreachable("Could not find instructions!"); } -TEST_F(ScalarEvolutionExpanderTest, ExpandPtrTypeSCEV) { - // It is to test the fix for PR30213. It exercises the branch in scev - // expansion when the value in ValueOffsetPair is a ptr and the offset - // is not divisible by the elem type size of value. - auto *I8Ty = Type::getInt8Ty(Context); - auto *I8PtrTy = Type::getInt8PtrTy(Context); - auto *I32Ty = Type::getInt32Ty(Context); - auto *I32PtrTy = Type::getInt32PtrTy(Context); - FunctionType *FTy = - FunctionType::get(Type::getVoidTy(Context), std::vector(), false); - Function *F = Function::Create(FTy, Function::ExternalLinkage, "f", M); - BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", F); - BasicBlock *LoopBB = BasicBlock::Create(Context, "loop", F); - BasicBlock *ExitBB = BasicBlock::Create(Context, "exit", F); - BranchInst::Create(LoopBB, EntryBB); - ReturnInst::Create(Context, nullptr, ExitBB); - - // loop: ; preds = %loop, %entry - // %alloca = alloca i32 - // %gep0 = getelementptr i32, i32* %alloca, i32 1 - // %bitcast1 = bitcast i32* %gep0 to i8* - // %gep1 = getelementptr i8, i8* %bitcast1, i32 1 - // %gep2 = getelementptr i8, i8* undef, i32 1 - // %cmp = icmp ult i8* undef, %bitcast1 - // %select = select i1 %cmp, i8* %gep1, i8* %gep2 - // %bitcast2 = bitcast i8* %select to i32* - // br i1 undef, label %loop, label %exit - - const DataLayout &DL = F->getParent()->getDataLayout(); - BranchInst *Br = BranchInst::Create( - LoopBB, ExitBB, UndefValue::get(Type::getInt1Ty(Context)), LoopBB); - AllocaInst *Alloca = - new AllocaInst(I32Ty, DL.getAllocaAddrSpace(), "alloca", Br); - ConstantInt *Ci32 = ConstantInt::get(Context, APInt(32, 1)); - GetElementPtrInst *Gep0 = - GetElementPtrInst::Create(I32Ty, Alloca, Ci32, "gep0", Br); - CastInst *CastA = - CastInst::CreateBitOrPointerCast(Gep0, I8PtrTy, "bitcast1", Br); - GetElementPtrInst *Gep1 = - GetElementPtrInst::Create(I8Ty, CastA, Ci32, "gep1", Br); - GetElementPtrInst *Gep2 = GetElementPtrInst::Create( - I8Ty, UndefValue::get(I8PtrTy), Ci32, "gep2", Br); - CmpInst *Cmp = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, - UndefValue::get(I8PtrTy), CastA, "cmp", Br); - SelectInst *Sel = SelectInst::Create(Cmp, Gep1, Gep2, "select", Br); - CastInst *CastB = - CastInst::CreateBitOrPointerCast(Sel, I32PtrTy, "bitcast2", Br); - - ScalarEvolution SE = buildSE(*F); - auto *S = SE.getSCEV(CastB); - SCEVExpander Exp(SE, M.getDataLayout(), "expander"); - Value *V = - Exp.expandCodeFor(cast(S)->getOperand(1), nullptr, Br); - - // Expect the expansion code contains: - // %0 = bitcast i32* %bitcast2 to i8* - // %uglygep = getelementptr i8, i8* %0, i64 -1 - // %1 = bitcast i8* %uglygep to i32* - EXPECT_TRUE(isa(V)); - Instruction *Gep = cast(V)->getPrevNode(); - EXPECT_TRUE(isa(Gep)); - EXPECT_TRUE(isa(Gep->getOperand(1))); - EXPECT_EQ(cast(Gep->getOperand(1))->getSExtValue(), -1); - EXPECT_TRUE(isa(Gep->getPrevNode())); -} - // Make sure that SCEV doesn't introduce illegal ptrtoint/inttoptr instructions TEST_F(ScalarEvolutionExpanderTest, SCEVZeroExtendExprNonIntegral) { /*