Index: lib/Analysis/ScalarEvolution.cpp =================================================================== --- lib/Analysis/ScalarEvolution.cpp +++ lib/Analysis/ScalarEvolution.cpp @@ -3951,8 +3951,6 @@ cast(Accum)->getLoop() == L)) { SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap; - // If the increment doesn't overflow, then neither the addrec nor - // the post-increment will overflow. if (auto BO = MatchBinaryOp(BEValueV)) { if (BO->Opcode == Instruction::Add && BO->LHS == PN) { if (BO->IsNUW) @@ -3983,16 +3981,19 @@ const SCEV *StartVal = getSCEV(StartValueV); const SCEV *PHISCEV = getAddRecExpr(StartVal, Accum, L, Flags); - // Since the no-wrap flags are on the increment, they apply to the - // post-incremented value as well. - if (isLoopInvariant(Accum, L)) - (void)getAddRecExpr(getAddExpr(StartVal, Accum), Accum, L, Flags); - // Okay, for the entire analysis of this edge we assumed the PHI // to be symbolic. We now need to go back and purge all of the // entries for the scalars that use the symbolic expression. forgetSymbolicName(PN, SymbolicName); ValueExprMap[SCEVCallbackVH(PN, this)] = PHISCEV; + + // We can add Flags to the post-inc expression only if we + // know that it us *undefined behavior* for BEValueV to + // overflow. + if (auto *BEInst = dyn_cast(BEValueV)) + if (isLoopInvariant(Accum, L) && isSCEVExprNeverPoison(BEInst)) + (void)getAddRecExpr(getAddExpr(StartVal, Accum), Accum, L, Flags); + return PHISCEV; } } Index: test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll =================================================================== --- test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll +++ test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll @@ -1,6 +1,6 @@ ; ; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s -define void @infer.sext.0(i1* %c, i32 %start) { +define void @infer.sext.0(i1* %c, i32 %start, i32* %buf) { ; CHECK-LABEL: Classifying expressions for: @infer.sext.0 entry: br label %loop @@ -12,6 +12,10 @@ %idx.inc.sext = sext i32 %idx.inc to i64 ; CHECK: %idx.inc.sext = sext i32 %idx.inc to i64 ; CHECK-NEXT: --> {(1 + (sext i32 %start to i64)),+,1}<%loop> + + %buf.gep = getelementptr inbounds i32, i32* %buf, i32 %idx.inc + %val = load i32, i32* %buf.gep + %condition = icmp eq i32 %counter, 1 %counter.inc = add i32 %counter, 1 br i1 %condition, label %exit, label %loop @@ -20,7 +24,7 @@ ret void } -define void @infer.zext.0(i1* %c, i32 %start) { +define void @infer.zext.0(i1* %c, i32 %start, i32* %buf) { ; CHECK-LABEL: Classifying expressions for: @infer.zext.0 entry: br label %loop @@ -32,6 +36,10 @@ %idx.inc.sext = zext i32 %idx.inc to i64 ; CHECK: %idx.inc.sext = zext i32 %idx.inc to i64 ; CHECK-NEXT: --> {(1 + (zext i32 %start to i64)),+,1}<%loop> + + %buf.gep = getelementptr inbounds i32, i32* %buf, i32 %idx.inc + %val = load i32, i32* %buf.gep + %condition = icmp eq i32 %counter, 1 %counter.inc = add i32 %counter, 1 br i1 %condition, label %exit, label %loop Index: test/Analysis/ScalarEvolution/nowrap-preinc-limits.ll =================================================================== --- test/Analysis/ScalarEvolution/nowrap-preinc-limits.ll +++ test/Analysis/ScalarEvolution/nowrap-preinc-limits.ll @@ -36,7 +36,8 @@ ; CHECK: %idx.inc2.sext = sext i32 %idx.inc2 to i64 ; CHECK-NEXT: --> {2,+,3}<%loop> - %c = load volatile i1, i1* %condition + %cond.gep = getelementptr inbounds i1, i1* %condition, i32 %idx.inc + %c = load volatile i1, i1* %cond.gep br i1 %c, label %loop, label %exit exit: Index: test/Analysis/ScalarEvolution/nsw.ll =================================================================== --- test/Analysis/ScalarEvolution/nsw.ll +++ test/Analysis/ScalarEvolution/nsw.ll @@ -30,15 +30,17 @@ %tmp8 = add nsw i32 %i.01, 1 ; [#uses=2] ; CHECK: %tmp8 ; CHECK-NEXT: --> {1,+,1}<%bb> + %p.gep = getelementptr double, double* %p, i32 %tmp8 + %p.val = load double, double* %p.gep br label %bb1 bb1: ; preds = %bb %phitmp = sext i32 %tmp8 to i64 ; [#uses=1] ; CHECK: %phitmp ; CHECK-NEXT: --> {1,+,1}<%bb> - %tmp9 = getelementptr double, double* %p, i64 %phitmp ; [#uses=1] + %tmp9 = getelementptr inbounds double, double* %p, i64 %phitmp ; [#uses=1] ; CHECK: %tmp9 -; CHECK-NEXT: --> {(8 + %p),+,8}<%bb> +; CHECK-NEXT: --> {(8 + %p),+,8}<%bb> %tmp10 = load double, double* %tmp9, align 8 ; [#uses=1] %tmp11 = fcmp ogt double %tmp10, 2.000000e+00 ; [#uses=1] br i1 %tmp11, label %bb, label %bb1.return_crit_edge @@ -143,15 +145,15 @@ } ; CHECK-LABEL: PR12376 -; CHECK: --> {(4 + %arg),+,4}<%bb2>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (4 + (4 * ((3 + (-1 * %arg) + (%arg umax %arg1)) /u 4)) + %arg) +; CHECK: --> {(4 + %arg),+,4}<%bb2>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (4 + (4 * ((-1 + (-1 * %arg) + ((4 + %arg) umax %arg1)) /u 4)) + %arg) define void @PR12376(i32* nocapture %arg, i32* nocapture %arg1) { bb: br label %bb2 bb2: ; preds = %bb2, %bb %tmp = phi i32* [ %arg, %bb ], [ %tmp4, %bb2 ] - %tmp3 = icmp ult i32* %tmp, %arg1 %tmp4 = getelementptr inbounds i32, i32* %tmp, i64 1 + %tmp3 = icmp ult i32* %tmp4, %arg1 br i1 %tmp3, label %bb2, label %bb5 bb5: ; preds = %bb2 @@ -162,7 +164,7 @@ ; CHECK-LABEL: nswnowrap ; CHECK: --> {(1 + %v),+,1}<%for.body>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (2 + %v) -define void @nswnowrap(i32 %v) { +define void @nswnowrap(i32 %v, i32* %buf) { entry: %add = add nsw i32 %v, 1 br label %for.body @@ -170,8 +172,10 @@ for.body: %i.04 = phi i32 [ %v, %entry ], [ %inc, %for.body ] %inc = add nsw i32 %i.04, 1 - tail call void @f(i32 %i.04) + %buf.gep = getelementptr inbounds i32, i32* %buf, i32 %inc + %buf.val = load i32, i32* %buf.gep %cmp = icmp slt i32 %i.04, %add + tail call void @f(i32 %i.04) br i1 %cmp, label %for.body, label %for.end for.end: Index: test/Analysis/ScalarEvolution/pr27315.ll =================================================================== --- /dev/null +++ test/Analysis/ScalarEvolution/pr27315.ll @@ -0,0 +1,31 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +declare i1 @use(i64) + +define void @f_0() { +; CHECK-LABEL: Classifying expressions for: @f_0 + +; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.inc.nowrap, %be ] +; CHECK-NEXT: --> {0,+,1}<%loop> +; CHECK: %iv.inc.maywrap = add i32 %iv, 1 +; CHECK-NEXT: --> {1,+,1}<%loop> +; CHECK: %iv.inc.maywrap.sext = sext i32 %iv.inc.maywrap to i64 +; CHECK-NEXT: --> (sext i32 {1,+,1}<%loop> to i64) +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.inc.nowrap, %be ] + %iv.inc.maywrap = add i32 %iv, 1 + %iv.inc.maywrap.sext = sext i32 %iv.inc.maywrap to i64 + %cond0 = call i1 @use(i64 %iv.inc.maywrap.sext) + br i1 %cond0, label %be, label %leave + +be: + %iv.inc.nowrap = add nsw i32 %iv, 1 + %be.cond = call i1 @use(i64 0) ;; Get an unanalyzable value + br i1 %be.cond, label %loop, label %leave + +leave: + ret void +} Index: test/Transforms/IndVarSimplify/elim-extend.ll =================================================================== --- test/Transforms/IndVarSimplify/elim-extend.ll +++ test/Transforms/IndVarSimplify/elim-extend.ll @@ -22,7 +22,7 @@ store i8 0, i8* %postadr %postivnsw = add nsw i32 %ivnsw, 1 %postofsnsw = sext i32 %postivnsw to i64 - %postadrnsw = getelementptr i8, i8* %base, i64 %postofsnsw + %postadrnsw = getelementptr inbounds i8, i8* %base, i64 %postofsnsw store i8 0, i8* %postadrnsw %cond = icmp sgt i32 %limit, %iv br i1 %cond, label %loop, label %exit