cl::desc("Max num uses visited for identifying load "
"invariance in loop using invariant start (default = 8)"));
-// Default value of zero implies we use the regular alias set tracker mechanism
-// instead of the cross product using AA to identify aliasing of the memory
-// location we are interested in.
-static cl::opt<int>
-LICMN2Theshold("licm-n2-threshold", cl::Hidden, cl::init(0),
- cl::desc("How many instruction to cross product using AA"));
-
// Experimental option to allow imprecision in LICM in pathological cases, in
// exchange for faster compile. This is to be removed if MemorySSA starts to
// address the same issue. This flag applies only when LICM uses MemorySSA
static bool pointerInvalidatedByLoop(MemoryLocation MemLoc,
AliasSetTracker *CurAST, Loop *CurLoop,
AAResults *AA) {
- // First check to see if any of the basic blocks in CurLoop invalidate *V.
- bool isInvalidatedAccordingToAST = CurAST->getAliasSetFor(MemLoc).isMod();
-
- if (!isInvalidatedAccordingToAST || !LICMN2Theshold)
- return isInvalidatedAccordingToAST;
-
- // Check with a diagnostic analysis if we can refine the information above.
- // This is to identify the limitations of using the AST.
- // The alias set mechanism used by LICM has a major weakness in that it
- // combines all things which may alias into a single set *before* asking
- // modref questions. As a result, a single readonly call within a loop will
- // collapse all loads and stores into a single alias set and report
- // invalidation if the loop contains any store. For example, readonly calls
- // with deopt states have this form and create a general alias set with all
- // loads and stores. In order to get any LICM in loops containing possible
- // deopt states we need a more precise invalidation of checking the mod ref
- // info of each instruction within the loop and LI. This has a complexity of
- // O(N^2), so currently, it is used only as a diagnostic tool since the
- // default value of LICMN2Threshold is zero.
-
- // Don't look at nested loops.
- if (CurLoop->begin() != CurLoop->end())
- return true;
-
- int N = 0;
- for (BasicBlock *BB : CurLoop->getBlocks())
- for (Instruction &I : *BB) {
- if (N >= LICMN2Theshold) {
- LLVM_DEBUG(dbgs() << "Alasing N2 threshold exhausted for "
- << *(MemLoc.Ptr) << "\n");
- return true;
- }
- N++;
- auto Res = AA->getModRefInfo(&I, MemLoc);
- if (isModSet(Res)) {
- LLVM_DEBUG(dbgs() << "Aliasing failed on " << I << " for "
- << *(MemLoc.Ptr) << "\n");
- return true;
- }
- }
- LLVM_DEBUG(dbgs() << "Aliasing okay for " << *(MemLoc.Ptr) << "\n");
- return false;
+ return CurAST->getAliasSetFor(MemLoc).isMod();
}
bool pointerInvalidatedByLoopWithMSSA(MemorySSA *MSSA, MemoryUse *MU,
-; RUN: opt -S -basic-aa -licm -licm-n2-threshold=0 -verify-memoryssa %s -enable-new-pm=0 | FileCheck %s --check-prefix=ALIAS-N2
-; RUN: opt -licm -basic-aa -licm-n2-threshold=200 < %s -S -enable-new-pm=0 | FileCheck %s --check-prefix=ALIAS-N2
-
-; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=0 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
-; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=0 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s --check-prefix=ALIAS-N2
-; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=200 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s --check-prefix=ALIAS-N2
+; RUN: opt -S -basic-aa -licm -verify-memoryssa %s -enable-new-pm=0 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
declare i32 @foo() readonly argmemonly nounwind
declare i32 @foo2() readonly nounwind
; CHECK-LABEL: @test
; CHECK: @foo
; CHECK-LABEL: loop:
-; ALIAS-N2-LABEL: @test
-; ALIAS-N2: @foo
-; ALIAS-N2-LABEL: loop:
br label %loop
loop:
; CHECK-LABEL: @test_neg
; CHECK-LABEL: loop:
; CHECK: @foo
-; ALIAS-N2-LABEL: @test_neg
-; ALIAS-N2-LABEL: loop:
-; ALIAS-N2: @foo
br label %loop
loop:
; CHECK-LABEL: @test2
; CHECK: @bar
; CHECK-LABEL: loop:
-; ALIAS-N2-LABEL: @test2
-; ALIAS-N2: @bar
-; ALIAS-N2-LABEL: loop:
br label %loop
loop:
; CHECK-LABEL: @test3
; CHECK-LABEL: loop:
; CHECK: @bar
-; ALIAS-N2-LABEL: @test3
-; ALIAS-N2-LABEL: loop:
-; ALIAS-N2: @bar
br label %loop
loop:
; CHECK-LABEL: @test4
; CHECK-LABEL: loop:
; CHECK: @bar
-; ALIAS-N2-LABEL: @test4
-; ALIAS-N2-LABEL: loop:
-; ALIAS-N2: @bar
br label %loop
loop:
}
declare i32 @foo_new(i32*) readonly
-; With the default AST mechanism used by LICM for alias analysis,
-; we clump foo_new with bar.
-; With the N2 Alias analysis diagnostic tool, we are able to hoist the
-; argmemonly bar call out of the loop.
-; Using MemorySSA we can also hoist bar.
define void @test5(i32* %loc2, i32* noalias %loc) {
-; ALIAS-N2-LABEL: @test5
-; ALIAS-N2: @bar
-; ALIAS-N2-LABEL: loop:
-
; CHECK-LABEL: @test5
+; CHECK: @bar
; CHECK-LABEL: loop:
-; CHECK: @bar
br label %loop
loop:
; CHECK: %val = load i32, i32* %loc2
; CHECK-LABEL: loop:
; CHECK: @llvm.memcpy
-; ALIAS-N2-LABEL: @test6
-; ALIAS-N2: %val = load i32, i32* %loc2
-; ALIAS-N2-LABEL: loop:
-; ALIAS-N2: @llvm.memcpy
br label %loop
loop:
; CHECK: %val = load i32, i32* %loc2
; CHECK-LABEL: loop:
; CHECK: @custom_memcpy
-; ALIAS-N2-LABEL: @test7
-; ALIAS-N2: %val = load i32, i32* %loc2
-; ALIAS-N2-LABEL: loop:
-; ALIAS-N2: @custom_memcpy
br label %loop
loop:
-; RUN: opt -licm -basic-aa -licm-n2-threshold=0 < %s -S | FileCheck %s
-; RUN: opt -licm -basic-aa -licm-n2-threshold=200 < %s -S | FileCheck %s --check-prefix=ALIAS-N2
-; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=0 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
-; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=200 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s --check-prefix=ALIAS-N2
+; RUN: opt -licm -basic-aa < %s -S | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
define void @test1(i1 %cond, i32* %ptr) {
; CHECK-LABEL: @test1(
; CHECK: %val = load i32, i32* %ptr
; CHECK-LABEL: loop:
-; ALIAS-N2-LABEL: @test1(
-; ALIAS-N2-LABEL: entry:
-; ALIAS-N2: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr)
-; ALIAS-N2: %val = load i32, i32* %ptr
-; ALIAS-N2-LABEL: loop:
-
entry:
br label %loop
; CHECK: %val = load i32, i32* %ptr
; CHECK-LABEL: loop:
; CHECK: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %piv)
-
-; ALIAS-N2-LABEL: @test2(
-; ALIAS-N2-LABEL: entry:
-; ALIAS-N2: %val = load i32, i32* %ptr
-; ALIAS-N2-LABEL: loop:
-; ALIAS-N2: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %piv)
entry:
br label %loop
; CHECK: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr)
; CHECK: %val = load i32, i32* %ptr
; CHECK-LABEL: loop:
-
-; ALIAS-N2-LABEL: @test3(
-; ALIAS-N2-LABEL: entry:
-; ALIAS-N2: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr)
-; ALIAS-N2: %val = load i32, i32* %ptr
-; ALIAS-N2-LABEL: loop:
entry:
br label %loop
; CHECK: store i32 0, i32* %ptr
; CHECK: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr)
; CHECK: %val = load i32, i32* %ptr
-
-; ALIAS-N2-LABEL: @test4(
-; ALIAS-N2-LABEL: entry:
-; ALIAS-N2-LABEL: loop:
-; ALIAS-N2: store i32 0, i32* %ptr
-; ALIAS-N2: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr)
-; ALIAS-N2: %val = load i32, i32* %ptr
entry:
br label %loop
; CHECK: store i32 0, i32* %ptr
; CHECK: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr)
; CHECK: %val = load i32, i32* %ptr
-
-; ALIAS-N2-LABEL: @test5(
-; ALIAS-N2-LABEL: entry:
-; ALIAS-N2-LABEL: loop:
-; ALIAS-N2: store i32 0, i32* %ptr
-; ALIAS-N2: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr)
-; ALIAS-N2: %val = load i32, i32* %ptr
entry:
br label %loop
-; RUN: opt -S -basic-aa -licm -licm-n2-threshold=0 %s -enable-new-pm=0 | FileCheck %s --check-prefix=ALIAS-N2
-; RUN: opt -licm -basic-aa -licm-n2-threshold=200 < %s -S -enable-new-pm=0 | FileCheck %s --check-prefix=ALIAS-N2
-
-; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=0 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
-; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=0 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s --check-prefix=ALIAS-N2
-; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=200 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s --check-prefix=ALIAS-N2
+; RUN: opt -S -basic-aa -licm %s -enable-new-pm=0 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
; We should be able to hoist loads in presence of read only calls and stores
; that do not alias.
define void @test1(i32* %ptr) {
; CHECK-LABEL: @test1(
; CHECK-LABEL: entry:
+; CHECK: %val = load i32, i32* %ptr
; CHECK-LABEL: loop:
-; CHECK: %val = load i32, i32* %ptr
-
-; ALIAS-N2-LABEL: @test1(
-; ALIAS-N2-LABEL: entry:
-; ALIAS-N2: %val = load i32, i32* %ptr
-; ALIAS-N2-LABEL: loop:
entry:
br label %loop
define void @test2(i32* %ptr) {
; CHECK-LABEL: @test2(
; CHECK-LABEL: entry:
-; CHECK: %val = load i32, i32* %ptr
+; CHECK: %val = load i32, i32* %ptr
; CHECK-LABEL: loop:
-
-; ALIAS-N2-LABEL: @test2(
-; ALIAS-N2-LABEL: entry:
-; ALIAS-N2: %val = load i32, i32* %ptr
-; ALIAS-N2-LABEL: loop:
entry:
br label %loop
; CHECK-LABEL: @test3(
; CHECK-LABEL: entry:
; CHECK-LABEL: loop:
-; CHECK: %val = load i32, i32* %ptr
-
-; ALIAS-N2-LABEL: @test3(
-; ALIAS-N2-LABEL: entry:
-; ALIAS-N2-LABEL: loop:
-; ALIAS-N2: %val = load i32, i32* %ptr
+; CHECK: %val = load i32, i32* %ptr
entry:
br label %loop