From 7dd25617402280e474247afdf16e117b35d98681 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Tue, 12 Feb 2019 00:33:25 +0000 Subject: [PATCH] [LoopReroll] Fix reroll root legality checking. The code checked that the first root was an appropriate distance from the base value, but skipped checking the other roots. This could lead to rerolling a loop that can't be legally rerolled (at least, not without rewriting the loop in a non-trivial way). Differential Revision: https://reviews.llvm.org/D56812 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@353779 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/LoopRerollPass.cpp | 10 ++++++++++ test/Transforms/LoopReroll/basic.ll | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/lib/Transforms/Scalar/LoopRerollPass.cpp b/lib/Transforms/Scalar/LoopRerollPass.cpp index 17aa442d86e..166b57f20b4 100644 --- a/lib/Transforms/Scalar/LoopRerollPass.cpp +++ b/lib/Transforms/Scalar/LoopRerollPass.cpp @@ -891,12 +891,22 @@ bool LoopReroll::DAGRootTracker::validateRootSet(DAGRootSet &DRS) { const auto *ADR = dyn_cast(SE->getSCEV(DRS.BaseInst)); if (!ADR) return false; + + // Check that the first root is evenly spaced. unsigned N = DRS.Roots.size() + 1; const SCEV *StepSCEV = SE->getMinusSCEV(SE->getSCEV(DRS.Roots[0]), ADR); const SCEV *ScaleSCEV = SE->getConstant(StepSCEV->getType(), N); if (ADR->getStepRecurrence(*SE) != SE->getMulExpr(StepSCEV, ScaleSCEV)) return false; + // Check that the remainling roots are evenly spaced. + for (unsigned i = 1; i < N - 1; ++i) { + const SCEV *NewStepSCEV = SE->getMinusSCEV(SE->getSCEV(DRS.Roots[i]), + SE->getSCEV(DRS.Roots[i-1])); + if (NewStepSCEV != StepSCEV) + return false; + } + return true; } diff --git a/test/Transforms/LoopReroll/basic.ll b/test/Transforms/LoopReroll/basic.ll index 6e2f2fcabf1..b415b2653ac 100644 --- a/test/Transforms/LoopReroll/basic.ll +++ b/test/Transforms/LoopReroll/basic.ll @@ -785,6 +785,30 @@ bb19: ; preds = %bb3 ret void } +define void @bad_step(i32* nocapture readnone %x) #0 { +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %i.08 = phi i32 [ 0, %entry ], [ %add3, %for.body ] + %call = tail call i32 @foo(i32 %i.08) #1 + %add = add nsw i32 %i.08, 2 + %call1 = tail call i32 @foo(i32 %add) #1 + %add2 = add nsw i32 %i.08, 3 + %call3 = tail call i32 @foo(i32 %add2) #1 + %add3 = add nsw i32 %i.08, 6 + %exitcond = icmp sge i32 %add3, 500 + br i1 %exitcond, label %for.end, label %for.body + +; CHECK-LABEL: @bad_step +; CHECK: %add = add nsw i32 %i.08, 2 +; CHECK: %add2 = add nsw i32 %i.08, 3 +; CHECK: %add3 = add nsw i32 %i.08, 6 + +for.end: ; preds = %for.body + ret void +} + attributes #0 = { nounwind uwtable } attributes #1 = { nounwind } -- 2.40.0