From a63d333881e20f3df462263ad6bc557ae3c3e024 Mon Sep 17 00:00:00 2001 From: Max Kazantsev Date: Tue, 27 Mar 2018 04:54:00 +0000 Subject: [PATCH] [SCEV] Add one more case in computeConstantDifference This patch teaches `computeConstantDifference` handle calculation of constant difference between `(X + C1)` and `(X + C2)` which is `(C2 - C1)`. Differential Revision: https://reviews.llvm.org/D43759 Reviewed By: anna llvm-svn: 328609 --- llvm/lib/Analysis/ScalarEvolution.cpp | 28 ++++--- .../promote-iv-to-eliminate-casts.ll | 89 ++++++++++++++++++++++ 2 files changed, 107 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 004eac7..b44107d 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -9449,17 +9449,25 @@ Optional ScalarEvolution::computeConstantDifference(const SCEV *More, return M - L; } - const SCEV *L, *R; SCEV::NoWrapFlags Flags; - if (splitBinaryAdd(Less, L, R, Flags)) - if (const auto *LC = dyn_cast(L)) - if (R == More) - return -(LC->getAPInt()); - - if (splitBinaryAdd(More, L, R, Flags)) - if (const auto *LC = dyn_cast(L)) - if (R == Less) - return LC->getAPInt(); + const SCEV *LLess = nullptr, *RLess = nullptr; + const SCEV *LMore = nullptr, *RMore = nullptr; + const SCEVConstant *C1 = nullptr, *C2 = nullptr; + // Compare (X + C1) vs X. + if (splitBinaryAdd(Less, LLess, RLess, Flags)) + if ((C1 = dyn_cast(LLess))) + if (RLess == More) + return -(C1->getAPInt()); + + // Compare X vs (X + C2). + if (splitBinaryAdd(More, LMore, RMore, Flags)) + if ((C2 = dyn_cast(LMore))) + if (RMore == Less) + return C2->getAPInt(); + + // Compare (X + C1) vs (X + C2). + if (C1 && C2 && RLess == RMore) + return C2->getAPInt() - C1->getAPInt(); return None; } diff --git a/llvm/test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll b/llvm/test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll index 956999b..5872e4e 100644 --- a/llvm/test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll +++ b/llvm/test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll @@ -101,3 +101,92 @@ bb: ; preds = %bb, %bb.thread return: ; preds = %bb ret void } + +define void @promote_latch_condition_decrementing_loop_01(i32* %p, i32* %a) { + +; CHECK-LABEL: @promote_latch_condition_decrementing_loop_01( +; CHECK-NOT: trunc + +entry: + %len = load i32, i32* %p, align 4, !range !0 + %len.minus.1 = add nsw i32 %len, -1 + %zero_check = icmp eq i32 %len, 0 + br i1 %zero_check, label %loopexit, label %preheader + +preheader: + br label %loop + +loopexit: + ret void + +loop: + %iv = phi i32 [ %iv.next, %loop ], [ %len.minus.1, %preheader ] + ; CHECK: %indvars.iv = phi i64 + %iv.wide = zext i32 %iv to i64 + %el = getelementptr inbounds i32, i32* %a, i64 %iv.wide + store atomic i32 0, i32* %el unordered, align 4 + %iv.next = add nsw i32 %iv, -1 + ; CHECK: %loopcond = icmp slt i64 %indvars.iv, 1 + %loopcond = icmp slt i32 %iv, 1 + br i1 %loopcond, label %loopexit, label %loop +} + +define void @promote_latch_condition_decrementing_loop_02(i32* %p, i32* %a) { + +; CHECK-LABEL: @promote_latch_condition_decrementing_loop_02( +; CHECK-NOT: trunc + +entry: + %len = load i32, i32* %p, align 4, !range !0 + %zero_check = icmp eq i32 %len, 0 + br i1 %zero_check, label %loopexit, label %preheader + +preheader: + br label %loop + +loopexit: + ret void + +loop: + %iv = phi i32 [ %iv.next, %loop ], [ %len, %preheader ] + ; CHECK: %indvars.iv = phi i64 + %iv.wide = zext i32 %iv to i64 + %el = getelementptr inbounds i32, i32* %a, i64 %iv.wide + store atomic i32 0, i32* %el unordered, align 4 + %iv.next = add nsw i32 %iv, -1 + ; CHECK: %loopcond = icmp slt i64 %indvars.iv, 1 + %loopcond = icmp slt i32 %iv, 1 + br i1 %loopcond, label %loopexit, label %loop +} + +define void @promote_latch_condition_decrementing_loop_03(i32* %p, i32* %a) { + +; CHECK-LABEL: @promote_latch_condition_decrementing_loop_03( +; CHECK-NOT: trunc + +entry: + %len = load i32, i32* %p, align 4, !range !0 + %len.plus.1 = add i32 %len, 1 + %zero_check = icmp eq i32 %len, 0 + br i1 %zero_check, label %loopexit, label %preheader + +preheader: + br label %loop + +loopexit: + ret void + +loop: + %iv = phi i32 [ %iv.next, %loop ], [ %len.plus.1, %preheader ] + ; CHECK: %indvars.iv = phi i64 + %iv.wide = zext i32 %iv to i64 + %el = getelementptr inbounds i32, i32* %a, i64 %iv.wide + store atomic i32 0, i32* %el unordered, align 4 + %iv.next = add nsw i32 %iv, -1 + ; CHECK: %loopcond = icmp slt i64 %indvars.iv, 1 + %loopcond = icmp slt i32 %iv, 1 + br i1 %loopcond, label %loopexit, label %loop +} + + +!0 = !{i32 0, i32 2147483647} -- 2.7.4