<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:Consolas;
panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:"Times New Roman",serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:purple;
text-decoration:underline;}
pre
{mso-style-priority:99;
mso-style-link:"HTML Preformatted Char";
margin:0cm;
margin-bottom:.0001pt;
font-size:10.0pt;
font-family:"Courier New";}
p.msonormal0, li.msonormal0, div.msonormal0
{mso-style-name:msonormal;
mso-margin-top-alt:auto;
margin-right:0cm;
mso-margin-bottom-alt:auto;
margin-left:0cm;
font-size:12.0pt;
font-family:"Times New Roman",serif;}
span.HTMLPreformattedChar
{mso-style-name:"HTML Preformatted Char";
mso-style-priority:99;
mso-style-link:"HTML Preformatted";
font-family:Consolas;
mso-fareast-language:RU;}
span.gmail-stdout
{mso-style-name:gmail-stdout;}
span.EmailStyle21
{mso-style-type:personal-reply;
font-family:"Calibri",sans-serif;
color:#1F497D;}
.MsoChpDefault
{mso-style-type:export-only;
font-family:"Calibri",sans-serif;
mso-fareast-language:EN-US;}
@page WordSection1
{size:612.0pt 792.0pt;
margin:2.0cm 42.5pt 2.0cm 3.0cm;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="RU" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US">Hi Vitaly,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US">I'm now updating the test to make the sanitizer happy.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US">Thanks,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US">Max<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><b><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri",sans-serif">From:</span></b><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri",sans-serif"> Vitaly Buka [mailto:vitalybuka@google.com]
<br>
<b>Sent:</b> Friday, August 4, 2017 3:54 AM<br>
<b>To:</b> Maxim Kazantsev <max.kazantsev@azul.com><br>
<b>Cc:</b> llvm-commits <llvm-commits@lists.llvm.org><br>
<b>Subject:</b> Re: [llvm] r309925 - [SCEV] Re-enable "Cache results of computeExitLimit"<o:p></o:p></span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<pre><span class="gmail-stdout"><span style="font-size:12.0pt;color:black"><a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/1960/steps/check-llvm%20asan/logs/stdio">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/1960/steps/check-llvm%20asan/logs/stdio</a></span></span><o:p></o:p></pre>
<pre><span style="font-size:13.5pt;color:black"><o:p> </o:p></span></pre>
<pre><span class="gmail-stdout"><span style="font-size:13.5pt;color:black">[ RUN ] ScalarEvolutionsTest.SCEVExitLimitForgetLoop<o:p></o:p></span></span></pre>
<pre><span class="gmail-stdout"><span style="font-size:13.5pt;color:black">=================================================================<o:p></o:p></span></span></pre>
<pre><span class="gmail-stdout"><span style="font-size:13.5pt;color:black">==9898==ERROR: AddressSanitizer: heap-use-after-free on address 0x60b000012ce8 at pc 0x000000d85a56 bp 0x7ffeaee9b0b0 sp 0x7ffeaee9b0a8<o:p></o:p></span></span></pre>
<pre><span class="gmail-stdout"><span style="font-size:13.5pt;color:black">READ of size 8 at 0x60b000012ce8 thread T0<o:p></o:p></span></span></pre>
<pre><span class="gmail-stdout"><span style="font-size:13.5pt;color:black"> #0 0xd85a55 in addToList /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/include/llvm/IR/Use.h:149:12<o:p></o:p></span></span></pre>
<pre><span class="gmail-stdout"><span style="font-size:13.5pt;color:black"> #1 0xd85a55 in addUse /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/include/llvm/IR/Value.h:432<o:p></o:p></span></span></pre>
<pre><span class="gmail-stdout"><span style="font-size:13.5pt;color:black"> #2 0xd85a55 in set /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/include/llvm/IR/Value.h:674<o:p></o:p></span></span></pre>
<pre><span class="gmail-stdout"><span style="font-size:13.5pt;color:black"> #3 0xd85a55 in operator= /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/include/llvm/IR/Value.h:678<o:p></o:p></span></span></pre>
<pre><span class="gmail-stdout"><span style="font-size:13.5pt;color:black"> #4 0xd85a55 in llvm::BranchInst::BranchInst(llvm::BasicBlock*, llvm::BasicBlock*, llvm::Value*, llvm::Instruction*) /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/lib/IR/Instructions.cpp:1148<o:p></o:p></span></span></pre>
<pre><span class="gmail-stdout"><span style="font-size:13.5pt;color:black"> #5 0x726734 in Create /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/include/llvm/IR/Instructions.h:3005:19<o:p></o:p></span></span></pre>
<pre><span class="gmail-stdout"><span style="font-size:13.5pt;color:black"> #6 0x726734 in CreateCondBr /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/include/llvm/IR/IRBuilder.h:778<o:p></o:p></span></span></pre>
<pre><span class="gmail-stdout"><span style="font-size:13.5pt;color:black"> #7 0x726734 in llvm::(anonymous namespace)::ScalarEvolutionsTest_SCEVExitLimitForgetLoop_Test::TestBody() /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/unittests/Analysis/ScalarEvolutionTest.cpp:1007<o:p></o:p></span></span></pre>
<pre><span class="gmail-stdout"><span style="font-size:13.5pt;color:black"> #8 0x1055261 in HandleExceptionsInMethodIfSupported<testing::Test, void> /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/utils/unittest/googletest/src/gtest.cc:2458:12<o:p></o:p></span></span></pre>
<pre><span class="gmail-stdout"><span style="font-size:13.5pt;color:black"> #9 0x1055261 in testing::Test::Run() /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/utils/unittest/googletest/src/gtest.cc:2474<o:p></o:p></span></span></pre>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<p class="MsoNormal">On Thu, Aug 3, 2017 at 1:41 AM, Max Kazantsev via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<o:p></o:p></p>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm">
<p class="MsoNormal">Author: mkazantsev<br>
Date: Thu Aug 3 01:41:30 2017<br>
New Revision: 309925<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=309925&view=rev" target="_blank">
http://llvm.org/viewvc/llvm-project?rev=309925&view=rev</a><br>
Log:<br>
[SCEV] Re-enable "Cache results of computeExitLimit"<br>
<br>
The patch rL309080 was reverted because it did not clean up the cache on "forgetValue"<br>
method call. This patch re-enables this change, adds the missing check and introduces<br>
two new unit tests that make sure that the cache is cleaned properly.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D36087" target="_blank">
https://reviews.llvm.org/D36087</a><br>
<br>
Added:<br>
llvm/trunk/test/Analysis/ScalarEvolution/cache_loop_exit_limit.ll<br>
Modified:<br>
llvm/trunk/include/llvm/Analysis/ScalarEvolution.h<br>
llvm/trunk/lib/Analysis/ScalarEvolution.cpp<br>
llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=309925&r1=309924&r2=309925&view=diff" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=309925&r1=309924&r2=309925&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)<br>
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Thu Aug 3 01:41:30 2017<br>
@@ -409,6 +409,32 @@ public:<br>
}<br>
};<br>
<br>
+struct ExitLimitQuery {<br>
+ ExitLimitQuery(const Loop *L, BasicBlock *ExitingBlock, bool AllowPredicates)<br>
+ : L(L), ExitingBlock(ExitingBlock), AllowPredicates(AllowPredicates) {}<br>
+<br>
+ const Loop *L;<br>
+ BasicBlock *ExitingBlock;<br>
+ bool AllowPredicates;<br>
+};<br>
+<br>
+template <> struct DenseMapInfo<ExitLimitQuery> {<br>
+ static inline ExitLimitQuery getEmptyKey() {<br>
+ return ExitLimitQuery(nullptr, nullptr, true);<br>
+ }<br>
+ static inline ExitLimitQuery getTombstoneKey() {<br>
+ return ExitLimitQuery(nullptr, nullptr, false);<br>
+ }<br>
+ static unsigned getHashValue(ExitLimitQuery Val) {<br>
+ return hash_combine(hash_combine(Val.L, Val.ExitingBlock),<br>
+ Val.AllowPredicates);<br>
+ }<br>
+ static bool isEqual(ExitLimitQuery LHS, ExitLimitQuery RHS) {<br>
+ return LHS.L == RHS.L && LHS.ExitingBlock == RHS.ExitingBlock &&<br>
+ LHS.AllowPredicates == RHS.AllowPredicates;<br>
+ }<br>
+};<br>
+<br>
/// The main scalar evolution driver. Because client code (intentionally)<br>
/// can't do much with the SCEV objects directly, they must ask this class<br>
/// for services.<br>
@@ -584,6 +610,8 @@ private:<br>
!isa<SCEVCouldNotCompute>(MaxNotTaken);<br>
}<br>
<br>
+ bool hasOperand(const SCEV *S) const;<br>
+<br>
/// Test whether this ExitLimit contains all information.<br>
bool hasFullInfo() const {<br>
return !isa<SCEVCouldNotCompute>(ExactNotTaken);<br>
@@ -704,6 +732,9 @@ private:<br>
/// function as they are computed.<br>
DenseMap<const Loop *, BackedgeTakenInfo> PredicatedBackedgeTakenCounts;<br>
<br>
+ // Cache the calculated exit limits for the loops.<br>
+ DenseMap<ExitLimitQuery, ExitLimit> ExitLimits;<br>
+<br>
/// This map contains entries for all of the PHI instructions that we<br>
/// attempt to compute constant evolutions for. This allows us to avoid<br>
/// potentially expensive recomputation of these properties. An instruction<br>
@@ -856,6 +887,9 @@ private:<br>
ExitLimit computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,<br>
bool AllowPredicates = false);<br>
<br>
+ ExitLimit computeExitLimitImpl(const Loop *L, BasicBlock *ExitingBlock,<br>
+ bool AllowPredicates = false);<br>
+<br>
/// Compute the number of times the backedge of the specified loop will<br>
/// execute if its exit condition were a conditional branch of ExitCond,<br>
/// TBB, and FBB.<br>
@@ -1095,8 +1129,9 @@ private:<br>
/// to be a constant.<br>
Optional<APInt> computeConstantDifference(const SCEV *LHS, const SCEV *RHS);<br>
<br>
- /// Drop memoized information computed for S.<br>
- void forgetMemoizedResults(const SCEV *S);<br>
+ /// Drop memoized information computed for S. Only erase Exit Limits info if<br>
+ /// we expect that the operation we have made is going to change it.<br>
+ void forgetMemoizedResults(const SCEV *S, bool EraseExitLimit = true);<br>
<br>
/// Return an existing SCEV for V if there is one, otherwise return nullptr.<br>
const SCEV *getExistingSCEV(Value *V);<br>
<br>
Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=309925&r1=309924&r2=309925&view=diff" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=309925&r1=309924&r2=309925&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)<br>
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Thu Aug 3 01:41:30 2017<br>
@@ -6200,7 +6200,7 @@ ScalarEvolution::getBackedgeTakenInfo(co<br>
// own when it gets to that point.<br>
if (!isa<PHINode>(I) || !isa<SCEVUnknown>(Old)) {<br>
eraseValueFromMap(It->first);<br>
- forgetMemoizedResults(Old);<br>
+ forgetMemoizedResults(Old, false);<br>
}<br>
if (PHINode *PN = dyn_cast<PHINode>(I))<br>
ConstantEvolutionLoopExitValue.erase(PN);<br>
@@ -6264,6 +6264,12 @@ void ScalarEvolution::forgetLoop(const L<br>
PushDefUseChildren(I, Worklist);<br>
}<br>
<br>
+ for (auto I = ExitLimits.begin(); I != ExitLimits.end(); ++I) {<br>
+ auto &Query = I->first;<br>
+ if (Query.L == L)<br>
+ ExitLimits.erase(I);<br>
+ }<br>
+<br>
// Forget all contained loops too, to avoid dangling entries in the<br>
// ValuesAtScopes map.<br>
for (Loop *I : *L)<br>
@@ -6526,6 +6532,18 @@ ScalarEvolution::computeBackedgeTakenCou<br>
ScalarEvolution::ExitLimit<br>
ScalarEvolution::computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,<br>
bool AllowPredicates) {<br>
+ ExitLimitQuery Query(L, ExitingBlock, AllowPredicates);<br>
+ auto MaybeEL = ExitLimits.find(Query);<br>
+ if (MaybeEL != ExitLimits.end())<br>
+ return MaybeEL->second;<br>
+ ExitLimit EL = computeExitLimitImpl(L, ExitingBlock, AllowPredicates);<br>
+ ExitLimits.insert({Query, EL});<br>
+ return EL;<br>
+}<br>
+<br>
+ScalarEvolution::ExitLimit<br>
+ScalarEvolution::computeExitLimitImpl(const Loop *L, BasicBlock *ExitingBlock,<br>
+ bool AllowPredicates) {<br>
<br>
// Okay, we've chosen an exiting block. See what condition causes us to exit<br>
// at this block and remember the exit block and whether all other targets<br>
@@ -10408,6 +10426,7 @@ ScalarEvolution::ScalarEvolution(ScalarE<br>
BackedgeTakenCounts(std::move(Arg.BackedgeTakenCounts)),<br>
PredicatedBackedgeTakenCounts(<br>
std::move(Arg.PredicatedBackedgeTakenCounts)),<br>
+ ExitLimits(std::move(Arg.ExitLimits)),<br>
ConstantEvolutionLoopExitValue(<br>
std::move(Arg.ConstantEvolutionLoopExitValue)),<br>
ValuesAtScopes(std::move(Arg.ValuesAtScopes)),<br>
@@ -10810,7 +10829,16 @@ bool ScalarEvolution::hasOperand(const S<br>
return SCEVExprContains(S, [&](const SCEV *Expr) { return Expr == Op; });<br>
}<br>
<br>
-void ScalarEvolution::forgetMemoizedResults(const SCEV *S) {<br>
+bool ScalarEvolution::ExitLimit::hasOperand(const SCEV *S) const {<br>
+ auto IsS = [&](const SCEV *X) { return S == X; };<br>
+ auto ContainsS = [&](const SCEV *X) {<br>
+ return !isa<SCEVCouldNotCompute>(X) && SCEVExprContains(X, IsS);<br>
+ };<br>
+ return ContainsS(ExactNotTaken) || ContainsS(MaxNotTaken);<br>
+}<br>
+<br>
+void<br>
+ScalarEvolution::forgetMemoizedResults(const SCEV *S, bool EraseExitLimit) {<br>
ValuesAtScopes.erase(S);<br>
LoopDispositions.erase(S);<br>
BlockDispositions.erase(S);<br>
@@ -10843,6 +10871,13 @@ void ScalarEvolution::forgetMemoizedResu<br>
<br>
RemoveSCEVFromBackedgeMap(BackedgeTakenCounts);<br>
RemoveSCEVFromBackedgeMap(PredicatedBackedgeTakenCounts);<br>
+<br>
+ // TODO: There is a suspicion that we only need to do it when there is a<br>
+ // SCEVUnknown somewhere inside S. Need to check this.<br>
+ if (EraseExitLimit)<br>
+ for (auto I = ExitLimits.begin(), E = ExitLimits.end(); I != E; ++I)<br>
+ if (I->second.hasOperand(S))<br>
+ ExitLimits.erase(I);<br>
}<br>
<br>
void ScalarEvolution::verify() const {<br>
<br>
Added: llvm/trunk/test/Analysis/ScalarEvolution/cache_loop_exit_limit.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/cache_loop_exit_limit.ll?rev=309925&view=auto" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/cache_loop_exit_limit.ll?rev=309925&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Analysis/ScalarEvolution/cache_loop_exit_limit.ll (added)<br>
+++ llvm/trunk/test/Analysis/ScalarEvolution/cache_loop_exit_limit.ll Thu Aug 3 01:41:30 2017<br>
@@ -0,0 +1,253 @@<br>
+; RUN: opt -scalar-evolution-max-arith-depth=4 -scalar-evolution-max-add-rec-size=4 -loop-reduce -S < %s | FileCheck %s<br>
+<br>
+; Check that the test does not hang.<br>
+define void @test_01(i32* nocapture %a) local_unnamed_addr {<br>
+<br>
+; CHECK-LABEL: @test_01(<br>
+<br>
+while.body.outer:<br>
+ %arrayidx2 = getelementptr inbounds i32, i32* %a, i64 96<br>
+ %arrayidx2.promoted50 = load i32, i32* %arrayidx2, align 1<br>
+ %a.promoted = load i32, i32* %a, align 1<br>
+ %add347.peel = xor i32 %arrayidx2.promoted50, -1<br>
+ %tobool48.peel = icmp eq i32 %a.promoted, %add347.peel<br>
+ br i1 %tobool48.peel, label %while.body.preheader, label %while.body4.preheader<br>
+<br>
+while.body.preheader: ; preds = %while.body.outer<br>
+ %tobool48 = icmp eq i32 %a.promoted, 1<br>
+ br label %while.body<br>
+<br>
+while.body: ; preds = %while.body.preheader, %while.body<br>
+ br i1 %tobool48, label %while.body, label %while.body4.preheader.loopexit<br>
+<br>
+while.body4.preheader.loopexit: ; preds = %while.body<br>
+ br label %while.body4.preheader<br>
+<br>
+while.body4.preheader: ; preds = %while.body4.preheader.loopexit, %while.body.outer<br>
+ br label %while.body4<br>
+<br>
+while.body4: ; preds = %while.body4.preheader, %while.end.22<br>
+ %0 = phi i32 [ %mul.22, %while.end.22 ], [ %arrayidx2.promoted50, %while.body4.preheader ]<br>
+ %mul = mul nsw i32 %0, %0<br>
+ br label %while.cond17<br>
+<br>
+while.cond17: ; preds = %while.cond17, %while.body4<br>
+ %add22.sink = phi i32 [ %add22, %while.cond17 ], [ %mul, %while.body4 ]<br>
+ %cmp = icmp slt i32 %add22.sink, 0<br>
+ %add22 = add nsw i32 %add22.sink, 1024<br>
+ br i1 %cmp, label %while.cond17, label %while.end<br>
+<br>
+while.end: ; preds = %while.cond17<br>
+ %mul.1 = mul nsw i32 %add22.sink, %add22.sink<br>
+ br label %while.cond17.1<br>
+<br>
+while.cond17.1: ; preds = %while.cond17.1, %while.end<br>
+ %add22.sink.1 = phi i32 [ %add22.1, %while.cond17.1 ], [ %mul.1, %while.end ]<br>
+ %cmp.1 = icmp slt i32 %add22.sink.1, 0<br>
+ %add22.1 = add nsw i32 %add22.sink.1, 2048<br>
+ br i1 %cmp.1, label %while.cond17.1, label %while.end.1<br>
+<br>
+while.end.1: ; preds = %while.cond17.1<br>
+ %mul.2 = mul nsw i32 %add22.sink.1, %add22.sink.1<br>
+ br label %while.cond17.2<br>
+<br>
+while.cond17.2: ; preds = %while.cond17.2, %while.end.1<br>
+ %add22.sink.2 = phi i32 [ %add22.2, %while.cond17.2 ], [ %mul.2, %while.end.1 ]<br>
+ %cmp.2 = icmp slt i32 %add22.sink.2, 0<br>
+ %add22.2 = add nsw i32 %add22.sink.2, 4096<br>
+ br i1 %cmp.2, label %while.cond17.2, label %while.end.2<br>
+<br>
+while.end.2: ; preds = %while.cond17.2<br>
+ %mul.3 = mul nsw i32 %add22.sink.2, %add22.sink.2<br>
+ br label %while.cond17.3<br>
+<br>
+while.cond17.3: ; preds = %while.cond17.3, %while.end.2<br>
+ %add22.sink.3 = phi i32 [ %add22.3, %while.cond17.3 ], [ %mul.3, %while.end.2 ]<br>
+ %cmp.3 = icmp slt i32 %add22.sink.3, 0<br>
+ %add22.3 = add nsw i32 %add22.sink.3, 8192<br>
+ br i1 %cmp.3, label %while.cond17.3, label %while.end.3<br>
+<br>
+while.end.3: ; preds = %while.cond17.3<br>
+ %mul.4 = mul nsw i32 %add22.sink.3, %add22.sink.3<br>
+ br label %while.cond17.4<br>
+<br>
+while.cond17.4: ; preds = %while.cond17.4, %while.end.3<br>
+ %add22.sink.4 = phi i32 [ %add22.4, %while.cond17.4 ], [ %mul.4, %while.end.3 ]<br>
+ %cmp.4 = icmp slt i32 %add22.sink.4, 0<br>
+ %add22.4 = add nsw i32 %add22.sink.4, 16384<br>
+ br i1 %cmp.4, label %while.cond17.4, label %while.end.4<br>
+<br>
+while.end.4: ; preds = %while.cond17.4<br>
+ %mul.5 = mul nsw i32 %add22.sink.4, %add22.sink.4<br>
+ br label %while.cond17.5<br>
+<br>
+while.cond17.5: ; preds = %while.cond17.5, %while.end.4<br>
+ %add22.sink.5 = phi i32 [ %add22.5, %while.cond17.5 ], [ %mul.5, %while.end.4 ]<br>
+ %cmp.5 = icmp slt i32 %add22.sink.5, 0<br>
+ %add22.5 = add nsw i32 %add22.sink.5, 32768<br>
+ br i1 %cmp.5, label %while.cond17.5, label %while.end.5<br>
+<br>
+while.end.5: ; preds = %while.cond17.5<br>
+ %mul.6 = mul nsw i32 %add22.sink.5, %add22.sink.5<br>
+ br label %while.cond17.6<br>
+<br>
+while.cond17.6: ; preds = %while.cond17.6, %while.end.5<br>
+ %add22.sink.6 = phi i32 [ %add22.6, %while.cond17.6 ], [ %mul.6, %while.end.5 ]<br>
+ %cmp.6 = icmp slt i32 %add22.sink.6, 0<br>
+ %add22.6 = add nsw i32 %add22.sink.6, 65536<br>
+ br i1 %cmp.6, label %while.cond17.6, label %while.end.6<br>
+<br>
+while.end.6: ; preds = %while.cond17.6<br>
+ %mul.7 = mul nsw i32 %add22.sink.6, %add22.sink.6<br>
+ br label %while.cond17.7<br>
+<br>
+while.cond17.7: ; preds = %while.cond17.7, %while.end.6<br>
+ %add22.sink.7 = phi i32 [ %add22.7, %while.cond17.7 ], [ %mul.7, %while.end.6 ]<br>
+ %cmp.7 = icmp slt i32 %add22.sink.7, 0<br>
+ %add22.7 = add nsw i32 %add22.sink.7, 131072<br>
+ br i1 %cmp.7, label %while.cond17.7, label %while.end.7<br>
+<br>
+while.end.7: ; preds = %while.cond17.7<br>
+ %mul.8 = mul nsw i32 %add22.sink.7, %add22.sink.7<br>
+ br label %while.cond17.8<br>
+<br>
+while.cond17.8: ; preds = %while.cond17.8, %while.end.7<br>
+ %add22.sink.8 = phi i32 [ %add22.8, %while.cond17.8 ], [ %mul.8, %while.end.7 ]<br>
+ %cmp.8 = icmp slt i32 %add22.sink.8, 0<br>
+ %add22.8 = add nsw i32 %add22.sink.8, 262144<br>
+ br i1 %cmp.8, label %while.cond17.8, label %while.end.8<br>
+<br>
+while.end.8: ; preds = %while.cond17.8<br>
+ %mul.9 = mul nsw i32 %add22.sink.8, %add22.sink.8<br>
+ br label %while.cond17.9<br>
+<br>
+while.cond17.9: ; preds = %while.cond17.9, %while.end.8<br>
+ %add22.sink.9 = phi i32 [ %add22.9, %while.cond17.9 ], [ %mul.9, %while.end.8 ]<br>
+ %cmp.9 = icmp slt i32 %add22.sink.9, 0<br>
+ %add22.9 = add nsw i32 %add22.sink.9, 524288<br>
+ br i1 %cmp.9, label %while.cond17.9, label %while.end.9<br>
+<br>
+while.end.9: ; preds = %while.cond17.9<br>
+ %mul.10 = mul nsw i32 %add22.sink.9, %add22.sink.9<br>
+ br label %while.cond17.10<br>
+<br>
+while.cond17.10: ; preds = %while.cond17.10, %while.end.9<br>
+ %add22.sink.10 = phi i32 [ %add22.10, %while.cond17.10 ], [ %mul.10, %while.end.9 ]<br>
+ %cmp.10 = icmp slt i32 %add22.sink.10, 0<br>
+ %add22.10 = add nsw i32 %add22.sink.10, 1048576<br>
+ br i1 %cmp.10, label %while.cond17.10, label %while.end.10<br>
+<br>
+while.end.10: ; preds = %while.cond17.10<br>
+ %mul.11 = mul nsw i32 %add22.sink.10, %add22.sink.10<br>
+ br label %while.cond17.11<br>
+<br>
+while.cond17.11: ; preds = %while.cond17.11, %while.end.10<br>
+ %add22.sink.11 = phi i32 [ %add22.11, %while.cond17.11 ], [ %mul.11, %while.end.10 ]<br>
+ %cmp.11 = icmp slt i32 %add22.sink.11, 0<br>
+ %add22.11 = add nsw i32 %add22.sink.11, 2097152<br>
+ br i1 %cmp.11, label %while.cond17.11, label %while.end.11<br>
+<br>
+while.end.11: ; preds = %while.cond17.11<br>
+ %mul.12 = mul nsw i32 %add22.sink.11, %add22.sink.11<br>
+ br label %while.cond17.12<br>
+<br>
+while.cond17.12: ; preds = %while.cond17.12, %while.end.11<br>
+ %add22.sink.12 = phi i32 [ %add22.12, %while.cond17.12 ], [ %mul.12, %while.end.11 ]<br>
+ %cmp.12 = icmp slt i32 %add22.sink.12, 0<br>
+ %add22.12 = add nsw i32 %add22.sink.12, 4194304<br>
+ br i1 %cmp.12, label %while.cond17.12, label %while.end.12<br>
+<br>
+while.end.12: ; preds = %while.cond17.12<br>
+ %mul.13 = mul nsw i32 %add22.sink.12, %add22.sink.12<br>
+ br label %while.cond17.13<br>
+<br>
+while.cond17.13: ; preds = %while.cond17.13, %while.end.12<br>
+ %add22.sink.13 = phi i32 [ %add22.13, %while.cond17.13 ], [ %mul.13, %while.end.12 ]<br>
+ %cmp.13 = icmp slt i32 %add22.sink.13, 0<br>
+ %add22.13 = add nsw i32 %add22.sink.13, 8388608<br>
+ br i1 %cmp.13, label %while.cond17.13, label %while.end.13<br>
+<br>
+while.end.13: ; preds = %while.cond17.13<br>
+ %mul.14 = mul nsw i32 %add22.sink.13, %add22.sink.13<br>
+ br label %while.cond17.14<br>
+<br>
+while.cond17.14: ; preds = %while.cond17.14, %while.end.13<br>
+ %add22.sink.14 = phi i32 [ %add22.14, %while.cond17.14 ], [ %mul.14, %while.end.13 ]<br>
+ %cmp.14 = icmp slt i32 %add22.sink.14, 0<br>
+ %add22.14 = add nsw i32 %add22.sink.14, 16777216<br>
+ br i1 %cmp.14, label %while.cond17.14, label %while.end.14<br>
+<br>
+while.end.14: ; preds = %while.cond17.14<br>
+ %mul.15 = mul nsw i32 %add22.sink.14, %add22.sink.14<br>
+ br label %while.cond17.15<br>
+<br>
+while.cond17.15: ; preds = %while.cond17.15, %while.end.14<br>
+ %add22.sink.15 = phi i32 [ %add22.15, %while.cond17.15 ], [ %mul.15, %while.end.14 ]<br>
+ %cmp.15 = icmp slt i32 %add22.sink.15, 0<br>
+ %add22.15 = add nsw i32 %add22.sink.15, 33554432<br>
+ br i1 %cmp.15, label %while.cond17.15, label %while.end.15<br>
+<br>
+while.end.15: ; preds = %while.cond17.15<br>
+ %mul.16 = mul nsw i32 %add22.sink.15, %add22.sink.15<br>
+ br label %while.cond17.16<br>
+<br>
+while.cond17.16: ; preds = %while.cond17.16, %while.end.15<br>
+ %add22.sink.16 = phi i32 [ %add22.16, %while.cond17.16 ], [ %mul.16, %while.end.15 ]<br>
+ %cmp.16 = icmp slt i32 %add22.sink.16, 0<br>
+ %add22.16 = add nsw i32 %add22.sink.16, 67108864<br>
+ br i1 %cmp.16, label %while.cond17.16, label %while.end.16<br>
+<br>
+while.end.16: ; preds = %while.cond17.16<br>
+ %mul.17 = mul nsw i32 %add22.sink.16, %add22.sink.16<br>
+ br label %while.cond17.17<br>
+<br>
+while.cond17.17: ; preds = %while.cond17.17, %while.end.16<br>
+ %add22.sink.17 = phi i32 [ %add22.17, %while.cond17.17 ], [ %mul.17, %while.end.16 ]<br>
+ %cmp.17 = icmp slt i32 %add22.sink.17, 0<br>
+ %add22.17 = add nsw i32 %add22.sink.17, 134217728<br>
+ br i1 %cmp.17, label %while.cond17.17, label %while.end.17<br>
+<br>
+while.end.17: ; preds = %while.cond17.17<br>
+ %mul.18 = mul nsw i32 %add22.sink.17, %add22.sink.17<br>
+ br label %while.cond17.18<br>
+<br>
+while.cond17.18: ; preds = %while.cond17.18, %while.end.17<br>
+ %add22.sink.18 = phi i32 [ %add22.18, %while.cond17.18 ], [ %mul.18, %while.end.17 ]<br>
+ %cmp.18 = icmp slt i32 %add22.sink.18, 0<br>
+ %add22.18 = add nsw i32 %add22.sink.18, 268435456<br>
+ br i1 %cmp.18, label %while.cond17.18, label %while.end.18<br>
+<br>
+while.end.18: ; preds = %while.cond17.18<br>
+ %mul.19 = mul nsw i32 %add22.sink.18, %add22.sink.18<br>
+ br label %while.cond17.19<br>
+<br>
+while.cond17.19: ; preds = %while.cond17.19, %while.end.18<br>
+ %add22.sink.19 = phi i32 [ %add22.19, %while.cond17.19 ], [ %mul.19, %while.end.18 ]<br>
+ %cmp.19 = icmp slt i32 %add22.sink.19, 0<br>
+ %add22.19 = add nsw i32 %add22.sink.19, 536870912<br>
+ br i1 %cmp.19, label %while.cond17.19, label %while.end.19<br>
+<br>
+while.end.19: ; preds = %while.cond17.19<br>
+ %mul.20 = mul nsw i32 %add22.sink.19, %add22.sink.19<br>
+ br label %while.cond17.20<br>
+<br>
+while.cond17.20: ; preds = %while.cond17.20, %while.end.19<br>
+ %add22.sink.20 = phi i32 [ %add22.20, %while.cond17.20 ], [ %mul.20, %while.end.19 ]<br>
+ %cmp.20 = icmp slt i32 %add22.sink.20, 0<br>
+ %add22.20 = add nsw i32 %add22.sink.20, 1073741824<br>
+ br i1 %cmp.20, label %while.cond17.20, label %while.end.20<br>
+<br>
+while.end.20: ; preds = %while.cond17.20<br>
+ %mul.21 = mul nsw i32 %add22.sink.20, %add22.sink.20<br>
+ br label %while.cond17.21<br>
+<br>
+while.cond17.21: ; preds = %while.cond17.21, %while.end.20<br>
+ %add22.sink.21 = phi i32 [ %add22.21, %while.cond17.21 ], [ %mul.21, %while.end.20 ]<br>
+ %cmp.21 = icmp slt i32 %add22.sink.21, 0<br>
+ %add22.21 = or i32 %add22.sink.21, -2147483648<br>
+ br i1 %cmp.21, label %while.cond17.21, label %while.end.22<br>
+<br>
+while.end.22: ; preds = %while.cond17.21<br>
+ %mul.22 = mul nsw i32 %add22.sink.21, %add22.sink.21<br>
+ br label %while.body4<br>
+}<br>
<br>
Modified: llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp?rev=309925&r1=309924&r2=309925&view=diff" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp?rev=309925&r1=309924&r2=309925&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp (original)<br>
+++ llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp Thu Aug 3 01:41:30 2017<br>
@@ -930,5 +930,165 @@ TEST_F(ScalarEvolutionsTest, SCEVZeroExt<br>
EXPECT_FALSE(verifyFunction(*F, &errs()));<br>
}<br>
<br>
+// Make sure that SCEV invalidates exit limits after invalidating the values it<br>
+// depends on when we forget a loop.<br>
+TEST_F(ScalarEvolutionsTest, SCEVExitLimitForgetLoop) {<br>
+ /*<br>
+ * Create the following code:<br>
+ * func(i64 addrspace(10)* %arg)<br>
+ * top:<br>
+ * br label %L.ph<br>
+ * L.ph:<br>
+ * br label %L<br>
+ * L:<br>
+ * %phi = phi i64 [i64 0, %L.ph], [ %add, %L2 ]<br>
+ * %add = add i64 %phi2, 1<br>
+ * %cond = icmp slt i64 %add, 1000; then becomes 2000.<br>
+ * br i1 %cond, label %post, label %L2<br>
+ * post:<br>
+ * ret void<br>
+ *<br>
+ */<br>
+<br>
+ // Create a module with non-integral pointers in it's datalayout<br>
+ Module NIM("nonintegral", Context);<br>
+ std::string DataLayout = M.getDataLayoutStr();<br>
+ if (!DataLayout.empty())<br>
+ DataLayout += "-";<br>
+ DataLayout += "ni:10";<br>
+ NIM.setDataLayout(DataLayout);<br>
+<br>
+ Type *T_int64 = Type::getInt64Ty(Context);<br>
+ Type *T_pint64 = T_int64->getPointerTo(10);<br>
+<br>
+ FunctionType *FTy =<br>
+ FunctionType::get(Type::getVoidTy(Context), {T_pint64}, false);<br>
+ Function *F = cast<Function>(NIM.getOrInsertFunction("foo", FTy));<br>
+<br>
+ Argument *Arg = &*F->arg_begin();<br>
+<br>
+ BasicBlock *Top = BasicBlock::Create(Context, "top", F);<br>
+ BasicBlock *LPh = BasicBlock::Create(Context, "L.ph", F);<br>
+ BasicBlock *L = BasicBlock::Create(Context, "L", F);<br>
+ BasicBlock *Post = BasicBlock::Create(Context, "post", F);<br>
+<br>
+ IRBuilder<> Builder(Top);<br>
+ Builder.CreateBr(LPh);<br>
+<br>
+ Builder.SetInsertPoint(LPh);<br>
+ Builder.CreateBr(L);<br>
+<br>
+ Builder.SetInsertPoint(L);<br>
+ PHINode *Phi = Builder.CreatePHI(T_int64, 2);<br>
+ auto *Add = cast<Instruction>(<br>
+ Builder.CreateAdd(Phi, ConstantInt::get(T_int64, 1), "add"));<br>
+ auto *Limit = ConstantInt::get(T_int64, 1000);<br>
+ auto *Cond = cast<Instruction>(<br>
+ Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, Limit, "cond"));<br>
+ auto *Br = cast<Instruction>(Builder.CreateCondBr(Cond, L, Post));<br>
+ Phi->addIncoming(ConstantInt::get(T_int64, 0), LPh);<br>
+ Phi->addIncoming(Add, L);<br>
+<br>
+ Builder.SetInsertPoint(Post);<br>
+ Builder.CreateRetVoid();<br>
+<br>
+ ScalarEvolution SE = buildSE(*F);<br>
+ auto *Loop = LI->getLoopFor(L);<br>
+ const SCEV *EC = SE.getBackedgeTakenCount(Loop);<br>
+ EXPECT_FALSE(isa<SCEVCouldNotCompute>(EC));<br>
+<br>
+ SE.forgetLoop(Loop);<br>
+ Br->eraseFromParent();<br>
+ Cond->eraseFromParent();<br>
+<br>
+ Builder.SetInsertPoint(L);<br>
+ Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, ConstantInt::get(T_int64, 2000),<br>
+ "new.cond");<br>
+ Builder.CreateCondBr(Cond, L, Post);<br>
+ const SCEV *NewEC = SE.getBackedgeTakenCount(Loop);<br>
+ EXPECT_NE(EC, NewEC);<br>
+}<br>
+<br>
+// Make sure that SCEV invalidates exit limits after invalidating the values it<br>
+// depends on when we forget a value.<br>
+TEST_F(ScalarEvolutionsTest, SCEVExitLimitForgetValue) {<br>
+ /*<br>
+ * Create the following code:<br>
+ * func(i64 addrspace(10)* %arg)<br>
+ * top:<br>
+ * br label %L.ph<br>
+ * L.ph:<br>
+ * %load = load i64 addrspace(10)* %arg<br>
+ * br label %L<br>
+ * L:<br>
+ * %phi = phi i64 [i64 0, %L.ph], [ %add, %L2 ]<br>
+ * %add = add i64 %phi2, 1<br>
+ * %cond = icmp slt i64 %add, %load ; then becomes 2000.<br>
+ * br i1 %cond, label %post, label %L2<br>
+ * post:<br>
+ * ret void<br>
+ *<br>
+ */<br>
+<br>
+ // Create a module with non-integral pointers in it's datalayout<br>
+ Module NIM("nonintegral", Context);<br>
+ std::string DataLayout = M.getDataLayoutStr();<br>
+ if (!DataLayout.empty())<br>
+ DataLayout += "-";<br>
+ DataLayout += "ni:10";<br>
+ NIM.setDataLayout(DataLayout);<br>
+<br>
+ Type *T_int64 = Type::getInt64Ty(Context);<br>
+ Type *T_pint64 = T_int64->getPointerTo(10);<br>
+<br>
+ FunctionType *FTy =<br>
+ FunctionType::get(Type::getVoidTy(Context), {T_pint64}, false);<br>
+ Function *F = cast<Function>(NIM.getOrInsertFunction("foo", FTy));<br>
+<br>
+ Argument *Arg = &*F->arg_begin();<br>
+<br>
+ BasicBlock *Top = BasicBlock::Create(Context, "top", F);<br>
+ BasicBlock *LPh = BasicBlock::Create(Context, "L.ph", F);<br>
+ BasicBlock *L = BasicBlock::Create(Context, "L", F);<br>
+ BasicBlock *Post = BasicBlock::Create(Context, "post", F);<br>
+<br>
+ IRBuilder<> Builder(Top);<br>
+ Builder.CreateBr(LPh);<br>
+<br>
+ Builder.SetInsertPoint(LPh);<br>
+ auto *Load = cast<Instruction>(Builder.CreateLoad(T_int64, Arg, "load"));<br>
+ Builder.CreateBr(L);<br>
+<br>
+ Builder.SetInsertPoint(L);<br>
+ PHINode *Phi = Builder.CreatePHI(T_int64, 2);<br>
+ auto *Add = cast<Instruction>(<br>
+ Builder.CreateAdd(Phi, ConstantInt::get(T_int64, 1), "add"));<br>
+ auto *Cond = cast<Instruction>(<br>
+ Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, Load, "cond"));<br>
+ auto *Br = cast<Instruction>(Builder.CreateCondBr(Cond, L, Post));<br>
+ Phi->addIncoming(ConstantInt::get(T_int64, 0), LPh);<br>
+ Phi->addIncoming(Add, L);<br>
+<br>
+ Builder.SetInsertPoint(Post);<br>
+ Builder.CreateRetVoid();<br>
+<br>
+ ScalarEvolution SE = buildSE(*F);<br>
+ auto *Loop = LI->getLoopFor(L);<br>
+ const SCEV *EC = SE.getBackedgeTakenCount(Loop);<br>
+ EXPECT_FALSE(isa<SCEVCouldNotCompute>(EC));<br>
+<br>
+ SE.forgetValue(Load);<br>
+ Br->eraseFromParent();<br>
+ Cond->eraseFromParent();<br>
+ Load->eraseFromParent();<br>
+<br>
+ Builder.SetInsertPoint(L);<br>
+ Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, ConstantInt::get(T_int64, 2000),<br>
+ "new.cond");<br>
+ Builder.CreateCondBr(Cond, L, Post);<br>
+ const SCEV *NewEC = SE.getBackedgeTakenCount(Loop);<br>
+ EXPECT_NE(EC, NewEC);<br>
+}<br>
+<br>
} // end anonymous namespace<br>
} // end namespace llvm<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><o:p></o:p></p>
</blockquote>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</div>
</body>
</html>