aboutsummaryrefslogtreecommitdiff
path: root/test/Transforms
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-05-03 20:26:11 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-05-03 20:26:11 +0000
commit148779df305667b6942fee7e758fdf81a6498f38 (patch)
tree976d85fb9cb4bc8ed54348b045f742be90e10c57 /test/Transforms
parenta303c417bbdb53703c2c17398b08486bde78f1f6 (diff)
Notes
Diffstat (limited to 'test/Transforms')
-rw-r--r--test/Transforms/BBVectorize/simple-int.ll2
-rw-r--r--test/Transforms/CodeExtractor/PartialInlineOptRemark.ll19
-rw-r--r--test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll2
-rw-r--r--test/Transforms/FunctionAttrs/readattrs.ll9
-rw-r--r--test/Transforms/FunctionImport/unnamed-globals.ll10
-rw-r--r--test/Transforms/GVN/2016-08-30-MaskedScatterGather.ll16
-rw-r--r--test/Transforms/InstCombine/intrinsics.ll4
-rw-r--r--test/Transforms/InstCombine/masked_intrinsics.ll8
-rw-r--r--test/Transforms/InstCombine/pow-sqrt.ll9
-rw-r--r--test/Transforms/InstCombine/sub-xor.ll2
-rw-r--r--test/Transforms/LoopDeletion/unreachable-loops.ll336
-rw-r--r--test/Transforms/LoopVectorize/X86/consecutive-ptr-uniforms.ll2
-rw-r--r--test/Transforms/LoopVectorize/X86/gather_scatter.ll206
-rwxr-xr-xtest/Transforms/LoopVectorize/X86/scatter_crash.ll4
-rw-r--r--test/Transforms/NewGVN/2016-08-30-MaskedScatterGather.ll16
-rw-r--r--test/Transforms/ObjCARC/basic.ll2
-rw-r--r--test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll2
-rw-r--r--test/Transforms/SLPVectorizer/X86/call.ll2
-rw-r--r--test/Transforms/SpeculativeExecution/spec-other.ll32
-rw-r--r--test/Transforms/SpeculativeExecution/spec-vector.ll73
20 files changed, 700 insertions, 56 deletions
diff --git a/test/Transforms/BBVectorize/simple-int.ll b/test/Transforms/BBVectorize/simple-int.ll
index 6b50e2b4f2fc..b7f87fe1db0e 100644
--- a/test/Transforms/BBVectorize/simple-int.ll
+++ b/test/Transforms/BBVectorize/simple-int.ll
@@ -503,4 +503,4 @@ define i64 @testcttzneg(i64 %A1, i64 %A2, i64 %B1, i64 %B2) {
; CHECK: declare <2 x i64> @llvm.ctpop.v2i64(<2 x i64>) #0
; CHECK: declare <2 x i64> @llvm.ctlz.v2i64(<2 x i64>, i1) #0
; CHECK: declare <2 x i64> @llvm.cttz.v2i64(<2 x i64>, i1) #0
-; CHECK: attributes #0 = { nounwind readnone }
+; CHECK: attributes #0 = { nounwind readnone speculatable }
diff --git a/test/Transforms/CodeExtractor/PartialInlineOptRemark.ll b/test/Transforms/CodeExtractor/PartialInlineOptRemark.ll
index c8808182f717..b2442b8b173c 100644
--- a/test/Transforms/CodeExtractor/PartialInlineOptRemark.ll
+++ b/test/Transforms/CodeExtractor/PartialInlineOptRemark.ll
@@ -64,6 +64,22 @@ bb2: ; preds = %bb1, %bb
ret i32 %tmp3, !dbg !19
}
+define i32 @bar_cold(i32 %arg) local_unnamed_addr #3 !dbg !5 {
+bb:
+ %tmp = icmp slt i32 %arg, 0, !dbg !7
+ br i1 %tmp, label %bb1, label %bb2, !dbg !8
+
+bb1: ; preds = %bb
+ tail call void (...) @foo() #0, !dbg !9
+ tail call void (...) @foo() #0, !dbg !10
+ tail call void (...) @foo() #0, !dbg !11
+ br label %bb2, !dbg !18
+
+bb2: ; preds = %bb1, %bb
+ %tmp3 = phi i32 [ 0, %bb1 ], [ 1, %bb ]
+ ret i32 %tmp3, !dbg !19
+}
+
; Function Attrs: nounwind
declare void @foo(...) local_unnamed_addr #0
@@ -73,16 +89,19 @@ bb:
; CHECK:remark{{.*}}bar partially inlined into dummy_caller
; CHECK-NOT:remark{{.*}}bar_noinline partially inlined into dummy_caller
; CHECK-NOT:remark{{.*}}bar_alwaysinline partially inlined into dummy_caller
+; CHECK-NOT:remark{{.*}}bar_cold partially inlined into dummy_caller
; LIMIT-NOT:remark{{.*}}bar partially inlined into dummy_caller
%tmp = tail call i32 @bar(i32 %arg), !dbg !21
%tmp2 = tail call i32 @bar_noinline(i32 %arg), !dbg !21
%tmp3 = tail call i32 @bar_alwaysinline(i32 %arg), !dbg !21
+ %tmp4 = tail call i32 @bar_cold(i32 %arg), !dbg !21
ret i32 %tmp, !dbg !22
}
attributes #0 = { nounwind }
attributes #1 = { noinline nounwind }
attributes #2 = { alwaysinline nounwind }
+attributes #3 = { cold nounwind }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3}
diff --git a/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll b/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll
index dfa999e1b34f..aec00e81bb48 100644
--- a/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll
+++ b/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll
@@ -39,7 +39,7 @@ bb2: ; preds = %bb1, %bb
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone
; CHECK: attributes #0 = { nounwind ssp }
-; CHECK: attributes #1 = { nounwind readnone }
+; CHECK: attributes #1 = { nounwind readnone speculatable }
; CHECK: attributes #2 = { noinline nounwind ssp }
; CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/Transforms/FunctionAttrs/readattrs.ll b/test/Transforms/FunctionAttrs/readattrs.ll
index 988557e27152..3728a7179724 100644
--- a/test/Transforms/FunctionAttrs/readattrs.ll
+++ b/test/Transforms/FunctionAttrs/readattrs.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -functionattrs -S | FileCheck %s
; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs)' -S | FileCheck %s
@x = global i32 0
@@ -68,22 +69,22 @@ entry:
}
; CHECK: declare void @llvm.masked.scatter
-declare void @llvm.masked.scatter.v4i32(<4 x i32>%val, <4 x i32*>, i32, <4 x i1>)
+declare void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>%val, <4 x i32*>, i32, <4 x i1>)
; CHECK-NOT: readnone
; CHECK-NOT: readonly
; CHECK: define void @test9
define void @test9(<4 x i32*> %ptrs, <4 x i32>%val) {
- call void @llvm.masked.scatter.v4i32(<4 x i32>%val, <4 x i32*> %ptrs, i32 4, <4 x i1><i1 true, i1 false, i1 true, i1 false>)
+ call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>%val, <4 x i32*> %ptrs, i32 4, <4 x i1><i1 true, i1 false, i1 true, i1 false>)
ret void
}
; CHECK: declare <4 x i32> @llvm.masked.gather
-declare <4 x i32> @llvm.masked.gather.v4i32(<4 x i32*>, i32, <4 x i1>, <4 x i32>)
+declare <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*>, i32, <4 x i1>, <4 x i32>)
; CHECK: readonly
; CHECK: define <4 x i32> @test10
define <4 x i32> @test10(<4 x i32*> %ptrs) {
- %res = call <4 x i32> @llvm.masked.gather.v4i32(<4 x i32*> %ptrs, i32 4, <4 x i1><i1 true, i1 false, i1 true, i1 false>, <4 x i32>undef)
+ %res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %ptrs, i32 4, <4 x i1><i1 true, i1 false, i1 true, i1 false>, <4 x i32>undef)
ret <4 x i32> %res
}
diff --git a/test/Transforms/FunctionImport/unnamed-globals.ll b/test/Transforms/FunctionImport/unnamed-globals.ll
deleted file mode 100644
index 167fad28f439..000000000000
--- a/test/Transforms/FunctionImport/unnamed-globals.ll
+++ /dev/null
@@ -1,10 +0,0 @@
-; Make sure we don't crash when referencing an unnamed global.
-; RUN: opt %s -module-summary-analysis -S
-
-@0 = external global [1 x { i64 }]
-
-define internal void @tinkywinky() {
- call void @patatino(i64 ptrtoint ([1 x { i64 }]* @0 to i64), i64 4)
- ret void
-}
-declare void @patatino(i64, i64)
diff --git a/test/Transforms/GVN/2016-08-30-MaskedScatterGather.ll b/test/Transforms/GVN/2016-08-30-MaskedScatterGather.ll
index 3f8fdcc8eafb..5b10a1bfc79e 100644
--- a/test/Transforms/GVN/2016-08-30-MaskedScatterGather.ll
+++ b/test/Transforms/GVN/2016-08-30-MaskedScatterGather.ll
@@ -1,7 +1,7 @@
; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
-declare void @llvm.masked.scatter.v2i32(<2 x i32> , <2 x i32*> , i32 , <2 x i1> )
-declare <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*>, i32, <2 x i1>, <2 x i32>)
+declare void @llvm.masked.scatter.v2i32.v2p0i32(<2 x i32> , <2 x i32*> , i32 , <2 x i1> )
+declare <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*>, i32, <2 x i1>, <2 x i32>)
; This test ensures that masked scatter and gather operations, which take vectors of pointers,
; do not have pointer aliasing ignored when being processed.
@@ -20,18 +20,18 @@ entry:
%tmp.i = insertelement <2 x i32*> undef, i32* %tmp.0, i32 0
%tmp = insertelement <2 x i32*> %tmp.i, i32* %tmp.1, i32 1
; Read from in1 and in2
- %in1.v = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %in1, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
- %in2.v = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %in2, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
+ %in1.v = call <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*> %in1, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
+ %in2.v = call <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*> %in2, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
; Store in1 to the allocas
- call void @llvm.masked.scatter.v2i32(<2 x i32> %in1.v, <2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>);
+ call void @llvm.masked.scatter.v2i32.v2p0i32(<2 x i32> %in1.v, <2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>);
; Read in1 from the allocas
; This gather should alias the scatter we just saw
- %tmp.v.0 = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
+ %tmp.v.0 = call <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
; Store in2 to the allocas
- call void @llvm.masked.scatter.v2i32(<2 x i32> %in2.v, <2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>);
+ call void @llvm.masked.scatter.v2i32.v2p0i32(<2 x i32> %in2.v, <2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>);
; Read in2 from the allocas
; This gather should alias the scatter we just saw, and not be eliminated
- %tmp.v.1 = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
+ %tmp.v.1 = call <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
; Store in2 to out for good measure
%tmp.v.1.0 = extractelement <2 x i32> %tmp.v.1, i32 0
%tmp.v.1.1 = extractelement <2 x i32> %tmp.v.1, i32 1
diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll
index b9e208440581..66ab7f48aeff 100644
--- a/test/Transforms/InstCombine/intrinsics.ll
+++ b/test/Transforms/InstCombine/intrinsics.ll
@@ -284,7 +284,7 @@ define i32 @cttz(i32 %a) {
define i1 @cttz_knownbits(i32 %arg) {
; CHECK-LABEL: @cttz_knownbits(
; CHECK-NEXT: [[OR:%.*]] = or i32 [[ARG:%.*]], 4
-; CHECK-NEXT: [[CNT:%.*]] = call i32 @llvm.cttz.i32(i32 [[OR]], i1 true) #0
+; CHECK-NEXT: [[CNT:%.*]] = call i32 @llvm.cttz.i32(i32 [[OR]], i1 true)
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[CNT]], 4
; CHECK-NEXT: ret i1 [[RES]]
;
@@ -307,7 +307,7 @@ define i8 @ctlz(i8 %a) {
define i1 @ctlz_knownbits(i8 %arg) {
; CHECK-LABEL: @ctlz_knownbits(
; CHECK-NEXT: [[OR:%.*]] = or i8 [[ARG:%.*]], 32
-; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctlz.i8(i8 [[OR]], i1 true) #0
+; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctlz.i8(i8 [[OR]], i1 true)
; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[CNT]], 4
; CHECK-NEXT: ret i1 [[RES]]
;
diff --git a/test/Transforms/InstCombine/masked_intrinsics.ll b/test/Transforms/InstCombine/masked_intrinsics.ll
index ce79ce56b5cb..d5403d17ddc2 100644
--- a/test/Transforms/InstCombine/masked_intrinsics.ll
+++ b/test/Transforms/InstCombine/masked_intrinsics.ll
@@ -2,8 +2,8 @@
declare <2 x double> @llvm.masked.load.v2f64.p0v2f64(<2 x double>* %ptrs, i32, <2 x i1> %mask, <2 x double> %src0)
declare void @llvm.masked.store.v2f64.p0v2f64(<2 x double> %val, <2 x double>* %ptrs, i32, <2 x i1> %mask)
-declare <2 x double> @llvm.masked.gather.v2f64(<2 x double*> %ptrs, i32, <2 x i1> %mask, <2 x double> %passthru)
-declare void @llvm.masked.scatter.v2f64(<2 x double> %val, <2 x double*> %ptrs, i32, <2 x i1> %mask)
+declare <2 x double> @llvm.masked.gather.v2f64.v2p0f64(<2 x double*> %ptrs, i32, <2 x i1> %mask, <2 x double> %passthru)
+declare void @llvm.masked.scatter.v2f64.v2p0f64(<2 x double> %val, <2 x double*> %ptrs, i32, <2 x i1> %mask)
define <2 x double> @load_zeromask(<2 x double>* %ptr, <2 x double> %passthru) {
%res = call <2 x double> @llvm.masked.load.v2f64.p0v2f64(<2 x double>* %ptr, i32 1, <2 x i1> zeroinitializer, <2 x double> %passthru)
@@ -49,7 +49,7 @@ define void @store_onemask(<2 x double>* %ptr, <2 x double> %val) {
}
define <2 x double> @gather_zeromask(<2 x double*> %ptrs, <2 x double> %passthru) {
- %res = call <2 x double> @llvm.masked.gather.v2f64(<2 x double*> %ptrs, i32 5, <2 x i1> zeroinitializer, <2 x double> %passthru)
+ %res = call <2 x double> @llvm.masked.gather.v2f64.v2p0f64(<2 x double*> %ptrs, i32 5, <2 x i1> zeroinitializer, <2 x double> %passthru)
ret <2 x double> %res
; CHECK-LABEL: @gather_zeromask(
@@ -57,7 +57,7 @@ define <2 x double> @gather_zeromask(<2 x double*> %ptrs, <2 x double> %passthru
}
define void @scatter_zeromask(<2 x double*> %ptrs, <2 x double> %val) {
- call void @llvm.masked.scatter.v2f64(<2 x double> %val, <2 x double*> %ptrs, i32 6, <2 x i1> zeroinitializer)
+ call void @llvm.masked.scatter.v2f64.v2p0f64(<2 x double> %val, <2 x double*> %ptrs, i32 6, <2 x i1> zeroinitializer)
ret void
; CHECK-LABEL: @scatter_zeromask(
diff --git a/test/Transforms/InstCombine/pow-sqrt.ll b/test/Transforms/InstCombine/pow-sqrt.ll
index 52175f1b1247..82db192ed801 100644
--- a/test/Transforms/InstCombine/pow-sqrt.ll
+++ b/test/Transforms/InstCombine/pow-sqrt.ll
@@ -6,7 +6,7 @@ define double @pow_half(double %x) {
}
; CHECK-LABEL: define double @pow_half(
-; CHECK-NEXT: %sqrt = call fast double @sqrt(double %x)
+; CHECK-NEXT: %sqrt = call fast double @sqrt(double %x) #1
; CHECK-NEXT: ret double %sqrt
define double @pow_neghalf(double %x) {
@@ -15,8 +15,11 @@ define double @pow_neghalf(double %x) {
}
; CHECK-LABEL: define double @pow_neghalf(
-; CHECK-NEXT: %sqrt = call fast double @sqrt(double %x) #0
+; CHECK-NEXT: %sqrt = call fast double @sqrt(double %x) #1
; CHECK-NEXT: %sqrtrecip = fdiv fast double 1.000000e+00, %sqrt
; CHECK-NEXT: ret double %sqrtrecip
-declare double @llvm.pow.f64(double, double)
+declare double @llvm.pow.f64(double, double) #0
+
+attributes #0 = { nounwind readnone speculatable }
+attributes #1 = { nounwind readnone }
diff --git a/test/Transforms/InstCombine/sub-xor.ll b/test/Transforms/InstCombine/sub-xor.ll
index 812305d8e489..adcca8480594 100644
--- a/test/Transforms/InstCombine/sub-xor.ll
+++ b/test/Transforms/InstCombine/sub-xor.ll
@@ -27,7 +27,7 @@ declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone
define i32 @test2(i32 %x) nounwind {
; CHECK-LABEL: @test2(
-; CHECK-NEXT: [[COUNT:%.*]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) #0
+; CHECK-NEXT: [[COUNT:%.*]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
; CHECK-NEXT: [[SUB:%.*]] = xor i32 [[COUNT]], 31
; CHECK-NEXT: ret i32 [[SUB]]
;
diff --git a/test/Transforms/LoopDeletion/unreachable-loops.ll b/test/Transforms/LoopDeletion/unreachable-loops.ll
new file mode 100644
index 000000000000..147a85670121
--- /dev/null
+++ b/test/Transforms/LoopDeletion/unreachable-loops.ll
@@ -0,0 +1,336 @@
+; RUN: opt < %s -loop-deletion -verify-dom-info -S | FileCheck %s
+
+; Checking that we can delete loops that are never executed.
+; We do not change the constant conditional branch statement (where the not-taken target
+; is the loop) to an unconditional one.
+
+; delete the infinite loop because it is never executed.
+define void @test1(i64 %n, i64 %m) nounwind {
+; CHECK-LABEL: test1
+; CHECK-LABEL: entry:
+; CHECK-NEXT: br i1 true, label %return, label %bb.preheader
+; CHECK-NOT: bb:
+entry:
+ br i1 true, label %return, label %bb
+
+bb:
+ %x.0 = phi i64 [ 0, %entry ], [ %t0, %bb ]
+ %t0 = add i64 %x.0, 1
+ %t1 = icmp slt i64 %x.0, %n
+ %t3 = icmp sgt i64 %x.0, %m
+ %t4 = and i1 %t1, %t3
+ br i1 true, label %bb, label %return
+
+return:
+ ret void
+}
+
+; FIXME: We can delete this infinite loop. Currently we do not,
+; because the infinite loop has no exit block.
+define void @test2(i64 %n, i64 %m) nounwind {
+; CHECK-LABEL: test2
+; CHECK-LABEL: entry:
+; CHECK-NEXT: br i1 true, label %return, label %bb.preheader
+; CHECK-LABEL: bb:
+; CHECK: br label %bb
+entry:
+ br i1 true, label %return, label %bb
+
+bb:
+ %x.0 = phi i64 [ 0, %entry ], [ %t0, %bb ]
+ %t0 = add i64 %x.0, 1
+ %t1 = icmp slt i64 %x.0, %n
+ %t3 = icmp sgt i64 %x.0, %m
+ %t4 = and i1 %t1, %t3
+ br label %bb
+
+return:
+ ret void
+}
+
+; There are multiple exiting blocks and a single exit block.
+; Since it is a never executed loop, we do not care about the values
+; from different exiting paths and we can
+; delete the loop.
+define i64 @test3(i64 %n, i64 %m, i64 %maybe_zero) nounwind {
+
+; CHECK-NOT: bb:
+; CHECK-NOT: bb2:
+; CHECK-NOT: bb3:
+; CHECK-LABEL: return.loopexit:
+; CHECK-NEXT: %x.lcssa.ph = phi i64 [ undef, %bb.preheader ]
+; CHECK-NEXT: br label %return
+; CHECK-LABEL: return:
+; CHECK-NEXT: %x.lcssa = phi i64 [ 20, %entry ], [ %x.lcssa.ph, %return.loopexit ]
+; CHECK-NEXT: ret i64 %x.lcssa
+entry:
+ br i1 false, label %bb, label %return
+
+bb:
+ %x.0 = phi i64 [ 0, %entry ], [ %t0, %bb3 ]
+ %t0 = add i64 %x.0, 1
+ %t1 = icmp slt i64 %x.0, %n
+ br i1 %t1, label %bb2, label %return
+
+bb2:
+ %t2 = icmp slt i64 %x.0, %m
+ %unused1 = udiv i64 42, %maybe_zero
+ br i1 %t2, label %bb3, label %return
+
+bb3:
+ %t3 = icmp slt i64 %x.0, %m
+ %unused2 = sdiv i64 42, %maybe_zero
+ br i1 %t3, label %bb, label %return
+
+return:
+; the only valid value fo x.lcssa is 20.
+ %x.lcssa = phi i64 [ 12, %bb ], [ 14, %bb2 ], [ 16, %bb3 ], [20, %entry ]
+ ret i64 %x.lcssa
+}
+
+; Cannot delete the loop, since it may be executed at runtime.
+define void @test4(i64 %n, i64 %m, i1 %cond) {
+; CHECK-LABEL: test4
+; CHECK-LABEL: bb:
+entry:
+ br i1 %cond, label %looppred1, label %looppred2
+
+looppred1:
+ br i1 true, label %return, label %bb
+
+looppred2:
+ br i1 false, label %return, label %bb
+
+bb:
+ %x.0 = phi i64 [ 0, %looppred1 ], [ 1, %looppred2 ], [ %t0, %bb ]
+ %t0 = add i64 %x.0, 1
+ %t1 = icmp slt i64 %x.0, %n
+ %t3 = icmp sgt i64 %x.0, %m
+ %t4 = and i1 %t1, %t3
+ br i1 true, label %bb, label %return
+
+return:
+ ret void
+}
+
+; multiple constant conditional branches with loop not-taken in all cases.
+define void @test5(i64 %n, i64 %m, i1 %cond) nounwind {
+; CHECK-LABEL: test5
+; CHECK-LABEL: looppred1:
+; CHECK-NEXT: br i1 true, label %return, label %bb.preheader
+; CHECK-LABEL: looppred2:
+; CHECK-NEXT: br i1 true, label %return, label %bb.preheader
+; CHECK-NOT: bb:
+entry:
+ br i1 %cond, label %looppred1, label %looppred2
+
+looppred1:
+ br i1 true, label %return, label %bb
+
+looppred2:
+ br i1 true, label %return, label %bb
+
+bb:
+ %x.0 = phi i64 [ 0, %looppred1 ], [ 1, %looppred2 ], [ %t0, %bb ]
+ %t0 = add i64 %x.0, 1
+ %t1 = icmp slt i64 %x.0, %n
+ %t3 = icmp sgt i64 %x.0, %m
+ %t4 = and i1 %t1, %t3
+ br i1 true, label %bb, label %return
+
+return:
+ ret void
+}
+
+; Don't delete this infinite loop because the loop
+; is executable at runtime.
+define void @test6(i64 %n, i64 %m) nounwind {
+; CHECK-LABEL: test6
+; CHECK-LABEL: entry:
+; CHECK-NEXT: br i1 true, label %bb.preheader, label %bb.preheader
+; CHECK: bb:
+entry:
+ br i1 true, label %bb, label %bb
+
+bb:
+ %x.0 = phi i64 [ 0, %entry ], [ 0, %entry ], [ %t0, %bb ]
+ %t0 = add i64 %x.0, 1
+ %t1 = icmp slt i64 %x.0, %n
+ %t3 = icmp sgt i64 %x.0, %m
+ %t4 = and i1 %t1, %t3
+ br i1 true, label %bb, label %return
+
+return:
+ ret void
+}
+
+declare i64 @foo(i64)
+; The loop L2 is never executed and is a subloop, with an
+; exit block that branches back to parent loop.
+; Here we can delete loop L2, while L1 still exists.
+define i64 @test7(i64 %n) {
+; CHECK-LABEL: test7
+; CHECK-LABEL: L1:
+; CHECK: br i1 true, label %L1Latch, label %L2.preheader
+; CHECK-LABEL: L2.preheader:
+; CHECK-NEXT: br label %L1Latch.loopexit
+; CHECK-LABEL: L1Latch.loopexit:
+; CHECK: br label %L1Latch
+; CHECK-LABEL: L1Latch:
+; CHECK-NEXT: %y = phi i64 [ %y.next, %L1 ], [ %y.L2.lcssa, %L1Latch.loopexit ]
+; CHECK: br i1 %cond2, label %exit, label %L1
+entry:
+ br label %L1
+
+L1:
+ %y.next = phi i64 [ 0, %entry ], [ %y.add, %L1Latch ]
+ br i1 true, label %L1Latch, label %L2
+
+L2:
+ %x = phi i64 [ 0, %L1 ], [ %x.next, %L2 ]
+ %x.next = add i64 %x, 1
+ %y.L2 = call i64 @foo(i64 %x.next)
+ %cond = icmp slt i64 %x.next, %n
+ br i1 %cond, label %L2, label %L1Latch
+
+L1Latch:
+ %y = phi i64 [ %y.next, %L1 ], [ %y.L2, %L2 ]
+ %y.add = add i64 %y, %n
+ %cond2 = icmp eq i64 %y.add, 42
+ br i1 %cond2, label %exit, label %L1
+
+exit:
+ ret i64 %y.add
+}
+
+
+; Show recursive deletion of loops. Since we start with subloops and progress outward
+; to parent loop, we first delete the loop L2. Now loop L1 becomes a non-loop since it's backedge
+; from L2's preheader to L1's exit block is never taken. So, L1 gets deleted as well.
+define void @test8(i64 %n) {
+; CHECK-LABEL: test8
+; CHECK-LABEL: entry:
+; CHECK-NEXT: br label %exit
+; CHECK-LABEL: exit:
+; CHECK-NEXT: ret void
+entry:
+ br label %L1
+
+L1:
+ br i1 true, label %exit, label %L2
+
+L2:
+ %x = phi i64 [ 0, %L1 ], [ %x.next, %L2 ]
+ %x.next = add i64 %x, 1
+ %y.L2 = call i64 @foo(i64 %x.next)
+ %cond = icmp slt i64 %x.next, %n
+ br i1 %cond, label %L2, label %L1
+
+exit:
+ ret void
+}
+
+
+; Delete a loop (L2) which has subloop (L3).
+; Here we delete loop L2, but leave L3 as is.
+; FIXME: Can delete L3 as well, by iteratively going backward through the single
+; predecessor of L3 until we reach L1's block that guarantees L3 is never
+; executed.
+define void @test9(i64 %n) {
+; CHECK-LABEL: test9
+; CHECK-LABEL: L2.preheader:
+; CHECK-NEXT: br label %L3.preheader
+; CHECK-NOT: L2:
+; CHECK-LABEL: L3.preheader:
+; CHECK-NEXT: %y.L2.lcssa = phi i64 [ undef, %L2.preheader ]
+; CHECK-NEXT: br label %L3
+; CHECK-LABEL: L3:
+; CHECK: br i1 %cond2, label %L3, label %L1.loopexit
+entry:
+ br label %L1
+
+L1:
+ br i1 true, label %exit, label %L2
+
+L2:
+ %x = phi i64 [ 0, %L1 ], [ %x.next, %L2 ]
+ %x.next = add i64 %x, 1
+ %y.L2 = call i64 @foo(i64 %x.next)
+ %cond = icmp slt i64 %x.next, %n
+ br i1 %cond, label %L2, label %L3
+
+L3:
+ %cond2 = icmp slt i64 %y.L2, %n
+ br i1 %cond2, label %L3, label %L1
+
+exit:
+ ret void
+}
+
+; We cannot delete L3 because of call within it.
+; Since L3 is not deleted, and entirely contained within L2, L2 is also not
+; deleted.
+; FIXME: We can delete unexecutable loops having
+; subloops contained entirely within them.
+define void @test10(i64 %n) {
+; CHECK-LABEL: test10
+; CHECK: L2:
+; CHECK: L3:
+entry:
+ br label %L1
+
+L1:
+ br i1 true, label %exit, label %L2
+
+L2:
+ %x = phi i64 [ 0, %L1 ], [ %x.next, %L3 ]
+ %x.next = add i64 %x, 1
+ %y.L2 = call i64 @foo(i64 %x.next)
+ %cond = icmp slt i64 %x.next, %n
+ br i1 %cond, label %L1, label %L3
+
+L3:
+ %y.L3 = phi i64 [ %y.L2, %L2 ], [ %y.L3.next, %L3 ]
+ %y.L3.next = add i64 %y.L3, 1
+ %dummy = call i64 @foo(i64 %y.L3.next)
+ %cond2 = icmp slt i64 %y.L3, %n
+ br i1 %cond2, label %L3, label %L2
+
+exit:
+ ret void
+}
+
+; same as test10, but L3 does not contain call.
+; So, in the first iteration, all statements of L3 are made invariant, and L3 is
+; deleted.
+; In the next iteration, since L2 is never executed and has no subloops, we delete
+; L2 as well. Finally, the outermost loop L1 is deleted.
+define void @test11(i64 %n) {
+; CHECK-LABEL: test11
+; CHECK-LABEL: entry:
+; CHECK-NEXT: br label %exit
+; CHECK-LABEL: exit:
+; CHECK-NEXT: ret void
+entry:
+ br label %L1
+
+L1:
+ br i1 true, label %exit, label %L2
+
+L2:
+ %x = phi i64 [ 0, %L1 ], [ %x.next, %L3 ]
+ %x.next = add i64 %x, 1
+ %y.L2 = call i64 @foo(i64 %x.next)
+ %cond = icmp slt i64 %x.next, %n
+ br i1 %cond, label %L1, label %L3
+
+L3:
+ %y.L3 = phi i64 [ %y.L2, %L2 ], [ %y.L3.next, %L3 ]
+ %y.L3.next = add i64 %y.L3, 1
+ %cond2 = icmp slt i64 %y.L3, %n
+ br i1 %cond2, label %L3, label %L2
+
+exit:
+ ret void
+}
+
diff --git a/test/Transforms/LoopVectorize/X86/consecutive-ptr-uniforms.ll b/test/Transforms/LoopVectorize/X86/consecutive-ptr-uniforms.ll
index 82f2e064a581..e18159f24624 100644
--- a/test/Transforms/LoopVectorize/X86/consecutive-ptr-uniforms.ll
+++ b/test/Transforms/LoopVectorize/X86/consecutive-ptr-uniforms.ll
@@ -36,7 +36,7 @@ target triple = "x86_64-unknown-linux-gnu"
; CHECK-NEXT: [[WIDE_VEC1:%.*]] = load <80 x float>, <80 x float>* [[TMP4]], align 4
; CHECK-NEXT: [[STRIDED_VEC2:%.*]] = shufflevector <80 x float> [[WIDE_VEC1]], <80 x float> undef, <16 x i32> <i32 0, i32 5, i32 10, i32 15, i32 20, i32 25, i32 30, i32 35, i32 40, i32 45, i32 50, i32 55, i32 60, i32 65, i32 70, i32 75>
; CHECK-NEXT: [[TMP5:%.*]] = fadd <16 x float> [[STRIDED_VEC2]], [[TMP2]]
-; CHECK-NEXT: call void @llvm.masked.scatter.v16f32(<16 x float> [[TMP5]], <16 x float*> [[TMP3]], i32 4, <16 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>)
+; CHECK-NEXT: call void @llvm.masked.scatter.v16f32.v16p0f32(<16 x float> [[TMP5]], <16 x float*> [[TMP3]], i32 4, <16 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>)
; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 16
; CHECK-NEXT: [[VEC_IND_NEXT]] = add <16 x i64> [[VEC_IND]], <i64 80, i64 80, i64 80, i64 80, i64 80, i64 80, i64 80, i64 80, i64 80, i64 80, i64 80, i64 80, i64 80, i64 80, i64 80, i64 80>
; CHECK: br i1 {{.*}}, label %middle.block, label %vector.body
diff --git a/test/Transforms/LoopVectorize/X86/gather_scatter.ll b/test/Transforms/LoopVectorize/X86/gather_scatter.ll
index 2ce357540d0b..8ef59613e646 100644
--- a/test/Transforms/LoopVectorize/X86/gather_scatter.ll
+++ b/test/Transforms/LoopVectorize/X86/gather_scatter.ll
@@ -17,9 +17,9 @@ target triple = "x86_64-pc_linux"
;}
;AVX512-LABEL: @foo1
-;AVX512: llvm.masked.load.v16i32
-;AVX512: llvm.masked.gather.v16f32
-;AVX512: llvm.masked.store.v16f32
+;AVX512: llvm.masked.load.v16i32.p0v16i32
+;AVX512: llvm.masked.gather.v16f32.v16p0f32
+;AVX512: llvm.masked.store.v16f32.p0v16f32
;AVX512: ret void
; Function Attrs: nounwind uwtable
@@ -96,8 +96,8 @@ for.end: ; preds = %for.cond
;AVX512-LABEL: @foo2
;AVX512: getelementptr inbounds %struct.In, %struct.In* %in, <16 x i64> {{.*}}, i32 1
-;AVX512: llvm.masked.gather.v16f32
-;AVX512: llvm.masked.scatter.v16f32
+;AVX512: llvm.masked.gather.v16f32.v16p0f32
+;AVX512: llvm.masked.scatter.v16f32.v16p0f32
;AVX512: ret void
define void @foo2(%struct.In* noalias %in, float* noalias %out, i32* noalias %trigger, i32* noalias %index) #0 {
entry:
@@ -171,10 +171,10 @@ for.end: ; preds = %for.cond
;AVX512-LABEL: @foo3
;AVX512: getelementptr inbounds %struct.In, %struct.In* %in, <16 x i64> {{.*}}, i32 1
-;AVX512: llvm.masked.gather.v16f32
+;AVX512: llvm.masked.gather.v16f32.v16p0f32
;AVX512: fadd <16 x float>
;AVX512: getelementptr inbounds %struct.Out, %struct.Out* %out, <16 x i64> {{.*}}, i32 1
-;AVX512: llvm.masked.scatter.v16f32
+;AVX512: llvm.masked.scatter.v16f32.v16p0f32
;AVX512: ret void
%struct.Out = type { float, float }
@@ -233,4 +233,194 @@ for.inc: ; preds = %if.end
for.end: ; preds = %for.cond
ret void
}
-declare void @llvm.masked.scatter.v16f32(<16 x float>, <16 x float*>, i32, <16 x i1>)
+declare void @llvm.masked.scatter.v16f32.v16p0f32(<16 x float>, <16 x float*>, i32, <16 x i1>)
+
+; The same as @foo2 but scatter/gather argument is a vecotr of ptrs with addresspace 1
+
+;AVX512-LABEL: @foo2_addrspace
+;AVX512: getelementptr inbounds %struct.In, %struct.In addrspace(1)* %in, <16 x i64> {{.*}}, i32 1
+;AVX512: llvm.masked.gather.v16f32.v16p1f32
+;AVX512: llvm.masked.scatter.v16f32.v16p1f32
+;AVX512: ret void
+define void @foo2_addrspace(%struct.In addrspace(1)* noalias %in, float addrspace(1)* noalias %out, i32* noalias %trigger, i32* noalias %index) #0 {
+entry:
+ %in.addr = alloca %struct.In addrspace(1)*, align 8
+ %out.addr = alloca float addrspace(1)*, align 8
+ %trigger.addr = alloca i32*, align 8
+ %index.addr = alloca i32*, align 8
+ %i = alloca i32, align 4
+ store %struct.In addrspace(1)* %in, %struct.In addrspace(1)** %in.addr, align 8
+ store float addrspace(1)* %out, float addrspace(1)** %out.addr, align 8
+ store i32* %trigger, i32** %trigger.addr, align 8
+ store i32* %index, i32** %index.addr, align 8
+ store i32 0, i32* %i, align 4
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %0 = load i32, i32* %i, align 4
+ %cmp = icmp slt i32 %0, 4096
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %1 = load i32, i32* %i, align 4
+ %idxprom = sext i32 %1 to i64
+ %2 = load i32*, i32** %trigger.addr, align 8
+ %arrayidx = getelementptr inbounds i32, i32* %2, i64 %idxprom
+ %3 = load i32, i32* %arrayidx, align 4
+ %cmp1 = icmp sgt i32 %3, 0
+ br i1 %cmp1, label %if.then, label %if.end
+
+if.then: ; preds = %for.body
+ %4 = load i32, i32* %i, align 4
+ %idxprom2 = sext i32 %4 to i64
+ %5 = load %struct.In addrspace(1)*, %struct.In addrspace(1)** %in.addr, align 8
+ %arrayidx3 = getelementptr inbounds %struct.In, %struct.In addrspace(1)* %5, i64 %idxprom2
+ %b = getelementptr inbounds %struct.In, %struct.In addrspace(1)* %arrayidx3, i32 0, i32 1
+ %6 = load float, float addrspace(1)* %b, align 4
+ %add = fadd float %6, 5.000000e-01
+ %7 = load i32, i32* %i, align 4
+ %idxprom4 = sext i32 %7 to i64
+ %8 = load float addrspace(1)*, float addrspace(1)** %out.addr, align 8
+ %arrayidx5 = getelementptr inbounds float, float addrspace(1)* %8, i64 %idxprom4
+ store float %add, float addrspace(1)* %arrayidx5, align 4
+ br label %if.end
+
+if.end: ; preds = %if.then, %for.body
+ br label %for.inc
+
+for.inc: ; preds = %if.end
+ %9 = load i32, i32* %i, align 4
+ %inc = add nsw i32 %9, 16
+ store i32 %inc, i32* %i, align 4
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
+
+; Same as foo2_addrspace but here only the input has the non-default address space.
+
+;AVX512-LABEL: @foo2_addrspace2
+;AVX512: getelementptr inbounds %struct.In, %struct.In addrspace(1)* %in, <16 x i64> {{.*}}, i32 1
+;AVX512: llvm.masked.gather.v16f32.v16p1f32
+;AVX512: llvm.masked.scatter.v16f32.v16p0f32
+;AVX512: ret void
+define void @foo2_addrspace2(%struct.In addrspace(1)* noalias %in, float addrspace(0)* noalias %out, i32* noalias %trigger, i32* noalias %index) {
+entry:
+ %in.addr = alloca %struct.In addrspace(1)*, align 8
+ %out.addr = alloca float addrspace(0)*, align 8
+ %trigger.addr = alloca i32*, align 8
+ %index.addr = alloca i32*, align 8
+ %i = alloca i32, align 4
+ store %struct.In addrspace(1)* %in, %struct.In addrspace(1)** %in.addr, align 8
+ store float addrspace(0)* %out, float addrspace(0)** %out.addr, align 8
+ store i32* %trigger, i32** %trigger.addr, align 8
+ store i32* %index, i32** %index.addr, align 8
+ store i32 0, i32* %i, align 4
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %0 = load i32, i32* %i, align 4
+ %cmp = icmp slt i32 %0, 4096
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %1 = load i32, i32* %i, align 4
+ %idxprom = sext i32 %1 to i64
+ %2 = load i32*, i32** %trigger.addr, align 8
+ %arrayidx = getelementptr inbounds i32, i32* %2, i64 %idxprom
+ %3 = load i32, i32* %arrayidx, align 4
+ %cmp1 = icmp sgt i32 %3, 0
+ br i1 %cmp1, label %if.then, label %if.end
+
+if.then: ; preds = %for.body
+ %4 = load i32, i32* %i, align 4
+ %idxprom2 = sext i32 %4 to i64
+ %5 = load %struct.In addrspace(1)*, %struct.In addrspace(1)** %in.addr, align 8
+ %arrayidx3 = getelementptr inbounds %struct.In, %struct.In addrspace(1)* %5, i64 %idxprom2
+ %b = getelementptr inbounds %struct.In, %struct.In addrspace(1)* %arrayidx3, i32 0, i32 1
+ %6 = load float, float addrspace(1)* %b, align 4
+ %add = fadd float %6, 5.000000e-01
+ %7 = load i32, i32* %i, align 4
+ %idxprom4 = sext i32 %7 to i64
+ %8 = load float addrspace(0)*, float addrspace(0)** %out.addr, align 8
+ %arrayidx5 = getelementptr inbounds float, float addrspace(0)* %8, i64 %idxprom4
+ store float %add, float addrspace(0)* %arrayidx5, align 4
+ br label %if.end
+
+if.end: ; preds = %if.then, %for.body
+ br label %for.inc
+
+for.inc: ; preds = %if.end
+ %9 = load i32, i32* %i, align 4
+ %inc = add nsw i32 %9, 16
+ store i32 %inc, i32* %i, align 4
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
+
+; Same as foo2_addrspace but here only the output has the non-default address space.
+
+;AVX512-LABEL: @foo2_addrspace3
+;AVX512: getelementptr inbounds %struct.In, %struct.In* %in, <16 x i64> {{.*}}, i32 1
+;AVX512: llvm.masked.gather.v16f32.v16p0f32
+;AVX512: llvm.masked.scatter.v16f32.v16p1f32
+;AVX512: ret void
+
+define void @foo2_addrspace3(%struct.In addrspace(0)* noalias %in, float addrspace(1)* noalias %out, i32* noalias %trigger, i32* noalias %index) {
+entry:
+ %in.addr = alloca %struct.In addrspace(0)*, align 8
+ %out.addr = alloca float addrspace(1)*, align 8
+ %trigger.addr = alloca i32*, align 8
+ %index.addr = alloca i32*, align 8
+ %i = alloca i32, align 4
+ store %struct.In addrspace(0)* %in, %struct.In addrspace(0)** %in.addr, align 8
+ store float addrspace(1)* %out, float addrspace(1)** %out.addr, align 8
+ store i32* %trigger, i32** %trigger.addr, align 8
+ store i32* %index, i32** %index.addr, align 8
+ store i32 0, i32* %i, align 4
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %0 = load i32, i32* %i, align 4
+ %cmp = icmp slt i32 %0, 4096
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %1 = load i32, i32* %i, align 4
+ %idxprom = sext i32 %1 to i64
+ %2 = load i32*, i32** %trigger.addr, align 8
+ %arrayidx = getelementptr inbounds i32, i32* %2, i64 %idxprom
+ %3 = load i32, i32* %arrayidx, align 4
+ %cmp1 = icmp sgt i32 %3, 0
+ br i1 %cmp1, label %if.then, label %if.end
+
+if.then: ; preds = %for.body
+ %4 = load i32, i32* %i, align 4
+ %idxprom2 = sext i32 %4 to i64
+ %5 = load %struct.In addrspace(0)*, %struct.In addrspace(0)** %in.addr, align 8
+ %arrayidx3 = getelementptr inbounds %struct.In, %struct.In addrspace(0)* %5, i64 %idxprom2
+ %b = getelementptr inbounds %struct.In, %struct.In addrspace(0)* %arrayidx3, i32 0, i32 1
+ %6 = load float, float addrspace(0)* %b, align 4
+ %add = fadd float %6, 5.000000e-01
+ %7 = load i32, i32* %i, align 4
+ %idxprom4 = sext i32 %7 to i64
+ %8 = load float addrspace(1)*, float addrspace(1)** %out.addr, align 8
+ %arrayidx5 = getelementptr inbounds float, float addrspace(1)* %8, i64 %idxprom4
+ store float %add, float addrspace(1)* %arrayidx5, align 4
+ br label %if.end
+
+if.end: ; preds = %if.then, %for.body
+ br label %for.inc
+
+for.inc: ; preds = %if.end
+ %9 = load i32, i32* %i, align 4
+ %inc = add nsw i32 %9, 16
+ store i32 %inc, i32* %i, align 4
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
diff --git a/test/Transforms/LoopVectorize/X86/scatter_crash.ll b/test/Transforms/LoopVectorize/X86/scatter_crash.ll
index bda4b2454ee2..aff372b562fb 100755
--- a/test/Transforms/LoopVectorize/X86/scatter_crash.ll
+++ b/test/Transforms/LoopVectorize/X86/scatter_crash.ll
@@ -23,11 +23,11 @@ define void @_Z3fn1v() #0 {
; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [10 x [10 x i32]], [10 x [10 x i32]]* @d, i64 0, <16 x i64> [[VEC_IND]]
; CHECK-NEXT: [[TMP12:%.*]] = add nsw <16 x i64> [[TMP10]], [[VEC_IND3]]
; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds [10 x i32], <16 x [10 x i32]*> [[TMP11]], <16 x i64> [[TMP12]], i64 0
-; CHECK-NEXT: call void @llvm.masked.scatter.v16i32(<16 x i32> <i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8>, <16 x i32*> [[TMP13]], i32 16, <16 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>)
+; CHECK-NEXT: call void @llvm.masked.scatter.v16i32.v16p0i32(<16 x i32> <i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8>, <16 x i32*> [[TMP13]], i32 16, <16 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>)
; CHECK-NEXT: [[TMP14:%.*]] = or <16 x i64> [[VEC_IND3]], <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1>
; CHECK-NEXT: [[TMP15:%.*]] = add nsw <16 x i64> [[TMP10]], [[TMP14]]
; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds [10 x i32], <16 x [10 x i32]*> [[TMP11]], <16 x i64> [[TMP15]], i64 0
-; CHECK-NEXT: call void @llvm.masked.scatter.v16i32(<16 x i32> <i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8>, <16 x i32*> [[TMP16]], i32 8, <16 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>)
+; CHECK-NEXT: call void @llvm.masked.scatter.v16i32.v16p0i32(<16 x i32> <i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8>, <16 x i32*> [[TMP16]], i32 8, <16 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>)
; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 16
; CHECK-NEXT: [[VEC_IND_NEXT]] = add <16 x i64> [[VEC_IND]], <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
; CHECK-NEXT: [[VEC_IND_NEXT4]] = add <16 x i64> [[VEC_IND3]], <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
diff --git a/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather.ll b/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather.ll
index a3511c3ae968..b3087c1577ca 100644
--- a/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather.ll
+++ b/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather.ll
@@ -1,8 +1,8 @@
; XFAIL: *
; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
-declare void @llvm.masked.scatter.v2i32(<2 x i32> , <2 x i32*> , i32 , <2 x i1> )
-declare <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*>, i32, <2 x i1>, <2 x i32>)
+declare void @llvm.masked.scatter.v2i32.v2p0i32(<2 x i32> , <2 x i32*> , i32 , <2 x i1> )
+declare <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*>, i32, <2 x i1>, <2 x i32>)
; This test ensures that masked scatter and gather operations, which take vectors of pointers,
; do not have pointer aliasing ignored when being processed.
@@ -21,18 +21,18 @@ entry:
%tmp.i = insertelement <2 x i32*> undef, i32* %tmp.0, i32 0
%tmp = insertelement <2 x i32*> %tmp.i, i32* %tmp.1, i32 1
; Read from in1 and in2
- %in1.v = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %in1, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
- %in2.v = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %in2, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
+ %in1.v = call <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*> %in1, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
+ %in2.v = call <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*> %in2, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
; Store in1 to the allocas
- call void @llvm.masked.scatter.v2i32(<2 x i32> %in1.v, <2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>);
+ call void @llvm.masked.scatter.v2i32.v2p0i32(<2 x i32> %in1.v, <2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>);
; Read in1 from the allocas
; This gather should alias the scatter we just saw
- %tmp.v.0 = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
+ %tmp.v.0 = call <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
; Store in2 to the allocas
- call void @llvm.masked.scatter.v2i32(<2 x i32> %in2.v, <2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>);
+ call void @llvm.masked.scatter.v2i32.v2p0i32(<2 x i32> %in2.v, <2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>);
; Read in2 from the allocas
; This gather should alias the scatter we just saw, and not be eliminated
- %tmp.v.1 = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
+ %tmp.v.1 = call <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
; Store in2 to out for good measure
%tmp.v.1.0 = extractelement <2 x i32> %tmp.v.1, i32 0
%tmp.v.1.1 = extractelement <2 x i32> %tmp.v.1, i32 1
diff --git a/test/Transforms/ObjCARC/basic.ll b/test/Transforms/ObjCARC/basic.ll
index c10c3b1381b7..ad44f9d6fd39 100644
--- a/test/Transforms/ObjCARC/basic.ll
+++ b/test/Transforms/ObjCARC/basic.ll
@@ -3049,6 +3049,6 @@ define void @test67(i8* %x) {
!4 = !DIFile(filename: "path/to/file", directory: "/path/to/dir")
!5 = !{i32 2, !"Debug Info Version", i32 3}
-; CHECK: attributes #0 = { nounwind readnone }
+; CHECK: attributes #0 = { nounwind readnone speculatable }
; CHECK: attributes [[NUW]] = { nounwind }
; CHECK: ![[RELEASE]] = !{}
diff --git a/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll b/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll
index c856706d3f03..93a12a927d89 100644
--- a/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll
+++ b/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll
@@ -105,7 +105,7 @@ declare void @NSLog(i8*, ...)
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone
; CHECK: attributes #0 = { ssp uwtable }
-; CHECK: attributes #1 = { nounwind readnone }
+; CHECK: attributes #1 = { nounwind readnone speculatable }
; CHECK: attributes #2 = { nonlazybind }
; CHECK: attributes #3 = { noinline ssp uwtable }
; CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/Transforms/SLPVectorizer/X86/call.ll b/test/Transforms/SLPVectorizer/X86/call.ll
index 923cbe74a567..03b1e837a0ca 100644
--- a/test/Transforms/SLPVectorizer/X86/call.ll
+++ b/test/Transforms/SLPVectorizer/X86/call.ll
@@ -147,5 +147,5 @@ entry:
; CHECK: declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>) [[ATTR0]]
; CHECK: declare <2 x double> @llvm.exp2.v2f64(<2 x double>) [[ATTR0]]
-; CHECK: attributes [[ATTR0]] = { nounwind readnone }
+; CHECK: attributes [[ATTR0]] = { nounwind readnone speculatable }
diff --git a/test/Transforms/SpeculativeExecution/spec-other.ll b/test/Transforms/SpeculativeExecution/spec-other.ll
new file mode 100644
index 000000000000..65e14b69e9e6
--- /dev/null
+++ b/test/Transforms/SpeculativeExecution/spec-other.ll
@@ -0,0 +1,32 @@
+; RUN: opt < %s -S -speculative-execution \
+; RUN: -spec-exec-max-speculation-cost 4 -spec-exec-max-not-hoisted 3 \
+; RUN: | FileCheck %s
+
+; CHECK-LABEL: @ifThen_extractvalue(
+; CHECK: extractvalue
+; CHECK: br i1 true
+define void @ifThen_extractvalue() {
+ br i1 true, label %a, label %b
+
+a:
+ %x = extractvalue { i32, i32 } undef, 0
+ br label %b
+
+b:
+ ret void
+}
+
+; CHECK-LABEL: @ifThen_insertvalue(
+; CHECK: insertvalue
+; CHECK: br i1 true
+define void @ifThen_insertvalue() {
+ br i1 true, label %a, label %b
+
+a:
+ %x = insertvalue { i32, i32 } undef, i32 undef, 0
+ br label %b
+
+b:
+ ret void
+}
+
diff --git a/test/Transforms/SpeculativeExecution/spec-vector.ll b/test/Transforms/SpeculativeExecution/spec-vector.ll
new file mode 100644
index 000000000000..9c64f1fb1005
--- /dev/null
+++ b/test/Transforms/SpeculativeExecution/spec-vector.ll
@@ -0,0 +1,73 @@
+; RUN: opt < %s -S -speculative-execution \
+; RUN: -spec-exec-max-speculation-cost 4 -spec-exec-max-not-hoisted 3 \
+; RUN: | FileCheck %s
+
+; CHECK-LABEL: @ifThen_extractelement_constindex(
+; CHECK: extractelement
+; CHECK: br i1 true
+define void @ifThen_extractelement_constindex() {
+ br i1 true, label %a, label %b
+
+a:
+ %x = extractelement <4 x i32> undef, i32 0
+ br label %b
+
+b:
+ ret void
+}
+
+; CHECK-LABEL: @ifThen_extractelement_varindex(
+; CHECK: extractelement
+; CHECK: br i1 true
+define void @ifThen_extractelement_varindex(i32 %idx) {
+ br i1 true, label %a, label %b
+
+a:
+ %x = extractelement <4 x i32> undef, i32 %idx
+ br label %b
+
+b:
+ ret void
+}
+
+; CHECK-LABEL: @ifThen_insertelement_constindex(
+; CHECK: insertelement
+; CHECK: br i1 true
+define void @ifThen_insertelement_constindex() {
+ br i1 true, label %a, label %b
+
+a:
+ %x = insertelement <4 x i32> undef, i32 undef, i32 0
+ br label %b
+
+b:
+ ret void
+}
+
+; CHECK-LABEL: @ifThen_insertelement_varindex(
+; CHECK: insertelement
+; CHECK: br i1 true
+define void @ifThen_insertelement_varindex(i32 %idx) {
+ br i1 true, label %a, label %b
+
+a:
+ %x = insertelement <4 x i32> undef, i32 undef, i32 %idx
+ br label %b
+
+b:
+ ret void
+}
+
+; CHECK-LABEL: @ifThen_shufflevector(
+; CHECK: shufflevector
+; CHECK: br i1 true
+define void @ifThen_shufflevector() {
+ br i1 true, label %a, label %b
+
+a:
+ %x = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32> undef
+ br label %b
+
+b:
+ ret void
+}