summaryrefslogtreecommitdiff
path: root/test/Transforms/LICM
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:41:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:41:05 +0000
commit01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch)
tree4def12e759965de927d963ac65840d663ef9d1ea /test/Transforms/LICM
parentf0f4822ed4b66e3579e92a89f368f8fb860e218e (diff)
Notes
Diffstat (limited to 'test/Transforms/LICM')
-rw-r--r--test/Transforms/LICM/AliasSetMemSet.ll51
-rw-r--r--test/Transforms/LICM/alias-set-tracker-loss.ll39
-rw-r--r--test/Transforms/LICM/argmemonly-call.ll1
-rw-r--r--test/Transforms/LICM/assume.ll52
-rw-r--r--test/Transforms/LICM/atomics.ll1
-rw-r--r--test/Transforms/LICM/basictest.ll1
-rw-r--r--test/Transforms/LICM/constexpr.ll1
-rw-r--r--test/Transforms/LICM/crash.ll1
-rw-r--r--test/Transforms/LICM/debug-value.ll16
-rw-r--r--test/Transforms/LICM/extra-copies.ll1
-rw-r--r--test/Transforms/LICM/funclet.ll1
-rw-r--r--test/Transforms/LICM/hoist-bitcast-load.ll1
-rw-r--r--test/Transforms/LICM/hoist-deref-load.ll123
-rw-r--r--test/Transforms/LICM/hoist-nounwind.ll72
-rw-r--r--test/Transforms/LICM/hoist-round.ll62
-rw-r--r--test/Transforms/LICM/hoisting.ll24
-rw-r--r--test/Transforms/LICM/lcssa-ssa-promoter.ll1
-rw-r--r--test/Transforms/LICM/no-preheader-test.ll1
-rw-r--r--test/Transforms/LICM/pr26843.ll32
-rw-r--r--test/Transforms/LICM/pr27262.ll33
-rw-r--r--test/Transforms/LICM/preheader-safe.ll4
-rw-r--r--test/Transforms/LICM/promote-order.ll1
-rw-r--r--test/Transforms/LICM/promote-tls.ll134
-rw-r--r--test/Transforms/LICM/scalar-promote-memmodel.ll1
-rw-r--r--test/Transforms/LICM/scalar_promote-unwind.ll72
-rw-r--r--test/Transforms/LICM/scalar_promote.ll3
-rw-r--r--test/Transforms/LICM/speculate.ll1
-rw-r--r--test/Transforms/LICM/update-scev.ll31
-rw-r--r--test/Transforms/LICM/volatile-alias.ll3
29 files changed, 745 insertions, 19 deletions
diff --git a/test/Transforms/LICM/AliasSetMemSet.ll b/test/Transforms/LICM/AliasSetMemSet.ll
new file mode 100644
index 000000000000..d60b321e278e
--- /dev/null
+++ b/test/Transforms/LICM/AliasSetMemSet.ll
@@ -0,0 +1,51 @@
+; RUN: opt < %s -loop-deletion -licm -loop-idiom -disable-output
+; Check no assertion when loop-idiom deletes the MemSet already analyzed by licm
+define void @set_array() {
+ br i1 false, label %bb3.preheader.lr.ph, label %bb9
+
+bb3.preheader.lr.ph: ; preds = %0
+ br label %bb3.preheader
+
+bb4: ; preds = %bb4.lr.ph, %bb7
+ %j.3.06 = phi i8 [ %j.3.17, %bb4.lr.ph ], [ %_tmp13, %bb7 ]
+ br label %bb6
+
+bb6: ; preds = %bb4, %bb6
+ %k.4.04 = phi i8 [ 0, %bb4 ], [ %_tmp9, %bb6 ]
+ %_tmp31 = sext i8 %j.3.06 to i64
+ %_tmp4 = mul i64 %_tmp31, 10
+ %_tmp5 = getelementptr i8, i8* undef, i64 %_tmp4
+ %_tmp7 = getelementptr i8, i8* %_tmp5, i8 %k.4.04
+ store i8 42, i8* %_tmp7
+ %_tmp9 = add i8 %k.4.04, 1
+ %_tmp11 = icmp slt i8 %_tmp9, 10
+ br i1 %_tmp11, label %bb6, label %bb7
+
+bb7: ; preds = %bb6
+ %_tmp13 = add i8 %j.3.06, 1
+ %_tmp15 = icmp slt i8 %_tmp13, 2
+ br i1 %_tmp15, label %bb4, label %bb3.bb1.loopexit_crit_edge
+
+bb3.bb1.loopexit_crit_edge: ; preds = %bb7
+ %split = phi i8 [ %_tmp13, %bb7 ]
+ br label %bb1.loopexit
+
+bb1.loopexit: ; preds = %bb3.bb1.loopexit_crit_edge, %bb3.preheader
+ %j.3.0.lcssa = phi i8 [ %split, %bb3.bb1.loopexit_crit_edge ], [ %j.3.17, %bb3.preheader ]
+ br i1 false, label %bb3.preheader, label %bb1.bb9_crit_edge
+
+bb3.preheader: ; preds = %bb3.preheader.lr.ph, %bb1.loopexit
+ %j.3.17 = phi i8 [ undef, %bb3.preheader.lr.ph ], [ %j.3.0.lcssa, %bb1.loopexit ]
+ %_tmp155 = icmp slt i8 %j.3.17, 2
+ br i1 %_tmp155, label %bb4.lr.ph, label %bb1.loopexit
+
+bb4.lr.ph: ; preds = %bb3.preheader
+ br label %bb4
+
+bb1.bb9_crit_edge: ; preds = %bb1.loopexit
+ br label %bb9
+
+bb9: ; preds = %bb1.bb9_crit_edge, %0
+ ret void
+}
+
diff --git a/test/Transforms/LICM/alias-set-tracker-loss.ll b/test/Transforms/LICM/alias-set-tracker-loss.ll
new file mode 100644
index 000000000000..378d908f6987
--- /dev/null
+++ b/test/Transforms/LICM/alias-set-tracker-loss.ll
@@ -0,0 +1,39 @@
+; RUN: opt -S -licm -loop-unroll < %s
+;
+; This test contains a carefully rotated set of three nested loops. The middle
+; loop can be unrolled leaving one copy of the inner loop inside the outer
+; loop. Because of how LICM works, when this middle loop is unrolled and
+; removed, its alias set tracker is destroyed and no longer available when LICM
+; runs on the outer loop.
+
+define void @f() {
+entry:
+ br label %l1
+
+l2.l1.loopexit_crit_edge:
+ br label %l1.loopexit
+
+l1.loopexit:
+ br label %l1.backedge
+
+l1:
+ br i1 undef, label %l1.backedge, label %l2.preheader
+
+l1.backedge:
+ br label %l1
+
+l2.preheader:
+ br i1 true, label %l1.loopexit, label %l3.preheader.lr.ph
+
+l3.preheader.lr.ph:
+ br label %l3.preheader
+
+l2.loopexit:
+ br i1 true, label %l2.l1.loopexit_crit_edge, label %l3.preheader
+
+l3.preheader:
+ br label %l3
+
+l3:
+ br i1 true, label %l3, label %l2.loopexit
+}
diff --git a/test/Transforms/LICM/argmemonly-call.ll b/test/Transforms/LICM/argmemonly-call.ll
index e2640a1c8deb..18d7f8351dca 100644
--- a/test/Transforms/LICM/argmemonly-call.ll
+++ b/test/Transforms/LICM/argmemonly-call.ll
@@ -1,4 +1,5 @@
; RUN: opt -S -basicaa -licm %s | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' < %s -S | FileCheck %s
declare i32 @foo() readonly argmemonly nounwind
declare i32 @foo2() readonly nounwind
declare i32 @bar(i32* %loc2) readonly argmemonly nounwind
diff --git a/test/Transforms/LICM/assume.ll b/test/Transforms/LICM/assume.ll
new file mode 100644
index 000000000000..f6369ac659f0
--- /dev/null
+++ b/test/Transforms/LICM/assume.ll
@@ -0,0 +1,52 @@
+; RUN: opt -licm -basicaa < %s -S | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' < %s -S | FileCheck %s
+
+define void @f_0(i1 %p) nounwind ssp {
+; CHECK-LABEL: @f_0(
+entry:
+ br label %for.body
+
+for.body:
+ br i1 undef, label %if.then, label %for.cond.backedge
+
+for.cond.backedge:
+ br i1 undef, label %for.end104, label %for.body
+
+if.then:
+ br i1 undef, label %if.then27, label %if.end.if.end.split_crit_edge.critedge
+
+if.then27:
+; CHECK: tail call void @llvm.assume
+ tail call void @llvm.assume(i1 %p)
+ br label %for.body61.us
+
+if.end.if.end.split_crit_edge.critedge:
+ br label %for.body61
+
+for.body61.us:
+ br i1 undef, label %for.cond.backedge, label %for.body61.us
+
+for.body61:
+ br i1 undef, label %for.cond.backedge, label %for.body61
+
+for.end104:
+ ret void
+}
+
+define void @f_1(i1 %cond, i32* %ptr) {
+; CHECK-LABEL: @f_1(
+; CHECK: %val = load i32, i32* %ptr
+; CHECK-NEXT: br label %loop
+
+entry:
+ br label %loop
+
+loop:
+ %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ]
+ call void @llvm.assume(i1 %cond)
+ %val = load i32, i32* %ptr
+ %x.inc = add i32 %x, %val
+ br label %loop
+}
+
+declare void @llvm.assume(i1)
diff --git a/test/Transforms/LICM/atomics.ll b/test/Transforms/LICM/atomics.ll
index 4fe197abf5d3..5dcd4bb8c05a 100644
--- a/test/Transforms/LICM/atomics.ll
+++ b/test/Transforms/LICM/atomics.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -S -basicaa -licm | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='lcssa,require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' < %s -S | FileCheck %s
; Check that we can hoist unordered loads
define i32 @test1(i32* nocapture %y) nounwind uwtable ssp {
diff --git a/test/Transforms/LICM/basictest.ll b/test/Transforms/LICM/basictest.ll
index 1dbb4dc6b499..570e226d2372 100644
--- a/test/Transforms/LICM/basictest.ll
+++ b/test/Transforms/LICM/basictest.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -licm | llvm-dis
+; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' < %s | llvm-dis
define void @testfunc(i32 %i) {
; <label>:0
diff --git a/test/Transforms/LICM/constexpr.ll b/test/Transforms/LICM/constexpr.ll
index 506721f25f8f..726246776dc6 100644
--- a/test/Transforms/LICM/constexpr.ll
+++ b/test/Transforms/LICM/constexpr.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -S -basicaa -licm | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='lcssa,require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' < %s -S | FileCheck %s
; This fixes PR22460
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
diff --git a/test/Transforms/LICM/crash.ll b/test/Transforms/LICM/crash.ll
index 7fa41157338d..75c27b8def0c 100644
--- a/test/Transforms/LICM/crash.ll
+++ b/test/Transforms/LICM/crash.ll
@@ -1,4 +1,5 @@
; RUN: opt -licm -disable-output < %s
+; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' -disable-output < %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-darwin10.0.0"
diff --git a/test/Transforms/LICM/debug-value.ll b/test/Transforms/LICM/debug-value.ll
index d8ae5e576641..ab77caa2bae0 100644
--- a/test/Transforms/LICM/debug-value.ll
+++ b/test/Transforms/LICM/debug-value.ll
@@ -1,4 +1,5 @@
; RUN: opt -licm -basicaa < %s -S | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' < %s -S | FileCheck %s
define void @dgefa() nounwind ssp {
entry:
@@ -34,19 +35,18 @@ for.end104: ; preds = %for.cond.backedge
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone
!llvm.module.flags = !{!26}
-!llvm.dbg.sp = !{!0, !6, !9, !10}
+!llvm.dbg.cu = !{!2}
-!0 = distinct !DISubprogram(name: "idamax", line: 112, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, file: !25, scope: !1, type: !3)
+!0 = distinct !DISubprogram(name: "idamax", line: 112, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !25, scope: !1, type: !3)
!1 = !DIFile(filename: "/Volumes/Lalgate/work/llvm/projects/llvm-test/SingleSource/Benchmarks/CoyoteBench/lpbench.c", directory: "/private/tmp")
-!2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 2.9 (trunk 127169)", isOptimized: true, emissionKind: 0, file: !25, enums: !8, retainedTypes: !8, subprograms: !8)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 2.9 (trunk 127169)", isOptimized: true, emissionKind: FullDebug, file: !25)
!3 = !DISubroutineType(types: !4)
!4 = !{!5}
!5 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
-!6 = distinct !DISubprogram(name: "dscal", line: 206, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, file: !25, scope: !1, type: !7)
-!7 = !DISubroutineType(types: !8)
-!8 = !{null}
-!9 = distinct !DISubprogram(name: "daxpy", line: 230, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, file: !25, scope: !1, type: !7)
-!10 = distinct !DISubprogram(name: "dgefa", line: 267, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, file: !25, scope: !1, type: !7)
+!6 = distinct !DISubprogram(name: "dscal", line: 206, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !25, scope: !1, type: !7)
+!7 = !DISubroutineType(types: !{null})
+!9 = distinct !DISubprogram(name: "daxpy", line: 230, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !25, scope: !1, type: !7)
+!10 = distinct !DISubprogram(name: "dgefa", line: 267, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !25, scope: !1, type: !7)
!11 = !DILocation(line: 281, column: 9, scope: !12)
!12 = distinct !DILexicalBlock(line: 272, column: 5, file: !25, scope: !13)
!13 = distinct !DILexicalBlock(line: 271, column: 5, file: !25, scope: !14)
diff --git a/test/Transforms/LICM/extra-copies.ll b/test/Transforms/LICM/extra-copies.ll
index ef52f9f404c1..84a3bc9ec6a6 100644
--- a/test/Transforms/LICM/extra-copies.ll
+++ b/test/Transforms/LICM/extra-copies.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -licm -S | FileCheck %s
+; RUN: opt -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' < %s -S | FileCheck %s
; PR19835
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
diff --git a/test/Transforms/LICM/funclet.ll b/test/Transforms/LICM/funclet.ll
index ef4be2969151..9bdc6dbcde88 100644
--- a/test/Transforms/LICM/funclet.ll
+++ b/test/Transforms/LICM/funclet.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -licm -S | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' < %s -S | FileCheck %s
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
target triple = "i386-pc-windows-msvc18.0.0"
diff --git a/test/Transforms/LICM/hoist-bitcast-load.ll b/test/Transforms/LICM/hoist-bitcast-load.ll
index 47c474c17dde..5752aecde387 100644
--- a/test/Transforms/LICM/hoist-bitcast-load.ll
+++ b/test/Transforms/LICM/hoist-bitcast-load.ll
@@ -1,4 +1,5 @@
; RUN: opt -S -basicaa -licm < %s | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='loop-simplify,require<aa>,require<targetir>,require<scalar-evolution>,loop(simplify-cfg,licm)' -S < %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
diff --git a/test/Transforms/LICM/hoist-deref-load.ll b/test/Transforms/LICM/hoist-deref-load.ll
index fd10c5d7503d..ed6ec7694d3c 100644
--- a/test/Transforms/LICM/hoist-deref-load.ll
+++ b/test/Transforms/LICM/hoist-deref-load.ll
@@ -1,4 +1,5 @@
; RUN: opt -S -basicaa -licm < %s | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='loop-simplify,require<aa>,require<targetir>,require<scalar-evolution>,loop(simplify-cfg,licm)' -S < %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@@ -432,5 +433,127 @@ for.end: ; preds = %for.inc, %entry
ret void
}
+define void @test11(i32* noalias %a, i32* %b, i32** dereferenceable(8) %cptr, i32 %n) #0 {
+; CHECK-LABEL: @test11(
+entry:
+ %cmp11 = icmp sgt i32 %n, 0
+ br i1 %cmp11, label %for.body, label %for.end
+
+; CHECK: for.body.preheader:
+; CHECK: %c = load i32*, i32** %cptr, !dereferenceable !0
+; CHECK: %d = load i32, i32* %c, align 4
+
+
+for.body: ; preds = %entry, %for.inc
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+ %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
+ %0 = load i32, i32* %arrayidx, align 4
+ %cmp1 = icmp sgt i32 %0, 0
+ %c = load i32*, i32** %cptr, !dereferenceable !0
+ br i1 %cmp1, label %if.then, label %for.inc
+
+if.then: ; preds = %for.body
+ %d = load i32, i32* %c, align 4
+ %arrayidx3 = getelementptr inbounds i32, i32* %b, i64 %indvars.iv
+ %e = load i32, i32* %arrayidx3, align 4
+ %mul = mul nsw i32 %e, %d
+ store i32 %mul, i32* %arrayidx, align 4
+ br label %for.inc
+
+for.inc: ; preds = %for.body, %if.then
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ %lftr.wideiv = trunc i64 %indvars.iv.next to i32
+ %exitcond = icmp eq i32 %lftr.wideiv, %n
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.inc, %entry
+ ret void
+}
+
+declare void @llvm.experimental.guard(i1, ...)
+
+define void @test12(i32* noalias %a, i32* %b, i32* dereferenceable_or_null(4) %c, i32 %n) #0 {
+; Prove non-null ness of %c via a guard, not a branch.
+
+; CHECK-LABEL: @test12(
+entry:
+ %not_null = icmp ne i32* %c, null
+ call void(i1, ...) @llvm.experimental.guard(i1 %not_null) [ "deopt"() ]
+ %cmp11 = icmp sgt i32 %n, 0
+ br i1 %cmp11, label %for.body, label %for.end
+
+; CHECK: for.body.preheader:
+; CHECK-NEXT: [[VAL:%[^ ]]] = load i32, i32* %c, align 4
+; CHECK-NEXT: br label %for.body
+
+
+for.body: ; preds = %entry, %for.inc
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+ %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
+ %0 = load i32, i32* %arrayidx, align 4
+ %cmp1 = icmp sgt i32 %0, 0
+ br i1 %cmp1, label %if.then, label %for.inc
+
+if.then: ; preds = %for.body
+ %1 = load i32, i32* %c, align 4
+ %arrayidx3 = getelementptr inbounds i32, i32* %b, i64 %indvars.iv
+ %2 = load i32, i32* %arrayidx3, align 4
+ %mul = mul nsw i32 %2, %1
+ store i32 %mul, i32* %arrayidx, align 4
+ br label %for.inc
+
+for.inc: ; preds = %for.body, %if.then
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ %lftr.wideiv = trunc i64 %indvars.iv.next to i32
+ %exitcond = icmp eq i32 %lftr.wideiv, %n
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.inc, %entry, %entry
+ ret void
+}
+
+define void @test13(i32* noalias %a, i32* %b, i32* dereferenceable_or_null(4) %c, i32 %n) #0 {
+; Like @test12, but has a post-dominating guard, which cannot be used
+; to prove %c is nonnull at the point of the load.
+
+; CHECK-LABEL: @test13(
+entry:
+ %not_null = icmp ne i32* %c, null
+ %cmp11 = icmp sgt i32 %n, 0
+ br i1 %cmp11, label %for.body, label %for.end
+
+; CHECK: for.body.preheader:
+; CHECK-NOT: load i32, i32* %c
+; CHECK: br label %for.body
+
+for.body: ; preds = %entry, %for.inc
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+ %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
+ %0 = load i32, i32* %arrayidx, align 4
+ %cmp1 = icmp sgt i32 %0, 0
+ br i1 %cmp1, label %if.then, label %for.inc
+
+if.then: ; preds = %for.body
+; CHECK: if.then:
+; CHECK: load i32, i32* %c
+; CHECK: br label %for.inc
+ %1 = load i32, i32* %c, align 4
+ %arrayidx3 = getelementptr inbounds i32, i32* %b, i64 %indvars.iv
+ %2 = load i32, i32* %arrayidx3, align 4
+ %mul = mul nsw i32 %2, %1
+ store i32 %mul, i32* %arrayidx, align 4
+ br label %for.inc
+
+for.inc: ; preds = %for.body, %if.then
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ %lftr.wideiv = trunc i64 %indvars.iv.next to i32
+ %exitcond = icmp eq i32 %lftr.wideiv, %n
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.inc, %entry, %entry
+ call void(i1, ...) @llvm.experimental.guard(i1 %not_null) [ "deopt"() ]
+ ret void
+}
+
attributes #0 = { nounwind uwtable }
!0 = !{i64 4}
diff --git a/test/Transforms/LICM/hoist-nounwind.ll b/test/Transforms/LICM/hoist-nounwind.ll
new file mode 100644
index 000000000000..081729f808bf
--- /dev/null
+++ b/test/Transforms/LICM/hoist-nounwind.ll
@@ -0,0 +1,72 @@
+; RUN: opt -S -basicaa -licm < %s | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='lcssa,require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' -S %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @f() nounwind
+
+; Don't hoist load past nounwind call.
+define i32 @test1(i32* noalias nocapture readonly %a) nounwind uwtable {
+; CHECK-LABEL: @test1(
+entry:
+ br label %for.body
+
+; CHECK: tail call void @f()
+; CHECK-NEXT: load i32
+for.body:
+ %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+ %x.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+ tail call void @f() nounwind
+ %i1 = load i32, i32* %a, align 4
+ %add = add nsw i32 %i1, %x.05
+ %inc = add nuw nsw i32 %i.06, 1
+ %exitcond = icmp eq i32 %inc, 1000
+ br i1 %exitcond, label %for.cond.cleanup, label %for.body
+
+for.cond.cleanup:
+ ret i32 %add
+}
+
+; Don't hoist division past nounwind call.
+define i32 @test2(i32 %N, i32 %c) nounwind uwtable {
+; CHECK-LABEL: @test2(
+entry:
+ %cmp4 = icmp sgt i32 %N, 0
+ br i1 %cmp4, label %for.body, label %for.cond.cleanup
+
+; CHECK: tail call void @f()
+; CHECK-NEXT: sdiv i32
+for.body:
+ %i.05 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
+ tail call void @f() nounwind
+ %div = sdiv i32 5, %c
+ %add = add i32 %i.05, 1
+ %inc = add i32 %add, %div
+ %cmp = icmp slt i32 %inc, %N
+ br i1 %cmp, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:
+ ret i32 0
+}
+
+; Don't hoist load past volatile load.
+define i32 @test3(i32* noalias nocapture readonly %a, i32* %v) nounwind uwtable {
+; CHECK-LABEL: @test3(
+entry:
+ br label %for.body
+
+; CHECK: load volatile i32
+; CHECK-NEXT: load i32
+for.body:
+ %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+ %x.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+ %xxx = load volatile i32, i32* %v, align 4
+ %i1 = load i32, i32* %a, align 4
+ %add = add nsw i32 %i1, %x.05
+ %inc = add nuw nsw i32 %i.06, 1
+ %exitcond = icmp eq i32 %inc, 1000
+ br i1 %exitcond, label %for.cond.cleanup, label %for.body
+
+for.cond.cleanup:
+ ret i32 %add
+}
diff --git a/test/Transforms/LICM/hoist-round.ll b/test/Transforms/LICM/hoist-round.ll
new file mode 100644
index 000000000000..a87709b810d2
--- /dev/null
+++ b/test/Transforms/LICM/hoist-round.ll
@@ -0,0 +1,62 @@
+; RUN: opt -S -licm < %s | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' -S %s | FileCheck %s
+
+target datalayout = "E-m:e-p:32:32-i8:8:8-i16:16:16-i64:32:32-f64:32:32-v64:32:32-v128:32:32-a0:0:32-n32"
+
+; This test verifies that ceil, floor, nearbyint, trunc, rint, round,
+; copysign, minnum, maxnum and fabs intrinsics are considered safe
+; to speculate.
+
+; CHECK-LABEL: @test
+; CHECK: call float @llvm.ceil.f32
+; CHECK: call float @llvm.floor.f32
+; CHECK: call float @llvm.nearbyint.f32
+; CHECK: call float @llvm.rint.f32
+; CHECK: call float @llvm.round.f32
+; CHECK: call float @llvm.trunc.f32
+; CHECK: call float @llvm.fabs.f32
+; CHECK: call float @llvm.copysign.f32
+; CHECK: call float @llvm.minnum.f32
+; CHECK: call float @llvm.maxnum.f32
+; CHECK: for.body:
+
+define void @test(float %arg1, float %arg2) {
+entry:
+ br label %for.head
+
+for.head:
+ %IND = phi i32 [ 0, %entry ], [ %IND.new, %for.body ]
+ %CMP = icmp slt i32 %IND, 10
+ br i1 %CMP, label %for.body, label %exit
+
+for.body:
+ %tmp.1 = call float @llvm.ceil.f32(float %arg1)
+ %tmp.2 = call float @llvm.floor.f32(float %tmp.1)
+ %tmp.3 = call float @llvm.nearbyint.f32(float %tmp.2)
+ %tmp.4 = call float @llvm.rint.f32(float %tmp.3)
+ %tmp.5 = call float @llvm.round.f32(float %tmp.4)
+ %tmp.6 = call float @llvm.trunc.f32(float %tmp.5)
+ %tmp.7 = call float @llvm.fabs.f32(float %tmp.6)
+ %tmp.8 = call float @llvm.copysign.f32(float %tmp.7, float %arg2)
+ %tmp.9 = call float @llvm.minnum.f32(float %tmp.8, float %arg2)
+ %tmp.10 = call float @llvm.maxnum.f32(float %tmp.9, float %arg2)
+ call void @consume(float %tmp.10)
+ %IND.new = add i32 %IND, 1
+ br label %for.head
+
+exit:
+ ret void
+}
+
+declare void @consume(float)
+
+declare float @llvm.ceil.f32(float)
+declare float @llvm.floor.f32(float)
+declare float @llvm.nearbyint.f32(float)
+declare float @llvm.rint.f32(float)
+declare float @llvm.round.f32(float)
+declare float @llvm.trunc.f32(float)
+declare float @llvm.fabs.f32(float)
+declare float @llvm.copysign.f32(float, float)
+declare float @llvm.minnum.f32(float, float)
+declare float @llvm.maxnum.f32(float, float)
diff --git a/test/Transforms/LICM/hoisting.ll b/test/Transforms/LICM/hoisting.ll
index 8609407cc599..cb6981ede1e7 100644
--- a/test/Transforms/LICM/hoisting.ll
+++ b/test/Transforms/LICM/hoisting.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -licm -S | FileCheck %s
+; RUN: opt -lcssa %s | opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' -S | FileCheck %s
@X = global i32 0 ; <i32*> [#uses=1]
@@ -37,16 +38,21 @@ define i32 @test2(i1 %c) {
; CHECK-LABEL: @test2(
; CHECK-NEXT: load i32, i32* @X
; CHECK-NEXT: %B = sdiv i32 4, %A
- %A = load i32, i32* @X ; <i32> [#uses=2]
- br label %Loop
+ %A = load i32, i32* @X
+ br label %Loop
+
Loop:
- ;; Should have hoisted this div!
- %B = sdiv i32 4, %A ; <i32> [#uses=2]
- call void @foo2( i32 %B )
- br i1 %c, label %Loop, label %Out
-Out: ; preds = %Loop
- %C = sub i32 %A, %B ; <i32> [#uses=1]
- ret i32 %C
+ ;; Should have hoisted this div!
+ %B = sdiv i32 4, %A
+ br label %loop2
+
+loop2:
+ call void @foo2( i32 %B )
+ br i1 %c, label %Loop, label %Out
+
+Out:
+ %C = sub i32 %A, %B
+ ret i32 %C
}
diff --git a/test/Transforms/LICM/lcssa-ssa-promoter.ll b/test/Transforms/LICM/lcssa-ssa-promoter.ll
index b0cae8772f3e..d466b3baffc8 100644
--- a/test/Transforms/LICM/lcssa-ssa-promoter.ll
+++ b/test/Transforms/LICM/lcssa-ssa-promoter.ll
@@ -1,4 +1,5 @@
; RUN: opt -S -basicaa -licm < %s | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' -S %s| FileCheck %s
;
; Manually validate LCSSA form is preserved even after SSAUpdater is used to
; promote things in the loop bodies.
diff --git a/test/Transforms/LICM/no-preheader-test.ll b/test/Transforms/LICM/no-preheader-test.ll
index bd3eea38ef3e..4b6847cdad51 100644
--- a/test/Transforms/LICM/no-preheader-test.ll
+++ b/test/Transforms/LICM/no-preheader-test.ll
@@ -1,5 +1,6 @@
; Test that LICM works when there is not a loop-preheader
; RUN: opt < %s -licm | llvm-dis
+; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' < %s | llvm-dis
define void @testfunc(i32 %i.s, i1 %ifcond) {
br i1 %ifcond, label %Then, label %Else
diff --git a/test/Transforms/LICM/pr26843.ll b/test/Transforms/LICM/pr26843.ll
new file mode 100644
index 000000000000..a14acbef964f
--- /dev/null
+++ b/test/Transforms/LICM/pr26843.ll
@@ -0,0 +1,32 @@
+; RUN: opt -S -basicaa -licm < %s | FileCheck %s
+
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i686-pc-windows-msvc18.0.0"
+
+@v = common global i32 zeroinitializer, align 4
+
+; Make sure the store to v is not sunk past the memset
+; CHECK-LABEL: @main
+; CHECK: for.body:
+; CHECK-NEXT: store i32 1, i32* @v
+; CHECK-NEXT: tail call void @llvm.memset
+; CHECK: end:
+; CHECK-NEXT: ret i32 0
+
+define i32 @main(i1 %k) {
+entry:
+ br label %for.body
+
+for.body:
+ store i32 1, i32* @v, align 4
+ tail call void @llvm.memset.p0i8.i32(i8* bitcast (i32* @v to i8*), i8 0, i32 4, i32 4, i1 false)
+ br label %for.latch
+
+for.latch:
+ br i1 %k, label %for.body, label %end
+
+end:
+ ret i32 0
+}
+
+declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1)
diff --git a/test/Transforms/LICM/pr27262.ll b/test/Transforms/LICM/pr27262.ll
new file mode 100644
index 000000000000..5fc6d9389e0d
--- /dev/null
+++ b/test/Transforms/LICM/pr27262.ll
@@ -0,0 +1,33 @@
+; RUN: opt -S -basicaa -licm < %s | FileCheck %s
+
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i686-pc-windows-msvc18.0.0"
+
+; Make sure the store to v is not sunk past the memset
+; CHECK-LABEL: @main
+; CHECK: for.body:
+; CHECK-NEXT: store i8 1, i8* %p
+; CHECK-NEXT: store i8 2, i8* %p1
+; CHECK-NEXT: call void @llvm.memset
+; CHECK: end:
+; CHECK-NEXT: ret i32 0
+
+define i32 @main(i1 %k, i8* %p) {
+entry:
+ %p1 = getelementptr i8, i8* %p, i32 1
+ br label %for.body
+
+for.body:
+ store i8 1, i8* %p, align 1
+ store i8 2, i8* %p1, align 1
+ call void @llvm.memset.p0i8.i32(i8* %p, i8 255, i32 4, i32 1, i1 false)
+ br label %for.latch
+
+for.latch:
+ br i1 %k, label %for.body, label %end
+
+end:
+ ret i32 0
+}
+
+declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1)
diff --git a/test/Transforms/LICM/preheader-safe.ll b/test/Transforms/LICM/preheader-safe.ll
index 260a5f653b77..adc4f4237a29 100644
--- a/test/Transforms/LICM/preheader-safe.ll
+++ b/test/Transforms/LICM/preheader-safe.ll
@@ -1,4 +1,5 @@
; RUN: opt -S -licm < %s | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' -S %s | FileCheck %s
declare void @use_nothrow(i64 %a) nounwind
declare void @use(i64 %a)
@@ -14,6 +15,9 @@ entry:
loop: ; preds = %entry, %for.inc
%div = udiv i64 %x, %y
+ br label %loop2
+
+loop2:
call void @use_nothrow(i64 %div)
br label %loop
}
diff --git a/test/Transforms/LICM/promote-order.ll b/test/Transforms/LICM/promote-order.ll
index a189cf22f66b..7d87bb221b76 100644
--- a/test/Transforms/LICM/promote-order.ll
+++ b/test/Transforms/LICM/promote-order.ll
@@ -1,4 +1,5 @@
; RUN: opt -tbaa -basicaa -licm -S < %s | FileCheck %s
+; RUN: opt -aa-pipeline=type-based-aa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' -S %s | FileCheck %s
; LICM should keep the stores in their original order when it sinks/promotes them.
; rdar://12045203
diff --git a/test/Transforms/LICM/promote-tls.ll b/test/Transforms/LICM/promote-tls.ll
new file mode 100644
index 000000000000..e3654902a124
--- /dev/null
+++ b/test/Transforms/LICM/promote-tls.ll
@@ -0,0 +1,134 @@
+; RUN: opt -tbaa -basicaa -licm -S < %s | FileCheck %s
+; RUN: opt -aa-pipeline=type-based-aa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' -S %s | FileCheck %s
+
+; If we can prove a local is thread local, we can insert stores during
+; promotion which wouldn't be legal otherwise.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-linux-generic"
+
+@p = external global i8*
+
+declare i8* @malloc(i64)
+
+; Exercise the TLS case
+define i32* @test(i32 %n) {
+entry:
+ ;; ignore the required null check for simplicity
+ %mem = call dereferenceable(16) noalias i8* @malloc(i64 16)
+ %addr = bitcast i8* %mem to i32*
+ br label %for.body.lr.ph
+
+for.body.lr.ph: ; preds = %entry
+ br label %for.header
+
+for.header:
+ %i.02 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
+ %old = load i32, i32* %addr, align 4
+ ; deliberate impossible to analyze branch
+ %guard = load atomic i8*, i8** @p monotonic, align 8
+ %exitcmp = icmp eq i8* %guard, null
+ br i1 %exitcmp, label %for.body, label %early-exit
+
+early-exit:
+; CHECK-LABEL: early-exit:
+; CHECK: store i32 %new1.lcssa, i32* %addr, align 1
+ ret i32* null
+
+for.body:
+ %new = add i32 %old, 1
+ store i32 %new, i32* %addr, align 4
+ %inc = add nsw i32 %i.02, 1
+ %cmp = icmp slt i32 %inc, %n
+ br i1 %cmp, label %for.header, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge: ; preds = %for.body
+; CHECK-LABEL: for.cond.for.end_crit_edge:
+; CHECK: store i32 %new.lcssa, i32* %addr, align 1
+ %split = phi i32* [ %addr, %for.body ]
+ ret i32* null
+}
+
+declare i8* @not_malloc(i64)
+
+; Negative test - not TLS
+define i32* @test_neg(i32 %n) {
+entry:
+ ;; ignore the required null check for simplicity
+ %mem = call dereferenceable(16) noalias i8* @not_malloc(i64 16)
+ %addr = bitcast i8* %mem to i32*
+ br label %for.body.lr.ph
+
+for.body.lr.ph: ; preds = %entry
+ br label %for.header
+
+for.header:
+ %i.02 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
+ %old = load i32, i32* %addr, align 4
+ ; deliberate impossible to analyze branch
+ %guard = load volatile i8*, i8** @p
+ %exitcmp = icmp eq i8* %guard, null
+ br i1 %exitcmp, label %for.body, label %early-exit
+
+early-exit:
+; CHECK-LABEL: early-exit:
+; CHECK-NOT: store
+ ret i32* null
+
+for.body:
+; CHECK-LABEL: for.body:
+; CHECK: store i32 %new, i32* %addr, align 4
+ %new = add i32 %old, 1
+ store i32 %new, i32* %addr, align 4
+ %inc = add nsw i32 %i.02, 1
+ %cmp = icmp slt i32 %inc, %n
+ br i1 %cmp, label %for.header, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge: ; preds = %for.body
+; CHECK-LABEL: for.cond.for.end_crit_edge:
+; CHECK-NOT: store
+ %split = phi i32* [ %addr, %for.body ]
+ ret i32* null
+}
+
+; Negative test - can't speculate load since branch
+; may control alignment
+define i32* @test_neg2(i32 %n) {
+entry:
+ ;; ignore the required null check for simplicity
+ %mem = call dereferenceable(16) noalias i8* @malloc(i64 16)
+ %addr = bitcast i8* %mem to i32*
+ br label %for.body.lr.ph
+
+for.body.lr.ph: ; preds = %entry
+ br label %for.header
+
+for.header:
+ %i.02 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
+ ; deliberate impossible to analyze branch
+ %guard = load volatile i8*, i8** @p
+ %exitcmp = icmp eq i8* %guard, null
+ br i1 %exitcmp, label %for.body, label %early-exit
+
+early-exit:
+; CHECK-LABEL: early-exit:
+; CHECK-NOT: store
+ ret i32* null
+
+for.body:
+; CHECK-LABEL: for.body:
+; CHECK: store i32 %new, i32* %addr, align 4
+ %old = load i32, i32* %addr, align 4
+ %new = add i32 %old, 1
+ store i32 %new, i32* %addr, align 4
+ %inc = add nsw i32 %i.02, 1
+ %cmp = icmp slt i32 %inc, %n
+ br i1 %cmp, label %for.header, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge: ; preds = %for.body
+; CHECK-LABEL: for.cond.for.end_crit_edge:
+; CHECK-NOT: store
+ %split = phi i32* [ %addr, %for.body ]
+ ret i32* null
+}
+
diff --git a/test/Transforms/LICM/scalar-promote-memmodel.ll b/test/Transforms/LICM/scalar-promote-memmodel.ll
index 3603c25ba23c..ceee7292ac5c 100644
--- a/test/Transforms/LICM/scalar-promote-memmodel.ll
+++ b/test/Transforms/LICM/scalar-promote-memmodel.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -basicaa -licm -S | FileCheck %s
+; RUN: opt -aa-pipeline=type-based-aa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' -S %s | FileCheck %s
; Make sure we don't hoist a conditionally-executed store out of the loop;
; it would violate the concurrency memory model
diff --git a/test/Transforms/LICM/scalar_promote-unwind.ll b/test/Transforms/LICM/scalar_promote-unwind.ll
new file mode 100644
index 000000000000..22e7e50c22e5
--- /dev/null
+++ b/test/Transforms/LICM/scalar_promote-unwind.ll
@@ -0,0 +1,72 @@
+; RUN: opt < %s -basicaa -licm -S | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' -S %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Make sure we don't hoist the store out of the loop; %a would
+; have the wrong value if f() unwinds
+
+define void @test1(i32* nocapture noalias %a, i1 zeroext %y) uwtable {
+entry:
+ br label %for.body
+
+for.body:
+ %i.03 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+ %0 = load i32, i32* %a, align 4
+ %add = add nsw i32 %0, 1
+ store i32 %add, i32* %a, align 4
+ br i1 %y, label %if.then, label %for.inc
+
+; CHECK: define void @test1
+; CHECK: load i32, i32*
+; CHECK-NEXT: add
+; CHECK-NEXT: store i32
+
+if.then:
+ tail call void @f()
+ br label %for.inc
+
+for.inc:
+ %inc = add nuw nsw i32 %i.03, 1
+ %exitcond = icmp eq i32 %inc, 10000
+ br i1 %exitcond, label %for.cond.cleanup, label %for.body
+
+for.cond.cleanup:
+ ret void
+}
+
+; We can hoist the store out of the loop here; if f() unwinds,
+; the lifetime of %a ends.
+
+define void @test2(i1 zeroext %y) uwtable {
+entry:
+ %a = alloca i32
+ br label %for.body
+
+for.body:
+ %i.03 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+ %0 = load i32, i32* %a, align 4
+ %add = add nsw i32 %0, 1
+ store i32 %add, i32* %a, align 4
+ br i1 %y, label %if.then, label %for.inc
+
+if.then:
+ tail call void @f()
+ br label %for.inc
+
+for.inc:
+ %inc = add nuw nsw i32 %i.03, 1
+ %exitcond = icmp eq i32 %inc, 10000
+ br i1 %exitcond, label %for.cond.cleanup, label %for.body
+
+for.cond.cleanup:
+ ret void
+
+; CHECK: define void @test2
+; CHECK: store i32
+; CHECK-NEXT: ret void
+ ret void
+}
+
+declare void @f() uwtable
diff --git a/test/Transforms/LICM/scalar_promote.ll b/test/Transforms/LICM/scalar_promote.ll
index 6ef4bac39bbc..91cdbdbc2269 100644
--- a/test/Transforms/LICM/scalar_promote.ll
+++ b/test/Transforms/LICM/scalar_promote.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -basicaa -tbaa -licm -S | FileCheck %s
+; RUN: opt -aa-pipeline=type-based-aa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' -S %s | FileCheck %s
target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
@X = global i32 7 ; <i32*> [#uses=4]
@@ -135,7 +136,7 @@ Loop: ; preds = %Loop, %0
%x2 = add i32 %x, 1 ; <i32> [#uses=1]
store i32 %x2, i32* @X
- store volatile i32* @X, i32** %P2
+ store atomic i32* @X, i32** %P2 monotonic, align 8
%Next = add i32 %j, 1 ; <i32> [#uses=2]
%cond = icmp eq i32 %Next, 0 ; <i1> [#uses=1]
diff --git a/test/Transforms/LICM/speculate.ll b/test/Transforms/LICM/speculate.ll
index 91b5a25ac0f5..fed1cbaa8555 100644
--- a/test/Transforms/LICM/speculate.ll
+++ b/test/Transforms/LICM/speculate.ll
@@ -1,4 +1,5 @@
; RUN: opt -S -licm < %s | FileCheck %s
+; RUN: opt -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' -S %s | FileCheck %s
; UDiv is safe to speculate if the denominator is known non-zero.
diff --git a/test/Transforms/LICM/update-scev.ll b/test/Transforms/LICM/update-scev.ll
new file mode 100644
index 000000000000..221c124c8bf1
--- /dev/null
+++ b/test/Transforms/LICM/update-scev.ll
@@ -0,0 +1,31 @@
+; RUN: opt -S -licm < %s | FileCheck %s --check-prefix=IR-AFTER-TRANSFORM
+; RUN: opt -analyze -scalar-evolution -licm -scalar-evolution < %s | FileCheck %s --check-prefix=SCEV-EXPRS
+
+declare void @clobber()
+
+define void @f_0(i1* %loc) {
+; IR-AFTER-TRANSFORM-LABEL: @f_0(
+; IR-AFTER-TRANSFORM: loop.outer:
+; IR-AFTER-TRANSFORM-NEXT: call void @clobber()
+; IR-AFTER-TRANSFORM-NEXT: %cond = load i1, i1* %loc
+; IR-AFTER-TRANSFORM-NEXT: br label %loop.inner
+
+; SCEV-EXPRS: Classifying expressions for: @f_0
+; SCEV-EXPRS: Classifying expressions for: @f_0
+; SCEV-EXPRS: %cond = load i1, i1* %loc
+; SCEV-EXPRS-NEXT: --> {{.*}} LoopDispositions: { %loop.outer: Variant, %loop.inner: Invariant }
+
+entry:
+ br label %loop.outer
+
+loop.outer:
+ call void @clobber()
+ br label %loop.inner
+
+loop.inner:
+ %cond = load i1, i1* %loc
+ br i1 %cond, label %loop.inner, label %leave.inner
+
+leave.inner:
+ br label %loop.outer
+}
diff --git a/test/Transforms/LICM/volatile-alias.ll b/test/Transforms/LICM/volatile-alias.ll
index fda930df933b..7836df004c0f 100644
--- a/test/Transforms/LICM/volatile-alias.ll
+++ b/test/Transforms/LICM/volatile-alias.ll
@@ -1,4 +1,5 @@
; RUN: opt -basicaa -sroa -loop-rotate -licm -S < %s | FileCheck %s
+; RUN: opt -basicaa -sroa -loop-rotate %s | opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,loop(licm)' -S | FileCheck %s
; The objects *p and *q are aliased to each other, but even though *q is
; volatile, *p can be considered invariant in the loop. Check if it is moved
; out of the loop.
@@ -9,7 +10,7 @@
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
; Function Attrs: nounwind uwtable
-define i32 @foo(i32* %p, i32* %q, i32 %n) #0 {
+define i32 @foo(i32* dereferenceable(4) nonnull %p, i32* %q, i32 %n) #0 {
entry:
%p.addr = alloca i32*, align 8
%q.addr = alloca i32*, align 8