diff options
Diffstat (limited to 'test/Analysis')
124 files changed, 6936 insertions, 1425 deletions
diff --git a/test/Analysis/BasicAA/2007-11-05-SizeCrash.ll b/test/Analysis/BasicAA/2007-11-05-SizeCrash.ll index 069bd0bcfd8f..b59ee42dec3a 100644 --- a/test/Analysis/BasicAA/2007-11-05-SizeCrash.ll +++ b/test/Analysis/BasicAA/2007-11-05-SizeCrash.ll @@ -9,7 +9,7 @@ target triple = "x86_64-unknown-linux-gnu" %struct.usb_hcd = type { %struct.usb_bus, i64, [0 x i64] } @uhci_pci_ids = constant [1 x %struct.pci_device_id] zeroinitializer -@__mod_pci_device_table = alias [1 x %struct.pci_device_id]* @uhci_pci_ids +@__mod_pci_device_table = alias [1 x %struct.pci_device_id], [1 x %struct.pci_device_id]* @uhci_pci_ids ; <[1 x %struct.pci_device_id]*> [#uses=0] define i32 @uhci_suspend(%struct.usb_hcd* %hcd) { diff --git a/test/Analysis/BasicAA/2007-12-08-OutOfBoundsCrash.ll b/test/Analysis/BasicAA/2007-12-08-OutOfBoundsCrash.ll index 20be13d153bb..ba9740028180 100644 --- a/test/Analysis/BasicAA/2007-12-08-OutOfBoundsCrash.ll +++ b/test/Analysis/BasicAA/2007-12-08-OutOfBoundsCrash.ll @@ -9,7 +9,7 @@ target triple = "x86_64-unknown-linux-gnu" %struct.usb_hcd = type { %struct.usb_bus, [0 x i64] } @pci_ids = constant [1 x %struct.pci_device_id] zeroinitializer -@__mod_pci_device_table = alias [1 x %struct.pci_device_id]* @pci_ids ; <[1 x %struct.pci_device_id]*> [#uses=0] +@__mod_pci_device_table = alias [1 x %struct.pci_device_id], [1 x %struct.pci_device_id]* @pci_ids ; <[1 x %struct.pci_device_id]*> [#uses=0] define i32 @ehci_pci_setup(%struct.usb_hcd* %hcd) { entry: diff --git a/test/Analysis/BasicAA/bug.23540.ll b/test/Analysis/BasicAA/bug.23540.ll new file mode 100644 index 000000000000..f693bcf73cd6 --- /dev/null +++ b/test/Analysis/BasicAA/bug.23540.ll @@ -0,0 +1,17 @@ +; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@c = external global i32 + +; CHECK-LABEL: f +; CHECK: PartialAlias: i32* %arrayidx, i32* %arrayidx6 +define void @f() { + %idxprom = zext i32 undef to i64 + %add4 = add i32 0, 1 + %idxprom5 = zext i32 %add4 to i64 + %arrayidx6 = getelementptr inbounds i32, i32* @c, i64 %idxprom5 + %arrayidx = getelementptr inbounds i32, i32* @c, i64 %idxprom + ret void +} + diff --git a/test/Analysis/BasicAA/bug.23626.ll b/test/Analysis/BasicAA/bug.23626.ll new file mode 100644 index 000000000000..6a1478c65cef --- /dev/null +++ b/test/Analysis/BasicAA/bug.23626.ll @@ -0,0 +1,31 @@ +; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-darwin13.4.0" + +; CHECK-LABEL: compute1 +; CHECK: PartialAlias: i32* %arrayidx8, i32* %out +; CHECK: PartialAlias: i32* %arrayidx11, i32* %out +; CHECK: PartialAlias: i32* %arrayidx11, i32* %arrayidx8 +; CHECK: PartialAlias: i32* %arrayidx14, i32* %out +; CHECK: PartialAlias: i32* %arrayidx14, i32* %arrayidx8 +; CHECK: PartialAlias: i32* %arrayidx11, i32* %arrayidx14 +define void @compute1(i32 %num.0.lcssa, i32* %out) { + %idxprom = zext i32 %num.0.lcssa to i64 + %arrayidx8 = getelementptr inbounds i32, i32* %out, i64 %idxprom + %add9 = or i32 %num.0.lcssa, 1 + %idxprom10 = zext i32 %add9 to i64 + %arrayidx11 = getelementptr inbounds i32, i32* %out, i64 %idxprom10 + %add12 = or i32 %num.0.lcssa, 2 + %idxprom13 = zext i32 %add12 to i64 + %arrayidx14 = getelementptr inbounds i32, i32* %out, i64 %idxprom13 + ret void +} + +; CHECK-LABEL: compute2 +; CHECK: PartialAlias: i32* %arrayidx11, i32* %out.addr +define void @compute2(i32 %num, i32* %out.addr) { + %add9 = add i32 %num, 1 + %idxprom10 = zext i32 %add9 to i64 + %arrayidx11 = getelementptr inbounds i32, i32* %out.addr, i64 %idxprom10 + ret void +} diff --git a/test/Analysis/BasicAA/cs-cs.ll b/test/Analysis/BasicAA/cs-cs.ll index 78670b61ca1c..dc298f1668be 100644 --- a/test/Analysis/BasicAA/cs-cs.ll +++ b/test/Analysis/BasicAA/cs-cs.ll @@ -2,8 +2,8 @@ target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32" target triple = "arm-apple-ios" -declare <8 x i16> @llvm.arm.neon.vld1.v8i16(i8*, i32) nounwind readonly -declare void @llvm.arm.neon.vst1.v8i16(i8*, <8 x i16>, i32) nounwind +declare <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8*, i32) nounwind readonly +declare void @llvm.arm.neon.vst1.p0i8.v8i16(i8*, <8 x i16>, i32) nounwind declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind @@ -13,27 +13,27 @@ declare void @a_readonly_func(i8 *) noinline nounwind readonly define <8 x i16> @test1(i8* %p, <8 x i16> %y) { entry: %q = getelementptr i8, i8* %p, i64 16 - %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) nounwind - call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) - %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) nounwind + %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) nounwind + call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) + %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) nounwind %c = add <8 x i16> %a, %b ret <8 x i16> %c ; CHECK-LABEL: Function: test1: ; CHECK: NoAlias: i8* %p, i8* %q -; CHECK: Just Ref: Ptr: i8* %p <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 -; CHECK: NoModRef: Ptr: i8* %q <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 -; CHECK: NoModRef: Ptr: i8* %p <-> call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) -; CHECK: Both ModRef: Ptr: i8* %q <-> call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) -; CHECK: Just Ref: Ptr: i8* %p <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 -; CHECK: NoModRef: Ptr: i8* %q <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 -; CHECK: NoModRef: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 <-> call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) -; CHECK: NoModRef: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 -; CHECK: NoModRef: call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 -; CHECK: NoModRef: call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 -; CHECK: NoModRef: %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 -; CHECK: NoModRef: %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 <-> call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) +; CHECK: Just Ref: Ptr: i8* %p <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 +; CHECK: NoModRef: Ptr: i8* %q <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 +; CHECK: NoModRef: Ptr: i8* %p <-> call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) +; CHECK: Both ModRef: Ptr: i8* %q <-> call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) +; CHECK: Just Ref: Ptr: i8* %p <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 +; CHECK: NoModRef: Ptr: i8* %q <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 +; CHECK: NoModRef: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 <-> call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) +; CHECK: NoModRef: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 +; CHECK: NoModRef: call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 +; CHECK: NoModRef: call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 +; CHECK: NoModRef: %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 +; CHECK: NoModRef: %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 <-> call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) } define void @test2(i8* %P, i8* %Q) nounwind ssp { @@ -233,4 +233,9 @@ define void @test6(i8* %P) nounwind ssp { ; CHECK: Just Ref: call void @a_readonly_func(i8* %P) <-> call void @llvm.memset.p0i8.i64(i8* %P, i8 -51, i64 32, i32 8, i1 false) } -attributes #0 = { nounwind } +attributes #0 = { nounwind readonly argmemonly } +attributes #1 = { nounwind argmemonly } +attributes #2 = { noinline nounwind readonly } +attributes #3 = { nounwind ssp } +attributes #4 = { nounwind } + diff --git a/test/Analysis/BasicAA/full-store-partial-alias.ll b/test/Analysis/BasicAA/full-store-partial-alias.ll index 341f6ba23b3a..20f6f7ec4ad0 100644 --- a/test/Analysis/BasicAA/full-store-partial-alias.ll +++ b/test/Analysis/BasicAA/full-store-partial-alias.ll @@ -1,5 +1,5 @@ -; RUN: opt -S -tbaa -basicaa -gvn < %s | FileCheck -check-prefix=BASICAA %s -; RUN: opt -S -tbaa -gvn < %s | FileCheck %s +; RUN: opt -S -tbaa -gvn < %s | FileCheck -check-prefix=BASICAA %s +; RUN: opt -S -tbaa -disable-basicaa -gvn < %s | FileCheck %s ; rdar://8875631, rdar://8875069 ; BasicAA should notice that the store stores to the entire %u object, diff --git a/test/Analysis/BasicAA/intrinsics.ll b/test/Analysis/BasicAA/intrinsics.ll index 8c05587ce233..526a039ef7ac 100644 --- a/test/Analysis/BasicAA/intrinsics.ll +++ b/test/Analysis/BasicAA/intrinsics.ll @@ -7,14 +7,14 @@ target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32- ; CHECK: define <8 x i16> @test0(i8* noalias %p, i8* noalias %q, <8 x i16> %y) { ; CHECK-NEXT: entry: -; CHECK-NEXT: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) [[ATTR:#[0-9]+]] -; CHECK-NEXT: call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) +; CHECK-NEXT: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) [[ATTR:#[0-9]+]] +; CHECK-NEXT: call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) ; CHECK-NEXT: %c = add <8 x i16> %a, %a define <8 x i16> @test0(i8* noalias %p, i8* noalias %q, <8 x i16> %y) { entry: - %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) nounwind - call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) - %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) nounwind + %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) nounwind + call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) + %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) nounwind %c = add <8 x i16> %a, %b ret <8 x i16> %c } @@ -22,21 +22,22 @@ entry: ; CHECK: define <8 x i16> @test1(i8* %p, <8 x i16> %y) { ; CHECK-NEXT: entry: ; CHECK-NEXT: %q = getelementptr i8, i8* %p, i64 16 -; CHECK-NEXT: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) [[ATTR]] -; CHECK-NEXT: call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) +; CHECK-NEXT: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) [[ATTR]] +; CHECK-NEXT: call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) ; CHECK-NEXT: %c = add <8 x i16> %a, %a define <8 x i16> @test1(i8* %p, <8 x i16> %y) { entry: %q = getelementptr i8, i8* %p, i64 16 - %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) nounwind - call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) - %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) nounwind + %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) nounwind + call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) + %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) nounwind %c = add <8 x i16> %a, %b ret <8 x i16> %c } -declare <8 x i16> @llvm.arm.neon.vld1.v8i16(i8*, i32) nounwind readonly -declare void @llvm.arm.neon.vst1.v8i16(i8*, <8 x i16>, i32) nounwind +declare <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8*, i32) nounwind readonly +declare void @llvm.arm.neon.vst1.p0i8.v8i16(i8*, <8 x i16>, i32) nounwind -; CHECK: attributes #0 = { nounwind readonly } +; CHECK: attributes #0 = { argmemonly nounwind readonly } +; CHECK: attributes #1 = { argmemonly nounwind } ; CHECK: attributes [[ATTR]] = { nounwind } diff --git a/test/Analysis/BasicAA/modref.ll b/test/Analysis/BasicAA/modref.ll index 3084f809c370..e42793936c3d 100644 --- a/test/Analysis/BasicAA/modref.ll +++ b/test/Analysis/BasicAA/modref.ll @@ -190,6 +190,43 @@ define i32 @test10(i32* %P, i32* %P2) { ; CHECK: ret i32 %Diff } +; CHECK-LABEL: @test11( +define i32 @test11(i32* %P, i32* %P2) { + %V1 = load i32, i32* %P + call i32 @func_argmemonly(i32* readonly %P2) + %V2 = load i32, i32* %P + %Diff = sub i32 %V1, %V2 + ret i32 %Diff + ; CHECK-NOT: load + ; CHECK: ret i32 0 +} + +declare i32 @func_argmemonly_two_args(i32* %P, i32* %P2) argmemonly + +; CHECK-LABEL: @test12( +define i32 @test12(i32* %P, i32* %P2, i32* %P3) { + %V1 = load i32, i32* %P + call i32 @func_argmemonly_two_args(i32* readonly %P2, i32* %P3) + %V2 = load i32, i32* %P + %Diff = sub i32 %V1, %V2 + ret i32 %Diff + ; CHECK: load + ; CHECK: load + ; CHECK: sub + ; CHECK: ret i32 %Diff +} + +; CHECK-LABEL: @test13( +define i32 @test13(i32* %P, i32* %P2) { + %V1 = load i32, i32* %P + call i32 @func_argmemonly(i32* readnone %P2) + %V2 = load i32, i32* %P + %Diff = sub i32 %V1, %V2 + ret i32 %Diff + ; CHECK-NOT: load + ; CHECK: ret i32 0 +} + declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) nounwind declare void @llvm.memset.p0i8.i8(i8* nocapture, i8, i8, i32, i1) nounwind declare void @llvm.memcpy.p0i8.p0i8.i8(i8* nocapture, i8* nocapture, i8, i32, i1) nounwind diff --git a/test/Analysis/BasicAA/noalias-bugs.ll b/test/Analysis/BasicAA/noalias-bugs.ll index acb230c45de4..71b3c443f542 100644 --- a/test/Analysis/BasicAA/noalias-bugs.ll +++ b/test/Analysis/BasicAA/noalias-bugs.ll @@ -24,7 +24,7 @@ define i64 @testcase(%nested * noalias %p1, %nested * noalias %p2, ; CHECK: store i64 2 ; CHECK: load -; CHECK; store i64 1 +; CHECK: store i64 1 store i64 2, i64* %ptr.64, align 8 %r = load i64, i64* %either_ptr.64, align 8 diff --git a/test/Analysis/BasicAA/phi-aa.ll b/test/Analysis/BasicAA/phi-aa.ll index a72778277bb2..3944e9e43566 100644 --- a/test/Analysis/BasicAA/phi-aa.ll +++ b/test/Analysis/BasicAA/phi-aa.ll @@ -39,6 +39,7 @@ return: ; CHECK-LABEL: pr18068 ; CHECK: MayAlias: i32* %0, i32* %arrayidx5 +; CHECK: NoAlias: i32* %arrayidx13, i32* %arrayidx5 define i32 @pr18068(i32* %jj7, i32* %j) { entry: diff --git a/test/Analysis/BasicAA/phi-loop.ll b/test/Analysis/BasicAA/phi-loop.ll new file mode 100644 index 000000000000..6337bfbc1cfb --- /dev/null +++ b/test/Analysis/BasicAA/phi-loop.ll @@ -0,0 +1,75 @@ +; RUN: opt < %s -basicaa -basicaa-recphi=1 -gvn -S | FileCheck %s +; +; Check that section->word_ofs doesn't get reloaded in every iteration of the +; for loop. +; +; Code: +; +; typedef struct { +; unsigned num_words; +; unsigned word_ofs; +; const unsigned *data; +; } section_t; +; +; +; void test2(const section_t * restrict section, unsigned * restrict dst) {; +; while (section->data != NULL) { +; const unsigned *src = section->data; +; for (unsigned i=0; i < section->num_words; ++i) { +; dst[section->word_ofs + i] = src[i]; +; } +; +; ++section; +; } +; } +; + +; CHECK-LABEL: for.body: +; CHECK-NOT: load i32, i32* %word_ofs + +%struct.section_t = type { i32, i32, i32* } + +define void @test2(%struct.section_t* noalias nocapture readonly %section, i32* noalias nocapture %dst) { +entry: + %data13 = getelementptr inbounds %struct.section_t, %struct.section_t* %section, i32 0, i32 2 + %0 = load i32*, i32** %data13, align 4 + %cmp14 = icmp eq i32* %0, null + br i1 %cmp14, label %while.end, label %for.cond.preheader + +for.cond.preheader: ; preds = %entry, %for.end + %1 = phi i32* [ %6, %for.end ], [ %0, %entry ] + %section.addr.015 = phi %struct.section_t* [ %incdec.ptr, %for.end ], [ %section, %entry ] + %num_words = getelementptr inbounds %struct.section_t, %struct.section_t* %section.addr.015, i32 0, i32 0 + %2 = load i32, i32* %num_words, align 4 + %cmp211 = icmp eq i32 %2, 0 + br i1 %cmp211, label %for.end, label %for.body.lr.ph + +for.body.lr.ph: ; preds = %for.cond.preheader + %word_ofs = getelementptr inbounds %struct.section_t, %struct.section_t* %section.addr.015, i32 0, i32 1 + br label %for.body + +for.body: ; preds = %for.body.lr.ph, %for.body + %arrayidx.phi = phi i32* [ %1, %for.body.lr.ph ], [ %arrayidx.inc, %for.body ] + %i.012 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ] + %3 = load i32, i32* %arrayidx.phi, align 4 + %4 = load i32, i32* %word_ofs, align 4 + %add = add i32 %4, %i.012 + %arrayidx3 = getelementptr inbounds i32, i32* %dst, i32 %add + store i32 %3, i32* %arrayidx3, align 4 + %inc = add i32 %i.012, 1 + %5 = load i32, i32* %num_words, align 4 + %cmp2 = icmp ult i32 %inc, %5 + %arrayidx.inc = getelementptr i32, i32* %arrayidx.phi, i32 1 + br i1 %cmp2, label %for.body, label %for.end + +for.end: ; preds = %for.body, %for.cond.preheader + %incdec.ptr = getelementptr inbounds %struct.section_t, %struct.section_t* %section.addr.015, i32 1 + %data = getelementptr inbounds %struct.section_t, %struct.section_t* %section.addr.015, i32 1, i32 2 + %6 = load i32*, i32** %data, align 4 + %cmp = icmp eq i32* %6, null + br i1 %cmp, label %while.end, label %for.cond.preheader + +while.end: ; preds = %for.end, %entry + ret void +} + diff --git a/test/Analysis/BasicAA/q.bad.ll b/test/Analysis/BasicAA/q.bad.ll new file mode 100644 index 000000000000..f2de6a76c5e0 --- /dev/null +++ b/test/Analysis/BasicAA/q.bad.ll @@ -0,0 +1,180 @@ +; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" +target triple = "thumbv7--linux-gnueabi" + +; CHECK-LABEL: test_zext_sext_amounts255 +; CHECK: NoAlias: i8* %a, i8* %b +define void @test_zext_sext_amounts255(i8* %mem) { + %sext.1 = sext i8 255 to i16 + %sext.zext.1 = zext i16 %sext.1 to i64 + %sext.2 = sext i8 255 to i32 + %sext.zext.2 = zext i32 %sext.2 to i64 + %a = getelementptr inbounds i8, i8* %mem, i64 %sext.zext.1 + %b = getelementptr inbounds i8, i8* %mem, i64 %sext.zext.2 + ret void +} + +; CHECK-LABEL: test_zext_sext_amounts +; CHECK: PartialAlias: i8* %a, i8* %b +; %a and %b only PartialAlias as, although they're both zext(sext(%num)) they'll extend the sign by a different +; number of bits before zext-ing the remainder. +define void @test_zext_sext_amounts(i8* %mem, i8 %num) { + %sext.1 = sext i8 %num to i16 + %sext.zext.1 = zext i16 %sext.1 to i64 + %sext.2 = sext i8 %num to i32 + %sext.zext.2 = zext i32 %sext.2 to i64 + %a = getelementptr inbounds i8, i8* %mem, i64 %sext.zext.1 + %b = getelementptr inbounds i8, i8* %mem, i64 %sext.zext.2 + ret void +} + +; CHECK-LABEL: based_on_pr18068 +; CHECK: NoAlias: i8* %a, i8* %b +; CHECK: NoAlias: i8* %a, i8* %c +define void @based_on_pr18068(i32 %loaded, i8* %mem) { + %loaded.64 = zext i32 %loaded to i64 + %add1 = add i32 %loaded, -1 ; unsigned wraps unless %loaded == 0 + %add1.64 = zext i32 %add1 to i64 ; is zext(%loaded) always != zext(%loaded - 1)? Yes -> NoAlias + %sub1 = sub i32 %loaded, 1 ; unsigned wraps iff %loaded == 0 + %sub1.64 = zext i32 %sub1 to i64 ; is zext(%loaded) always != zext(%loaded - 1)? Yes -> NoAlias + %a = getelementptr inbounds i8, i8* %mem, i64 %loaded.64 + %b = getelementptr inbounds i8, i8* %mem, i64 %add1.64 + %c = getelementptr inbounds i8, i8* %mem, i64 %sub1.64 + ret void +} + +; CHECK-LABEL: test_path_dependence +; CHECK: PartialAlias: i8* %a, i8* %b +; CHECK: MustAlias: i8* %a, i8* %c +; CHECK: PartialAlias: i8* %a, i8* %d +define void @test_path_dependence(i32 %p, i8* %mem) { + %p.minus1 = add i32 %p, -1 ; this will always unsigned-wrap, unless %p == 0 + %p.minus1.64 = zext i32 %p.minus1 to i64 + %p.64.again = add i64 %p.minus1.64, 1 ; either %p (if we wrapped) or 4294967296 (if we didn't) + + %p.nsw.nuw.minus1 = sub nsw nuw i32 %p, 1 ; as nuw we know %p >= 1, and as nsw %p <= 2147483647 + %p.nsw.nuw.minus1.64 = zext i32 %p.nsw.nuw.minus1 to i64 + %p.nsw.nuw.64.again = add nsw nuw i64 %p.nsw.nuw.minus1.64, 1 ; ...so always exactly %p + + %p.nsw.minus1 = sub nsw i32 %p, 1 ; only nsw, so can only guarantee %p != 0x10000000 + %p.nsw.minus1.64 = zext i32 %p.nsw.minus1 to i64 ; when %p > 0x10000000 (ie <= 0 as a signed number) then the zext will make this a huge positive number + %p.nsw.64.again = add nsw i64 %p.nsw.minus1.64, 1 ; ...and so this is very much != %p + + %p.64 = zext i32 %p to i64 + %a = getelementptr inbounds i8, i8* %mem, i64 %p.64 + %b = getelementptr inbounds i8, i8* %mem, i64 %p.64.again + %c = getelementptr inbounds i8, i8* %mem, i64 %p.nsw.nuw.64.again + %d = getelementptr inbounds i8, i8* %mem, i64 %p.nsw.64.again + ret void +} + +; CHECK-LABEL: test_zext_sext_255 +; CHECK: NoAlias: i8* %a, i8* %b +define void @test_zext_sext_255(i8* %mem) { + %zext.255 = zext i8 255 to i16 ; 0x00FF + %sext.255 = sext i8 255 to i16 ; 0xFFFF + %zext.sext.255 = zext i16 %sext.255 to i32 ; 0x0000FFFF + %sext.zext.255 = sext i16 %zext.255 to i32 ; 0x000000FF + %zext.zext.sext.255 = zext i32 %zext.sext.255 to i64 + %zext.sext.zext.255 = zext i32 %sext.zext.255 to i64 + %a = getelementptr inbounds i8, i8* %mem, i64 %zext.zext.sext.255 + %b = getelementptr inbounds i8, i8* %mem, i64 %zext.sext.zext.255 + ret void +} + +; CHECK-LABEL: test_zext_sext_num +; CHECK: PartialAlias: i8* %a, i8* %b +; %a and %b NoAlias if %num == 255 (see @test_zext_sext_255), but %a and %b NoAlias for other values of %num (e.g. 0) +define void @test_zext_sext_num(i8* %mem, i8 %num) { + %zext.num = zext i8 %num to i16 + %sext.num = sext i8 %num to i16 + %zext.sext.num = zext i16 %sext.num to i32 + %sext.zext.num = sext i16 %zext.num to i32 + %zext.zext.sext.num = zext i32 %zext.sext.num to i64 + %zext.sext.zext.num = zext i32 %sext.zext.num to i64 + %a = getelementptr inbounds i8, i8* %mem, i64 %zext.zext.sext.num + %b = getelementptr inbounds i8, i8* %mem, i64 %zext.sext.zext.num + ret void +} + +; CHECK-LABEL: uncompressStream +; CHECK: MustAlias: i8* %a, i8* %b +; CHECK: NoAlias: i8* %a, i8* %c +define void @uncompressStream(i8* %mem) { + %zext.255 = zext i8 255 to i32 + %sext.255 = sext i8 255 to i32 + %a = getelementptr inbounds i8, i8* %mem, i32 255 + %b = getelementptr inbounds i8, i8* %mem, i32 %zext.255 + %c = getelementptr inbounds i8, i8* %mem, i32 %sext.255 + ret void +} + +; CHECK-LABEL: constantOffsetHeuristic_i3_i32 +; CHECK: NoAlias: i32* %a, i32* %b +; CHECK: NoAlias: i32* %a, i32* %c +; CHECK: NoAlias: i32* %b, i32* %c +define void @constantOffsetHeuristic_i3_i32(i32* %mem, i3 %val) { + %zext.plus.7 = add nsw i3 %val, 7 + %zext.plus.4 = add nsw i3 %val, 4 + %zext.val = zext i3 %val to i32 + %zext.4 = zext i3 %zext.plus.4 to i32 + %zext.7 = zext i3 %zext.plus.7 to i32 + %a = getelementptr inbounds i32, i32* %mem, i32 %zext.4 + %b = getelementptr inbounds i32, i32* %mem, i32 %zext.7 + %c = getelementptr inbounds i32, i32* %mem, i32 %zext.val + ret void +} + +; CHECK-LABEL: constantOffsetHeuristic_i8_i32 +; CHECK: NoAlias: i32* %a, i32* %b +; CHECK: NoAlias: i32* %a, i32* %c +; CHECK: NoAlias: i32* %b, i32* %c +define void @constantOffsetHeuristic_i8_i32(i32* %mem, i8 %val) { + %zext.plus.7 = add nsw i8 %val, 7 + %zext.plus.4 = add nsw i8 %val, 4 + %zext.val = zext i8 %val to i32 + %zext.4 = zext i8 %zext.plus.4 to i32 + %zext.7 = zext i8 %zext.plus.7 to i32 + %a = getelementptr inbounds i32, i32* %mem, i32 %zext.4 + %b = getelementptr inbounds i32, i32* %mem, i32 %zext.7 + %c = getelementptr inbounds i32, i32* %mem, i32 %zext.val + ret void +} + +; CHECK-LABEL: constantOffsetHeuristic_i3_i8 +; CHECK: PartialAlias: i32* %a, i32* %b +; CHECK: NoAlias: i32* %a, i32* %c +; CHECK: PartialAlias: i32* %b, i32* %c +define void @constantOffsetHeuristic_i3_i8(i8* %mem, i3 %val) { + %zext.plus.7 = add nsw i3 %val, 7 + %zext.plus.4 = add nsw i3 %val, 4 + %zext.val = zext i3 %val to i32 + %zext.4 = zext i3 %zext.plus.4 to i32 + %zext.7 = zext i3 %zext.plus.7 to i32 + %a.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.4 + %b.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.7 + %c.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.val + %a = bitcast i8* %a.8 to i32* + %b = bitcast i8* %b.8 to i32* + %c = bitcast i8* %c.8 to i32* + ret void +} + +; CHECK-LABEL: constantOffsetHeuristic_i8_i8 +; CHECK: PartialAlias: i32* %a, i32* %b +; CHECK: NoAlias: i32* %a, i32* %c +; CHECK: NoAlias: i32* %b, i32* %c +define void @constantOffsetHeuristic_i8_i8(i8* %mem, i8 %val) { + %zext.plus.7 = add nsw i8 %val, 7 + %zext.plus.4 = add nsw i8 %val, 4 + %zext.val = zext i8 %val to i32 + %zext.4 = zext i8 %zext.plus.4 to i32 + %zext.7 = zext i8 %zext.plus.7 to i32 + %a.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.4 + %b.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.7 + %c.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.val + %a = bitcast i8* %a.8 to i32* + %b = bitcast i8* %b.8 to i32* + %c = bitcast i8* %c.8 to i32* + ret void +} diff --git a/test/Analysis/BasicAA/sequential-gep.ll b/test/Analysis/BasicAA/sequential-gep.ll new file mode 100644 index 000000000000..c17a782aa04b --- /dev/null +++ b/test/Analysis/BasicAA/sequential-gep.ll @@ -0,0 +1,54 @@ +; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +; CHECK: Function: t1 +; CHECK: NoAlias: i32* %gep1, i32* %gep2 +define void @t1([8 x i32]* %p, i32 %addend, i32* %q) { + %knownnonzero = load i32, i32* %q, !range !0 + %add = add nsw nuw i32 %addend, %knownnonzero + %gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 2, i32 %addend + %gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 2, i32 %add + ret void +} + +; CHECK: Function: t2 +; CHECK: PartialAlias: i32* %gep1, i32* %gep2 +define void @t2([8 x i32]* %p, i32 %addend, i32* %q) { + %knownnonzero = load i32, i32* %q, !range !0 + %add = add nsw nuw i32 %addend, %knownnonzero + %gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 1, i32 %addend + %gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 0, i32 %add + ret void +} + +; CHECK: Function: t3 +; CHECK: MustAlias: i32* %gep1, i32* %gep2 +define void @t3([8 x i32]* %p, i32 %addend, i32* %q) { + %knownnonzero = load i32, i32* %q, !range !0 + %add = add nsw nuw i32 %addend, %knownnonzero + %gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 0, i32 %add + %gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 0, i32 %add + ret void +} + +; CHECK: Function: t4 +; CHECK: PartialAlias: i32* %gep1, i32* %gep2 +define void @t4([8 x i32]* %p, i32 %addend, i32* %q) { + %knownnonzero = load i32, i32* %q, !range !0 + %add = add nsw nuw i32 %addend, %knownnonzero + %gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 1, i32 %addend + %gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 %add, i32 %add + ret void +} + +; CHECK: Function: t5 +; CHECK: PartialAlias: i32* %gep2, i64* %bc +define void @t5([8 x i32]* %p, i32 %addend, i32* %q) { + %knownnonzero = load i32, i32* %q, !range !0 + %add = add nsw nuw i32 %addend, %knownnonzero + %gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 2, i32 %addend + %gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 2, i32 %add + %bc = bitcast i32* %gep1 to i64* + ret void +} + +!0 = !{ i32 1, i32 5 } diff --git a/test/Analysis/BasicAA/zext.ll b/test/Analysis/BasicAA/zext.ll new file mode 100644 index 000000000000..685d45be6151 --- /dev/null +++ b/test/Analysis/BasicAA/zext.ll @@ -0,0 +1,231 @@ +; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %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-S128" +target triple = "x86_64-unknown-linux-gnu" + +; CHECK-LABEL: test_with_zext +; CHECK: NoAlias: i8* %a, i8* %b + +define void @test_with_zext() { + %1 = tail call i8* @malloc(i64 120) + %a = getelementptr inbounds i8, i8* %1, i64 8 + %2 = getelementptr inbounds i8, i8* %1, i64 16 + %3 = zext i32 3 to i64 + %b = getelementptr inbounds i8, i8* %2, i64 %3 + ret void +} + +; CHECK-LABEL: test_with_lshr +; CHECK: NoAlias: i8* %a, i8* %b + +define void @test_with_lshr(i64 %i) { + %1 = tail call i8* @malloc(i64 120) + %a = getelementptr inbounds i8, i8* %1, i64 8 + %2 = getelementptr inbounds i8, i8* %1, i64 16 + %3 = lshr i64 %i, 2 + %b = getelementptr inbounds i8, i8* %2, i64 %3 + ret void +} + +; CHECK-LABEL: test_with_a_loop +; CHECK: NoAlias: i8* %a, i8* %b + +define void @test_with_a_loop(i8* %mem) { + br label %for.loop + +for.loop: + %i = phi i32 [ 0, %0 ], [ %i.plus1, %for.loop ] + %a = getelementptr inbounds i8, i8* %mem, i64 8 + %a.plus1 = getelementptr inbounds i8, i8* %mem, i64 16 + %i.64 = zext i32 %i to i64 + %b = getelementptr inbounds i8, i8* %a.plus1, i64 %i.64 + %i.plus1 = add nuw nsw i32 %i, 1 + %cmp = icmp eq i32 %i.plus1, 10 + br i1 %cmp, label %for.loop.exit, label %for.loop + +for.loop.exit: + ret void +} + +; CHECK-LABEL: test_with_varying_base_pointer_in_loop +; CHECK: NoAlias: i8* %a, i8* %b + +define void @test_with_varying_base_pointer_in_loop(i8* %mem.orig) { + br label %for.loop + +for.loop: + %mem = phi i8* [ %mem.orig, %0 ], [ %mem.plus1, %for.loop ] + %i = phi i32 [ 0, %0 ], [ %i.plus1, %for.loop ] + %a = getelementptr inbounds i8, i8* %mem, i64 8 + %a.plus1 = getelementptr inbounds i8, i8* %mem, i64 16 + %i.64 = zext i32 %i to i64 + %b = getelementptr inbounds i8, i8* %a.plus1, i64 %i.64 + %i.plus1 = add nuw nsw i32 %i, 1 + %mem.plus1 = getelementptr inbounds i8, i8* %mem, i64 8 + %cmp = icmp eq i32 %i.plus1, 10 + br i1 %cmp, label %for.loop.exit, label %for.loop + +for.loop.exit: + ret void +} + +; CHECK-LABEL: test_sign_extension +; CHECK: PartialAlias: i64* %b.i64, i8* %a + +define void @test_sign_extension(i32 %p) { + %1 = tail call i8* @malloc(i64 120) + %p.64 = zext i32 %p to i64 + %a = getelementptr inbounds i8, i8* %1, i64 %p.64 + %p.minus1 = add i32 %p, -1 + %p.minus1.64 = zext i32 %p.minus1 to i64 + %b.i8 = getelementptr inbounds i8, i8* %1, i64 %p.minus1.64 + %b.i64 = bitcast i8* %b.i8 to i64* + ret void +} + +; CHECK-LABEL: test_fe_tools +; CHECK: PartialAlias: i32* %a, i32* %b + +define void @test_fe_tools([8 x i32]* %values) { + br label %reorder + +for.loop: + %i = phi i32 [ 0, %reorder ], [ %i.next, %for.loop ] + %idxprom = zext i32 %i to i64 + %b = getelementptr inbounds [8 x i32], [8 x i32]* %values, i64 0, i64 %idxprom + %i.next = add nuw nsw i32 %i, 1 + %1 = icmp eq i32 %i.next, 10 + br i1 %1, label %for.loop.exit, label %for.loop + +reorder: + %a = getelementptr inbounds [8 x i32], [8 x i32]* %values, i64 0, i64 1 + br label %for.loop + +for.loop.exit: + ret void +} + +@b = global i32 0, align 4 +@d = global i32 0, align 4 + +; CHECK-LABEL: test_spec2006 +; CHECK: PartialAlias: i32** %x, i32** %y + +define void @test_spec2006() { + %h = alloca [1 x [2 x i32*]], align 16 + %d.val = load i32, i32* @d, align 4 + %d.promoted = sext i32 %d.val to i64 + %1 = icmp slt i32 %d.val, 2 + br i1 %1, label %.lr.ph, label %3 + +.lr.ph: ; preds = %0 + br label %2 + +; <label>:2 ; preds = %.lr.ph, %2 + %i = phi i32 [ %d.val, %.lr.ph ], [ %i.plus1, %2 ] + %i.promoted = sext i32 %i to i64 + %x = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 %d.promoted, i64 %i.promoted + %i.plus1 = add nsw i32 %i, 1 + %cmp = icmp slt i32 %i.plus1, 2 + br i1 %cmp, label %2, label %3 + +; <label>:3 ; preds = %._crit_edge, %0 + %y = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 0, i64 1 + ret void +} + +; CHECK-LABEL: test_modulo_analysis_easy_case +; CHECK: NoAlias: i32** %x, i32** %y + +define void @test_modulo_analysis_easy_case(i64 %i) { + %h = alloca [1 x [2 x i32*]], align 16 + %x = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 %i, i64 0 + %y = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 0, i64 1 + ret void +} + +; CHECK-LABEL: test_modulo_analysis_in_loop +; CHECK: NoAlias: i32** %x, i32** %y + +define void @test_modulo_analysis_in_loop() { + %h = alloca [1 x [2 x i32*]], align 16 + br label %for.loop + +for.loop: + %i = phi i32 [ 0, %0 ], [ %i.plus1, %for.loop ] + %i.promoted = sext i32 %i to i64 + %x = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 %i.promoted, i64 0 + %y = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 0, i64 1 + %i.plus1 = add nsw i32 %i, 1 + %cmp = icmp slt i32 %i.plus1, 2 + br i1 %cmp, label %for.loop, label %for.loop.exit + +for.loop.exit: + ret void +} + +; CHECK-LABEL: test_modulo_analysis_with_global +; CHECK: PartialAlias: i32** %x, i32** %y + +define void @test_modulo_analysis_with_global() { + %h = alloca [1 x [2 x i32*]], align 16 + %b = load i32, i32* @b, align 4 + %b.promoted = sext i32 %b to i64 + br label %for.loop + +for.loop: + %i = phi i32 [ 0, %0 ], [ %i.plus1, %for.loop ] + %i.promoted = sext i32 %i to i64 + %x = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 %i.promoted, i64 %b.promoted + %y = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 0, i64 1 + %i.plus1 = add nsw i32 %i, 1 + %cmp = icmp slt i32 %i.plus1, 2 + br i1 %cmp, label %for.loop, label %for.loop.exit + +for.loop.exit: + ret void +} + +; CHECK-LABEL: test_const_eval +; CHECK: NoAlias: i8* %a, i8* %b +define void @test_const_eval(i8* %ptr, i64 %offset) { + %a = getelementptr inbounds i8, i8* %ptr, i64 %offset + %a.dup = getelementptr inbounds i8, i8* %ptr, i64 %offset + %three = zext i32 3 to i64 + %b = getelementptr inbounds i8, i8* %a.dup, i64 %three + ret void +} + +; CHECK-LABEL: test_const_eval_scaled +; CHECK: MustAlias: i8* %a, i8* %b +define void @test_const_eval_scaled(i8* %ptr) { + %three = zext i32 3 to i64 + %six = mul i64 %three, 2 + %a = getelementptr inbounds i8, i8* %ptr, i64 %six + %b = getelementptr inbounds i8, i8* %ptr, i64 6 + ret void +} + +; CHECK-LABEL: Function: foo +; CHECK: MustAlias: float* %arrayidx, float* %arrayidx4.84 +define float @foo(i32 *%A, float %rend, float** %wayar) { +entry: + %x0 = load i32, i32* %A, align 4 + %conv = sext i32 %x0 to i64 + %mul = shl nsw i64 %conv, 3 + %call = tail call i8* @malloc(i64 %mul) + %x1 = bitcast i8* %call to float* + + %sub = add nsw i32 %x0, -1 + %idxprom = sext i32 %sub to i64 + %arrayidx = getelementptr inbounds float, float* %x1, i64 %idxprom + store float %rend, float* %arrayidx, align 8 + + %indvars.iv76.83 = add nsw i64 %conv, -1 + %arrayidx4.84 = getelementptr inbounds float, float* %x1, i64 %indvars.iv76.83 + %x4 = load float, float* %arrayidx4.84, align 8 + + ret float %x4 +} + +; Function Attrs: nounwind +declare noalias i8* @malloc(i64) diff --git a/test/Analysis/BlockFrequencyInfo/bad_input.ll b/test/Analysis/BlockFrequencyInfo/bad_input.ll index e5b1f500e1e6..20b87e6dfcb4 100644 --- a/test/Analysis/BlockFrequencyInfo/bad_input.ll +++ b/test/Analysis/BlockFrequencyInfo/bad_input.ll @@ -9,8 +9,8 @@ define void @branch_weight_0(i32 %a) { entry: br label %for.body -; Check that we get 1,4 instead of 0,3. -; CHECK-NEXT: for.body: float = 4.0, +; Check that we get 1 and a huge frequency instead of 0,3. +; CHECK-NEXT: for.body: float = 2147483647.8, for.body: %i = phi i32 [ 0, %entry ], [ %inc, %for.body ] call void @g(i32 %i) diff --git a/test/Analysis/BlockFrequencyInfo/basic.ll b/test/Analysis/BlockFrequencyInfo/basic.ll index 728adf007f42..8e81cc2ea31c 100644 --- a/test/Analysis/BlockFrequencyInfo/basic.ll +++ b/test/Analysis/BlockFrequencyInfo/basic.ll @@ -104,13 +104,13 @@ for.cond1.preheader: %x.024 = phi i32 [ 0, %entry ], [ %inc12, %for.inc11 ] br label %for.cond4.preheader -; CHECK-NEXT: for.cond4.preheader: float = 16008001.0, +; CHECK-NEXT: for.cond4.preheader: float = 16007984.8, for.cond4.preheader: %y.023 = phi i32 [ 0, %for.cond1.preheader ], [ %inc9, %for.inc8 ] %add = add i32 %y.023, %x.024 br label %for.body6 -; CHECK-NEXT: for.body6: float = 64048012001.0, +; CHECK-NEXT: for.body6: float = 64047914563.9, for.body6: %z.022 = phi i32 [ 0, %for.cond4.preheader ], [ %inc, %for.body6 ] %add7 = add i32 %add, %z.022 @@ -119,7 +119,7 @@ for.body6: %cmp5 = icmp ugt i32 %inc, %a br i1 %cmp5, label %for.inc8, label %for.body6, !prof !2 -; CHECK-NEXT: for.inc8: float = 16008001.0, +; CHECK-NEXT: for.inc8: float = 16007984.8, for.inc8: %inc9 = add i32 %y.023, 1 %cmp2 = icmp ugt i32 %inc9, %a diff --git a/test/Analysis/BlockFrequencyInfo/irreducible_loop_crash.ll b/test/Analysis/BlockFrequencyInfo/irreducible_loop_crash.ll new file mode 100644 index 000000000000..2bcd088dd16e --- /dev/null +++ b/test/Analysis/BlockFrequencyInfo/irreducible_loop_crash.ll @@ -0,0 +1,155 @@ +; RUN: opt < %s -analyze -block-freq + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @fn1(i32* %f) { +entry: + %tobool7 = icmp eq i32 undef, 0 + br i1 undef, label %if.end.12, label %for.body.5 + +for.inc: + store i32 undef, i32* %f, align 4 + br label %for.body.5 + +for.body.5: ; preds = %for.cond.4.preheader + br i1 %tobool7, label %for.inc.9, label %for.inc + +for.inc.9: ; preds = %for.body.5 + br i1 %tobool7, label %for.inc.9.1, label %for.inc + +if.end.12: ; preds = %if.end.12, %for.body + br i1 undef, label %for.end.17, label %for.inc + +for.end.17: ; preds = %entry + ret void + +for.inc.9.1: ; preds = %for.inc.9 + br i1 %tobool7, label %for.inc.9.2, label %for.inc + +for.inc.9.2: ; preds = %for.inc.9.1 + br i1 %tobool7, label %for.inc.9.3, label %for.inc + +for.inc.9.3: ; preds = %for.inc.9.2 + br i1 %tobool7, label %for.inc.9.4, label %for.inc + +for.inc.9.4: ; preds = %for.inc.9.3 + br i1 %tobool7, label %for.inc.9.5, label %for.inc + +for.inc.9.5: ; preds = %for.inc.9.4 + br i1 %tobool7, label %for.inc.9.6, label %for.inc + +for.inc.9.6: ; preds = %for.inc.9.5 + br i1 %tobool7, label %for.inc.9.7, label %for.inc + +for.inc.9.7: ; preds = %for.inc.9.6 + br i1 %tobool7, label %for.inc.9.8, label %for.inc + +for.inc.9.8: ; preds = %for.inc.9.7 + br i1 %tobool7, label %for.inc.9.9, label %for.inc + +for.inc.9.9: ; preds = %for.inc.9.8 + br i1 %tobool7, label %for.inc.9.10, label %for.inc + +for.inc.9.10: ; preds = %for.inc.9.9 + br i1 %tobool7, label %for.inc.9.11, label %for.inc + +for.inc.9.11: ; preds = %for.inc.9.10 + br i1 %tobool7, label %for.inc.9.12, label %for.inc + +for.inc.9.12: ; preds = %for.inc.9.11 + br i1 %tobool7, label %for.inc.9.13, label %for.inc + +for.inc.9.13: ; preds = %for.inc.9.12 + br i1 %tobool7, label %for.inc.9.14, label %for.inc + +for.inc.9.14: ; preds = %for.inc.9.13 + br i1 %tobool7, label %for.inc.9.15, label %for.inc + +for.inc.9.15: ; preds = %for.inc.9.14 + br i1 %tobool7, label %for.inc.9.16, label %for.inc + +for.inc.9.16: ; preds = %for.inc.9.15 + br i1 %tobool7, label %for.inc.9.17, label %for.inc + +for.inc.9.17: ; preds = %for.inc.9.16 + br i1 %tobool7, label %for.inc.9.18, label %for.inc + +for.inc.9.18: ; preds = %for.inc.9.17 + br i1 %tobool7, label %for.inc.9.19, label %for.inc + +for.inc.9.19: ; preds = %for.inc.9.18 + br i1 %tobool7, label %for.inc.9.20, label %for.inc + +for.inc.9.20: ; preds = %for.inc.9.19 + br i1 %tobool7, label %for.inc.9.21, label %for.inc + +for.inc.9.21: ; preds = %for.inc.9.20 + br i1 %tobool7, label %for.inc.9.22, label %for.inc + +for.inc.9.22: ; preds = %for.inc.9.21 + br i1 %tobool7, label %for.inc.9.23, label %for.inc + +for.inc.9.23: ; preds = %for.inc.9.22 + br i1 %tobool7, label %for.inc.9.24, label %for.inc + +for.inc.9.24: ; preds = %for.inc.9.23 + br i1 %tobool7, label %for.inc.9.25, label %for.inc + +for.inc.9.25: ; preds = %for.inc.9.24 + br i1 %tobool7, label %for.inc.9.26, label %for.inc + +for.inc.9.26: ; preds = %for.inc.9.25 + br i1 %tobool7, label %for.inc.9.27, label %for.inc + +for.inc.9.27: ; preds = %for.inc.9.26 + br i1 %tobool7, label %for.inc.9.28, label %for.inc + +for.inc.9.28: ; preds = %for.inc.9.27 + br i1 %tobool7, label %for.inc.9.29, label %for.inc + +for.inc.9.29: ; preds = %for.inc.9.28 + br i1 %tobool7, label %for.inc.9.30, label %for.inc + +for.inc.9.30: ; preds = %for.inc.9.29 + br i1 %tobool7, label %for.inc.9.31, label %for.inc + +for.inc.9.31: ; preds = %for.inc.9.30 + br i1 %tobool7, label %for.inc.9.32, label %for.inc + +for.inc.9.32: ; preds = %for.inc.9.31 + br i1 %tobool7, label %for.inc.9.33, label %for.inc + +for.inc.9.33: ; preds = %for.inc.9.32 + br i1 %tobool7, label %for.inc.9.34, label %for.inc + +for.inc.9.34: ; preds = %for.inc.9.33 + br i1 %tobool7, label %for.inc.9.35, label %for.inc + +for.inc.9.35: ; preds = %for.inc.9.34 + br i1 %tobool7, label %for.inc.9.36, label %for.inc + +for.inc.9.36: ; preds = %for.inc.9.35 + br i1 %tobool7, label %for.inc.9.37, label %for.inc + +for.inc.9.37: ; preds = %for.inc.9.36 + br i1 %tobool7, label %for.inc.9.38, label %for.inc + +for.inc.9.38: ; preds = %for.inc.9.37 + br i1 %tobool7, label %for.inc.9.39, label %for.inc + +for.inc.9.39: ; preds = %for.inc.9.38 + br i1 %tobool7, label %for.inc.9.40, label %for.inc + +for.inc.9.40: ; preds = %for.inc.9.39 + br i1 %tobool7, label %for.inc.9.41, label %for.inc + +for.inc.9.41: ; preds = %for.inc.9.40 + br i1 %tobool7, label %for.inc.9.42, label %for.inc + +for.inc.9.42: ; preds = %for.inc.9.41 + br i1 %tobool7, label %for.inc.9.43, label %for.inc + +for.inc.9.43: ; preds = %for.inc.9.42 + br i1 %tobool7, label %if.end.12, label %for.inc +} diff --git a/test/Analysis/BlockFrequencyInfo/loops_with_profile_info.ll b/test/Analysis/BlockFrequencyInfo/loops_with_profile_info.ll index 534c4ad0e94f..29a9f3b29fb0 100644 --- a/test/Analysis/BlockFrequencyInfo/loops_with_profile_info.ll +++ b/test/Analysis/BlockFrequencyInfo/loops_with_profile_info.ll @@ -93,7 +93,7 @@ for.cond4: ; preds = %for.inc, %for.body3 %cmp5 = icmp slt i32 %2, 100 br i1 %cmp5, label %for.body6, label %for.end, !prof !3 -; CHECK: - for.body6: float = 500000.5, int = 4000003 +; CHECK: - for.body6: float = 500000.5, int = 4000004 for.body6: ; preds = %for.cond4 call void @bar() br label %for.inc @@ -143,7 +143,7 @@ for.cond16: ; preds = %for.inc19, %for.bod %cmp17 = icmp slt i32 %8, 10000 br i1 %cmp17, label %for.body18, label %for.end21, !prof !4 -; CHECK: - for.body18: float = 500000.5, int = 4000003 +; CHECK: - for.body18: float = 499999.9, int = 3999998 for.body18: ; preds = %for.cond16 call void @bar() br label %for.inc19 @@ -175,7 +175,7 @@ for.cond26: ; preds = %for.inc29, %for.end %cmp27 = icmp slt i32 %12, 1000000 br i1 %cmp27, label %for.body28, label %for.end31, !prof !5 -; CHECK: - for.body28: float = 500000.5, int = 4000003 +; CHECK: - for.body28: float = 499995.2, int = 3999961 for.body28: ; preds = %for.cond26 call void @bar() br label %for.inc29 diff --git a/test/Analysis/BranchProbabilityInfo/basic.ll b/test/Analysis/BranchProbabilityInfo/basic.ll index 2c9c15618682..d833b8339aac 100644 --- a/test/Analysis/BranchProbabilityInfo/basic.ll +++ b/test/Analysis/BranchProbabilityInfo/basic.ll @@ -4,7 +4,7 @@ define i32 @test1(i32 %i, i32* %a) { ; CHECK: Printing analysis {{.*}} for function 'test1' entry: br label %body -; CHECK: edge entry -> body probability is 16 / 16 = 100% +; CHECK: edge entry -> body probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] body: %iv = phi i32 [ 0, %entry ], [ %next, %body ] @@ -15,8 +15,8 @@ body: %next = add i32 %iv, 1 %exitcond = icmp eq i32 %next, %i br i1 %exitcond, label %exit, label %body -; CHECK: edge body -> exit probability is 4 / 128 -; CHECK: edge body -> body probability is 124 / 128 +; CHECK: edge body -> exit probability is 0x04000000 / 0x80000000 = 3.12% +; CHECK: edge body -> body probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] exit: ret i32 %sum @@ -27,16 +27,16 @@ define i32 @test2(i32 %i, i32 %a, i32 %b) { entry: %cond = icmp ult i32 %i, 42 br i1 %cond, label %then, label %else, !prof !0 -; CHECK: edge entry -> then probability is 64 / 68 -; CHECK: edge entry -> else probability is 4 / 68 +; CHECK: edge entry -> then probability is 0x78787878 / 0x80000000 = 94.12% [HOT edge] +; CHECK: edge entry -> else probability is 0x07878788 / 0x80000000 = 5.88% then: br label %exit -; CHECK: edge then -> exit probability is 16 / 16 = 100% +; CHECK: edge then -> exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] else: br label %exit -; CHECK: edge else -> exit probability is 16 / 16 = 100% +; CHECK: edge else -> exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] exit: %result = phi i32 [ %a, %then ], [ %b, %else ] @@ -52,31 +52,31 @@ entry: i32 2, label %case_c i32 3, label %case_d i32 4, label %case_e ], !prof !1 -; CHECK: edge entry -> case_a probability is 4 / 80 -; CHECK: edge entry -> case_b probability is 4 / 80 -; CHECK: edge entry -> case_c probability is 64 / 80 -; CHECK: edge entry -> case_d probability is 4 / 80 -; CHECK: edge entry -> case_e probability is 4 / 80 +; CHECK: edge entry -> case_a probability is 0x06666666 / 0x80000000 = 5.00% +; CHECK: edge entry -> case_b probability is 0x06666666 / 0x80000000 = 5.00% +; CHECK: edge entry -> case_c probability is 0x66666666 / 0x80000000 = 80.00% +; CHECK: edge entry -> case_d probability is 0x06666666 / 0x80000000 = 5.00% +; CHECK: edge entry -> case_e probability is 0x06666666 / 0x80000000 = 5.00% case_a: br label %exit -; CHECK: edge case_a -> exit probability is 16 / 16 = 100% +; CHECK: edge case_a -> exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] case_b: br label %exit -; CHECK: edge case_b -> exit probability is 16 / 16 = 100% +; CHECK: edge case_b -> exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] case_c: br label %exit -; CHECK: edge case_c -> exit probability is 16 / 16 = 100% +; CHECK: edge case_c -> exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] case_d: br label %exit -; CHECK: edge case_d -> exit probability is 16 / 16 = 100% +; CHECK: edge case_d -> exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] case_e: br label %exit -; CHECK: edge case_e -> exit probability is 16 / 16 = 100% +; CHECK: edge case_e -> exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] exit: %result = phi i32 [ %a, %case_a ], @@ -99,9 +99,9 @@ entry: i64 2, label %sw.bb i64 5, label %sw.bb1 ], !prof !2 -; CHECK: edge entry -> return probability is 7 / 85 -; CHECK: edge entry -> sw.bb probability is 14 / 85 -; CHECK: edge entry -> sw.bb1 probability is 64 / 85 +; CHECK: edge entry -> return probability is 0x0a8a8a8b / 0x80000000 = 8.24% +; CHECK: edge entry -> sw.bb probability is 0x15151515 / 0x80000000 = 16.47% +; CHECK: edge entry -> sw.bb1 probability is 0x60606060 / 0x80000000 = 75.29% sw.bb: br label %return @@ -122,17 +122,17 @@ define i32 @test5(i32 %a, i32 %b, i1 %flag) { ; CHECK: Printing analysis {{.*}} for function 'test5' entry: br i1 %flag, label %then, label %else -; CHECK: edge entry -> then probability is 4 / 68 -; CHECK: edge entry -> else probability is 64 / 68 +; CHECK: edge entry -> then probability is 0x07878788 / 0x80000000 = 5.88% +; CHECK: edge entry -> else probability is 0x78787878 / 0x80000000 = 94.12% [HOT edge] then: call void @coldfunc() br label %exit -; CHECK: edge then -> exit probability is 16 / 16 = 100% +; CHECK: edge then -> exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] else: br label %exit -; CHECK: edge else -> exit probability is 16 / 16 = 100% +; CHECK: edge else -> exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] exit: %result = phi i32 [ %a, %then ], [ %b, %else ] @@ -149,8 +149,8 @@ define i32 @test_cold_call_sites(i32* %a) { ; after that is fixed. ; CHECK: Printing analysis {{.*}} for function 'test_cold_call_sites' -; CHECK: edge entry -> then probability is 4 / 68 = 5.88235% -; CHECK: edge entry -> else probability is 64 / 68 = 94.1176% [HOT edge] +; CHECK: edge entry -> then probability is 0x07878788 / 0x80000000 = 5.88% +; CHECK: edge entry -> else probability is 0x78787878 / 0x80000000 = 94.12% [HOT edge] entry: %gep1 = getelementptr i32, i32* %a, i32 1 @@ -179,8 +179,8 @@ define i32 @zero1(i32 %i, i32 %a, i32 %b) { entry: %cond = icmp eq i32 %i, 0 br i1 %cond, label %then, label %else -; CHECK: edge entry -> then probability is 12 / 32 -; CHECK: edge entry -> else probability is 20 / 32 +; CHECK: edge entry -> then probability is 0x30000000 / 0x80000000 = 37.50% +; CHECK: edge entry -> else probability is 0x50000000 / 0x80000000 = 62.50% then: br label %exit @@ -198,8 +198,8 @@ define i32 @zero2(i32 %i, i32 %a, i32 %b) { entry: %cond = icmp ne i32 %i, -1 br i1 %cond, label %then, label %else -; CHECK: edge entry -> then probability is 20 / 32 -; CHECK: edge entry -> else probability is 12 / 32 +; CHECK: edge entry -> then probability is 0x50000000 / 0x80000000 = 62.50% +; CHECK: edge entry -> else probability is 0x30000000 / 0x80000000 = 37.50% then: br label %exit @@ -220,8 +220,8 @@ entry: %and = and i32 %i, 2 %tobool = icmp eq i32 %and, 0 br i1 %tobool, label %then, label %else -; CHECK: edge entry -> then probability is 16 / 32 -; CHECK: edge entry -> else probability is 16 / 32 +; CHECK: edge entry -> then probability is 0x40000000 / 0x80000000 = 50.00% +; CHECK: edge entry -> else probability is 0x40000000 / 0x80000000 = 50.00% then: ; AND'ing with other bitmask might be something else, so we still assume the @@ -229,8 +229,8 @@ then: %and2 = and i32 %i, 5 %tobool2 = icmp eq i32 %and2, 0 br i1 %tobool2, label %else, label %exit -; CHECK: edge then -> else probability is 12 / 32 -; CHECK: edge then -> exit probability is 20 / 32 +; CHECK: edge then -> else probability is 0x30000000 / 0x80000000 = 37.50% +; CHECK: edge then -> exit probability is 0x50000000 / 0x80000000 = 62.50% else: br label %exit diff --git a/test/Analysis/BranchProbabilityInfo/loop.ll b/test/Analysis/BranchProbabilityInfo/loop.ll index e792790f84f8..5be7adf3909d 100644 --- a/test/Analysis/BranchProbabilityInfo/loop.ll +++ b/test/Analysis/BranchProbabilityInfo/loop.ll @@ -9,13 +9,13 @@ declare void @g4() define void @test1(i32 %a, i32 %b) { entry: br label %do.body -; CHECK: edge entry -> do.body probability is 16 / 16 = 100% +; CHECK: edge entry -> do.body probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] do.body: %i.0 = phi i32 [ 0, %entry ], [ %inc3, %do.end ] call void @g1() br label %do.body1 -; CHECK: edge do.body -> do.body1 probability is 16 / 16 = 100% +; CHECK: edge do.body -> do.body1 probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] do.body1: %j.0 = phi i32 [ 0, %do.body ], [ %inc, %do.body1 ] @@ -23,16 +23,16 @@ do.body1: %inc = add nsw i32 %j.0, 1 %cmp = icmp slt i32 %inc, %b br i1 %cmp, label %do.body1, label %do.end -; CHECK: edge do.body1 -> do.body1 probability is 124 / 128 -; CHECK: edge do.body1 -> do.end probability is 4 / 128 +; CHECK: edge do.body1 -> do.body1 probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] +; CHECK: edge do.body1 -> do.end probability is 0x04000000 / 0x80000000 = 3.12% do.end: call void @g3() %inc3 = add nsw i32 %i.0, 1 %cmp4 = icmp slt i32 %inc3, %a br i1 %cmp4, label %do.body, label %do.end5 -; CHECK: edge do.end -> do.body probability is 124 / 128 -; CHECK: edge do.end -> do.end5 probability is 4 / 128 +; CHECK: edge do.end -> do.body probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] +; CHECK: edge do.end -> do.end5 probability is 0x04000000 / 0x80000000 = 3.12% do.end5: call void @g4() @@ -43,20 +43,20 @@ define void @test2(i32 %a, i32 %b) { entry: %cmp9 = icmp sgt i32 %a, 0 br i1 %cmp9, label %for.body.lr.ph, label %for.end6 -; CHECK: edge entry -> for.body.lr.ph probability is 20 / 32 -; CHECK: edge entry -> for.end6 probability is 12 / 32 +; CHECK: edge entry -> for.body.lr.ph probability is 0x50000000 / 0x80000000 = 62.50% +; CHECK: edge entry -> for.end6 probability is 0x30000000 / 0x80000000 = 37.50% for.body.lr.ph: %cmp27 = icmp sgt i32 %b, 0 br label %for.body -; CHECK: edge for.body.lr.ph -> for.body probability is 16 / 16 = 100% +; CHECK: edge for.body.lr.ph -> for.body probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] for.body: %i.010 = phi i32 [ 0, %for.body.lr.ph ], [ %inc5, %for.end ] call void @g1() br i1 %cmp27, label %for.body3, label %for.end -; CHECK: edge for.body -> for.body3 probability is 20 / 32 = 62.5% -; CHECK: edge for.body -> for.end probability is 12 / 32 = 37.5% +; CHECK: edge for.body -> for.body3 probability is 0x50000000 / 0x80000000 = 62.50% +; CHECK: edge for.body -> for.end probability is 0x30000000 / 0x80000000 = 37.50% for.body3: %j.08 = phi i32 [ %inc, %for.body3 ], [ 0, %for.body ] @@ -64,16 +64,16 @@ for.body3: %inc = add nsw i32 %j.08, 1 %exitcond = icmp eq i32 %inc, %b br i1 %exitcond, label %for.end, label %for.body3 -; CHECK: edge for.body3 -> for.end probability is 4 / 128 -; CHECK: edge for.body3 -> for.body3 probability is 124 / 128 +; CHECK: edge for.body3 -> for.end probability is 0x04000000 / 0x80000000 = 3.12% +; CHECK: edge for.body3 -> for.body3 probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] for.end: call void @g3() %inc5 = add nsw i32 %i.010, 1 %exitcond11 = icmp eq i32 %inc5, %a br i1 %exitcond11, label %for.end6, label %for.body -; CHECK: edge for.end -> for.end6 probability is 4 / 128 -; CHECK: edge for.end -> for.body probability is 124 / 128 +; CHECK: edge for.end -> for.end6 probability is 0x04000000 / 0x80000000 = 3.12% +; CHECK: edge for.end -> for.body probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] for.end6: call void @g4() @@ -83,7 +83,7 @@ for.end6: define void @test3(i32 %a, i32 %b, i32* %c) { entry: br label %do.body -; CHECK: edge entry -> do.body probability is 16 / 16 = 100% +; CHECK: edge entry -> do.body probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] do.body: %i.0 = phi i32 [ 0, %entry ], [ %inc4, %if.end ] @@ -91,8 +91,8 @@ do.body: %0 = load i32, i32* %c, align 4 %cmp = icmp slt i32 %0, 42 br i1 %cmp, label %do.body1, label %if.end -; CHECK: edge do.body -> do.body1 probability is 16 / 32 = 50% -; CHECK: edge do.body -> if.end probability is 16 / 32 = 50% +; CHECK: edge do.body -> do.body1 probability is 0x40000000 / 0x80000000 = 50.00% +; CHECK: edge do.body -> if.end probability is 0x40000000 / 0x80000000 = 50.00% do.body1: %j.0 = phi i32 [ %inc, %do.body1 ], [ 0, %do.body ] @@ -100,16 +100,16 @@ do.body1: %inc = add nsw i32 %j.0, 1 %cmp2 = icmp slt i32 %inc, %b br i1 %cmp2, label %do.body1, label %if.end -; CHECK: edge do.body1 -> do.body1 probability is 124 / 128 -; CHECK: edge do.body1 -> if.end probability is 4 / 128 +; CHECK: edge do.body1 -> do.body1 probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] +; CHECK: edge do.body1 -> if.end probability is 0x04000000 / 0x80000000 = 3.12% if.end: call void @g3() %inc4 = add nsw i32 %i.0, 1 %cmp5 = icmp slt i32 %inc4, %a br i1 %cmp5, label %do.body, label %do.end6 -; CHECK: edge if.end -> do.body probability is 124 / 128 -; CHECK: edge if.end -> do.end6 probability is 4 / 128 +; CHECK: edge if.end -> do.body probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] +; CHECK: edge if.end -> do.end6 probability is 0x04000000 / 0x80000000 = 3.12% do.end6: call void @g4() @@ -119,7 +119,7 @@ do.end6: define void @test4(i32 %a, i32 %b, i32* %c) { entry: br label %do.body -; CHECK: edge entry -> do.body probability is 16 / 16 = 100% +; CHECK: edge entry -> do.body probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] do.body: %i.0 = phi i32 [ 0, %entry ], [ %inc4, %do.end ] @@ -127,8 +127,8 @@ do.body: %0 = load i32, i32* %c, align 4 %cmp = icmp slt i32 %0, 42 br i1 %cmp, label %return, label %do.body1 -; CHECK: edge do.body -> return probability is 4 / 128 -; CHECK: edge do.body -> do.body1 probability is 124 / 128 +; CHECK: edge do.body -> return probability is 0x04000000 / 0x80000000 = 3.12% +; CHECK: edge do.body -> do.body1 probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] do.body1: %j.0 = phi i32 [ %inc, %do.body1 ], [ 0, %do.body ] @@ -136,21 +136,21 @@ do.body1: %inc = add nsw i32 %j.0, 1 %cmp2 = icmp slt i32 %inc, %b br i1 %cmp2, label %do.body1, label %do.end -; CHECK: edge do.body1 -> do.body1 probability is 124 / 128 -; CHECK: edge do.body1 -> do.end probability is 4 / 128 +; CHECK: edge do.body1 -> do.body1 probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] +; CHECK: edge do.body1 -> do.end probability is 0x04000000 / 0x80000000 = 3.12% do.end: call void @g3() %inc4 = add nsw i32 %i.0, 1 %cmp5 = icmp slt i32 %inc4, %a br i1 %cmp5, label %do.body, label %do.end6 -; CHECK: edge do.end -> do.body probability is 124 / 128 -; CHECK: edge do.end -> do.end6 probability is 4 / 128 +; CHECK: edge do.end -> do.body probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] +; CHECK: edge do.end -> do.end6 probability is 0x04000000 / 0x80000000 = 3.12% do.end6: call void @g4() br label %return -; CHECK: edge do.end6 -> return probability is 16 / 16 = 100% +; CHECK: edge do.end6 -> return probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] return: ret void @@ -159,42 +159,42 @@ return: define void @test5(i32 %a, i32 %b, i32* %c) { entry: br label %do.body -; CHECK: edge entry -> do.body probability is 16 / 16 = 100% +; CHECK: edge entry -> do.body probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] do.body: %i.0 = phi i32 [ 0, %entry ], [ %inc4, %do.end ] call void @g1() br label %do.body1 -; CHECK: edge do.body -> do.body1 probability is 16 / 16 = 100% +; CHECK: edge do.body -> do.body1 probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] do.body1: %j.0 = phi i32 [ 0, %do.body ], [ %inc, %if.end ] %0 = load i32, i32* %c, align 4 %cmp = icmp slt i32 %0, 42 br i1 %cmp, label %return, label %if.end -; CHECK: edge do.body1 -> return probability is 4 / 128 -; CHECK: edge do.body1 -> if.end probability is 124 / 128 +; CHECK: edge do.body1 -> return probability is 0x04000000 / 0x80000000 = 3.12% +; CHECK: edge do.body1 -> if.end probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] if.end: call void @g2() %inc = add nsw i32 %j.0, 1 %cmp2 = icmp slt i32 %inc, %b br i1 %cmp2, label %do.body1, label %do.end -; CHECK: edge if.end -> do.body1 probability is 124 / 128 -; CHECK: edge if.end -> do.end probability is 4 / 128 +; CHECK: edge if.end -> do.body1 probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] +; CHECK: edge if.end -> do.end probability is 0x04000000 / 0x80000000 = 3.12% do.end: call void @g3() %inc4 = add nsw i32 %i.0, 1 %cmp5 = icmp slt i32 %inc4, %a br i1 %cmp5, label %do.body, label %do.end6 -; CHECK: edge do.end -> do.body probability is 124 / 128 -; CHECK: edge do.end -> do.end6 probability is 4 / 128 +; CHECK: edge do.end -> do.body probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] +; CHECK: edge do.end -> do.end6 probability is 0x04000000 / 0x80000000 = 3.12% do.end6: call void @g4() br label %return -; CHECK: edge do.end6 -> return probability is 16 / 16 = 100% +; CHECK: edge do.end6 -> return probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] return: ret void @@ -203,13 +203,13 @@ return: define void @test6(i32 %a, i32 %b, i32* %c) { entry: br label %do.body -; CHECK: edge entry -> do.body probability is 16 / 16 = 100% +; CHECK: edge entry -> do.body probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] do.body: %i.0 = phi i32 [ 0, %entry ], [ %inc4, %do.end ] call void @g1() br label %do.body1 -; CHECK: edge do.body -> do.body1 probability is 16 / 16 = 100% +; CHECK: edge do.body -> do.body1 probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] do.body1: %j.0 = phi i32 [ 0, %do.body ], [ %inc, %do.cond ] @@ -217,28 +217,28 @@ do.body1: %0 = load i32, i32* %c, align 4 %cmp = icmp slt i32 %0, 42 br i1 %cmp, label %return, label %do.cond -; CHECK: edge do.body1 -> return probability is 4 / 128 -; CHECK: edge do.body1 -> do.cond probability is 124 / 128 +; CHECK: edge do.body1 -> return probability is 0x04000000 / 0x80000000 = 3.12% +; CHECK: edge do.body1 -> do.cond probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] do.cond: %inc = add nsw i32 %j.0, 1 %cmp2 = icmp slt i32 %inc, %b br i1 %cmp2, label %do.body1, label %do.end -; CHECK: edge do.cond -> do.body1 probability is 124 / 128 -; CHECK: edge do.cond -> do.end probability is 4 / 128 +; CHECK: edge do.cond -> do.body1 probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] +; CHECK: edge do.cond -> do.end probability is 0x04000000 / 0x80000000 = 3.12% do.end: call void @g3() %inc4 = add nsw i32 %i.0, 1 %cmp5 = icmp slt i32 %inc4, %a br i1 %cmp5, label %do.body, label %do.end6 -; CHECK: edge do.end -> do.body probability is 124 / 128 -; CHECK: edge do.end -> do.end6 probability is 4 / 128 +; CHECK: edge do.end -> do.body probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] +; CHECK: edge do.end -> do.end6 probability is 0x04000000 / 0x80000000 = 3.12% do.end6: call void @g4() br label %return -; CHECK: edge do.end6 -> return probability is 16 / 16 = 100% +; CHECK: edge do.end6 -> return probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] return: ret void @@ -248,27 +248,27 @@ define void @test7(i32 %a, i32 %b, i32* %c) { entry: %cmp10 = icmp sgt i32 %a, 0 br i1 %cmp10, label %for.body.lr.ph, label %for.end7 -; CHECK: edge entry -> for.body.lr.ph probability is 20 / 32 -; CHECK: edge entry -> for.end7 probability is 12 / 32 +; CHECK: edge entry -> for.body.lr.ph probability is 0x50000000 / 0x80000000 = 62.50% +; CHECK: edge entry -> for.end7 probability is 0x30000000 / 0x80000000 = 37.50% for.body.lr.ph: %cmp38 = icmp sgt i32 %b, 0 br label %for.body -; CHECK: edge for.body.lr.ph -> for.body probability is 16 / 16 = 100% +; CHECK: edge for.body.lr.ph -> for.body probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] for.body: %i.011 = phi i32 [ 0, %for.body.lr.ph ], [ %inc6, %for.inc5 ] %0 = load i32, i32* %c, align 4 %cmp1 = icmp eq i32 %0, %i.011 br i1 %cmp1, label %for.inc5, label %if.end -; CHECK: edge for.body -> for.inc5 probability is 16 / 32 = 50% -; CHECK: edge for.body -> if.end probability is 16 / 32 = 50% +; CHECK: edge for.body -> for.inc5 probability is 0x40000000 / 0x80000000 = 50.00% +; CHECK: edge for.body -> if.end probability is 0x40000000 / 0x80000000 = 50.00% if.end: call void @g1() br i1 %cmp38, label %for.body4, label %for.end -; CHECK: edge if.end -> for.body4 probability is 20 / 32 = 62.5% -; CHECK: edge if.end -> for.end probability is 12 / 32 = 37.5% +; CHECK: edge if.end -> for.body4 probability is 0x50000000 / 0x80000000 = 62.50% +; CHECK: edge if.end -> for.end probability is 0x30000000 / 0x80000000 = 37.50% for.body4: %j.09 = phi i32 [ %inc, %for.body4 ], [ 0, %if.end ] @@ -276,20 +276,20 @@ for.body4: %inc = add nsw i32 %j.09, 1 %exitcond = icmp eq i32 %inc, %b br i1 %exitcond, label %for.end, label %for.body4 -; CHECK: edge for.body4 -> for.end probability is 4 / 128 -; CHECK: edge for.body4 -> for.body4 probability is 124 / 128 +; CHECK: edge for.body4 -> for.end probability is 0x04000000 / 0x80000000 = 3.12% +; CHECK: edge for.body4 -> for.body4 probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] for.end: call void @g3() br label %for.inc5 -; CHECK: edge for.end -> for.inc5 probability is 16 / 16 = 100% +; CHECK: edge for.end -> for.inc5 probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] for.inc5: %inc6 = add nsw i32 %i.011, 1 %exitcond12 = icmp eq i32 %inc6, %a br i1 %exitcond12, label %for.end7, label %for.body -; CHECK: edge for.inc5 -> for.end7 probability is 4 / 128 -; CHECK: edge for.inc5 -> for.body probability is 124 / 128 +; CHECK: edge for.inc5 -> for.end7 probability is 0x04000000 / 0x80000000 = 3.12% +; CHECK: edge for.inc5 -> for.body probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] for.end7: call void @g4() @@ -300,64 +300,64 @@ define void @test8(i32 %a, i32 %b, i32* %c) { entry: %cmp18 = icmp sgt i32 %a, 0 br i1 %cmp18, label %for.body.lr.ph, label %for.end15 -; CHECK: edge entry -> for.body.lr.ph probability is 20 / 32 -; CHECK: edge entry -> for.end15 probability is 12 / 32 +; CHECK: edge entry -> for.body.lr.ph probability is 0x50000000 / 0x80000000 = 62.50% +; CHECK: edge entry -> for.end15 probability is 0x30000000 / 0x80000000 = 37.50% for.body.lr.ph: %cmp216 = icmp sgt i32 %b, 0 %arrayidx5 = getelementptr inbounds i32, i32* %c, i64 1 %arrayidx9 = getelementptr inbounds i32, i32* %c, i64 2 br label %for.body -; CHECK: edge for.body.lr.ph -> for.body probability is 16 / 16 = 100% +; CHECK: edge for.body.lr.ph -> for.body probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] for.body: %i.019 = phi i32 [ 0, %for.body.lr.ph ], [ %inc14, %for.end ] call void @g1() br i1 %cmp216, label %for.body3, label %for.end -; CHECK: edge for.body -> for.body3 probability is 20 / 32 = 62.5% -; CHECK: edge for.body -> for.end probability is 12 / 32 = 37.5% +; CHECK: edge for.body -> for.body3 probability is 0x50000000 / 0x80000000 = 62.50% +; CHECK: edge for.body -> for.end probability is 0x30000000 / 0x80000000 = 37.50% for.body3: %j.017 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ] %0 = load i32, i32* %c, align 4 %cmp4 = icmp eq i32 %0, %j.017 br i1 %cmp4, label %for.inc, label %if.end -; CHECK: edge for.body3 -> for.inc probability is 16 / 32 = 50% -; CHECK: edge for.body3 -> if.end probability is 16 / 32 = 50% +; CHECK: edge for.body3 -> for.inc probability is 0x40000000 / 0x80000000 = 50.00% +; CHECK: edge for.body3 -> if.end probability is 0x40000000 / 0x80000000 = 50.00% if.end: %1 = load i32, i32* %arrayidx5, align 4 %cmp6 = icmp eq i32 %1, %j.017 br i1 %cmp6, label %for.inc, label %if.end8 -; CHECK: edge if.end -> for.inc probability is 16 / 32 = 50% -; CHECK: edge if.end -> if.end8 probability is 16 / 32 = 50% +; CHECK: edge if.end -> for.inc probability is 0x40000000 / 0x80000000 = 50.00% +; CHECK: edge if.end -> if.end8 probability is 0x40000000 / 0x80000000 = 50.00% if.end8: %2 = load i32, i32* %arrayidx9, align 4 %cmp10 = icmp eq i32 %2, %j.017 br i1 %cmp10, label %for.inc, label %if.end12 -; CHECK: edge if.end8 -> for.inc probability is 16 / 32 = 50% -; CHECK: edge if.end8 -> if.end12 probability is 16 / 32 = 50% +; CHECK: edge if.end8 -> for.inc probability is 0x40000000 / 0x80000000 = 50.00% +; CHECK: edge if.end8 -> if.end12 probability is 0x40000000 / 0x80000000 = 50.00% if.end12: call void @g2() br label %for.inc -; CHECK: edge if.end12 -> for.inc probability is 16 / 16 = 100% +; CHECK: edge if.end12 -> for.inc probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge] for.inc: %inc = add nsw i32 %j.017, 1 %exitcond = icmp eq i32 %inc, %b br i1 %exitcond, label %for.end, label %for.body3 -; CHECK: edge for.inc -> for.end probability is 4 / 128 -; CHECK: edge for.inc -> for.body3 probability is 124 / 128 +; CHECK: edge for.inc -> for.end probability is 0x04000000 / 0x80000000 = 3.12% +; CHECK: edge for.inc -> for.body3 probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] for.end: call void @g3() %inc14 = add nsw i32 %i.019, 1 %exitcond20 = icmp eq i32 %inc14, %a br i1 %exitcond20, label %for.end15, label %for.body -; CHECK: edge for.end -> for.end15 probability is 4 / 128 -; CHECK: edge for.end -> for.body probability is 124 / 128 +; CHECK: edge for.end -> for.end15 probability is 0x04000000 / 0x80000000 = 3.12% +; CHECK: edge for.end -> for.body probability is 0x7c000000 / 0x80000000 = 96.88% [HOT edge] for.end15: call void @g4() diff --git a/test/Analysis/BranchProbabilityInfo/noreturn.ll b/test/Analysis/BranchProbabilityInfo/noreturn.ll index 8b9ae11f7d35..7098c2f7b8cc 100644 --- a/test/Analysis/BranchProbabilityInfo/noreturn.ll +++ b/test/Analysis/BranchProbabilityInfo/noreturn.ll @@ -8,8 +8,8 @@ define i32 @test1(i32 %a, i32 %b) { entry: %cond = icmp eq i32 %a, 42 br i1 %cond, label %exit, label %abort -; CHECK: edge entry -> exit probability is 1048575 / 1048576 -; CHECK: edge entry -> abort probability is 1 / 1048576 +; CHECK: edge entry -> exit probability is 0x7ffff800 / 0x80000000 = 100.00% [HOT edge] +; CHECK: edge entry -> abort probability is 0x00000800 / 0x80000000 = 0.00% abort: call void @abort() noreturn @@ -26,11 +26,11 @@ entry: i32 2, label %case_b i32 3, label %case_c i32 4, label %case_d] -; CHECK: edge entry -> exit probability is 1048575 / 1048579 -; CHECK: edge entry -> case_a probability is 1 / 1048579 -; CHECK: edge entry -> case_b probability is 1 / 1048579 -; CHECK: edge entry -> case_c probability is 1 / 1048579 -; CHECK: edge entry -> case_d probability is 1 / 1048579 +; CHECK: edge entry -> exit probability is 0x7ffff800 / 0x80000000 = 100.00% [HOT edge] +; CHECK: edge entry -> case_a probability is 0x00000200 / 0x80000000 = 0.00% +; CHECK: edge entry -> case_b probability is 0x00000200 / 0x80000000 = 0.00% +; CHECK: edge entry -> case_c probability is 0x00000200 / 0x80000000 = 0.00% +; CHECK: edge entry -> case_d probability is 0x00000200 / 0x80000000 = 0.00% case_a: br label %case_b @@ -55,14 +55,14 @@ define i32 @test3(i32 %a, i32 %b) { entry: %cond1 = icmp eq i32 %a, 42 br i1 %cond1, label %exit, label %dom -; CHECK: edge entry -> exit probability is 1048575 / 1048576 -; CHECK: edge entry -> dom probability is 1 / 1048576 +; CHECK: edge entry -> exit probability is 0x7ffff800 / 0x80000000 = 100.00% [HOT edge] +; CHECK: edge entry -> dom probability is 0x00000800 / 0x80000000 = 0.00% dom: %cond2 = icmp ult i32 %a, 42 br i1 %cond2, label %idom1, label %idom2 -; CHECK: edge dom -> idom1 probability is 1 / 2 -; CHECK: edge dom -> idom2 probability is 1 / 2 +; CHECK: edge dom -> idom1 probability is 0x40000000 / 0x80000000 = 50.00% +; CHECK: edge dom -> idom2 probability is 0x40000000 / 0x80000000 = 50.00% idom1: br label %abort @@ -77,3 +77,48 @@ abort: exit: ret i32 %b } + +@_ZTIi = external global i8* + +; CHECK-LABEL: throwSmallException +; CHECK-NOT: invoke i32 @smallFunction +define i32 @throwSmallException(i32 %idx, i32 %limit) #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +entry: + %cmp = icmp sge i32 %idx, %limit + br i1 %cmp, label %if.then, label %if.end +; CHECK: edge entry -> if.then probability is 0x00000800 / 0x80000000 = 0.00% +; CHECK: edge entry -> if.end probability is 0x7ffff800 / 0x80000000 = 100.00% [HOT edge] + +if.then: ; preds = %entry + %exception = call i8* @__cxa_allocate_exception(i64 1) #0 + invoke i32 @smallFunction(i32 %idx) + to label %invoke.cont unwind label %lpad +; CHECK: edge if.then -> invoke.cont probability is 0x7ffff800 / 0x80000000 = 100.00% [HOT edge] +; CHECK: edge if.then -> lpad probability is 0x00000800 / 0x80000000 = 0.00% + +invoke.cont: ; preds = %if.then + call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #1 + unreachable + +lpad: ; preds = %if.then + %ll = landingpad { i8*, i32 } + cleanup + ret i32 %idx + +if.end: ; preds = %entry + ret i32 %idx +} + +@a = global i32 4 +define i32 @smallFunction(i32 %a) { +entry: + %r = load volatile i32, i32* @a + ret i32 %r +} + +attributes #0 = { nounwind } +attributes #1 = { noreturn } + +declare i8* @__cxa_allocate_exception(i64) +declare i32 @__gxx_personality_v0(...) +declare void @__cxa_throw(i8*, i8*, i8*) diff --git a/test/Analysis/BranchProbabilityInfo/pr18705.ll b/test/Analysis/BranchProbabilityInfo/pr18705.ll index aff08a63d506..f5f9612fcdb6 100644 --- a/test/Analysis/BranchProbabilityInfo/pr18705.ll +++ b/test/Analysis/BranchProbabilityInfo/pr18705.ll @@ -4,8 +4,8 @@ ; calcLoopBranchHeuristics should return early without setting the weights. ; calcFloatingPointHeuristics, which is run later, sets the weights. ; -; CHECK: edge while.body -> if.then probability is 20 / 32 = 62.5% -; CHECK: edge while.body -> if.else probability is 12 / 32 = 37.5% +; CHECK: edge while.body -> if.then probability is 0x50000000 / 0x80000000 = 62.50% +; CHECK: edge while.body -> if.else probability is 0x30000000 / 0x80000000 = 37.50% define void @foo1(i32 %n, i32* nocapture %b, i32* nocapture %c, i32* nocapture %d, float* nocapture readonly %f0, float* nocapture readonly %f1) { entry: diff --git a/test/Analysis/BranchProbabilityInfo/pr22718.ll b/test/Analysis/BranchProbabilityInfo/pr22718.ll index 0de4d643c9c9..51bbd13e83c1 100644 --- a/test/Analysis/BranchProbabilityInfo/pr22718.ll +++ b/test/Analysis/BranchProbabilityInfo/pr22718.ll @@ -4,8 +4,8 @@ ; reflected in the probability computation because the weight is larger than ; the branch weight cap (about 2 billion). ; -; CHECK: edge for.body -> if.then probability is 216661881 / 2166666667 = 9.9 -; CHECK: edge for.body -> if.else probability is 1950004786 / 2166666667 = 90.0 +; CHECK: edge for.body -> if.then probability is 0x0cccba45 / 0x80000000 = 10.00% +; CHECK: edge for.body -> if.else probability is 0x733345bb / 0x80000000 = 90.00% [HOT edge] @y = common global i64 0, align 8 @x = common global i64 0, align 8 diff --git a/test/Analysis/CFLAliasAnalysis/arguments-globals.ll b/test/Analysis/CFLAliasAnalysis/arguments-globals.ll index 18bbe8b6b41f..4844577d6fef 100644 --- a/test/Analysis/CFLAliasAnalysis/arguments-globals.ll +++ b/test/Analysis/CFLAliasAnalysis/arguments-globals.ll @@ -3,7 +3,7 @@ ; (Everything should alias everything, because args can alias globals, so the ; aliasing sets should of args+alloca+global should be combined) -; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s ; CHECK: Function: test diff --git a/test/Analysis/CFLAliasAnalysis/basic-interproc.ll b/test/Analysis/CFLAliasAnalysis/basic-interproc.ll index c0a5404eab6e..d6515eb9ebe5 100644 --- a/test/Analysis/CFLAliasAnalysis/basic-interproc.ll +++ b/test/Analysis/CFLAliasAnalysis/basic-interproc.ll @@ -1,7 +1,7 @@ ; This testcase ensures that CFL AA gives conservative answers on variables ; that involve arguments. -; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s ; CHECK: Function: test ; CHECK: 2 Total Alias Queries Performed diff --git a/test/Analysis/CFLAliasAnalysis/branch-alias.ll b/test/Analysis/CFLAliasAnalysis/branch-alias.ll index 8307462928e7..dbbf035f3440 100644 --- a/test/Analysis/CFLAliasAnalysis/branch-alias.ll +++ b/test/Analysis/CFLAliasAnalysis/branch-alias.ll @@ -13,7 +13,7 @@ ; int* ShouldAliasA = *AliasA1; ; } -; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s ; CHECK: Function: ptr_test define void @ptr_test() #0 { diff --git a/test/Analysis/CFLAliasAnalysis/const-expr-gep.ll b/test/Analysis/CFLAliasAnalysis/const-expr-gep.ll index c7ff407db2f6..11b60dd33b55 100644 --- a/test/Analysis/CFLAliasAnalysis/const-expr-gep.ll +++ b/test/Analysis/CFLAliasAnalysis/const-expr-gep.ll @@ -2,7 +2,7 @@ ; resolvable by cfl-aa, but require analysis of getelementptr constant exprs. ; Derived from BasicAA/2003-12-11-ConstExprGEP.ll -; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s %T = type { i32, [10 x i8] } diff --git a/test/Analysis/CFLAliasAnalysis/full-store-partial-alias.ll b/test/Analysis/CFLAliasAnalysis/full-store-partial-alias.ll index adacf048d678..3503e16898c0 100644 --- a/test/Analysis/CFLAliasAnalysis/full-store-partial-alias.ll +++ b/test/Analysis/CFLAliasAnalysis/full-store-partial-alias.ll @@ -1,5 +1,5 @@ -; RUN: opt -S -tbaa -cfl-aa -gvn < %s | FileCheck -check-prefix=CFLAA %s -; RUN: opt -S -tbaa -gvn < %s | FileCheck %s +; RUN: opt -S -disable-basicaa -tbaa -cfl-aa -gvn < %s | FileCheck -check-prefix=CFLAA %s +; RUN: opt -S -disable-basicaa -tbaa -gvn < %s | FileCheck %s ; Adapted from the BasicAA full-store-partial-alias.ll test. ; CFL AA could notice that the store stores to the entire %u object, diff --git a/test/Analysis/CFLAliasAnalysis/gep-signed-arithmetic.ll b/test/Analysis/CFLAliasAnalysis/gep-signed-arithmetic.ll index c2fcf32ce06b..1edbb9fff56b 100644 --- a/test/Analysis/CFLAliasAnalysis/gep-signed-arithmetic.ll +++ b/test/Analysis/CFLAliasAnalysis/gep-signed-arithmetic.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -cfl-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s ; Derived from BasicAA/2010-09-15-GEP-SignedArithmetic.ll target datalayout = "e-p:32:32:32" diff --git a/test/Analysis/CFLAliasAnalysis/multilevel-combine.ll b/test/Analysis/CFLAliasAnalysis/multilevel-combine.ll index e997374e92d9..be671bfc4ca2 100644 --- a/test/Analysis/CFLAliasAnalysis/multilevel-combine.ll +++ b/test/Analysis/CFLAliasAnalysis/multilevel-combine.ll @@ -8,7 +8,7 @@ ; } ; -; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s %T = type { i32, [10 x i8] } diff --git a/test/Analysis/CFLAliasAnalysis/must-and-partial.ll b/test/Analysis/CFLAliasAnalysis/must-and-partial.ll index 9deacf860ed8..5bcc3f991022 100644 --- a/test/Analysis/CFLAliasAnalysis/must-and-partial.ll +++ b/test/Analysis/CFLAliasAnalysis/must-and-partial.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -cfl-aa -aa-eval -print-all-alias-modref-info 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-all-alias-modref-info 2>&1 | FileCheck %s ; When merging MustAlias and PartialAlias, merge to PartialAlias ; instead of MayAlias. diff --git a/test/Analysis/CFLAliasAnalysis/opaque-call-alias.ll b/test/Analysis/CFLAliasAnalysis/opaque-call-alias.ll new file mode 100644 index 000000000000..6121dca1345d --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/opaque-call-alias.ll @@ -0,0 +1,20 @@ +; We previously had a case where we would put results from a no-args call in +; its own stratified set. This would make cases like the one in @test say that +; nothing (except %Escapes and %Arg) can alias + +; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s + +; CHECK: Function: test +; CHECK: MayAlias: i8* %Arg, i8* %Escapes +; CHECK: MayAlias: i8* %Arg, i8* %Retrieved +; CHECK: MayAlias: i8* %Escapes, i8* %Retrieved +define void @test(i8* %Arg) { + %Noalias = alloca i8 + %Escapes = alloca i8 + call void @set_thepointer(i8* %Escapes) + %Retrieved = call i8* @get_thepointer() + ret void +} + +declare void @set_thepointer(i8* %P) +declare i8* @get_thepointer() diff --git a/test/Analysis/CFLAliasAnalysis/va.ll b/test/Analysis/CFLAliasAnalysis/va.ll index 3094cb0967f6..a432cea8a1df 100644 --- a/test/Analysis/CFLAliasAnalysis/va.ll +++ b/test/Analysis/CFLAliasAnalysis/va.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s ; CHECK-LABEL: Function: test1 ; CHECK: 0 no alias responses diff --git a/test/Analysis/CallGraph/non-leaf-intrinsics.ll b/test/Analysis/CallGraph/non-leaf-intrinsics.ll index 11bed6abce60..5caecf7e2244 100644 --- a/test/Analysis/CallGraph/non-leaf-intrinsics.ll +++ b/test/Analysis/CallGraph/non-leaf-intrinsics.ll @@ -1,7 +1,7 @@ ; RUN: opt -S -print-callgraph -disable-output < %s 2>&1 | FileCheck %s declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...) -declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) +declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) define private void @f() { ret void @@ -10,7 +10,7 @@ define private void @f() { define void @calls_statepoint(i8 addrspace(1)* %arg) gc "statepoint-example" { entry: %cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)* - %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @f, i32 0, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) + %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @f, i32 0, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) ret void } diff --git a/test/Analysis/CostModel/AArch64/select.ll b/test/Analysis/CostModel/AArch64/select.ll index 216dc5ddc488..1a1248e661c5 100644 --- a/test/Analysis/CostModel/AArch64/select.ll +++ b/test/Analysis/CostModel/AArch64/select.ll @@ -17,16 +17,16 @@ define void @select() { ; CHECK: cost of 1 {{.*}} select %v6 = select i1 undef, double undef, double undef - ; Vector values - check for vectors that have a high cost because they end up - ; scalarized. - ; CHECK: cost of 320 {{.*}} select + ; CHECK: cost of 16 {{.*}} select %v13b = select <16 x i1> undef, <16 x i16> undef, <16 x i16> undef - ; CHECK: cost of 160 {{.*}} select + ; CHECK: cost of 8 {{.*}} select %v15b = select <8 x i1> undef, <8 x i32> undef, <8 x i32> undef - ; CHECK: cost of 320 {{.*}} select + ; CHECK: cost of 16 {{.*}} select %v15c = select <16 x i1> undef, <16 x i32> undef, <16 x i32> undef + ; Vector values - check for vectors of i64s that have a high cost because + ; they end up scalarized. ; CHECK: cost of 80 {{.*}} select %v16a = select <4 x i1> undef, <4 x i64> undef, <4 x i64> undef ; CHECK: cost of 160 {{.*}} select @@ -34,5 +34,5 @@ define void @select() { ; CHECK: cost of 320 {{.*}} select %v16c = select <16 x i1> undef, <16 x i64> undef, <16 x i64> undef - ret void + ret void } diff --git a/test/Analysis/CostModel/AMDGPU/br.ll b/test/Analysis/CostModel/AMDGPU/br.ll new file mode 100644 index 000000000000..0b9649397563 --- /dev/null +++ b/test/Analysis/CostModel/AMDGPU/br.ll @@ -0,0 +1,45 @@ +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa < %s | FileCheck %s + +; CHECK: 'test_br_cost' +; CHECK: estimated cost of 10 for instruction: br i1 +; CHECK: estimated cost of 10 for instruction: br label +; CHECK: estimated cost of 10 for instruction: ret void +define void @test_br_cost(i32 addrspace(1)* %out, i32 addrspace(1)* %vaddr, i32 %b) #0 { +bb0: + br i1 undef, label %bb1, label %bb2 + +bb1: + %vec = load i32, i32 addrspace(1)* %vaddr + %add = add i32 %vec, %b + store i32 %add, i32 addrspace(1)* %out + br label %bb2 + +bb2: + ret void + +} + +; CHECK: 'test_switch_cost' +; CHECK: Unknown cost for instruction: switch +define void @test_switch_cost(i32 %a) #0 { +entry: + switch i32 %a, label %default [ + i32 0, label %case0 + i32 1, label %case1 + ] + +case0: + store volatile i32 undef, i32 addrspace(1)* undef + ret void + +case1: + store volatile i32 undef, i32 addrspace(1)* undef + ret void + +default: + store volatile i32 undef, i32 addrspace(1)* undef + ret void + +end: + ret void +} diff --git a/test/Analysis/CostModel/AMDGPU/extractelement.ll b/test/Analysis/CostModel/AMDGPU/extractelement.ll new file mode 100644 index 000000000000..c328d7686466 --- /dev/null +++ b/test/Analysis/CostModel/AMDGPU/extractelement.ll @@ -0,0 +1,110 @@ +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa < %s | FileCheck %s + +; CHECK: 'extractelement_v2i32' +; CHECK: estimated cost of 0 for {{.*}} extractelement <2 x i32> +define void @extractelement_v2i32(i32 addrspace(1)* %out, <2 x i32> addrspace(1)* %vaddr) { + %vec = load <2 x i32>, <2 x i32> addrspace(1)* %vaddr + %elt = extractelement <2 x i32> %vec, i32 1 + store i32 %elt, i32 addrspace(1)* %out + ret void +} + +; CHECK: 'extractelement_v2f32' +; CHECK: estimated cost of 0 for {{.*}} extractelement <2 x float> +define void @extractelement_v2f32(float addrspace(1)* %out, <2 x float> addrspace(1)* %vaddr) { + %vec = load <2 x float>, <2 x float> addrspace(1)* %vaddr + %elt = extractelement <2 x float> %vec, i32 1 + store float %elt, float addrspace(1)* %out + ret void +} + +; CHECK: 'extractelement_v3i32' +; CHECK: estimated cost of 0 for {{.*}} extractelement <3 x i32> +define void @extractelement_v3i32(i32 addrspace(1)* %out, <3 x i32> addrspace(1)* %vaddr) { + %vec = load <3 x i32>, <3 x i32> addrspace(1)* %vaddr + %elt = extractelement <3 x i32> %vec, i32 1 + store i32 %elt, i32 addrspace(1)* %out + ret void +} + +; CHECK: 'extractelement_v4i32' +; CHECK: estimated cost of 0 for {{.*}} extractelement <4 x i32> +define void @extractelement_v4i32(i32 addrspace(1)* %out, <4 x i32> addrspace(1)* %vaddr) { + %vec = load <4 x i32>, <4 x i32> addrspace(1)* %vaddr + %elt = extractelement <4 x i32> %vec, i32 1 + store i32 %elt, i32 addrspace(1)* %out + ret void +} + +; CHECK: 'extractelement_v8i32' +; CHECK: estimated cost of 0 for {{.*}} extractelement <8 x i32> +define void @extractelement_v8i32(i32 addrspace(1)* %out, <8 x i32> addrspace(1)* %vaddr) { + %vec = load <8 x i32>, <8 x i32> addrspace(1)* %vaddr + %elt = extractelement <8 x i32> %vec, i32 1 + store i32 %elt, i32 addrspace(1)* %out + ret void +} + +; FIXME: Should be non-0 +; CHECK: 'extractelement_v8i32_dynindex' +; CHECK: estimated cost of 2 for {{.*}} extractelement <8 x i32> +define void @extractelement_v8i32_dynindex(i32 addrspace(1)* %out, <8 x i32> addrspace(1)* %vaddr, i32 %idx) { + %vec = load <8 x i32>, <8 x i32> addrspace(1)* %vaddr + %elt = extractelement <8 x i32> %vec, i32 %idx + store i32 %elt, i32 addrspace(1)* %out + ret void +} + +; CHECK: 'extractelement_v2i64' +; CHECK: estimated cost of 0 for {{.*}} extractelement <2 x i64> +define void @extractelement_v2i64(i64 addrspace(1)* %out, <2 x i64> addrspace(1)* %vaddr) { + %vec = load <2 x i64>, <2 x i64> addrspace(1)* %vaddr + %elt = extractelement <2 x i64> %vec, i64 1 + store i64 %elt, i64 addrspace(1)* %out + ret void +} + +; CHECK: 'extractelement_v3i64' +; CHECK: estimated cost of 0 for {{.*}} extractelement <3 x i64> +define void @extractelement_v3i64(i64 addrspace(1)* %out, <3 x i64> addrspace(1)* %vaddr) { + %vec = load <3 x i64>, <3 x i64> addrspace(1)* %vaddr + %elt = extractelement <3 x i64> %vec, i64 1 + store i64 %elt, i64 addrspace(1)* %out + ret void +} + +; CHECK: 'extractelement_v4i64' +; CHECK: estimated cost of 0 for {{.*}} extractelement <4 x i64> +define void @extractelement_v4i64(i64 addrspace(1)* %out, <4 x i64> addrspace(1)* %vaddr) { + %vec = load <4 x i64>, <4 x i64> addrspace(1)* %vaddr + %elt = extractelement <4 x i64> %vec, i64 1 + store i64 %elt, i64 addrspace(1)* %out + ret void +} + +; CHECK: 'extractelement_v8i64' +; CHECK: estimated cost of 0 for {{.*}} extractelement <8 x i64> +define void @extractelement_v8i64(i64 addrspace(1)* %out, <8 x i64> addrspace(1)* %vaddr) { + %vec = load <8 x i64>, <8 x i64> addrspace(1)* %vaddr + %elt = extractelement <8 x i64> %vec, i64 1 + store i64 %elt, i64 addrspace(1)* %out + ret void +} + +; CHECK: 'extractelement_v4i8' +; CHECK: estimated cost of 0 for {{.*}} extractelement <4 x i8> +define void @extractelement_v4i8(i8 addrspace(1)* %out, <4 x i8> addrspace(1)* %vaddr) { + %vec = load <4 x i8>, <4 x i8> addrspace(1)* %vaddr + %elt = extractelement <4 x i8> %vec, i8 1 + store i8 %elt, i8 addrspace(1)* %out + ret void +} + +; CHECK: 'extractelement_v2i16' +; CHECK: estimated cost of 0 for {{.*}} extractelement <2 x i16> +define void @extractelement_v2i16(i16 addrspace(1)* %out, <2 x i16> addrspace(1)* %vaddr) { + %vec = load <2 x i16>, <2 x i16> addrspace(1)* %vaddr + %elt = extractelement <2 x i16> %vec, i16 1 + store i16 %elt, i16 addrspace(1)* %out + ret void +} diff --git a/test/Analysis/CostModel/AMDGPU/lit.local.cfg b/test/Analysis/CostModel/AMDGPU/lit.local.cfg new file mode 100644 index 000000000000..2a665f06be72 --- /dev/null +++ b/test/Analysis/CostModel/AMDGPU/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'AMDGPU' in config.root.targets: + config.unsupported = True diff --git a/test/Analysis/CostModel/ARM/cast.ll b/test/Analysis/CostModel/ARM/cast.ll index 18d6e841433f..21e292822099 100644 --- a/test/Analysis/CostModel/ARM/cast.ll +++ b/test/Analysis/CostModel/ARM/cast.ll @@ -5,543 +5,544 @@ target triple = "thumbv7-apple-ios6.0.0" define i32 @casts() { ; -- scalars -- - ; CHECK: cost of 1 {{.*}} sext + ; CHECK: Found an estimated cost of 1 for instruction: %r0 = sext i1 undef to i8 %r0 = sext i1 undef to i8 - ; CHECK: cost of 1 {{.*}} zext + ; CHECK: Found an estimated cost of 1 for instruction: %r1 = zext i1 undef to i8 %r1 = zext i1 undef to i8 - ; CHECK: cost of 1 {{.*}} sext + ; CHECK: Found an estimated cost of 1 for instruction: %r2 = sext i1 undef to i16 %r2 = sext i1 undef to i16 - ; CHECK: cost of 1 {{.*}} zext + ; CHECK: Found an estimated cost of 1 for instruction: %r3 = zext i1 undef to i16 %r3 = zext i1 undef to i16 - ; CHECK: cost of 1 {{.*}} sext + ; CHECK: Found an estimated cost of 1 for instruction: %r4 = sext i1 undef to i32 %r4 = sext i1 undef to i32 - ; CHECK: cost of 1 {{.*}} zext + ; CHECK: Found an estimated cost of 1 for instruction: %r5 = zext i1 undef to i32 %r5 = zext i1 undef to i32 - ; CHECK: cost of 1 {{.*}} sext + ; CHECK: Found an estimated cost of 1 for instruction: %r6 = sext i1 undef to i64 %r6 = sext i1 undef to i64 - ; CHECK: cost of 1 {{.*}} zext + ; CHECK: Found an estimated cost of 1 for instruction: %r7 = zext i1 undef to i64 %r7 = zext i1 undef to i64 - ; CHECK: cost of 0 {{.*}} trunc + ; CHECK: Found an estimated cost of 0 for instruction: %r8 = trunc i8 undef to i1 %r8 = trunc i8 undef to i1 - ; CHECK: cost of 1 {{.*}} sext + ; CHECK: Found an estimated cost of 1 for instruction: %r9 = sext i8 undef to i16 %r9 = sext i8 undef to i16 - ; CHECK: cost of 1 {{.*}} zext + ; CHECK: Found an estimated cost of 1 for instruction: %r10 = zext i8 undef to i16 %r10 = zext i8 undef to i16 - ; CHECK: cost of 1 {{.*}} sext + ; CHECK: Found an estimated cost of 1 for instruction: %r11 = sext i8 undef to i32 %r11 = sext i8 undef to i32 - ; CHECK: cost of 1 {{.*}} zext + ; CHECK: Found an estimated cost of 1 for instruction: %r12 = zext i8 undef to i32 %r12 = zext i8 undef to i32 - ; CHECK: cost of 1 {{.*}} sext + ; CHECK: Found an estimated cost of 1 for instruction: %r13 = sext i8 undef to i64 %r13 = sext i8 undef to i64 - ; CHECK: cost of 1 {{.*}} zext + ; CHECK: Found an estimated cost of 1 for instruction: %r14 = zext i8 undef to i64 %r14 = zext i8 undef to i64 - ; CHECK: cost of 0 {{.*}} trunc + ; CHECK: Found an estimated cost of 0 for instruction: %r15 = trunc i16 undef to i1 %r15 = trunc i16 undef to i1 - ; CHECK: cost of 0 {{.*}} trunc + ; CHECK: Found an estimated cost of 0 for instruction: %r16 = trunc i16 undef to i8 %r16 = trunc i16 undef to i8 - ; CHECK: cost of 1 {{.*}} sext + ; CHECK: Found an estimated cost of 1 for instruction: %r17 = sext i16 undef to i32 %r17 = sext i16 undef to i32 - ; CHECK: cost of 1 {{.*}} zext + ; CHECK: Found an estimated cost of 1 for instruction: %r18 = zext i16 undef to i32 %r18 = zext i16 undef to i32 - ; CHECK: cost of 2 {{.*}} sext + ; CHECK: Found an estimated cost of 2 for instruction: %r19 = sext i16 undef to i64 %r19 = sext i16 undef to i64 - ; CHECK: cost of 1 {{.*}} zext + ; CHECK: Found an estimated cost of 1 for instruction: %r20 = zext i16 undef to i64 %r20 = zext i16 undef to i64 - ; CHECK: cost of 0 {{.*}} trunc + ; CHECK: Found an estimated cost of 0 for instruction: %r21 = trunc i32 undef to i1 %r21 = trunc i32 undef to i1 - ; CHECK: cost of 0 {{.*}} trunc + ; CHECK: Found an estimated cost of 0 for instruction: %r22 = trunc i32 undef to i8 %r22 = trunc i32 undef to i8 - ; CHECK: cost of 0 {{.*}} trunc + ; CHECK: Found an estimated cost of 0 for instruction: %r23 = trunc i32 undef to i16 %r23 = trunc i32 undef to i16 - ; CHECK: cost of 1 {{.*}} sext + ; CHECK: Found an estimated cost of 1 for instruction: %r24 = sext i32 undef to i64 %r24 = sext i32 undef to i64 - ; CHECK: cost of 1 {{.*}} zext + ; CHECK: Found an estimated cost of 1 for instruction: %r25 = zext i32 undef to i64 %r25 = zext i32 undef to i64 - ; CHECK: cost of 0 {{.*}} trunc + ; CHECK: Found an estimated cost of 0 for instruction: %r26 = trunc i64 undef to i1 %r26 = trunc i64 undef to i1 - ; CHECK: cost of 0 {{.*}} trunc + ; CHECK: Found an estimated cost of 0 for instruction: %r27 = trunc i64 undef to i8 %r27 = trunc i64 undef to i8 - ; CHECK: cost of 0 {{.*}} trunc + ; CHECK: Found an estimated cost of 0 for instruction: %r28 = trunc i64 undef to i16 %r28 = trunc i64 undef to i16 - ; CHECK: cost of 0 {{.*}} trunc + ; CHECK: Found an estimated cost of 0 for instruction: %r29 = trunc i64 undef to i32 %r29 = trunc i64 undef to i32 ; -- floating point conversions -- ; Moves between scalar and NEON registers. - ; CHECK: cost of 2 {{.*}} fptoui + ; CHECK: Found an estimated cost of 2 for instruction: %r30 = fptoui float undef to i1 %r30 = fptoui float undef to i1 - ; CHECK: cost of 2 {{.*}} fptosi + ; CHECK: Found an estimated cost of 2 for instruction: %r31 = fptosi float undef to i1 %r31 = fptosi float undef to i1 - ; CHECK: cost of 2 {{.*}} fptoui + ; CHECK: Found an estimated cost of 2 for instruction: %r32 = fptoui float undef to i8 %r32 = fptoui float undef to i8 - ; CHECK: cost of 2 {{.*}} fptosi + ; CHECK: Found an estimated cost of 2 for instruction: %r33 = fptosi float undef to i8 %r33 = fptosi float undef to i8 - ; CHECK: cost of 2 {{.*}} fptoui + ; CHECK: Found an estimated cost of 2 for instruction: %r34 = fptoui float undef to i16 %r34 = fptoui float undef to i16 - ; CHECK: cost of 2 {{.*}} fptosi + ; CHECK: Found an estimated cost of 2 for instruction: %r35 = fptosi float undef to i16 %r35 = fptosi float undef to i16 - ; CHECK: cost of 2 {{.*}} fptoui + ; CHECK: Found an estimated cost of 2 for instruction: %r36 = fptoui float undef to i32 %r36 = fptoui float undef to i32 - ; CHECK: cost of 2 {{.*}} fptosi + ; CHECK: Found an estimated cost of 2 for instruction: %r37 = fptosi float undef to i32 %r37 = fptosi float undef to i32 - ; CHECK: cost of 10 {{.*}} fptoui + ; CHECK: Found an estimated cost of 10 for instruction: %r38 = fptoui float undef to i64 %r38 = fptoui float undef to i64 - ; CHECK: cost of 10 {{.*}} fptosi + ; CHECK: Found an estimated cost of 10 for instruction: %r39 = fptosi float undef to i64 %r39 = fptosi float undef to i64 - ; CHECK: cost of 2 {{.*}} fptoui + ; CHECK: Found an estimated cost of 2 for instruction: %r40 = fptoui double undef to i1 %r40 = fptoui double undef to i1 - ; CHECK: cost of 2 {{.*}} fptosi + ; CHECK: Found an estimated cost of 2 for instruction: %r41 = fptosi double undef to i1 %r41 = fptosi double undef to i1 - ; CHECK: cost of 2 {{.*}} fptoui + ; CHECK: Found an estimated cost of 2 for instruction: %r42 = fptoui double undef to i8 %r42 = fptoui double undef to i8 - ; CHECK: cost of 2 {{.*}} fptosi + ; CHECK: Found an estimated cost of 2 for instruction: %r43 = fptosi double undef to i8 %r43 = fptosi double undef to i8 - ; CHECK: cost of 2 {{.*}} fptoui + ; CHECK: Found an estimated cost of 2 for instruction: %r44 = fptoui double undef to i16 %r44 = fptoui double undef to i16 - ; CHECK: cost of 2 {{.*}} fptosi + ; CHECK: Found an estimated cost of 2 for instruction: %r45 = fptosi double undef to i16 %r45 = fptosi double undef to i16 - ; CHECK: cost of 2 {{.*}} fptoui + ; CHECK: Found an estimated cost of 2 for instruction: %r46 = fptoui double undef to i32 %r46 = fptoui double undef to i32 - ; CHECK: cost of 2 {{.*}} fptosi + ; CHECK: Found an estimated cost of 2 for instruction: %r47 = fptosi double undef to i32 %r47 = fptosi double undef to i32 ; Function call - ; CHECK: cost of 10 {{.*}} fptoui + ; CHECK: Found an estimated cost of 10 for instruction: %r48 = fptoui double undef to i64 %r48 = fptoui double undef to i64 - ; CHECK: cost of 10 {{.*}} fptosi + ; CHECK: Found an estimated cost of 10 for instruction: %r49 = fptosi double undef to i64 %r49 = fptosi double undef to i64 - ; CHECK: cost of 2 {{.*}} sitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r50 = sitofp i1 undef to float %r50 = sitofp i1 undef to float - ; CHECK: cost of 2 {{.*}} uitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r51 = uitofp i1 undef to float %r51 = uitofp i1 undef to float - ; CHECK: cost of 2 {{.*}} sitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r52 = sitofp i1 undef to double %r52 = sitofp i1 undef to double - ; CHECK: cost of 2 {{.*}} uitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r53 = uitofp i1 undef to double %r53 = uitofp i1 undef to double - ; CHECK: cost of 2 {{.*}} sitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r54 = sitofp i8 undef to float %r54 = sitofp i8 undef to float - ; CHECK: cost of 2 {{.*}} uitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r55 = uitofp i8 undef to float %r55 = uitofp i8 undef to float - ; CHECK: cost of 2 {{.*}} sitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r56 = sitofp i8 undef to double %r56 = sitofp i8 undef to double - ; CHECK: cost of 2 {{.*}} uitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r57 = uitofp i8 undef to double %r57 = uitofp i8 undef to double - ; CHECK: cost of 2 {{.*}} sitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r58 = sitofp i16 undef to float %r58 = sitofp i16 undef to float - ; CHECK: cost of 2 {{.*}} uitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r59 = uitofp i16 undef to float %r59 = uitofp i16 undef to float - ; CHECK: cost of 2 {{.*}} sitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r60 = sitofp i16 undef to double %r60 = sitofp i16 undef to double - ; CHECK: cost of 2 {{.*}} uitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r61 = uitofp i16 undef to double %r61 = uitofp i16 undef to double - ; CHECK: cost of 2 {{.*}} sitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r62 = sitofp i32 undef to float %r62 = sitofp i32 undef to float - ; CHECK: cost of 2 {{.*}} uitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r63 = uitofp i32 undef to float %r63 = uitofp i32 undef to float - ; CHECK: cost of 2 {{.*}} sitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r64 = sitofp i32 undef to double %r64 = sitofp i32 undef to double - ; CHECK: cost of 2 {{.*}} uitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r65 = uitofp i32 undef to double %r65 = uitofp i32 undef to double ; Function call - ; CHECK: cost of 10 {{.*}} sitofp + ; CHECK: Found an estimated cost of 10 for instruction: %r66 = sitofp i64 undef to float %r66 = sitofp i64 undef to float - ; CHECK: cost of 10 {{.*}} uitofp + ; CHECK: Found an estimated cost of 10 for instruction: %r67 = uitofp i64 undef to float %r67 = uitofp i64 undef to float - ; CHECK: cost of 10 {{.*}} sitofp + ; CHECK: Found an estimated cost of 10 for instruction: %r68 = sitofp i64 undef to double %r68 = sitofp i64 undef to double - ; CHECK: cost of 10 {{.*}} uitofp + ; CHECK: Found an estimated cost of 10 for instruction: %r69 = uitofp i64 undef to double %r69 = uitofp i64 undef to double - ; CHECK: cost of 3 {{.*}} sext + ; CHECK: Found an estimated cost of 3 for instruction: %r70 = sext <8 x i8> undef to <8 x i32> %r70 = sext <8 x i8> undef to <8 x i32> - ; CHECK: cost of 6 {{.*}} sext + ; CHECK: Found an estimated cost of 6 for instruction: %r71 = sext <16 x i8> undef to <16 x i32> %r71 = sext <16 x i8> undef to <16 x i32> - ; CHECK: cost of 3 {{.*}} zext + ; CHECK: Found an estimated cost of 3 for instruction: %r72 = zext <8 x i8> undef to <8 x i32> %r72 = zext <8 x i8> undef to <8 x i32> - ; CHECK: cost of 6 {{.*}} zext + ; CHECK: Found an estimated cost of 6 for instruction: %r73 = zext <16 x i8> undef to <16 x i32> %r73 = zext <16 x i8> undef to <16 x i32> - ; CHECK: cost of 7 {{.*}} sext + ; CHECK: Found an estimated cost of 7 for instruction: %rext_0 = sext <8 x i8> undef to <8 x i64> %rext_0 = sext <8 x i8> undef to <8 x i64> - ; CHECK: cost of 7 {{.*}} zext + ; CHECK: Found an estimated cost of 7 for instruction: %rext_1 = zext <8 x i8> undef to <8 x i64> %rext_1 = zext <8 x i8> undef to <8 x i64> - ; CHECK: cost of 6 {{.*}} sext + ; CHECK: Found an estimated cost of 6 for instruction: %rext_2 = sext <8 x i16> undef to <8 x i64> %rext_2 = sext <8 x i16> undef to <8 x i64> - ; CHECK: cost of 6 {{.*}} zext + ; CHECK: Found an estimated cost of 6 for instruction: %rext_3 = zext <8 x i16> undef to <8 x i64> %rext_3 = zext <8 x i16> undef to <8 x i64> - ; CHECK: cost of 3 {{.*}} sext + ; CHECK: Found an estimated cost of 3 for instruction: %rext_4 = sext <4 x i16> undef to <4 x i64> %rext_4 = sext <4 x i16> undef to <4 x i64> - ; CHECK: cost of 3 {{.*}} zext + ; CHECK: Found an estimated cost of 3 for instruction: %rext_5 = zext <4 x i16> undef to <4 x i64> %rext_5 = zext <4 x i16> undef to <4 x i64> ; Vector cast cost of instructions lowering the cast to the stack. - ; CHECK: cost of 3 {{.*}} trunc + ; CHECK: Found an estimated cost of 3 for instruction: %r74 = trunc <8 x i32> undef to <8 x i8> %r74 = trunc <8 x i32> undef to <8 x i8> - ; CHECK: cost of 6 {{.*}} trunc + ; CHECK: Found an estimated cost of 6 for instruction: %r75 = trunc <16 x i32> undef to <16 x i8> %r75 = trunc <16 x i32> undef to <16 x i8> ; Floating point truncation costs. - ; CHECK: cost of 1 {{.*}} fptrunc double + ; CHECK: Found an estimated cost of 1 for instruction: %r80 = fptrunc double undef to float %r80 = fptrunc double undef to float - ; CHECK: cost of 2 {{.*}} fptrunc <2 x double + ; CHECK: Found an estimated cost of 2 for instruction: %r81 = fptrunc <2 x double> undef to <2 x float> %r81 = fptrunc <2 x double> undef to <2 x float> - ; CHECK: cost of 4 {{.*}} fptrunc <4 x double + ; CHECK: Found an estimated cost of 4 for instruction: %r82 = fptrunc <4 x double> undef to <4 x float> %r82 = fptrunc <4 x double> undef to <4 x float> - ; CHECK: cost of 8 {{.*}} fptrunc <8 x double + ; CHECK: Found an estimated cost of 8 for instruction: %r83 = fptrunc <8 x double> undef to <8 x float> %r83 = fptrunc <8 x double> undef to <8 x float> - ; CHECK: cost of 16 {{.*}} fptrunc <16 x double + ; CHECK: Found an estimated cost of 16 for instruction: %r84 = fptrunc <16 x double> undef to <16 x float> %r84 = fptrunc <16 x double> undef to <16 x float> ; Floating point extension costs. - ; CHECK: cost of 1 {{.*}} fpext float + ; CHECK: Found an estimated cost of 1 for instruction: %r85 = fpext float undef to double %r85 = fpext float undef to double - ; CHECK: cost of 2 {{.*}} fpext <2 x float + ; CHECK: Found an estimated cost of 2 for instruction: %r86 = fpext <2 x float> undef to <2 x double> %r86 = fpext <2 x float> undef to <2 x double> - ; CHECK: cost of 4 {{.*}} fpext <4 x float + ; CHECK: Found an estimated cost of 4 for instruction: %r87 = fpext <4 x float> undef to <4 x double> %r87 = fpext <4 x float> undef to <4 x double> - ; CHECK: cost of 8 {{.*}} fpext <8 x float + ; CHECK: Found an estimated cost of 8 for instruction: %r88 = fpext <8 x float> undef to <8 x double> %r88 = fpext <8 x float> undef to <8 x double> - ; CHECK: cost of 16 {{.*}} fpext <16 x float + ; CHECK: Found an estimated cost of 16 for instruction: %r89 = fpext <16 x float> undef to <16 x double> %r89 = fpext <16 x float> undef to <16 x double> ;; Floating point to integer vector casts. - ; CHECK: cost of 1 {{.*}} fptoui + ; CHECK: Found an estimated cost of 1 for instruction: %r90 = fptoui <2 x float> undef to <2 x i1> %r90 = fptoui <2 x float> undef to <2 x i1> - ; CHECK: cost of 1 {{.*}} fptosi + ; CHECK: Found an estimated cost of 1 for instruction: %r91 = fptosi <2 x float> undef to <2 x i1> %r91 = fptosi <2 x float> undef to <2 x i1> - ; CHECK: cost of 1 {{.*}} fptoui + ; CHECK: Found an estimated cost of 1 for instruction: %r92 = fptoui <2 x float> undef to <2 x i8> %r92 = fptoui <2 x float> undef to <2 x i8> - ; CHECK: cost of 1 {{.*}} fptosi + ; CHECK: Found an estimated cost of 1 for instruction: %r93 = fptosi <2 x float> undef to <2 x i8> %r93 = fptosi <2 x float> undef to <2 x i8> - ; CHECK: cost of 1 {{.*}} fptoui + ; CHECK: Found an estimated cost of 1 for instruction: %r94 = fptoui <2 x float> undef to <2 x i16> %r94 = fptoui <2 x float> undef to <2 x i16> - ; CHECK: cost of 1 {{.*}} fptosi + ; CHECK: Found an estimated cost of 1 for instruction: %r95 = fptosi <2 x float> undef to <2 x i16> %r95 = fptosi <2 x float> undef to <2 x i16> - ; CHECK: cost of 1 {{.*}} fptoui + ; CHECK: Found an estimated cost of 1 for instruction: %r96 = fptoui <2 x float> undef to <2 x i32> %r96 = fptoui <2 x float> undef to <2 x i32> - ; CHECK: cost of 1 {{.*}} fptosi + ; CHECK: Found an estimated cost of 1 for instruction: %r97 = fptosi <2 x float> undef to <2 x i32> %r97 = fptosi <2 x float> undef to <2 x i32> - ; CHECK: cost of 32 {{.*}} fptoui + ; CHECK: Found an estimated cost of 32 for instruction: %r98 = fptoui <2 x float> undef to <2 x i64> %r98 = fptoui <2 x float> undef to <2 x i64> - ; CHECK: cost of 32 {{.*}} fptosi + ; CHECK: Found an estimated cost of 32 for instruction: %r99 = fptosi <2 x float> undef to <2 x i64> %r99 = fptosi <2 x float> undef to <2 x i64> - ; CHECK: cost of 16 {{.*}} fptoui + ; CHECK: Found an estimated cost of 16 for instruction: %r100 = fptoui <2 x double> undef to <2 x i1> %r100 = fptoui <2 x double> undef to <2 x i1> - ; CHECK: cost of 16 {{.*}} fptosi + ; CHECK: Found an estimated cost of 16 for instruction: %r101 = fptosi <2 x double> undef to <2 x i1> %r101 = fptosi <2 x double> undef to <2 x i1> - ; CHECK: cost of 16 {{.*}} fptoui + ; CHECK: Found an estimated cost of 16 for instruction: %r102 = fptoui <2 x double> undef to <2 x i8> %r102 = fptoui <2 x double> undef to <2 x i8> - ; CHECK: cost of 16 {{.*}} fptosi + ; CHECK: Found an estimated cost of 16 for instruction: %r103 = fptosi <2 x double> undef to <2 x i8> %r103 = fptosi <2 x double> undef to <2 x i8> - ; CHECK: cost of 16 {{.*}} fptoui + ; CHECK: Found an estimated cost of 16 for instruction: %r104 = fptoui <2 x double> undef to <2 x i16> %r104 = fptoui <2 x double> undef to <2 x i16> - ; CHECK: cost of 16 {{.*}} fptosi + ; CHECK: Found an estimated cost of 16 for instruction: %r105 = fptosi <2 x double> undef to <2 x i16> %r105 = fptosi <2 x double> undef to <2 x i16> - ; CHECK: cost of 2 {{.*}} fptoui + ; CHECK: Found an estimated cost of 2 for instruction: %r106 = fptoui <2 x double> undef to <2 x i32> %r106 = fptoui <2 x double> undef to <2 x i32> - ; CHECK: cost of 2 {{.*}} fptosi + ; CHECK: Found an estimated cost of 2 for instruction: %r107 = fptosi <2 x double> undef to <2 x i32> %r107 = fptosi <2 x double> undef to <2 x i32> - ; CHECK: cost of 32 {{.*}} fptoui + ; CHECK: Found an estimated cost of 32 for instruction: %r108 = fptoui <2 x double> undef to <2 x i64> %r108 = fptoui <2 x double> undef to <2 x i64> - ; CHECK: cost of 32 {{.*}} fptosi + ; CHECK: Found an estimated cost of 32 for instruction: %r109 = fptosi <2 x double> undef to <2 x i64> %r109 = fptosi <2 x double> undef to <2 x i64> - ; CHECK: cost of 32 {{.*}} fptoui + ; CHECK: Found an estimated cost of 32 for instruction: %r110 = fptoui <4 x float> undef to <4 x i1> %r110 = fptoui <4 x float> undef to <4 x i1> - ; CHECK: cost of 32 {{.*}} fptosi + ; CHECK: Found an estimated cost of 32 for instruction: %r111 = fptosi <4 x float> undef to <4 x i1> %r111 = fptosi <4 x float> undef to <4 x i1> - ; CHECK: cost of 3 {{.*}} fptoui + ; CHECK: Found an estimated cost of 3 for instruction: %r112 = fptoui <4 x float> undef to <4 x i8> %r112 = fptoui <4 x float> undef to <4 x i8> - ; CHECK: cost of 3 {{.*}} fptosi + ; CHECK: Found an estimated cost of 3 for instruction: %r113 = fptosi <4 x float> undef to <4 x i8> %r113 = fptosi <4 x float> undef to <4 x i8> - ; CHECK: cost of 2 {{.*}} fptoui + + ; CHECK: Found an estimated cost of 2 for instruction: %r114 = fptoui <4 x float> undef to <4 x i16> %r114 = fptoui <4 x float> undef to <4 x i16> - ; CHECK: cost of 2 {{.*}} fptosi + ; CHECK: Found an estimated cost of 2 for instruction: %r115 = fptosi <4 x float> undef to <4 x i16> %r115 = fptosi <4 x float> undef to <4 x i16> - ; CHECK: cost of 1 {{.*}} fptoui + ; CHECK: Found an estimated cost of 1 for instruction: %r116 = fptoui <4 x float> undef to <4 x i32> %r116 = fptoui <4 x float> undef to <4 x i32> - ; CHECK: cost of 1 {{.*}} fptosi + ; CHECK: Found an estimated cost of 1 for instruction: %r117 = fptosi <4 x float> undef to <4 x i32> %r117 = fptosi <4 x float> undef to <4 x i32> - ; CHECK: cost of 64 {{.*}} fptoui + ; CHECK: Found an estimated cost of 64 for instruction: %r118 = fptoui <4 x float> undef to <4 x i64> %r118 = fptoui <4 x float> undef to <4 x i64> - ; CHECK: cost of 64 {{.*}} fptosi + ; CHECK: Found an estimated cost of 64 for instruction: %r119 = fptosi <4 x float> undef to <4 x i64> %r119 = fptosi <4 x float> undef to <4 x i64> - ; CHECK: cost of 32 {{.*}} fptoui + ; CHECK: Found an estimated cost of 32 for instruction: %r120 = fptoui <4 x double> undef to <4 x i1> %r120 = fptoui <4 x double> undef to <4 x i1> - ; CHECK: cost of 32 {{.*}} fptosi + ; CHECK: Found an estimated cost of 32 for instruction: %r121 = fptosi <4 x double> undef to <4 x i1> %r121 = fptosi <4 x double> undef to <4 x i1> - ; CHECK: cost of 32 {{.*}} fptoui + ; CHECK: Found an estimated cost of 32 for instruction: %r122 = fptoui <4 x double> undef to <4 x i8> %r122 = fptoui <4 x double> undef to <4 x i8> - ; CHECK: cost of 32 {{.*}} fptosi + ; CHECK: Found an estimated cost of 32 for instruction: %r123 = fptosi <4 x double> undef to <4 x i8> %r123 = fptosi <4 x double> undef to <4 x i8> - ; CHECK: cost of 32 {{.*}} fptoui + ; CHECK: Found an estimated cost of 32 for instruction: %r124 = fptoui <4 x double> undef to <4 x i16> %r124 = fptoui <4 x double> undef to <4 x i16> - ; CHECK: cost of 32 {{.*}} fptosi + ; CHECK: Found an estimated cost of 32 for instruction: %r125 = fptosi <4 x double> undef to <4 x i16> %r125 = fptosi <4 x double> undef to <4 x i16> - ; CHECK: cost of 32 {{.*}} fptoui + ; CHECK: Found an estimated cost of 32 for instruction: %r126 = fptoui <4 x double> undef to <4 x i32> %r126 = fptoui <4 x double> undef to <4 x i32> - ; CHECK: cost of 32 {{.*}} fptosi + ; CHECK: Found an estimated cost of 32 for instruction: %r127 = fptosi <4 x double> undef to <4 x i32> %r127 = fptosi <4 x double> undef to <4 x i32> - ; CHECK: cost of 64 {{.*}} fptoui + ; CHECK: Found an estimated cost of 64 for instruction: %r128 = fptoui <4 x double> undef to <4 x i64> %r128 = fptoui <4 x double> undef to <4 x i64> - ; CHECK: cost of 64 {{.*}} fptosi + ; CHECK: Found an estimated cost of 64 for instruction: %r129 = fptosi <4 x double> undef to <4 x i64> %r129 = fptosi <4 x double> undef to <4 x i64> - ; CHECK: cost of 64 {{.*}} fptoui + ; CHECK: Found an estimated cost of 64 for instruction: %r130 = fptoui <8 x float> undef to <8 x i1> %r130 = fptoui <8 x float> undef to <8 x i1> - ; CHECK: cost of 64 {{.*}} fptosi + ; CHECK: Found an estimated cost of 64 for instruction: %r131 = fptosi <8 x float> undef to <8 x i1> %r131 = fptosi <8 x float> undef to <8 x i1> - ; CHECK: cost of 64 {{.*}} fptoui + ; CHECK: Found an estimated cost of 64 for instruction: %r132 = fptoui <8 x float> undef to <8 x i8> %r132 = fptoui <8 x float> undef to <8 x i8> - ; CHECK: cost of 64 {{.*}} fptosi + ; CHECK: Found an estimated cost of 64 for instruction: %r133 = fptosi <8 x float> undef to <8 x i8> %r133 = fptosi <8 x float> undef to <8 x i8> - ; CHECK: cost of 4 {{.*}} fptoui + ; CHECK: Found an estimated cost of 4 for instruction: %r134 = fptoui <8 x float> undef to <8 x i16> %r134 = fptoui <8 x float> undef to <8 x i16> - ; CHECK: cost of 4 {{.*}} fptosi + ; CHECK: Found an estimated cost of 4 for instruction: %r135 = fptosi <8 x float> undef to <8 x i16> %r135 = fptosi <8 x float> undef to <8 x i16> - ; CHECK: cost of 2 {{.*}} fptoui + ; CHECK: Found an estimated cost of 2 for instruction: %r136 = fptoui <8 x float> undef to <8 x i32> %r136 = fptoui <8 x float> undef to <8 x i32> - ; CHECK: cost of 2 {{.*}} fptosi + ; CHECK: Found an estimated cost of 2 for instruction: %r137 = fptosi <8 x float> undef to <8 x i32> %r137 = fptosi <8 x float> undef to <8 x i32> - ; CHECK: cost of 128 {{.*}} fptoui + ; CHECK: Found an estimated cost of 128 for instruction: %r138 = fptoui <8 x float> undef to <8 x i64> %r138 = fptoui <8 x float> undef to <8 x i64> - ; CHECK: cost of 128 {{.*}} fptosi + ; CHECK: Found an estimated cost of 128 for instruction: %r139 = fptosi <8 x float> undef to <8 x i64> %r139 = fptosi <8 x float> undef to <8 x i64> - ; CHECK: cost of 64 {{.*}} fptoui + ; CHECK: Found an estimated cost of 64 for instruction: %r140 = fptoui <8 x double> undef to <8 x i1> %r140 = fptoui <8 x double> undef to <8 x i1> - ; CHECK: cost of 64 {{.*}} fptosi + ; CHECK: Found an estimated cost of 64 for instruction: %r141 = fptosi <8 x double> undef to <8 x i1> %r141 = fptosi <8 x double> undef to <8 x i1> - ; CHECK: cost of 64 {{.*}} fptoui + ; CHECK: Found an estimated cost of 64 for instruction: %r142 = fptoui <8 x double> undef to <8 x i8> %r142 = fptoui <8 x double> undef to <8 x i8> - ; CHECK: cost of 64 {{.*}} fptosi + ; CHECK: Found an estimated cost of 64 for instruction: %r143 = fptosi <8 x double> undef to <8 x i8> %r143 = fptosi <8 x double> undef to <8 x i8> - ; CHECK: cost of 64 {{.*}} fptoui + ; CHECK: Found an estimated cost of 64 for instruction: %r144 = fptoui <8 x double> undef to <8 x i16> %r144 = fptoui <8 x double> undef to <8 x i16> - ; CHECK: cost of 64 {{.*}} fptosi + ; CHECK: Found an estimated cost of 64 for instruction: %r145 = fptosi <8 x double> undef to <8 x i16> %r145 = fptosi <8 x double> undef to <8 x i16> - ; CHECK: cost of 64 {{.*}} fptoui + ; CHECK: Found an estimated cost of 64 for instruction: %r146 = fptoui <8 x double> undef to <8 x i32> %r146 = fptoui <8 x double> undef to <8 x i32> - ; CHECK: cost of 64 {{.*}} fptosi + ; CHECK: Found an estimated cost of 64 for instruction: %r147 = fptosi <8 x double> undef to <8 x i32> %r147 = fptosi <8 x double> undef to <8 x i32> - ; CHECK: cost of 128 {{.*}} fptoui + ; CHECK: Found an estimated cost of 128 for instruction: %r148 = fptoui <8 x double> undef to <8 x i64> %r148 = fptoui <8 x double> undef to <8 x i64> - ; CHECK: cost of 128 {{.*}} fptosi + ; CHECK: Found an estimated cost of 128 for instruction: %r149 = fptosi <8 x double> undef to <8 x i64> %r149 = fptosi <8 x double> undef to <8 x i64> - ; CHECK: cost of 128 {{.*}} fptoui + ; CHECK: Found an estimated cost of 128 for instruction: %r150 = fptoui <16 x float> undef to <16 x i1> %r150 = fptoui <16 x float> undef to <16 x i1> - ; CHECK: cost of 128 {{.*}} fptosi + ; CHECK: Found an estimated cost of 128 for instruction: %r151 = fptosi <16 x float> undef to <16 x i1> %r151 = fptosi <16 x float> undef to <16 x i1> - ; CHECK: cost of 128 {{.*}} fptoui + ; CHECK: Found an estimated cost of 128 for instruction: %r152 = fptoui <16 x float> undef to <16 x i8> %r152 = fptoui <16 x float> undef to <16 x i8> - ; CHECK: cost of 128 {{.*}} fptosi + ; CHECK: Found an estimated cost of 128 for instruction: %r153 = fptosi <16 x float> undef to <16 x i8> %r153 = fptosi <16 x float> undef to <16 x i8> - ; CHECK: cost of 8 {{.*}} fptoui + ; CHECK: Found an estimated cost of 8 for instruction: %r154 = fptoui <16 x float> undef to <16 x i16> %r154 = fptoui <16 x float> undef to <16 x i16> - ; CHECK: cost of 8 {{.*}} fptosi + ; CHECK: Found an estimated cost of 8 for instruction: %r155 = fptosi <16 x float> undef to <16 x i16> %r155 = fptosi <16 x float> undef to <16 x i16> - ; CHECK: cost of 4 {{.*}} fptoui + ; CHECK: Found an estimated cost of 4 for instruction: %r156 = fptoui <16 x float> undef to <16 x i32> %r156 = fptoui <16 x float> undef to <16 x i32> - ; CHECK: cost of 4 {{.*}} fptosi + ; CHECK: Found an estimated cost of 4 for instruction: %r157 = fptosi <16 x float> undef to <16 x i32> %r157 = fptosi <16 x float> undef to <16 x i32> - ; CHECK: cost of 256 {{.*}} fptoui + ; CHECK: Found an estimated cost of 256 for instruction: %r158 = fptoui <16 x float> undef to <16 x i64> %r158 = fptoui <16 x float> undef to <16 x i64> - ; CHECK: cost of 256 {{.*}} fptosi + ; CHECK: Found an estimated cost of 256 for instruction: %r159 = fptosi <16 x float> undef to <16 x i64> %r159 = fptosi <16 x float> undef to <16 x i64> - ; CHECK: cost of 128 {{.*}} fptoui + ; CHECK: Found an estimated cost of 128 for instruction: %r160 = fptoui <16 x double> undef to <16 x i1> %r160 = fptoui <16 x double> undef to <16 x i1> - ; CHECK: cost of 128 {{.*}} fptosi + ; CHECK: Found an estimated cost of 128 for instruction: %r161 = fptosi <16 x double> undef to <16 x i1> %r161 = fptosi <16 x double> undef to <16 x i1> - ; CHECK: cost of 128 {{.*}} fptoui + ; CHECK: Found an estimated cost of 128 for instruction: %r162 = fptoui <16 x double> undef to <16 x i8> %r162 = fptoui <16 x double> undef to <16 x i8> - ; CHECK: cost of 128 {{.*}} fptosi + ; CHECK: Found an estimated cost of 128 for instruction: %r163 = fptosi <16 x double> undef to <16 x i8> %r163 = fptosi <16 x double> undef to <16 x i8> - ; CHECK: cost of 128 {{.*}} fptoui + ; CHECK: Found an estimated cost of 128 for instruction: %r164 = fptoui <16 x double> undef to <16 x i16> %r164 = fptoui <16 x double> undef to <16 x i16> - ; CHECK: cost of 128 {{.*}} fptosi + ; CHECK: Found an estimated cost of 128 for instruction: %r165 = fptosi <16 x double> undef to <16 x i16> %r165 = fptosi <16 x double> undef to <16 x i16> - ; CHECK: cost of 128 {{.*}} fptoui + ; CHECK: Found an estimated cost of 128 for instruction: %r166 = fptoui <16 x double> undef to <16 x i32> %r166 = fptoui <16 x double> undef to <16 x i32> - ; CHECK: cost of 128 {{.*}} fptosi + ; CHECK: Found an estimated cost of 128 for instruction: %r167 = fptosi <16 x double> undef to <16 x i32> %r167 = fptosi <16 x double> undef to <16 x i32> - ; CHECK: cost of 256 {{.*}} fptoui + ; CHECK: Found an estimated cost of 256 for instruction: %r168 = fptoui <16 x double> undef to <16 x i64> %r168 = fptoui <16 x double> undef to <16 x i64> - ; CHECK: cost of 256 {{.*}} fptosi + ; CHECK: Found an estimated cost of 256 for instruction: %r169 = fptosi <16 x double> undef to <16 x i64> %r169 = fptosi <16 x double> undef to <16 x i64> - ; CHECK: cost of 8 {{.*}} uitofp + ; CHECK: Found an estimated cost of 12 for instruction: %r170 = uitofp <2 x i1> undef to <2 x float> %r170 = uitofp <2 x i1> undef to <2 x float> - ; CHECK: cost of 8 {{.*}} sitofp + ; CHECK: Found an estimated cost of 12 for instruction: %r171 = sitofp <2 x i1> undef to <2 x float> %r171 = sitofp <2 x i1> undef to <2 x float> - ; CHECK: cost of 3 {{.*}} uitofp + ; CHECK: Found an estimated cost of 3 for instruction: %r172 = uitofp <2 x i8> undef to <2 x float> %r172 = uitofp <2 x i8> undef to <2 x float> - ; CHECK: cost of 3 {{.*}} sitofp + ; CHECK: Found an estimated cost of 3 for instruction: %r173 = sitofp <2 x i8> undef to <2 x float> %r173 = sitofp <2 x i8> undef to <2 x float> - ; CHECK: cost of 2 {{.*}} uitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r174 = uitofp <2 x i16> undef to <2 x float> %r174 = uitofp <2 x i16> undef to <2 x float> - ; CHECK: cost of 2 {{.*}} sitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r175 = sitofp <2 x i16> undef to <2 x float> %r175 = sitofp <2 x i16> undef to <2 x float> - ; CHECK: cost of 1 {{.*}} uitofp + ; CHECK: Found an estimated cost of 1 for instruction: %r176 = uitofp <2 x i32> undef to <2 x float> %r176 = uitofp <2 x i32> undef to <2 x float> - ; CHECK: cost of 1 {{.*}} sitofp + ; CHECK: Found an estimated cost of 1 for instruction: %r177 = sitofp <2 x i32> undef to <2 x float> %r177 = sitofp <2 x i32> undef to <2 x float> - ; CHECK: cost of 24 {{.*}} uitofp + ; CHECK: Found an estimated cost of 28 for instruction: %r178 = uitofp <2 x i64> undef to <2 x float> %r178 = uitofp <2 x i64> undef to <2 x float> - ; CHECK: cost of 24 {{.*}} sitofp + ; CHECK: Found an estimated cost of 28 for instruction: %r179 = sitofp <2 x i64> undef to <2 x float> %r179 = sitofp <2 x i64> undef to <2 x float> - ; CHECK: cost of 8 {{.*}} uitofp + ; CHECK: Found an estimated cost of 8 for instruction: %r180 = uitofp <2 x i1> undef to <2 x double> %r180 = uitofp <2 x i1> undef to <2 x double> - ; CHECK: cost of 8 {{.*}} sitofp + ; CHECK: Found an estimated cost of 8 for instruction: %r181 = sitofp <2 x i1> undef to <2 x double> %r181 = sitofp <2 x i1> undef to <2 x double> - ; CHECK: cost of 4 {{.*}} uitofp + ; CHECK: Found an estimated cost of 4 for instruction: %r182 = uitofp <2 x i8> undef to <2 x double> %r182 = uitofp <2 x i8> undef to <2 x double> - ; CHECK: cost of 4 {{.*}} sitofp + ; CHECK: Found an estimated cost of 4 for instruction: %r183 = sitofp <2 x i8> undef to <2 x double> %r183 = sitofp <2 x i8> undef to <2 x double> - ; CHECK: cost of 3 {{.*}} uitofp + ; CHECK: Found an estimated cost of 3 for instruction: %r184 = uitofp <2 x i16> undef to <2 x double> %r184 = uitofp <2 x i16> undef to <2 x double> - ; CHECK: cost of 3 {{.*}} sitofp + ; CHECK: Found an estimated cost of 3 for instruction: %r185 = sitofp <2 x i16> undef to <2 x double> %r185 = sitofp <2 x i16> undef to <2 x double> - ; CHECK: cost of 2 {{.*}} uitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r186 = uitofp <2 x i32> undef to <2 x double> %r186 = uitofp <2 x i32> undef to <2 x double> - ; CHECK: cost of 2 {{.*}} sitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r187 = sitofp <2 x i32> undef to <2 x double> %r187 = sitofp <2 x i32> undef to <2 x double> - ; CHECK: cost of 24 {{.*}} uitofp + ; CHECK: Found an estimated cost of 24 for instruction: %r188 = uitofp <2 x i64> undef to <2 x double> %r188 = uitofp <2 x i64> undef to <2 x double> - ; CHECK: cost of 24 {{.*}} sitofp + ; CHECK: Found an estimated cost of 24 for instruction: %r189 = sitofp <2 x i64> undef to <2 x double> %r189 = sitofp <2 x i64> undef to <2 x double> - ; CHECK: cost of 3 {{.*}} uitofp + ; CHECK: Found an estimated cost of 3 for instruction: %r190 = uitofp <4 x i1> undef to <4 x float> %r190 = uitofp <4 x i1> undef to <4 x float> - ; CHECK: cost of 3 {{.*}} sitofp + ; CHECK: Found an estimated cost of 3 for instruction: %r191 = sitofp <4 x i1> undef to <4 x float> %r191 = sitofp <4 x i1> undef to <4 x float> - ; CHECK: cost of 3 {{.*}} uitofp + ; CHECK: Found an estimated cost of 3 for instruction: %r192 = uitofp <4 x i8> undef to <4 x float> %r192 = uitofp <4 x i8> undef to <4 x float> - ; CHECK: cost of 3 {{.*}} sitofp + ; CHECK: Found an estimated cost of 3 for instruction: %r193 = sitofp <4 x i8> undef to <4 x float> %r193 = sitofp <4 x i8> undef to <4 x float> - ; CHECK: cost of 2 {{.*}} uitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r194 = uitofp <4 x i16> undef to <4 x float> %r194 = uitofp <4 x i16> undef to <4 x float> - ; CHECK: cost of 2 {{.*}} sitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r195 = sitofp <4 x i16> undef to <4 x float> %r195 = sitofp <4 x i16> undef to <4 x float> - ; CHECK: cost of 1 {{.*}} uitofp + ; CHECK: Found an estimated cost of 1 for instruction: %r196 = uitofp <4 x i32> undef to <4 x float> %r196 = uitofp <4 x i32> undef to <4 x float> - ; CHECK: cost of 1 {{.*}} sitofp + ; CHECK: Found an estimated cost of 1 for instruction: %r197 = sitofp <4 x i32> undef to <4 x float> %r197 = sitofp <4 x i32> undef to <4 x float> - ; CHECK: cost of 48 {{.*}} uitofp + ; CHECK: Found an estimated cost of 56 for instruction: %r198 = uitofp <4 x i64> undef to <4 x float> %r198 = uitofp <4 x i64> undef to <4 x float> - ; CHECK: cost of 48 {{.*}} sitofp + ; CHECK: Found an estimated cost of 56 for instruction: %r199 = sitofp <4 x i64> undef to <4 x float> %r199 = sitofp <4 x i64> undef to <4 x float> - ; CHECK: cost of 16 {{.*}} uitofp + ; CHECK: Found an estimated cost of 16 for instruction: %r200 = uitofp <4 x i1> undef to <4 x double> %r200 = uitofp <4 x i1> undef to <4 x double> - ; CHECK: cost of 16 {{.*}} sitofp + ; CHECK: Found an estimated cost of 16 for instruction: %r201 = sitofp <4 x i1> undef to <4 x double> %r201 = sitofp <4 x i1> undef to <4 x double> - ; CHECK: cost of 16 {{.*}} uitofp + ; CHECK: Found an estimated cost of 16 for instruction: %r202 = uitofp <4 x i8> undef to <4 x double> %r202 = uitofp <4 x i8> undef to <4 x double> - ; CHECK: cost of 16 {{.*}} sitofp + ; CHECK: Found an estimated cost of 16 for instruction: %r203 = sitofp <4 x i8> undef to <4 x double> %r203 = sitofp <4 x i8> undef to <4 x double> - ; CHECK: cost of 16 {{.*}} uitofp + ; CHECK: Found an estimated cost of 16 for instruction: %r204 = uitofp <4 x i16> undef to <4 x double> %r204 = uitofp <4 x i16> undef to <4 x double> - ; CHECK: cost of 16 {{.*}} sitofp + ; CHECK: Found an estimated cost of 16 for instruction: %r205 = sitofp <4 x i16> undef to <4 x double> %r205 = sitofp <4 x i16> undef to <4 x double> - ; CHECK: cost of 16 {{.*}} uitofp + ; CHECK: Found an estimated cost of 16 for instruction: %r206 = uitofp <4 x i32> undef to <4 x double> %r206 = uitofp <4 x i32> undef to <4 x double> - ; CHECK: cost of 16 {{.*}} sitofp + ; CHECK: Found an estimated cost of 16 for instruction: %r207 = sitofp <4 x i32> undef to <4 x double> %r207 = sitofp <4 x i32> undef to <4 x double> - ; CHECK: cost of 48 {{.*}} uitofp + ; CHECK: Found an estimated cost of 48 for instruction: %r208 = uitofp <4 x i64> undef to <4 x double> %r208 = uitofp <4 x i64> undef to <4 x double> - ; CHECK: cost of 48 {{.*}} sitofp + ; CHECK: Found an estimated cost of 48 for instruction: %r209 = sitofp <4 x i64> undef to <4 x double> %r209 = sitofp <4 x i64> undef to <4 x double> - ; CHECK: cost of 32 {{.*}} uitofp + ; CHECK: Found an estimated cost of 48 for instruction: %r210 = uitofp <8 x i1> undef to <8 x float> %r210 = uitofp <8 x i1> undef to <8 x float> - ; CHECK: cost of 32 {{.*}} sitofp + ; CHECK: Found an estimated cost of 48 for instruction: %r211 = sitofp <8 x i1> undef to <8 x float> %r211 = sitofp <8 x i1> undef to <8 x float> - ; CHECK: cost of 32 {{.*}} uitofp + ; CHECK: Found an estimated cost of 48 for instruction: %r212 = uitofp <8 x i8> undef to <8 x float> %r212 = uitofp <8 x i8> undef to <8 x float> - ; CHECK: cost of 32 {{.*}} sitofp + ; CHECK: Found an estimated cost of 48 for instruction: %r213 = sitofp <8 x i8> undef to <8 x float> %r213 = sitofp <8 x i8> undef to <8 x float> - ; CHECK: cost of 4 {{.*}} uitofp + ; CHECK: Found an estimated cost of 4 for instruction: %r214 = uitofp <8 x i16> undef to <8 x float> %r214 = uitofp <8 x i16> undef to <8 x float> - ; CHECK: cost of 4 {{.*}} sitofp + ; CHECK: Found an estimated cost of 4 for instruction: %r215 = sitofp <8 x i16> undef to <8 x float> %r215 = sitofp <8 x i16> undef to <8 x float> - ; CHECK: cost of 2 {{.*}} uitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r216 = uitofp <8 x i32> undef to <8 x float> %r216 = uitofp <8 x i32> undef to <8 x float> - ; CHECK: cost of 2 {{.*}} sitofp + ; CHECK: Found an estimated cost of 2 for instruction: %r217 = sitofp <8 x i32> undef to <8 x float> %r217 = sitofp <8 x i32> undef to <8 x float> - ; CHECK: cost of 96 {{.*}} uitofp + ; CHECK: Found an estimated cost of 112 for instruction: %r218 = uitofp <8 x i64> undef to <8 x float> %r218 = uitofp <8 x i64> undef to <8 x float> - ; CHECK: cost of 96 {{.*}} sitofp + ; CHECK: Found an estimated cost of 112 for instruction: %r219 = sitofp <8 x i64> undef to <8 x float> %r219 = sitofp <8 x i64> undef to <8 x float> - ; CHECK: cost of 32 {{.*}} uitofp + ; CHECK: Found an estimated cost of 32 for instruction: %r220 = uitofp <8 x i1> undef to <8 x double> %r220 = uitofp <8 x i1> undef to <8 x double> - ; CHECK: cost of 32 {{.*}} sitofp + ; CHECK: Found an estimated cost of 32 for instruction: %r221 = sitofp <8 x i1> undef to <8 x double> %r221 = sitofp <8 x i1> undef to <8 x double> - ; CHECK: cost of 32 {{.*}} uitofp + ; CHECK: Found an estimated cost of 32 for instruction: %r222 = uitofp <8 x i8> undef to <8 x double> %r222 = uitofp <8 x i8> undef to <8 x double> - ; CHECK: cost of 32 {{.*}} sitofp + ; CHECK: Found an estimated cost of 32 for instruction: %r223 = sitofp <8 x i8> undef to <8 x double> %r223 = sitofp <8 x i8> undef to <8 x double> - ; CHECK: cost of 32 {{.*}} uitofp + ; CHECK: Found an estimated cost of 32 for instruction: %r224 = uitofp <8 x i16> undef to <8 x double> %r224 = uitofp <8 x i16> undef to <8 x double> - ; CHECK: cost of 32 {{.*}} sitofp + ; CHECK: Found an estimated cost of 32 for instruction: %r225 = sitofp <8 x i16> undef to <8 x double> %r225 = sitofp <8 x i16> undef to <8 x double> - ; CHECK: cost of 32 {{.*}} uitofp + ; CHECK: Found an estimated cost of 32 for instruction: %r226 = uitofp <8 x i16> undef to <8 x double> %r226 = uitofp <8 x i16> undef to <8 x double> - ; CHECK: cost of 32 {{.*}} sitofp + ; CHECK: Found an estimated cost of 32 for instruction: %r227 = sitofp <8 x i16> undef to <8 x double> %r227 = sitofp <8 x i16> undef to <8 x double> - ; CHECK: cost of 96 {{.*}} uitofp + ; CHECK: Found an estimated cost of 96 for instruction: %r228 = uitofp <8 x i64> undef to <8 x double> %r228 = uitofp <8 x i64> undef to <8 x double> - ; CHECK: cost of 96 {{.*}} sitofp + ; CHECK: Found an estimated cost of 96 for instruction: %r229 = sitofp <8 x i64> undef to <8 x double> %r229 = sitofp <8 x i64> undef to <8 x double> - ; CHECK: cost of 64 {{.*}} uitofp + ; CHECK: Found an estimated cost of 96 for instruction: %r230 = uitofp <16 x i1> undef to <16 x float> %r230 = uitofp <16 x i1> undef to <16 x float> - ; CHECK: cost of 64 {{.*}} sitofp + ; CHECK: Found an estimated cost of 96 for instruction: %r231 = sitofp <16 x i1> undef to <16 x float> %r231 = sitofp <16 x i1> undef to <16 x float> - ; CHECK: cost of 64 {{.*}} uitofp + ; CHECK: Found an estimated cost of 96 for instruction: %r232 = uitofp <16 x i8> undef to <16 x float> %r232 = uitofp <16 x i8> undef to <16 x float> - ; CHECK: cost of 64 {{.*}} sitofp + ; CHECK: Found an estimated cost of 96 for instruction: %r233 = sitofp <16 x i8> undef to <16 x float> %r233 = sitofp <16 x i8> undef to <16 x float> - ; CHECK: cost of 8 {{.*}} uitofp + ; CHECK: Found an estimated cost of 8 for instruction: %r234 = uitofp <16 x i16> undef to <16 x float> %r234 = uitofp <16 x i16> undef to <16 x float> - ; CHECK: cost of 8 {{.*}} sitofp + ; CHECK: Found an estimated cost of 8 for instruction: %r235 = sitofp <16 x i16> undef to <16 x float> %r235 = sitofp <16 x i16> undef to <16 x float> - ; CHECK: cost of 4 {{.*}} uitofp + ; CHECK: Found an estimated cost of 4 for instruction: %r236 = uitofp <16 x i32> undef to <16 x float> %r236 = uitofp <16 x i32> undef to <16 x float> - ; CHECK: cost of 4 {{.*}} sitofp + ; CHECK: Found an estimated cost of 4 for instruction: %r237 = sitofp <16 x i32> undef to <16 x float> %r237 = sitofp <16 x i32> undef to <16 x float> - ; CHECK: cost of 192 {{.*}} uitofp + ; CHECK: Found an estimated cost of 224 for instruction: %r238 = uitofp <16 x i64> undef to <16 x float> %r238 = uitofp <16 x i64> undef to <16 x float> - ; CHECK: cost of 192 {{.*}} sitofp + ; CHECK: Found an estimated cost of 224 for instruction: %r239 = sitofp <16 x i64> undef to <16 x float> %r239 = sitofp <16 x i64> undef to <16 x float> - ; CHECK: cost of 64 {{.*}} uitofp + ; CHECK: Found an estimated cost of 64 for instruction: %r240 = uitofp <16 x i1> undef to <16 x double> %r240 = uitofp <16 x i1> undef to <16 x double> - ; CHECK: cost of 64 {{.*}} sitofp + ; CHECK: Found an estimated cost of 64 for instruction: %r241 = sitofp <16 x i1> undef to <16 x double> %r241 = sitofp <16 x i1> undef to <16 x double> - ; CHECK: cost of 64 {{.*}} uitofp + ; CHECK: Found an estimated cost of 64 for instruction: %r242 = uitofp <16 x i8> undef to <16 x double> %r242 = uitofp <16 x i8> undef to <16 x double> - ; CHECK: cost of 64 {{.*}} sitofp + ; CHECK: Found an estimated cost of 64 for instruction: %r243 = sitofp <16 x i8> undef to <16 x double> %r243 = sitofp <16 x i8> undef to <16 x double> - ; CHECK: cost of 64 {{.*}} uitofp + ; CHECK: Found an estimated cost of 64 for instruction: %r244 = uitofp <16 x i16> undef to <16 x double> %r244 = uitofp <16 x i16> undef to <16 x double> - ; CHECK: cost of 64 {{.*}} sitofp + ; CHECK: Found an estimated cost of 64 for instruction: %r245 = sitofp <16 x i16> undef to <16 x double> %r245 = sitofp <16 x i16> undef to <16 x double> - ; CHECK: cost of 64 {{.*}} uitofp + ; CHECK: Found an estimated cost of 64 for instruction: %r246 = uitofp <16 x i16> undef to <16 x double> %r246 = uitofp <16 x i16> undef to <16 x double> - ; CHECK: cost of 64 {{.*}} sitofp + ; CHECK: Found an estimated cost of 64 for instruction: %r247 = sitofp <16 x i16> undef to <16 x double> %r247 = sitofp <16 x i16> undef to <16 x double> - ; CHECK: cost of 192 {{.*}} uitofp + ; CHECK: Found an estimated cost of 192 for instruction: %r248 = uitofp <16 x i64> undef to <16 x double> %r248 = uitofp <16 x i64> undef to <16 x double> - ; CHECK: cost of 192 {{.*}} sitofp + ; CHECK: Found an estimated cost of 192 for instruction: %r249 = sitofp <16 x i64> undef to <16 x double> %r249 = sitofp <16 x i64> undef to <16 x double> - ;CHECK: cost of 0 {{.*}} ret + ; CHECK: Found an estimated cost of 0 for instruction: ret i32 undef ret i32 undef } diff --git a/test/Analysis/CostModel/ARM/gep.ll b/test/Analysis/CostModel/ARM/gep.ll index 624ca113a302..a70d6d42b61b 100644 --- a/test/Analysis/CostModel/ARM/gep.ll +++ b/test/Analysis/CostModel/ARM/gep.ll @@ -3,41 +3,85 @@ target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32" target triple = "thumbv7-apple-ios6.0.0" -define void @test_geps() { - ; Cost of scalar integer geps should be one. We can't always expect it to be - ; folded into the instruction addressing mode. -;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds i8, i8* +define void @test_geps(i32 %i) { + ; GEPs with index 0 are essentially NOOPs. +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds i8, i8* %a0 = getelementptr inbounds i8, i8* undef, i32 0 -;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds i16, i16* +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds i16, i16* %a1 = getelementptr inbounds i16, i16* undef, i32 0 -;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds i32, i32* +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds i32, i32* %a2 = getelementptr inbounds i32, i32* undef, i32 0 - -;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds i64, i64* +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds i64, i64* %a3 = getelementptr inbounds i64, i64* undef, i32 0 - - ; Cost of scalar floating point geps should be one. We cannot fold the address - ; computation. -;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds float, float* +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds float, float* %a4 = getelementptr inbounds float, float* undef, i32 0 -;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds double, double* +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds double, double* %a5 = getelementptr inbounds double, double* undef, i32 0 - - - ; Cost of vector geps should be one. We cannot fold the address computation. -;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds <4 x i8>, <4 x i8>* +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x i8>, <4 x i8>* %a7 = getelementptr inbounds <4 x i8>, <4 x i8>* undef, i32 0 -;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds <4 x i16>, <4 x i16>* +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x i16>, <4 x i16>* %a8 = getelementptr inbounds <4 x i16>, <4 x i16>* undef, i32 0 -;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds <4 x i32>, <4 x i32>* +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x i32>, <4 x i32>* %a9 = getelementptr inbounds <4 x i32>, <4 x i32>* undef, i32 0 -;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds <4 x i64>, <4 x i64>* +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x i64>, <4 x i64>* %a10 = getelementptr inbounds <4 x i64>, <4 x i64>* undef, i32 0 -;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds <4 x float>, <4 x float>* +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x float>, <4 x float>* %a11 = getelementptr inbounds <4 x float>, <4 x float>* undef, i32 0 -;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds <4 x double>, <4 x double>* +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x double>, <4 x double>* %a12 = getelementptr inbounds <4 x double>, <4 x double>* undef, i32 0 + ; Cost of GEPs is one if we cannot fold the address computation. +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds i8, i8* + %b0 = getelementptr inbounds i8, i8* undef, i32 1024 +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds i16, i16* + %b1 = getelementptr inbounds i16, i16* undef, i32 1024 + ; Thumb-2 cannot fold offset >= 2^12 into address computation. +;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds i32, i32* + %b2 = getelementptr inbounds i32, i32* undef, i32 1024 +;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds i64, i64* + %b3 = getelementptr inbounds i64, i64* undef, i32 1024 +;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds float, float* + %b4 = getelementptr inbounds float, float* undef, i32 1024 +;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds double, double* + %b5 = getelementptr inbounds double, double* undef, i32 1024 +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x i8>, <4 x i8>* + %b7 = getelementptr inbounds <4 x i8>, <4 x i8>* undef, i32 1 +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x i16>, <4 x i16>* + %b8 = getelementptr inbounds <4 x i16>, <4 x i16>* undef, i32 1 +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x i32>, <4 x i32>* + %b9 = getelementptr inbounds <4 x i32>, <4 x i32>* undef, i32 1 +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x i64>, <4 x i64>* + %b10 = getelementptr inbounds <4 x i64>, <4 x i64>* undef, i32 1 +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x float>, <4 x float>* + %b11 = getelementptr inbounds <4 x float>, <4 x float>* undef, i32 1 +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x double>, <4 x double>* + %b12 = getelementptr inbounds <4 x double>, <4 x double>* undef, i32 1 + +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds i8, i8* + %c0 = getelementptr inbounds i8, i8* undef, i32 %i +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds i16, i16* + %c1 = getelementptr inbounds i16, i16* undef, i32 %i +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds i32, i32* + %c2 = getelementptr inbounds i32, i32* undef, i32 %i +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds i64, i64* + %c3 = getelementptr inbounds i64, i64* undef, i32 %i +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds float, float* + %c4 = getelementptr inbounds float, float* undef, i32 %i +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds double, double* + %c5 = getelementptr inbounds double, double* undef, i32 %i +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x i8>, <4 x i8>* + %c7 = getelementptr inbounds <4 x i8>, <4 x i8>* undef, i32 %i +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x i16>, <4 x i16>* + %c8 = getelementptr inbounds <4 x i16>, <4 x i16>* undef, i32 %i + ; Thumb-2 cannot fold scales larger than 8 to address computation. +;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds <4 x i32>, <4 x i32>* + %c9 = getelementptr inbounds <4 x i32>, <4 x i32>* undef, i32 %i +;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds <4 x i64>, <4 x i64>* + %c10 = getelementptr inbounds <4 x i64>, <4 x i64>* undef, i32 %i +;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds <4 x float>, <4 x float>* + %c11 = getelementptr inbounds <4 x float>, <4 x float>* undef, i32 %i +;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds <4 x double>, <4 x double>* + %c12 = getelementptr inbounds <4 x double>, <4 x double>* undef, i32 %i ret void } diff --git a/test/Analysis/CostModel/ARM/select.ll b/test/Analysis/CostModel/ARM/select.ll index 21eef83c4bbe..57e1418a3f28 100644 --- a/test/Analysis/CostModel/ARM/select.ll +++ b/test/Analysis/CostModel/ARM/select.ll @@ -34,16 +34,16 @@ define void @casts() { %v12 = select <4 x i1> undef, <4 x i16> undef, <4 x i16> undef ; CHECK: cost of 1 {{.*}} select %v13 = select <8 x i1> undef, <8 x i16> undef, <8 x i16> undef - ; CHECK: cost of 40 {{.*}} select + ; CHECK: cost of 2 {{.*}} select %v13b = select <16 x i1> undef, <16 x i16> undef, <16 x i16> undef ; CHECK: cost of 1 {{.*}} select %v14 = select <2 x i1> undef, <2 x i32> undef, <2 x i32> undef ; CHECK: cost of 1 {{.*}} select %v15 = select <4 x i1> undef, <4 x i32> undef, <4 x i32> undef - ; CHECK: cost of 41 {{.*}} select + ; CHECK: cost of 2 {{.*}} select %v15b = select <8 x i1> undef, <8 x i32> undef, <8 x i32> undef - ; CHECK: cost of 82 {{.*}} select + ; CHECK: cost of 4 {{.*}} select %v15c = select <16 x i1> undef, <16 x i32> undef, <16 x i32> undef ; CHECK: cost of 1 {{.*}} select diff --git a/test/Analysis/CostModel/PowerPC/load_store.ll b/test/Analysis/CostModel/PowerPC/load_store.ll index 1e50f1651e0a..0a568b88e726 100644 --- a/test/Analysis/CostModel/PowerPC/load_store.ll +++ b/test/Analysis/CostModel/PowerPC/load_store.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -cost-model -analyze -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 | FileCheck %s +; RUN: opt < %s -cost-model -analyze -mtriple=powerpc64-unknown-linux-gnu -mcpu=g5 | FileCheck %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-f128:128:128-v128:128:128-n32:64" target triple = "powerpc64-unknown-linux-gnu" @@ -34,7 +34,7 @@ define i32 @loads(i32 %arg) { ; CHECK: cost of 48 {{.*}} load load <4 x i16>, <4 x i16>* undef, align 2 - ; CHECK: cost of 1 {{.*}} load + ; CHECK: cost of 2 {{.*}} load load <4 x i32>, <4 x i32>* undef, align 4 ; CHECK: cost of 46 {{.*}} load diff --git a/test/Analysis/CostModel/PowerPC/unal-vec-ldst.ll b/test/Analysis/CostModel/PowerPC/unal-vec-ldst.ll new file mode 100644 index 000000000000..3b1bc3b3fdbc --- /dev/null +++ b/test/Analysis/CostModel/PowerPC/unal-vec-ldst.ll @@ -0,0 +1,404 @@ +; RUN: opt < %s -cost-model -analyze | FileCheck %s +target datalayout = "E-m:e-i64:64-n32:64" +target triple = "powerpc64-unknown-linux-gnu" + +define <16 x i8> @test_l_v16i8(<16 x i8>* %p) #0 { +entry: + %r = load <16 x i8>, <16 x i8>* %p, align 1 + ret <16 x i8> %r + +; CHECK-LABEL: test_l_v16i8 +; CHECK: cost of 2 for instruction: %r = load <16 x i8>, <16 x i8>* %p, align 1 +} + +define <32 x i8> @test_l_v32i8(<32 x i8>* %p) #0 { +entry: + %r = load <32 x i8>, <32 x i8>* %p, align 1 + ret <32 x i8> %r + +; CHECK-LABEL: test_l_v32i8 +; CHECK: cost of 4 for instruction: %r = load <32 x i8>, <32 x i8>* %p, align 1 +} + +define <8 x i16> @test_l_v8i16(<8 x i16>* %p) #0 { +entry: + %r = load <8 x i16>, <8 x i16>* %p, align 2 + ret <8 x i16> %r + +; CHECK-LABEL: test_l_v8i16 +; CHECK: cost of 2 for instruction: %r = load <8 x i16>, <8 x i16>* %p, align 2 +} + +define <16 x i16> @test_l_v16i16(<16 x i16>* %p) #0 { +entry: + %r = load <16 x i16>, <16 x i16>* %p, align 2 + ret <16 x i16> %r + +; CHECK-LABEL: test_l_v16i16 +; CHECK: cost of 4 for instruction: %r = load <16 x i16>, <16 x i16>* %p, align 2 +} + +define <4 x i32> @test_l_v4i32(<4 x i32>* %p) #0 { +entry: + %r = load <4 x i32>, <4 x i32>* %p, align 4 + ret <4 x i32> %r + +; CHECK-LABEL: test_l_v4i32 +; CHECK: cost of 2 for instruction: %r = load <4 x i32>, <4 x i32>* %p, align 4 +} + +define <8 x i32> @test_l_v8i32(<8 x i32>* %p) #0 { +entry: + %r = load <8 x i32>, <8 x i32>* %p, align 4 + ret <8 x i32> %r + +; CHECK-LABEL: test_l_v8i32 +; CHECK: cost of 4 for instruction: %r = load <8 x i32>, <8 x i32>* %p, align 4 +} + +define <2 x i64> @test_l_v2i64(<2 x i64>* %p) #0 { +entry: + %r = load <2 x i64>, <2 x i64>* %p, align 8 + ret <2 x i64> %r + +; CHECK-LABEL: test_l_v2i64 +; CHECK: cost of 1 for instruction: %r = load <2 x i64>, <2 x i64>* %p, align 8 +} + +define <4 x i64> @test_l_v4i64(<4 x i64>* %p) #0 { +entry: + %r = load <4 x i64>, <4 x i64>* %p, align 8 + ret <4 x i64> %r + +; CHECK-LABEL: test_l_v4i64 +; CHECK: cost of 2 for instruction: %r = load <4 x i64>, <4 x i64>* %p, align 8 +} + +define <4 x float> @test_l_v4float(<4 x float>* %p) #0 { +entry: + %r = load <4 x float>, <4 x float>* %p, align 4 + ret <4 x float> %r + +; CHECK-LABEL: test_l_v4float +; CHECK: cost of 2 for instruction: %r = load <4 x float>, <4 x float>* %p, align 4 +} + +define <8 x float> @test_l_v8float(<8 x float>* %p) #0 { +entry: + %r = load <8 x float>, <8 x float>* %p, align 4 + ret <8 x float> %r + +; CHECK-LABEL: test_l_v8float +; CHECK: cost of 4 for instruction: %r = load <8 x float>, <8 x float>* %p, align 4 +} + +define <2 x double> @test_l_v2double(<2 x double>* %p) #0 { +entry: + %r = load <2 x double>, <2 x double>* %p, align 8 + ret <2 x double> %r + +; CHECK-LABEL: test_l_v2double +; CHECK: cost of 1 for instruction: %r = load <2 x double>, <2 x double>* %p, align 8 +} + +define <4 x double> @test_l_v4double(<4 x double>* %p) #0 { +entry: + %r = load <4 x double>, <4 x double>* %p, align 8 + ret <4 x double> %r + +; CHECK-LABEL: test_l_v4double +; CHECK: cost of 2 for instruction: %r = load <4 x double>, <4 x double>* %p, align 8 +} + +define <16 x i8> @test_l_p8v16i8(<16 x i8>* %p) #2 { +entry: + %r = load <16 x i8>, <16 x i8>* %p, align 1 + ret <16 x i8> %r + +; CHECK-LABEL: test_l_p8v16i8 +; CHECK: cost of 1 for instruction: %r = load <16 x i8>, <16 x i8>* %p, align 1 +} + +define <32 x i8> @test_l_p8v32i8(<32 x i8>* %p) #2 { +entry: + %r = load <32 x i8>, <32 x i8>* %p, align 1 + ret <32 x i8> %r + +; CHECK-LABEL: test_l_p8v32i8 +; CHECK: cost of 2 for instruction: %r = load <32 x i8>, <32 x i8>* %p, align 1 +} + +define <8 x i16> @test_l_p8v8i16(<8 x i16>* %p) #2 { +entry: + %r = load <8 x i16>, <8 x i16>* %p, align 2 + ret <8 x i16> %r + +; CHECK-LABEL: test_l_p8v8i16 +; CHECK: cost of 1 for instruction: %r = load <8 x i16>, <8 x i16>* %p, align 2 +} + +define <16 x i16> @test_l_p8v16i16(<16 x i16>* %p) #2 { +entry: + %r = load <16 x i16>, <16 x i16>* %p, align 2 + ret <16 x i16> %r + +; CHECK-LABEL: test_l_p8v16i16 +; CHECK: cost of 2 for instruction: %r = load <16 x i16>, <16 x i16>* %p, align 2 +} + +define <4 x i32> @test_l_p8v4i32(<4 x i32>* %p) #2 { +entry: + %r = load <4 x i32>, <4 x i32>* %p, align 4 + ret <4 x i32> %r + +; CHECK-LABEL: test_l_p8v4i32 +; CHECK: cost of 1 for instruction: %r = load <4 x i32>, <4 x i32>* %p, align 4 +} + +define <8 x i32> @test_l_p8v8i32(<8 x i32>* %p) #2 { +entry: + %r = load <8 x i32>, <8 x i32>* %p, align 4 + ret <8 x i32> %r + +; CHECK-LABEL: test_l_p8v8i32 +; CHECK: cost of 2 for instruction: %r = load <8 x i32>, <8 x i32>* %p, align 4 +} + +define <2 x i64> @test_l_p8v2i64(<2 x i64>* %p) #2 { +entry: + %r = load <2 x i64>, <2 x i64>* %p, align 8 + ret <2 x i64> %r + +; CHECK-LABEL: test_l_p8v2i64 +; CHECK: cost of 1 for instruction: %r = load <2 x i64>, <2 x i64>* %p, align 8 +} + +define <4 x i64> @test_l_p8v4i64(<4 x i64>* %p) #2 { +entry: + %r = load <4 x i64>, <4 x i64>* %p, align 8 + ret <4 x i64> %r + +; CHECK-LABEL: test_l_p8v4i64 +; CHECK: cost of 2 for instruction: %r = load <4 x i64>, <4 x i64>* %p, align 8 +} + +define <4 x float> @test_l_p8v4float(<4 x float>* %p) #2 { +entry: + %r = load <4 x float>, <4 x float>* %p, align 4 + ret <4 x float> %r + +; CHECK-LABEL: test_l_p8v4float +; CHECK: cost of 1 for instruction: %r = load <4 x float>, <4 x float>* %p, align 4 +} + +define <8 x float> @test_l_p8v8float(<8 x float>* %p) #2 { +entry: + %r = load <8 x float>, <8 x float>* %p, align 4 + ret <8 x float> %r + +; CHECK-LABEL: test_l_p8v8float +; CHECK: cost of 2 for instruction: %r = load <8 x float>, <8 x float>* %p, align 4 +} + +define <2 x double> @test_l_p8v2double(<2 x double>* %p) #2 { +entry: + %r = load <2 x double>, <2 x double>* %p, align 8 + ret <2 x double> %r + +; CHECK-LABEL: test_l_p8v2double +; CHECK: cost of 1 for instruction: %r = load <2 x double>, <2 x double>* %p, align 8 +} + +define <4 x double> @test_l_p8v4double(<4 x double>* %p) #2 { +entry: + %r = load <4 x double>, <4 x double>* %p, align 8 + ret <4 x double> %r + +; CHECK-LABEL: test_l_p8v4double +; CHECK: cost of 2 for instruction: %r = load <4 x double>, <4 x double>* %p, align 8 +} + +define <4 x float> @test_l_qv4float(<4 x float>* %p) #1 { +entry: + %r = load <4 x float>, <4 x float>* %p, align 4 + ret <4 x float> %r + +; CHECK-LABEL: test_l_qv4float +; CHECK: cost of 2 for instruction: %r = load <4 x float>, <4 x float>* %p, align 4 +} + +define <8 x float> @test_l_qv8float(<8 x float>* %p) #1 { +entry: + %r = load <8 x float>, <8 x float>* %p, align 4 + ret <8 x float> %r + +; CHECK-LABEL: test_l_qv8float +; CHECK: cost of 4 for instruction: %r = load <8 x float>, <8 x float>* %p, align 4 +} + +define <4 x double> @test_l_qv4double(<4 x double>* %p) #1 { +entry: + %r = load <4 x double>, <4 x double>* %p, align 8 + ret <4 x double> %r + +; CHECK-LABEL: test_l_qv4double +; CHECK: cost of 2 for instruction: %r = load <4 x double>, <4 x double>* %p, align 8 +} + +define <8 x double> @test_l_qv8double(<8 x double>* %p) #1 { +entry: + %r = load <8 x double>, <8 x double>* %p, align 8 + ret <8 x double> %r + +; CHECK-LABEL: test_l_qv8double +; CHECK: cost of 4 for instruction: %r = load <8 x double>, <8 x double>* %p, align 8 +} + +define void @test_s_v16i8(<16 x i8>* %p, <16 x i8> %v) #0 { +entry: + store <16 x i8> %v, <16 x i8>* %p, align 1 + ret void + +; CHECK-LABEL: test_s_v16i8 +; CHECK: cost of 1 for instruction: store <16 x i8> %v, <16 x i8>* %p, align 1 +} + +define void @test_s_v32i8(<32 x i8>* %p, <32 x i8> %v) #0 { +entry: + store <32 x i8> %v, <32 x i8>* %p, align 1 + ret void + +; CHECK-LABEL: test_s_v32i8 +; CHECK: cost of 2 for instruction: store <32 x i8> %v, <32 x i8>* %p, align 1 +} + +define void @test_s_v8i16(<8 x i16>* %p, <8 x i16> %v) #0 { +entry: + store <8 x i16> %v, <8 x i16>* %p, align 2 + ret void + +; CHECK-LABEL: test_s_v8i16 +; CHECK: cost of 1 for instruction: store <8 x i16> %v, <8 x i16>* %p, align 2 +} + +define void @test_s_v16i16(<16 x i16>* %p, <16 x i16> %v) #0 { +entry: + store <16 x i16> %v, <16 x i16>* %p, align 2 + ret void + +; CHECK-LABEL: test_s_v16i16 +; CHECK: cost of 2 for instruction: store <16 x i16> %v, <16 x i16>* %p, align 2 +} + +define void @test_s_v4i32(<4 x i32>* %p, <4 x i32> %v) #0 { +entry: + store <4 x i32> %v, <4 x i32>* %p, align 4 + ret void + +; CHECK-LABEL: test_s_v4i32 +; CHECK: cost of 1 for instruction: store <4 x i32> %v, <4 x i32>* %p, align 4 +} + +define void @test_s_v8i32(<8 x i32>* %p, <8 x i32> %v) #0 { +entry: + store <8 x i32> %v, <8 x i32>* %p, align 4 + ret void + +; CHECK-LABEL: test_s_v8i32 +; CHECK: cost of 2 for instruction: store <8 x i32> %v, <8 x i32>* %p, align 4 +} + +define void @test_s_v2i64(<2 x i64>* %p, <2 x i64> %v) #0 { +entry: + store <2 x i64> %v, <2 x i64>* %p, align 8 + ret void + +; CHECK-LABEL: test_s_v2i64 +; CHECK: cost of 1 for instruction: store <2 x i64> %v, <2 x i64>* %p, align 8 +} + +define void @test_s_v4i64(<4 x i64>* %p, <4 x i64> %v) #0 { +entry: + store <4 x i64> %v, <4 x i64>* %p, align 8 + ret void + +; CHECK-LABEL: test_s_v4i64 +; CHECK: cost of 2 for instruction: store <4 x i64> %v, <4 x i64>* %p, align 8 +} + +define void @test_s_v4float(<4 x float>* %p, <4 x float> %v) #0 { +entry: + store <4 x float> %v, <4 x float>* %p, align 4 + ret void + +; CHECK-LABEL: test_s_v4float +; CHECK: cost of 1 for instruction: store <4 x float> %v, <4 x float>* %p, align 4 +} + +define void @test_s_v8float(<8 x float>* %p, <8 x float> %v) #0 { +entry: + store <8 x float> %v, <8 x float>* %p, align 4 + ret void + +; CHECK-LABEL: test_s_v8float +; CHECK: cost of 2 for instruction: store <8 x float> %v, <8 x float>* %p, align 4 +} + +define void @test_s_v2double(<2 x double>* %p, <2 x double> %v) #0 { +entry: + store <2 x double> %v, <2 x double>* %p, align 8 + ret void + +; CHECK-LABEL: test_s_v2double +; CHECK: cost of 1 for instruction: store <2 x double> %v, <2 x double>* %p, align 8 +} + +define void @test_s_v4double(<4 x double>* %p, <4 x double> %v) #0 { +entry: + store <4 x double> %v, <4 x double>* %p, align 8 + ret void + +; CHECK-LABEL: test_s_v4double +; CHECK: cost of 2 for instruction: store <4 x double> %v, <4 x double>* %p, align 8 +} + +define void @test_s_qv4float(<4 x float>* %p, <4 x float> %v) #1 { +entry: + store <4 x float> %v, <4 x float>* %p, align 4 + ret void + +; CHECK-LABEL: test_s_qv4float +; CHECK: cost of 7 for instruction: store <4 x float> %v, <4 x float>* %p, align 4 +} + +define void @test_s_qv8float(<8 x float>* %p, <8 x float> %v) #1 { +entry: + store <8 x float> %v, <8 x float>* %p, align 4 + ret void + +; CHECK-LABEL: test_s_qv8float +; CHECK: cost of 15 for instruction: store <8 x float> %v, <8 x float>* %p, align 4 +} + +define void @test_s_qv4double(<4 x double>* %p, <4 x double> %v) #1 { +entry: + store <4 x double> %v, <4 x double>* %p, align 8 + ret void + +; CHECK-LABEL: test_s_qv4double +; CHECK: cost of 7 for instruction: store <4 x double> %v, <4 x double>* %p, align 8 +} + +define void @test_s_qv8double(<8 x double>* %p, <8 x double> %v) #1 { +entry: + store <8 x double> %v, <8 x double>* %p, align 8 + ret void + +; CHECK-LABEL: test_s_qv8double +; CHECK: cost of 15 for instruction: store <8 x double> %v, <8 x double>* %p, align 8 +} + +attributes #0 = { nounwind "target-cpu"="pwr7" } +attributes #1 = { nounwind "target-cpu"="a2q" } +attributes #2 = { nounwind "target-cpu"="pwr8" } + diff --git a/test/Analysis/CostModel/X86/arith.ll b/test/Analysis/CostModel/X86/arith.ll index 92f5a1ec3a00..0b61d3cd4214 100644 --- a/test/Analysis/CostModel/X86/arith.ll +++ b/test/Analysis/CostModel/X86/arith.ll @@ -94,7 +94,7 @@ define void @shift() { ; AVX2: cost of 1 {{.*}} ashr %C0 = ashr <4 x i32> undef, undef ; AVX: cost of 6 {{.*}} ashr - ; AVX2: cost of 20 {{.*}} ashr + ; AVX2: cost of 4 {{.*}} ashr %C1 = ashr <2 x i64> undef, undef ret void @@ -121,7 +121,7 @@ define void @avx2shift() { ; AVX2: cost of 1 {{.*}} ashr %C0 = ashr <8 x i32> undef, undef ; AVX: cost of 12 {{.*}} ashr - ; AVX2: cost of 40 {{.*}} ashr + ; AVX2: cost of 4 {{.*}} ashr %C1 = ashr <4 x i64> undef, undef ret void diff --git a/test/Analysis/CostModel/X86/cast.ll b/test/Analysis/CostModel/X86/cast.ll index fb16af635f07..c518587c0e1a 100644 --- a/test/Analysis/CostModel/X86/cast.ll +++ b/test/Analysis/CostModel/X86/cast.ll @@ -84,11 +84,11 @@ define i32 @zext_sext(<8 x i1> %in) { ;CHECK-AVX: cost of 4 {{.*}} zext %D = zext <4 x i32> undef to <4 x i64> - ;CHECK-AVX512: cost of 3 {{.*}} %D1 = zext - %D1 = zext <16 x i32> undef to <16 x i64> + ;CHECK-AVX512: cost of 1 {{.*}} %D1 = zext + %D1 = zext <8 x i32> undef to <8 x i64> - ;CHECK-AVX512: cost of 3 {{.*}} %D2 = sext - %D2 = sext <16 x i32> undef to <16 x i64> + ;CHECK-AVX512: cost of 1 {{.*}} %D2 = sext + %D2 = sext <8 x i32> undef to <8 x i64> ;CHECK-AVX512: cost of 1 {{.*}} %D3 = zext %D3 = zext <16 x i16> undef to <16 x i32> @@ -118,9 +118,11 @@ define i32 @zext_sext(<8 x i1> %in) { ;CHECK_AVX512: cost of 1 {{.*}} G = trunc %G = trunc <8 x i64> undef to <8 x i32> - ;CHECK-AVX512: cost of 4 {{.*}} %G1 = trunc - %G1 = trunc <16 x i64> undef to <16 x i32> + ;CHECK-AVX512: cost of 1 {{.*}} %G1 = trunc + %G1 = trunc <16 x i32> undef to <16 x i16> + ;CHECK-AVX512: cost of 1 {{.*}} %G2 = trunc + %G2 = trunc <16 x i32> undef to <16 x i8> ret i32 undef } @@ -207,38 +209,40 @@ define void @uitofp4(<4 x i1> %a, <4 x i8> %b, <4 x i16> %c, <4 x i32> %d) { ; CHECK: cost of 2 {{.*}} uitofp %C2 = uitofp <4 x i16> %c to <4 x double> - ; CHECK: cost of 6 {{.*}} uitofp + ; CHECK-AVX2: cost of 6 {{.*}} uitofp %D1 = uitofp <4 x i32> %d to <4 x float> - ; CHECK: cost of 6 {{.*}} uitofp + ; CHECK-AVX2: cost of 6 {{.*}} uitofp %D2 = uitofp <4 x i32> %d to <4 x double> ret void } define void @uitofp8(<8 x i1> %a, <8 x i8> %b, <8 x i16> %c, <8 x i32> %d) { ; CHECK-LABEL: for function 'uitofp8' - ; CHECK: cost of 6 {{.*}} uitofp + ; CHECK-AVX2: cost of 6 {{.*}} uitofp %A1 = uitofp <8 x i1> %a to <8 x float> - ; CHECK: cost of 5 {{.*}} uitofp + ; CHECK-AVX2: cost of 5 {{.*}} uitofp + ; CHECK-AVX512: cost of 2 {{.*}} uitofp %B1 = uitofp <8 x i8> %b to <8 x float> - ; CHECK: cost of 5 {{.*}} uitofp + ; CHECK-AVX2: cost of 5 {{.*}} uitofp + ; CHECK-AVX512: cost of 2 {{.*}} uitofp %C1 = uitofp <8 x i16> %c to <8 x float> ; CHECK-AVX2: cost of 8 {{.*}} uitofp - ; CHECK-AVX512: cost of 8 {{.*}} uitofp + ; CHECK-AVX512: cost of 1 {{.*}} uitofp ; CHECK-AVX: cost of 9 {{.*}} uitofp %D1 = uitofp <8 x i32> %d to <8 x float> ret void } -define void @fp_conv(<8 x float> %a, <16 x float>%b) { +define void @fp_conv(<8 x float> %a, <16 x float>%b, <4 x float> %c) { ;CHECK-LABEL: for function 'fp_conv' ; CHECK-AVX512: cost of 1 {{.*}} fpext %A1 = fpext <8 x float> %a to <8 x double> - ; CHECK-AVX512: cost of 3 {{.*}} fpext - %A2 = fpext <16 x float> %b to <16 x double> + ; CHECK-AVX512: cost of 1 {{.*}} fpext + %A2 = fpext <4 x float> %c to <4 x double> ; CHECK-AVX2: cost of 3 {{.*}} %A3 = fpext ; CHECK-AVX512: cost of 1 {{.*}} %A3 = fpext @@ -248,7 +252,7 @@ define void @fp_conv(<8 x float> %a, <16 x float>%b) { ; CHECK-AVX512: cost of 1 {{.*}} %A4 = fptrunc %A4 = fptrunc <8 x double> undef to <8 x float> - ; CHECK-AVX512: cost of 3 {{.*}} %A5 = fptrunc - %A5 = fptrunc <16 x double> undef to <16 x float> + ; CHECK-AVX512: cost of 1 {{.*}} %A5 = fptrunc + %A5 = fptrunc <4 x double> undef to <4 x float> ret void } diff --git a/test/Analysis/CostModel/X86/masked-intrinsic-cost.ll b/test/Analysis/CostModel/X86/masked-intrinsic-cost.ll index 4683c432c559..61d3e0116e8b 100644 --- a/test/Analysis/CostModel/X86/masked-intrinsic-cost.ll +++ b/test/Analysis/CostModel/X86/masked-intrinsic-cost.ll @@ -1,4 +1,6 @@ -; RUN: opt -S -mtriple=x86_64-apple-darwin -mcpu=core-avx2 -cost-model -analyze < %s | FileCheck %s -check-prefix=AVX2 +; RUN: opt -S -mtriple=x86_64-apple-darwin -mcpu=core-avx2 -cost-model -analyze < %s | FileCheck %s --check-prefix=AVX2 +; RUN: opt -S -mtriple=x86_64-apple-darwin -mcpu=knl -cost-model -analyze < %s | FileCheck %s --check-prefix=KNL +; RUN: opt -S -mtriple=x86_64-apple-darwin -mcpu=skx -cost-model -analyze < %s | FileCheck %s --check-prefix=SKX ; AVX2-LABEL: test1 @@ -65,6 +67,217 @@ define <2 x i32> @test8(<2 x i32> %trigger, <2 x i32>* %addr, <2 x i32> %dst) { ret <2 x i32> %res } +define <2 x double> @test_gather_2f64(<2 x double*> %ptrs, <2 x i1> %mask, <2 x double> %src0) { + +; AVX2-LABEL: test_gather_2f64 +; AVX2: Found an estimated cost of 7 {{.*}}.gather + +; KNL-LABEL: test_gather_2f64 +; KNL: Found an estimated cost of 7 {{.*}}.gather + +; SKX-LABEL: test_gather_2f64 +; SKX: Found an estimated cost of 7 {{.*}}.gather + +%res = call <2 x double> @llvm.masked.gather.v2f64(<2 x double*> %ptrs, i32 4, <2 x i1> %mask, <2 x double> %src0) + ret <2 x double> %res +} +declare <2 x double> @llvm.masked.gather.v2f64(<2 x double*> %ptrs, i32, <2 x i1> %mask, <2 x double> %src0) + +define <4 x i32> @test_gather_4i32(<4 x i32*> %ptrs, <4 x i1> %mask, <4 x i32> %src0) { + +; AVX2-LABEL: test_gather_4i32 +; AVX2: Found an estimated cost of 16 {{.*}}.gather + +; KNL-LABEL: test_gather_4i32 +; KNL: Found an estimated cost of 16 {{.*}}.gather + +; SKX-LABEL: test_gather_4i32 +; SKX: Found an estimated cost of 6 {{.*}}.gather + +%res = call <4 x i32> @llvm.masked.gather.v4i32(<4 x i32*> %ptrs, i32 4, <4 x i1> %mask, <4 x i32> %src0) + ret <4 x i32> %res +} + +define <4 x i32> @test_gather_4i32_const_mask(<4 x i32*> %ptrs, <4 x i32> %src0) { + +; AVX2-LABEL: test_gather_4i32_const_mask +; AVX2: Found an estimated cost of 8 {{.*}}.gather + +; KNL-LABEL: test_gather_4i32_const_mask +; KNL: Found an estimated cost of 8 {{.*}}.gather + +; SKX-LABEL: test_gather_4i32_const_mask +; SKX: Found an estimated cost of 6 {{.*}}.gather + +%res = call <4 x i32> @llvm.masked.gather.v4i32(<4 x i32*> %ptrs, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> %src0) + ret <4 x i32> %res +} +declare <4 x i32> @llvm.masked.gather.v4i32(<4 x i32*> %ptrs, i32, <4 x i1> %mask, <4 x i32> %src0) + +define <16 x float> @test_gather_16f32_const_mask(float* %base, <16 x i32> %ind) { + +; AVX2-LABEL: test_gather_16f32_const_mask +; AVX2: Found an estimated cost of 30 {{.*}}.gather + +; KNL-LABEL: test_gather_16f32_const_mask +; KNL: Found an estimated cost of 18 {{.*}}.gather + +; SKX-LABEL: test_gather_16f32_const_mask +; SKX: Found an estimated cost of 18 {{.*}}.gather + + %sext_ind = sext <16 x i32> %ind to <16 x i64> + %gep.v = getelementptr float, float* %base, <16 x i64> %sext_ind + + %res = call <16 x float> @llvm.masked.gather.v16f32(<16 x float*> %gep.v, 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>, <16 x float> undef) + ret <16 x float>%res +} + +define <16 x float> @test_gather_16f32_var_mask(float* %base, <16 x i32> %ind, <16 x i1>%mask) { + +; AVX2-LABEL: test_gather_16f32_var_mask +; AVX2: Found an estimated cost of 62 {{.*}}.gather + +; KNL-LABEL: test_gather_16f32_var_mask +; KNL: Found an estimated cost of 18 {{.*}}.gather + +; SKX-LABEL: test_gather_16f32_var_mask +; SKX: Found an estimated cost of 18 {{.*}}.gather + + %sext_ind = sext <16 x i32> %ind to <16 x i64> + %gep.v = getelementptr float, float* %base, <16 x i64> %sext_ind + + %res = call <16 x float> @llvm.masked.gather.v16f32(<16 x float*> %gep.v, i32 4, <16 x i1> %mask, <16 x float> undef) + ret <16 x float>%res +} + +define <16 x float> @test_gather_16f32_ra_var_mask(<16 x float*> %ptrs, <16 x i32> %ind, <16 x i1>%mask) { + +; AVX2-LABEL: test_gather_16f32_ra_var_mask +; AVX2: Found an estimated cost of 62 {{.*}}.gather + +; KNL-LABEL: test_gather_16f32_ra_var_mask +; KNL: Found an estimated cost of 20 {{.*}}.gather + +; SKX-LABEL: test_gather_16f32_ra_var_mask +; SKX: Found an estimated cost of 20 {{.*}}.gather + + %sext_ind = sext <16 x i32> %ind to <16 x i64> + %gep.v = getelementptr float, <16 x float*> %ptrs, <16 x i64> %sext_ind + + %res = call <16 x float> @llvm.masked.gather.v16f32(<16 x float*> %gep.v, i32 4, <16 x i1> %mask, <16 x float> undef) + ret <16 x float>%res +} + +define <16 x float> @test_gather_16f32_const_mask2(float* %base, <16 x i32> %ind) { + +; AVX2-LABEL: test_gather_16f32_const_mask2 +; AVX2: Found an estimated cost of 30 {{.*}}.gather + +; KNL-LABEL: test_gather_16f32_const_mask2 +; KNL: Found an estimated cost of 18 {{.*}}.gather + +; SKX-LABEL: test_gather_16f32_const_mask2 +; SKX: Found an estimated cost of 18 {{.*}}.gather + + %broadcast.splatinsert = insertelement <16 x float*> undef, float* %base, i32 0 + %broadcast.splat = shufflevector <16 x float*> %broadcast.splatinsert, <16 x float*> undef, <16 x i32> zeroinitializer + + %sext_ind = sext <16 x i32> %ind to <16 x i64> + %gep.random = getelementptr float, <16 x float*> %broadcast.splat, <16 x i64> %sext_ind + + %res = call <16 x float> @llvm.masked.gather.v16f32(<16 x float*> %gep.random, 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>, <16 x float> undef) + ret <16 x float>%res +} + +define void @test_scatter_16i32(i32* %base, <16 x i32> %ind, i16 %mask, <16 x i32>%val) { +; AVX2-LABEL: test_scatter_16i32 +; AVX2: Found an estimated cost of 64 {{.*}}.scatter + +; KNL-LABEL: test_scatter_16i32 +; KNL: Found an estimated cost of 18 {{.*}}.scatter + +; SKX-LABEL: test_scatter_16i32 +; SKX: Found an estimated cost of 18 {{.*}}.scatter + + %broadcast.splatinsert = insertelement <16 x i32*> undef, i32* %base, i32 0 + %broadcast.splat = shufflevector <16 x i32*> %broadcast.splatinsert, <16 x i32*> undef, <16 x i32> zeroinitializer + + %gep.random = getelementptr i32, <16 x i32*> %broadcast.splat, <16 x i32> %ind + %imask = bitcast i16 %mask to <16 x i1> + call void @llvm.masked.scatter.v16i32(<16 x i32>%val, <16 x i32*> %gep.random, i32 4, <16 x i1> %imask) + ret void +} + +define void @test_scatter_8i32(<8 x i32>%a1, <8 x i32*> %ptr, <8 x i1>%mask) { +; AVX2-LABEL: test_scatter_8i32 +; AVX2: Found an estimated cost of 32 {{.*}}.scatter + +; KNL-LABEL: test_scatter_8i32 +; KNL: Found an estimated cost of 10 {{.*}}.scatter + +; SKX-LABEL: test_scatter_8i32 +; SKX: Found an estimated cost of 10 {{.*}}.scatter + + call void @llvm.masked.scatter.v8i32(<8 x i32> %a1, <8 x i32*> %ptr, i32 4, <8 x i1> %mask) + ret void +} + +declare void @llvm.masked.scatter.v8i32(<8 x i32> %a1, <8 x i32*> %ptr, i32, <8 x i1> %mask) + +define void @test_scatter_4i32(<4 x i32>%a1, <4 x i32*> %ptr, <4 x i1>%mask) { +; AVX2-LABEL: test_scatter_4i32 +; AVX2: Found an estimated cost of 16 {{.*}}.scatter + +; KNL-LABEL: test_scatter_4i32 +; KNL: Found an estimated cost of 16 {{.*}}.scatter + +; SKX-LABEL: test_scatter_4i32 +; SKX: Found an estimated cost of 6 {{.*}}.scatter + + call void @llvm.masked.scatter.v4i32(<4 x i32> %a1, <4 x i32*> %ptr, i32 4, <4 x i1> %mask) + ret void +} + +define <4 x float> @test_gather_4f32(float* %ptr, <4 x i32> %ind, <4 x i1>%mask) { + +; AVX2-LABEL: test_gather_4f32 +; AVX2: Found an estimated cost of 15 {{.*}}.gather + +; KNL-LABEL: test_gather_4f32 +; KNL: Found an estimated cost of 15 {{.*}}.gather + +; SKX-LABEL: test_gather_4f32 +; SKX: Found an estimated cost of 6 {{.*}}.gather + + %sext_ind = sext <4 x i32> %ind to <4 x i64> + %gep.v = getelementptr float, float* %ptr, <4 x i64> %sext_ind + + %res = call <4 x float> @llvm.masked.gather.v4f32(<4 x float*> %gep.v, i32 4, <4 x i1> %mask, <4 x float> undef) + ret <4 x float>%res +} + +define <4 x float> @test_gather_4f32_const_mask(float* %ptr, <4 x i32> %ind) { + +; AVX2-LABEL: test_gather_4f32_const_mask +; AVX2: Found an estimated cost of 7 {{.*}}.gather + +; KNL-LABEL: test_gather_4f32_const_mask +; KNL: Found an estimated cost of 7 {{.*}}.gather + +; SKX-LABEL: test_gather_4f32_const_mask +; SKX: Found an estimated cost of 6 {{.*}}.gather + + %sext_ind = sext <4 x i32> %ind to <4 x i64> + %gep.v = getelementptr float, float* %ptr, <4 x i64> %sext_ind + + %res = call <4 x float> @llvm.masked.gather.v4f32(<4 x float*> %gep.v, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x float> undef) + ret <4 x float>%res +} + +declare <4 x float> @llvm.masked.gather.v4f32(<4 x float*> %gep.v, i32, <4 x i1> %mask, <4 x float> ) +declare void @llvm.masked.scatter.v4i32(<4 x i32> %a1, <4 x i32*> %ptr, i32, <4 x i1> %mask) +declare void @llvm.masked.scatter.v16i32(<16 x i32>%val, <16 x i32*> %gep.random, i32, <16 x i1> %imask) +declare <16 x float> @llvm.masked.gather.v16f32(<16 x float*> %gep.v, i32, <16 x i1> %mask, <16 x float>) declare <16 x i32> @llvm.masked.load.v16i32(<16 x i32>*, i32, <16 x i1>, <16 x i32>) declare <4 x i32> @llvm.masked.load.v4i32(<4 x i32>*, i32, <4 x i1>, <4 x i32>) diff --git a/test/Analysis/CostModel/X86/reduction.ll b/test/Analysis/CostModel/X86/reduction.ll index 78e65aee1460..aaafe07c1eb8 100644 --- a/test/Analysis/CostModel/X86/reduction.ll +++ b/test/Analysis/CostModel/X86/reduction.ll @@ -33,7 +33,7 @@ define fastcc i32 @reduction_cost_int(<8 x i32> %rdx) { %bin.rdx.3 = add <8 x i32> %bin.rdx.2, %rdx.shuf.3 ; CHECK-LABEL: reduction_cost_int -; CHECK: cost of 23 {{.*}} extractelement +; CHECK: cost of 17 {{.*}} extractelement %r = extractelement <8 x i32> %bin.rdx.3, i32 0 ret i32 %r diff --git a/test/Analysis/CostModel/X86/sitofp.ll b/test/Analysis/CostModel/X86/sitofp.ll index dcd0088d0df7..9f0c4065c178 100644 --- a/test/Analysis/CostModel/X86/sitofp.ll +++ b/test/Analysis/CostModel/X86/sitofp.ll @@ -4,656 +4,656 @@ ; RUN: opt -mtriple=x86_64-apple-darwin -mattr=+avx512f -cost-model -analyze < %s | FileCheck --check-prefix=AVX512F %s define <2 x double> @sitofpv2i8v2double(<2 x i8> %a) { - ; SSE2: sitofpv2i8v2double + ; SSE2-LABEL: sitofpv2i8v2double ; SSE2: cost of 20 {{.*}} sitofp ; - ; AVX1: sitofpv2i8v2double + ; AVX1-LABEL: sitofpv2i8v2double ; AVX1: cost of 4 {{.*}} sitofp ; - ; AVX2: sitofpv2i8v2double + ; AVX2-LABEL: sitofpv2i8v2double ; AVX2: cost of 4 {{.*}} sitofp ; - ; AVX512F: sitofpv2i8v2double + ; AVX512F-LABEL: sitofpv2i8v2double ; AVX512F: cost of 4 {{.*}} sitofp %1 = sitofp <2 x i8> %a to <2 x double> ret <2 x double> %1 } define <4 x double> @sitofpv4i8v4double(<4 x i8> %a) { - ; SSE2: sitofpv4i8v4double + ; SSE2-LABEL: sitofpv4i8v4double ; SSE2: cost of 40 {{.*}} sitofp ; - ; AVX1: sitofpv4i8v4double + ; AVX1-LABEL: sitofpv4i8v4double ; AVX1: cost of 3 {{.*}} sitofp ; - ; AVX2: sitofpv4i8v4double + ; AVX2-LABEL: sitofpv4i8v4double ; AVX2: cost of 3 {{.*}} sitofp ; - ; AVX512F: sitofpv4i8v4double + ; AVX512F-LABEL: sitofpv4i8v4double ; AVX512F: cost of 3 {{.*}} sitofp %1 = sitofp <4 x i8> %a to <4 x double> ret <4 x double> %1 } define <8 x double> @sitofpv8i8v8double(<8 x i8> %a) { - ; SSE2: sitofpv8i8v8double + ; SSE2-LABEL: sitofpv8i8v8double ; SSE2: cost of 80 {{.*}} sitofp ; - ; AVX1: sitofpv8i8v8double + ; AVX1-LABEL: sitofpv8i8v8double ; AVX1: cost of 20 {{.*}} sitofp ; - ; AVX2: sitofpv8i8v8double + ; AVX2-LABEL: sitofpv8i8v8double ; AVX2: cost of 20 {{.*}} sitofp ; - ; AVX512F: sitofpv8i8v8double + ; AVX512F-LABEL: sitofpv8i8v8double ; AVX512F: cost of 2 {{.*}} sitofp %1 = sitofp <8 x i8> %a to <8 x double> ret <8 x double> %1 } define <16 x double> @sitofpv16i8v16double(<16 x i8> %a) { - ; SSE2: sitofpv16i8v16double + ; SSE2-LABEL: sitofpv16i8v16double ; SSE2: cost of 160 {{.*}} sitofp ; - ; AVX1: sitofpv16i8v16double + ; AVX1-LABEL: sitofpv16i8v16double ; AVX1: cost of 40 {{.*}} sitofp ; - ; AVX2: sitofpv16i8v16double + ; AVX2-LABEL: sitofpv16i8v16double ; AVX2: cost of 40 {{.*}} sitofp ; - ; AVX512F: sitofpv16i8v16double + ; AVX512F-LABEL: sitofpv16i8v16double ; AVX512F: cost of 44 {{.*}} sitofp %1 = sitofp <16 x i8> %a to <16 x double> ret <16 x double> %1 } define <32 x double> @sitofpv32i8v32double(<32 x i8> %a) { - ; SSE2: sitofpv32i8v32double + ; SSE2-LABEL: sitofpv32i8v32double ; SSE2: cost of 320 {{.*}} sitofp ; - ; AVX1: sitofpv32i8v32double + ; AVX1-LABEL: sitofpv32i8v32double ; AVX1: cost of 80 {{.*}} sitofp ; - ; AVX2: sitofpv32i8v32double + ; AVX2-LABEL: sitofpv32i8v32double ; AVX2: cost of 80 {{.*}} sitofp ; - ; AVX512F: sitofpv32i8v32double + ; AVX512F-LABEL: sitofpv32i8v32double ; AVX512F: cost of 88 {{.*}} sitofp %1 = sitofp <32 x i8> %a to <32 x double> ret <32 x double> %1 } define <2 x double> @sitofpv2i16v2double(<2 x i16> %a) { - ; SSE2: sitofpv2i16v2double + ; SSE2-LABEL: sitofpv2i16v2double ; SSE2: cost of 20 {{.*}} sitofp ; - ; AVX1: sitofpv2i16v2double + ; AVX1-LABEL: sitofpv2i16v2double ; AVX1: cost of 4 {{.*}} sitofp ; - ; AVX2: sitofpv2i16v2double + ; AVX2-LABEL: sitofpv2i16v2double ; AVX2: cost of 4 {{.*}} sitofp ; - ; AVX512F: sitofpv2i16v2double + ; AVX512F-LABEL: sitofpv2i16v2double ; AVX512F: cost of 4 {{.*}} sitofp %1 = sitofp <2 x i16> %a to <2 x double> ret <2 x double> %1 } define <4 x double> @sitofpv4i16v4double(<4 x i16> %a) { - ; SSE2: sitofpv4i16v4double + ; SSE2-LABEL: sitofpv4i16v4double ; SSE2: cost of 40 {{.*}} sitofp ; - ; AVX1: sitofpv4i16v4double + ; AVX1-LABEL: sitofpv4i16v4double ; AVX1: cost of 3 {{.*}} sitofp ; - ; AVX2: sitofpv4i16v4double + ; AVX2-LABEL: sitofpv4i16v4double ; AVX2: cost of 3 {{.*}} sitofp ; - ; AVX512F: sitofpv4i16v4double + ; AVX512F-LABEL: sitofpv4i16v4double ; AVX512F: cost of 3 {{.*}} sitofp %1 = sitofp <4 x i16> %a to <4 x double> ret <4 x double> %1 } define <8 x double> @sitofpv8i16v8double(<8 x i16> %a) { - ; SSE2: sitofpv8i16v8double + ; SSE2-LABEL: sitofpv8i16v8double ; SSE2: cost of 80 {{.*}} sitofp ; - ; AVX1: sitofpv8i16v8double + ; AVX1-LABEL: sitofpv8i16v8double ; AVX1: cost of 20 {{.*}} sitofp ; - ; AVX2: sitofpv8i16v8double + ; AVX2-LABEL: sitofpv8i16v8double ; AVX2: cost of 20 {{.*}} sitofp ; - ; AVX512F: sitofpv8i16v8double + ; AVX512F-LABEL: sitofpv8i16v8double ; AVX512F: cost of 2 {{.*}} sitofp %1 = sitofp <8 x i16> %a to <8 x double> ret <8 x double> %1 } define <16 x double> @sitofpv16i16v16double(<16 x i16> %a) { - ; SSE2: sitofpv16i16v16double + ; SSE2-LABEL: sitofpv16i16v16double ; SSE2: cost of 160 {{.*}} sitofp ; - ; AVX1: sitofpv16i16v16double + ; AVX1-LABEL: sitofpv16i16v16double ; AVX1: cost of 40 {{.*}} sitofp ; - ; AVX2: sitofpv16i16v16double + ; AVX2-LABEL: sitofpv16i16v16double ; AVX2: cost of 40 {{.*}} sitofp ; - ; AVX512F: sitofpv16i16v16double + ; AVX512F-LABEL: sitofpv16i16v16double ; AVX512F: cost of 44 {{.*}} sitofp %1 = sitofp <16 x i16> %a to <16 x double> ret <16 x double> %1 } define <32 x double> @sitofpv32i16v32double(<32 x i16> %a) { - ; SSE2: sitofpv32i16v32double + ; SSE2-LABEL: sitofpv32i16v32double ; SSE2: cost of 320 {{.*}} sitofp ; - ; AVX1: sitofpv32i16v32double + ; AVX1-LABEL: sitofpv32i16v32double ; AVX1: cost of 80 {{.*}} sitofp ; - ; AVX2: sitofpv32i16v32double + ; AVX2-LABEL: sitofpv32i16v32double ; AVX2: cost of 80 {{.*}} sitofp ; - ; AVX512F: sitofpv32i16v32double + ; AVX512F-LABEL: sitofpv32i16v32double ; AVX512F: cost of 88 {{.*}} sitofp %1 = sitofp <32 x i16> %a to <32 x double> ret <32 x double> %1 } define <2 x double> @sitofpv2i32v2double(<2 x i32> %a) { - ; SSE2: sitofpv2i32v2double + ; SSE2-LABEL: sitofpv2i32v2double ; SSE2: cost of 20 {{.*}} sitofp ; - ; AVX1: sitofpv2i32v2double + ; AVX1-LABEL: sitofpv2i32v2double ; AVX1: cost of 4 {{.*}} sitofp ; - ; AVX2: sitofpv2i32v2double + ; AVX2-LABEL: sitofpv2i32v2double ; AVX2: cost of 4 {{.*}} sitofp ; - ; AVX512F: sitofpv2i32v2double + ; AVX512F-LABEL: sitofpv2i32v2double ; AVX512F: cost of 4 {{.*}} sitofp %1 = sitofp <2 x i32> %a to <2 x double> ret <2 x double> %1 } define <4 x double> @sitofpv4i32v4double(<4 x i32> %a) { - ; SSE2: sitofpv4i32v4double + ; SSE2-LABEL: sitofpv4i32v4double ; SSE2: cost of 40 {{.*}} sitofp ; - ; AVX1: sitofpv4i32v4double + ; AVX1-LABEL: sitofpv4i32v4double ; AVX1: cost of 1 {{.*}} sitofp ; - ; AVX2: sitofpv4i32v4double + ; AVX2-LABEL: sitofpv4i32v4double ; AVX2: cost of 1 {{.*}} sitofp ; - ; AVX512F: sitofpv4i32v4double + ; AVX512F-LABEL: sitofpv4i32v4double ; AVX512F: cost of 1 {{.*}} sitofp %1 = sitofp <4 x i32> %a to <4 x double> ret <4 x double> %1 } define <8 x double> @sitofpv8i32v8double(<8 x i32> %a) { - ; SSE2: sitofpv8i32v8double + ; SSE2-LABEL: sitofpv8i32v8double ; SSE2: cost of 80 {{.*}} sitofp ; - ; AVX1: sitofpv8i32v8double + ; AVX1-LABEL: sitofpv8i32v8double ; AVX1: cost of 20 {{.*}} sitofp ; - ; AVX2: sitofpv8i32v8double + ; AVX2-LABEL: sitofpv8i32v8double ; AVX2: cost of 20 {{.*}} sitofp ; - ; AVX512F: sitofpv8i32v8double + ; AVX512F-LABEL: sitofpv8i32v8double ; AVX512F: cost of 1 {{.*}} sitofp %1 = sitofp <8 x i32> %a to <8 x double> ret <8 x double> %1 } define <16 x double> @sitofpv16i32v16double(<16 x i32> %a) { - ; SSE2: sitofpv16i32v16double + ; SSE2-LABEL: sitofpv16i32v16double ; SSE2: cost of 160 {{.*}} sitofp ; - ; AVX1: sitofpv16i32v16double + ; AVX1-LABEL: sitofpv16i32v16double ; AVX1: cost of 40 {{.*}} sitofp ; - ; AVX2: sitofpv16i32v16double + ; AVX2-LABEL: sitofpv16i32v16double ; AVX2: cost of 40 {{.*}} sitofp ; - ; AVX512F: sitofpv16i32v16double + ; AVX512F-LABEL: sitofpv16i32v16double ; AVX512F: cost of 44 {{.*}} sitofp %1 = sitofp <16 x i32> %a to <16 x double> ret <16 x double> %1 } define <32 x double> @sitofpv32i32v32double(<32 x i32> %a) { - ; SSE2: sitofpv32i32v32double + ; SSE2-LABEL: sitofpv32i32v32double ; SSE2: cost of 320 {{.*}} sitofp ; - ; AVX1: sitofpv32i32v32double + ; AVX1-LABEL: sitofpv32i32v32double ; AVX1: cost of 80 {{.*}} sitofp ; - ; AVX2: sitofpv32i32v32double + ; AVX2-LABEL: sitofpv32i32v32double ; AVX2: cost of 80 {{.*}} sitofp ; - ; AVX512F: sitofpv32i32v32double + ; AVX512F-LABEL: sitofpv32i32v32double ; AVX512F: cost of 88 {{.*}} sitofp %1 = sitofp <32 x i32> %a to <32 x double> ret <32 x double> %1 } define <2 x double> @sitofpv2i64v2double(<2 x i64> %a) { - ; SSE2: sitofpv2i64v2double + ; SSE2-LABEL: sitofpv2i64v2double ; SSE2: cost of 20 {{.*}} sitofp ; - ; AVX1: sitofpv2i64v2double - ; AVX1: cost of 4 {{.*}} sitofp + ; AVX1-LABEL: sitofpv2i64v2double + ; AVX1: cost of 20 {{.*}} sitofp ; - ; AVX2: sitofpv2i64v2double - ; AVX2: cost of 4 {{.*}} sitofp + ; AVX2-LABEL: sitofpv2i64v2double + ; AVX2: cost of 20 {{.*}} sitofp ; - ; AVX512F: sitofpv2i64v2double - ; AVX512F: cost of 4 {{.*}} sitofp + ; AVX512F-LABEL: sitofpv2i64v2double + ; AVX512F: cost of 20 {{.*}} sitofp %1 = sitofp <2 x i64> %a to <2 x double> ret <2 x double> %1 } define <4 x double> @sitofpv4i64v4double(<4 x i64> %a) { - ; SSE2: sitofpv4i64v4double + ; SSE2-LABEL: sitofpv4i64v4double ; SSE2: cost of 40 {{.*}} sitofp ; - ; AVX1: sitofpv4i64v4double + ; AVX1-LABEL: sitofpv4i64v4double ; AVX1: cost of 10 {{.*}} sitofp ; - ; AVX2: sitofpv4i64v4double + ; AVX2-LABEL: sitofpv4i64v4double ; AVX2: cost of 10 {{.*}} sitofp ; - ; AVX512F: sitofpv4i64v4double + ; AVX512F-LABEL: sitofpv4i64v4double ; AVX512F: cost of 10 {{.*}} sitofp %1 = sitofp <4 x i64> %a to <4 x double> ret <4 x double> %1 } define <8 x double> @sitofpv8i64v8double(<8 x i64> %a) { - ; SSE2: sitofpv8i64v8double + ; SSE2-LABEL: sitofpv8i64v8double ; SSE2: cost of 80 {{.*}} sitofp ; - ; AVX1: sitofpv8i64v8double + ; AVX1-LABEL: sitofpv8i64v8double ; AVX1: cost of 20 {{.*}} sitofp ; - ; AVX2: sitofpv8i64v8double + ; AVX2-LABEL: sitofpv8i64v8double ; AVX2: cost of 20 {{.*}} sitofp ; - ; AVX512F: sitofpv8i64v8double + ; AVX512F-LABEL: sitofpv8i64v8double ; AVX512F: cost of 22 {{.*}} sitofp %1 = sitofp <8 x i64> %a to <8 x double> ret <8 x double> %1 } define <16 x double> @sitofpv16i64v16double(<16 x i64> %a) { - ; SSE2: sitofpv16i64v16double + ; SSE2-LABEL: sitofpv16i64v16double ; SSE2: cost of 160 {{.*}} sitofp ; - ; AVX1: sitofpv16i64v16double + ; AVX1-LABEL: sitofpv16i64v16double ; AVX1: cost of 40 {{.*}} sitofp ; - ; AVX2: sitofpv16i64v16double + ; AVX2-LABEL: sitofpv16i64v16double ; AVX2: cost of 40 {{.*}} sitofp ; - ; AVX512F: sitofpv16i64v16double + ; AVX512F-LABEL: sitofpv16i64v16double ; AVX512F: cost of 44 {{.*}} sitofp %1 = sitofp <16 x i64> %a to <16 x double> ret <16 x double> %1 } define <32 x double> @sitofpv32i64v32double(<32 x i64> %a) { - ; SSE2: sitofpv32i64v32double + ; SSE2-LABEL: sitofpv32i64v32double ; SSE2: cost of 320 {{.*}} sitofp ; - ; AVX1: sitofpv32i64v32double + ; AVX1-LABEL: sitofpv32i64v32double ; AVX1: cost of 80 {{.*}} sitofp ; - ; AVX2: sitofpv32i64v32double + ; AVX2-LABEL: sitofpv32i64v32double ; AVX2: cost of 80 {{.*}} sitofp ; - ; AVX512F: sitofpv32i64v32double + ; AVX512F-LABEL: sitofpv32i64v32double ; AVX512F: cost of 88 {{.*}} sitofp %1 = sitofp <32 x i64> %a to <32 x double> ret <32 x double> %1 } define <2 x float> @sitofpv2i8v2float(<2 x i8> %a) { - ; SSE2: sitofpv2i8v2float + ; SSE2-LABEL: sitofpv2i8v2float ; SSE2: cost of 15 {{.*}} sitofp ; - ; AVX1: sitofpv2i8v2float + ; AVX1-LABEL: sitofpv2i8v2float ; AVX1: cost of 4 {{.*}} sitofp ; - ; AVX2: sitofpv2i8v2float + ; AVX2-LABEL: sitofpv2i8v2float ; AVX2: cost of 4 {{.*}} sitofp ; - ; AVX512F: sitofpv2i8v2float + ; AVX512F-LABEL: sitofpv2i8v2float ; AVX512F: cost of 4 {{.*}} sitofp %1 = sitofp <2 x i8> %a to <2 x float> ret <2 x float> %1 } define <4 x float> @sitofpv4i8v4float(<4 x i8> %a) { - ; SSE2: sitofpv4i8v4float + ; SSE2-LABEL: sitofpv4i8v4float ; SSE2: cost of 15 {{.*}} sitofp ; - ; AVX1: sitofpv4i8v4float + ; AVX1-LABEL: sitofpv4i8v4float ; AVX1: cost of 3 {{.*}} sitofp ; - ; AVX2: sitofpv4i8v4float + ; AVX2-LABEL: sitofpv4i8v4float ; AVX2: cost of 3 {{.*}} sitofp ; - ; AVX512F: sitofpv4i8v4float + ; AVX512F-LABEL: sitofpv4i8v4float ; AVX512F: cost of 3 {{.*}} sitofp %1 = sitofp <4 x i8> %a to <4 x float> ret <4 x float> %1 } define <8 x float> @sitofpv8i8v8float(<8 x i8> %a) { - ; SSE2: sitofpv8i8v8float + ; SSE2-LABEL: sitofpv8i8v8float ; SSE2: cost of 15 {{.*}} sitofp ; - ; AVX1: sitofpv8i8v8float + ; AVX1-LABEL: sitofpv8i8v8float ; AVX1: cost of 8 {{.*}} sitofp ; - ; AVX2: sitofpv8i8v8float + ; AVX2-LABEL: sitofpv8i8v8float ; AVX2: cost of 8 {{.*}} sitofp ; - ; AVX512F: sitofpv8i8v8float + ; AVX512F-LABEL: sitofpv8i8v8float ; AVX512F: cost of 8 {{.*}} sitofp %1 = sitofp <8 x i8> %a to <8 x float> ret <8 x float> %1 } define <16 x float> @sitofpv16i8v16float(<16 x i8> %a) { - ; SSE2: sitofpv16i8v16float + ; SSE2-LABEL: sitofpv16i8v16float ; SSE2: cost of 8 {{.*}} sitofp ; - ; AVX1: sitofpv16i8v16float + ; AVX1-LABEL: sitofpv16i8v16float ; AVX1: cost of 44 {{.*}} sitofp ; - ; AVX2: sitofpv16i8v16float + ; AVX2-LABEL: sitofpv16i8v16float ; AVX2: cost of 44 {{.*}} sitofp ; - ; AVX512F: sitofpv16i8v16float + ; AVX512F-LABEL: sitofpv16i8v16float ; AVX512F: cost of 2 {{.*}} sitofp %1 = sitofp <16 x i8> %a to <16 x float> ret <16 x float> %1 } define <32 x float> @sitofpv32i8v32float(<32 x i8> %a) { - ; SSE2: sitofpv32i8v32float + ; SSE2-LABEL: sitofpv32i8v32float ; SSE2: cost of 16 {{.*}} sitofp ; - ; AVX1: sitofpv32i8v32float + ; AVX1-LABEL: sitofpv32i8v32float ; AVX1: cost of 88 {{.*}} sitofp ; - ; AVX2: sitofpv32i8v32float + ; AVX2-LABEL: sitofpv32i8v32float ; AVX2: cost of 88 {{.*}} sitofp ; - ; AVX512F: sitofpv32i8v32float + ; AVX512F-LABEL: sitofpv32i8v32float ; AVX512F: cost of 92 {{.*}} sitofp %1 = sitofp <32 x i8> %a to <32 x float> ret <32 x float> %1 } define <2 x float> @sitofpv2i16v2float(<2 x i16> %a) { - ; SSE2: sitofpv2i16v2float + ; SSE2-LABEL: sitofpv2i16v2float ; SSE2: cost of 15 {{.*}} sitofp ; - ; AVX1: sitofpv2i16v2float + ; AVX1-LABEL: sitofpv2i16v2float ; AVX1: cost of 4 {{.*}} sitofp ; - ; AVX2: sitofpv2i16v2float + ; AVX2-LABEL: sitofpv2i16v2float ; AVX2: cost of 4 {{.*}} sitofp ; - ; AVX512F: sitofpv2i16v2float + ; AVX512F-LABEL: sitofpv2i16v2float ; AVX512F: cost of 4 {{.*}} sitofp %1 = sitofp <2 x i16> %a to <2 x float> ret <2 x float> %1 } define <4 x float> @sitofpv4i16v4float(<4 x i16> %a) { - ; SSE2: sitofpv4i16v4float + ; SSE2-LABEL: sitofpv4i16v4float ; SSE2: cost of 15 {{.*}} sitofp ; - ; AVX1: sitofpv4i16v4float + ; AVX1-LABEL: sitofpv4i16v4float ; AVX1: cost of 3 {{.*}} sitofp ; - ; AVX2: sitofpv4i16v4float + ; AVX2-LABEL: sitofpv4i16v4float ; AVX2: cost of 3 {{.*}} sitofp ; - ; AVX512F: sitofpv4i16v4float + ; AVX512F-LABEL: sitofpv4i16v4float ; AVX512F: cost of 3 {{.*}} sitofp %1 = sitofp <4 x i16> %a to <4 x float> ret <4 x float> %1 } define <8 x float> @sitofpv8i16v8float(<8 x i16> %a) { - ; SSE2: sitofpv8i16v8float + ; SSE2-LABEL: sitofpv8i16v8float ; SSE2: cost of 15 {{.*}} sitofp ; - ; AVX1: sitofpv8i16v8float + ; AVX1-LABEL: sitofpv8i16v8float ; AVX1: cost of 5 {{.*}} sitofp ; - ; AVX2: sitofpv8i16v8float + ; AVX2-LABEL: sitofpv8i16v8float ; AVX2: cost of 5 {{.*}} sitofp ; - ; AVX512F: sitofpv8i16v8float + ; AVX512F-LABEL: sitofpv8i16v8float ; AVX512F: cost of 5 {{.*}} sitofp %1 = sitofp <8 x i16> %a to <8 x float> ret <8 x float> %1 } define <16 x float> @sitofpv16i16v16float(<16 x i16> %a) { - ; SSE2: sitofpv16i16v16float + ; SSE2-LABEL: sitofpv16i16v16float ; SSE2: cost of 30 {{.*}} sitofp ; - ; AVX1: sitofpv16i16v16float + ; AVX1-LABEL: sitofpv16i16v16float ; AVX1: cost of 44 {{.*}} sitofp ; - ; AVX2: sitofpv16i16v16float + ; AVX2-LABEL: sitofpv16i16v16float ; AVX2: cost of 44 {{.*}} sitofp ; - ; AVX512F: sitofpv16i16v16float + ; AVX512F-LABEL: sitofpv16i16v16float ; AVX512F: cost of 2 {{.*}} sitofp %1 = sitofp <16 x i16> %a to <16 x float> ret <16 x float> %1 } define <32 x float> @sitofpv32i16v32float(<32 x i16> %a) { - ; SSE2: sitofpv32i16v32float + ; SSE2-LABEL: sitofpv32i16v32float ; SSE2: cost of 60 {{.*}} sitofp ; - ; AVX1: sitofpv32i16v32float + ; AVX1-LABEL: sitofpv32i16v32float ; AVX1: cost of 88 {{.*}} sitofp ; - ; AVX2: sitofpv32i16v32float + ; AVX2-LABEL: sitofpv32i16v32float ; AVX2: cost of 88 {{.*}} sitofp ; - ; AVX512F: sitofpv32i16v32float - ; AVX512F: cost of 2 {{.*}} sitofp + ; AVX512F-LABEL: sitofpv32i16v32float + ; AVX512F: cost of 92 {{.*}} sitofp %1 = sitofp <32 x i16> %a to <32 x float> ret <32 x float> %1 } define <2 x float> @sitofpv2i32v2float(<2 x i32> %a) { - ; SSE2: sitofpv2i32v2float + ; SSE2-LABEL: sitofpv2i32v2float ; SSE2: cost of 15 {{.*}} sitofp ; - ; AVX1: sitofpv2i32v2float + ; AVX1-LABEL: sitofpv2i32v2float ; AVX1: cost of 4 {{.*}} sitofp ; - ; AVX2: sitofpv2i32v2float + ; AVX2-LABEL: sitofpv2i32v2float ; AVX2: cost of 4 {{.*}} sitofp ; - ; AVX512F: sitofpv2i32v2float + ; AVX512F-LABEL: sitofpv2i32v2float ; AVX512F: cost of 4 {{.*}} sitofp %1 = sitofp <2 x i32> %a to <2 x float> ret <2 x float> %1 } define <4 x float> @sitofpv4i32v4float(<4 x i32> %a) { - ; SSE2: sitofpv4i32v4float + ; SSE2-LABEL: sitofpv4i32v4float ; SSE2: cost of 15 {{.*}} sitofp ; - ; AVX1: sitofpv4i32v4float + ; AVX1-LABEL: sitofpv4i32v4float ; AVX1: cost of 1 {{.*}} sitofp ; - ; AVX2: sitofpv4i32v4float + ; AVX2-LABEL: sitofpv4i32v4float ; AVX2: cost of 1 {{.*}} sitofp ; - ; AVX512F: sitofpv4i32v4float + ; AVX512F-LABEL: sitofpv4i32v4float ; AVX512F: cost of 1 {{.*}} sitofp %1 = sitofp <4 x i32> %a to <4 x float> ret <4 x float> %1 } define <8 x float> @sitofpv8i32v8float(<8 x i32> %a) { - ; SSE2: sitofpv8i32v8float + ; SSE2-LABEL: sitofpv8i32v8float ; SSE2: cost of 30 {{.*}} sitofp ; - ; AVX1: sitofpv8i32v8float + ; AVX1-LABEL: sitofpv8i32v8float ; AVX1: cost of 1 {{.*}} sitofp ; - ; AVX2: sitofpv8i32v8float + ; AVX2-LABEL: sitofpv8i32v8float ; AVX2: cost of 1 {{.*}} sitofp ; - ; AVX512F: sitofpv8i32v8float + ; AVX512F-LABEL: sitofpv8i32v8float ; AVX512F: cost of 1 {{.*}} sitofp %1 = sitofp <8 x i32> %a to <8 x float> ret <8 x float> %1 } define <16 x float> @sitofpv16i32v16float(<16 x i32> %a) { - ; SSE2: sitofpv16i32v16float + ; SSE2-LABEL: sitofpv16i32v16float ; SSE2: cost of 60 {{.*}} sitofp ; - ; AVX1: sitofpv16i32v16float + ; AVX1-LABEL: sitofpv16i32v16float ; AVX1: cost of 44 {{.*}} sitofp ; - ; AVX2: sitofpv16i32v16float + ; AVX2-LABEL: sitofpv16i32v16float ; AVX2: cost of 44 {{.*}} sitofp ; - ; AVX512F: sitofpv16i32v16float + ; AVX512F-LABEL: sitofpv16i32v16float ; AVX512F: cost of 1 {{.*}} sitofp %1 = sitofp <16 x i32> %a to <16 x float> ret <16 x float> %1 } define <32 x float> @sitofpv32i32v32float(<32 x i32> %a) { - ; SSE2: sitofpv32i32v32float + ; SSE2-LABEL: sitofpv32i32v32float ; SSE2: cost of 120 {{.*}} sitofp ; - ; AVX1: sitofpv32i32v32float + ; AVX1-LABEL: sitofpv32i32v32float ; AVX1: cost of 88 {{.*}} sitofp ; - ; AVX2: sitofpv32i32v32float + ; AVX2-LABEL: sitofpv32i32v32float ; AVX2: cost of 88 {{.*}} sitofp ; - ; AVX512F: sitofpv32i32v32float - ; AVX512F: cost of 1 {{.*}} sitofp + ; AVX512F-LABEL: sitofpv32i32v32float + ; AVX512F: cost of 92 {{.*}} sitofp %1 = sitofp <32 x i32> %a to <32 x float> ret <32 x float> %1 } define <2 x float> @sitofpv2i64v2float(<2 x i64> %a) { - ; SSE2: sitofpv2i64v2float + ; SSE2-LABEL: sitofpv2i64v2float ; SSE2: cost of 15 {{.*}} sitofp ; - ; AVX1: sitofpv2i64v2float + ; AVX1-LABEL: sitofpv2i64v2float ; AVX1: cost of 4 {{.*}} sitofp ; - ; AVX2: sitofpv2i64v2float + ; AVX2-LABEL: sitofpv2i64v2float ; AVX2: cost of 4 {{.*}} sitofp ; - ; AVX512F: sitofpv2i64v2float + ; AVX512F-LABEL: sitofpv2i64v2float ; AVX512F: cost of 4 {{.*}} sitofp %1 = sitofp <2 x i64> %a to <2 x float> ret <2 x float> %1 } define <4 x float> @sitofpv4i64v4float(<4 x i64> %a) { - ; SSE2: sitofpv4i64v4float + ; SSE2-LABEL: sitofpv4i64v4float ; SSE2: cost of 30 {{.*}} sitofp ; - ; AVX1: sitofpv4i64v4float + ; AVX1-LABEL: sitofpv4i64v4float ; AVX1: cost of 10 {{.*}} sitofp ; - ; AVX2: sitofpv4i64v4float + ; AVX2-LABEL: sitofpv4i64v4float ; AVX2: cost of 10 {{.*}} sitofp ; - ; AVX512F: sitofpv4i64v4float + ; AVX512F-LABEL: sitofpv4i64v4float ; AVX512F: cost of 10 {{.*}} sitofp %1 = sitofp <4 x i64> %a to <4 x float> ret <4 x float> %1 } define <8 x float> @sitofpv8i64v8float(<8 x i64> %a) { - ; SSE2: sitofpv8i64v8float + ; SSE2-LABEL: sitofpv8i64v8float ; SSE2: cost of 60 {{.*}} sitofp ; - ; AVX1: sitofpv8i64v8float + ; AVX1-LABEL: sitofpv8i64v8float ; AVX1: cost of 22 {{.*}} sitofp ; - ; AVX2: sitofpv8i64v8float + ; AVX2-LABEL: sitofpv8i64v8float ; AVX2: cost of 22 {{.*}} sitofp ; - ; AVX512F: sitofpv8i64v8float + ; AVX512F-LABEL: sitofpv8i64v8float ; AVX512F: cost of 22 {{.*}} sitofp %1 = sitofp <8 x i64> %a to <8 x float> ret <8 x float> %1 } define <16 x float> @sitofpv16i64v16float(<16 x i64> %a) { - ; SSE2: sitofpv16i64v16float + ; SSE2-LABEL: sitofpv16i64v16float ; SSE2: cost of 120 {{.*}} sitofp ; - ; AVX1: sitofpv16i64v16float + ; AVX1-LABEL: sitofpv16i64v16float ; AVX1: cost of 44 {{.*}} sitofp ; - ; AVX2: sitofpv16i64v16float + ; AVX2-LABEL: sitofpv16i64v16float ; AVX2: cost of 44 {{.*}} sitofp ; - ; AVX512F: sitofpv16i64v16float + ; AVX512F-LABEL: sitofpv16i64v16float ; AVX512F: cost of 46 {{.*}} sitofp %1 = sitofp <16 x i64> %a to <16 x float> ret <16 x float> %1 } define <32 x float> @sitofpv32i64v32float(<32 x i64> %a) { - ; SSE2: sitofpv32i64v32float + ; SSE2-LABEL: sitofpv32i64v32float ; SSE2: cost of 240 {{.*}} sitofp ; - ; AVX1: sitofpv32i64v32float + ; AVX1-LABEL: sitofpv32i64v32float ; AVX1: cost of 88 {{.*}} sitofp ; - ; AVX2: sitofpv32i64v32float + ; AVX2-LABEL: sitofpv32i64v32float ; AVX2: cost of 88 {{.*}} sitofp ; - ; AVX512F: sitofpv32i64v32float + ; AVX512F-LABEL: sitofpv32i64v32float ; AVX512F: cost of 92 {{.*}} sitofp %1 = sitofp <32 x i64> %a to <32 x float> ret <32 x float> %1 } define <8 x double> @sitofpv8i1v8double(<8 x double> %a) { - ; SSE2: sitofpv8i1v8double + ; SSE2-LABEL: sitofpv8i1v8double ; SSE2: cost of 80 {{.*}} sitofp ; - ; AVX1: sitofpv8i1v8double + ; AVX1-LABEL: sitofpv8i1v8double ; AVX1: cost of 20 {{.*}} sitofp ; - ; AVX2: sitofpv8i1v8double + ; AVX2-LABEL: sitofpv8i1v8double ; AVX2: cost of 20 {{.*}} sitofp ; - ; AVX512F: sitofpv8i1v8double + ; AVX512F-LABEL: sitofpv8i1v8double ; AVX512F: cost of 4 {{.*}} sitofp %cmpres = fcmp ogt <8 x double> %a, zeroinitializer %1 = sitofp <8 x i1> %cmpres to <8 x double> @@ -661,16 +661,16 @@ define <8 x double> @sitofpv8i1v8double(<8 x double> %a) { } define <16 x float> @sitofpv16i1v16float(<16 x float> %a) { - ; SSE2: sitofpv16i1v16float + ; SSE2-LABEL: sitofpv16i1v16float ; SSE2: cost of 8 {{.*}} sitofp ; - ; AVX1: sitofpv16i1v16float + ; AVX1-LABEL: sitofpv16i1v16float ; AVX1: cost of 44 {{.*}} sitofp ; - ; AVX2: sitofpv16i1v16float + ; AVX2-LABEL: sitofpv16i1v16float ; AVX2: cost of 44 {{.*}} sitofp ; - ; AVX512F: sitofpv16i1v16float + ; AVX512F-LABEL: sitofpv16i1v16float ; AVX512F: cost of 3 {{.*}} sitofp %cmpres = fcmp ogt <16 x float> %a, zeroinitializer %1 = sitofp <16 x i1> %cmpres to <16 x float> diff --git a/test/Analysis/CostModel/X86/sse-itoi.ll b/test/Analysis/CostModel/X86/sse-itoi.ll new file mode 100644 index 000000000000..9e7f26e54d29 --- /dev/null +++ b/test/Analysis/CostModel/X86/sse-itoi.ll @@ -0,0 +1,353 @@ +; RUN: opt -mtriple=x86_64-apple-darwin -mattr=+sse2 -cost-model -analyze < %s | FileCheck --check-prefix=SSE2 %s +; RUN: opt -mtriple=x86_64-apple-darwin -mattr=+sse4.1 -cost-model -analyze < %s | FileCheck --check-prefix=SSE41 %s + +define void @zext_v16i16_to_v16i32(<16 x i16>* %a) { +; SSE2: zext_v16i16_to_v16i32 +; SSE2: cost of 6 {{.*}} zext +; +; SSE41: zext_v16i16_to_v16i32 +; SSE41: cost of 4 {{.*}} zext +; + %1 = load <16 x i16>, <16 x i16>* %a + %2 = zext <16 x i16> %1 to <16 x i32> + store <16 x i32> %2, <16 x i32>* undef, align 4 + ret void +} + +define void @sext_v16i16_to_v16i32(<16 x i16>* %a) { +; SSE2: sext_v16i16_to_v16i32 +; SSE2: cost of 8 {{.*}} sext +; +; SSE41: sext_v16i16_to_v16i32 +; SSE41: cost of 4 {{.*}} sext +; + %1 = load <16 x i16>, <16 x i16>* %a + %2 = sext <16 x i16> %1 to <16 x i32> + store <16 x i32> %2, <16 x i32>* undef, align 4 + ret void +} + +define void @zext_v8i16_to_v8i32(<8 x i16>* %a) { +; SSE2: zext_v8i16_to_v8i32 +; SSE2: cost of 3 {{.*}} zext +; +; SSE41: zext_v8i16_to_v8i32 +; SSE41: cost of 2 {{.*}} zext +; + %1 = load <8 x i16>, <8 x i16>* %a + %2 = zext <8 x i16> %1 to <8 x i32> + store <8 x i32> %2, <8 x i32>* undef, align 4 + ret void +} + +define void @sext_v8i16_to_v8i32(<8 x i16>* %a) { +; SSE2: sext_v8i16_to_v8i32 +; SSE2: cost of 4 {{.*}} sext +; +; SSE41: sext_v8i16_to_v8i32 +; SSE41: cost of 2 {{.*}} sext +; + %1 = load <8 x i16>, <8 x i16>* %a + %2 = sext <8 x i16> %1 to <8 x i32> + store <8 x i32> %2, <8 x i32>* undef, align 4 + ret void +} + +define void @zext_v4i16_to_v4i32(<4 x i16>* %a) { +; SSE2: zext_v4i16_to_v4i32 +; SSE2: cost of 1 {{.*}} zext +; +; SSE41: zext_v4i16_to_v4i32 +; SSE41: cost of 1 {{.*}} zext +; + %1 = load <4 x i16>, <4 x i16>* %a + %2 = zext <4 x i16> %1 to <4 x i32> + store <4 x i32> %2, <4 x i32>* undef, align 4 + ret void +} + +define void @sext_v4i16_to_v4i32(<4 x i16>* %a) { +; SSE2: sext_v4i16_to_v4i32 +; SSE2: cost of 2 {{.*}} sext +; +; SSE41: sext_v4i16_to_v4i32 +; SSE41: cost of 1 {{.*}} sext +; + %1 = load <4 x i16>, <4 x i16>* %a + %2 = sext <4 x i16> %1 to <4 x i32> + store <4 x i32> %2, <4 x i32>* undef, align 4 + ret void +} + +define void @zext_v16i8_to_v16i32(<16 x i8>* %a) { +; SSE2: zext_v16i8_to_v16i32 +; SSE2: cost of 9 {{.*}} zext +; +; SSE41: zext_v16i8_to_v16i32 +; SSE41: cost of 4 {{.*}} zext +; + %1 = load <16 x i8>, <16 x i8>* %a + %2 = zext <16 x i8> %1 to <16 x i32> + store <16 x i32> %2, <16 x i32>* undef, align 4 + ret void +} + +define void @sext_v16i8_to_v16i32(<16 x i8>* %a) { +; SSE2: sext_v16i8_to_v16i32 +; SSE2: cost of 12 {{.*}} sext +; +; SSE41: sext_v16i8_to_v16i32 +; SSE41: cost of 4 {{.*}} sext +; + %1 = load <16 x i8>, <16 x i8>* %a + %2 = sext <16 x i8> %1 to <16 x i32> + store <16 x i32> %2, <16 x i32>* undef, align 4 + ret void +} + +define void @zext_v8i8_to_v8i32(<8 x i8>* %a) { +; SSE2: zext_v8i8_to_v8i32 +; SSE2: cost of 6 {{.*}} zext +; +; SSE41: zext_v8i8_to_v8i32 +; SSE41: cost of 2 {{.*}} zext +; + %1 = load <8 x i8>, <8 x i8>* %a + %2 = zext <8 x i8> %1 to <8 x i32> + store <8 x i32> %2, <8 x i32>* undef, align 4 + ret void +} + +define void @sext_v8i8_to_v8i32(<8 x i8>* %a) { +; SSE2: sext_v8i8_to_v8i32 +; SSE2: cost of 6 {{.*}} sext +; +; SSE41: sext_v8i8_to_v8i32 +; SSE41: cost of 2 {{.*}} sext +; + %1 = load <8 x i8>, <8 x i8>* %a + %2 = sext <8 x i8> %1 to <8 x i32> + store <8 x i32> %2, <8 x i32>* undef, align 4 + ret void +} + +define void @zext_v4i8_to_v4i32(<4 x i8>* %a) { +; SSE2: zext_v4i8_to_v4i32 +; SSE2: cost of 2 {{.*}} zext +; +; SSE41: zext_v4i8_to_v4i32 +; SSE41: cost of 1 {{.*}} zext +; + %1 = load <4 x i8>, <4 x i8>* %a + %2 = zext <4 x i8> %1 to <4 x i32> + store <4 x i32> %2, <4 x i32>* undef, align 4 + ret void +} + +define void @sext_v4i8_to_v4i32(<4 x i8>* %a) { +; SSE2: sext_v4i8_to_v4i32 +; SSE2: cost of 3 {{.*}} sext +; +; SSE41: sext_v4i8_to_v4i32 +; SSE41: cost of 1 {{.*}} sext +; + %1 = load <4 x i8>, <4 x i8>* %a + %2 = sext <4 x i8> %1 to <4 x i32> + store <4 x i32> %2, <4 x i32>* undef, align 4 + ret void +} + +define void @zext_v16i8_to_v16i16(<16 x i8>* %a) { +; SSE2: zext_v16i8_to_v16i16 +; SSE2: cost of 3 {{.*}} zext +; +; SSE41: zext_v16i8_to_v16i16 +; SSE41: cost of 2 {{.*}} zext +; + %1 = load <16 x i8>, <16 x i8>* %a + %2 = zext <16 x i8> %1 to <16 x i16> + store <16 x i16> %2, <16 x i16>* undef, align 4 + ret void +} + +define void @sext_v16i8_to_v16i16(<16 x i8>* %a) { +; SSE2: sext_v16i8_to_v16i16 +; SSE2: cost of 4 {{.*}} sext +; +; SSE41: sext_v16i8_to_v16i16 +; SSE41: cost of 2 {{.*}} sext +; + %1 = load <16 x i8>, <16 x i8>* %a + %2 = sext <16 x i8> %1 to <16 x i16> + store <16 x i16> %2, <16 x i16>* undef, align 4 + ret void +} + +define void @zext_v8i8_to_v8i16(<8 x i8>* %a) { +; SSE2: zext_v8i8_to_v8i16 +; SSE2: cost of 1 {{.*}} zext +; +; SSE41: zext_v8i8_to_v8i16 +; SSE41: cost of 1 {{.*}} zext +; + %1 = load <8 x i8>, <8 x i8>* %a + %2 = zext <8 x i8> %1 to <8 x i16> + store <8 x i16> %2, <8 x i16>* undef, align 4 + ret void +} + +define void @sext_v8i8_to_v8i16(<8 x i8>* %a) { +; SSE2: sext_v8i8_to_v8i16 +; SSE2: cost of 2 {{.*}} sext +; +; SSE41: sext_v8i8_to_v8i16 +; SSE41: cost of 1 {{.*}} sext +; + %1 = load <8 x i8>, <8 x i8>* %a + %2 = sext <8 x i8> %1 to <8 x i16> + store <8 x i16> %2, <8 x i16>* undef, align 4 + ret void +} + +define void @zext_v4i8_to_v4i16(<4 x i8>* %a) { +; SSE2: zext_v4i8_to_v4i16 +; SSE2: cost of 1 {{.*}} zext +; +; SSE41: zext_v4i8_to_v4i16 +; SSE41: cost of 1 {{.*}} zext +; + %1 = load <4 x i8>, <4 x i8>* %a + %2 = zext <4 x i8> %1 to <4 x i16> + store <4 x i16> %2, <4 x i16>* undef, align 4 + ret void +} + +define void @sext_v4i8_to_v4i16(<4 x i8>* %a) { +; SSE2: sext_v4i8_to_v4i16 +; SSE2: cost of 6 {{.*}} sext +; +; SSE41: sext_v4i8_to_v4i16 +; SSE41: cost of 2 {{.*}} sext +; + %1 = load <4 x i8>, <4 x i8>* %a + %2 = sext <4 x i8> %1 to <4 x i16> + store <4 x i16> %2, <4 x i16>* undef, align 4 + ret void +} + +define void @truncate_v16i32_to_v16i16(<16 x i32>* %a) { +; SSE2: truncate_v16i32_to_v16i16 +; SSE2: cost of 10 {{.*}} trunc +; +; SSE41: truncate_v16i32_to_v16i16 +; SSE41: cost of 6 {{.*}} trunc +; + %1 = load <16 x i32>, <16 x i32>* %a + %2 = trunc <16 x i32> %1 to <16 x i16> + store <16 x i16> %2, <16 x i16>* undef, align 4 + ret void +} + +define void @truncate_v8i32_to_v8i16(<8 x i32>* %a) { +; SSE2: truncate_v8i32_to_v8i16 +; SSE2: cost of 5 {{.*}} trunc +; +; SSE41: truncate_v8i32_to_v8i16 +; SSE41: cost of 3 {{.*}} trunc +; + %1 = load <8 x i32>, <8 x i32>* %a + %2 = trunc <8 x i32> %1 to <8 x i16> + store <8 x i16> %2, <8 x i16>* undef, align 4 + ret void +} + +define void @truncate_v4i32_to_v4i16(<4 x i32>* %a) { +; SSE2: truncate_v4i32_to_v4i16 +; SSE2: cost of 3 {{.*}} trunc +; +; SSE41: truncate_v4i32_to_v4i16 +; SSE41: cost of 1 {{.*}} trunc +; + %1 = load <4 x i32>, <4 x i32>* %a + %2 = trunc <4 x i32> %1 to <4 x i16> + store <4 x i16> %2, <4 x i16>* undef, align 4 + ret void +} + +define void @truncate_v16i32_to_v16i8(<16 x i32>* %a) { +; SSE2: truncate_v16i32_to_v16i8 +; SSE2: cost of 7 {{.*}} trunc +; +; SSE41: truncate_v16i32_to_v16i8 +; SSE41: cost of 30 {{.*}} trunc +; + %1 = load <16 x i32>, <16 x i32>* %a + %2 = trunc <16 x i32> %1 to <16 x i8> + store <16 x i8> %2, <16 x i8>* undef, align 4 + ret void +} + +define void @truncate_v8i32_to_v8i8(<8 x i32>* %a) { +; SSE2: truncate_v8i32_to_v8i8 +; SSE2: cost of 4 {{.*}} trunc +; +; SSE41: truncate_v8i32_to_v8i8 +; SSE41: cost of 3 {{.*}} trunc +; + %1 = load <8 x i32>, <8 x i32>* %a + %2 = trunc <8 x i32> %1 to <8 x i8> + store <8 x i8> %2, <8 x i8>* undef, align 4 + ret void +} + +define void @truncate_v4i32_to_v4i8(<4 x i32>* %a) { +; SSE2: truncate_v4i32_to_v4i8 +; SSE2: cost of 3 {{.*}} trunc +; +; SSE41: truncate_v4i32_to_v4i8 +; SSE41: cost of 1 {{.*}} trunc +; + %1 = load <4 x i32>, <4 x i32>* %a + %2 = trunc <4 x i32> %1 to <4 x i8> + store <4 x i8> %2, <4 x i8>* undef, align 4 + ret void +} + +define void @truncate_v16i16_to_v16i8(<16 x i16>* %a) { +; SSE2: truncate_v16i16_to_v16i8 +; SSE2: cost of 3 {{.*}} trunc +; +; SSE41: truncate_v16i16_to_v16i8 +; SSE41: cost of 3 {{.*}} trunc +; + %1 = load <16 x i16>, <16 x i16>* %a + %2 = trunc <16 x i16> %1 to <16 x i8> + store <16 x i8> %2, <16 x i8>* undef, align 4 + ret void +} + +define void @truncate_v8i16_to_v8i8(<8 x i16>* %a) { +; SSE2: truncate_v8i16_to_v8i8 +; SSE2: cost of 2 {{.*}} trunc +; +; SSE41: truncate_v8i16_to_v8i8 +; SSE41: cost of 1 {{.*}} trunc +; + %1 = load <8 x i16>, <8 x i16>* %a + %2 = trunc <8 x i16> %1 to <8 x i8> + store <8 x i8> %2, <8 x i8>* undef, align 4 + ret void +} + +define void @truncate_v4i16_to_v4i8(<4 x i16>* %a) { +; SSE2: truncate_v4i16_to_v4i8 +; SSE2: cost of 4 {{.*}} trunc +; +; SSE41: truncate_v4i16_to_v4i8 +; SSE41: cost of 2 {{.*}} trunc +; + %1 = load <4 x i16>, <4 x i16>* %a + %2 = trunc <4 x i16> %1 to <4 x i8> + store <4 x i8> %2, <4 x i8>* undef, align 4 + ret void +} diff --git a/test/Analysis/CostModel/X86/testshiftashr.ll b/test/Analysis/CostModel/X86/testshiftashr.ll index da4e7d466e2b..13f2bd2019d3 100644 --- a/test/Analysis/CostModel/X86/testshiftashr.ll +++ b/test/Analysis/CostModel/X86/testshiftashr.ll @@ -5,9 +5,9 @@ define %shifttype @shift2i16(%shifttype %a, %shifttype %b) { entry: ; SSE2: shift2i16 - ; SSE2: cost of 20 {{.*}} ashr + ; SSE2: cost of 12 {{.*}} ashr ; SSE2-CODEGEN: shift2i16 - ; SSE2-CODEGEN: sarq %cl + ; SSE2-CODEGEN: psrlq %0 = ashr %shifttype %a , %b ret %shifttype %0 @@ -65,9 +65,9 @@ entry: define %shifttype2i32 @shift2i32(%shifttype2i32 %a, %shifttype2i32 %b) { entry: ; SSE2: shift2i32 - ; SSE2: cost of 20 {{.*}} ashr + ; SSE2: cost of 12 {{.*}} ashr ; SSE2-CODEGEN: shift2i32 - ; SSE2-CODEGEN: sarq %cl + ; SSE2-CODEGEN: psrlq %0 = ashr %shifttype2i32 %a , %b ret %shifttype2i32 %0 @@ -125,9 +125,9 @@ entry: define %shifttype2i64 @shift2i64(%shifttype2i64 %a, %shifttype2i64 %b) { entry: ; SSE2: shift2i64 - ; SSE2: cost of 20 {{.*}} ashr + ; SSE2: cost of 12 {{.*}} ashr ; SSE2-CODEGEN: shift2i64 - ; SSE2-CODEGEN: sarq %cl + ; SSE2-CODEGEN: psrlq %0 = ashr %shifttype2i64 %a , %b ret %shifttype2i64 %0 @@ -137,9 +137,9 @@ entry: define %shifttype4i64 @shift4i64(%shifttype4i64 %a, %shifttype4i64 %b) { entry: ; SSE2: shift4i64 - ; SSE2: cost of 40 {{.*}} ashr + ; SSE2: cost of 24 {{.*}} ashr ; SSE2-CODEGEN: shift4i64 - ; SSE2-CODEGEN: sarq %cl + ; SSE2-CODEGEN: psrlq %0 = ashr %shifttype4i64 %a , %b ret %shifttype4i64 %0 @@ -149,9 +149,9 @@ entry: define %shifttype8i64 @shift8i64(%shifttype8i64 %a, %shifttype8i64 %b) { entry: ; SSE2: shift8i64 - ; SSE2: cost of 80 {{.*}} ashr + ; SSE2: cost of 48 {{.*}} ashr ; SSE2-CODEGEN: shift8i64 - ; SSE2-CODEGEN: sarq %cl + ; SSE2-CODEGEN: psrlq %0 = ashr %shifttype8i64 %a , %b ret %shifttype8i64 %0 @@ -161,9 +161,9 @@ entry: define %shifttype16i64 @shift16i64(%shifttype16i64 %a, %shifttype16i64 %b) { entry: ; SSE2: shift16i64 - ; SSE2: cost of 160 {{.*}} ashr + ; SSE2: cost of 96 {{.*}} ashr ; SSE2-CODEGEN: shift16i64 - ; SSE2-CODEGEN: sarq %cl + ; SSE2-CODEGEN: psrlq %0 = ashr %shifttype16i64 %a , %b ret %shifttype16i64 %0 @@ -173,9 +173,9 @@ entry: define %shifttype32i64 @shift32i64(%shifttype32i64 %a, %shifttype32i64 %b) { entry: ; SSE2: shift32i64 - ; SSE2: cost of 320 {{.*}} ashr + ; SSE2: cost of 192 {{.*}} ashr ; SSE2-CODEGEN: shift32i64 - ; SSE2-CODEGEN: sarq %cl + ; SSE2-CODEGEN: psrlq %0 = ashr %shifttype32i64 %a , %b ret %shifttype32i64 %0 @@ -185,9 +185,9 @@ entry: define %shifttype2i8 @shift2i8(%shifttype2i8 %a, %shifttype2i8 %b) { entry: ; SSE2: shift2i8 - ; SSE2: cost of 20 {{.*}} ashr + ; SSE2: cost of 12 {{.*}} ashr ; SSE2-CODEGEN: shift2i8 - ; SSE2-CODEGEN: sarq %cl + ; SSE2-CODEGEN: psrlq %0 = ashr %shifttype2i8 %a , %b ret %shifttype2i8 %0 diff --git a/test/Analysis/CostModel/X86/testshiftlshr.ll b/test/Analysis/CostModel/X86/testshiftlshr.ll index 5775a42d08ad..52f176fe4d63 100644 --- a/test/Analysis/CostModel/X86/testshiftlshr.ll +++ b/test/Analysis/CostModel/X86/testshiftlshr.ll @@ -5,7 +5,7 @@ define %shifttype @shift2i16(%shifttype %a, %shifttype %b) { entry: ; SSE2: shift2i16 - ; SSE2: cost of 20 {{.*}} lshr + ; SSE2: cost of 4 {{.*}} lshr ; SSE2-CODEGEN: shift2i16 ; SSE2-CODEGEN: psrlq @@ -65,7 +65,7 @@ entry: define %shifttype2i32 @shift2i32(%shifttype2i32 %a, %shifttype2i32 %b) { entry: ; SSE2: shift2i32 - ; SSE2: cost of 20 {{.*}} lshr + ; SSE2: cost of 4 {{.*}} lshr ; SSE2-CODEGEN: shift2i32 ; SSE2-CODEGEN: psrlq @@ -125,7 +125,7 @@ entry: define %shifttype2i64 @shift2i64(%shifttype2i64 %a, %shifttype2i64 %b) { entry: ; SSE2: shift2i64 - ; SSE2: cost of 20 {{.*}} lshr + ; SSE2: cost of 4 {{.*}} lshr ; SSE2-CODEGEN: shift2i64 ; SSE2-CODEGEN: psrlq @@ -137,7 +137,7 @@ entry: define %shifttype4i64 @shift4i64(%shifttype4i64 %a, %shifttype4i64 %b) { entry: ; SSE2: shift4i64 - ; SSE2: cost of 40 {{.*}} lshr + ; SSE2: cost of 8 {{.*}} lshr ; SSE2-CODEGEN: shift4i64 ; SSE2-CODEGEN: psrlq @@ -149,7 +149,7 @@ entry: define %shifttype8i64 @shift8i64(%shifttype8i64 %a, %shifttype8i64 %b) { entry: ; SSE2: shift8i64 - ; SSE2: cost of 80 {{.*}} lshr + ; SSE2: cost of 16 {{.*}} lshr ; SSE2-CODEGEN: shift8i64 ; SSE2-CODEGEN: psrlq @@ -161,7 +161,7 @@ entry: define %shifttype16i64 @shift16i64(%shifttype16i64 %a, %shifttype16i64 %b) { entry: ; SSE2: shift16i64 - ; SSE2: cost of 160 {{.*}} lshr + ; SSE2: cost of 32 {{.*}} lshr ; SSE2-CODEGEN: shift16i64 ; SSE2-CODEGEN: psrlq @@ -173,7 +173,7 @@ entry: define %shifttype32i64 @shift32i64(%shifttype32i64 %a, %shifttype32i64 %b) { entry: ; SSE2: shift32i64 - ; SSE2: cost of 320 {{.*}} lshr + ; SSE2: cost of 64 {{.*}} lshr ; SSE2-CODEGEN: shift32i64 ; SSE2-CODEGEN: psrlq @@ -185,7 +185,7 @@ entry: define %shifttype2i8 @shift2i8(%shifttype2i8 %a, %shifttype2i8 %b) { entry: ; SSE2: shift2i8 - ; SSE2: cost of 20 {{.*}} lshr + ; SSE2: cost of 4 {{.*}} lshr ; SSE2-CODEGEN: shift2i8 ; SSE2-CODEGEN: psrlq diff --git a/test/Analysis/CostModel/X86/testshiftshl.ll b/test/Analysis/CostModel/X86/testshiftshl.ll index d4e33818932b..e385c5bfeeac 100644 --- a/test/Analysis/CostModel/X86/testshiftshl.ll +++ b/test/Analysis/CostModel/X86/testshiftshl.ll @@ -5,7 +5,7 @@ define %shifttype @shift2i16(%shifttype %a, %shifttype %b) { entry: ; SSE2: shift2i16 - ; SSE2: cost of 20 {{.*}} shl + ; SSE2: cost of 4 {{.*}} shl ; SSE2-CODEGEN: shift2i16 ; SSE2-CODEGEN: psllq @@ -65,7 +65,7 @@ entry: define %shifttype2i32 @shift2i32(%shifttype2i32 %a, %shifttype2i32 %b) { entry: ; SSE2: shift2i32 - ; SSE2: cost of 20 {{.*}} shl + ; SSE2: cost of 4 {{.*}} shl ; SSE2-CODEGEN: shift2i32 ; SSE2-CODEGEN: psllq @@ -125,7 +125,7 @@ entry: define %shifttype2i64 @shift2i64(%shifttype2i64 %a, %shifttype2i64 %b) { entry: ; SSE2: shift2i64 - ; SSE2: cost of 20 {{.*}} shl + ; SSE2: cost of 4 {{.*}} shl ; SSE2-CODEGEN: shift2i64 ; SSE2-CODEGEN: psllq @@ -137,7 +137,7 @@ entry: define %shifttype4i64 @shift4i64(%shifttype4i64 %a, %shifttype4i64 %b) { entry: ; SSE2: shift4i64 - ; SSE2: cost of 40 {{.*}} shl + ; SSE2: cost of 8 {{.*}} shl ; SSE2-CODEGEN: shift4i64 ; SSE2-CODEGEN: psllq @@ -149,7 +149,7 @@ entry: define %shifttype8i64 @shift8i64(%shifttype8i64 %a, %shifttype8i64 %b) { entry: ; SSE2: shift8i64 - ; SSE2: cost of 80 {{.*}} shl + ; SSE2: cost of 16 {{.*}} shl ; SSE2-CODEGEN: shift8i64 ; SSE2-CODEGEN: psllq @@ -161,7 +161,7 @@ entry: define %shifttype16i64 @shift16i64(%shifttype16i64 %a, %shifttype16i64 %b) { entry: ; SSE2: shift16i64 - ; SSE2: cost of 160 {{.*}} shl + ; SSE2: cost of 32 {{.*}} shl ; SSE2-CODEGEN: shift16i64 ; SSE2-CODEGEN: psllq @@ -173,7 +173,7 @@ entry: define %shifttype32i64 @shift32i64(%shifttype32i64 %a, %shifttype32i64 %b) { entry: ; SSE2: shift32i64 - ; SSE2: cost of 320 {{.*}} shl + ; SSE2: cost of 64 {{.*}} shl ; SSE2-CODEGEN: shift32i64 ; SSE2-CODEGEN: psllq @@ -185,7 +185,7 @@ entry: define %shifttype2i8 @shift2i8(%shifttype2i8 %a, %shifttype2i8 %b) { entry: ; SSE2: shift2i8 - ; SSE2: cost of 20 {{.*}} shl + ; SSE2: cost of 4 {{.*}} shl ; SSE2-CODEGEN: shift2i8 ; SSE2-CODEGEN: psllq diff --git a/test/Analysis/CostModel/X86/uitofp.ll b/test/Analysis/CostModel/X86/uitofp.ll index 9ffc483e3f5a..08e36650bec4 100644 --- a/test/Analysis/CostModel/X86/uitofp.ll +++ b/test/Analysis/CostModel/X86/uitofp.ll @@ -2,644 +2,708 @@ ; RUN: opt -mtriple=x86_64-apple-darwin -mattr=+avx -cost-model -analyze < %s | FileCheck --check-prefix=AVX --check-prefix=AVX1 %s ; RUN: opt -mtriple=x86_64-apple-darwin -mattr=+avx2 -cost-model -analyze < %s | FileCheck --check-prefix=AVX --check-prefix=AVX2 %s ; RUN: opt -mtriple=x86_64-apple-darwin -mattr=+avx512f -cost-model -analyze < %s | FileCheck --check-prefix=AVX512F %s +; RUN: opt -mtriple=x86_64-apple-darwin -mattr=+avx512dq -cost-model -analyze < %s | FileCheck --check-prefix=AVX512DQ %s define <2 x double> @uitofpv2i8v2double(<2 x i8> %a) { - ; SSE2: uitofpv2i8v2double + ; SSE2-LABEL: uitofpv2i8v2double ; SSE2: cost of 20 {{.*}} uitofp ; - ; AVX1: uitofpv2i8v2double + ; AVX1-LABEL: uitofpv2i8v2double ; AVX1: cost of 4 {{.*}} uitofp ; - ; AVX2: uitofpv2i8v2double + ; AVX2-LABEL: uitofpv2i8v2double ; AVX2: cost of 4 {{.*}} uitofp ; - ; AVX512F: uitofpv2i8v2double - ; AVX512F: cost of 4 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv2i8v2double + ; AVX512F: cost of 2 {{.*}} uitofp %1 = uitofp <2 x i8> %a to <2 x double> ret <2 x double> %1 } define <4 x double> @uitofpv4i8v4double(<4 x i8> %a) { - ; SSE2: uitofpv4i8v4double + ; SSE2-LABEL: uitofpv4i8v4double ; SSE2: cost of 40 {{.*}} uitofp ; - ; AVX1: uitofpv4i8v4double + ; AVX1-LABEL: uitofpv4i8v4double ; AVX1: cost of 2 {{.*}} uitofp ; - ; AVX2: uitofpv4i8v4double + ; AVX2-LABEL: uitofpv4i8v4double ; AVX2: cost of 2 {{.*}} uitofp ; - ; AVX512F: uitofpv4i8v4double + ; AVX512F-LABEL: uitofpv4i8v4double ; AVX512F: cost of 2 {{.*}} uitofp %1 = uitofp <4 x i8> %a to <4 x double> ret <4 x double> %1 } define <8 x double> @uitofpv8i8v8double(<8 x i8> %a) { - ; SSE2: uitofpv8i8v8double + ; SSE2-LABEL: uitofpv8i8v8double ; SSE2: cost of 80 {{.*}} uitofp ; - ; AVX1: uitofpv8i8v8double + ; AVX1-LABEL: uitofpv8i8v8double ; AVX1: cost of 20 {{.*}} uitofp ; - ; AVX2: uitofpv8i8v8double + ; AVX2-LABEL: uitofpv8i8v8double ; AVX2: cost of 20 {{.*}} uitofp ; - ; AVX512F: uitofpv8i8v8double - ; AVX512F: cost of 22 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv8i8v8double + ; AVX512F: cost of 2 {{.*}} uitofp %1 = uitofp <8 x i8> %a to <8 x double> ret <8 x double> %1 } define <16 x double> @uitofpv16i8v16double(<16 x i8> %a) { - ; SSE2: uitofpv16i8v16double + ; SSE2-LABEL: uitofpv16i8v16double ; SSE2: cost of 160 {{.*}} uitofp ; - ; AVX1: uitofpv16i8v16double + ; AVX1-LABEL: uitofpv16i8v16double ; AVX1: cost of 40 {{.*}} uitofp ; - ; AVX2: uitofpv16i8v16double + ; AVX2-LABEL: uitofpv16i8v16double ; AVX2: cost of 40 {{.*}} uitofp ; - ; AVX512F: uitofpv16i8v16double + ; AVX512F-LABEL: uitofpv16i8v16double ; AVX512F: cost of 44 {{.*}} uitofp %1 = uitofp <16 x i8> %a to <16 x double> ret <16 x double> %1 } define <32 x double> @uitofpv32i8v32double(<32 x i8> %a) { - ; SSE2: uitofpv32i8v32double + ; SSE2-LABEL: uitofpv32i8v32double ; SSE2: cost of 320 {{.*}} uitofp ; - ; AVX1: uitofpv32i8v32double + ; AVX1-LABEL: uitofpv32i8v32double ; AVX1: cost of 80 {{.*}} uitofp ; - ; AVX2: uitofpv32i8v32double + ; AVX2-LABEL: uitofpv32i8v32double ; AVX2: cost of 80 {{.*}} uitofp ; - ; AVX512F: uitofpv32i8v32double + ; AVX512F-LABEL: uitofpv32i8v32double ; AVX512F: cost of 88 {{.*}} uitofp %1 = uitofp <32 x i8> %a to <32 x double> ret <32 x double> %1 } define <2 x double> @uitofpv2i16v2double(<2 x i16> %a) { - ; SSE2: uitofpv2i16v2double + ; SSE2-LABEL: uitofpv2i16v2double ; SSE2: cost of 20 {{.*}} uitofp ; - ; AVX1: uitofpv2i16v2double + ; AVX1-LABEL: uitofpv2i16v2double ; AVX1: cost of 4 {{.*}} uitofp ; - ; AVX2: uitofpv2i16v2double + ; AVX2-LABEL: uitofpv2i16v2double ; AVX2: cost of 4 {{.*}} uitofp ; - ; AVX512F: uitofpv2i16v2double - ; AVX512F: cost of 4 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv2i16v2double + ; AVX512F: cost of 5 {{.*}} uitofp %1 = uitofp <2 x i16> %a to <2 x double> ret <2 x double> %1 } define <4 x double> @uitofpv4i16v4double(<4 x i16> %a) { - ; SSE2: uitofpv4i16v4double + ; SSE2-LABEL: uitofpv4i16v4double ; SSE2: cost of 40 {{.*}} uitofp ; - ; AVX1: uitofpv4i16v4double + ; AVX1-LABEL: uitofpv4i16v4double ; AVX1: cost of 2 {{.*}} uitofp ; - ; AVX2: uitofpv4i16v4double + ; AVX2-LABEL: uitofpv4i16v4double ; AVX2: cost of 2 {{.*}} uitofp ; - ; AVX512F: uitofpv4i16v4double + ; AVX512F-LABEL: uitofpv4i16v4double ; AVX512F: cost of 2 {{.*}} uitofp %1 = uitofp <4 x i16> %a to <4 x double> ret <4 x double> %1 } define <8 x double> @uitofpv8i16v8double(<8 x i16> %a) { - ; SSE2: uitofpv8i16v8double + ; SSE2-LABEL: uitofpv8i16v8double ; SSE2: cost of 80 {{.*}} uitofp ; - ; AVX1: uitofpv8i16v8double + ; AVX1-LABEL: uitofpv8i16v8double ; AVX1: cost of 20 {{.*}} uitofp ; - ; AVX2: uitofpv8i16v8double + ; AVX2-LABEL: uitofpv8i16v8double ; AVX2: cost of 20 {{.*}} uitofp ; - ; AVX512F: uitofpv8i16v8double - ; AVX512F: cost of 22 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv8i16v8double + ; AVX512F: cost of 2 {{.*}} uitofp %1 = uitofp <8 x i16> %a to <8 x double> ret <8 x double> %1 } define <16 x double> @uitofpv16i16v16double(<16 x i16> %a) { - ; SSE2: uitofpv16i16v16double + ; SSE2-LABEL: uitofpv16i16v16double ; SSE2: cost of 160 {{.*}} uitofp ; - ; AVX1: uitofpv16i16v16double + ; AVX1-LABEL: uitofpv16i16v16double ; AVX1: cost of 40 {{.*}} uitofp ; - ; AVX2: uitofpv16i16v16double + ; AVX2-LABEL: uitofpv16i16v16double ; AVX2: cost of 40 {{.*}} uitofp ; - ; AVX512F: uitofpv16i16v16double + ; AVX512F-LABEL: uitofpv16i16v16double ; AVX512F: cost of 44 {{.*}} uitofp %1 = uitofp <16 x i16> %a to <16 x double> ret <16 x double> %1 } define <32 x double> @uitofpv32i16v32double(<32 x i16> %a) { - ; SSE2: uitofpv32i16v32double + ; SSE2-LABEL: uitofpv32i16v32double ; SSE2: cost of 320 {{.*}} uitofp ; - ; AVX1: uitofpv32i16v32double + ; AVX1-LABEL: uitofpv32i16v32double ; AVX1: cost of 80 {{.*}} uitofp ; - ; AVX2: uitofpv32i16v32double + ; AVX2-LABEL: uitofpv32i16v32double ; AVX2: cost of 80 {{.*}} uitofp ; - ; AVX512F: uitofpv32i16v32double + ; AVX512F-LABEL: uitofpv32i16v32double ; AVX512F: cost of 88 {{.*}} uitofp %1 = uitofp <32 x i16> %a to <32 x double> ret <32 x double> %1 } define <2 x double> @uitofpv2i32v2double(<2 x i32> %a) { - ; SSE2: uitofpv2i32v2double + ; SSE2-LABEL: uitofpv2i32v2double ; SSE2: cost of 20 {{.*}} uitofp ; - ; AVX1: uitofpv2i32v2double + ; AVX1-LABEL: uitofpv2i32v2double ; AVX1: cost of 4 {{.*}} uitofp ; - ; AVX2: uitofpv2i32v2double + ; AVX2-LABEL: uitofpv2i32v2double ; AVX2: cost of 4 {{.*}} uitofp ; - ; AVX512F: uitofpv2i32v2double + ; AVX512F-LABEL: uitofpv2i32v2double ; AVX512F: cost of 4 {{.*}} uitofp %1 = uitofp <2 x i32> %a to <2 x double> ret <2 x double> %1 } define <4 x double> @uitofpv4i32v4double(<4 x i32> %a) { - ; SSE2: uitofpv4i32v4double + ; SSE2-LABEL: uitofpv4i32v4double ; SSE2: cost of 40 {{.*}} uitofp ; - ; AVX1: uitofpv4i32v4double + ; AVX1-LABEL: uitofpv4i32v4double ; AVX1: cost of 6 {{.*}} uitofp ; - ; AVX2: uitofpv4i32v4double + ; AVX2-LABEL: uitofpv4i32v4double ; AVX2: cost of 6 {{.*}} uitofp ; - ; AVX512F: uitofpv4i32v4double - ; AVX512F: cost of 6 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv4i32v4double + ; AVX512F: cost of 1 {{.*}} uitofp %1 = uitofp <4 x i32> %a to <4 x double> ret <4 x double> %1 } define <8 x double> @uitofpv8i32v8double(<8 x i32> %a) { - ; SSE2: uitofpv8i32v8double + ; SSE2-LABEL: uitofpv8i32v8double ; SSE2: cost of 80 {{.*}} uitofp ; - ; AVX1: uitofpv8i32v8double + ; AVX1-LABEL: uitofpv8i32v8double ; AVX1: cost of 20 {{.*}} uitofp ; - ; AVX2: uitofpv8i32v8double + ; AVX2-LABEL: uitofpv8i32v8double ; AVX2: cost of 20 {{.*}} uitofp ; - ; AVX512F: uitofpv8i32v8double - ; AVX512F: cost of 22 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv8i32v8double + ; AVX512F: cost of 1 {{.*}} uitofp %1 = uitofp <8 x i32> %a to <8 x double> ret <8 x double> %1 } define <16 x double> @uitofpv16i32v16double(<16 x i32> %a) { - ; SSE2: uitofpv16i32v16double + ; SSE2-LABEL: uitofpv16i32v16double ; SSE2: cost of 160 {{.*}} uitofp ; - ; AVX1: uitofpv16i32v16double + ; AVX1-LABEL: uitofpv16i32v16double ; AVX1: cost of 40 {{.*}} uitofp ; - ; AVX2: uitofpv16i32v16double + ; AVX2-LABEL: uitofpv16i32v16double ; AVX2: cost of 40 {{.*}} uitofp ; - ; AVX512F: uitofpv16i32v16double + ; AVX512F-LABEL: uitofpv16i32v16double ; AVX512F: cost of 44 {{.*}} uitofp %1 = uitofp <16 x i32> %a to <16 x double> ret <16 x double> %1 } define <32 x double> @uitofpv32i32v32double(<32 x i32> %a) { - ; SSE2: uitofpv32i32v32double + ; SSE2-LABEL: uitofpv32i32v32double ; SSE2: cost of 320 {{.*}} uitofp ; - ; AVX1: uitofpv32i32v32double + ; AVX1-LABEL: uitofpv32i32v32double ; AVX1: cost of 80 {{.*}} uitofp ; - ; AVX2: uitofpv32i32v32double + ; AVX2-LABEL: uitofpv32i32v32double ; AVX2: cost of 80 {{.*}} uitofp ; - ; AVX512F: uitofpv32i32v32double + ; AVX512F-LABEL: uitofpv32i32v32double ; AVX512F: cost of 88 {{.*}} uitofp %1 = uitofp <32 x i32> %a to <32 x double> ret <32 x double> %1 } define <2 x double> @uitofpv2i64v2double(<2 x i64> %a) { - ; SSE2: uitofpv2i64v2double + ; SSE2-LABEL: uitofpv2i64v2double ; SSE2: cost of 20 {{.*}} uitofp ; - ; AVX1: uitofpv2i64v2double + ; AVX1-LABEL: uitofpv2i64v2double ; AVX1: cost of 20 {{.*}} uitofp ; - ; AVX2: uitofpv2i64v2double + ; AVX2-LABEL: uitofpv2i64v2double ; AVX2: cost of 20 {{.*}} uitofp ; - ; AVX512F: uitofpv2i64v2double - ; AVX512F: cost of 20 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv2i64v2double + ; AVX512F: cost of 5 {{.*}} uitofp + ; + ; AVX512DQ: uitofpv2i64v2double + ; AVX512DQ: cost of 1 {{.*}} uitofp %1 = uitofp <2 x i64> %a to <2 x double> ret <2 x double> %1 } define <4 x double> @uitofpv4i64v4double(<4 x i64> %a) { - ; SSE2: uitofpv4i64v4double + ; SSE2-LABEL: uitofpv4i64v4double ; SSE2: cost of 40 {{.*}} uitofp ; - ; AVX1: uitofpv4i64v4double + ; AVX1-LABEL: uitofpv4i64v4double ; AVX1: cost of 40 {{.*}} uitofp ; - ; AVX2: uitofpv4i64v4double + ; AVX2-LABEL: uitofpv4i64v4double ; AVX2: cost of 40 {{.*}} uitofp ; - ; AVX512F: uitofpv4i64v4double - ; AVX512F: cost of 40 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv4i64v4double + ; AVX512F: cost of 12 {{.*}} uitofp + ; + ; AVX512DQ: uitofpv4i64v4double + ; AVX512DQ: cost of 1 {{.*}} uitofp %1 = uitofp <4 x i64> %a to <4 x double> ret <4 x double> %1 } define <8 x double> @uitofpv8i64v8double(<8 x i64> %a) { - ; SSE2: uitofpv8i64v8double + ; SSE2-LABEL: uitofpv8i64v8double ; SSE2: cost of 80 {{.*}} uitofp ; - ; AVX1: uitofpv8i64v8double + ; AVX1-LABEL: uitofpv8i64v8double ; AVX1: cost of 20 {{.*}} uitofp ; - ; AVX2: uitofpv8i64v8double + ; AVX2-LABEL: uitofpv8i64v8double ; AVX2: cost of 20 {{.*}} uitofp ; - ; AVX512F: uitofpv8i64v8double - ; AVX512F: cost of 22 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv8i64v8double + ; AVX512F: cost of 26 {{.*}} uitofp + ; + ; AVX512DQ: uitofpv8i64v8double + ; AVX512DQ: cost of 1 {{.*}} uitofp %1 = uitofp <8 x i64> %a to <8 x double> ret <8 x double> %1 } define <16 x double> @uitofpv16i64v16double(<16 x i64> %a) { - ; SSE2: uitofpv16i64v16double + ; SSE2-LABEL: uitofpv16i64v16double ; SSE2: cost of 160 {{.*}} uitofp ; - ; AVX1: uitofpv16i64v16double + ; AVX1-LABEL: uitofpv16i64v16double ; AVX1: cost of 40 {{.*}} uitofp ; - ; AVX2: uitofpv16i64v16double + ; AVX2-LABEL: uitofpv16i64v16double ; AVX2: cost of 40 {{.*}} uitofp ; - ; AVX512F: uitofpv16i64v16double + ; AVX512F-LABEL: uitofpv16i64v16double ; AVX512F: cost of 44 {{.*}} uitofp + ; + ; AVX512DQ: uitofpv16i64v16double + ; AVX512DQ: cost of 44 {{.*}} uitofp %1 = uitofp <16 x i64> %a to <16 x double> ret <16 x double> %1 } define <32 x double> @uitofpv32i64v32double(<32 x i64> %a) { - ; SSE2: uitofpv32i64v32double + ; SSE2-LABEL: uitofpv32i64v32double ; SSE2: cost of 320 {{.*}} uitofp ; - ; AVX1: uitofpv32i64v32double + ; AVX1-LABEL: uitofpv32i64v32double ; AVX1: cost of 80 {{.*}} uitofp ; - ; AVX2: uitofpv32i64v32double + ; AVX2-LABEL: uitofpv32i64v32double ; AVX2: cost of 80 {{.*}} uitofp ; - ; AVX512F: uitofpv32i64v32double + ; AVX512F-LABEL: uitofpv32i64v32double ; AVX512F: cost of 88 {{.*}} uitofp + ; + ; AVX512DQ: uitofpv32i64v32double + ; AVX512DQ: cost of 88 {{.*}} uitofp %1 = uitofp <32 x i64> %a to <32 x double> ret <32 x double> %1 } define <2 x float> @uitofpv2i8v2float(<2 x i8> %a) { - ; SSE2: uitofpv2i8v2float + ; SSE2-LABEL: uitofpv2i8v2float ; SSE2: cost of 15 {{.*}} uitofp ; - ; AVX1: uitofpv2i8v2float + ; AVX1-LABEL: uitofpv2i8v2float ; AVX1: cost of 4 {{.*}} uitofp ; - ; AVX2: uitofpv2i8v2float + ; AVX2-LABEL: uitofpv2i8v2float ; AVX2: cost of 4 {{.*}} uitofp ; - ; AVX512F: uitofpv2i8v2float + ; AVX512F-LABEL: uitofpv2i8v2float ; AVX512F: cost of 4 {{.*}} uitofp %1 = uitofp <2 x i8> %a to <2 x float> ret <2 x float> %1 } define <4 x float> @uitofpv4i8v4float(<4 x i8> %a) { - ; SSE2: uitofpv4i8v4float + ; SSE2-LABEL: uitofpv4i8v4float ; SSE2: cost of 8 {{.*}} uitofp ; - ; AVX1: uitofpv4i8v4float + ; AVX1-LABEL: uitofpv4i8v4float ; AVX1: cost of 2 {{.*}} uitofp ; - ; AVX2: uitofpv4i8v4float + ; AVX2-LABEL: uitofpv4i8v4float ; AVX2: cost of 2 {{.*}} uitofp ; - ; AVX512F: uitofpv4i8v4float + ; AVX512F-LABEL: uitofpv4i8v4float ; AVX512F: cost of 2 {{.*}} uitofp %1 = uitofp <4 x i8> %a to <4 x float> ret <4 x float> %1 } define <8 x float> @uitofpv8i8v8float(<8 x i8> %a) { - ; SSE2: uitofpv8i8v8float + ; SSE2-LABEL: uitofpv8i8v8float ; SSE2: cost of 15 {{.*}} uitofp ; - ; AVX1: uitofpv8i8v8float + ; AVX1-LABEL: uitofpv8i8v8float ; AVX1: cost of 5 {{.*}} uitofp ; - ; AVX2: uitofpv8i8v8float + ; AVX2-LABEL: uitofpv8i8v8float ; AVX2: cost of 5 {{.*}} uitofp ; - ; AVX512F: uitofpv8i8v8float - ; AVX512F: cost of 5 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv8i8v8float + ; AVX512F: cost of 2 {{.*}} uitofp %1 = uitofp <8 x i8> %a to <8 x float> ret <8 x float> %1 } define <16 x float> @uitofpv16i8v16float(<16 x i8> %a) { - ; SSE2: uitofpv16i8v16float + ; SSE2-LABEL: uitofpv16i8v16float ; SSE2: cost of 8 {{.*}} uitofp ; - ; AVX1: uitofpv16i8v16float + ; AVX1-LABEL: uitofpv16i8v16float ; AVX1: cost of 44 {{.*}} uitofp ; - ; AVX2: uitofpv16i8v16float + ; AVX2-LABEL: uitofpv16i8v16float ; AVX2: cost of 44 {{.*}} uitofp ; - ; AVX512F: uitofpv16i8v16float - ; AVX512F: cost of 46 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv16i8v16float + ; AVX512F: cost of 2 {{.*}} uitofp %1 = uitofp <16 x i8> %a to <16 x float> ret <16 x float> %1 } define <32 x float> @uitofpv32i8v32float(<32 x i8> %a) { - ; SSE2: uitofpv32i8v32float + ; SSE2-LABEL: uitofpv32i8v32float ; SSE2: cost of 16 {{.*}} uitofp ; - ; AVX1: uitofpv32i8v32float + ; AVX1-LABEL: uitofpv32i8v32float ; AVX1: cost of 88 {{.*}} uitofp ; - ; AVX2: uitofpv32i8v32float + ; AVX2-LABEL: uitofpv32i8v32float ; AVX2: cost of 88 {{.*}} uitofp ; - ; AVX512F: uitofpv32i8v32float + ; AVX512F-LABEL: uitofpv32i8v32float ; AVX512F: cost of 92 {{.*}} uitofp %1 = uitofp <32 x i8> %a to <32 x float> ret <32 x float> %1 } define <2 x float> @uitofpv2i16v2float(<2 x i16> %a) { - ; SSE2: uitofpv2i16v2float + ; SSE2-LABEL: uitofpv2i16v2float ; SSE2: cost of 15 {{.*}} uitofp ; - ; AVX1: uitofpv2i16v2float + ; AVX1-LABEL: uitofpv2i16v2float ; AVX1: cost of 4 {{.*}} uitofp ; - ; AVX2: uitofpv2i16v2float + ; AVX2-LABEL: uitofpv2i16v2float ; AVX2: cost of 4 {{.*}} uitofp ; - ; AVX512F: uitofpv2i16v2float + ; AVX512F-LABEL: uitofpv2i16v2float ; AVX512F: cost of 4 {{.*}} uitofp %1 = uitofp <2 x i16> %a to <2 x float> ret <2 x float> %1 } define <4 x float> @uitofpv4i16v4float(<4 x i16> %a) { - ; SSE2: uitofpv4i16v4float + ; SSE2-LABEL: uitofpv4i16v4float ; SSE2: cost of 8 {{.*}} uitofp ; - ; AVX1: uitofpv4i16v4float + ; AVX1-LABEL: uitofpv4i16v4float ; AVX1: cost of 2 {{.*}} uitofp ; - ; AVX2: uitofpv4i16v4float + ; AVX2-LABEL: uitofpv4i16v4float ; AVX2: cost of 2 {{.*}} uitofp ; - ; AVX512F: uitofpv4i16v4float + ; AVX512F-LABEL: uitofpv4i16v4float ; AVX512F: cost of 2 {{.*}} uitofp %1 = uitofp <4 x i16> %a to <4 x float> ret <4 x float> %1 } define <8 x float> @uitofpv8i16v8float(<8 x i16> %a) { - ; SSE2: uitofpv8i16v8float + ; SSE2-LABEL: uitofpv8i16v8float ; SSE2: cost of 15 {{.*}} uitofp ; - ; AVX1: uitofpv8i16v8float + ; AVX1-LABEL: uitofpv8i16v8float ; AVX1: cost of 5 {{.*}} uitofp ; - ; AVX2: uitofpv8i16v8float + ; AVX2-LABEL: uitofpv8i16v8float ; AVX2: cost of 5 {{.*}} uitofp ; - ; AVX512F: uitofpv8i16v8float - ; AVX512F: cost of 5 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv8i16v8float + ; AVX512F: cost of 2 {{.*}} uitofp %1 = uitofp <8 x i16> %a to <8 x float> ret <8 x float> %1 } define <16 x float> @uitofpv16i16v16float(<16 x i16> %a) { - ; SSE2: uitofpv16i16v16float + ; SSE2-LABEL: uitofpv16i16v16float ; SSE2: cost of 30 {{.*}} uitofp ; - ; AVX1: uitofpv16i16v16float + ; AVX1-LABEL: uitofpv16i16v16float ; AVX1: cost of 44 {{.*}} uitofp ; - ; AVX2: uitofpv16i16v16float + ; AVX2-LABEL: uitofpv16i16v16float ; AVX2: cost of 44 {{.*}} uitofp ; - ; AVX512F: uitofpv16i16v16float - ; AVX512F: cost of 46 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv16i16v16float + ; AVX512F: cost of 2 {{.*}} uitofp %1 = uitofp <16 x i16> %a to <16 x float> ret <16 x float> %1 } define <32 x float> @uitofpv32i16v32float(<32 x i16> %a) { - ; SSE2: uitofpv32i16v32float + ; SSE2-LABEL: uitofpv32i16v32float ; SSE2: cost of 60 {{.*}} uitofp ; - ; AVX1: uitofpv32i16v32float + ; AVX1-LABEL: uitofpv32i16v32float ; AVX1: cost of 88 {{.*}} uitofp ; - ; AVX2: uitofpv32i16v32float + ; AVX2-LABEL: uitofpv32i16v32float ; AVX2: cost of 88 {{.*}} uitofp ; - ; AVX512F: uitofpv32i16v32float + ; AVX512F-LABEL: uitofpv32i16v32float ; AVX512F: cost of 92 {{.*}} uitofp %1 = uitofp <32 x i16> %a to <32 x float> ret <32 x float> %1 } define <2 x float> @uitofpv2i32v2float(<2 x i32> %a) { - ; SSE2: uitofpv2i32v2float + ; SSE2-LABEL: uitofpv2i32v2float ; SSE2: cost of 15 {{.*}} uitofp ; - ; AVX1: uitofpv2i32v2float + ; AVX1-LABEL: uitofpv2i32v2float ; AVX1: cost of 4 {{.*}} uitofp ; - ; AVX2: uitofpv2i32v2float + ; AVX2-LABEL: uitofpv2i32v2float ; AVX2: cost of 4 {{.*}} uitofp ; - ; AVX512F: uitofpv2i32v2float - ; AVX512F: cost of 4 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv2i32v2float + ; AVX512F: cost of 2 {{.*}} uitofp %1 = uitofp <2 x i32> %a to <2 x float> ret <2 x float> %1 } define <4 x float> @uitofpv4i32v4float(<4 x i32> %a) { - ; SSE2: uitofpv4i32v4float + ; SSE2-LABEL: uitofpv4i32v4float ; SSE2: cost of 8 {{.*}} uitofp ; - ; AVX1: uitofpv4i32v4float + ; AVX1-LABEL: uitofpv4i32v4float ; AVX1: cost of 6 {{.*}} uitofp ; - ; AVX2: uitofpv4i32v4float + ; AVX2-LABEL: uitofpv4i32v4float ; AVX2: cost of 6 {{.*}} uitofp ; - ; AVX512F: uitofpv4i32v4float - ; AVX512F: cost of 6 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv4i32v4float + ; AVX512F: cost of 1 {{.*}} uitofp %1 = uitofp <4 x i32> %a to <4 x float> ret <4 x float> %1 } define <8 x float> @uitofpv8i32v8float(<8 x i32> %a) { - ; SSE2: uitofpv8i32v8float + ; SSE2-LABEL: uitofpv8i32v8float ; SSE2: cost of 16 {{.*}} uitofp ; - ; AVX1: uitofpv8i32v8float + ; AVX1-LABEL: uitofpv8i32v8float ; AVX1: cost of 9 {{.*}} uitofp ; - ; AVX2: uitofpv8i32v8float + ; AVX2-LABEL: uitofpv8i32v8float ; AVX2: cost of 8 {{.*}} uitofp ; - ; AVX512F: uitofpv8i32v8float - ; AVX512F: cost of 8 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv8i32v8float + ; AVX512F: cost of 1 {{.*}} uitofp %1 = uitofp <8 x i32> %a to <8 x float> ret <8 x float> %1 } define <16 x float> @uitofpv16i32v16float(<16 x i32> %a) { - ; SSE2: uitofpv16i32v16float + ; SSE2-LABEL: uitofpv16i32v16float ; SSE2: cost of 32 {{.*}} uitofp ; - ; AVX1: uitofpv16i32v16float + ; AVX1-LABEL: uitofpv16i32v16float ; AVX1: cost of 44 {{.*}} uitofp ; - ; AVX2: uitofpv16i32v16float + ; AVX2-LABEL: uitofpv16i32v16float ; AVX2: cost of 44 {{.*}} uitofp ; - ; AVX512F: uitofpv16i32v16float - ; AVX512F: cost of 46 {{.*}} uitofp + ; AVX512F-LABEL: uitofpv16i32v16float + ; AVX512F: cost of 1 {{.*}} uitofp %1 = uitofp <16 x i32> %a to <16 x float> ret <16 x float> %1 } define <32 x float> @uitofpv32i32v32float(<32 x i32> %a) { - ; SSE2: uitofpv32i32v32float + ; SSE2-LABEL: uitofpv32i32v32float ; SSE2: cost of 64 {{.*}} uitofp ; - ; AVX1: uitofpv32i32v32float + ; AVX1-LABEL: uitofpv32i32v32float ; AVX1: cost of 88 {{.*}} uitofp ; - ; AVX2: uitofpv32i32v32float + ; AVX2-LABEL: uitofpv32i32v32float ; AVX2: cost of 88 {{.*}} uitofp ; - ; AVX512F: uitofpv32i32v32float + ; AVX512F-LABEL: uitofpv32i32v32float ; AVX512F: cost of 92 {{.*}} uitofp %1 = uitofp <32 x i32> %a to <32 x float> ret <32 x float> %1 } define <2 x float> @uitofpv2i64v2float(<2 x i64> %a) { - ; SSE2: uitofpv2i64v2float + ; SSE2-LABEL: uitofpv2i64v2float ; SSE2: cost of 15 {{.*}} uitofp ; - ; AVX1: uitofpv2i64v2float + ; AVX1-LABEL: uitofpv2i64v2float ; AVX1: cost of 4 {{.*}} uitofp ; - ; AVX2: uitofpv2i64v2float + ; AVX2-LABEL: uitofpv2i64v2float ; AVX2: cost of 4 {{.*}} uitofp ; - ; AVX512F: uitofpv2i64v2float + ; AVX512F-LABEL: uitofpv2i64v2float ; AVX512F: cost of 4 {{.*}} uitofp %1 = uitofp <2 x i64> %a to <2 x float> ret <2 x float> %1 } define <4 x float> @uitofpv4i64v4float(<4 x i64> %a) { - ; SSE2: uitofpv4i64v4float + ; SSE2-LABEL: uitofpv4i64v4float ; SSE2: cost of 30 {{.*}} uitofp ; - ; AVX1: uitofpv4i64v4float + ; AVX1-LABEL: uitofpv4i64v4float ; AVX1: cost of 10 {{.*}} uitofp ; - ; AVX2: uitofpv4i64v4float + ; AVX2-LABEL: uitofpv4i64v4float ; AVX2: cost of 10 {{.*}} uitofp ; - ; AVX512F: uitofpv4i64v4float + ; AVX512F-LABEL: uitofpv4i64v4float ; AVX512F: cost of 10 {{.*}} uitofp %1 = uitofp <4 x i64> %a to <4 x float> ret <4 x float> %1 } define <8 x float> @uitofpv8i64v8float(<8 x i64> %a) { - ; SSE2: uitofpv8i64v8float + ; SSE2-LABEL: uitofpv8i64v8float ; SSE2: cost of 60 {{.*}} uitofp ; - ; AVX1: uitofpv8i64v8float + ; AVX1-LABEL: uitofpv8i64v8float ; AVX1: cost of 22 {{.*}} uitofp ; - ; AVX2: uitofpv8i64v8float + ; AVX2-LABEL: uitofpv8i64v8float ; AVX2: cost of 22 {{.*}} uitofp ; - ; AVX512F: uitofpv8i64v8float + ; AVX512F-LABEL: uitofpv8i64v8float ; AVX512F: cost of 22 {{.*}} uitofp %1 = uitofp <8 x i64> %a to <8 x float> ret <8 x float> %1 } define <16 x float> @uitofpv16i64v16float(<16 x i64> %a) { - ; SSE2: uitofpv16i64v16float + ; SSE2-LABEL: uitofpv16i64v16float ; SSE2: cost of 120 {{.*}} uitofp ; - ; AVX1: uitofpv16i64v16float + ; AVX1-LABEL: uitofpv16i64v16float ; AVX1: cost of 44 {{.*}} uitofp ; - ; AVX2: uitofpv16i64v16float + ; AVX2-LABEL: uitofpv16i64v16float ; AVX2: cost of 44 {{.*}} uitofp ; - ; AVX512F: uitofpv16i64v16float + ; AVX512F-LABEL: uitofpv16i64v16float ; AVX512F: cost of 46 {{.*}} uitofp %1 = uitofp <16 x i64> %a to <16 x float> ret <16 x float> %1 } define <32 x float> @uitofpv32i64v32float(<32 x i64> %a) { - ; SSE2: uitofpv32i64v32float + ; SSE2-LABEL: uitofpv32i64v32float ; SSE2: cost of 240 {{.*}} uitofp ; - ; AVX1: uitofpv32i64v32float + ; AVX1-LABEL: uitofpv32i64v32float ; AVX1: cost of 88 {{.*}} uitofp ; - ; AVX2: uitofpv32i64v32float + ; AVX2-LABEL: uitofpv32i64v32float ; AVX2: cost of 88 {{.*}} uitofp ; - ; AVX512F: uitofpv32i64v32float + ; AVX512F-LABEL: uitofpv32i64v32float ; AVX512F: cost of 92 {{.*}} uitofp %1 = uitofp <32 x i64> %a to <32 x float> ret <32 x float> %1 } +define <8 x i32> @fptouiv8f32v8i32(<8 x float> %a) { + ; AVX512F-LABEL: fptouiv8f32v8i32 + ; AVX512F: cost of 1 {{.*}} fptoui + %1 = fptoui <8 x float> %a to <8 x i32> + ret <8 x i32> %1 +} + +define <4 x i32> @fptouiv4f32v4i32(<4 x float> %a) { + ; AVX512F-LABEL: fptouiv4f32v4i32 + ; AVX512F: cost of 1 {{.*}} fptoui + %1 = fptoui <4 x float> %a to <4 x i32> + ret <4 x i32> %1 +} + +define <2 x i32> @fptouiv2f32v2i32(<2 x float> %a) { + ; AVX512F-LABEL: fptouiv2f32v2i32 + ; AVX512F: cost of 1 {{.*}} fptoui + %1 = fptoui <2 x float> %a to <2 x i32> + ret <2 x i32> %1 +} + +define <16 x i32> @fptouiv16f32v16i32(<16 x float> %a) { + ; AVX512F-LABEL: fptouiv16f32v16i32 + ; AVX512F: cost of 1 {{.*}} fptoui + %1 = fptoui <16 x float> %a to <16 x i32> + ret <16 x i32> %1 +} + +define <8 x i64> @fptouiv8f32v8i64(<8 x float> %a) { + ; AVX512DQ-LABEL: fptouiv8f32v8i64 + ; AVX512DQ: cost of 1 {{.*}} fptoui + %1 = fptoui <8 x float> %a to <8 x i64> + ret <8 x i64> %1 +} + +define <4 x i64> @fptouiv4f32v4i64(<4 x float> %a) { + ; AVX512DQ-LABEL: fptouiv4f32v4i64 + ; AVX512DQ: cost of 1 {{.*}} fptoui + %1 = fptoui <4 x float> %a to <4 x i64> + ret <4 x i64> %1 +} + +define <2 x i64> @fptouiv2f32v2i64(<2 x float> %a) { + ; AVX512DQ-LABEL: fptouiv2f32v2i64 + ; AVX512DQ: cost of 1 {{.*}} fptoui + %1 = fptoui <2 x float> %a to <2 x i64> + ret <2 x i64> %1 +} diff --git a/test/Analysis/CostModel/X86/vector_gep.ll b/test/Analysis/CostModel/X86/vector_gep.ll new file mode 100644 index 000000000000..e49f25871d66 --- /dev/null +++ b/test/Analysis/CostModel/X86/vector_gep.ll @@ -0,0 +1,17 @@ +; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-linux-unknown-unknown -mattr=+avx512f | FileCheck %s + +%struct.S = type { [1000 x i32] } + + +declare <4 x i32> @llvm.masked.gather.v4i32(<4 x i32*>, i32, <4 x i1>, <4 x i32>) + +define <4 x i32> @foov(<4 x %struct.S*> %s, i64 %base){ + %temp = insertelement <4 x i64> undef, i64 %base, i32 0 + %vector = shufflevector <4 x i64> %temp, <4 x i64> undef, <4 x i32> zeroinitializer +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds %struct.S + %B = getelementptr inbounds %struct.S, <4 x %struct.S*> %s, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer +;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds [1000 x i32] + %arrayidx = getelementptr inbounds [1000 x i32], <4 x [1000 x i32]*> %B, <4 x i64> zeroinitializer, <4 x i64> %vector + %res = call <4 x i32> @llvm.masked.gather.v4i32(<4 x i32*> %arrayidx, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef) + ret <4 x i32> %res +} diff --git a/test/Analysis/CostModel/X86/vshift-ashr-cost.ll b/test/Analysis/CostModel/X86/vshift-ashr-cost.ll new file mode 100644 index 000000000000..a0d07d7b6ec0 --- /dev/null +++ b/test/Analysis/CostModel/X86/vshift-ashr-cost.ll @@ -0,0 +1,392 @@ +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -mattr=+sse2,-sse4.1 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=SSE2 +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=SSE41 +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7-avx -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=AVX +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=core-avx2 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=AVX2 +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=bdver2 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=XOP -check-prefix=XOPAVX +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=bdver4 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=XOP -check-prefix=XOPAVX2 + +; Verify the cost of vector arithmetic shift right instructions. + +; +; Variable Shifts +; + +define <2 x i64> @var_shift_v2i64(<2 x i64> %a, <2 x i64> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v2i64': +; SSE2: Found an estimated cost of 12 for instruction: %shift +; SSE41: Found an estimated cost of 12 for instruction: %shift +; AVX: Found an estimated cost of 12 for instruction: %shift +; AVX2: Found an estimated cost of 4 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = ashr <2 x i64> %a, %b + ret <2 x i64> %shift +} + +define <4 x i64> @var_shift_v4i64(<4 x i64> %a, <4 x i64> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v4i64': +; SSE2: Found an estimated cost of 24 for instruction: %shift +; SSE41: Found an estimated cost of 24 for instruction: %shift +; AVX: Found an estimated cost of 24 for instruction: %shift +; AVX2: Found an estimated cost of 4 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = ashr <4 x i64> %a, %b + ret <4 x i64> %shift +} + +define <4 x i32> @var_shift_v4i32(<4 x i32> %a, <4 x i32> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v4i32': +; SSE2: Found an estimated cost of 16 for instruction: %shift +; SSE41: Found an estimated cost of 16 for instruction: %shift +; AVX: Found an estimated cost of 16 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = ashr <4 x i32> %a, %b + ret <4 x i32> %shift +} + +define <8 x i32> @var_shift_v8i32(<8 x i32> %a, <8 x i32> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v8i32': +; SSE2: Found an estimated cost of 32 for instruction: %shift +; SSE41: Found an estimated cost of 32 for instruction: %shift +; AVX: Found an estimated cost of 32 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 4 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = ashr <8 x i32> %a, %b + ret <8 x i32> %shift +} + +define <8 x i16> @var_shift_v8i16(<8 x i16> %a, <8 x i16> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v8i16': +; SSE2: Found an estimated cost of 32 for instruction: %shift +; SSE41: Found an estimated cost of 32 for instruction: %shift +; AVX: Found an estimated cost of 32 for instruction: %shift +; AVX2: Found an estimated cost of 32 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = ashr <8 x i16> %a, %b + ret <8 x i16> %shift +} + +define <16 x i16> @var_shift_v16i16(<16 x i16> %a, <16 x i16> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v16i16': +; SSE2: Found an estimated cost of 64 for instruction: %shift +; SSE41: Found an estimated cost of 64 for instruction: %shift +; AVX: Found an estimated cost of 64 for instruction: %shift +; AVX2: Found an estimated cost of 10 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = ashr <16 x i16> %a, %b + ret <16 x i16> %shift +} + +define <16 x i8> @var_shift_v16i8(<16 x i8> %a, <16 x i8> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v16i8': +; SSE2: Found an estimated cost of 54 for instruction: %shift +; SSE41: Found an estimated cost of 54 for instruction: %shift +; AVX: Found an estimated cost of 54 for instruction: %shift +; AVX2: Found an estimated cost of 54 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = ashr <16 x i8> %a, %b + ret <16 x i8> %shift +} + +define <32 x i8> @var_shift_v32i8(<32 x i8> %a, <32 x i8> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v32i8': +; SSE2: Found an estimated cost of 108 for instruction: %shift +; SSE41: Found an estimated cost of 108 for instruction: %shift +; AVX: Found an estimated cost of 108 for instruction: %shift +; AVX2: Found an estimated cost of 24 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = ashr <32 x i8> %a, %b + ret <32 x i8> %shift +} + +; +; Uniform Variable Shifts +; + +define <2 x i64> @splatvar_shift_v2i64(<2 x i64> %a, <2 x i64> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v2i64': +; SSE2: Found an estimated cost of 12 for instruction: %shift +; SSE41: Found an estimated cost of 12 for instruction: %shift +; AVX: Found an estimated cost of 12 for instruction: %shift +; AVX2: Found an estimated cost of 4 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %splat = shufflevector <2 x i64> %b, <2 x i64> undef, <2 x i32> zeroinitializer + %shift = ashr <2 x i64> %a, %splat + ret <2 x i64> %shift +} + +define <4 x i64> @splatvar_shift_v4i64(<4 x i64> %a, <4 x i64> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v4i64': +; SSE2: Found an estimated cost of 24 for instruction: %shift +; SSE41: Found an estimated cost of 24 for instruction: %shift +; AVX: Found an estimated cost of 24 for instruction: %shift +; AVX2: Found an estimated cost of 4 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %splat = shufflevector <4 x i64> %b, <4 x i64> undef, <4 x i32> zeroinitializer + %shift = ashr <4 x i64> %a, %splat + ret <4 x i64> %shift +} + +define <4 x i32> @splatvar_shift_v4i32(<4 x i32> %a, <4 x i32> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v4i32': +; SSE2: Found an estimated cost of 16 for instruction: %shift +; SSE41: Found an estimated cost of 16 for instruction: %shift +; AVX: Found an estimated cost of 16 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %splat = shufflevector <4 x i32> %b, <4 x i32> undef, <4 x i32> zeroinitializer + %shift = ashr <4 x i32> %a, %splat + ret <4 x i32> %shift +} + +define <8 x i32> @splatvar_shift_v8i32(<8 x i32> %a, <8 x i32> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v8i32': +; SSE2: Found an estimated cost of 32 for instruction: %shift +; SSE41: Found an estimated cost of 32 for instruction: %shift +; AVX: Found an estimated cost of 32 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 4 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %splat = shufflevector <8 x i32> %b, <8 x i32> undef, <8 x i32> zeroinitializer + %shift = ashr <8 x i32> %a, %splat + ret <8 x i32> %shift +} + +define <8 x i16> @splatvar_shift_v8i16(<8 x i16> %a, <8 x i16> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v8i16': +; SSE2: Found an estimated cost of 32 for instruction: %shift +; SSE41: Found an estimated cost of 32 for instruction: %shift +; AVX: Found an estimated cost of 32 for instruction: %shift +; AVX2: Found an estimated cost of 32 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %splat = shufflevector <8 x i16> %b, <8 x i16> undef, <8 x i32> zeroinitializer + %shift = ashr <8 x i16> %a, %splat + ret <8 x i16> %shift +} + +define <16 x i16> @splatvar_shift_v16i16(<16 x i16> %a, <16 x i16> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v16i16': +; SSE2: Found an estimated cost of 64 for instruction: %shift +; SSE41: Found an estimated cost of 64 for instruction: %shift +; AVX: Found an estimated cost of 64 for instruction: %shift +; AVX2: Found an estimated cost of 10 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %splat = shufflevector <16 x i16> %b, <16 x i16> undef, <16 x i32> zeroinitializer + %shift = ashr <16 x i16> %a, %splat + ret <16 x i16> %shift +} + +define <16 x i8> @splatvar_shift_v16i8(<16 x i8> %a, <16 x i8> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v16i8': +; SSE2: Found an estimated cost of 54 for instruction: %shift +; SSE41: Found an estimated cost of 54 for instruction: %shift +; AVX: Found an estimated cost of 54 for instruction: %shift +; AVX2: Found an estimated cost of 54 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %splat = shufflevector <16 x i8> %b, <16 x i8> undef, <16 x i32> zeroinitializer + %shift = ashr <16 x i8> %a, %splat + ret <16 x i8> %shift +} + +define <32 x i8> @splatvar_shift_v32i8(<32 x i8> %a, <32 x i8> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v32i8': +; SSE2: Found an estimated cost of 108 for instruction: %shift +; SSE41: Found an estimated cost of 108 for instruction: %shift +; AVX: Found an estimated cost of 108 for instruction: %shift +; AVX2: Found an estimated cost of 24 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %splat = shufflevector <32 x i8> %b, <32 x i8> undef, <32 x i32> zeroinitializer + %shift = ashr <32 x i8> %a, %splat + ret <32 x i8> %shift +} + +; +; Constant Shifts +; + +define <2 x i64> @constant_shift_v2i64(<2 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v2i64': +; SSE2: Found an estimated cost of 12 for instruction: %shift +; SSE41: Found an estimated cost of 12 for instruction: %shift +; AVX: Found an estimated cost of 12 for instruction: %shift +; AVX2: Found an estimated cost of 4 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = ashr <2 x i64> %a, <i64 1, i64 7> + ret <2 x i64> %shift +} + +define <4 x i64> @constant_shift_v4i64(<4 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v4i64': +; SSE2: Found an estimated cost of 24 for instruction: %shift +; SSE41: Found an estimated cost of 24 for instruction: %shift +; AVX: Found an estimated cost of 24 for instruction: %shift +; AVX2: Found an estimated cost of 4 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = ashr <4 x i64> %a, <i64 1, i64 7, i64 15, i64 31> + ret <4 x i64> %shift +} + +define <4 x i32> @constant_shift_v4i32(<4 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v4i32': +; SSE2: Found an estimated cost of 16 for instruction: %shift +; SSE41: Found an estimated cost of 16 for instruction: %shift +; AVX: Found an estimated cost of 16 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = ashr <4 x i32> %a, <i32 4, i32 5, i32 6, i32 7> + ret <4 x i32> %shift +} + +define <8 x i32> @constant_shift_v8i32(<8 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v8i32': +; SSE2: Found an estimated cost of 32 for instruction: %shift +; SSE41: Found an estimated cost of 32 for instruction: %shift +; AVX: Found an estimated cost of 32 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 4 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = ashr <8 x i32> %a, <i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3> + ret <8 x i32> %shift +} + +define <8 x i16> @constant_shift_v8i16(<8 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v8i16': +; SSE2: Found an estimated cost of 32 for instruction: %shift +; SSE41: Found an estimated cost of 32 for instruction: %shift +; AVX: Found an estimated cost of 32 for instruction: %shift +; AVX2: Found an estimated cost of 32 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = ashr <8 x i16> %a, <i16 0, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7> + ret <8 x i16> %shift +} + +define <16 x i16> @constant_shift_v16i16(<16 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v16i16': +; SSE2: Found an estimated cost of 64 for instruction: %shift +; SSE41: Found an estimated cost of 64 for instruction: %shift +; AVX: Found an estimated cost of 64 for instruction: %shift +; AVX2: Found an estimated cost of 10 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = ashr <16 x i16> %a, <i16 0, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 0, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7> + ret <16 x i16> %shift +} + +define <16 x i8> @constant_shift_v16i8(<16 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v16i8': +; SSE2: Found an estimated cost of 54 for instruction: %shift +; SSE41: Found an estimated cost of 54 for instruction: %shift +; AVX: Found an estimated cost of 54 for instruction: %shift +; AVX2: Found an estimated cost of 54 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = ashr <16 x i8> %a, <i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0> + ret <16 x i8> %shift +} + +define <32 x i8> @constant_shift_v32i8(<32 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v32i8': +; SSE2: Found an estimated cost of 108 for instruction: %shift +; SSE41: Found an estimated cost of 108 for instruction: %shift +; AVX: Found an estimated cost of 108 for instruction: %shift +; AVX2: Found an estimated cost of 24 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = ashr <32 x i8> %a, <i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0, i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0> + ret <32 x i8> %shift +} + +; +; Uniform Constant Shifts +; + +define <2 x i64> @splatconstant_shift_v2i64(<2 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v2i64': +; SSE2: Found an estimated cost of 4 for instruction: %shift +; SSE41: Found an estimated cost of 4 for instruction: %shift +; AVX: Found an estimated cost of 4 for instruction: %shift +; AVX2: Found an estimated cost of 4 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = ashr <2 x i64> %a, <i64 7, i64 7> + ret <2 x i64> %shift +} + +define <4 x i64> @splatconstant_shift_v4i64(<4 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v4i64': +; SSE2: Found an estimated cost of 8 for instruction: %shift +; SSE41: Found an estimated cost of 8 for instruction: %shift +; AVX: Found an estimated cost of 8 for instruction: %shift +; AVX2: Found an estimated cost of 4 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = ashr <4 x i64> %a, <i64 7, i64 7, i64 7, i64 7> + ret <4 x i64> %shift +} + +define <4 x i32> @splatconstant_shift_v4i32(<4 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v4i32': +; SSE2: Found an estimated cost of 1 for instruction: %shift +; SSE41: Found an estimated cost of 1 for instruction: %shift +; AVX: Found an estimated cost of 1 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = ashr <4 x i32> %a, <i32 5, i32 5, i32 5, i32 5> + ret <4 x i32> %shift +} + +define <8 x i32> @splatconstant_shift_v8i32(<8 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v8i32': +; SSE2: Found an estimated cost of 2 for instruction: %shift +; SSE41: Found an estimated cost of 2 for instruction: %shift +; AVX: Found an estimated cost of 2 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 4 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = ashr <8 x i32> %a, <i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5> + ret <8 x i32> %shift +} + +define <8 x i16> @splatconstant_shift_v8i16(<8 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v8i16': +; SSE2: Found an estimated cost of 1 for instruction: %shift +; SSE41: Found an estimated cost of 1 for instruction: %shift +; AVX: Found an estimated cost of 1 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = ashr <8 x i16> %a, <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3> + ret <8 x i16> %shift +} + +define <16 x i16> @splatconstant_shift_v16i16(<16 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v16i16': +; SSE2: Found an estimated cost of 2 for instruction: %shift +; SSE41: Found an estimated cost of 2 for instruction: %shift +; AVX: Found an estimated cost of 2 for instruction: %shift +; AVX2: Found an estimated cost of 10 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = ashr <16 x i16> %a, <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3> + ret <16 x i16> %shift +} + +define <16 x i8> @splatconstant_shift_v16i8(<16 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v16i8': +; SSE2: Found an estimated cost of 4 for instruction: %shift +; SSE41: Found an estimated cost of 4 for instruction: %shift +; AVX: Found an estimated cost of 4 for instruction: %shift +; AVX2: Found an estimated cost of 4 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = ashr <16 x i8> %a, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3> + ret <16 x i8> %shift +} + +define <32 x i8> @splatconstant_shift_v32i8(<32 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v32i8': +; SSE2: Found an estimated cost of 8 for instruction: %shift +; SSE41: Found an estimated cost of 8 for instruction: %shift +; AVX: Found an estimated cost of 8 for instruction: %shift +; AVX2: Found an estimated cost of 24 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = ashr <32 x i8> %a, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3> + ret <32 x i8> %shift +} diff --git a/test/Analysis/CostModel/X86/vshift-cost.ll b/test/Analysis/CostModel/X86/vshift-cost.ll deleted file mode 100644 index 84d72463ac0d..000000000000 --- a/test/Analysis/CostModel/X86/vshift-cost.ll +++ /dev/null @@ -1,167 +0,0 @@ -; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -mattr=+sse2,-sse4.1 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=SSE2 -; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=SSE41 -; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7-avx -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=AVX -; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=core-avx2 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=AVX2 - - -; Verify the cost of vector shift left instructions. - -; We always emit a single pmullw in the case of v8i16 vector shifts by -; non-uniform constant. - -define <8 x i16> @test1(<8 x i16> %a) { - %shl = shl <8 x i16> %a, <i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11> - ret <8 x i16> %shl -} -; CHECK: 'Cost Model Analysis' for function 'test1': -; CHECK: Found an estimated cost of 1 for instruction: %shl - - -define <8 x i16> @test2(<8 x i16> %a) { - %shl = shl <8 x i16> %a, <i16 0, i16 undef, i16 0, i16 0, i16 1, i16 undef, i16 -1, i16 1> - ret <8 x i16> %shl -} -; CHECK: 'Cost Model Analysis' for function 'test2': -; CHECK: Found an estimated cost of 1 for instruction: %shl - - -; With SSE4.1, v4i32 shifts can be lowered into a single pmulld instruction. -; Make sure that the estimated cost is always 1 except for the case where -; we only have SSE2 support. With SSE2, we are forced to special lower the -; v4i32 mul as a 2x shuffle, 2x pmuludq, 2x shuffle. - -define <4 x i32> @test3(<4 x i32> %a) { - %shl = shl <4 x i32> %a, <i32 1, i32 -1, i32 2, i32 -3> - ret <4 x i32> %shl -} -; CHECK: 'Cost Model Analysis' for function 'test3': -; SSE2: Found an estimated cost of 6 for instruction: %shl -; SSE41: Found an estimated cost of 1 for instruction: %shl -; AVX: Found an estimated cost of 1 for instruction: %shl -; AVX2: Found an estimated cost of 1 for instruction: %shl - - -define <4 x i32> @test4(<4 x i32> %a) { - %shl = shl <4 x i32> %a, <i32 0, i32 0, i32 1, i32 1> - ret <4 x i32> %shl -} -; CHECK: 'Cost Model Analysis' for function 'test4': -; SSE2: Found an estimated cost of 6 for instruction: %shl -; SSE41: Found an estimated cost of 1 for instruction: %shl -; AVX: Found an estimated cost of 1 for instruction: %shl -; AVX2: Found an estimated cost of 1 for instruction: %shl - - -; On AVX2 we are able to lower the following shift into a single -; vpsllvq. Therefore, the expected cost is only 1. -; In all other cases, this shift is scalarized as the target does not support -; vpsllv instructions. - -define <2 x i64> @test5(<2 x i64> %a) { - %shl = shl <2 x i64> %a, <i64 2, i64 3> - ret <2 x i64> %shl -} -; CHECK: 'Cost Model Analysis' for function 'test5': -; SSE2: Found an estimated cost of 20 for instruction: %shl -; SSE41: Found an estimated cost of 20 for instruction: %shl -; AVX: Found an estimated cost of 20 for instruction: %shl -; AVX2: Found an estimated cost of 1 for instruction: %shl - - -; v16i16 and v8i32 shift left by non-uniform constant are lowered into -; vector multiply instructions. With AVX (but not AVX2), the vector multiply -; is lowered into a sequence of: 1 extract + 2 vpmullw + 1 insert. -; -; With AVX2, instruction vpmullw works with 256bit quantities and -; therefore there is no need to split the resulting vector multiply into -; a sequence of two multiply. -; -; With SSE2 and SSE4.1, the vector shift cost for 'test6' is twice -; the cost computed in the case of 'test1'. That is because the backend -; simply emits 2 pmullw with no extract/insert. - - -define <16 x i16> @test6(<16 x i16> %a) { - %shl = shl <16 x i16> %a, <i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11, i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11> - ret <16 x i16> %shl -} -; CHECK: 'Cost Model Analysis' for function 'test6': -; SSE2: Found an estimated cost of 2 for instruction: %shl -; SSE41: Found an estimated cost of 2 for instruction: %shl -; AVX: Found an estimated cost of 4 for instruction: %shl -; AVX2: Found an estimated cost of 1 for instruction: %shl - - -; With SSE2 and SSE4.1, the vector shift cost for 'test7' is twice -; the cost computed in the case of 'test3'. That is because the multiply -; is type-legalized into two 4i32 vector multiply. - -define <8 x i32> @test7(<8 x i32> %a) { - %shl = shl <8 x i32> %a, <i32 1, i32 1, i32 2, i32 3, i32 1, i32 1, i32 2, i32 3> - ret <8 x i32> %shl -} -; CHECK: 'Cost Model Analysis' for function 'test7': -; SSE2: Found an estimated cost of 12 for instruction: %shl -; SSE41: Found an estimated cost of 2 for instruction: %shl -; AVX: Found an estimated cost of 4 for instruction: %shl -; AVX2: Found an estimated cost of 1 for instruction: %shl - - -; On AVX2 we are able to lower the following shift into a single -; vpsllvq. Therefore, the expected cost is only 1. -; In all other cases, this shift is scalarized as the target does not support -; vpsllv instructions. - -define <4 x i64> @test8(<4 x i64> %a) { - %shl = shl <4 x i64> %a, <i64 1, i64 2, i64 3, i64 4> - ret <4 x i64> %shl -} -; CHECK: 'Cost Model Analysis' for function 'test8': -; SSE2: Found an estimated cost of 40 for instruction: %shl -; SSE41: Found an estimated cost of 40 for instruction: %shl -; AVX: Found an estimated cost of 40 for instruction: %shl -; AVX2: Found an estimated cost of 1 for instruction: %shl - - -; Same as 'test6', with the difference that the cost is double. - -define <32 x i16> @test9(<32 x i16> %a) { - %shl = shl <32 x i16> %a, <i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11, i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11, i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11, i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11> - ret <32 x i16> %shl -} -; CHECK: 'Cost Model Analysis' for function 'test9': -; SSE2: Found an estimated cost of 4 for instruction: %shl -; SSE41: Found an estimated cost of 4 for instruction: %shl -; AVX: Found an estimated cost of 8 for instruction: %shl -; AVX2: Found an estimated cost of 2 for instruction: %shl - - -; Same as 'test7', except that now the cost is double. - -define <16 x i32> @test10(<16 x i32> %a) { - %shl = shl <16 x i32> %a, <i32 1, i32 1, i32 2, i32 3, i32 1, i32 1, i32 2, i32 3, i32 1, i32 1, i32 2, i32 3, i32 1, i32 1, i32 2, i32 3> - ret <16 x i32> %shl -} -; CHECK: 'Cost Model Analysis' for function 'test10': -; SSE2: Found an estimated cost of 24 for instruction: %shl -; SSE41: Found an estimated cost of 4 for instruction: %shl -; AVX: Found an estimated cost of 8 for instruction: %shl -; AVX2: Found an estimated cost of 2 for instruction: %shl - - -; On AVX2 we are able to lower the following shift into a sequence of -; two vpsllvq instructions. Therefore, the expected cost is only 2. -; In all other cases, this shift is scalarized as we don't have vpsllv -; instructions. - -define <8 x i64> @test11(<8 x i64> %a) { - %shl = shl <8 x i64> %a, <i64 1, i64 1, i64 2, i64 3, i64 1, i64 1, i64 2, i64 3> - ret <8 x i64> %shl -} -; CHECK: 'Cost Model Analysis' for function 'test11': -; SSE2: Found an estimated cost of 80 for instruction: %shl -; SSE41: Found an estimated cost of 80 for instruction: %shl -; AVX: Found an estimated cost of 80 for instruction: %shl -; AVX2: Found an estimated cost of 2 for instruction: %shl - - diff --git a/test/Analysis/CostModel/X86/vshift-lshr-cost.ll b/test/Analysis/CostModel/X86/vshift-lshr-cost.ll new file mode 100644 index 000000000000..a686b4368f21 --- /dev/null +++ b/test/Analysis/CostModel/X86/vshift-lshr-cost.ll @@ -0,0 +1,400 @@ +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -mattr=+sse2,-sse4.1 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=SSE2 +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=SSE41 +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7-avx -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=AVX +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=core-avx2 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=AVX2 +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=bdver2 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=XOP -check-prefix=XOPAVX +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=bdver4 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=XOP -check-prefix=XOPAVX2 + +; Verify the cost of vector logical shift right instructions. + +; +; Variable Shifts +; + +define <2 x i64> @var_shift_v2i64(<2 x i64> %a, <2 x i64> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v2i64': +; SSE2: Found an estimated cost of 4 for instruction: %shift +; SSE41: Found an estimated cost of 4 for instruction: %shift +; AVX: Found an estimated cost of 4 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = lshr <2 x i64> %a, %b + ret <2 x i64> %shift +} + +define <4 x i64> @var_shift_v4i64(<4 x i64> %a, <4 x i64> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v4i64': +; SSE2: Found an estimated cost of 8 for instruction: %shift +; SSE41: Found an estimated cost of 8 for instruction: %shift +; AVX: Found an estimated cost of 8 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 4 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = lshr <4 x i64> %a, %b + ret <4 x i64> %shift +} + +define <4 x i32> @var_shift_v4i32(<4 x i32> %a, <4 x i32> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v4i32': +; SSE2: Found an estimated cost of 16 for instruction: %shift +; SSE41: Found an estimated cost of 16 for instruction: %shift +; AVX: Found an estimated cost of 16 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = lshr <4 x i32> %a, %b + ret <4 x i32> %shift +} + +define <8 x i32> @var_shift_v8i32(<8 x i32> %a, <8 x i32> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v8i32': +; SSE2: Found an estimated cost of 32 for instruction: %shift +; SSE41: Found an estimated cost of 32 for instruction: %shift +; AVX: Found an estimated cost of 32 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 4 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = lshr <8 x i32> %a, %b + ret <8 x i32> %shift +} + +define <8 x i16> @var_shift_v8i16(<8 x i16> %a, <8 x i16> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v8i16': +; SSE2: Found an estimated cost of 32 for instruction: %shift +; SSE41: Found an estimated cost of 32 for instruction: %shift +; AVX: Found an estimated cost of 32 for instruction: %shift +; AVX2: Found an estimated cost of 32 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = lshr <8 x i16> %a, %b + ret <8 x i16> %shift +} + +define <16 x i16> @var_shift_v16i16(<16 x i16> %a, <16 x i16> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v16i16': +; SSE2: Found an estimated cost of 64 for instruction: %shift +; SSE41: Found an estimated cost of 64 for instruction: %shift +; AVX: Found an estimated cost of 64 for instruction: %shift +; AVX2: Found an estimated cost of 10 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = lshr <16 x i16> %a, %b + ret <16 x i16> %shift +} + +define <16 x i8> @var_shift_v16i8(<16 x i8> %a, <16 x i8> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v16i8': +; SSE2: Found an estimated cost of 26 for instruction: %shift +; SSE41: Found an estimated cost of 26 for instruction: %shift +; AVX: Found an estimated cost of 26 for instruction: %shift +; AVX2: Found an estimated cost of 26 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = lshr <16 x i8> %a, %b + ret <16 x i8> %shift +} + +define <32 x i8> @var_shift_v32i8(<32 x i8> %a, <32 x i8> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v32i8': +; SSE2: Found an estimated cost of 52 for instruction: %shift +; SSE41: Found an estimated cost of 52 for instruction: %shift +; AVX: Found an estimated cost of 52 for instruction: %shift +; AVX2: Found an estimated cost of 11 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = lshr <32 x i8> %a, %b + ret <32 x i8> %shift +} + +; +; Uniform Variable Shifts +; + +define <2 x i64> @splatvar_shift_v2i64(<2 x i64> %a, <2 x i64> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v2i64': +; SSE2: Found an estimated cost of 4 for instruction: %shift +; SSE41: Found an estimated cost of 4 for instruction: %shift +; AVX: Found an estimated cost of 4 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %splat = shufflevector <2 x i64> %b, <2 x i64> undef, <2 x i32> zeroinitializer + %shift = lshr <2 x i64> %a, %splat + ret <2 x i64> %shift +} + +define <4 x i64> @splatvar_shift_v4i64(<4 x i64> %a, <4 x i64> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v4i64': +; SSE2: Found an estimated cost of 8 for instruction: %shift +; SSE41: Found an estimated cost of 8 for instruction: %shift +; AVX: Found an estimated cost of 8 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 4 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %splat = shufflevector <4 x i64> %b, <4 x i64> undef, <4 x i32> zeroinitializer + %shift = lshr <4 x i64> %a, %splat + ret <4 x i64> %shift +} + +define <4 x i32> @splatvar_shift_v4i32(<4 x i32> %a, <4 x i32> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v4i32': +; SSE2: Found an estimated cost of 16 for instruction: %shift +; SSE41: Found an estimated cost of 16 for instruction: %shift +; AVX: Found an estimated cost of 16 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %splat = shufflevector <4 x i32> %b, <4 x i32> undef, <4 x i32> zeroinitializer + %shift = lshr <4 x i32> %a, %splat + ret <4 x i32> %shift +} + +define <8 x i32> @splatvar_shift_v8i32(<8 x i32> %a, <8 x i32> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v8i32': +; SSE2: Found an estimated cost of 32 for instruction: %shift +; SSE41: Found an estimated cost of 32 for instruction: %shift +; AVX: Found an estimated cost of 32 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 4 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %splat = shufflevector <8 x i32> %b, <8 x i32> undef, <8 x i32> zeroinitializer + %shift = lshr <8 x i32> %a, %splat + ret <8 x i32> %shift +} + +define <8 x i16> @splatvar_shift_v8i16(<8 x i16> %a, <8 x i16> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v8i16': +; SSE2: Found an estimated cost of 32 for instruction: %shift +; SSE41: Found an estimated cost of 32 for instruction: %shift +; AVX: Found an estimated cost of 32 for instruction: %shift +; AVX2: Found an estimated cost of 32 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %splat = shufflevector <8 x i16> %b, <8 x i16> undef, <8 x i32> zeroinitializer + %shift = lshr <8 x i16> %a, %splat + ret <8 x i16> %shift +} + +define <16 x i16> @splatvar_shift_v16i16(<16 x i16> %a, <16 x i16> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v16i16': +; SSE2: Found an estimated cost of 64 for instruction: %shift +; SSE41: Found an estimated cost of 64 for instruction: %shift +; AVX: Found an estimated cost of 64 for instruction: %shift +; AVX2: Found an estimated cost of 10 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %splat = shufflevector <16 x i16> %b, <16 x i16> undef, <16 x i32> zeroinitializer + %shift = lshr <16 x i16> %a, %splat + ret <16 x i16> %shift +} + +define <16 x i8> @splatvar_shift_v16i8(<16 x i8> %a, <16 x i8> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v16i8': +; SSE2: Found an estimated cost of 26 for instruction: %shift +; SSE41: Found an estimated cost of 26 for instruction: %shift +; AVX: Found an estimated cost of 26 for instruction: %shift +; AVX2: Found an estimated cost of 26 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %splat = shufflevector <16 x i8> %b, <16 x i8> undef, <16 x i32> zeroinitializer + %shift = lshr <16 x i8> %a, %splat + ret <16 x i8> %shift +} + +define <32 x i8> @splatvar_shift_v32i8(<32 x i8> %a, <32 x i8> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v32i8': +; SSE2: Found an estimated cost of 52 for instruction: %shift +; SSE41: Found an estimated cost of 52 for instruction: %shift +; AVX: Found an estimated cost of 52 for instruction: %shift +; AVX2: Found an estimated cost of 11 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %splat = shufflevector <32 x i8> %b, <32 x i8> undef, <32 x i32> zeroinitializer + %shift = lshr <32 x i8> %a, %splat + ret <32 x i8> %shift +} + +; +; Constant Shifts +; + +define <2 x i64> @constant_shift_v2i64(<2 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v2i64': +; SSE2: Found an estimated cost of 4 for instruction: %shift +; SSE41: Found an estimated cost of 4 for instruction: %shift +; AVX: Found an estimated cost of 4 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = lshr <2 x i64> %a, <i64 1, i64 7> + ret <2 x i64> %shift +} + +define <4 x i64> @constant_shift_v4i64(<4 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v4i64': +; SSE2: Found an estimated cost of 8 for instruction: %shift +; SSE41: Found an estimated cost of 8 for instruction: %shift +; AVX: Found an estimated cost of 8 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 4 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = lshr <4 x i64> %a, <i64 1, i64 7, i64 15, i64 31> + ret <4 x i64> %shift +} + +define <4 x i32> @constant_shift_v4i32(<4 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v4i32': +; SSE2: Found an estimated cost of 16 for instruction: %shift +; SSE41: Found an estimated cost of 16 for instruction: %shift +; AVX: Found an estimated cost of 16 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = lshr <4 x i32> %a, <i32 4, i32 5, i32 6, i32 7> + ret <4 x i32> %shift +} + +define <8 x i32> @constant_shift_v8i32(<8 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v8i32': +; SSE2: Found an estimated cost of 32 for instruction: %shift +; SSE41: Found an estimated cost of 32 for instruction: %shift +; AVX: Found an estimated cost of 32 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 4 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = lshr <8 x i32> %a, <i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3> + ret <8 x i32> %shift +} + +define <8 x i16> @constant_shift_v8i16(<8 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v8i16': +; SSE2: Found an estimated cost of 32 for instruction: %shift +; SSE41: Found an estimated cost of 32 for instruction: %shift +; AVX: Found an estimated cost of 32 for instruction: %shift +; AVX2: Found an estimated cost of 32 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = lshr <8 x i16> %a, <i16 0, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7> + ret <8 x i16> %shift +} + +define <16 x i16> @constant_shift_v16i16(<16 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v16i16': +; SSE2: Found an estimated cost of 64 for instruction: %shift +; SSE41: Found an estimated cost of 64 for instruction: %shift +; AVX: Found an estimated cost of 64 for instruction: %shift +; AVX2: Found an estimated cost of 10 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = lshr <16 x i16> %a, <i16 0, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 0, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7> + ret <16 x i16> %shift +} + +define <16 x i8> @constant_shift_v16i8(<16 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v16i8': +; SSE2: Found an estimated cost of 26 for instruction: %shift +; SSE41: Found an estimated cost of 26 for instruction: %shift +; AVX: Found an estimated cost of 26 for instruction: %shift +; AVX2: Found an estimated cost of 26 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = lshr <16 x i8> %a, <i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0> + ret <16 x i8> %shift +} + +define <32 x i8> @constant_shift_v32i8(<32 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v32i8': +; SSE2: Found an estimated cost of 52 for instruction: %shift +; SSE41: Found an estimated cost of 52 for instruction: %shift +; AVX: Found an estimated cost of 52 for instruction: %shift +; AVX2: Found an estimated cost of 11 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = lshr <32 x i8> %a, <i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0, i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0> + ret <32 x i8> %shift +} + +; +; Uniform Constant Shifts +; + +define <2 x i64> @splatconstant_shift_v2i64(<2 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v2i64': +; SSE2: Found an estimated cost of 1 for instruction: %shift +; SSE41: Found an estimated cost of 1 for instruction: %shift +; AVX: Found an estimated cost of 1 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = lshr <2 x i64> %a, <i64 7, i64 7> + ret <2 x i64> %shift +} + +define <4 x i64> @splatconstant_shift_v4i64(<4 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v4i64': +; SSE2: Found an estimated cost of 2 for instruction: %shift +; SSE41: Found an estimated cost of 2 for instruction: %shift +; AVX: Found an estimated cost of 2 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 4 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = lshr <4 x i64> %a, <i64 7, i64 7, i64 7, i64 7> + ret <4 x i64> %shift +} + +define <4 x i32> @splatconstant_shift_v4i32(<4 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v4i32': +; SSE2: Found an estimated cost of 1 for instruction: %shift +; SSE41: Found an estimated cost of 1 for instruction: %shift +; AVX: Found an estimated cost of 1 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = lshr <4 x i32> %a, <i32 5, i32 5, i32 5, i32 5> + ret <4 x i32> %shift +} + +define <8 x i32> @splatconstant_shift_v8i32(<8 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v8i32': +; SSE2: Found an estimated cost of 2 for instruction: %shift +; SSE41: Found an estimated cost of 2 for instruction: %shift +; AVX: Found an estimated cost of 2 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 4 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = lshr <8 x i32> %a, <i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5> + ret <8 x i32> %shift +} + +define <8 x i16> @splatconstant_shift_v8i16(<8 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v8i16': +; SSE2: Found an estimated cost of 1 for instruction: %shift +; SSE41: Found an estimated cost of 1 for instruction: %shift +; AVX: Found an estimated cost of 1 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = lshr <8 x i16> %a, <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3> + ret <8 x i16> %shift +} + +define <16 x i16> @splatconstant_shift_v16i16(<16 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v16i16': +; SSE2: Found an estimated cost of 2 for instruction: %shift +; SSE41: Found an estimated cost of 2 for instruction: %shift +; AVX: Found an estimated cost of 2 for instruction: %shift +; AVX2: Found an estimated cost of 10 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = lshr <16 x i16> %a, <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3> + ret <16 x i16> %shift +} + +define <16 x i8> @splatconstant_shift_v16i8(<16 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v16i8': +; SSE2: Found an estimated cost of 1 for instruction: %shift +; SSE41: Found an estimated cost of 1 for instruction: %shift +; AVX: Found an estimated cost of 1 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = lshr <16 x i8> %a, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3> + ret <16 x i8> %shift +} + +define <32 x i8> @splatconstant_shift_v32i8(<32 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v32i8': +; SSE2: Found an estimated cost of 2 for instruction: %shift +; SSE41: Found an estimated cost of 2 for instruction: %shift +; AVX: Found an estimated cost of 2 for instruction: %shift +; AVX2: Found an estimated cost of 11 for instruction: %shift +; XOP: Found an estimated cost of 4 for instruction: %shift + %shift = lshr <32 x i8> %a, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3> + ret <32 x i8> %shift +} diff --git a/test/Analysis/CostModel/X86/vshift-shl-cost.ll b/test/Analysis/CostModel/X86/vshift-shl-cost.ll new file mode 100644 index 000000000000..85ca5a5a7f32 --- /dev/null +++ b/test/Analysis/CostModel/X86/vshift-shl-cost.ll @@ -0,0 +1,580 @@ +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -mattr=+sse2,-sse4.1 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=SSE2 +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=SSE41 +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7-avx -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=AVX +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=core-avx2 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=AVX2 +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=bdver2 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=XOP -check-prefix=XOPAVX +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=bdver4 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=XOP -check-prefix=XOPAVX2 + +; Verify the cost of vector shift left instructions. + +; +; +; Variable Shifts +; + +define <2 x i64> @var_shift_v2i64(<2 x i64> %a, <2 x i64> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v2i64': +; SSE2: Found an estimated cost of 4 for instruction: %shift +; SSE41: Found an estimated cost of 4 for instruction: %shift +; AVX: Found an estimated cost of 4 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 1 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = shl <2 x i64> %a, %b + ret <2 x i64> %shift +} + +define <4 x i64> @var_shift_v4i64(<4 x i64> %a, <4 x i64> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v4i64': +; SSE2: Found an estimated cost of 8 for instruction: %shift +; SSE41: Found an estimated cost of 8 for instruction: %shift +; AVX: Found an estimated cost of 8 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = shl <4 x i64> %a, %b + ret <4 x i64> %shift +} + +define <4 x i32> @var_shift_v4i32(<4 x i32> %a, <4 x i32> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v4i32': +; SSE2: Found an estimated cost of 10 for instruction: %shift +; SSE41: Found an estimated cost of 10 for instruction: %shift +; AVX: Found an estimated cost of 10 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 1 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = shl <4 x i32> %a, %b + ret <4 x i32> %shift +} + +define <8 x i32> @var_shift_v8i32(<8 x i32> %a, <8 x i32> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v8i32': +; SSE2: Found an estimated cost of 20 for instruction: %shift +; SSE41: Found an estimated cost of 20 for instruction: %shift +; AVX: Found an estimated cost of 20 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = shl <8 x i32> %a, %b + ret <8 x i32> %shift +} + +define <8 x i16> @var_shift_v8i16(<8 x i16> %a, <8 x i16> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v8i16': +; SSE2: Found an estimated cost of 32 for instruction: %shift +; SSE41: Found an estimated cost of 32 for instruction: %shift +; AVX: Found an estimated cost of 32 for instruction: %shift +; AVX2: Found an estimated cost of 32 for instruction: %shift +; XOP: Found an estimated cost of 1 for instruction: %shift + %shift = shl <8 x i16> %a, %b + ret <8 x i16> %shift +} + +define <16 x i16> @var_shift_v16i16(<16 x i16> %a, <16 x i16> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v16i16': +; SSE2: Found an estimated cost of 64 for instruction: %shift +; SSE41: Found an estimated cost of 64 for instruction: %shift +; AVX: Found an estimated cost of 64 for instruction: %shift +; AVX2: Found an estimated cost of 10 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = shl <16 x i16> %a, %b + ret <16 x i16> %shift +} + +define <16 x i8> @var_shift_v16i8(<16 x i8> %a, <16 x i8> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v16i8': +; SSE2: Found an estimated cost of 26 for instruction: %shift +; SSE41: Found an estimated cost of 26 for instruction: %shift +; AVX: Found an estimated cost of 26 for instruction: %shift +; AVX2: Found an estimated cost of 26 for instruction: %shift +; XOP: Found an estimated cost of 1 for instruction: %shift + %shift = shl <16 x i8> %a, %b + ret <16 x i8> %shift +} + +define <32 x i8> @var_shift_v32i8(<32 x i8> %a, <32 x i8> %b) { +; CHECK: 'Cost Model Analysis' for function 'var_shift_v32i8': +; SSE2: Found an estimated cost of 52 for instruction: %shift +; SSE41: Found an estimated cost of 52 for instruction: %shift +; AVX: Found an estimated cost of 52 for instruction: %shift +; AVX2: Found an estimated cost of 11 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = shl <32 x i8> %a, %b + ret <32 x i8> %shift +} + +; +; Uniform Variable Shifts +; + +define <2 x i64> @splatvar_shift_v2i64(<2 x i64> %a, <2 x i64> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v2i64': +; SSE2: Found an estimated cost of 4 for instruction: %shift +; SSE41: Found an estimated cost of 4 for instruction: %shift +; AVX: Found an estimated cost of 4 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 1 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %splat = shufflevector <2 x i64> %b, <2 x i64> undef, <2 x i32> zeroinitializer + %shift = shl <2 x i64> %a, %splat + ret <2 x i64> %shift +} + +define <4 x i64> @splatvar_shift_v4i64(<4 x i64> %a, <4 x i64> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v4i64': +; SSE2: Found an estimated cost of 8 for instruction: %shift +; SSE41: Found an estimated cost of 8 for instruction: %shift +; AVX: Found an estimated cost of 8 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %splat = shufflevector <4 x i64> %b, <4 x i64> undef, <4 x i32> zeroinitializer + %shift = shl <4 x i64> %a, %splat + ret <4 x i64> %shift +} + +define <4 x i32> @splatvar_shift_v4i32(<4 x i32> %a, <4 x i32> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v4i32': +; SSE2: Found an estimated cost of 10 for instruction: %shift +; SSE41: Found an estimated cost of 10 for instruction: %shift +; AVX: Found an estimated cost of 10 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 1 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %splat = shufflevector <4 x i32> %b, <4 x i32> undef, <4 x i32> zeroinitializer + %shift = shl <4 x i32> %a, %splat + ret <4 x i32> %shift +} + +define <8 x i32> @splatvar_shift_v8i32(<8 x i32> %a, <8 x i32> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v8i32': +; SSE2: Found an estimated cost of 20 for instruction: %shift +; SSE41: Found an estimated cost of 20 for instruction: %shift +; AVX: Found an estimated cost of 20 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %splat = shufflevector <8 x i32> %b, <8 x i32> undef, <8 x i32> zeroinitializer + %shift = shl <8 x i32> %a, %splat + ret <8 x i32> %shift +} + +define <8 x i16> @splatvar_shift_v8i16(<8 x i16> %a, <8 x i16> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v8i16': +; SSE2: Found an estimated cost of 32 for instruction: %shift +; SSE41: Found an estimated cost of 32 for instruction: %shift +; AVX: Found an estimated cost of 32 for instruction: %shift +; AVX2: Found an estimated cost of 32 for instruction: %shift +; XOP: Found an estimated cost of 1 for instruction: %shift + %splat = shufflevector <8 x i16> %b, <8 x i16> undef, <8 x i32> zeroinitializer + %shift = shl <8 x i16> %a, %splat + ret <8 x i16> %shift +} + +define <16 x i16> @splatvar_shift_v16i16(<16 x i16> %a, <16 x i16> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v16i16': +; SSE2: Found an estimated cost of 64 for instruction: %shift +; SSE41: Found an estimated cost of 64 for instruction: %shift +; AVX: Found an estimated cost of 64 for instruction: %shift +; AVX2: Found an estimated cost of 10 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %splat = shufflevector <16 x i16> %b, <16 x i16> undef, <16 x i32> zeroinitializer + %shift = shl <16 x i16> %a, %splat + ret <16 x i16> %shift +} + +define <16 x i8> @splatvar_shift_v16i8(<16 x i8> %a, <16 x i8> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v16i8': +; SSE2: Found an estimated cost of 26 for instruction: %shift +; SSE41: Found an estimated cost of 26 for instruction: %shift +; AVX: Found an estimated cost of 26 for instruction: %shift +; AVX2: Found an estimated cost of 26 for instruction: %shift +; XOP: Found an estimated cost of 1 for instruction: %shift + %splat = shufflevector <16 x i8> %b, <16 x i8> undef, <16 x i32> zeroinitializer + %shift = shl <16 x i8> %a, %splat + ret <16 x i8> %shift +} + +define <32 x i8> @splatvar_shift_v32i8(<32 x i8> %a, <32 x i8> %b) { +; CHECK: 'Cost Model Analysis' for function 'splatvar_shift_v32i8': +; SSE2: Found an estimated cost of 52 for instruction: %shift +; SSE41: Found an estimated cost of 52 for instruction: %shift +; AVX: Found an estimated cost of 52 for instruction: %shift +; AVX2: Found an estimated cost of 11 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %splat = shufflevector <32 x i8> %b, <32 x i8> undef, <32 x i32> zeroinitializer + %shift = shl <32 x i8> %a, %splat + ret <32 x i8> %shift +} + +; +; Constant Shifts +; + +define <2 x i64> @constant_shift_v2i64(<2 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v2i64': +; SSE2: Found an estimated cost of 4 for instruction: %shift +; SSE41: Found an estimated cost of 4 for instruction: %shift +; AVX: Found an estimated cost of 4 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 1 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = shl <2 x i64> %a, <i64 1, i64 7> + ret <2 x i64> %shift +} + +define <4 x i64> @constant_shift_v4i64(<4 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v4i64': +; SSE2: Found an estimated cost of 8 for instruction: %shift +; SSE41: Found an estimated cost of 8 for instruction: %shift +; AVX: Found an estimated cost of 8 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = shl <4 x i64> %a, <i64 1, i64 7, i64 15, i64 31> + ret <4 x i64> %shift +} + +define <4 x i32> @constant_shift_v4i32(<4 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v4i32': +; SSE2: Found an estimated cost of 6 for instruction: %shift +; SSE41: Found an estimated cost of 1 for instruction: %shift +; AVX: Found an estimated cost of 1 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 1 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = shl <4 x i32> %a, <i32 4, i32 5, i32 6, i32 7> + ret <4 x i32> %shift +} + +define <8 x i32> @constant_shift_v8i32(<8 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v8i32': +; SSE2: Found an estimated cost of 12 for instruction: %shift +; SSE41: Found an estimated cost of 2 for instruction: %shift +; AVX: Found an estimated cost of 4 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = shl <8 x i32> %a, <i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3> + ret <8 x i32> %shift +} + +define <8 x i16> @constant_shift_v8i16(<8 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v8i16': +; SSE2: Found an estimated cost of 1 for instruction: %shift +; SSE41: Found an estimated cost of 1 for instruction: %shift +; AVX: Found an estimated cost of 1 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOP: Found an estimated cost of 1 for instruction: %shift + %shift = shl <8 x i16> %a, <i16 0, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7> + ret <8 x i16> %shift +} + +define <16 x i16> @constant_shift_v16i16(<16 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v16i16': +; SSE2: Found an estimated cost of 2 for instruction: %shift +; SSE41: Found an estimated cost of 2 for instruction: %shift +; AVX: Found an estimated cost of 4 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = shl <16 x i16> %a, <i16 0, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 0, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7> + ret <16 x i16> %shift +} + +define <16 x i8> @constant_shift_v16i8(<16 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v16i8': +; SSE2: Found an estimated cost of 26 for instruction: %shift +; SSE41: Found an estimated cost of 26 for instruction: %shift +; AVX: Found an estimated cost of 26 for instruction: %shift +; AVX2: Found an estimated cost of 26 for instruction: %shift +; XOP: Found an estimated cost of 1 for instruction: %shift + %shift = shl <16 x i8> %a, <i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0> + ret <16 x i8> %shift +} + +define <32 x i8> @constant_shift_v32i8(<32 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'constant_shift_v32i8': +; SSE2: Found an estimated cost of 52 for instruction: %shift +; SSE41: Found an estimated cost of 52 for instruction: %shift +; AVX: Found an estimated cost of 52 for instruction: %shift +; AVX2: Found an estimated cost of 11 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = shl <32 x i8> %a, <i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0, i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0> + ret <32 x i8> %shift +} + +; +; Uniform Constant Shifts +; + +define <2 x i64> @splatconstant_shift_v2i64(<2 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v2i64': +; SSE2: Found an estimated cost of 1 for instruction: %shift +; SSE41: Found an estimated cost of 1 for instruction: %shift +; AVX: Found an estimated cost of 1 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 1 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = shl <2 x i64> %a, <i64 7, i64 7> + ret <2 x i64> %shift +} + +define <4 x i64> @splatconstant_shift_v4i64(<4 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v4i64': +; SSE2: Found an estimated cost of 2 for instruction: %shift +; SSE41: Found an estimated cost of 2 for instruction: %shift +; AVX: Found an estimated cost of 2 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = shl <4 x i64> %a, <i64 7, i64 7, i64 7, i64 7> + ret <4 x i64> %shift +} + +define <4 x i32> @splatconstant_shift_v4i32(<4 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v4i32': +; SSE2: Found an estimated cost of 1 for instruction: %shift +; SSE41: Found an estimated cost of 1 for instruction: %shift +; AVX: Found an estimated cost of 1 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 1 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = shl <4 x i32> %a, <i32 5, i32 5, i32 5, i32 5> + ret <4 x i32> %shift +} + +define <8 x i32> @splatconstant_shift_v8i32(<8 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v8i32': +; SSE2: Found an estimated cost of 2 for instruction: %shift +; SSE41: Found an estimated cost of 2 for instruction: %shift +; AVX: Found an estimated cost of 2 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = shl <8 x i32> %a, <i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5> + ret <8 x i32> %shift +} + +define <8 x i16> @splatconstant_shift_v8i16(<8 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v8i16': +; SSE2: Found an estimated cost of 1 for instruction: %shift +; SSE41: Found an estimated cost of 1 for instruction: %shift +; AVX: Found an estimated cost of 1 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOP: Found an estimated cost of 1 for instruction: %shift + %shift = shl <8 x i16> %a, <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3> + ret <8 x i16> %shift +} + +define <16 x i16> @splatconstant_shift_v16i16(<16 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v16i16': +; SSE2: Found an estimated cost of 2 for instruction: %shift +; SSE41: Found an estimated cost of 2 for instruction: %shift +; AVX: Found an estimated cost of 2 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOPAVX: Found an estimated cost of 2 for instruction: %shift +; XOPAVX2: Found an estimated cost of 1 for instruction: %shift + %shift = shl <16 x i16> %a, <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3> + ret <16 x i16> %shift +} + +define <16 x i8> @splatconstant_shift_v16i8(<16 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v16i8': +; SSE2: Found an estimated cost of 1 for instruction: %shift +; SSE41: Found an estimated cost of 1 for instruction: %shift +; AVX: Found an estimated cost of 1 for instruction: %shift +; AVX2: Found an estimated cost of 1 for instruction: %shift +; XOP: Found an estimated cost of 1 for instruction: %shift + %shift = shl <16 x i8> %a, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3> + ret <16 x i8> %shift +} + +define <32 x i8> @splatconstant_shift_v32i8(<32 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'splatconstant_shift_v32i8': +; SSE2: Found an estimated cost of 2 for instruction: %shift +; SSE41: Found an estimated cost of 2 for instruction: %shift +; AVX: Found an estimated cost of 2 for instruction: %shift +; AVX2: Found an estimated cost of 11 for instruction: %shift +; XOP: Found an estimated cost of 2 for instruction: %shift + %shift = shl <32 x i8> %a, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3> + ret <32 x i8> %shift +} + +; +; Special Cases +; + +; We always emit a single pmullw in the case of v8i16 vector shifts by +; non-uniform constant. + +define <8 x i16> @test1(<8 x i16> %a) { + %shl = shl <8 x i16> %a, <i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11> + ret <8 x i16> %shl +} +; CHECK: 'Cost Model Analysis' for function 'test1': +; CHECK: Found an estimated cost of 1 for instruction: %shl + + +define <8 x i16> @test2(<8 x i16> %a) { + %shl = shl <8 x i16> %a, <i16 0, i16 undef, i16 0, i16 0, i16 1, i16 undef, i16 -1, i16 1> + ret <8 x i16> %shl +} +; CHECK: 'Cost Model Analysis' for function 'test2': +; CHECK: Found an estimated cost of 1 for instruction: %shl + + +; With SSE4.1, v4i32 shifts can be lowered into a single pmulld instruction. +; Make sure that the estimated cost is always 1 except for the case where +; we only have SSE2 support. With SSE2, we are forced to special lower the +; v4i32 mul as a 2x shuffle, 2x pmuludq, 2x shuffle. + +define <4 x i32> @test3(<4 x i32> %a) { + %shl = shl <4 x i32> %a, <i32 1, i32 -1, i32 2, i32 -3> + ret <4 x i32> %shl +} +; CHECK: 'Cost Model Analysis' for function 'test3': +; SSE2: Found an estimated cost of 6 for instruction: %shl +; SSE41: Found an estimated cost of 1 for instruction: %shl +; AVX: Found an estimated cost of 1 for instruction: %shl +; AVX2: Found an estimated cost of 1 for instruction: %shl +; XOP: Found an estimated cost of 1 for instruction: %shl + + +define <4 x i32> @test4(<4 x i32> %a) { + %shl = shl <4 x i32> %a, <i32 0, i32 0, i32 1, i32 1> + ret <4 x i32> %shl +} +; CHECK: 'Cost Model Analysis' for function 'test4': +; SSE2: Found an estimated cost of 6 for instruction: %shl +; SSE41: Found an estimated cost of 1 for instruction: %shl +; AVX: Found an estimated cost of 1 for instruction: %shl +; AVX2: Found an estimated cost of 1 for instruction: %shl +; XOP: Found an estimated cost of 1 for instruction: %shl + + +; On AVX2 we are able to lower the following shift into a single +; vpsllvq. Therefore, the expected cost is only 1. +; In all other cases, this shift is scalarized as the target does not support +; vpsllv instructions. + +define <2 x i64> @test5(<2 x i64> %a) { + %shl = shl <2 x i64> %a, <i64 2, i64 3> + ret <2 x i64> %shl +} +; CHECK: 'Cost Model Analysis' for function 'test5': +; SSE2: Found an estimated cost of 4 for instruction: %shl +; SSE41: Found an estimated cost of 4 for instruction: %shl +; AVX: Found an estimated cost of 4 for instruction: %shl +; AVX2: Found an estimated cost of 1 for instruction: %shl +; XOP: Found an estimated cost of 1 for instruction: %shl + + +; v16i16 and v8i32 shift left by non-uniform constant are lowered into +; vector multiply instructions. With AVX (but not AVX2), the vector multiply +; is lowered into a sequence of: 1 extract + 2 vpmullw + 1 insert. +; +; With AVX2, instruction vpmullw works with 256bit quantities and +; therefore there is no need to split the resulting vector multiply into +; a sequence of two multiply. +; +; With SSE2 and SSE4.1, the vector shift cost for 'test6' is twice +; the cost computed in the case of 'test1'. That is because the backend +; simply emits 2 pmullw with no extract/insert. + + +define <16 x i16> @test6(<16 x i16> %a) { + %shl = shl <16 x i16> %a, <i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11, i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11> + ret <16 x i16> %shl +} +; CHECK: 'Cost Model Analysis' for function 'test6': +; SSE2: Found an estimated cost of 2 for instruction: %shl +; SSE41: Found an estimated cost of 2 for instruction: %shl +; AVX: Found an estimated cost of 4 for instruction: %shl +; AVX2: Found an estimated cost of 1 for instruction: %shl +; XOPAVX: Found an estimated cost of 2 for instruction: %shl +; XOPAVX2: Found an estimated cost of 1 for instruction: %shl + + +; With SSE2 and SSE4.1, the vector shift cost for 'test7' is twice +; the cost computed in the case of 'test3'. That is because the multiply +; is type-legalized into two 4i32 vector multiply. + +define <8 x i32> @test7(<8 x i32> %a) { + %shl = shl <8 x i32> %a, <i32 1, i32 1, i32 2, i32 3, i32 1, i32 1, i32 2, i32 3> + ret <8 x i32> %shl +} +; CHECK: 'Cost Model Analysis' for function 'test7': +; SSE2: Found an estimated cost of 12 for instruction: %shl +; SSE41: Found an estimated cost of 2 for instruction: %shl +; AVX: Found an estimated cost of 4 for instruction: %shl +; AVX2: Found an estimated cost of 1 for instruction: %shl +; XOPAVX: Found an estimated cost of 2 for instruction: %shl +; XOPAVX2: Found an estimated cost of 1 for instruction: %shl + + +; On AVX2 we are able to lower the following shift into a single +; vpsllvq. Therefore, the expected cost is only 1. +; In all other cases, this shift is scalarized as the target does not support +; vpsllv instructions. + +define <4 x i64> @test8(<4 x i64> %a) { + %shl = shl <4 x i64> %a, <i64 1, i64 2, i64 3, i64 4> + ret <4 x i64> %shl +} +; CHECK: 'Cost Model Analysis' for function 'test8': +; SSE2: Found an estimated cost of 8 for instruction: %shl +; SSE41: Found an estimated cost of 8 for instruction: %shl +; AVX: Found an estimated cost of 8 for instruction: %shl +; AVX2: Found an estimated cost of 1 for instruction: %shl +; XOPAVX: Found an estimated cost of 2 for instruction: %shl +; XOPAVX2: Found an estimated cost of 1 for instruction: %shl + + +; Same as 'test6', with the difference that the cost is double. + +define <32 x i16> @test9(<32 x i16> %a) { + %shl = shl <32 x i16> %a, <i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11, i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11, i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11, i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11> + ret <32 x i16> %shl +} +; CHECK: 'Cost Model Analysis' for function 'test9': +; SSE2: Found an estimated cost of 4 for instruction: %shl +; SSE41: Found an estimated cost of 4 for instruction: %shl +; AVX: Found an estimated cost of 8 for instruction: %shl +; AVX2: Found an estimated cost of 2 for instruction: %shl +; XOPAVX: Found an estimated cost of 4 for instruction: %shl +; XOPAVX2: Found an estimated cost of 2 for instruction: %shl + + +; Same as 'test7', except that now the cost is double. + +define <16 x i32> @test10(<16 x i32> %a) { + %shl = shl <16 x i32> %a, <i32 1, i32 1, i32 2, i32 3, i32 1, i32 1, i32 2, i32 3, i32 1, i32 1, i32 2, i32 3, i32 1, i32 1, i32 2, i32 3> + ret <16 x i32> %shl +} +; CHECK: 'Cost Model Analysis' for function 'test10': +; SSE2: Found an estimated cost of 24 for instruction: %shl +; SSE41: Found an estimated cost of 4 for instruction: %shl +; AVX: Found an estimated cost of 8 for instruction: %shl +; AVX2: Found an estimated cost of 2 for instruction: %shl +; XOPAVX: Found an estimated cost of 4 for instruction: %shl +; XOPAVX2: Found an estimated cost of 2 for instruction: %shl + + +; On AVX2 we are able to lower the following shift into a sequence of +; two vpsllvq instructions. Therefore, the expected cost is only 2. +; In all other cases, this shift is scalarized as we don't have vpsllv +; instructions. + +define <8 x i64> @test11(<8 x i64> %a) { + %shl = shl <8 x i64> %a, <i64 1, i64 1, i64 2, i64 3, i64 1, i64 1, i64 2, i64 3> + ret <8 x i64> %shl +} +; CHECK: 'Cost Model Analysis' for function 'test11': +; SSE2: Found an estimated cost of 16 for instruction: %shl +; SSE41: Found an estimated cost of 16 for instruction: %shl +; AVX: Found an estimated cost of 16 for instruction: %shl +; AVX2: Found an estimated cost of 2 for instruction: %shl +; XOPAVX: Found an estimated cost of 4 for instruction: %shl +; XOPAVX2: Found an estimated cost of 2 for instruction: %shl diff --git a/test/Analysis/CostModel/no_info.ll b/test/Analysis/CostModel/no_info.ll index 5f3b56ad9cf8..931669b60176 100644 --- a/test/Analysis/CostModel/no_info.ll +++ b/test/Analysis/CostModel/no_info.ll @@ -5,9 +5,27 @@ ; -- No triple in this module -- -;CHECK: cost of 1 {{.*}} add -;CHECK: cost of 1 {{.*}} ret +; CHECK-LABEL: function 'no_info' +; CHECK: cost of 1 {{.*}} add +; CHECK: cost of 1 {{.*}} ret define i32 @no_info(i32 %arg) { %e = add i32 %arg, %arg ret i32 %e } + +define i8 @addressing_mode_reg_reg(i8* %a, i32 %b) { +; CHECK-LABEL: function 'addressing_mode_reg_reg' + %p = getelementptr i8, i8* %a, i32 %b ; NoTTI accepts reg+reg addressing. +; CHECK: cost of 0 {{.*}} getelementptr + %v = load i8, i8* %p + ret i8 %v +} + +; CHECK-LABEL: function 'addressing_mode_scaled_reg' +define i32 @addressing_mode_scaled_reg(i32* %a, i32 %b) { + ; NoTTI rejects reg+scale*reg addressing. + %p = getelementptr i32, i32* %a, i32 %b +; CHECK: cost of 1 {{.*}} getelementptr + %v = load i32, i32* %p + ret i32 %v +} diff --git a/test/Analysis/Delinearization/a.ll b/test/Analysis/Delinearization/a.ll index 78bbfcf7de6e..917fc355726c 100644 --- a/test/Analysis/Delinearization/a.ll +++ b/test/Analysis/Delinearization/a.ll @@ -10,7 +10,7 @@ ; AddRec: {{{(28 + (4 * (-4 + (3 * %m)) * %o) + %A),+,(8 * %m * %o)}<%for.i>,+,(12 * %o)}<%for.j>,+,20}<%for.k> ; CHECK: Base offset: %A ; CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of 4 bytes. -; CHECK: ArrayRef[{3,+,2}<%for.i>][{-4,+,3}<%for.j>][{7,+,5}<%for.k>] +; CHECK: ArrayRef[{3,+,2}<%for.i>][{-4,+,3}<%for.j>][{7,+,5}<nw><%for.k>] define void @foo(i64 %n, i64 %m, i64 %o, i32* nocapture %A) #0 { entry: diff --git a/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_3d.ll b/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_3d.ll index 317e62c8ef90..79d0c789704b 100644 --- a/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_3d.ll +++ b/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_3d.ll @@ -11,7 +11,7 @@ ; AddRec: {{{(56 + (8 * (-4 + (3 * %m)) * %o) + %A),+,(8 * %m * %o)}<%for.i>,+,(8 * %o)}<%for.j>,+,8}<%for.k> ; CHECK: Base offset: %A ; CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of 8 bytes. -; CHECK: ArrayRef[{3,+,1}<nw><%for.i>][{-4,+,1}<nw><%for.j>][{7,+,1}<nw><%for.k>] +; CHECK: ArrayRef[{3,+,1}<nuw><%for.i>][{-4,+,1}<nw><%for.j>][{7,+,1}<nuw><nsw><%for.k>] define void @foo(i64 %n, i64 %m, i64 %o, double* %A) { entry: diff --git a/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_nts_3d.ll b/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_nts_3d.ll index ada7758b21ba..f886d2ccd288 100644 --- a/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_nts_3d.ll +++ b/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_nts_3d.ll @@ -11,7 +11,7 @@ ; AddRec: {{{(56 + (8 * (-4 + (3 * %m)) * (%o + %p)) + %A),+,(8 * (%o + %p) * %m)}<%for.cond4.preheader.lr.ph.us>,+,(8 * (%o + %p))}<%for.body6.lr.ph.us.us>,+,8}<%for.body6.us.us> ; CHECK: Base offset: %A ; CHECK: ArrayDecl[UnknownSize][%m][(%o + %p)] with elements of 8 bytes. -; CHECK: ArrayRef[{3,+,1}<nw><%for.cond4.preheader.lr.ph.us>][{-4,+,1}<nw><%for.body6.lr.ph.us.us>][{7,+,1}<nw><%for.body6.us.us>] +; CHECK: ArrayRef[{3,+,1}<nuw><%for.cond4.preheader.lr.ph.us>][{-4,+,1}<nw><%for.body6.lr.ph.us.us>][{7,+,1}<nw><%for.body6.us.us>] define void @foo(i64 %n, i64 %m, i64 %o, i64 %p, double* nocapture %A) nounwind uwtable { entry: diff --git a/test/Analysis/Delinearization/multidim_ivs_and_parameteric_offsets_3d.ll b/test/Analysis/Delinearization/multidim_ivs_and_parameteric_offsets_3d.ll index 9e37b76e59b9..893c542c06a9 100644 --- a/test/Analysis/Delinearization/multidim_ivs_and_parameteric_offsets_3d.ll +++ b/test/Analysis/Delinearization/multidim_ivs_and_parameteric_offsets_3d.ll @@ -11,7 +11,7 @@ ; AddRec: {{{((8 * ((((%m * %p) + %q) * %o) + %r)) + %A),+,(8 * %m * %o)}<%for.i>,+,(8 * %o)}<%for.j>,+,8}<%for.k> ; CHECK: Base offset: %A ; CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of 8 bytes. -; CHECK: ArrayRef[{%p,+,1}<nw><%for.i>][{%q,+,1}<nw><%for.j>][{%r,+,1}<nw><%for.k>] +; CHECK: ArrayRef[{%p,+,1}<nw><%for.i>][{%q,+,1}<nw><%for.j>][{%r,+,1}<nsw><%for.k>] define void @foo(i64 %n, i64 %m, i64 %o, double* %A, i64 %p, i64 %q, i64 %r) { entry: diff --git a/test/Analysis/Delinearization/parameter_addrec_product.ll b/test/Analysis/Delinearization/parameter_addrec_product.ll new file mode 100644 index 000000000000..561158eae739 --- /dev/null +++ b/test/Analysis/Delinearization/parameter_addrec_product.ll @@ -0,0 +1,56 @@ +; RUN: opt -delinearize -analyze < %s | FileCheck %s +; +; void foo(float *A, long *p) { +; for (long i = 0; i < 100; i++) +; for (long j = 0; j < 100; j++) +; A[i * (*p) + j] += i + j; +; } +; +; CHECK: ArrayDecl[UnknownSize][%pval] with elements of 4 bytes. +; CHECK: ArrayRef[{0,+,1}<nuw><nsw><%bb2>][{0,+,1}<nuw><nsw><%bb4>] +; +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +define void @foo(float* %A, i64* %p) { +bb: + br label %bb2 + +bb2: ; preds = %bb16, %bb + %i.0 = phi i64 [ 0, %bb ], [ %tmp17, %bb16 ] + %exitcond1 = icmp ne i64 %i.0, 100 + br i1 %exitcond1, label %bb3, label %bb18 + +bb3: ; preds = %bb2 + br label %bb4 + +bb4: ; preds = %bb13, %bb3 + %j.0 = phi i64 [ 0, %bb3 ], [ %tmp14, %bb13 ] + %exitcond = icmp ne i64 %j.0, 100 + br i1 %exitcond, label %bb5, label %bb15 + +bb5: ; preds = %bb4 + %tmp = add nuw nsw i64 %i.0, %j.0 + %tmp6 = sitofp i64 %tmp to float + %pval = load i64, i64* %p, align 8 + %tmp8 = mul nsw i64 %i.0, %pval + %tmp9 = add nsw i64 %tmp8, %j.0 + %tmp10 = getelementptr inbounds float, float* %A, i64 %tmp9 + %tmp11 = load float, float* %tmp10, align 4 + %tmp12 = fadd float %tmp11, %tmp6 + store float %tmp12, float* %tmp10, align 4 + br label %bb13 + +bb13: ; preds = %bb5 + %tmp14 = add nuw nsw i64 %j.0, 1 + br label %bb4 + +bb15: ; preds = %bb4 + br label %bb16 + +bb16: ; preds = %bb15 + %tmp17 = add nuw nsw i64 %i.0, 1 + br label %bb2 + +bb18: ; preds = %bb2 + ret void +} diff --git a/test/Analysis/DemandedBits/basic.ll b/test/Analysis/DemandedBits/basic.ll new file mode 100644 index 000000000000..487e522e9dbc --- /dev/null +++ b/test/Analysis/DemandedBits/basic.ll @@ -0,0 +1,34 @@ +; RUN: opt -S -demanded-bits -analyze < %s | FileCheck %s + +; CHECK-LABEL: 'test_mul' +; CHECK-DAG: DemandedBits: 0xFF for %1 = add nsw i32 %a, 5 +; CHECK-DAG: DemandedBits: 0xFF for %3 = trunc i32 %2 to i8 +; CHECK-DAG: DemandedBits: 0xFF for %2 = mul nsw i32 %1, %b +define i8 @test_mul(i32 %a, i32 %b) { + %1 = add nsw i32 %a, 5 + %2 = mul nsw i32 %1, %b + %3 = trunc i32 %2 to i8 + ret i8 %3 +} + +; CHECK-LABEL: 'test_icmp1' +; CHECK-DAG: DemandedBits: 0x1 for %3 = icmp eq i32 %1, %2 +; CHECK-DAG: DemandedBits: 0xFFF for %1 = and i32 %a, 255 +; CHECK-DAG: DemandedBits: 0xFFF for %2 = shl i32 %1, 4 +define i1 @test_icmp1(i32 %a, i32 %b) { + %1 = and i32 %a, 255 + %2 = shl i32 %1, 4 + %3 = icmp eq i32 %1, %2 + ret i1 %3 +} + +; CHECK-LABEL: 'test_icmp2' +; CHECK-DAG: DemandedBits: 0x1 for %3 = icmp eq i32 %1, %2 +; CHECK-DAG: DemandedBits: 0xFF for %1 = and i32 %a, 255 +; CHECK-DAG: DemandedBits: 0xF for %2 = ashr i32 %1, 4 +define i1 @test_icmp2(i32 %a, i32 %b) { + %1 = and i32 %a, 255 + %2 = ashr i32 %1, 4 + %3 = icmp eq i32 %1, %2 + ret i1 %3 +} diff --git a/test/Analysis/DependenceAnalysis/GCD.ll b/test/Analysis/DependenceAnalysis/GCD.ll index 81d05a10cf1c..f9749d51bb33 100644 --- a/test/Analysis/DependenceAnalysis/GCD.ll +++ b/test/Analysis/DependenceAnalysis/GCD.ll @@ -269,10 +269,10 @@ entry: ; CHECK: da analyze - none! ; DELIN: 'Dependence Analysis' for function 'gcd4' -; DELIN: da analyze - output [* *]! +; DELIN: da analyze - none! ; DELIN: da analyze - none! ; DELIN: da analyze - confused! -; DELIN: da analyze - input [* *]! +; DELIN: da analyze - none! ; DELIN: da analyze - confused! ; DELIN: da analyze - none! @@ -339,10 +339,10 @@ entry: ; CHECK: da analyze - none! ; DELIN: 'Dependence Analysis' for function 'gcd5' -; DELIN: da analyze - output [* *]! -; DELIN: da analyze - flow [<> *]! +; DELIN: da analyze - none! +; DELIN: da analyze - flow [> *]! ; DELIN: da analyze - confused! -; DELIN: da analyze - input [* *]! +; DELIN: da analyze - none! ; DELIN: da analyze - confused! ; DELIN: da analyze - none! @@ -410,10 +410,10 @@ entry: ; CHECK: da analyze - output [* *]! ; DELIN: 'Dependence Analysis' for function 'gcd6' -; DELIN: da analyze - output [* *]! +; DELIN: da analyze - none! ; DELIN: da analyze - none! ; DELIN: da analyze - confused! -; DELIN: da analyze - input [* *]! +; DELIN: da analyze - none! ; DELIN: da analyze - confused! ; DELIN: da analyze - output [* *]! diff --git a/test/Analysis/DependenceAnalysis/NonAffineExpr.ll b/test/Analysis/DependenceAnalysis/NonAffineExpr.ll new file mode 100644 index 000000000000..265533797cec --- /dev/null +++ b/test/Analysis/DependenceAnalysis/NonAffineExpr.ll @@ -0,0 +1,36 @@ +; RUN: opt < %s -analyze -basicaa -da-delinearize -da +; +; CHECK: da analyze - consistent input [S S]! +; CHECK: da analyze - confused! +; CHECK: da analyze - input [* *]! +; +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n8:16:32-S64" +target triple = "thumbv7--linux-gnueabi" + +define void @f(i32** %a, i32 %n) align 2 { +for.preheader: + %t.0 = ashr exact i32 %n, 3 + br label %for.body.1 + +for.body.1: + %i.1 = phi i32 [ %t.5, %for.inc ], [ 0, %for.preheader ] + %i.2 = phi i32 [ %i.5, %for.inc ], [ %t.0, %for.preheader ] + br i1 undef, label %for.inc, label %for.body.2 + +for.body.2: + %i.3 = phi i32 [ %t.1, %for.body.2 ], [ %i.1, %for.body.1 ] + %t.1 = add i32 %i.3, 1 + %t.2 = load i32*, i32** %a, align 4 + %t.3 = getelementptr inbounds i32, i32* %t.2, i32 %i.3 + %t.4 = load i32, i32* %t.3, align 4 + br i1 undef, label %for.inc, label %for.body.2 + +for.inc: + %i.4 = phi i32 [ %i.2, %for.body.1 ], [ %i.2, %for.body.2 ] + %t.5 = add i32 %i.1, %i.4 + %i.5 = add i32 %i.2, -1 + br i1 undef, label %for.exit, label %for.body.1 + +for.exit: + ret void +} diff --git a/test/Analysis/DependenceAnalysis/PR21585.ll b/test/Analysis/DependenceAnalysis/PR21585.ll index bb62c68918f7..23af449ad51e 100644 --- a/test/Analysis/DependenceAnalysis/PR21585.ll +++ b/test/Analysis/DependenceAnalysis/PR21585.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -analyze -basicaa -globalsmodref-aa -da | FileCheck %s +; RUN: opt < %s -analyze -basicaa -globals-aa -da | FileCheck %s define void @i32_subscript(i32* %a) { entry: br label %for.body diff --git a/test/Analysis/DivergenceAnalysis/AMDGPU/kernel-args.ll b/test/Analysis/DivergenceAnalysis/AMDGPU/kernel-args.ll new file mode 100644 index 000000000000..63e6c5c50ded --- /dev/null +++ b/test/Analysis/DivergenceAnalysis/AMDGPU/kernel-args.ll @@ -0,0 +1,16 @@ +; RUN: opt %s -mtriple amdgcn-- -analyze -divergence | FileCheck %s + +; CHECK: DIVERGENT: +; CHECK-NOT: %arg0 +; CHECK-NOT: %arg1 +; CHECK-NOT; %arg2 +; CHECK: <2 x i32> %arg3 +; CHECK: DIVERGENT: <3 x i32> %arg4 +; CHECK: DIVERGENT: float %arg5 +; CHECK: DIVERGENT: i32 %arg6 + +define void @main([4 x <16 x i8>] addrspace(2)* byval %arg0, float inreg %arg1, i32 inreg %arg2, <2 x i32> %arg3, <3 x i32> %arg4, float %arg5, i32 %arg6) #0 { + ret void +} + +attributes #0 = { "ShaderType"="0" } diff --git a/test/Analysis/DivergenceAnalysis/AMDGPU/lit.local.cfg b/test/Analysis/DivergenceAnalysis/AMDGPU/lit.local.cfg new file mode 100644 index 000000000000..2a665f06be72 --- /dev/null +++ b/test/Analysis/DivergenceAnalysis/AMDGPU/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'AMDGPU' in config.root.targets: + config.unsupported = True diff --git a/test/Analysis/DivergenceAnalysis/NVPTX/diverge.ll b/test/Analysis/DivergenceAnalysis/NVPTX/diverge.ll index 9dd3d557f8cd..fc63038e77cc 100644 --- a/test/Analysis/DivergenceAnalysis/NVPTX/diverge.ll +++ b/test/Analysis/DivergenceAnalysis/NVPTX/diverge.ll @@ -185,14 +185,35 @@ else: ret i32 1 } +; Verifies sync-dependence is computed correctly in the absense of loops. +define i32 @sync_no_loop(i32 %arg) { +entry: + %0 = add i32 %arg, 1 + %tid = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() + %1 = icmp sge i32 %tid, 10 + br i1 %1, label %bb1, label %bb2 + +bb1: + br label %bb3 + +bb2: + br label %bb3 + +bb3: + %2 = add i32 %0, 2 + ; CHECK-NOT: DIVERGENT: %2 + ret i32 %2 +} + declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() declare i32 @llvm.nvvm.read.ptx.sreg.tid.y() declare i32 @llvm.nvvm.read.ptx.sreg.tid.z() declare i32 @llvm.ptx.read.laneid() -!nvvm.annotations = !{!0, !1, !2, !3, !4} +!nvvm.annotations = !{!0, !1, !2, !3, !4, !5} !0 = !{i32 (i32, i32, i32)* @no_diverge, !"kernel", i32 1} !1 = !{i32 (i32, i32)* @sync, !"kernel", i32 1} !2 = !{i32 (i32, i32, i32)* @mixed, !"kernel", i32 1} !3 = !{i32 ()* @loop, !"kernel", i32 1} !4 = !{i32 (i1)* @unstructured_loop, !"kernel", i32 1} +!5 = !{i32 (i32)* @sync_no_loop, !"kernel", i32 1} diff --git a/test/Analysis/GlobalsModRef/2008-09-03-ReadGlobals.ll b/test/Analysis/GlobalsModRef/2008-09-03-ReadGlobals.ll index 513ec86ef031..37796a9ceb32 100644 --- a/test/Analysis/GlobalsModRef/2008-09-03-ReadGlobals.ll +++ b/test/Analysis/GlobalsModRef/2008-09-03-ReadGlobals.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -globalsmodref-aa -gvn -S | FileCheck %s +; RUN: opt < %s -globals-aa -gvn -S | FileCheck %s @g = internal global i32 0 ; <i32*> [#uses=2] diff --git a/test/Analysis/GlobalsModRef/aliastest.ll b/test/Analysis/GlobalsModRef/aliastest.ll index 3474e130de8c..ecc6bcc55d1d 100644 --- a/test/Analysis/GlobalsModRef/aliastest.ll +++ b/test/Analysis/GlobalsModRef/aliastest.ll @@ -1,4 +1,7 @@ -; RUN: opt < %s -basicaa -globalsmodref-aa -gvn -S | FileCheck %s +; RUN: opt < %s -basicaa -globals-aa -gvn -S -enable-unsafe-globalsmodref-alias-results | FileCheck %s +; +; Note that this test relies on an unsafe feature of GlobalsModRef. While this +; test is correct and safe, GMR's technique for handling this isn't generally. @X = internal global i32 4 ; <i32*> [#uses=1] diff --git a/test/Analysis/GlobalsModRef/argmemonly-escape.ll b/test/Analysis/GlobalsModRef/argmemonly-escape.ll new file mode 100644 index 000000000000..64c625810af9 --- /dev/null +++ b/test/Analysis/GlobalsModRef/argmemonly-escape.ll @@ -0,0 +1,47 @@ +; RUN: opt < %s -O1 -S -enable-non-lto-gmr=true | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.10.0" + +@a = internal global [3 x i32] zeroinitializer, align 4 + +; The important thing we're checking for here is the reload of (some element of) +; @a after the memset. + +; CHECK-LABEL: @main +; CHECK: load i32, i32* getelementptr {{.*}} @a +; CHECK-NEXT: call void @memsetp0i8i64{{.*}} @a +; CHECK-NEXT: load i32, i32* getelementptr {{.*}} @a +; CHECK-NEXT: call void @memsetp0i8i64A{{.*}} @a +; CHECK-NEXT: load i32, i32* getelementptr {{.*}} @a +; CHECK: icmp eq +; CHECK: br i1 + +define i32 @main() { +entry: + %0 = bitcast [3 x i32]* @a to i8* + %1 = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @a, i64 0, i64 2), align 4 + call void @memsetp0i8i64(i8* %0, i8 0, i64 4, i32 4, i1 false) + %2 = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @a, i64 0, i64 2), align 4 + call void @memsetp0i8i64A(i8* %0, i8 0, i64 4, i32 4, i1 false) + %3 = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @a, i64 0, i64 2), align 4 + %4 = add i32 %2, %3 + %cmp1 = icmp eq i32 %1, %4 + br i1 %cmp1, label %if.then, label %if.end + +if.then: ; preds = %entr + call void @abort() #3 + unreachable + +if.end: ; preds = %entry + ret i32 0 +} + +; Function Attrs: nounwind argmemonly +declare void @memsetp0i8i64(i8* nocapture, i8, i64, i32, i1) nounwind argmemonly + +; Function Attrs: nounwind inaccessiblemem_or_argmemonly +declare void @memsetp0i8i64A(i8* nocapture, i8, i64, i32, i1) nounwind inaccessiblemem_or_argmemonly + +; Function Attrs: noreturn nounwind +declare void @abort() noreturn nounwind diff --git a/test/Analysis/GlobalsModRef/atomic-instrs.ll b/test/Analysis/GlobalsModRef/atomic-instrs.ll new file mode 100644 index 000000000000..d2ae830ff87a --- /dev/null +++ b/test/Analysis/GlobalsModRef/atomic-instrs.ll @@ -0,0 +1,37 @@ +; RUN: opt < %s -globals-aa -gvn -S | FileCheck %s + +@X = internal global i32 4 + +define i32 @test_cmpxchg(i32* %P) { +; CHECK-LABEL: @test_cmpxchg +; CHECK-NEXT: store i32 12, i32* @X +; CHECK-NEXT: call void @modrefX_cmpxchg() +; CHECK-NEXT: %V = load i32, i32* @X +; CHECK-NEXT: ret i32 %V + store i32 12, i32* @X + call void @modrefX_cmpxchg() + %V = load i32, i32* @X + ret i32 %V +} + +define void @modrefX_cmpxchg() { + %1 = cmpxchg i32* @X, i32 0, i32 -1 monotonic monotonic + ret void +} + +define i32 @test_atomicrmw(i32* %P) { +; CHECK-LABEL: @test_atomicrmw +; CHECK-NEXT: store i32 12, i32* @X +; CHECK-NEXT: call void @modrefXatomicrmw() +; CHECK-NEXT: %V = load i32, i32* @X +; CHECK-NEXT: ret i32 %V + store i32 12, i32* @X + call void @modrefXatomicrmw() + %V = load i32, i32* @X + ret i32 %V +} + +define void @modrefXatomicrmw() { + %1 = atomicrmw add i32* @X, i32 1 acquire + ret void +} diff --git a/test/Analysis/GlobalsModRef/chaining-analysis.ll b/test/Analysis/GlobalsModRef/chaining-analysis.ll index 26671daf3480..a12d7371524a 100644 --- a/test/Analysis/GlobalsModRef/chaining-analysis.ll +++ b/test/Analysis/GlobalsModRef/chaining-analysis.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -basicaa -globalsmodref-aa -gvn -S | FileCheck %s +; RUN: opt < %s -basicaa -globals-aa -gvn -S | FileCheck %s ; This test requires the use of previous analyses to determine that ; doesnotmodX does not modify X (because 'sin' doesn't). diff --git a/test/Analysis/GlobalsModRef/indirect-global.ll b/test/Analysis/GlobalsModRef/indirect-global.ll index 028132324674..a51f54b07503 100644 --- a/test/Analysis/GlobalsModRef/indirect-global.ll +++ b/test/Analysis/GlobalsModRef/indirect-global.ll @@ -1,4 +1,7 @@ -; RUN: opt < %s -basicaa -globalsmodref-aa -gvn -instcombine -S | FileCheck %s +; RUN: opt < %s -basicaa -globals-aa -gvn -instcombine -S -enable-unsafe-globalsmodref-alias-results | FileCheck %s +; +; Note that this test relies on an unsafe feature of GlobalsModRef. While this +; test is correct and safe, GMR's technique for handling this isn't generally. @G = internal global i32* null ; <i32**> [#uses=3] diff --git a/test/Analysis/GlobalsModRef/memset-escape.ll b/test/Analysis/GlobalsModRef/memset-escape.ll new file mode 100644 index 000000000000..8da375ad8775 --- /dev/null +++ b/test/Analysis/GlobalsModRef/memset-escape.ll @@ -0,0 +1,65 @@ +; RUN: opt < %s -O1 -S -enable-non-lto-gmr=true | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.10.0" + +@a = internal global [3 x i32] zeroinitializer, align 4 +@b = common global i32 0, align 4 + +; The important thing we're checking for here is the reload of (some element of) +; @a after the memset. + +; CHECK-LABEL: @main +; CHECK: call void @llvm.memset.p0i8.i64{{.*}} @a +; CHECK: store i32 3 +; CHECK: load i32, i32* getelementptr {{.*}} @a +; CHECK: icmp eq i32 +; CHECK: br i1 + +define i32 @main() { +entry: + %retval = alloca i32, align 4 + %c = alloca [1 x i32], align 4 + store i32 0, i32* %retval, align 4 + %0 = bitcast [1 x i32]* %c to i8* + call void @llvm.memset.p0i8.i64(i8* %0, i8 0, i64 4, i32 4, i1 false) + store i32 1, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @a, i64 0, i64 2), align 4 + store i32 0, i32* @b, align 4 + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %1 = load i32, i32* @b, align 4 + %cmp = icmp slt i32 %1, 3 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %2 = load i32, i32* @b, align 4 + %idxprom = sext i32 %2 to i64 + %arrayidx = getelementptr inbounds [3 x i32], [3 x i32]* @a, i64 0, i64 %idxprom + store i32 0, i32* %arrayidx, align 4 + br label %for.inc + +for.inc: ; preds = %for.body + %3 = load i32, i32* @b, align 4 + %inc = add nsw i32 %3, 1 + store i32 %inc, i32* @b, align 4 + br label %for.cond + +for.end: ; preds = %for.cond + %4 = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @a, i64 0, i64 2), align 4 + %cmp1 = icmp ne i32 %4, 0 + br i1 %cmp1, label %if.then, label %if.end + +if.then: ; preds = %for.end + call void @abort() #3 + unreachable + +if.end: ; preds = %for.end + ret i32 0 +} + +; Function Attrs: nounwind argmemonly +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind argmemonly + +; Function Attrs: noreturn nounwind +declare void @abort() noreturn nounwind diff --git a/test/Analysis/GlobalsModRef/modreftest.ll b/test/Analysis/GlobalsModRef/modreftest.ll index 74101e23bed9..2018b149fc06 100644 --- a/test/Analysis/GlobalsModRef/modreftest.ll +++ b/test/Analysis/GlobalsModRef/modreftest.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -basicaa -globalsmodref-aa -gvn -S | FileCheck %s +; RUN: opt < %s -basicaa -globals-aa -gvn -S | FileCheck %s @X = internal global i32 4 ; <i32*> [#uses=2] @@ -16,3 +16,23 @@ define i32 @test(i32* %P) { define void @doesnotmodX() { ret void } + +declare void @InaccessibleMemOnlyFunc( ) #0 +declare void @InaccessibleMemOrArgMemOnlyFunc( ) #1 + +define i32 @test2(i32* %P) { +; CHECK: @test2 +; CHECK-NEXT: store i32 12, i32* @X +; CHECK-NEXT: call void @InaccessibleMemOnlyFunc() +; CHECK-NEXT: call void @InaccessibleMemOrArgMemOnlyFunc() +; CHECK-NOT: load i32 +; CHECK-NEXT: ret i32 12 + store i32 12, i32* @X + call void @InaccessibleMemOnlyFunc( ) + call void @InaccessibleMemOrArgMemOnlyFunc( ) + %V = load i32, i32* @X ; <i32> [#uses=1] + ret i32 %V +} + +attributes #0 = { inaccessiblememonly } +attributes #1 = { inaccessiblemem_or_argmemonly } diff --git a/test/Analysis/GlobalsModRef/nocapture.ll b/test/Analysis/GlobalsModRef/nocapture.ll new file mode 100644 index 000000000000..0cb80a10f8da --- /dev/null +++ b/test/Analysis/GlobalsModRef/nocapture.ll @@ -0,0 +1,57 @@ +; RUN: opt < %s -globals-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.10.0" + +@a = internal global i32 0, align 4 +@b = internal global i32 0, align 4 + +define void @g(i32* %p, void (i32*)* nocapture %ptr) { +entry: + tail call void %ptr(i32* %p) #1 + ret void +} + +; CHECK-LABEL: Function: f +; CHECK: MayAlias: i32* %p, i32* @a +; CHECK: MayAlias: i32* %q, i32* @a +define i32 @f(i32 %n, i32* nocapture readonly %p, i32* nocapture %q, void (i32*)* nocapture %ptr) { +entry: + tail call void @g(i32* nonnull @a, void (i32*)* %ptr) + %arrayidx = getelementptr inbounds i32, i32* %p, i64 0 + %z1 = load i32, i32* %arrayidx, align 4 + %z2 = load i32, i32* %q, align 4 + %add = add nsw i32 %z2, %z1 + store i32 %add, i32* %q, align 4 + ret i32 4 +} + +define void @g2(i32* nocapture %p, void (i32*)* nocapture %ptr) { +entry: + tail call void %ptr(i32* %p) #1 + ret void +} + +; CHECK-LABEL: Function: f2 +; CHECK: NoAlias: i32* %p, i32* @b +; CHECK: NoAlias: i32* %q, i32* @b +define i32 @f2(i32 %n, i32* nocapture readonly %p, i32* nocapture %q, void (i32*)* nocapture %ptr) { +entry: + tail call void @g2(i32* nonnull @b, void (i32*)* %ptr) + %arrayidx = getelementptr inbounds i32, i32* %p, i64 0 + %z1 = load i32, i32* %arrayidx, align 4 + %z2 = load i32, i32* %q, align 4 + %add = add nsw i32 %z2, %z1 + store i32 %add, i32* %q, align 4 + ret i32 4 +} + +declare void @g3() + +; CHECK-LABEL: Function: f3 +; CHECK: NoAlias: i32* %p, i32* @b +define void @f3(i32* nocapture readonly %p) { +entry: + tail call void @g3() [ "deopt"(i32* @b, i32 *%p) ] + unreachable +} diff --git a/test/Analysis/GlobalsModRef/nonescaping-noalias.ll b/test/Analysis/GlobalsModRef/nonescaping-noalias.ll new file mode 100644 index 000000000000..8ce9551edec7 --- /dev/null +++ b/test/Analysis/GlobalsModRef/nonescaping-noalias.ll @@ -0,0 +1,116 @@ +; RUN: opt < %s -globals-aa -gvn -S | FileCheck %s +; +; This tests the safe no-alias conclusions of GMR -- when there is +; a non-escaping global as one indentified underlying object and some pointer +; that would inherently have escaped any other function as the other underlying +; pointer of an alias query. + +@g1 = internal global i32 0 + +define i32 @test1(i32* %param) { +; Ensure that we can fold a store to a load of a global across a store to +; a parameter when the global is non-escaping. +; +; CHECK-LABEL: @test1( +; CHECK: store i32 42, i32* @g1 +; CHECK-NOT: load i32 +; CHECK: ret i32 42 +entry: + store i32 42, i32* @g1 + store i32 7, i32* %param + %v = load i32, i32* @g1 + ret i32 %v +} + +declare i32* @f() + +define i32 @test2() { +; Ensure that we can fold a store to a load of a global across a store to +; the pointer returned by a function call. Since the global could not escape, +; this function cannot be returning its address. +; +; CHECK-LABEL: @test2( +; CHECK: store i32 42, i32* @g1 +; CHECK-NOT: load i32 +; CHECK: ret i32 42 +entry: + %ptr = call i32* @f() readnone + store i32 42, i32* @g1 + store i32 7, i32* %ptr + %v = load i32, i32* @g1 + ret i32 %v +} + +@g2 = external global i32* + +define i32 @test3() { +; Ensure that we can fold a store to a load of a global across a store to +; the pointer loaded from that global. Because the global does not escape, it +; cannot alias a pointer loaded out of a global. +; +; CHECK-LABEL: @test3( +; CHECK: store i32 42, i32* @g1 +; CHECK: store i32 7, i32* +; CHECK-NOT: load i32 +; CHECK: ret i32 42 +entry: + store i32 42, i32* @g1 + %ptr1 = load i32*, i32** @g2 + store i32 7, i32* %ptr1 + %v = load i32, i32* @g1 + ret i32 %v +} + +@g3 = internal global i32 1 +@g4 = internal global [10 x i32*] zeroinitializer + +define i32 @test4(i32* %param, i32 %n, i1 %c1, i1 %c2, i1 %c3) { +; Ensure that we can fold a store to a load of a global across a store to +; the pointer loaded from that global even when the load is behind PHIs and +; selects, and there is a mixture of a load and another global or argument. +; Note that we can't eliminate the load here because it is used in a PHI and +; GVN doesn't try to do real DCE. The store is still forwarded by GVN though. +; +; CHECK-LABEL: @test4( +; CHECK: store i32 42, i32* @g1 +; CHECK: store i32 7, i32* +; CHECK: ret i32 42 +entry: + %call = call i32* @f() + store i32 42, i32* @g1 + %ptr1 = load i32*, i32** @g2 + %ptr2 = select i1 %c1, i32* %ptr1, i32* %param + %ptr3 = select i1 %c3, i32* %ptr2, i32* @g3 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %inc, %loop ] + %ptr = phi i32* [ %ptr3, %entry ], [ %ptr5, %loop ] + store i32 7, i32* %ptr + %ptr4 = load i32*, i32** getelementptr ([10 x i32*], [10 x i32*]* @g4, i32 0, i32 1) + %ptr5 = select i1 %c2, i32* %ptr4, i32* %call + %inc = add i32 %iv, 1 + %test = icmp slt i32 %inc, %n + br i1 %test, label %loop, label %exit + +exit: + %v = load i32, i32* @g1 + ret i32 %v +} + +define i32 @test5(i32** %param) { +; Ensure that we can fold a store to a load of a global across a store to +; a parameter that has been dereferenced when the global is non-escaping. +; +; CHECK-LABEL: @test5( +; CHECK: %p = load i32* +; CHECK: store i32 42, i32* @g1 +; CHECK-NOT: load i32 +; CHECK: ret i32 42 +entry: + %p = load i32*, i32** %param + store i32 42, i32* @g1 + store i32 7, i32* %p + %v = load i32, i32* @g1 + ret i32 %v +} diff --git a/test/Analysis/GlobalsModRef/pr12351.ll b/test/Analysis/GlobalsModRef/pr12351.ll index 8f922770b306..5d299cd2e917 100644 --- a/test/Analysis/GlobalsModRef/pr12351.ll +++ b/test/Analysis/GlobalsModRef/pr12351.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -basicaa -globalsmodref-aa -gvn -S | FileCheck %s +; RUN: opt < %s -basicaa -globals-aa -gvn -S | FileCheck %s declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1) define void @foo(i8* %x, i8* %y) { diff --git a/test/Analysis/GlobalsModRef/pr25309.ll b/test/Analysis/GlobalsModRef/pr25309.ll new file mode 100644 index 000000000000..bca5e9307656 --- /dev/null +++ b/test/Analysis/GlobalsModRef/pr25309.ll @@ -0,0 +1,27 @@ +; RUN: opt -globals-aa -gvn < %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" + +; @o and @m are initialized to @i, so they should not be classed as +; indirect globals referring only to allocation functions. +@o = internal global i32* @i, align 8 +@m = internal global i32* @i, align 8 +@i = internal global i32 0, align 4 + +; CHECK-LABEL: @f +define i1 @f() { +entry: + %0 = load i32*, i32** @o, align 8 + store i32 0, i32* %0, align 4 + %1 = load volatile i32*, i32** @m, align 8 + store i32 1, i32* %1, align 4 + ; CHECK: %[[a:.*]] = load i32* + %2 = load i32*, i32** @o, align 8 + ; CHECK: %[[b:.*]] = load i32, i32* %[[a]] + %3 = load i32, i32* %2, align 4 + ; CHECK: %[[c:.*]] = icmp ne i32 %[[b]], 0 + %tobool.i = icmp ne i32 %3, 0 + ; CHECK: ret i1 %[[c]] + ret i1 %tobool.i +} diff --git a/test/Analysis/GlobalsModRef/purecse.ll b/test/Analysis/GlobalsModRef/purecse.ll index e030417f9552..8e2bfebc8af4 100644 --- a/test/Analysis/GlobalsModRef/purecse.ll +++ b/test/Analysis/GlobalsModRef/purecse.ll @@ -1,5 +1,5 @@ ; Test that pure functions are cse'd away -; RUN: opt < %s -globalsmodref-aa -gvn -instcombine -S | FileCheck %s +; RUN: opt < %s -disable-basicaa -globals-aa -gvn -instcombine -S | FileCheck %s define i32 @pure(i32 %X) { %Y = add i32 %X, 1 ; <i32> [#uses=1] diff --git a/test/Analysis/GlobalsModRef/weak-interposition.ll b/test/Analysis/GlobalsModRef/weak-interposition.ll new file mode 100644 index 000000000000..091aa74d5217 --- /dev/null +++ b/test/Analysis/GlobalsModRef/weak-interposition.ll @@ -0,0 +1,24 @@ +; RUN: opt -S -O1 -enable-non-lto-gmr=true < %s | FileCheck %s + +@a = common global i32 0, align 4 + +; @hook_me is weak, so GMR must not eliminate the reload of @a in @f, +; even though @hook_me doesn't mod or ref @a. + +; Function Attrs: nounwind ssp uwtable +define weak i32 @hook_me() { + ret i32 0 +} + +; Function Attrs: nounwind ssp uwtable +define i32 @f() { + %1 = alloca i32, align 4 + store i32 4, i32* @a, align 4 + %2 = call i32 @hook_me() + ; CHECK: load i32, i32* @a, align 4 + %3 = load i32, i32* @a, align 4 + %4 = add nsw i32 %3, %2 + store i32 %4, i32* @a, align 4 + %5 = load i32, i32* %1 + ret i32 %5 +} diff --git a/test/Analysis/LazyCallGraph/non-leaf-intrinsics.ll b/test/Analysis/LazyCallGraph/non-leaf-intrinsics.ll index 01782e0f2c47..89a21e542f74 100644 --- a/test/Analysis/LazyCallGraph/non-leaf-intrinsics.ll +++ b/test/Analysis/LazyCallGraph/non-leaf-intrinsics.ll @@ -1,7 +1,7 @@ ; RUN: opt -S -disable-output -passes=print-cg < %s 2>&1 | FileCheck %s declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...) -declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) +declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) define private void @f() { ret void @@ -12,7 +12,7 @@ define void @calls_statepoint(i8 addrspace(1)* %arg) gc "statepoint-example" { ; CHECK-NEXT: -> f entry: %cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)* - %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @f, i32 0, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) + %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @f, i32 0, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) ret void } diff --git a/test/Analysis/Lint/cppeh-catch-intrinsics.ll b/test/Analysis/Lint/cppeh-catch-intrinsics.ll deleted file mode 100644 index 19480a2f60fe..000000000000 --- a/test/Analysis/Lint/cppeh-catch-intrinsics.ll +++ /dev/null @@ -1,278 +0,0 @@ -; RUN: opt -lint -disable-output < %s 2>&1 | FileCheck %s - -; This test is meant to prove that the Verifier is able to identify a variety -; of errors with the llvm.eh.begincatch and llvm.eh.endcatch intrinsics. -; See cppeh-catch-intrinsics-clean for correct uses. - -target triple = "x86_64-pc-windows-msvc" - -declare void @llvm.eh.begincatch(i8*, i8*) - -declare void @llvm.eh.endcatch() - -@_ZTIi = external constant i8* - -; Function Attrs: uwtable -define void @test_missing_endcatch() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -; CHECK: Some paths from llvm.eh.begincatch may not reach llvm.eh.endcatch -; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn, i8* null) -entry: - invoke void @_Z9may_throwv() - to label %try.cont unwind label %lpad - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* bitcast (i8** @_ZTIi to i8*) - %exn = extractvalue { i8*, i32 } %0, 0 - %sel = extractvalue { i8*, i32 } %0, 1 - %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) - %matches = icmp eq i32 %sel, %1 - br i1 %matches, label %catch, label %eh.resume - -catch: ; preds = %lpad - call void @llvm.eh.begincatch(i8* %exn, i8* null) - call void @_Z10handle_intv() - br label %invoke.cont2 - -invoke.cont2: ; preds = %catch - br label %try.cont - -try.cont: ; preds = %invoke.cont2, %entry - ret void - -eh.resume: ; preds = %catch.dispatch - resume { i8*, i32 } %0 -} - -; Function Attrs: uwtable -define void @test_missing_begincatch() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -; CHECK: llvm.eh.endcatch may be reachable without passing llvm.eh.begincatch -; CHECK-NEXT: call void @llvm.eh.endcatch() -entry: - invoke void @_Z9may_throwv() - to label %try.cont unwind label %lpad - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* bitcast (i8** @_ZTIi to i8*) - %exn = extractvalue { i8*, i32 } %0, 0 - %sel = extractvalue { i8*, i32 } %0, 1 - %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) - %matches = icmp eq i32 %sel, %1 - br i1 %matches, label %catch, label %eh.resume - -catch: ; preds = %lpad - call void @_Z10handle_intv() - br label %invoke.cont2 - -invoke.cont2: ; preds = %catch - call void @llvm.eh.endcatch() - br label %try.cont - -try.cont: ; preds = %invoke.cont2, %entry - ret void - -eh.resume: ; preds = %catch.dispatch - resume { i8*, i32 } %0 -} - -; Function Attrs: uwtable -define void @test_multiple_begin() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -; CHECK: llvm.eh.begincatch may be called a second time before llvm.eh.endcatch -; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn, i8* null) -; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn, i8* null) -entry: - invoke void @_Z9may_throwv() - to label %try.cont unwind label %lpad - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* bitcast (i8** @_ZTIi to i8*) - %exn = extractvalue { i8*, i32 } %0, 0 - %sel = extractvalue { i8*, i32 } %0, 1 - %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) - %matches = icmp eq i32 %sel, %1 - br i1 %matches, label %catch, label %eh.resume - -catch: ; preds = %lpad - call void @llvm.eh.begincatch(i8* %exn, i8* null) - call void @_Z10handle_intv() - br label %invoke.cont2 - -invoke.cont2: ; preds = %catch - call void @llvm.eh.begincatch(i8* %exn, i8* null) - call void @llvm.eh.endcatch() - br label %try.cont - -try.cont: ; preds = %invoke.cont2, %entry - ret void - -eh.resume: ; preds = %catch.dispatch - resume { i8*, i32 } %0 -} - -; Function Attrs: uwtable -define void @test_multiple_end() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -; CHECK: llvm.eh.endcatch may be called a second time after llvm.eh.begincatch -; CHECK-NEXT: call void @llvm.eh.endcatch() -; CHECK-NEXT: call void @llvm.eh.endcatch() -entry: - invoke void @_Z9may_throwv() - to label %try.cont unwind label %lpad - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* bitcast (i8** @_ZTIi to i8*) - %exn = extractvalue { i8*, i32 } %0, 0 - %sel = extractvalue { i8*, i32 } %0, 1 - %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) - %matches = icmp eq i32 %sel, %1 - br i1 %matches, label %catch, label %eh.resume - -catch: ; preds = %lpad - call void @llvm.eh.begincatch(i8* %exn, i8* null) - call void @_Z10handle_intv() - call void @llvm.eh.endcatch() - br label %invoke.cont2 - -invoke.cont2: ; preds = %catch - call void @llvm.eh.endcatch() - br label %try.cont - -try.cont: ; preds = %invoke.cont2, %entry - ret void - -eh.resume: ; preds = %catch.dispatch - resume { i8*, i32 } %0 -} - - -; Function Attrs: uwtable -define void @test_begincatch_without_lpad() { -; CHECK: llvm.eh.begincatch may be reachable without passing a landingpad -; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn, i8* null) -entry: - %exn = alloca i8 - call void @llvm.eh.begincatch(i8* %exn, i8* null) - call void @_Z10handle_intv() - br label %invoke.cont2 - -invoke.cont2: ; preds = %catch - call void @llvm.eh.endcatch() - br label %try.cont - -try.cont: ; preds = %invoke.cont2, %entry - ret void -} - -; Function Attrs: uwtable -define void @test_branch_to_begincatch_with_no_lpad(i32 %fake.sel) personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -; CHECK: llvm.eh.begincatch may be reachable without passing a landingpad -; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn2, i8* null) -entry: - %fake.exn = alloca i8 - invoke void @_Z9may_throwv() - to label %catch unwind label %lpad - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* bitcast (i8** @_ZTIi to i8*) - %exn = extractvalue { i8*, i32 } %0, 0 - %sel = extractvalue { i8*, i32 } %0, 1 - %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) - %matches = icmp eq i32 %sel, %1 - br i1 %matches, label %catch, label %eh.resume - - invoke void @_Z9may_throwv() - to label %try.cont unwind label %lpad - -catch: ; preds = %lpad, %entry - %exn2 = phi i8* [%exn, %lpad], [%fake.exn, %entry] - %sel2 = phi i32 [%sel, %lpad], [%fake.sel, %entry] - call void @llvm.eh.begincatch(i8* %exn2, i8* null) - call void @_Z10handle_intv() - %matches1 = icmp eq i32 %sel2, 0 - br i1 %matches1, label %invoke.cont2, label %invoke.cont3 - -invoke.cont2: ; preds = %catch - call void @llvm.eh.endcatch() - br label %try.cont - -invoke.cont3: ; preds = %catch - call void @llvm.eh.endcatch() - br label %eh.resume - -try.cont: ; preds = %invoke.cont2 - ret void - -eh.resume: ; preds = %catch.dispatch - %lpad.val = insertvalue { i8*, i32 } undef, i32 0, 1 - resume { i8*, i32 } %lpad.val -} - -; Function Attrs: uwtable -define void @test_branch_missing_endcatch() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -; CHECK: Some paths from llvm.eh.begincatch may not reach llvm.eh.endcatch -; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn2, i8* null) -entry: - invoke void @_Z9may_throwv() - to label %invoke.cont unwind label %lpad - -invoke.cont: - invoke void @_Z9may_throwv() - to label %invoke.cont unwind label %lpad1 - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* bitcast (i8** @_ZTIi to i8*) - %exn = extractvalue { i8*, i32 } %0, 0 - %sel = extractvalue { i8*, i32 } %0, 1 - %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) - %matches = icmp eq i32 %sel, %1 - br i1 %matches, label %catch, label %eh.resume - - invoke void @_Z9may_throwv() - to label %try.cont unwind label %lpad - -lpad1: ; preds = %entry - %l1.0 = landingpad { i8*, i32 } - cleanup - catch i8* bitcast (i8** @_ZTIi to i8*) - %exn1 = extractvalue { i8*, i32 } %l1.0, 0 - %sel1 = extractvalue { i8*, i32 } %l1.0, 1 - %l1.1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) - %matchesl1 = icmp eq i32 %sel1, %l1.1 - br i1 %matchesl1, label %catch, label %eh.resume - -catch: ; preds = %lpad, %lpad1 - %exn2 = phi i8* [%exn, %lpad], [%exn1, %lpad1] - %sel2 = phi i32 [%sel, %lpad], [%sel1, %lpad1] - call void @llvm.eh.begincatch(i8* %exn2, i8* null) - call void @_Z10handle_intv() - %matches1 = icmp eq i32 %sel2, 0 - br i1 %matches1, label %invoke.cont2, label %invoke.cont3 - -invoke.cont2: ; preds = %catch - call void @llvm.eh.endcatch() - br label %try.cont - -invoke.cont3: ; preds = %catch - br label %eh.resume - -try.cont: ; preds = %invoke.cont2, %entry - ret void - -eh.resume: ; preds = %catch.dispatch - %lpad.val = insertvalue { i8*, i32 } undef, i32 0, 1 - resume { i8*, i32 } %lpad.val -} - -declare void @_Z9may_throwv() - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) - -declare void @_Z10handle_intv() - diff --git a/test/Analysis/LoopAccessAnalysis/forward-loop-carried.ll b/test/Analysis/LoopAccessAnalysis/forward-loop-carried.ll new file mode 100644 index 000000000000..e18ec2357fdb --- /dev/null +++ b/test/Analysis/LoopAccessAnalysis/forward-loop-carried.ll @@ -0,0 +1,44 @@ +; RUN: opt -loop-accesses -analyze < %s | FileCheck %s + +; for (unsigned i = 0; i < 100; i++) { +; A[i+8] = B[i] + 2; +; C[i] = A[i] * 2; +; } + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + +define void @f(i32* %A, i32* %B, i32* %C, i64 %N) { + +; CHECK: Dependences: +; CHECK-NEXT: Forward: +; CHECK-NEXT: store i32 %a_p1, i32* %Aidx_ahead, align 4 -> +; CHECK-NEXT: %a = load i32, i32* %Aidx, align 4 + +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + + %idx = add nuw nsw i64 %indvars.iv, 8 + + %Aidx_ahead = getelementptr inbounds i32, i32* %A, i64 %idx + %Bidx = getelementptr inbounds i32, i32* %B, i64 %indvars.iv + %Cidx = getelementptr inbounds i32, i32* %C, i64 %indvars.iv + %Aidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + + %b = load i32, i32* %Bidx, align 4 + %a_p1 = add i32 %b, 2 + store i32 %a_p1, i32* %Aidx_ahead, align 4 + + %a = load i32, i32* %Aidx, align 4 + %c = mul i32 %a, 2 + store i32 %c, i32* %Cidx, align 4 + + %exitcond = icmp eq i64 %indvars.iv.next, %N + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} diff --git a/test/Analysis/LoopAccessAnalysis/forward-loop-independent.ll b/test/Analysis/LoopAccessAnalysis/forward-loop-independent.ll new file mode 100644 index 000000000000..e1ba674ce80a --- /dev/null +++ b/test/Analysis/LoopAccessAnalysis/forward-loop-independent.ll @@ -0,0 +1,64 @@ +; RUN: opt -loop-accesses -analyze < %s | FileCheck %s + +; Check that loop-indepedent forward dependences are discovered properly. +; +; FIXME: This does not actually always work which is pretty confusing. Right +; now there is hack in LAA that tries to figure out loop-indepedent forward +; dependeces *outside* of the MemoryDepChecker logic (i.e. proper dependence +; analysis). +; +; Therefore if there is only loop-independent dependences for an array +; (i.e. the same index is used), we don't discover the forward dependence. +; So, at ***, we add another non-I-based access of A to trigger +; MemoryDepChecker analysis for accesses of A. +; +; for (unsigned i = 0; i < 100; i++) { +; A[i + 1] = B[i] + 1; // *** +; A[i] = B[i] + 2; +; C[i] = A[i] * 2; +; } + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + +define void @f(i32* noalias %A, i32* noalias %B, i32* noalias %C, i64 %N) { + +; CHECK: Dependences: +; CHECK-NEXT: Forward: +; CHECK-NEXT: store i32 %b_p1, i32* %Aidx, align 4 -> +; CHECK-NEXT: %a = load i32, i32* %Aidx, align 4 +; CHECK: ForwardButPreventsForwarding: +; CHECK-NEXT: store i32 %b_p2, i32* %Aidx_next, align 4 -> +; CHECK-NEXT: %a = load i32, i32* %Aidx, align 4 +; CHECK: Forward: +; CHECK-NEXT: store i32 %b_p2, i32* %Aidx_next, align 4 -> +; CHECK-NEXT: store i32 %b_p1, i32* %Aidx, align 4 + +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + + %Bidx = getelementptr inbounds i32, i32* %B, i64 %indvars.iv + %Cidx = getelementptr inbounds i32, i32* %C, i64 %indvars.iv + %Aidx_next = getelementptr inbounds i32, i32* %A, i64 %indvars.iv.next + %Aidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + + %b = load i32, i32* %Bidx, align 4 + %b_p2 = add i32 %b, 1 + store i32 %b_p2, i32* %Aidx_next, align 4 + + %b_p1 = add i32 %b, 2 + store i32 %b_p1, i32* %Aidx, align 4 + + %a = load i32, i32* %Aidx, align 4 + %c = mul i32 %a, 2 + store i32 %c, i32* %Cidx, align 4 + + %exitcond = icmp eq i64 %indvars.iv.next, %N + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} diff --git a/test/Analysis/LoopAccessAnalysis/nullptr.ll b/test/Analysis/LoopAccessAnalysis/nullptr.ll new file mode 100644 index 000000000000..a72b48cc352d --- /dev/null +++ b/test/Analysis/LoopAccessAnalysis/nullptr.ll @@ -0,0 +1,38 @@ +; RUN: opt -loop-accesses -analyze %s | FileCheck %s + +; Test that the loop accesses are proven safe in this case. +; The analyzer uses to be confused by the "diamond" because GetUnderlyingObjects +; is saying that the two pointers can both points to null. The loop analyzer +; needs to ignore null in the results returned by GetUnderlyingObjects. + +; CHECK: Memory dependences are safe with run-time checks + + +; ModuleID = 'bugpoint-reduced-simplified.bc' +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.11.0" + +; Function Attrs: ssp uwtable +define void @foo(i1 %cond, i32* %ptr1, i32* %ptr2) { + br i1 %cond, label %.preheader, label %diamond + +diamond: ; preds = %.noexc.i.i + br label %.preheader + +.preheader: ; preds = %diamond, %0 + %ptr1_or_null = phi i32* [ null, %0 ], [ %ptr1, %diamond ] + %ptr2_or_null = phi i32* [ null, %0 ], [ %ptr2, %diamond ] + br label %.lr.ph + +.lr.ph: ; preds = %.lr.ph, %.preheader + %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 10, %.preheader ] + %indvars.iv.next = add nsw i64 %indvars.iv, -1 + %tmp4 = getelementptr inbounds i32, i32* %ptr2_or_null, i64 %indvars.iv.next + %tmp5 = load i32, i32* %tmp4, align 4 + %tmp6 = getelementptr inbounds i32, i32* %ptr1_or_null, i64 %indvars.iv.next + store i32 undef, i32* %tmp6, align 4 + br i1 false, label %.lr.ph, label %.end + +.end: + ret void +} diff --git a/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll b/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll index 50b37a031a60..01b3eda3e123 100644 --- a/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll +++ b/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll @@ -81,28 +81,28 @@ for.end: ; preds = %for.body ; CHECK: Run-time memory checks: ; CHECK-NEXT: Check 0: -; CHECK-NEXT: Comparing group 0: +; CHECK-NEXT: Comparing group ([[ZERO:.+]]): ; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc ; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind -; CHECK-NEXT: Against group 1: +; CHECK-NEXT: Against group ([[ONE:.+]]): ; CHECK-NEXT: %arrayidxA1 = getelementptr inbounds i16, i16* %a, i64 %add ; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind ; CHECK-NEXT: Check 1: -; CHECK-NEXT: Comparing group 0: +; CHECK-NEXT: Comparing group ({{.*}}[[ZERO]]): ; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc ; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind -; CHECK-NEXT: Against group 2: +; CHECK-NEXT: Against group ([[TWO:.+]]): ; CHECK-NEXT: %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind ; CHECK-NEXT: Grouped accesses: -; CHECK-NEXT: Group 0: +; CHECK-NEXT: Group {{.*}}[[ZERO]]: ; CHECK-NEXT: (Low: %c High: (78 + %c)) ; CHECK-NEXT: Member: {(2 + %c),+,4} ; CHECK-NEXT: Member: {%c,+,4} -; CHECK-NEXT: Group 1: +; CHECK-NEXT: Group {{.*}}[[ONE]]: ; CHECK-NEXT: (Low: %a High: (40 + %a)) ; CHECK-NEXT: Member: {(2 + %a),+,2} ; CHECK-NEXT: Member: {%a,+,2} -; CHECK-NEXT: Group 2: +; CHECK-NEXT: Group {{.*}}[[TWO]]: ; CHECK-NEXT: (Low: %b High: (38 + %b)) ; CHECK-NEXT: Member: {%b,+,2} @@ -153,28 +153,28 @@ for.end: ; preds = %for.body ; CHECK: function 'testh': ; CHECK: Run-time memory checks: ; CHECK-NEXT: Check 0: -; CHECK-NEXT: Comparing group 0: +; CHECK-NEXT: Comparing group ([[ZERO:.+]]): ; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc ; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind -; CHECK-NEXT: Against group 1: +; CHECK-NEXT: Against group ([[ONE:.+]]): ; CHECK-NEXT: %arrayidxA1 = getelementptr i16, i16* %a, i64 %add ; CHECK-NEXT: %arrayidxA = getelementptr i16, i16* %a, i64 %ind ; CHECK-NEXT: Check 1: -; CHECK-NEXT: Comparing group 0: +; CHECK-NEXT: Comparing group ({{.*}}[[ZERO]]): ; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc ; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind -; CHECK-NEXT: Against group 2: +; CHECK-NEXT: Against group ([[TWO:.+]]): ; CHECK-NEXT: %arrayidxB = getelementptr i16, i16* %b, i64 %ind ; CHECK-NEXT: Grouped accesses: -; CHECK-NEXT: Group 0: +; CHECK-NEXT: Group {{.*}}[[ZERO]]: ; CHECK-NEXT: (Low: %c High: (78 + %c)) ; CHECK-NEXT: Member: {(2 + %c),+,4} ; CHECK-NEXT: Member: {%c,+,4} -; CHECK-NEXT: Group 1: +; CHECK-NEXT: Group {{.*}}[[ONE]]: ; CHECK-NEXT: (Low: %a High: (40 + %a)) ; CHECK-NEXT: Member: {(2 + %a),+,2} ; CHECK-NEXT: Member: {%a,+,2} -; CHECK-NEXT: Group 2: +; CHECK-NEXT: Group {{.*}}[[TWO]]: ; CHECK-NEXT: (Low: %b High: (38 + %b)) ; CHECK-NEXT: Member: {%b,+,2} @@ -217,8 +217,9 @@ for.end: ; preds = %for.body ret void } -; Don't merge pointers if there is some other check which could be falsely -; invalidated. For example, in the following loop: +; Don't merge pointers if we need to perform a check against a pointer +; to the same underlying object (doing so would emit a check that could be +; falsely invalidated) For example, in the following loop: ; ; for (i = 0; i < 5000; ++i) ; a[i + offset] = a[i] + a[i + 10000] @@ -226,27 +227,31 @@ for.end: ; preds = %for.body ; we should not merge the intervals associated with the reads (0,5000) and ; (10000, 15000) into (0, 15000) as this will pottentially fail the check ; against the interval associated with the write. +; +; We cannot have this check unless ShouldRetryWithRuntimeCheck is set, +; and therefore the grouping algorithm would create a separate group for +; each pointer. ; CHECK: function 'testi': ; CHECK: Run-time memory checks: ; CHECK-NEXT: Check 0: -; CHECK-NEXT: Comparing group 0: +; CHECK-NEXT: Comparing group ([[ZERO:.+]]): ; CHECK-NEXT: %storeidx = getelementptr inbounds i16, i16* %a, i64 %store_ind -; CHECK-NEXT: Against group 1: +; CHECK-NEXT: Against group ([[ONE:.+]]): ; CHECK-NEXT: %arrayidxA1 = getelementptr i16, i16* %a, i64 %ind ; CHECK-NEXT: Check 1: -; CHECK-NEXT: Comparing group 0: +; CHECK-NEXT: Comparing group ({{.*}}[[ZERO]]): ; CHECK-NEXT: %storeidx = getelementptr inbounds i16, i16* %a, i64 %store_ind -; CHECK-NEXT: Against group 2: +; CHECK-NEXT: Against group ([[TWO:.+]]): ; CHECK-NEXT: %arrayidxA2 = getelementptr i16, i16* %a, i64 %ind2 ; CHECK-NEXT: Grouped accesses: -; CHECK-NEXT: Group 0: +; CHECK-NEXT: Group {{.*}}[[ZERO]]: ; CHECK-NEXT: (Low: ((2 * %offset) + %a) High: (9998 + (2 * %offset) + %a)) ; CHECK-NEXT: Member: {((2 * %offset) + %a),+,2}<nsw><%for.body> -; CHECK-NEXT: Group 1: +; CHECK-NEXT: Group {{.*}}[[ONE]]: ; CHECK-NEXT: (Low: %a High: (9998 + %a)) ; CHECK-NEXT: Member: {%a,+,2}<%for.body> -; CHECK-NEXT: Group 2: +; CHECK-NEXT: Group {{.*}}[[TWO]]: ; CHECK-NEXT: (Low: (20000 + %a) High: (29998 + %a)) ; CHECK-NEXT: Member: {(20000 + %a),+,2}<%for.body> diff --git a/test/Analysis/LoopAccessAnalysis/pointer-with-unknown-bounds.ll b/test/Analysis/LoopAccessAnalysis/pointer-with-unknown-bounds.ll index d05849e2be2d..20b7fb2c6335 100644 --- a/test/Analysis/LoopAccessAnalysis/pointer-with-unknown-bounds.ll +++ b/test/Analysis/LoopAccessAnalysis/pointer-with-unknown-bounds.ll @@ -4,7 +4,7 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" ; We shouldn't quit the analysis if we encounter a pointer without known ; bounds *unless* we actually need to emit a memcheck for it. (We only -; compute bounds for SCEVAddRecs so A[i*I] is deemed not having known bounds.) +; compute bounds for SCEVAddRecs so A[i*i] is deemed not having known bounds.) ; ; for (i = 0; i < 20; ++i) ; A[i*i] *= 2; @@ -12,7 +12,7 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" ; CHECK: for.body: ; CHECK: Report: unsafe dependent memory operations in loop ; CHECK-NOT: Report: cannot identify array bounds -; CHECK: Interesting Dependences: +; CHECK: Dependences: ; CHECK: Unknown: ; CHECK: %loadA = load i16, i16* %arrayidxA, align 2 -> ; CHECK: store i16 %mul, i16* %arrayidxA, align 2 diff --git a/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll b/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll index e7305173dd95..9412028fc702 100644 --- a/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll +++ b/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll @@ -2,7 +2,7 @@ ; We give up analyzing the dependences in this loop due to non-constant ; distance between A[i+offset] and A[i] and add memchecks to prove -; independence. Make sure that no interesting dependences are reported in +; independence. Make sure that no dependences are reported in ; this case. ; ; for (i = 0; i < n; i++) @@ -12,7 +12,7 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.10.0" ; CHECK: Memory dependences are safe with run-time checks -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: 0: ; CHECK-NEXT: Comparing group diff --git a/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll b/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll new file mode 100644 index 000000000000..2053e49826b9 --- /dev/null +++ b/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll @@ -0,0 +1,89 @@ +; RUN: opt -loop-accesses -analyze < %s | FileCheck %s + +; The runtime memory check code and the access grouping +; algorithm both assume that the start and end values +; for an access range are ordered (start <= stop). +; When generating checks for accesses with negative stride +; we need to take this into account and swap the interval +; ends. +; +; for (i = 0; i < 10000; i++) { +; B[i] = A[15000 - i] * 3; +; } + +target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux-gnueabi" + +; CHECK: function 'f': +; CHECK: (Low: (20000 + %a) High: (60000 + %a)) + +@B = common global i32* null, align 8 +@A = common global i32* null, align 8 + +define void @f() { +entry: + %a = load i32*, i32** @A, align 8 + %b = load i32*, i32** @B, align 8 + br label %for.body + +for.body: ; preds = %for.body, %entry + %idx = phi i64 [ 0, %entry ], [ %add, %for.body ] + %negidx = sub i64 15000, %idx + + %arrayidxA0 = getelementptr inbounds i32, i32* %a, i64 %negidx + %loadA0 = load i32, i32* %arrayidxA0, align 2 + + %res = mul i32 %loadA0, 3 + + %add = add nuw nsw i64 %idx, 1 + + %arrayidxB = getelementptr inbounds i32, i32* %b, i64 %idx + store i32 %res, i32* %arrayidxB, align 2 + + %exitcond = icmp eq i64 %idx, 10000 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} + +; CHECK: function 'g': +; When the stride is not constant, we are forced to do umin/umax to get +; the interval limits. + +; for (i = 0; i < 10000; i++) { +; B[i] = A[15000 - step * i] * 3; +; } + +; Here it is not obvious what the limits are, since 'step' could be negative. + +; CHECK: Low: (-1 + (-1 * ((-60001 + (-1 * %a)) umax (-60001 + (40000 * %step) + (-1 * %a))))) +; CHECK: High: ((60000 + %a) umax (60000 + (-40000 * %step) + %a)) + +define void @g(i64 %step) { +entry: + %a = load i32*, i32** @A, align 8 + %b = load i32*, i32** @B, align 8 + br label %for.body + +for.body: ; preds = %for.body, %entry + %idx = phi i64 [ 0, %entry ], [ %add, %for.body ] + %idx_mul = mul i64 %idx, %step + %negidx = sub i64 15000, %idx_mul + + %arrayidxA0 = getelementptr inbounds i32, i32* %a, i64 %negidx + %loadA0 = load i32, i32* %arrayidxA0, align 2 + + %res = mul i32 %loadA0, 3 + + %add = add nuw nsw i64 %idx, 1 + + %arrayidxB = getelementptr inbounds i32, i32* %b, i64 %idx + store i32 %res, i32* %arrayidxB, align 2 + + %exitcond = icmp eq i64 %idx, 10000 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} diff --git a/test/Analysis/LoopAccessAnalysis/safe-no-checks.ll b/test/Analysis/LoopAccessAnalysis/safe-no-checks.ll index fa70c024a9c5..d85258f75aae 100644 --- a/test/Analysis/LoopAccessAnalysis/safe-no-checks.ll +++ b/test/Analysis/LoopAccessAnalysis/safe-no-checks.ll @@ -7,7 +7,15 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.10.0" +; Check the loop-carried forward anti-dep between the load of A[i+1] and the +; store of A[i]; + ; CHECK: Memory dependences are safe{{$}} +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Forward: +; CHECK-NEXT: %loadA_plus_2 = load i16, i16* %arrayidxA_plus_2, align 2 -> +; CHECK-NEXT: store i16 %mul1, i16* %arrayidxA, align 2 + define void @f(i16* noalias %a, i16* noalias %b, diff --git a/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll b/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll index 735735662952..5fc353e70cf8 100644 --- a/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll +++ b/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll @@ -13,7 +13,7 @@ target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" ; CHECK: function 'nodep_Read_Write': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Memory dependences are safe -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: Run-time memory checks: define void @nodep_Read_Write(i32* nocapture %A) { @@ -49,7 +49,7 @@ for.body: ; preds = %entry, %for.body ; CHECK: function 'nodep_Write_Read': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Memory dependences are safe -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: Run-time memory checks: define i32 @nodep_Write_Read(i32* nocapture %A) { @@ -84,7 +84,7 @@ for.body: ; preds = %entry, %for.body ; CHECK: function 'nodep_Write_Write': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Memory dependences are safe -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: Run-time memory checks: define void @nodep_Write_Write(i32* nocapture %A) { @@ -118,7 +118,7 @@ for.body: ; preds = %entry, %for.body ; CHECK: function 'unsafe_Read_Write': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: Backward: ; CHECK-NEXT: %0 = load i32, i32* %arrayidx, align 4 -> ; CHECK-NEXT: store i32 %add, i32* %arrayidx3, align 4 @@ -157,7 +157,7 @@ for.body: ; preds = %entry, %for.body ; CHECK: function 'unsafe_Write_Read': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: Backward: ; CHECK-NEXT: store i32 %0, i32* %arrayidx, align 4 -> ; CHECK-NEXT: %1 = load i32, i32* %arrayidx2, align 4 @@ -193,7 +193,7 @@ for.body: ; preds = %entry, %for.body ; CHECK: function 'unsafe_Write_Write': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: Backward: ; CHECK-NEXT: store i32 %0, i32* %arrayidx, align 4 -> ; CHECK-NEXT: store i32 %2, i32* %arrayidx3, align 4 @@ -230,7 +230,7 @@ for.body: ; preds = %entry, %for.body ; CHECK: function 'vectorizable_Read_Write': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Memory dependences are safe -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: BackwardVectorizable: ; CHECK-NEXT: %0 = load i32, i32* %arrayidx, align 4 -> ; CHECK-NEXT: store i32 %add, i32* %arrayidx2, align 4 @@ -269,7 +269,7 @@ for.body: ; preds = %entry, %for.body ; CHECK: function 'vectorizable_Write_Read': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Memory dependences are safe -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: BackwardVectorizable: ; CHECK-NEXT: store i32 %0, i32* %arrayidx, align 4 -> ; CHECK-NEXT: %1 = load i32, i32* %arrayidx2, align 4 @@ -307,7 +307,7 @@ for.body: ; preds = %entry, %for.body ; CHECK: function 'vectorizable_Write_Write': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Memory dependences are safe -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: BackwardVectorizable: ; CHECK-NEXT: store i32 %0, i32* %arrayidx, align 4 -> ; CHECK-NEXT: store i32 %2, i32* %arrayidx2, align 4 @@ -346,7 +346,7 @@ for.body: ; preds = %entry, %for.body ; CHECK: function 'vectorizable_unscaled_Read_Write': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: BackwardVectorizableButPreventsForwarding: ; CHECK-NEXT: %2 = load i32, i32* %arrayidx, align 4 -> ; CHECK-NEXT: store i32 %add, i32* %arrayidx2, align 4 @@ -387,7 +387,7 @@ for.body: ; preds = %entry, %for.body ; CHECK: for function 'vectorizable_unscaled_Write_Read': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Memory dependences are safe -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: BackwardVectorizable: ; CHECK-NEXT: store i32 %2, i32* %arrayidx, align 4 -> ; CHECK-NEXT: %3 = load i32, i32* %arrayidx2, align 4 @@ -425,7 +425,7 @@ for.body: ; preds = %entry, %for.body ; CHECK: function 'unsafe_unscaled_Read_Write': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: Backward: ; CHECK-NEXT: %2 = load i32, i32* %arrayidx, align 4 -> ; CHECK-NEXT: store i32 %add, i32* %arrayidx2, align 4 @@ -455,7 +455,7 @@ for.body: ; preds = %entry, %for.body ; CHECK: function 'unsafe_unscaled_Read_Write2': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: Backward: ; CHECK-NEXT: %2 = load i32, i32* %arrayidx, align 4 -> ; CHECK-NEXT: store i32 %add, i32* %arrayidx2, align 4 @@ -505,7 +505,7 @@ for.body: ; preds = %entry, %for.body ; CHECK: function 'interleaved_stores': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: Backward: ; CHECK-NEXT: store i32 %4, i32* %arrayidx5, align 4 -> ; CHECK-NEXT: store i32 %4, i32* %arrayidx9, align 4 diff --git a/test/Analysis/LoopAccessAnalysis/underlying-objects-2.ll b/test/Analysis/LoopAccessAnalysis/underlying-objects-2.ll index d0bed68188db..d388151365f1 100644 --- a/test/Analysis/LoopAccessAnalysis/underlying-objects-2.ll +++ b/test/Analysis/LoopAccessAnalysis/underlying-objects-2.ll @@ -38,7 +38,7 @@ target triple = "x86_64-apple-macosx10.10.0" ; CHECK: for_j.body: ; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: Backward: ; CHECK-NEXT: %loadB = load i8, i8* %gepB, align 1 -> ; CHECK-NEXT: store i8 2, i8* %gepB_plus_one, align 1 diff --git a/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll b/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll index 237cbc8b9873..7157b954c5b6 100644 --- a/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll +++ b/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll @@ -8,7 +8,7 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.10.0" ; CHECK: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Interesting Dependences: +; CHECK-NEXT: Dependences: ; CHECK-NEXT: Backward: ; CHECK-NEXT: %loadA = load i16, i16* %arrayidxA, align 2 -> ; CHECK-NEXT: store i16 %mul1, i16* %arrayidxA_plus_2, align 2 diff --git a/test/Analysis/MemoryDependenceAnalysis/memdep-block-scan-limit.ll b/test/Analysis/MemoryDependenceAnalysis/memdep-block-scan-limit.ll new file mode 100644 index 000000000000..20ca31456fd3 --- /dev/null +++ b/test/Analysis/MemoryDependenceAnalysis/memdep-block-scan-limit.ll @@ -0,0 +1,15 @@ +; RUN: opt -S -memdep -gvn -basicaa < %s | FileCheck %s +; RUN: opt -S -memdep -memdep-block-scan-limit=1 -gvn -basicaa < %s | FileCheck %s --check-prefix=WITH-LIMIT +; CHECK-LABEL: @test( +; CHECK: load +; CHECK-NOT: load +; WITH-LIMIT-LABEL: @test( +; WITH-LIMIT-CHECK: load +; WITH-LIMIT-CHECK: load +define i32 @test(i32* %p) { + %1 = load i32, i32* %p + %2 = add i32 %1, 3 + %3 = load i32, i32* %p + %4 = add i32 %2, %3 + ret i32 %4 +} diff --git a/test/Analysis/ScalarEvolution/avoid-assume-hang.ll b/test/Analysis/ScalarEvolution/avoid-assume-hang.ll new file mode 100644 index 000000000000..e2428ed1f73f --- /dev/null +++ b/test/Analysis/ScalarEvolution/avoid-assume-hang.ll @@ -0,0 +1,139 @@ +; RUN: opt %s -always-inline | opt -analyze -scalar-evolution +; There was optimization bug in ScalarEvolution, that causes too long +; compute time and stack overflow crash. + +declare void @body(i32) +declare void @llvm.assume(i1) + +define available_externally void @assume1(i64 %i.ext, i64 %a) alwaysinline { + %cmp0 = icmp ne i64 %i.ext, %a + call void @llvm.assume(i1 %cmp0) + + %a1 = add i64 %a, 1 + %cmp1 = icmp ne i64 %i.ext, %a1 + call void @llvm.assume(i1 %cmp1) + + %a2 = add i64 %a1, 1 + %cmp2 = icmp ne i64 %i.ext, %a2 + call void @llvm.assume(i1 %cmp2) + + %a3 = add i64 %a2, 1 + %cmp3 = icmp ne i64 %i.ext, %a3 + call void @llvm.assume(i1 %cmp3) + + %a4 = add i64 %a3, 1 + %cmp4 = icmp ne i64 %i.ext, %a4 + call void @llvm.assume(i1 %cmp4) + + ret void +} + +define available_externally void @assume2(i64 %i.ext, i64 %a) alwaysinline { + call void @assume1(i64 %i.ext, i64 %a) + + %a1 = add i64 %a, 5 + %cmp1 = icmp ne i64 %i.ext, %a1 + call void @assume1(i64 %i.ext, i64 %a1) + + %a2 = add i64 %a1, 5 + %cmp2 = icmp ne i64 %i.ext, %a2 + call void @assume1(i64 %i.ext, i64 %a2) + + %a3 = add i64 %a2, 5 + %cmp3 = icmp ne i64 %i.ext, %a3 + call void @assume1(i64 %i.ext, i64 %a3) + + %a4 = add i64 %a3, 5 + %cmp4 = icmp ne i64 %i.ext, %a4 + call void @assume1(i64 %i.ext, i64 %a4) + + ret void +} + +define available_externally void @assume3(i64 %i.ext, i64 %a) alwaysinline { + call void @assume2(i64 %i.ext, i64 %a) + + %a1 = add i64 %a, 25 + %cmp1 = icmp ne i64 %i.ext, %a1 + call void @assume2(i64 %i.ext, i64 %a1) + + %a2 = add i64 %a1, 25 + %cmp2 = icmp ne i64 %i.ext, %a2 + call void @assume2(i64 %i.ext, i64 %a2) + + %a3 = add i64 %a2, 25 + %cmp3 = icmp ne i64 %i.ext, %a3 + call void @assume2(i64 %i.ext, i64 %a3) + + %a4 = add i64 %a3, 25 + %cmp4 = icmp ne i64 %i.ext, %a4 + call void @assume2(i64 %i.ext, i64 %a4) + + ret void +} + +define available_externally void @assume4(i64 %i.ext, i64 %a) alwaysinline { + call void @assume3(i64 %i.ext, i64 %a) + + %a1 = add i64 %a, 125 + %cmp1 = icmp ne i64 %i.ext, %a1 + call void @assume3(i64 %i.ext, i64 %a1) + + %a2 = add i64 %a1, 125 + %cmp2 = icmp ne i64 %i.ext, %a2 + call void @assume3(i64 %i.ext, i64 %a2) + + %a3 = add i64 %a2, 125 + %cmp3 = icmp ne i64 %i.ext, %a3 + call void @assume3(i64 %i.ext, i64 %a3) + + %a4 = add i64 %a3, 125 + %cmp4 = icmp ne i64 %i.ext, %a4 + call void @assume3(i64 %i.ext, i64 %a4) + + ret void +} + +define available_externally void @assume5(i64 %i.ext, i64 %a) alwaysinline { + call void @assume4(i64 %i.ext, i64 %a) + + %a1 = add i64 %a, 625 + %cmp1 = icmp ne i64 %i.ext, %a1 + call void @assume4(i64 %i.ext, i64 %a1) + + %a2 = add i64 %a1, 625 + %cmp2 = icmp ne i64 %i.ext, %a2 + call void @assume4(i64 %i.ext, i64 %a2) + + %a3 = add i64 %a2, 625 + %cmp3 = icmp ne i64 %i.ext, %a3 + call void @assume4(i64 %i.ext, i64 %a3) + + %a4 = add i64 %a3, 625 + %cmp4 = icmp ne i64 %i.ext, %a4 + call void @assume4(i64 %i.ext, i64 %a4) + + ret void +} + +define void @fn(i32 %init) { +entry: + br label %loop + +loop: + %i = phi i32 [%init, %entry], [%next, %loop] + call void @body(i32 %i) + + %i.ext = zext i32 %i to i64 + + call void @assume5(i64 %i.ext, i64 500000000) + + %i.next = add i64 %i.ext, 1 + %next = trunc i64 %i.next to i32 + %done = icmp eq i32 %i, 500000000 + + br i1 %done, label %exit, label %loop + +exit: + ret void +}
\ No newline at end of file diff --git a/test/Analysis/ScalarEvolution/constant_condition.ll b/test/Analysis/ScalarEvolution/constant_condition.ll new file mode 100644 index 000000000000..32ab91b2c857 --- /dev/null +++ b/test/Analysis/ScalarEvolution/constant_condition.ll @@ -0,0 +1,51 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +define i32 @branch_true(i32 %x, i32 %y) { +; CHECK-LABEL: Classifying expressions for: @branch_true + entry: + br i1 true, label %add, label %merge + + add: + %sum = add i32 %x, %y + br label %merge + + merge: + %v = phi i32 [ %sum, %add ], [ %x, %entry ] +; CHECK: %v = phi i32 [ %sum, %add ], [ %x, %entry ] +; CHECK-NEXT: --> (%x + %y) U: full-set S: full-set + ret i32 %v +} + +define i32 @branch_false(i32 %x, i32 %y) { +; CHECK-LABEL: Classifying expressions for: @branch_false + entry: + br i1 false, label %add, label %merge + + add: + %sum = add i32 %x, %y + br label %merge + + merge: + %v = phi i32 [ %sum, %add ], [ %x, %entry ] +; CHECK: %v = phi i32 [ %sum, %add ], [ %x, %entry ] +; CHECK-NEXT: --> %x U: full-set S: full-set + ret i32 %v +} + +define i32 @select_true(i32 %x, i32 %y) { +; CHECK-LABEL: Classifying expressions for: @select_true + entry: + %v = select i1 true, i32 %x, i32 %y +; CHECK: %v = select i1 true, i32 %x, i32 %y +; CHECK-NEXT: --> %x U: full-set S: full-set + ret i32 %v +} + +define i32 @select_false(i32 %x, i32 %y) { +; CHECK-LABEL: Classifying expressions for: @select_false + entry: + %v = select i1 false, i32 %x, i32 %y +; CHECK: %v = select i1 false, i32 %x, i32 %y +; CHECK-NEXT: --> %y U: full-set S: full-set + ret i32 %v +} diff --git a/test/Analysis/ScalarEvolution/flags-from-poison.ll b/test/Analysis/ScalarEvolution/flags-from-poison.ll new file mode 100644 index 000000000000..b1fe7f1138b6 --- /dev/null +++ b/test/Analysis/ScalarEvolution/flags-from-poison.ll @@ -0,0 +1,592 @@ +; RUN: opt < %s -S -analyze -scalar-evolution | FileCheck %s + +; Positive and negative tests for inferring flags like nsw from +; reasoning about how a poison value from overflow would trigger +; undefined behavior. + +define void @foo() { + ret void +} + +; Example where an add should get the nsw flag, so that a sext can be +; distributed over the add. +define void @test-add-nsw(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-nsw +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {%offset,+,1}<nsw> + %index32 = add nsw i32 %i, %offset + +; CHECK: %index64 = +; CHECK: --> {(sext i32 %offset to i64),+,1}<nsw> + %index64 = sext i32 %index32 to i64 + + %ptr = getelementptr inbounds float, float* %input, i64 %index64 + %nexti = add nsw i32 %i, 1 + %f = load float, float* %ptr, align 4 + call void @foo() + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Example where an add should get the nuw flag. +define void @test-add-nuw(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-nuw +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {%offset,+,1}<nuw> + %index32 = add nuw i32 %i, %offset + + %ptr = getelementptr inbounds float, float* %input, i32 %index32 + %nexti = add nuw i32 %i, 1 + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +; With no load to trigger UB from poison, we cannot infer nsw. +define void @test-add-no-load(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-no-load +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {%offset,+,1}<nw> + %index32 = add nsw i32 %i, %offset + + %ptr = getelementptr inbounds float, float* %input, i32 %index32 + %nexti = add nuw i32 %i, 1 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +; The current code is only supposed to look at the loop header, so +; it should not infer nsw in this case, as that would require looking +; outside the loop header. +define void @test-add-not-header(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-not-header +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ] + br label %loop2 +loop2: + +; CHECK: %index32 = +; CHECK: --> {%offset,+,1}<nw> + %index32 = add nsw i32 %i, %offset + + %ptr = getelementptr inbounds float, float* %input, i32 %index32 + %nexti = add nsw i32 %i, 1 + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Same thing as test-add-not-header, but in this case only the load +; instruction is outside the loop header. +define void @test-add-not-header2(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-not-header2 +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {%offset,+,1}<nw> + %index32 = add nsw i32 %i, %offset + + %ptr = getelementptr inbounds float, float* %input, i32 %index32 + %nexti = add nsw i32 %i, 1 + br label %loop2 +loop2: + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; The call instruction makes it not guaranteed that the add will be +; executed, since it could run forever or throw an exception, so we +; cannot assume that the UB is realized. +define void @test-add-call(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-call +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {%offset,+,1}<nw> + call void @foo() + %index32 = add nsw i32 %i, %offset + + %ptr = getelementptr inbounds float, float* %input, i32 %index32 + %nexti = add nsw i32 %i, 1 + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Same issue as test-add-call, but this time the call is between the +; producer of poison and the load that consumes it. +define void @test-add-call2(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-call2 +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {%offset,+,1}<nw> + %index32 = add nsw i32 %i, %offset + + %ptr = getelementptr inbounds float, float* %input, i32 %index32 + %nexti = add nsw i32 %i, 1 + call void @foo() + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Without inbounds, GEP does not propagate poison in the very +; conservative approach used here. +define void @test-add-no-inbounds(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-no-inbounds +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {%offset,+,1}<nw> + %index32 = add nsw i32 %i, %offset + + %ptr = getelementptr float, float* %input, i32 %index32 + %nexti = add nsw i32 %i, 1 + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Multiplication by a non-zero constant propagates poison if there is +; a nuw or nsw flag on the multiplication. +define void @test-add-mul-propagates(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-mul-propagates +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {%offset,+,1}<nsw> + %index32 = add nsw i32 %i, %offset + + %indexmul = mul nuw i32 %index32, 2 + %ptr = getelementptr inbounds float, float* %input, i32 %indexmul + %nexti = add nsw i32 %i, 1 + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Multiplication by a non-constant should not propagate poison in the +; very conservative approach used here. +define void @test-add-mul-no-propagation(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-mul-no-propagation +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {%offset,+,1}<nw> + %index32 = add nsw i32 %i, %offset + + %indexmul = mul nsw i32 %index32, %offset + %ptr = getelementptr inbounds float, float* %input, i32 %indexmul + %nexti = add nsw i32 %i, 1 + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Multiplication by a non-zero constant does not propagate poison +; without a no-wrap flag. +define void @test-add-mul-no-propagation2(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-mul-no-propagation2 +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {%offset,+,1}<nw> + %index32 = add nsw i32 %i, %offset + + %indexmul = mul i32 %index32, 2 + %ptr = getelementptr inbounds float, float* %input, i32 %indexmul + %nexti = add nsw i32 %i, 1 + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Division by poison triggers UB. +define void @test-add-div(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-div +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %j = +; CHECK: --> {%offset,+,1}<nsw> + %j = add nsw i32 %i, %offset + + %q = sdiv i32 %numIterations, %j + %nexti = add nsw i32 %i, 1 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Remainder of poison by non-poison divisor does not trigger UB. +define void @test-add-div2(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-div2 +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %j = +; CHECK: --> {%offset,+,1}<nw> + %j = add nsw i32 %i, %offset + + %q = sdiv i32 %j, %numIterations + %nexti = add nsw i32 %i, 1 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Store to poison address triggers UB. +define void @test-add-store(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-store +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {%offset,+,1}<nsw> + %index32 = add nsw i32 %i, %offset + + %ptr = getelementptr inbounds float, float* %input, i32 %index32 + %nexti = add nsw i32 %i, 1 + store float 1.0, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Three sequential adds where the middle add should have nsw. There is +; a special case for sequential adds and this test covers that. We have to +; put the final add first in the program since otherwise the special case +; is not triggered, hence the strange basic block ordering. +define void @test-add-twice(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-twice +entry: + br label %loop +loop2: +; CHECK: %seq = +; CHECK: --> {(2 + %offset),+,1}<nw> + %seq = add nsw nuw i32 %index32, 1 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop + +loop: + %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ] + + %j = add nsw i32 %i, 1 +; CHECK: %index32 = +; CHECK: --> {(1 + %offset),+,1}<nsw> + %index32 = add nsw i32 %j, %offset + + %ptr = getelementptr inbounds float, float* %input, i32 %index32 + %nexti = add nsw i32 %i, 1 + store float 1.0, float* %ptr, align 4 + br label %loop2 +exit: + ret void +} + +; Example where a mul should get the nsw flag, so that a sext can be +; distributed over the mul. +define void @test-mul-nsw(float* %input, i32 %stride, i32 %numIterations) { +; CHECK-LABEL: @test-mul-nsw +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {0,+,%stride}<nsw> + %index32 = mul nsw i32 %i, %stride + +; CHECK: %index64 = +; CHECK: --> {0,+,(sext i32 %stride to i64)}<nsw> + %index64 = sext i32 %index32 to i64 + + %ptr = getelementptr inbounds float, float* %input, i64 %index64 + %nexti = add nsw i32 %i, 1 + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Example where a mul should get the nuw flag. +define void @test-mul-nuw(float* %input, i32 %stride, i32 %numIterations) { +; CHECK-LABEL: @test-mul-nuw +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {0,+,%stride}<nuw> + %index32 = mul nuw i32 %i, %stride + + %ptr = getelementptr inbounds float, float* %input, i32 %index32 + %nexti = add nuw i32 %i, 1 + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +; Example where a shl should get the nsw flag, so that a sext can be +; distributed over the shl. +define void @test-shl-nsw(float* %input, i32 %start, i32 %numIterations) { +; CHECK-LABEL: @test-shl-nsw +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ %start, %entry ] + +; CHECK: %index32 = +; CHECK: --> {(256 * %start),+,256}<nsw> + %index32 = shl nsw i32 %i, 8 + +; CHECK: %index64 = +; CHECK: --> {(sext i32 (256 * %start) to i64),+,256}<nsw> + %index64 = sext i32 %index32 to i64 + + %ptr = getelementptr inbounds float, float* %input, i64 %index64 + %nexti = add nsw i32 %i, 1 + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Example where a shl should get the nuw flag. +define void @test-shl-nuw(float* %input, i32 %numIterations) { +; CHECK-LABEL: @test-shl-nuw +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {0,+,512}<nuw> + %index32 = shl nuw i32 %i, 9 + + %ptr = getelementptr inbounds float, float* %input, i32 %index32 + %nexti = add nuw i32 %i, 1 + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +; Example where a sub should *not* get the nsw flag, because of how +; scalar evolution represents A - B as A + (-B) and -B can wrap even +; in cases where A - B does not. +define void @test-sub-no-nsw(float* %input, i32 %start, i32 %sub, i32 %numIterations) { +; CHECK-LABEL: @test-sub-no-nsw +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ %start, %entry ] + +; CHECK: %index32 = +; CHECK: --> {((-1 * %sub) + %start),+,1}<nw> + %index32 = sub nsw i32 %i, %sub + %index64 = sext i32 %index32 to i64 + + %ptr = getelementptr inbounds float, float* %input, i64 %index64 + %nexti = add nsw i32 %i, 1 + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Example where a sub should get the nsw flag as the RHS cannot be the +; minimal signed value. +define void @test-sub-nsw(float* %input, i32 %start, i32 %sub, i32 %numIterations) { +; CHECK-LABEL: @test-sub-nsw +entry: + %halfsub = ashr i32 %sub, 1 + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ %start, %entry ] + +; CHECK: %index32 = +; CHECK: --> {((-1 * %halfsub)<nsw> + %start),+,1}<nsw> + %index32 = sub nsw i32 %i, %halfsub + %index64 = sext i32 %index32 to i64 + + %ptr = getelementptr inbounds float, float* %input, i64 %index64 + %nexti = add nsw i32 %i, 1 + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Example where a sub should get the nsw flag, since the LHS is non-negative, +; which implies that the RHS cannot be the minimal signed value. +define void @test-sub-nsw-lhs-non-negative(float* %input, i32 %sub, i32 %numIterations) { +; CHECK-LABEL: @test-sub-nsw-lhs-non-negative +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {(-1 * %sub),+,1}<nsw> + %index32 = sub nsw i32 %i, %sub + +; CHECK: %index64 = +; CHECK: --> {(sext i32 (-1 * %sub) to i64),+,1}<nsw> + %index64 = sext i32 %index32 to i64 + + %ptr = getelementptr inbounds float, float* %input, i64 %index64 + %nexti = add nsw i32 %i, 1 + %f = load float, float* %ptr, align 4 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop +exit: + ret void +} + +; Two adds with a sub in the middle and the sub should have nsw. There is +; a special case for sequential adds/subs and this test covers that. We have to +; put the final add first in the program since otherwise the special case +; is not triggered, hence the strange basic block ordering. +define void @test-sub-with-add(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-sub-with-add +entry: + br label %loop +loop2: +; CHECK: %seq = +; CHECK: --> {(2 + (-1 * %offset)),+,1}<nw> + %seq = add nsw nuw i32 %index32, 1 + %exitcond = icmp eq i32 %nexti, %numIterations + br i1 %exitcond, label %exit, label %loop + +loop: + %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ] + + %j = add nsw i32 %i, 1 +; CHECK: %index32 = +; CHECK: --> {(1 + (-1 * %offset)),+,1}<nsw> + %index32 = sub nsw i32 %j, %offset + + %ptr = getelementptr inbounds float, float* %input, i32 %index32 + %nexti = add nsw i32 %i, 1 + store float 1.0, float* %ptr, align 4 + br label %loop2 +exit: + ret void +} + + +; Subtraction of two recurrences. The addition in the SCEV that this +; maps to is NSW, but the negation of the RHS does not since that +; recurrence could be the most negative representable value. +define void @subrecurrences(i32 %outer_l, i32 %inner_l, i32 %val) { +; CHECK-LABEL: @subrecurrences + entry: + br label %outer + +outer: + %o_idx = phi i32 [ 0, %entry ], [ %o_idx.inc, %outer.be ] + %o_idx.inc = add nsw i32 %o_idx, 1 + %cond = icmp eq i32 %o_idx, %val + br i1 %cond, label %inner, label %outer.be + +inner: + %i_idx = phi i32 [ 0, %outer ], [ %i_idx.inc, %inner ] + %i_idx.inc = add nsw i32 %i_idx, 1 +; CHECK: %v = +; CHECK-NEXT: --> {{[{][{]}}-1,+,-1}<nw><%outer>,+,1}<nsw><%inner> + %v = sub nsw i32 %i_idx, %o_idx.inc + %forub = udiv i32 1, %v + %cond2 = icmp eq i32 %i_idx, %inner_l + br i1 %cond2, label %outer.be, label %inner + +outer.be: + %cond3 = icmp eq i32 %o_idx, %outer_l + br i1 %cond3, label %exit, label %outer + +exit: + ret void +} diff --git a/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll b/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll index 078ca03ff14e..5c372b5d7b8a 100644 --- a/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll +++ b/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll @@ -11,7 +11,7 @@ define void @infer.sext.0(i1* %c, i32 %start) { %idx.inc = add nsw i32 %idx, 1 %idx.inc.sext = sext i32 %idx.inc to i64 ; CHECK: %idx.inc.sext = sext i32 %idx.inc to i64 -; CHECK-NEXT: --> {(1 + (sext i32 %start to i64)),+,1}<nsw><%loop> +; CHECK-NEXT: --> {(1 + (sext i32 %start to i64))<nsw>,+,1}<nsw><%loop> %condition = icmp eq i32 %counter, 1 %counter.inc = add i32 %counter, 1 br i1 %condition, label %exit, label %loop @@ -31,7 +31,7 @@ define void @infer.zext.0(i1* %c, i32 %start) { %idx.inc = add nuw i32 %idx, 1 %idx.inc.sext = zext i32 %idx.inc to i64 ; CHECK: %idx.inc.sext = zext i32 %idx.inc to i64 -; CHECK-NEXT: --> {(1 + (zext i32 %start to i64)),+,1}<nuw><%loop> +; CHECK-NEXT: --> {(1 + (zext i32 %start to i64))<nuw><nsw>,+,1}<nuw><%loop> %condition = icmp eq i32 %counter, 1 %counter.inc = add i32 %counter, 1 br i1 %condition, label %exit, label %loop @@ -51,7 +51,7 @@ define void @infer.sext.1(i32 %start, i1* %c) { %idx = phi i32 [ %start.real, %entry ], [ %idx.inc, %loop ] %idx.sext = sext i32 %idx to i64 ; CHECK: %idx.sext = sext i32 %idx to i64 -; CHECK-NEXT: --> {(2 + (sext i32 (4 * %start) to i64)),+,2}<nsw><%loop> +; CHECK-NEXT: --> {(2 + (sext i32 (4 * %start) to i64))<nsw>,+,2}<nsw><%loop> %idx.inc = add nsw i32 %idx, 2 %condition = load i1, i1* %c br i1 %condition, label %exit, label %loop @@ -71,7 +71,7 @@ define void @infer.sext.2(i1* %c, i8 %start) { %idx = phi i8 [ %start.inc, %entry ], [ %idx.inc, %loop ] %idx.sext = sext i8 %idx to i16 ; CHECK: %idx.sext = sext i8 %idx to i16 -; CHECK-NEXT: --> {(1 + (sext i8 %start to i16)),+,1}<nsw><%loop> +; CHECK-NEXT: --> {(1 + (sext i8 %start to i16))<nsw>,+,1}<nsw><%loop> %idx.inc = add nsw i8 %idx, 1 %condition = load volatile i1, i1* %c br i1 %condition, label %exit, label %loop @@ -91,7 +91,7 @@ define void @infer.zext.1(i1* %c, i8 %start) { %idx = phi i8 [ %start.inc, %entry ], [ %idx.inc, %loop ] %idx.zext = zext i8 %idx to i16 ; CHECK: %idx.zext = zext i8 %idx to i16 -; CHECK-NEXT: --> {(1 + (zext i8 %start to i16)),+,1}<nuw><%loop> +; CHECK-NEXT: --> {(1 + (zext i8 %start to i16))<nuw><nsw>,+,1}<nuw><%loop> %idx.inc = add nuw i8 %idx, 1 %condition = load volatile i1, i1* %c br i1 %condition, label %exit, label %loop diff --git a/test/Analysis/ScalarEvolution/min-max-exprs.ll b/test/Analysis/ScalarEvolution/min-max-exprs.ll index 892fc23fe6b2..e8c1e33e095f 100644 --- a/test/Analysis/ScalarEvolution/min-max-exprs.ll +++ b/test/Analysis/ScalarEvolution/min-max-exprs.ll @@ -33,7 +33,7 @@ bb2: ; preds = %bb1 %tmp9 = select i1 %tmp4, i64 %tmp5, i64 %tmp6 ; min(N, i+3) ; CHECK: select i1 %tmp4, i64 %tmp5, i64 %tmp6 -; CHECK-NEXT: --> (-1 + (-1 * ((-1 + (-1 * (sext i32 {3,+,1}<nw><%bb1> to i64))) smax (-1 + (-1 * (sext i32 %N to i64)))))) +; CHECK-NEXT: --> (-1 + (-1 * ((-1 + (-1 * (sext i32 {3,+,1}<nuw><%bb1> to i64))<nsw>)<nsw> smax (-1 + (-1 * (sext i32 %N to i64))<nsw>)<nsw>))<nsw>)<nsw> %tmp11 = getelementptr inbounds i32, i32* %A, i64 %tmp9 %tmp12 = load i32, i32* %tmp11, align 4 %tmp13 = shl nsw i32 %tmp12, 1 diff --git a/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll b/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll new file mode 100644 index 000000000000..c24d7173e4ee --- /dev/null +++ b/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll @@ -0,0 +1,122 @@ +; RUN: opt -S -analyze -scalar-evolution < %s | FileCheck %s + +!0 = !{i8 0, i8 127} + +define void @f0(i8* %len_addr) { +; CHECK-LABEL: Classifying expressions for: @f0 + entry: + %len = load i8, i8* %len_addr, !range !0 + %len_norange = load i8, i8* %len_addr +; CHECK: %len = load i8, i8* %len_addr, !range !0 +; CHECK-NEXT: --> %len U: [0,127) S: [0,127) +; CHECK: %len_norange = load i8, i8* %len_addr +; CHECK-NEXT: --> %len_norange U: full-set S: full-set + + %t0 = add i8 %len, 1 + %t1 = add i8 %len, 2 +; CHECK: %t0 = add i8 %len, 1 +; CHECK-NEXT: --> (1 + %len)<nuw><nsw> U: [1,-128) S: [1,-128) +; CHECK: %t1 = add i8 %len, 2 +; CHECK-NEXT: --> (2 + %len)<nuw> U: [2,-127) S: [2,-127) + + %t2 = sub i8 %len, 1 + %t3 = sub i8 %len, 2 +; CHECK: %t2 = sub i8 %len, 1 +; CHECK-NEXT: --> (-1 + %len)<nsw> U: [-1,126) S: [-1,126) +; CHECK: %t3 = sub i8 %len, 2 +; CHECK-NEXT: --> (-2 + %len)<nsw> U: [-2,125) S: [-2,125) + + %q0 = add i8 %len_norange, 1 + %q1 = add i8 %len_norange, 2 +; CHECK: %q0 = add i8 %len_norange, 1 +; CHECK-NEXT: --> (1 + %len_norange) U: full-set S: full-set +; CHECK: %q1 = add i8 %len_norange, 2 +; CHECK-NEXT: --> (2 + %len_norange) U: full-set S: full-set + + %q2 = sub i8 %len_norange, 1 + %q3 = sub i8 %len_norange, 2 +; CHECK: %q2 = sub i8 %len_norange, 1 +; CHECK-NEXT: --> (-1 + %len_norange) U: full-set S: full-set +; CHECK: %q3 = sub i8 %len_norange, 2 +; CHECK-NEXT: --> (-2 + %len_norange) U: full-set S: full-set + + ret void +} + +define void @f1(i8* %len_addr) { +; CHECK-LABEL: Classifying expressions for: @f1 + entry: + %len = load i8, i8* %len_addr, !range !0 + %len_norange = load i8, i8* %len_addr +; CHECK: %len = load i8, i8* %len_addr, !range !0 +; CHECK-NEXT: --> %len U: [0,127) S: [0,127) +; CHECK: %len_norange = load i8, i8* %len_addr +; CHECK-NEXT: --> %len_norange U: full-set S: full-set + + %t0 = add i8 %len, -1 + %t1 = add i8 %len, -2 +; CHECK: %t0 = add i8 %len, -1 +; CHECK-NEXT: --> (-1 + %len)<nsw> U: [-1,126) S: [-1,126) +; CHECK: %t1 = add i8 %len, -2 +; CHECK-NEXT: --> (-2 + %len)<nsw> U: [-2,125) S: [-2,125) + + %t0.sext = sext i8 %t0 to i16 + %t1.sext = sext i8 %t1 to i16 +; CHECK: %t0.sext = sext i8 %t0 to i16 +; CHECK-NEXT: --> (-1 + (zext i8 %len to i16))<nsw> U: [-1,126) S: [-1,126) +; CHECK: %t1.sext = sext i8 %t1 to i16 +; CHECK-NEXT: --> (-2 + (zext i8 %len to i16))<nsw> U: [-2,125) S: [-2,125) + + %q0 = add i8 %len_norange, 1 + %q1 = add i8 %len_norange, 2 +; CHECK: %q0 = add i8 %len_norange, 1 +; CHECK-NEXT: --> (1 + %len_norange) U: full-set S: full-set +; CHECK: %q1 = add i8 %len_norange, 2 +; CHECK-NEXT: --> (2 + %len_norange) U: full-set S: full-set + + %q0.sext = sext i8 %q0 to i16 + %q1.sext = sext i8 %q1 to i16 +; CHECK: %q0.sext = sext i8 %q0 to i16 +; CHECK-NEXT: --> (sext i8 (1 + %len_norange) to i16) U: [-128,128) S: [-128,128) +; CHECK: %q1.sext = sext i8 %q1 to i16 +; CHECK-NEXT: --> (sext i8 (2 + %len_norange) to i16) U: [-128,128) S: [-128,128) + + ret void +} + +define void @f2(i8* %len_addr) { +; CHECK-LABEL: Classifying expressions for: @f2 + entry: + %len = load i8, i8* %len_addr, !range !0 + %len_norange = load i8, i8* %len_addr +; CHECK: %len = load i8, i8* %len_addr, !range !0 +; CHECK-NEXT: --> %len U: [0,127) S: [0,127) +; CHECK: %len_norange = load i8, i8* %len_addr +; CHECK-NEXT: --> %len_norange U: full-set S: full-set + + %t0 = add i8 %len, 1 + %t1 = add i8 %len, 2 +; CHECK: %t0 = add i8 %len, 1 +; CHECK-NEXT: --> (1 + %len)<nuw><nsw> +; CHECK: %t1 = add i8 %len, 2 +; CHECK-NEXT: --> (2 + %len)<nuw> + + %t0.zext = zext i8 %t0 to i16 + %t1.zext = zext i8 %t1 to i16 +; CHECK: %t0.zext = zext i8 %t0 to i16 +; CHECK-NEXT: --> (1 + (zext i8 %len to i16))<nuw><nsw> U: [1,128) S: [1,128) +; CHECK: %t1.zext = zext i8 %t1 to i16 +; CHECK-NEXT: --> (2 + (zext i8 %len to i16))<nuw><nsw> U: [2,129) S: [2,129) + + %q0 = add i8 %len_norange, 1 + %q1 = add i8 %len_norange, 2 + %q0.zext = zext i8 %q0 to i16 + %q1.zext = zext i8 %q1 to i16 + +; CHECK: %q0.zext = zext i8 %q0 to i16 +; CHECK-NEXT: --> (zext i8 (1 + %len_norange) to i16) U: [0,256) S: [0,256) +; CHECK: %q1.zext = zext i8 %q1 to i16 +; CHECK-NEXT: --> (zext i8 (2 + %len_norange) to i16) U: [0,256) S: [0,256) + + ret void +} diff --git a/test/Analysis/ScalarEvolution/non-IV-phi.ll b/test/Analysis/ScalarEvolution/non-IV-phi.ll new file mode 100644 index 000000000000..f0d6c2f5d9d3 --- /dev/null +++ b/test/Analysis/ScalarEvolution/non-IV-phi.ll @@ -0,0 +1,59 @@ +; RUN: opt -scalar-evolution -analyze < %s | FileCheck %s + +define void @test1(i8 %t, i32 %len) { +; CHECK-LABEL: test1 +; CHECK: %sphi = phi i32 [ %ext, %entry ], [ %idx.inc.ext, %loop ] +; CHECK-NEXT: --> (zext i8 {%t,+,1}<%loop> to i32) + + entry: + %st = zext i8 %t to i16 + %ext = zext i8 %t to i32 + %ecmp = icmp ult i16 %st, 42 + br i1 %ecmp, label %loop, label %exit + + loop: + + %idx = phi i8 [ %t, %entry ], [ %idx.inc, %loop ] + %sphi = phi i32 [ %ext, %entry ], [%idx.inc.ext, %loop] + + %idx.inc = add i8 %idx, 1 + %idx.inc.ext = zext i8 %idx.inc to i32 + %idx.ext = zext i8 %idx to i32 + + %c = icmp ult i32 %idx.inc.ext, %len + br i1 %c, label %loop, label %exit + + exit: + ret void +} + +define void @test2(i8 %t, i32 %len) { +; CHECK-LABEL: test2 +; CHECK: %sphi = phi i32 [ %ext.mul, %entry ], [ %mul, %loop ] +; CHECK-NEXT: --> (4 * (zext i8 {%t,+,1}<%loop> to i32)) + + entry: + %st = zext i8 %t to i16 + %ext = zext i8 %t to i32 + %ext.mul = mul i32 %ext, 4 + + %ecmp = icmp ult i16 %st, 42 + br i1 %ecmp, label %loop, label %exit + + loop: + + %idx = phi i8 [ %t, %entry ], [ %idx.inc, %loop ] + %sphi = phi i32 [ %ext.mul, %entry ], [%mul, %loop] + + %idx.inc = add i8 %idx, 1 + %idx.inc.ext = zext i8 %idx.inc to i32 + %mul = mul i32 %idx.inc.ext, 4 + + %idx.ext = zext i8 %idx to i32 + + %c = icmp ult i32 %idx.inc.ext, %len + br i1 %c, label %loop, label %exit + + exit: + ret void +} diff --git a/test/Analysis/ScalarEvolution/pr24757.ll b/test/Analysis/ScalarEvolution/pr24757.ll new file mode 100644 index 000000000000..815adcde0e9d --- /dev/null +++ b/test/Analysis/ScalarEvolution/pr24757.ll @@ -0,0 +1,35 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +; CHECK: Loop %bb1: backedge-taken count is (zext i7 (trunc i8 %a.promoted to i7) to i8) + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.10.0" + +@a = global i8 -127, align 1 +@b = common global i32 0, align 4 + +declare void @use(i32) + +define i32 @main() { +bb: + %a.promoted = load i8, i8* @a + br label %bb1 + +bb1: ; preds = %bb1, %bb + %tmp = phi i8 [ %tmp2, %bb1 ], [ %a.promoted, %bb ] + %tmp2 = add i8 %tmp, -1 + %tmp3 = sext i8 %tmp to i32 + %tmp4 = xor i32 %tmp3, -1 + %tmp5 = sext i8 %tmp2 to i32 + %tmpf = sub nsw i32 %tmp4, %tmp5 + %tmp6 = trunc i32 %tmpf to i8 + %tmp7 = icmp eq i8 %tmp6, 0 + br i1 %tmp7, label %bb8, label %bb1 + +bb8: ; preds = %bb1 + store i8 %tmp2, i8* @a + store i32 %tmp4, i32* @b + %tmp9 = sext i8 %tmp2 to i32 + call void @use(i32 %tmp9) + ret i32 0 +} diff --git a/test/Analysis/ScalarEvolution/pr25369.ll b/test/Analysis/ScalarEvolution/pr25369.ll new file mode 100644 index 000000000000..10754867a368 --- /dev/null +++ b/test/Analysis/ScalarEvolution/pr25369.ll @@ -0,0 +1,78 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @hoge1() { +; CHECK-LABEL: Classifying expressions for: @hoge1 +bb: + br i1 undef, label %bb4, label %bb2 + +bb2: ; preds = %bb2, %bb + br i1 false, label %bb4, label %bb2 + +bb3: ; preds = %bb4 + %tmp = add i32 %tmp10, -1 + br label %bb13 + +bb4: ; preds = %bb4, %bb2, %bb + %tmp5 = phi i64 [ %tmp11, %bb4 ], [ 1, %bb2 ], [ 1, %bb ] + %tmp6 = phi i32 [ %tmp10, %bb4 ], [ 0, %bb2 ], [ 0, %bb ] + %tmp7 = load i32, i32* undef, align 4 + %tmp8 = add i32 %tmp7, %tmp6 + %tmp9 = add i32 undef, %tmp8 + %tmp10 = add i32 undef, %tmp9 + %tmp11 = add nsw i64 %tmp5, 3 + %tmp12 = icmp eq i64 %tmp11, 64 + br i1 %tmp12, label %bb3, label %bb4 + +; CHECK: Loop %bb4: backedge-taken count is 20 +; CHECK: Loop %bb4: max backedge-taken count is 20 + +bb13: ; preds = %bb13, %bb3 + %tmp14 = phi i64 [ 0, %bb3 ], [ %tmp15, %bb13 ] + %tmp15 = add nuw nsw i64 %tmp14, 1 + %tmp16 = trunc i64 %tmp15 to i32 + %tmp17 = icmp eq i32 %tmp16, %tmp + br i1 %tmp17, label %bb18, label %bb13 + +bb18: ; preds = %bb13 + ret void +} + +define void @hoge2() { +; CHECK-LABEL: Classifying expressions for: @hoge2 +bb: + br i1 undef, label %bb4, label %bb2 + +bb2: ; preds = %bb2, %bb + br i1 false, label %bb4, label %bb2 + +bb3: ; preds = %bb4 + %tmp = add i32 %tmp10, -1 + br label %bb13 + +bb4: ; preds = %bb4, %bb2, %bb + %tmp5 = phi i64 [ %tmp11, %bb4 ], [ 1, %bb2 ], [ 3, %bb ] + %tmp6 = phi i32 [ %tmp10, %bb4 ], [ 0, %bb2 ], [ 0, %bb ] + %tmp7 = load i32, i32* undef, align 4 + %tmp8 = add i32 %tmp7, %tmp6 + %tmp9 = add i32 undef, %tmp8 + %tmp10 = add i32 undef, %tmp9 + %tmp11 = add nsw i64 %tmp5, 3 + %tmp12 = icmp eq i64 %tmp11, 64 + br i1 %tmp12, label %bb3, label %bb4 + +; CHECK: Loop %bb4: Unpredictable backedge-taken count. +; CHECK: Loop %bb4: Unpredictable max backedge-taken count. + +bb13: ; preds = %bb13, %bb3 + %tmp14 = phi i64 [ 0, %bb3 ], [ %tmp15, %bb13 ] + %tmp15 = add nuw nsw i64 %tmp14, 1 + %tmp16 = trunc i64 %tmp15 to i32 + %tmp17 = icmp eq i32 %tmp16, %tmp + br i1 %tmp17, label %bb18, label %bb13 + +bb18: ; preds = %bb13 + ret void +} diff --git a/test/Analysis/ScalarEvolution/scev-aa.ll b/test/Analysis/ScalarEvolution/scev-aa.ll index e2123f44f167..47a84d57c3b3 100644 --- a/test/Analysis/ScalarEvolution/scev-aa.ll +++ b/test/Analysis/ScalarEvolution/scev-aa.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -scev-aa -aa-eval -print-all-alias-modref-info \ +; RUN: opt -disable-output < %s -disable-basicaa -scev-aa -aa-eval -print-all-alias-modref-info \ ; RUN: 2>&1 | FileCheck %s ; At the time of this writing, -basicaa misses the example of the form diff --git a/test/Analysis/ScalarEvolution/shift-op.ll b/test/Analysis/ScalarEvolution/shift-op.ll new file mode 100644 index 000000000000..fe832d567687 --- /dev/null +++ b/test/Analysis/ScalarEvolution/shift-op.ll @@ -0,0 +1,164 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +define void @test0(i32 %init) { +; CHECK-LABEL: Classifying expressions for: @test0 +; CHECK: Loop %loop: max backedge-taken count is 32 + entry: + br label %loop + + loop: + %iv = phi i32 [ %init, %entry ], [ %iv.shift, %loop ] + %iv.shift = lshr i32 %iv, 1 + %exit.cond = icmp eq i32 %iv, 0 + br i1 %exit.cond, label %leave, label %loop + + leave: + ret void +} + +define void @test1(i32 %init) { +; CHECK-LABEL: Classifying expressions for: @test1 +; CHECK: Loop %loop: max backedge-taken count is 32 + entry: + br label %loop + + loop: + %iv = phi i32 [ %init, %entry ], [ %iv.shift, %loop ] + %iv.shift = shl i32 %iv, 1 + %exit.cond = icmp eq i32 %iv, 0 + br i1 %exit.cond, label %leave, label %loop + + leave: + ret void +} + +define void @test2(i32 %init) { +; CHECK-LABEL: Determining loop execution counts for: @test2 +; CHECK: Loop %loop: Unpredictable max backedge-taken count. + +; Unpredictable because %iv could "stabilize" to either -1 or 0, +; depending on %init. + entry: + br label %loop + + loop: + %iv = phi i32 [ %init, %entry ], [ %iv.shift, %loop ] + %iv.shift = ashr i32 %iv, 1 + %exit.cond = icmp eq i32 %iv, 0 + br i1 %exit.cond, label %leave, label %loop + + leave: + ret void +} + +define void @test3(i32* %init.ptr) { +; CHECK-LABEL: Determining loop execution counts for: @test3 +; CHECK: Loop %loop: max backedge-taken count is 32 + entry: + %init = load i32, i32* %init.ptr, !range !0 + br label %loop + + loop: + %iv = phi i32 [ %init, %entry ], [ %iv.shift, %loop ] + %iv.shift = ashr i32 %iv, 1 + %exit.cond = icmp eq i32 %iv, 0 + br i1 %exit.cond, label %leave, label %loop + + leave: + ret void +} + +define void @test4(i32* %init.ptr) { +; CHECK-LABEL: Classifying expressions for: @test4 +; CHECK-LABEL: Loop %loop: max backedge-taken count is 32 + entry: + %init = load i32, i32* %init.ptr, !range !1 + br label %loop + + loop: + %iv = phi i32 [ %init, %entry ], [ %iv.shift, %loop ] + %iv.shift = ashr i32 %iv, 1 + %exit.cond = icmp eq i32 %iv, -1 + br i1 %exit.cond, label %leave, label %loop + + leave: + ret void +} + +define void @test5(i32* %init.ptr) { +; CHECK-LABEL: Determining loop execution counts for: @test5 +; CHECK: Loop %loop: Unpredictable max backedge-taken count. + +; %iv will "stabilize" to -1, so this is an infinite loop + entry: + %init = load i32, i32* %init.ptr, !range !1 + br label %loop + + loop: + %iv = phi i32 [ %init, %entry ], [ %iv.shift, %loop ] + %iv.shift = ashr i32 %iv, 1 + %exit.cond = icmp eq i32 %iv, 0 + br i1 %exit.cond, label %leave, label %loop + + leave: + ret void +} + +define void @test6(i32 %init, i32 %shift.amt) { +; CHECK-LABEL: Determining loop execution counts for: @test6 +; CHECK: Loop %loop: Unpredictable max backedge-taken count. + +; Potentially infinite loop, since %shift.amt could be 0 + entry: + br label %loop + + loop: + %iv = phi i32 [ %init, %entry ], [ %iv.shift, %loop ] + %iv.shift = lshr i32 %iv, %shift.amt + %exit.cond = icmp eq i32 %iv, 0 + br i1 %exit.cond, label %leave, label %loop + + leave: + ret void +} + +define void @test7(i32 %init) { +; CHECK-LABEL: Classifying expressions for: @test7 +; CHECK: Loop %loop: max backedge-taken count is 32 + + entry: + br label %loop + + loop: + %iv = phi i32 [ %init, %entry ], [ %iv.shift, %loop ] + %iv.shift = lshr i32 %iv, 1 + %exit.cond = icmp eq i32 %iv.shift, 0 + br i1 %exit.cond, label %leave, label %loop + + leave: + ret void +} + +define void @test8(i32 %init) { +; CHECK-LABEL: Classifying expressions for: @test8 +; CHECK: Loop %loop: Unpredictable max backedge-taken count. + +; In this test case, %iv.test stabilizes to 127, not -1, so the loop +; is infinite. + + entry: + br label %loop + + loop: + %iv = phi i32 [ %init, %entry ], [ %iv.shift, %loop ] + %iv.shift = ashr i32 %iv, 1 + %iv.test = lshr i32 %iv, 1 + %exit.cond = icmp eq i32 %iv.test, -1 + br i1 %exit.cond, label %leave, label %loop + + leave: + ret void +} + +!0 = !{i32 0, i32 50000} +!1 = !{i32 -5000, i32 -1} diff --git a/test/Analysis/ScalarEvolution/smax-br-phi-idioms.ll b/test/Analysis/ScalarEvolution/smax-br-phi-idioms.ll new file mode 100644 index 000000000000..500f3e16c8f5 --- /dev/null +++ b/test/Analysis/ScalarEvolution/smax-br-phi-idioms.ll @@ -0,0 +1,128 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +define i32 @f0(i32 %x, i32 %y) { +; CHECK-LABEL: Classifying expressions for: @f0 + entry: + %c = icmp sgt i32 %y, 0 + br i1 %c, label %add, label %merge + + add: + %sum = add i32 %x, %y + br label %merge + + merge: + %v = phi i32 [ %sum, %add ], [ %x, %entry ] +; CHECK: %v = phi i32 [ %sum, %add ], [ %x, %entry ] +; CHECK-NEXT: --> ((0 smax %y) + %x) U: full-set S: full-set + ret i32 %v +} + +define i32 @f1(i32 %x, i32 %y) { +; CHECK-LABEL: Classifying expressions for: @f1 + entry: + %c = icmp sge i32 %y, 0 + br i1 %c, label %add, label %merge + + add: + %sum = add i32 %x, %y + br label %merge + + merge: + %v = phi i32 [ %sum, %add ], [ %x, %entry ] +; CHECK: %v = phi i32 [ %sum, %add ], [ %x, %entry ] +; CHECK-NEXT: --> ((0 smax %y) + %x) U: full-set S: full-set + ret i32 %v +} + +define i32 @f2(i32 %x, i32 %y, i32* %ptr) { +; CHECK-LABEL: Classifying expressions for: @f2 + entry: + %c = icmp sge i32 %y, 0 + br i1 %c, label %add, label %merge + + add: + %lv = load i32, i32* %ptr + br label %merge + + merge: + %v = phi i32 [ %lv, %add ], [ %x, %entry ] +; CHECK: %v = phi i32 [ %lv, %add ], [ %x, %entry ] +; CHECK-NEXT: --> %v U: full-set S: full-set + ret i32 %v +} + +define i32 @f3(i32 %x, i32 %init, i32 %lim) { +; CHECK-LABEL: Classifying expressions for: @f3 + entry: + br label %loop + +loop: + %iv = phi i32 [ %init, %entry ], [ %iv.inc, %merge ] + %iv.inc = add i32 %iv, 1 + %c = icmp sge i32 %iv, 0 + br i1 %c, label %add, label %merge + + add: + %sum = add i32 %x, %iv + br label %merge + + merge: + %v = phi i32 [ %sum, %add ], [ %x, %loop ] +; CHECK: %v = phi i32 [ %sum, %add ], [ %x, %loop ] +; CHECK-NEXT: --> ((0 smax {%init,+,1}<%loop>) + %x) U: full-set S: full-set + %be.cond = icmp eq i32 %iv.inc, %lim + br i1 %be.cond, label %loop, label %leave + + leave: + ret i32 0 +} + +define i32 @f4(i32 %x, i32 %init, i32 %lim) { +; CHECK-LABEL: Classifying expressions for: @f4 + entry: + %c = icmp sge i32 %init, 0 + br i1 %c, label %add, label %merge + + add: + br label %loop + + loop: + %iv = phi i32 [ %init, %add ], [ %iv.inc, %loop ] + %iv.inc = add i32 %iv, 1 + %be.cond = icmp eq i32 %iv.inc, %lim + br i1 %be.cond, label %loop, label %add.cont + + add.cont: + %sum = add i32 %x, %iv + br label %merge + + merge: + %v = phi i32 [ %sum, %add.cont ], [ %x, %entry ] +; CHECK: %v = phi i32 [ %sum, %add.cont ], [ %x, %entry ] +; CHECK-NEXT: --> %v U: full-set S: full-set + ret i32 %v +} + +define i32 @f5(i32* %val) { +; CHECK-LABEL: Classifying expressions for: @f5 +entry: + br label %for.end + +for.condt: + br i1 true, label %for.cond.0, label %for.end + +for.end: + %inc = load i32, i32* %val + br i1 false, label %for.condt, label %for.cond.0 + +for.cond.0: + %init = phi i32 [ 0, %for.condt ], [ %inc, %for.end ] + +; CHECK: %init = phi i32 [ 0, %for.condt ], [ %inc, %for.end ] +; CHECK-NEXT: --> %init U: full-set S: full-set + +; Matching "through" %init will break LCSSA at the SCEV expression +; level. + + ret i32 %init +} diff --git a/test/Analysis/ScalarEvolution/trip-count.ll b/test/Analysis/ScalarEvolution/trip-count.ll index 1b75c88c753c..89750810d1b7 100644 --- a/test/Analysis/ScalarEvolution/trip-count.ll +++ b/test/Analysis/ScalarEvolution/trip-count.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -scalar-evolution -scalar-evolution-max-iterations=0 | FileCheck %s +; RUN: opt < %s -passes='print<scalar-evolution>' -disable-output 2>&1 | FileCheck %s ; PR1101 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" @@ -6,7 +7,7 @@ target triple = "x86_64-unknown-linux-gnu" @A = weak global [1000 x i32] zeroinitializer, align 32 -; CHECK: Printing analysis 'Scalar Evolution Analysis' for function 'test1': +; CHECK-LABEL: Determining loop execution counts for: @test1 ; CHECK: backedge-taken count is 10000 define void @test1(i32 %N) { @@ -32,7 +33,7 @@ return: ; preds = %bb5 } ; PR22795 -; CHECK: Printing analysis 'Scalar Evolution Analysis' for function 'test2': +; CHECK-LABEL: Classifying expressions for: @test2 ; CHECK: %iv = phi i32 [ -1, %entry ], [ %next.1, %for.inc.1 ] ; CHECK-NEXT: --> {-1,+,2}<%preheader> U: full-set S: full-set Exits: 13 diff --git a/test/Analysis/ScalarEvolution/zext-wrap.ll b/test/Analysis/ScalarEvolution/zext-wrap.ll index f56e4556c697..5bc149e2309a 100644 --- a/test/Analysis/ScalarEvolution/zext-wrap.ll +++ b/test/Analysis/ScalarEvolution/zext-wrap.ll @@ -10,7 +10,7 @@ bb.i: ; preds = %bb1.i, %bb.nph ; This cast shouldn't be folded into the addrec. ; CHECK: %tmp = zext i8 %l_95.0.i1 to i16 -; CHECK: --> (zext i8 {0,+,-1}<%bb.i> to i16){{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: 2 +; CHECK: --> (zext i8 {0,+,-1}<nw><%bb.i> to i16){{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: 2 %tmp = zext i8 %l_95.0.i1 to i16 diff --git a/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll b/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll index 6c9439afeeab..fe2fdd74b411 100644 --- a/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll +++ b/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll @@ -30,7 +30,7 @@ define void @test1_yes(i32* %p) nounwind { ret void } -; CHECK: define void @test1_no(i32* %p) #1 { +; CHECK: define void @test1_no(i32* %p) #3 { define void @test1_no(i32* %p) nounwind { call void @callee(i32* %p), !tbaa !2 ret void @@ -72,9 +72,11 @@ define i32 @test3_no(i8* %p) nounwind { declare void @callee(i32* %p) nounwind declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i32, i1) nounwind -; CHECK: attributes #0 = { nounwind readnone } -; CHECK: attributes #1 = { nounwind } +; CHECK: attributes #0 = { norecurse nounwind readnone } +; CHECK: attributes #1 = { norecurse nounwind } ; CHECK: attributes #2 = { nounwind readonly } +; CHECK: attributes #3 = { nounwind } +; CHECK: attributes #4 = { argmemonly nounwind } ; Root note. !0 = !{ } diff --git a/test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll b/test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll index 0c12cac27d3a..197ef7e5196f 100644 --- a/test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll +++ b/test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll @@ -7,22 +7,23 @@ target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32- ; CHECK: define <8 x i16> @test0(i8* %p, i8* %q, <8 x i16> %y) { ; CHECK-NEXT: entry: -; CHECK-NEXT: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) [[NUW:#[0-9]+]] -; CHECK-NEXT: call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) +; CHECK-NEXT: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) [[NUW:#[0-9]+]] +; CHECK-NEXT: call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16) ; CHECK-NEXT: %c = add <8 x i16> %a, %a define <8 x i16> @test0(i8* %p, i8* %q, <8 x i16> %y) { entry: - %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) nounwind, !tbaa !2 - call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16), !tbaa !1 - %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) nounwind, !tbaa !2 + %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) nounwind, !tbaa !2 + call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16), !tbaa !1 + %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) nounwind, !tbaa !2 %c = add <8 x i16> %a, %b ret <8 x i16> %c } -declare <8 x i16> @llvm.arm.neon.vld1.v8i16(i8*, i32) nounwind readonly -declare void @llvm.arm.neon.vst1.v8i16(i8*, <8 x i16>, i32) nounwind +declare <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8*, i32) nounwind readonly +declare void @llvm.arm.neon.vst1.p0i8.v8i16(i8*, <8 x i16>, i32) nounwind -; CHECK: attributes #0 = { nounwind readonly } +; CHECK: attributes #0 = { argmemonly nounwind readonly } +; CHECK: attributes #1 = { argmemonly nounwind } ; CHECK: attributes [[NUW]] = { nounwind } !0 = !{!"tbaa root", null} diff --git a/test/Analysis/TypeBasedAliasAnalysis/licm.ll b/test/Analysis/TypeBasedAliasAnalysis/licm.ll index fe07730577e6..d2aee58204df 100644 --- a/test/Analysis/TypeBasedAliasAnalysis/licm.ll +++ b/test/Analysis/TypeBasedAliasAnalysis/licm.ll @@ -5,7 +5,7 @@ ; CHECK: @foo ; CHECK: entry: -; CHECK-NEXT: %tmp3 = load double*, double** @P, !tbaa !0 +; CHECK-NEXT: %tmp3 = load double*, double** @P ; CHECK-NEXT: br label %for.body @P = common global double* null diff --git a/test/Analysis/TypeBasedAliasAnalysis/precedence.ll b/test/Analysis/TypeBasedAliasAnalysis/precedence.ll index b2931cac75c8..c7cd2e274dff 100644 --- a/test/Analysis/TypeBasedAliasAnalysis/precedence.ll +++ b/test/Analysis/TypeBasedAliasAnalysis/precedence.ll @@ -1,9 +1,9 @@ -; RUN: opt -basicaa -tbaa -gvn -instcombine -S < %s | FileCheck %s --check-prefix=TBAA -; RUN: opt -tbaa -basicaa -gvn -instcombine -S < %s | FileCheck %s --check-prefix=BASICAA +; RUN: opt -tbaa -disable-basicaa -gvn -instcombine -S < %s | FileCheck %s --check-prefix=TBAA +; RUN: opt -tbaa -gvn -instcombine -S < %s | FileCheck %s --check-prefix=BASICAA ; According to the TBAA metadata the load and store don't alias. However, -; according to the actual code, they do. The order of the alias analysis -; passes should determine which of these takes precedence. +; according to the actual code, they do. Disabling basicaa shows the raw TBAA +; results. target datalayout = "e-p:64:64:64" diff --git a/test/Analysis/ValueTracking/known-bits-from-range-md.ll b/test/Analysis/ValueTracking/known-bits-from-range-md.ll new file mode 100644 index 000000000000..e1de089b3501 --- /dev/null +++ b/test/Analysis/ValueTracking/known-bits-from-range-md.ll @@ -0,0 +1,34 @@ +; RUN: opt -S -instsimplify < %s | FileCheck %s + +define i1 @test0(i8* %ptr) { +; CHECK-LABEL: @test0( + entry: + %val = load i8, i8* %ptr, !range !{i8 -50, i8 0} + %and = and i8 %val, 128 + %is.eq = icmp eq i8 %and, 128 + ret i1 %is.eq +; CHECK: ret i1 true +} + +define i1 @test1(i8* %ptr) { +; CHECK-LABEL: @test1( + entry: + %val = load i8, i8* %ptr, !range !{i8 64, i8 128} + %and = and i8 %val, 64 + %is.eq = icmp eq i8 %and, 64 + ret i1 %is.eq +; CHECK: ret i1 true +} + +define i1 @test2(i8* %ptr) { +; CHECK-LABEL: @test2( + entry: +; CHECK: load +; CHECK: and +; CHECK: icmp eq +; CHECK: ret + %val = load i8, i8* %ptr, !range !{i8 64, i8 129} + %and = and i8 %val, 64 + %is.eq = icmp eq i8 %and, 64 + ret i1 %is.eq +} diff --git a/test/Analysis/ValueTracking/known-non-equal.ll b/test/Analysis/ValueTracking/known-non-equal.ll new file mode 100644 index 000000000000..d28b3f4f63a3 --- /dev/null +++ b/test/Analysis/ValueTracking/known-non-equal.ll @@ -0,0 +1,21 @@ +; RUN: opt -instsimplify < %s -S | FileCheck %s + +; CHECK: define i1 @test +define i1 @test(i8* %pq, i8 %B) { + %q = load i8, i8* %pq, !range !0 ; %q is known nonzero; no known bits + %A = add nsw i8 %B, %q + %cmp = icmp eq i8 %A, %B + ; CHECK: ret i1 false + ret i1 %cmp +} + +; CHECK: define i1 @test2 +define i1 @test2(i8 %a, i8 %b) { + %A = or i8 %a, 2 ; %A[1] = 1 + %B = and i8 %b, -3 ; %B[1] = 0 + %cmp = icmp eq i8 %A, %B ; %A[1] and %B[1] are contradictory. + ; CHECK: ret i1 false + ret i1 %cmp +} + +!0 = !{ i8 1, i8 5 } diff --git a/test/Analysis/ValueTracking/knownnonzero-shift.ll b/test/Analysis/ValueTracking/knownnonzero-shift.ll new file mode 100644 index 000000000000..e59d19cc2e26 --- /dev/null +++ b/test/Analysis/ValueTracking/knownnonzero-shift.ll @@ -0,0 +1,13 @@ +; RUN: opt -instsimplify -S < %s | FileCheck %s + +; CHECK-LABEL: @test +define i1 @test(i8 %p, i8* %pq) { + %q = load i8, i8* %pq, !range !0 ; %q is known nonzero; no known bits + %1 = shl i8 %p, %q ; because %q is nonzero, %1[0] is known to be zero. + %2 = and i8 %1, 1 + %x = icmp eq i8 %2, 0 + ; CHECK: ret i1 true + ret i1 %x +} + +!0 = !{ i8 1, i8 5 } diff --git a/test/Analysis/ValueTracking/knownzero-shift.ll b/test/Analysis/ValueTracking/knownzero-shift.ll new file mode 100644 index 000000000000..835d87a9d9c1 --- /dev/null +++ b/test/Analysis/ValueTracking/knownzero-shift.ll @@ -0,0 +1,14 @@ +; RUN: opt -instsimplify -S < %s | FileCheck %s + +; CHECK-LABEL: @test +define i1 @test(i8 %p, i8* %pq) { + %q = load i8, i8* %pq, !range !0 ; %q is known nonzero; no known bits + %1 = or i8 %p, 2 ; %1[1] = 1 + %2 = and i8 %1, 254 ; %2[0] = 0, %2[1] = 1 + %A = lshr i8 %2, 1 ; We should know that %A is nonzero. + %x = icmp eq i8 %A, 0 + ; CHECK: ret i1 false + ret i1 %x +} + +!0 = !{ i8 1, i8 5 } diff --git a/test/Analysis/ValueTracking/memory-dereferenceable.ll b/test/Analysis/ValueTracking/memory-dereferenceable.ll index f49f4f77f404..5b45172f695e 100644 --- a/test/Analysis/ValueTracking/memory-dereferenceable.ll +++ b/test/Analysis/ValueTracking/memory-dereferenceable.ll @@ -5,73 +5,156 @@ target datalayout = "e" +%TypeOpaque = type opaque + declare zeroext i1 @return_i1() +declare i32* @foo() @globalstr = global [6 x i8] c"hello\00" @globali32ptr = external global i32* %struct.A = type { [8 x i8], [5 x i8] } @globalstruct = external global %struct.A -define void @test(i32 addrspace(1)* dereferenceable(8) %dparam) gc "statepoint-example" { +@globalptr.align1 = external global i8, align 1 +@globalptr.align16 = external global i8, align 16 + +; CHECK-LABEL: 'test' +define void @test(i32 addrspace(1)* dereferenceable(8) %dparam, + i8 addrspace(1)* dereferenceable(32) align 1 %dparam.align1, + i8 addrspace(1)* dereferenceable(32) align 16 %dparam.align16) + gc "statepoint-example" { ; CHECK: The following are dereferenceable: -; CHECK: %globalptr -; CHECK: %alloca -; CHECK: %dparam -; CHECK: %relocate -; CHECK-NOT: %nparam -; CHECK-NOT: %nd_load -; CHECK: %d4_load -; CHECK-NOT: %d2_load -; CHECK-NOT: %d_or_null_load -; CHECK: %d_or_null_non_null_load -; CHECK: %within_allocation -; CHECK-NOT: %outside_allocation entry: +; CHECK: %globalptr{{.*}}(aligned) %globalptr = getelementptr inbounds [6 x i8], [6 x i8]* @globalstr, i32 0, i32 0 %load1 = load i8, i8* %globalptr + +; CHECK: %alloca{{.*}}(aligned) %alloca = alloca i1 %load2 = load i1, i1* %alloca + +; CHECK: %dparam{{.*}}(aligned) %load3 = load i32, i32 addrspace(1)* %dparam - %tok = tail call i32 (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam) - %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 7, i32 7) + +; CHECK: %relocate{{.*}}(aligned) + %tok = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam) + %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 7, i32 7) %load4 = load i32, i32 addrspace(1)* %relocate + +; CHECK-NOT: %nparam %nparam = getelementptr i32, i32 addrspace(1)* %dparam, i32 5 %load5 = load i32, i32 addrspace(1)* %nparam ; Load from a non-dereferenceable load +; CHECK-NOT: %nd_load %nd_load = load i32*, i32** @globali32ptr %load6 = load i32, i32* %nd_load ; Load from a dereferenceable load +; CHECK: %d4_load{{.*}}(aligned) %d4_load = load i32*, i32** @globali32ptr, !dereferenceable !0 %load7 = load i32, i32* %d4_load ; Load from an offset not covered by the dereferenceable portion +; CHECK-NOT: %d2_load %d2_load = load i32*, i32** @globali32ptr, !dereferenceable !1 %load8 = load i32, i32* %d2_load ; Load from a potentially null pointer with dereferenceable_or_null +; CHECK-NOT: %d_or_null_load %d_or_null_load = load i32*, i32** @globali32ptr, !dereferenceable_or_null !0 %load9 = load i32, i32* %d_or_null_load ; Load from a non-null pointer with dereferenceable_or_null +; CHECK: %d_or_null_non_null_load{{.*}}(aligned) %d_or_null_non_null_load = load i32*, i32** @globali32ptr, !nonnull !2, !dereferenceable_or_null !0 %load10 = load i32, i32* %d_or_null_non_null_load ; It's OK to overrun static array size as long as we stay within underlying object size +; CHECK: %within_allocation{{.*}}(aligned) %within_allocation = getelementptr inbounds %struct.A, %struct.A* @globalstruct, i64 0, i32 0, i64 10 %load11 = load i8, i8* %within_allocation ; GEP is outside the underlying object size +; CHECK-NOT: %outside_allocation %outside_allocation = getelementptr inbounds %struct.A, %struct.A* @globalstruct, i64 0, i32 1, i64 10 %load12 = load i8, i8* %outside_allocation + ; Loads from aligned globals +; CHECK: @globalptr.align1{{.*}}(unaligned) +; CHECK: @globalptr.align16{{.*}}(aligned) + %load13 = load i8, i8* @globalptr.align1, align 16 + %load14 = load i8, i8* @globalptr.align16, align 16 + + ; Loads from aligned arguments +; CHECK: %dparam.align1{{.*}}(unaligned) +; CHECK: %dparam.align16{{.*}}(aligned) + %load15 = load i8, i8 addrspace(1)* %dparam.align1, align 16 + %load16 = load i8, i8 addrspace(1)* %dparam.align16, align 16 + + ; Loads from aligned allocas +; CHECK: %alloca.align1{{.*}}(unaligned) +; CHECK: %alloca.align16{{.*}}(aligned) + %alloca.align1 = alloca i1, align 1 + %alloca.align16 = alloca i1, align 16 + %load17 = load i1, i1* %alloca.align1, align 16 + %load18 = load i1, i1* %alloca.align16, align 16 + + ; Loads from GEPs +; CHECK: %gep.align1.offset1{{.*}}(unaligned) +; CHECK: %gep.align16.offset1{{.*}}(unaligned) +; CHECK: %gep.align1.offset16{{.*}}(unaligned) +; CHECK: %gep.align16.offset16{{.*}}(aligned) + %gep.align1.offset1 = getelementptr inbounds i8, i8 addrspace(1)* %dparam.align1, i32 1 + %gep.align16.offset1 = getelementptr inbounds i8, i8 addrspace(1)* %dparam.align16, i32 1 + %gep.align1.offset16 = getelementptr inbounds i8, i8 addrspace(1)* %dparam.align1, i32 16 + %gep.align16.offset16 = getelementptr inbounds i8, i8 addrspace(1)* %dparam.align16, i32 16 + %load19 = load i8, i8 addrspace(1)* %gep.align1.offset1, align 16 + %load20 = load i8, i8 addrspace(1)* %gep.align16.offset1, align 16 + %load21 = load i8, i8 addrspace(1)* %gep.align1.offset16, align 16 + %load22 = load i8, i8 addrspace(1)* %gep.align16.offset16, align 16 + +; CHECK-NOT: %no_deref_return +; CHECK: %deref_return{{.*}}(unaligned) +; CHECK: %deref_and_aligned_return{{.*}}(aligned) + %no_deref_return = call i32* @foo() + %deref_return = call dereferenceable(32) i32* @foo() + %deref_and_aligned_return = call dereferenceable(32) align 16 i32* @foo() + %load23 = load i32, i32* %no_deref_return + %load24 = load i32, i32* %deref_return, align 16 + %load25 = load i32, i32* %deref_and_aligned_return, align 16 + + ; Load from a dereferenceable and aligned load +; CHECK: %d4_unaligned_load{{.*}}(unaligned) +; CHECK: %d4_aligned_load{{.*}}(aligned) + %d4_unaligned_load = load i32*, i32** @globali32ptr, !dereferenceable !0 + %d4_aligned_load = load i32*, i32** @globali32ptr, !dereferenceable !0, !align !{i64 16} + %load26 = load i32, i32* %d4_unaligned_load, align 16 + %load27 = load i32, i32* %d4_aligned_load, align 16 + ret void } -declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...) -declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32) +; Just check that we don't crash. +; CHECK-LABEL: 'opaque_type_crasher' +define void @opaque_type_crasher(%TypeOpaque* dereferenceable(16) %a) { +entry: + %bc = bitcast %TypeOpaque* %a to i8* + %ptr8 = getelementptr inbounds i8, i8* %bc, i32 8 + %ptr32 = bitcast i8* %ptr8 to i32* + br i1 undef, label %if.then, label %if.end + +if.then: + %res = load i32, i32* %ptr32, align 4 + br label %if.end + +if.end: + ret void +} + +declare token @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...) +declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) !0 = !{i64 4} !1 = !{i64 2} diff --git a/test/Analysis/ValueTracking/monotonic-phi.ll b/test/Analysis/ValueTracking/monotonic-phi.ll new file mode 100644 index 000000000000..3204bda49f0b --- /dev/null +++ b/test/Analysis/ValueTracking/monotonic-phi.ll @@ -0,0 +1,49 @@ +; RUN: opt -instsimplify -S < %s | FileCheck %s + +; CHECK-LABEL: @test1 +define i1 @test1(i8 %p, i8* %pq, i8 %n, i8 %r) { +entry: + br label %loop +loop: + %A = phi i8 [ 1, %entry ], [ %next, %loop ] + %next = add nsw i8 %A, 1 + %cmp1 = icmp eq i8 %A, %n + br i1 %cmp1, label %exit, label %loop +exit: + %add = or i8 %A, %r + %cmp = icmp eq i8 %add, 0 + ; CHECK: ret i1 false + ret i1 %cmp +} + +; CHECK-LABEL: @test2 +define i1 @test2(i8 %p, i8* %pq, i8 %n, i8 %r) { +entry: + br label %loop +loop: + %A = phi i8 [ 1, %entry ], [ %next, %loop ] + %next = add i8 %A, 1 + %cmp1 = icmp eq i8 %A, %n + br i1 %cmp1, label %exit, label %loop +exit: + %add = or i8 %A, %r + %cmp = icmp eq i8 %add, 0 + ; CHECK-NOT: ret i1 false + ret i1 %cmp +} + +; CHECK-LABEL: @test3 +define i1 @test3(i8 %p, i8* %pq, i8 %n, i8 %r) { +entry: + br label %loop +loop: + %A = phi i8 [ 1, %entry ], [ %next, %loop ] + %next = add nuw i8 %A, 1 + %cmp1 = icmp eq i8 %A, %n + br i1 %cmp1, label %exit, label %loop +exit: + %add = or i8 %A, %r + %cmp = icmp eq i8 %add, 0 + ; CHECK: ret i1 false + ret i1 %cmp +} diff --git a/test/Analysis/ValueTracking/pr24866.ll b/test/Analysis/ValueTracking/pr24866.ll new file mode 100644 index 000000000000..b146b4ac0564 --- /dev/null +++ b/test/Analysis/ValueTracking/pr24866.ll @@ -0,0 +1,44 @@ +; RUN: opt -S %s -value-tracking-dom-conditions -licm -load-combine | FileCheck %s +; In pr24866.ll, we saw a crash when accessing a nullptr returned when +; asking for a dominator tree Node. This reproducer is really fragile, +; but it's currently the best we have. + +%struct.c_derived_tbl.2.5.8.11.14.17.23.38.59.80.92.98.104.107.155.183 = type { [256 x i32], [256 x i8] } + + +; Function Attrs: nounwind uwtable +define void @encode_one_blockX2(%struct.c_derived_tbl.2.5.8.11.14.17.23.38.59.80.92.98.104.107.155.183* nocapture readonly %actbl) #0 { +; CHECK-LABEL: @encode_one_blockX2 +entry: + br i1 false, label %L_KLOOP_01, label %L_KLOOP.preheader + +L_KLOOP_01: ; preds = %while.end, %entry + br label %L_KLOOP.preheader + +L_KLOOP_08: ; preds = %while.end + br label %L_KLOOP.preheader + +L_KLOOP.preheader: ; preds = %L_KLOOP_08, %L_KLOOP_01, %entry + %r.2.ph = phi i32 [ undef, %L_KLOOP_08 ], [ 0, %entry ], [ undef, %L_KLOOP_01 ] + br label %L_KLOOP + +L_KLOOP: ; preds = %while.end, %L_KLOOP.preheader + %r.2 = phi i32 [ 0, %while.end ], [ %r.2.ph, %L_KLOOP.preheader ] + br i1 true, label %while.body, label %while.end + +while.body: ; preds = %while.body, %L_KLOOP + br label %while.body + +while.end: ; preds = %L_KLOOP + %shl105 = shl i32 %r.2, 4 + %add106 = add nsw i32 %shl105, undef + %idxprom107 = sext i32 %add106 to i64 + %arrayidx108 = getelementptr inbounds %struct.c_derived_tbl.2.5.8.11.14.17.23.38.59.80.92.98.104.107.155.183, %struct.c_derived_tbl.2.5.8.11.14.17.23.38.59.80.92.98.104.107.155.183* %actbl, i64 0, i32 0, i64 %idxprom107 + %0 = load i32, i32* %arrayidx108, align 4 + %arrayidx110 = getelementptr inbounds %struct.c_derived_tbl.2.5.8.11.14.17.23.38.59.80.92.98.104.107.155.183, %struct.c_derived_tbl.2.5.8.11.14.17.23.38.59.80.92.98.104.107.155.183* %actbl, i64 0, i32 1, i64 %idxprom107 + %1 = load i8, i8* %arrayidx110, align 1 + indirectbr i8* undef, [label %L_KLOOP_DONE, label %L_KLOOP_01, label %L_KLOOP_08, label %L_KLOOP] + +L_KLOOP_DONE: ; preds = %while.end + ret void +} |
