diff options
| author | Sebastian Pop <sebpop@gmail.com> | 2016-12-12 02:52:51 +0000 |
|---|---|---|
| committer | Sebastian Pop <sebpop@gmail.com> | 2016-12-12 02:52:51 +0000 |
| commit | 8c9cc8c86be80abd4224341314725d03551460d6 (patch) | |
| tree | 233be3a765d7f5e2f181c5dd2ffaaf5085c473d9 /llvm/unittests/Analysis/ScalarEvolutionTest.cpp | |
| parent | 7fc6d34ed1fce99505713c5b09b3701aaac9d60e (diff) | |
| download | bcm5719-llvm-8c9cc8c86be80abd4224341314725d03551460d6.tar.gz bcm5719-llvm-8c9cc8c86be80abd4224341314725d03551460d6.zip | |
[SCEVExpand] do not hoist divisions by zero (PR30935)
SCEVExpand computes the insertion point for the components of a SCEV to be code
generated. When it comes to generating code for a division, SCEVexpand would
not be able to check (at compilation time) all the conditions necessary to avoid
a division by zero. The patch disables hoisting of expressions containing
divisions by anything other than non-zero constants in order to avoid hoisting
these expressions past conditions that should hold before doing the division.
The patch passes check-all on x86_64-linux.
Differential Revision: https://reviews.llvm.org/D27216
llvm-svn: 289412
Diffstat (limited to 'llvm/unittests/Analysis/ScalarEvolutionTest.cpp')
| -rw-r--r-- | llvm/unittests/Analysis/ScalarEvolutionTest.cpp | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp index 752cc812824..1e1993843bb 100644 --- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp +++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp @@ -349,6 +349,13 @@ static Instruction *getInstructionByName(Function &F, StringRef Name) { llvm_unreachable("Expected to find instruction!"); } +static Argument *getArgByName(Function &F, StringRef Name) { + for (auto &A : F.args()) + if (A.getName() == Name) + return &A; + llvm_unreachable("Expected to find argument!"); +} + TEST_F(ScalarEvolutionsTest, CommutativeExprOperandOrder) { LLVMContext C; SMDiagnostic Err; @@ -532,5 +539,74 @@ TEST_F(ScalarEvolutionsTest, SCEVCompareComplexity) { EXPECT_NE(nullptr, SE.getSCEV(Acc[0])); } +TEST_F(ScalarEvolutionsTest, BadHoistingSCEVExpander_PR30942) { + LLVMContext C; + SMDiagnostic Err; + std::unique_ptr<Module> M = parseAssemblyString( + "target datalayout = \"e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128\" " + " " + "define void @f_1(i32 %x, i32 %y, i32 %n, i1* %cond_buf) " + " local_unnamed_addr { " + "entry: " + " %entrycond = icmp sgt i32 %n, 0 " + " br i1 %entrycond, label %loop.ph, label %for.end " + " " + "loop.ph: " + " br label %loop " + " " + "loop: " + " %iv1 = phi i32 [ %iv1.inc, %right ], [ 0, %loop.ph ] " + " %iv1.inc = add nuw nsw i32 %iv1, 1 " + " %cond = load volatile i1, i1* %cond_buf " + " br i1 %cond, label %left, label %right " + " " + "left: " + " %div = udiv i32 %x, %y " + " br label %right " + " " + "right: " + " %exitcond = icmp eq i32 %iv1.inc, %n " + " br i1 %exitcond, label %for.end.loopexit, label %loop " + " " + "for.end.loopexit: " + " br label %for.end " + " " + "for.end: " + " ret void " + "} ", + Err, C); + + assert(M && "Could not parse module?"); + assert(!verifyModule(*M) && "Must have been well formed!"); + + runWithFunctionAndSE(*M, "f_1", [&](Function &F, ScalarEvolution &SE) { + SCEVExpander Expander(SE, M->getDataLayout(), "unittests"); + auto *DivInst = getInstructionByName(F, "div"); + + { + auto *DivSCEV = SE.getSCEV(DivInst); + auto *DivExpansion = Expander.expandCodeFor( + DivSCEV, DivSCEV->getType(), DivInst->getParent()->getTerminator()); + auto *DivExpansionInst = dyn_cast<Instruction>(DivExpansion); + ASSERT_NE(DivExpansionInst, nullptr); + EXPECT_EQ(DivInst->getParent(), DivExpansionInst->getParent()); + } + + { + auto *ArgY = getArgByName(F, "y"); + auto *DivFromScratchSCEV = + SE.getUDivExpr(SE.getOne(ArgY->getType()), SE.getSCEV(ArgY)); + + auto *DivFromScratchExpansion = Expander.expandCodeFor( + DivFromScratchSCEV, DivFromScratchSCEV->getType(), + DivInst->getParent()->getTerminator()); + auto *DivFromScratchExpansionInst = + dyn_cast<Instruction>(DivFromScratchExpansion); + ASSERT_NE(DivFromScratchExpansionInst, nullptr); + EXPECT_EQ(DivInst->getParent(), DivFromScratchExpansionInst->getParent()); + } + }); +} + } // end anonymous namespace } // end namespace llvm |

