[llvm] r309925 - [SCEV] Re-enable "Cache results of computeExitLimit"

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 3 13:54:12 PDT 2017


http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/1960/steps/check-llvm%20asan/logs/stdio


[ RUN      ] ScalarEvolutionsTest.SCEVExitLimitForgetLoop
===================================================================9898==ERROR:
AddressSanitizer: heap-use-after-free on address 0x60b000012ce8 at pc
0x000000d85a56 bp 0x7ffeaee9b0b0 sp 0x7ffeaee9b0a8
READ of size 8 at 0x60b000012ce8 thread T0
    #0 0xd85a55 in addToList
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/include/llvm/IR/Use.h:149:12
    #1 0xd85a55 in addUse
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/include/llvm/IR/Value.h:432
    #2 0xd85a55 in set
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/include/llvm/IR/Value.h:674
    #3 0xd85a55 in operator=
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/include/llvm/IR/Value.h:678
    #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
    #5 0x726734 in Create
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/include/llvm/IR/Instructions.h:3005:19
    #6 0x726734 in CreateCondBr
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/include/llvm/IR/IRBuilder.h:778
    #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
    #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
    #9 0x1055261 in testing::Test::Run()
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/utils/unittest/googletest/src/gtest.cc:2474



On Thu, Aug 3, 2017 at 1:41 AM, Max Kazantsev via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: mkazantsev
> Date: Thu Aug  3 01:41:30 2017
> New Revision: 309925
>
> URL: http://llvm.org/viewvc/llvm-project?rev=309925&view=rev
> Log:
> [SCEV] Re-enable "Cache results of computeExitLimit"
>
> The patch rL309080 was reverted because it did not clean up the cache on
> "forgetValue"
> method call. This patch re-enables this change, adds the missing check and
> introduces
> two new unit tests that make sure that the cache is cleaned properly.
>
> Differential Revision: https://reviews.llvm.org/D36087
>
> Added:
>     llvm/trunk/test/Analysis/ScalarEvolution/cache_loop_exit_limit.ll
> Modified:
>     llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
>     llvm/trunk/lib/Analysis/ScalarEvolution.cpp
>     llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp
>
> Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/
> llvm/Analysis/ScalarEvolution.h?rev=309925&r1=309924&r2=309925&view=diff
> ============================================================
> ==================
> --- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)
> +++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Thu Aug  3
> 01:41:30 2017
> @@ -409,6 +409,32 @@ public:
>    }
>  };
>
> +struct ExitLimitQuery {
> +  ExitLimitQuery(const Loop *L, BasicBlock *ExitingBlock, bool
> AllowPredicates)
> +      : L(L), ExitingBlock(ExitingBlock), AllowPredicates(AllowPredicates)
> {}
> +
> +  const Loop *L;
> +  BasicBlock *ExitingBlock;
> +  bool AllowPredicates;
> +};
> +
> +template <> struct DenseMapInfo<ExitLimitQuery> {
> +  static inline ExitLimitQuery getEmptyKey() {
> +    return ExitLimitQuery(nullptr, nullptr, true);
> +  }
> +  static inline ExitLimitQuery getTombstoneKey() {
> +    return ExitLimitQuery(nullptr, nullptr, false);
> +  }
> +  static unsigned getHashValue(ExitLimitQuery Val) {
> +    return hash_combine(hash_combine(Val.L, Val.ExitingBlock),
> +                        Val.AllowPredicates);
> +  }
> +  static bool isEqual(ExitLimitQuery LHS, ExitLimitQuery RHS) {
> +    return LHS.L == RHS.L && LHS.ExitingBlock == RHS.ExitingBlock &&
> +           LHS.AllowPredicates == RHS.AllowPredicates;
> +  }
> +};
> +
>  /// The main scalar evolution driver. Because client code (intentionally)
>  /// can't do much with the SCEV objects directly, they must ask this class
>  /// for services.
> @@ -584,6 +610,8 @@ private:
>               !isa<SCEVCouldNotCompute>(MaxNotTaken);
>      }
>
> +    bool hasOperand(const SCEV *S) const;
> +
>      /// Test whether this ExitLimit contains all information.
>      bool hasFullInfo() const {
>        return !isa<SCEVCouldNotCompute>(ExactNotTaken);
> @@ -704,6 +732,9 @@ private:
>    /// function as they are computed.
>    DenseMap<const Loop *, BackedgeTakenInfo> PredicatedBackedgeTakenCounts;
>
> +  // Cache the calculated exit limits for the loops.
> +  DenseMap<ExitLimitQuery, ExitLimit> ExitLimits;
> +
>    /// This map contains entries for all of the PHI instructions that we
>    /// attempt to compute constant evolutions for.  This allows us to avoid
>    /// potentially expensive recomputation of these properties.  An
> instruction
> @@ -856,6 +887,9 @@ private:
>    ExitLimit computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,
>                               bool AllowPredicates = false);
>
> +  ExitLimit computeExitLimitImpl(const Loop *L, BasicBlock *ExitingBlock,
> +                                 bool AllowPredicates = false);
> +
>    /// Compute the number of times the backedge of the specified loop will
>    /// execute if its exit condition were a conditional branch of ExitCond,
>    /// TBB, and FBB.
> @@ -1095,8 +1129,9 @@ private:
>    /// to be a constant.
>    Optional<APInt> computeConstantDifference(const SCEV *LHS, const SCEV
> *RHS);
>
> -  /// Drop memoized information computed for S.
> -  void forgetMemoizedResults(const SCEV *S);
> +  /// Drop memoized information computed for S. Only erase Exit Limits
> info if
> +  /// we expect that the operation we have made is going to change it.
> +  void forgetMemoizedResults(const SCEV *S, bool EraseExitLimit = true);
>
>    /// Return an existing SCEV for V if there is one, otherwise return
> nullptr.
>    const SCEV *getExistingSCEV(Value *V);
>
> Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> Analysis/ScalarEvolution.cpp?rev=309925&r1=309924&r2=309925&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
> +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Thu Aug  3 01:41:30 2017
> @@ -6200,7 +6200,7 @@ ScalarEvolution::getBackedgeTakenInfo(co
>          // own when it gets to that point.
>          if (!isa<PHINode>(I) || !isa<SCEVUnknown>(Old)) {
>            eraseValueFromMap(It->first);
> -          forgetMemoizedResults(Old);
> +          forgetMemoizedResults(Old, false);
>          }
>          if (PHINode *PN = dyn_cast<PHINode>(I))
>            ConstantEvolutionLoopExitValue.erase(PN);
> @@ -6264,6 +6264,12 @@ void ScalarEvolution::forgetLoop(const L
>      PushDefUseChildren(I, Worklist);
>    }
>
> +  for (auto I = ExitLimits.begin(); I != ExitLimits.end(); ++I) {
> +    auto &Query = I->first;
> +    if (Query.L == L)
> +      ExitLimits.erase(I);
> +  }
> +
>    // Forget all contained loops too, to avoid dangling entries in the
>    // ValuesAtScopes map.
>    for (Loop *I : *L)
> @@ -6526,6 +6532,18 @@ ScalarEvolution::computeBackedgeTakenCou
>  ScalarEvolution::ExitLimit
>  ScalarEvolution::computeExitLimit(const Loop *L, BasicBlock
> *ExitingBlock,
>                                    bool AllowPredicates) {
> +  ExitLimitQuery Query(L, ExitingBlock, AllowPredicates);
> +  auto MaybeEL = ExitLimits.find(Query);
> +  if (MaybeEL != ExitLimits.end())
> +    return MaybeEL->second;
> +  ExitLimit EL = computeExitLimitImpl(L, ExitingBlock, AllowPredicates);
> +  ExitLimits.insert({Query, EL});
> +  return EL;
> +}
> +
> +ScalarEvolution::ExitLimit
> +ScalarEvolution::computeExitLimitImpl(const Loop *L, BasicBlock
> *ExitingBlock,
> +                                      bool AllowPredicates) {
>
>    // Okay, we've chosen an exiting block.  See what condition causes us
> to exit
>    // at this block and remember the exit block and whether all other
> targets
> @@ -10408,6 +10426,7 @@ ScalarEvolution::ScalarEvolution(ScalarE
>        BackedgeTakenCounts(std::move(Arg.BackedgeTakenCounts)),
>        PredicatedBackedgeTakenCounts(
>            std::move(Arg.PredicatedBackedgeTakenCounts)),
> +      ExitLimits(std::move(Arg.ExitLimits)),
>        ConstantEvolutionLoopExitValue(
>            std::move(Arg.ConstantEvolutionLoopExitValue)),
>        ValuesAtScopes(std::move(Arg.ValuesAtScopes)),
> @@ -10810,7 +10829,16 @@ bool ScalarEvolution::hasOperand(const S
>    return SCEVExprContains(S, [&](const SCEV *Expr) { return Expr == Op;
> });
>  }
>
> -void ScalarEvolution::forgetMemoizedResults(const SCEV *S) {
> +bool ScalarEvolution::ExitLimit::hasOperand(const SCEV *S) const {
> +  auto IsS = [&](const SCEV *X) { return S == X; };
> +  auto ContainsS = [&](const SCEV *X) {
> +    return !isa<SCEVCouldNotCompute>(X) && SCEVExprContains(X, IsS);
> +  };
> +  return ContainsS(ExactNotTaken) || ContainsS(MaxNotTaken);
> +}
> +
> +void
> +ScalarEvolution::forgetMemoizedResults(const SCEV *S, bool
> EraseExitLimit) {
>    ValuesAtScopes.erase(S);
>    LoopDispositions.erase(S);
>    BlockDispositions.erase(S);
> @@ -10843,6 +10871,13 @@ void ScalarEvolution::forgetMemoizedResu
>
>    RemoveSCEVFromBackedgeMap(BackedgeTakenCounts);
>    RemoveSCEVFromBackedgeMap(PredicatedBackedgeTakenCounts);
> +
> +  // TODO: There is a suspicion that we only need to do it when there is a
> +  // SCEVUnknown somewhere inside S. Need to check this.
> +  if (EraseExitLimit)
> +    for (auto I = ExitLimits.begin(), E = ExitLimits.end(); I != E; ++I)
> +      if (I->second.hasOperand(S))
> +        ExitLimits.erase(I);
>  }
>
>  void ScalarEvolution::verify() const {
>
> Added: llvm/trunk/test/Analysis/ScalarEvolution/cache_loop_exit_limit.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> Analysis/ScalarEvolution/cache_loop_exit_limit.ll?rev=309925&view=auto
> ============================================================
> ==================
> --- llvm/trunk/test/Analysis/ScalarEvolution/cache_loop_exit_limit.ll
> (added)
> +++ llvm/trunk/test/Analysis/ScalarEvolution/cache_loop_exit_limit.ll Thu
> Aug  3 01:41:30 2017
> @@ -0,0 +1,253 @@
> +; RUN: opt -scalar-evolution-max-arith-depth=4
> -scalar-evolution-max-add-rec-size=4 -loop-reduce -S < %s | FileCheck %s
> +
> +; Check that the test does not hang.
> +define void @test_01(i32* nocapture %a) local_unnamed_addr {
> +
> +; CHECK-LABEL: @test_01(
> +
> +while.body.outer:
> +  %arrayidx2 = getelementptr inbounds i32, i32* %a, i64 96
> +  %arrayidx2.promoted50 = load i32, i32* %arrayidx2, align 1
> +  %a.promoted = load i32, i32* %a, align 1
> +  %add347.peel = xor i32 %arrayidx2.promoted50, -1
> +  %tobool48.peel = icmp eq i32 %a.promoted, %add347.peel
> +  br i1 %tobool48.peel, label %while.body.preheader, label
> %while.body4.preheader
> +
> +while.body.preheader:                             ; preds =
> %while.body.outer
> +  %tobool48 = icmp eq i32 %a.promoted, 1
> +  br label %while.body
> +
> +while.body:                                       ; preds =
> %while.body.preheader, %while.body
> +  br i1 %tobool48, label %while.body, label %while.body4.preheader.
> loopexit
> +
> +while.body4.preheader.loopexit:                   ; preds = %while.body
> +  br label %while.body4.preheader
> +
> +while.body4.preheader:                            ; preds =
> %while.body4.preheader.loopexit, %while.body.outer
> +  br label %while.body4
> +
> +while.body4:                                      ; preds =
> %while.body4.preheader, %while.end.22
> +  %0 = phi i32 [ %mul.22, %while.end.22 ], [ %arrayidx2.promoted50,
> %while.body4.preheader ]
> +  %mul = mul nsw i32 %0, %0
> +  br label %while.cond17
> +
> +while.cond17:                                     ; preds =
> %while.cond17, %while.body4
> +  %add22.sink = phi i32 [ %add22, %while.cond17 ], [ %mul, %while.body4 ]
> +  %cmp = icmp slt i32 %add22.sink, 0
> +  %add22 = add nsw i32 %add22.sink, 1024
> +  br i1 %cmp, label %while.cond17, label %while.end
> +
> +while.end:                                        ; preds = %while.cond17
> +  %mul.1 = mul nsw i32 %add22.sink, %add22.sink
> +  br label %while.cond17.1
> +
> +while.cond17.1:                                   ; preds =
> %while.cond17.1, %while.end
> +  %add22.sink.1 = phi i32 [ %add22.1, %while.cond17.1 ], [ %mul.1,
> %while.end ]
> +  %cmp.1 = icmp slt i32 %add22.sink.1, 0
> +  %add22.1 = add nsw i32 %add22.sink.1, 2048
> +  br i1 %cmp.1, label %while.cond17.1, label %while.end.1
> +
> +while.end.1:                                      ; preds =
> %while.cond17.1
> +  %mul.2 = mul nsw i32 %add22.sink.1, %add22.sink.1
> +  br label %while.cond17.2
> +
> +while.cond17.2:                                   ; preds =
> %while.cond17.2, %while.end.1
> +  %add22.sink.2 = phi i32 [ %add22.2, %while.cond17.2 ], [ %mul.2,
> %while.end.1 ]
> +  %cmp.2 = icmp slt i32 %add22.sink.2, 0
> +  %add22.2 = add nsw i32 %add22.sink.2, 4096
> +  br i1 %cmp.2, label %while.cond17.2, label %while.end.2
> +
> +while.end.2:                                      ; preds =
> %while.cond17.2
> +  %mul.3 = mul nsw i32 %add22.sink.2, %add22.sink.2
> +  br label %while.cond17.3
> +
> +while.cond17.3:                                   ; preds =
> %while.cond17.3, %while.end.2
> +  %add22.sink.3 = phi i32 [ %add22.3, %while.cond17.3 ], [ %mul.3,
> %while.end.2 ]
> +  %cmp.3 = icmp slt i32 %add22.sink.3, 0
> +  %add22.3 = add nsw i32 %add22.sink.3, 8192
> +  br i1 %cmp.3, label %while.cond17.3, label %while.end.3
> +
> +while.end.3:                                      ; preds =
> %while.cond17.3
> +  %mul.4 = mul nsw i32 %add22.sink.3, %add22.sink.3
> +  br label %while.cond17.4
> +
> +while.cond17.4:                                   ; preds =
> %while.cond17.4, %while.end.3
> +  %add22.sink.4 = phi i32 [ %add22.4, %while.cond17.4 ], [ %mul.4,
> %while.end.3 ]
> +  %cmp.4 = icmp slt i32 %add22.sink.4, 0
> +  %add22.4 = add nsw i32 %add22.sink.4, 16384
> +  br i1 %cmp.4, label %while.cond17.4, label %while.end.4
> +
> +while.end.4:                                      ; preds =
> %while.cond17.4
> +  %mul.5 = mul nsw i32 %add22.sink.4, %add22.sink.4
> +  br label %while.cond17.5
> +
> +while.cond17.5:                                   ; preds =
> %while.cond17.5, %while.end.4
> +  %add22.sink.5 = phi i32 [ %add22.5, %while.cond17.5 ], [ %mul.5,
> %while.end.4 ]
> +  %cmp.5 = icmp slt i32 %add22.sink.5, 0
> +  %add22.5 = add nsw i32 %add22.sink.5, 32768
> +  br i1 %cmp.5, label %while.cond17.5, label %while.end.5
> +
> +while.end.5:                                      ; preds =
> %while.cond17.5
> +  %mul.6 = mul nsw i32 %add22.sink.5, %add22.sink.5
> +  br label %while.cond17.6
> +
> +while.cond17.6:                                   ; preds =
> %while.cond17.6, %while.end.5
> +  %add22.sink.6 = phi i32 [ %add22.6, %while.cond17.6 ], [ %mul.6,
> %while.end.5 ]
> +  %cmp.6 = icmp slt i32 %add22.sink.6, 0
> +  %add22.6 = add nsw i32 %add22.sink.6, 65536
> +  br i1 %cmp.6, label %while.cond17.6, label %while.end.6
> +
> +while.end.6:                                      ; preds =
> %while.cond17.6
> +  %mul.7 = mul nsw i32 %add22.sink.6, %add22.sink.6
> +  br label %while.cond17.7
> +
> +while.cond17.7:                                   ; preds =
> %while.cond17.7, %while.end.6
> +  %add22.sink.7 = phi i32 [ %add22.7, %while.cond17.7 ], [ %mul.7,
> %while.end.6 ]
> +  %cmp.7 = icmp slt i32 %add22.sink.7, 0
> +  %add22.7 = add nsw i32 %add22.sink.7, 131072
> +  br i1 %cmp.7, label %while.cond17.7, label %while.end.7
> +
> +while.end.7:                                      ; preds =
> %while.cond17.7
> +  %mul.8 = mul nsw i32 %add22.sink.7, %add22.sink.7
> +  br label %while.cond17.8
> +
> +while.cond17.8:                                   ; preds =
> %while.cond17.8, %while.end.7
> +  %add22.sink.8 = phi i32 [ %add22.8, %while.cond17.8 ], [ %mul.8,
> %while.end.7 ]
> +  %cmp.8 = icmp slt i32 %add22.sink.8, 0
> +  %add22.8 = add nsw i32 %add22.sink.8, 262144
> +  br i1 %cmp.8, label %while.cond17.8, label %while.end.8
> +
> +while.end.8:                                      ; preds =
> %while.cond17.8
> +  %mul.9 = mul nsw i32 %add22.sink.8, %add22.sink.8
> +  br label %while.cond17.9
> +
> +while.cond17.9:                                   ; preds =
> %while.cond17.9, %while.end.8
> +  %add22.sink.9 = phi i32 [ %add22.9, %while.cond17.9 ], [ %mul.9,
> %while.end.8 ]
> +  %cmp.9 = icmp slt i32 %add22.sink.9, 0
> +  %add22.9 = add nsw i32 %add22.sink.9, 524288
> +  br i1 %cmp.9, label %while.cond17.9, label %while.end.9
> +
> +while.end.9:                                      ; preds =
> %while.cond17.9
> +  %mul.10 = mul nsw i32 %add22.sink.9, %add22.sink.9
> +  br label %while.cond17.10
> +
> +while.cond17.10:                                  ; preds =
> %while.cond17.10, %while.end.9
> +  %add22.sink.10 = phi i32 [ %add22.10, %while.cond17.10 ], [ %mul.10,
> %while.end.9 ]
> +  %cmp.10 = icmp slt i32 %add22.sink.10, 0
> +  %add22.10 = add nsw i32 %add22.sink.10, 1048576
> +  br i1 %cmp.10, label %while.cond17.10, label %while.end.10
> +
> +while.end.10:                                     ; preds =
> %while.cond17.10
> +  %mul.11 = mul nsw i32 %add22.sink.10, %add22.sink.10
> +  br label %while.cond17.11
> +
> +while.cond17.11:                                  ; preds =
> %while.cond17.11, %while.end.10
> +  %add22.sink.11 = phi i32 [ %add22.11, %while.cond17.11 ], [ %mul.11,
> %while.end.10 ]
> +  %cmp.11 = icmp slt i32 %add22.sink.11, 0
> +  %add22.11 = add nsw i32 %add22.sink.11, 2097152
> +  br i1 %cmp.11, label %while.cond17.11, label %while.end.11
> +
> +while.end.11:                                     ; preds =
> %while.cond17.11
> +  %mul.12 = mul nsw i32 %add22.sink.11, %add22.sink.11
> +  br label %while.cond17.12
> +
> +while.cond17.12:                                  ; preds =
> %while.cond17.12, %while.end.11
> +  %add22.sink.12 = phi i32 [ %add22.12, %while.cond17.12 ], [ %mul.12,
> %while.end.11 ]
> +  %cmp.12 = icmp slt i32 %add22.sink.12, 0
> +  %add22.12 = add nsw i32 %add22.sink.12, 4194304
> +  br i1 %cmp.12, label %while.cond17.12, label %while.end.12
> +
> +while.end.12:                                     ; preds =
> %while.cond17.12
> +  %mul.13 = mul nsw i32 %add22.sink.12, %add22.sink.12
> +  br label %while.cond17.13
> +
> +while.cond17.13:                                  ; preds =
> %while.cond17.13, %while.end.12
> +  %add22.sink.13 = phi i32 [ %add22.13, %while.cond17.13 ], [ %mul.13,
> %while.end.12 ]
> +  %cmp.13 = icmp slt i32 %add22.sink.13, 0
> +  %add22.13 = add nsw i32 %add22.sink.13, 8388608
> +  br i1 %cmp.13, label %while.cond17.13, label %while.end.13
> +
> +while.end.13:                                     ; preds =
> %while.cond17.13
> +  %mul.14 = mul nsw i32 %add22.sink.13, %add22.sink.13
> +  br label %while.cond17.14
> +
> +while.cond17.14:                                  ; preds =
> %while.cond17.14, %while.end.13
> +  %add22.sink.14 = phi i32 [ %add22.14, %while.cond17.14 ], [ %mul.14,
> %while.end.13 ]
> +  %cmp.14 = icmp slt i32 %add22.sink.14, 0
> +  %add22.14 = add nsw i32 %add22.sink.14, 16777216
> +  br i1 %cmp.14, label %while.cond17.14, label %while.end.14
> +
> +while.end.14:                                     ; preds =
> %while.cond17.14
> +  %mul.15 = mul nsw i32 %add22.sink.14, %add22.sink.14
> +  br label %while.cond17.15
> +
> +while.cond17.15:                                  ; preds =
> %while.cond17.15, %while.end.14
> +  %add22.sink.15 = phi i32 [ %add22.15, %while.cond17.15 ], [ %mul.15,
> %while.end.14 ]
> +  %cmp.15 = icmp slt i32 %add22.sink.15, 0
> +  %add22.15 = add nsw i32 %add22.sink.15, 33554432
> +  br i1 %cmp.15, label %while.cond17.15, label %while.end.15
> +
> +while.end.15:                                     ; preds =
> %while.cond17.15
> +  %mul.16 = mul nsw i32 %add22.sink.15, %add22.sink.15
> +  br label %while.cond17.16
> +
> +while.cond17.16:                                  ; preds =
> %while.cond17.16, %while.end.15
> +  %add22.sink.16 = phi i32 [ %add22.16, %while.cond17.16 ], [ %mul.16,
> %while.end.15 ]
> +  %cmp.16 = icmp slt i32 %add22.sink.16, 0
> +  %add22.16 = add nsw i32 %add22.sink.16, 67108864
> +  br i1 %cmp.16, label %while.cond17.16, label %while.end.16
> +
> +while.end.16:                                     ; preds =
> %while.cond17.16
> +  %mul.17 = mul nsw i32 %add22.sink.16, %add22.sink.16
> +  br label %while.cond17.17
> +
> +while.cond17.17:                                  ; preds =
> %while.cond17.17, %while.end.16
> +  %add22.sink.17 = phi i32 [ %add22.17, %while.cond17.17 ], [ %mul.17,
> %while.end.16 ]
> +  %cmp.17 = icmp slt i32 %add22.sink.17, 0
> +  %add22.17 = add nsw i32 %add22.sink.17, 134217728
> +  br i1 %cmp.17, label %while.cond17.17, label %while.end.17
> +
> +while.end.17:                                     ; preds =
> %while.cond17.17
> +  %mul.18 = mul nsw i32 %add22.sink.17, %add22.sink.17
> +  br label %while.cond17.18
> +
> +while.cond17.18:                                  ; preds =
> %while.cond17.18, %while.end.17
> +  %add22.sink.18 = phi i32 [ %add22.18, %while.cond17.18 ], [ %mul.18,
> %while.end.17 ]
> +  %cmp.18 = icmp slt i32 %add22.sink.18, 0
> +  %add22.18 = add nsw i32 %add22.sink.18, 268435456
> +  br i1 %cmp.18, label %while.cond17.18, label %while.end.18
> +
> +while.end.18:                                     ; preds =
> %while.cond17.18
> +  %mul.19 = mul nsw i32 %add22.sink.18, %add22.sink.18
> +  br label %while.cond17.19
> +
> +while.cond17.19:                                  ; preds =
> %while.cond17.19, %while.end.18
> +  %add22.sink.19 = phi i32 [ %add22.19, %while.cond17.19 ], [ %mul.19,
> %while.end.18 ]
> +  %cmp.19 = icmp slt i32 %add22.sink.19, 0
> +  %add22.19 = add nsw i32 %add22.sink.19, 536870912
> +  br i1 %cmp.19, label %while.cond17.19, label %while.end.19
> +
> +while.end.19:                                     ; preds =
> %while.cond17.19
> +  %mul.20 = mul nsw i32 %add22.sink.19, %add22.sink.19
> +  br label %while.cond17.20
> +
> +while.cond17.20:                                  ; preds =
> %while.cond17.20, %while.end.19
> +  %add22.sink.20 = phi i32 [ %add22.20, %while.cond17.20 ], [ %mul.20,
> %while.end.19 ]
> +  %cmp.20 = icmp slt i32 %add22.sink.20, 0
> +  %add22.20 = add nsw i32 %add22.sink.20, 1073741824
> +  br i1 %cmp.20, label %while.cond17.20, label %while.end.20
> +
> +while.end.20:                                     ; preds =
> %while.cond17.20
> +  %mul.21 = mul nsw i32 %add22.sink.20, %add22.sink.20
> +  br label %while.cond17.21
> +
> +while.cond17.21:                                  ; preds =
> %while.cond17.21, %while.end.20
> +  %add22.sink.21 = phi i32 [ %add22.21, %while.cond17.21 ], [ %mul.21,
> %while.end.20 ]
> +  %cmp.21 = icmp slt i32 %add22.sink.21, 0
> +  %add22.21 = or i32 %add22.sink.21, -2147483648
> +  br i1 %cmp.21, label %while.cond17.21, label %while.end.22
> +
> +while.end.22:                                     ; preds =
> %while.cond17.21
> +  %mul.22 = mul nsw i32 %add22.sink.21, %add22.sink.21
> +  br label %while.body4
> +}
>
> Modified: llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/
> Analysis/ScalarEvolutionTest.cpp?rev=309925&r1=309924&r2=309925&view=diff
> ============================================================
> ==================
> --- llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp (original)
> +++ llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp Thu Aug  3
> 01:41:30 2017
> @@ -930,5 +930,165 @@ TEST_F(ScalarEvolutionsTest, SCEVZeroExt
>    EXPECT_FALSE(verifyFunction(*F, &errs()));
>  }
>
> +// Make sure that SCEV invalidates exit limits after invalidating the
> values it
> +// depends on when we forget a loop.
> +TEST_F(ScalarEvolutionsTest, SCEVExitLimitForgetLoop) {
> +  /*
> +   * Create the following code:
> +   * func(i64 addrspace(10)* %arg)
> +   * top:
> +   *  br label %L.ph
> +   * L.ph:
> +   *  br label %L
> +   * L:
> +   *  %phi = phi i64 [i64 0, %L.ph], [ %add, %L2 ]
> +   *  %add = add i64 %phi2, 1
> +   *  %cond = icmp slt i64 %add, 1000; then becomes 2000.
> +   *  br i1 %cond, label %post, label %L2
> +   * post:
> +   *  ret void
> +   *
> +   */
> +
> +  // Create a module with non-integral pointers in it's datalayout
> +  Module NIM("nonintegral", Context);
> +  std::string DataLayout = M.getDataLayoutStr();
> +  if (!DataLayout.empty())
> +    DataLayout += "-";
> +  DataLayout += "ni:10";
> +  NIM.setDataLayout(DataLayout);
> +
> +  Type *T_int64 = Type::getInt64Ty(Context);
> +  Type *T_pint64 = T_int64->getPointerTo(10);
> +
> +  FunctionType *FTy =
> +      FunctionType::get(Type::getVoidTy(Context), {T_pint64}, false);
> +  Function *F = cast<Function>(NIM.getOrInsertFunction("foo", FTy));
> +
> +  Argument *Arg = &*F->arg_begin();
> +
> +  BasicBlock *Top = BasicBlock::Create(Context, "top", F);
> +  BasicBlock *LPh = BasicBlock::Create(Context, "L.ph", F);
> +  BasicBlock *L = BasicBlock::Create(Context, "L", F);
> +  BasicBlock *Post = BasicBlock::Create(Context, "post", F);
> +
> +  IRBuilder<> Builder(Top);
> +  Builder.CreateBr(LPh);
> +
> +  Builder.SetInsertPoint(LPh);
> +  Builder.CreateBr(L);
> +
> +  Builder.SetInsertPoint(L);
> +  PHINode *Phi = Builder.CreatePHI(T_int64, 2);
> +  auto *Add = cast<Instruction>(
> +      Builder.CreateAdd(Phi, ConstantInt::get(T_int64, 1), "add"));
> +  auto *Limit = ConstantInt::get(T_int64, 1000);
> +  auto *Cond = cast<Instruction>(
> +      Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, Limit, "cond"));
> +  auto *Br = cast<Instruction>(Builder.CreateCondBr(Cond, L, Post));
> +  Phi->addIncoming(ConstantInt::get(T_int64, 0), LPh);
> +  Phi->addIncoming(Add, L);
> +
> +  Builder.SetInsertPoint(Post);
> +  Builder.CreateRetVoid();
> +
> +  ScalarEvolution SE = buildSE(*F);
> +  auto *Loop = LI->getLoopFor(L);
> +  const SCEV *EC = SE.getBackedgeTakenCount(Loop);
> +  EXPECT_FALSE(isa<SCEVCouldNotCompute>(EC));
> +
> +  SE.forgetLoop(Loop);
> +  Br->eraseFromParent();
> +  Cond->eraseFromParent();
> +
> +  Builder.SetInsertPoint(L);
> +  Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, ConstantInt::get(T_int64,
> 2000),
> +                     "new.cond");
> +  Builder.CreateCondBr(Cond, L, Post);
> +  const SCEV *NewEC = SE.getBackedgeTakenCount(Loop);
> +  EXPECT_NE(EC, NewEC);
> +}
> +
> +// Make sure that SCEV invalidates exit limits after invalidating the
> values it
> +// depends on when we forget a value.
> +TEST_F(ScalarEvolutionsTest, SCEVExitLimitForgetValue) {
> +  /*
> +   * Create the following code:
> +   * func(i64 addrspace(10)* %arg)
> +   * top:
> +   *  br label %L.ph
> +   * L.ph:
> +   *  %load = load i64 addrspace(10)* %arg
> +   *  br label %L
> +   * L:
> +   *  %phi = phi i64 [i64 0, %L.ph], [ %add, %L2 ]
> +   *  %add = add i64 %phi2, 1
> +   *  %cond = icmp slt i64 %add, %load ; then becomes 2000.
> +   *  br i1 %cond, label %post, label %L2
> +   * post:
> +   *  ret void
> +   *
> +   */
> +
> +  // Create a module with non-integral pointers in it's datalayout
> +  Module NIM("nonintegral", Context);
> +  std::string DataLayout = M.getDataLayoutStr();
> +  if (!DataLayout.empty())
> +    DataLayout += "-";
> +  DataLayout += "ni:10";
> +  NIM.setDataLayout(DataLayout);
> +
> +  Type *T_int64 = Type::getInt64Ty(Context);
> +  Type *T_pint64 = T_int64->getPointerTo(10);
> +
> +  FunctionType *FTy =
> +      FunctionType::get(Type::getVoidTy(Context), {T_pint64}, false);
> +  Function *F = cast<Function>(NIM.getOrInsertFunction("foo", FTy));
> +
> +  Argument *Arg = &*F->arg_begin();
> +
> +  BasicBlock *Top = BasicBlock::Create(Context, "top", F);
> +  BasicBlock *LPh = BasicBlock::Create(Context, "L.ph", F);
> +  BasicBlock *L = BasicBlock::Create(Context, "L", F);
> +  BasicBlock *Post = BasicBlock::Create(Context, "post", F);
> +
> +  IRBuilder<> Builder(Top);
> +  Builder.CreateBr(LPh);
> +
> +  Builder.SetInsertPoint(LPh);
> +  auto *Load = cast<Instruction>(Builder.CreateLoad(T_int64, Arg,
> "load"));
> +  Builder.CreateBr(L);
> +
> +  Builder.SetInsertPoint(L);
> +  PHINode *Phi = Builder.CreatePHI(T_int64, 2);
> +  auto *Add = cast<Instruction>(
> +      Builder.CreateAdd(Phi, ConstantInt::get(T_int64, 1), "add"));
> +  auto *Cond = cast<Instruction>(
> +      Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, Load, "cond"));
> +  auto *Br = cast<Instruction>(Builder.CreateCondBr(Cond, L, Post));
> +  Phi->addIncoming(ConstantInt::get(T_int64, 0), LPh);
> +  Phi->addIncoming(Add, L);
> +
> +  Builder.SetInsertPoint(Post);
> +  Builder.CreateRetVoid();
> +
> +  ScalarEvolution SE = buildSE(*F);
> +  auto *Loop = LI->getLoopFor(L);
> +  const SCEV *EC = SE.getBackedgeTakenCount(Loop);
> +  EXPECT_FALSE(isa<SCEVCouldNotCompute>(EC));
> +
> +  SE.forgetValue(Load);
> +  Br->eraseFromParent();
> +  Cond->eraseFromParent();
> +  Load->eraseFromParent();
> +
> +  Builder.SetInsertPoint(L);
> +  Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, ConstantInt::get(T_int64,
> 2000),
> +                     "new.cond");
> +  Builder.CreateCondBr(Cond, L, Post);
> +  const SCEV *NewEC = SE.getBackedgeTakenCount(Loop);
> +  EXPECT_NE(EC, NewEC);
> +}
> +
>  }  // end anonymous namespace
>  }  // end namespace llvm
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170803/af602c4d/attachment.html>


More information about the llvm-commits mailing list