diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 |
| commit | 01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch) | |
| tree | 4def12e759965de927d963ac65840d663ef9d1ea /test/Analysis | |
| parent | f0f4822ed4b66e3579e92a89f368f8fb860e218e (diff) | |
Notes
Diffstat (limited to 'test/Analysis')
188 files changed, 6946 insertions, 664 deletions
diff --git a/test/Analysis/BasicAA/cs-cs.ll b/test/Analysis/BasicAA/cs-cs.ll index dc298f1668bed..3bc4d72eab355 100644 --- a/test/Analysis/BasicAA/cs-cs.ll +++ b/test/Analysis/BasicAA/cs-cs.ll @@ -9,6 +9,7 @@ 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 declare void @a_readonly_func(i8 *) noinline nounwind readonly +declare void @a_writeonly_func(i8 *) noinline nounwind writeonly define <8 x i16> @test1(i8* %p, <8 x i16> %y) { entry: @@ -22,18 +23,18 @@ entry: ; 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.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: Just Ref: Ptr: i8* %p <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 +; CHECK: NoModRef: Ptr: i8* %q <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 ; 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) +; CHECK: Just Ref: Ptr: i8* %p <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 +; CHECK: NoModRef: Ptr: i8* %q <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 +; CHECK: NoModRef: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 <-> 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) #5 <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 +; 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) #5 +; 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) #5 +; CHECK: NoModRef: %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 +; CHECK: NoModRef: %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 <-> 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,9 +234,23 @@ 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 readonly argmemonly } -attributes #1 = { nounwind argmemonly } +define void @test7(i8* %P) nounwind ssp { + call void @a_writeonly_func(i8* %P) + call void @a_readonly_func(i8* %P) + ret void + +; CHECK-LABEL: Function: test7: + +; CHECK: Just Mod: Ptr: i8* %P <-> call void @a_writeonly_func(i8* %P) +; CHECK: Just Ref: Ptr: i8* %P <-> call void @a_readonly_func(i8* %P) +; CHECK: Just Mod: call void @a_writeonly_func(i8* %P) <-> call void @a_readonly_func(i8* %P) +; CHECK: Just Ref: call void @a_readonly_func(i8* %P) <-> call void @a_writeonly_func(i8* %P) +} + +attributes #0 = { argmemonly nounwind readonly } +attributes #1 = { argmemonly nounwind } attributes #2 = { noinline nounwind readonly } -attributes #3 = { nounwind ssp } -attributes #4 = { nounwind } +attributes #3 = { noinline nounwind writeonly } +attributes #4 = { nounwind ssp } +attributes #5 = { nounwind } diff --git a/test/Analysis/BasicAA/guards.ll b/test/Analysis/BasicAA/guards.ll new file mode 100644 index 0000000000000..66cfb156b7d91 --- /dev/null +++ b/test/Analysis/BasicAA/guards.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +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" + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) #0 +declare void @llvm.experimental.guard(i1, ...) +declare void @unknown_but_readonly() readonly + +define void @test1(i8* %P, i8* %Q) { + tail call void(i1,...) @llvm.experimental.guard(i1 true) [ "deopt"() ] + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false) + ret void + +; CHECK-LABEL: Function: test1: + +; CHECK: Just Ref: Ptr: i8* %P <-> tail call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] +; CHECK: Just Ref: Ptr: i8* %Q <-> tail call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] +; CHECK: Both ModRef: Ptr: i8* %P <-> tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false) +; CHECK: Both ModRef: Ptr: i8* %Q <-> tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false) +; CHECK: Just Ref: tail call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] <-> tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false) +; CHECK: Just Mod: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i32 1, i1 false) <-> tail call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] +} + +define void @test2() { + tail call void(i1,...) @llvm.experimental.guard(i1 true) [ "deopt"() ] + tail call void @unknown_but_readonly() + ret void +; CHECK-LABEL: Function: test2: +; CHECK: NoModRef: tail call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] <-> tail call void @unknown_but_readonly() +; CHECK: NoModRef: tail call void @unknown_but_readonly() <-> tail call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] +} diff --git a/test/Analysis/BasicAA/negoffset.ll b/test/Analysis/BasicAA/negoffset.ll new file mode 100644 index 0000000000000..e8550948dc1e6 --- /dev/null +++ b/test/Analysis/BasicAA/negoffset.ll @@ -0,0 +1,98 @@ +; 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-f64:32:64-f80:32-n8:16:32-S128" +target triple = "i386-unknown-linux-gnu" + +declare i32* @random.i32(i32* %ptr) + +; CHECK-LABEL: Function: arr: +; CHECK-DAG: MayAlias: i32* %alloca, i32* %p0 +; CHECK-DAG: NoAlias: i32* %alloca, i32* %p1 +define void @arr() { + %alloca = alloca i32, i32 4 + %random = call i32* @random.i32(i32* %alloca) + %p0 = getelementptr inbounds i32, i32* %random, i32 0 + %p1 = getelementptr inbounds i32, i32* %random, i32 1 + ret void +} + +; CHECK-LABEL: Function: arg: +; CHECK-DAG: MayAlias: i32* %arg, i32* %p0 +; CHECK-DAG: MayAlias: i32* %arg, i32* %p1 +define void @arg(i32* %arg) { + %random = call i32* @random.i32(i32* %arg) + %p0 = getelementptr inbounds i32, i32* %random, i32 0 + %p1 = getelementptr inbounds i32, i32* %random, i32 1 + ret void +} + +@gv = global i32 1 +; CHECK-LABEL: Function: global: +; CHECK-DAG: MayAlias: i32* %p0, i32* @gv +; CHECK-DAG: NoAlias: i32* %p1, i32* @gv +define void @global() { + %random = call i32* @random.i32(i32* @gv) + %p0 = getelementptr inbounds i32, i32* %random, i32 0 + %p1 = getelementptr inbounds i32, i32* %random, i32 1 + ret void +} + +; CHECK-LABEL: Function: struct: +; CHECK-DAG: MayAlias: i32* %f0, i32* %p0 +; CHECK-DAG: MayAlias: i32* %f1, i32* %p0 +; CHECK-DAG: NoAlias: i32* %f0, i32* %p1 +; CHECK-DAG: MayAlias: i32* %f1, i32* %p1 +%struct = type { i32, i32, i32 } +define void @struct() { + %alloca = alloca %struct + %alloca.i32 = bitcast %struct* %alloca to i32* + %random = call i32* @random.i32(i32* %alloca.i32) + %f0 = getelementptr inbounds %struct, %struct* %alloca, i32 0, i32 0 + %f1 = getelementptr inbounds %struct, %struct* %alloca, i32 0, i32 1 + %p0 = getelementptr inbounds i32, i32* %random, i32 0 + %p1 = getelementptr inbounds i32, i32* %random, i32 1 + ret void +} + +; CHECK-LABEL: Function: complex1: +; CHECK-DAG: MayAlias: i32* %a2.0, i32* %r2.0 +; CHECK-DAG: NoAlias: i32* %a2.0, i32* %r2.1 +; CHECK-DAG: MayAlias: i32* %a2.0, i32* %r2.i +; CHECK-DAG: MayAlias: i32* %a2.0, i32* %r2.1i +; CHECK-DAG: NoAlias: i32* %a1, i32* %r2.0 +; CHECK-DAG: NoAlias: i32* %a1, i32* %r2.1 +; CHECK-DAG: NoAlias: i32* %a1, i32* %r2.i +; CHECK-DAG: NoAlias: i32* %a1, i32* %r2.1i +%complex = type { i32, i32, [4 x i32] } +define void @complex1(i32 %i) { + %alloca = alloca %complex + %alloca.i32 = bitcast %complex* %alloca to i32* + %r.i32 = call i32* @random.i32(i32* %alloca.i32) + %random = bitcast i32* %r.i32 to %complex* + %a1 = getelementptr inbounds %complex, %complex* %alloca, i32 0, i32 1 + %a2.0 = getelementptr inbounds %complex, %complex* %alloca, i32 0, i32 2, i32 0 + %r2.0 = getelementptr inbounds %complex, %complex* %random, i32 0, i32 2, i32 0 + %r2.1 = getelementptr inbounds %complex, %complex* %random, i32 0, i32 2, i32 1 + %r2.i = getelementptr inbounds %complex, %complex* %random, i32 0, i32 2, i32 %i + %r2.1i = getelementptr inbounds i32, i32* %r2.1, i32 %i + ret void +} + +; CHECK-LABEL: Function: complex2: +; CHECK-DAG: NoAlias: i32* %alloca, i32* %p120 +; CHECK-DAG: NoAlias: i32* %alloca, i32* %pi20 +; CHECK-DAG: NoAlias: i32* %alloca, i32* %pij1 +; CHECK-DAG: MayAlias: i32* %a3, i32* %pij1 +%inner = type { i32, i32 } +%outer = type { i32, i32, [10 x %inner] } +declare %outer* @rand_outer(i32* %p) +define void @complex2(i32 %i, i32 %j) { + %alloca = alloca i32, i32 128 + %a3 = getelementptr inbounds i32, i32* %alloca, i32 3 + %random = call %outer* @rand_outer(i32* %alloca) + %p120 = getelementptr inbounds %outer, %outer* %random, i32 1, i32 2, i32 2, i32 0 + %pi20 = getelementptr inbounds %outer, %outer* %random, i32 %i, i32 2, i32 2, i32 0 + %pij1 = getelementptr inbounds %outer, %outer* %random, i32 %i, i32 2, i32 %j, i32 1 + ret void +} + diff --git a/test/Analysis/BasicAA/noalias-wraparound-bug.ll b/test/Analysis/BasicAA/noalias-wraparound-bug.ll new file mode 100644 index 0000000000000..a75322ed3e9d4 --- /dev/null +++ b/test/Analysis/BasicAA/noalias-wraparound-bug.ll @@ -0,0 +1,24 @@ +; RUN: opt -S -basicaa -gvn < %s | FileCheck %s + +target datalayout = "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128" +target triple = "i386-apple-macosx10.6.0" + +; We incorrectly returned noalias in the example below for "tmp5" and +; "tmp12" returning i32 32, since basicaa converted the offsets to 64b +; and missed the wrap-around + +define i32 @foo(i8* %buffer) { +entry: + %tmp2 = getelementptr i8, i8* %buffer, i32 -2071408432 + %tmp3 = bitcast i8* %tmp2 to i32* + %tmp4 = getelementptr i8, i8* %buffer, i32 128 + %tmp5 = bitcast i8* %tmp4 to i32* + store i32 32, i32* %tmp5, align 4 + %tmp12 = getelementptr i32, i32* %tmp3, i32 -1629631508 + store i32 28, i32* %tmp12, align 4 + %tmp13 = getelementptr i8, i8* %buffer, i32 128 + %tmp14 = bitcast i8* %tmp13 to i32* + %tmp2083 = load i32, i32* %tmp14, align 4 +; CHECK: ret i32 28 + ret i32 %tmp2083 +} diff --git a/test/Analysis/BasicAA/phi-aa.ll b/test/Analysis/BasicAA/phi-aa.ll index 3944e9e435666..e410520bc0fce 100644 --- a/test/Analysis/BasicAA/phi-aa.ll +++ b/test/Analysis/BasicAA/phi-aa.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=basic-aa -passes=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" diff --git a/test/Analysis/BasicAA/returned.ll b/test/Analysis/BasicAA/returned.ll new file mode 100644 index 0000000000000..c6ef6806140df --- /dev/null +++ b/test/Analysis/BasicAA/returned.ll @@ -0,0 +1,45 @@ +; 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" + +%struct = type { i32, i32, i32 } + +; CHECK-LABEL: test_simple + +; CHECK-DAG: MustAlias: %struct* %st, %struct* %sta + +; CHECK-DAG: PartialAlias: %struct* %st, i32* %x +; CHECK-DAG: PartialAlias: %struct* %st, i32* %y +; CHECK-DAG: PartialAlias: %struct* %st, i32* %z + +; CHECK-DAG: NoAlias: i32* %x, i32* %y +; CHECK-DAG: NoAlias: i32* %x, i32* %z +; CHECK-DAG: NoAlias: i32* %y, i32* %z + +; CHECK-DAG: PartialAlias: %struct* %st, %struct* %y_12 +; CHECK-DAG: PartialAlias: %struct* %y_12, i32* %x +; CHECK-DAG: PartialAlias: i32* %x, i80* %y_10 + +; CHECK-DAG: PartialAlias: %struct* %st, i64* %y_8 +; CHECK-DAG: PartialAlias: i32* %z, i64* %y_8 +; CHECK-DAG: NoAlias: i32* %x, i64* %y_8 + +; CHECK-DAG: MustAlias: %struct* %y_12, i32* %y +; CHECK-DAG: MustAlias: i32* %y, i64* %y_8 +; CHECK-DAG: MustAlias: i32* %y, i80* %y_10 + +define void @test_simple(%struct* %st, i64 %i, i64 %j, i64 %k) { + %x = getelementptr %struct, %struct* %st, i64 %i, i32 0 + %y = getelementptr %struct, %struct* %st, i64 %j, i32 1 + %sta = call %struct* @func2(%struct* %st) + %z = getelementptr %struct, %struct* %sta, i64 %k, i32 2 + %y_12 = bitcast i32* %y to %struct* + %y_10 = bitcast i32* %y to i80* + %ya = call i32* @func1(i32* %y) + %y_8 = bitcast i32* %ya to i64* + ret void +} + +declare i32* @func1(i32* returned) nounwind +declare %struct* @func2(%struct* returned) nounwind + diff --git a/test/Analysis/BasicAA/struct-geps.ll b/test/Analysis/BasicAA/struct-geps.ll index d63c71a3278b9..2d85e1dd0173d 100644 --- a/test/Analysis/BasicAA/struct-geps.ll +++ b/test/Analysis/BasicAA/struct-geps.ll @@ -162,3 +162,12 @@ define void @test_struct_in_array(%struct2* %st, i64 %i, i64 %j, i64 %k) { %y = getelementptr %struct2, %struct2* %st, i32 0, i32 0, i32 1, i32 1 ret void } + +; PR27418 - Treat GEP indices with the same value but different types the same +; CHECK-LABEL: test_different_index_types +; CHECK: MustAlias: i16* %tmp1, i16* %tmp2 +define void @test_different_index_types([2 x i16]* %arr) { + %tmp1 = getelementptr [2 x i16], [2 x i16]* %arr, i16 0, i32 1 + %tmp2 = getelementptr [2 x i16], [2 x i16]* %arr, i16 0, i16 1 + ret void +} diff --git a/test/Analysis/BlockFrequencyInfo/bad_input.ll b/test/Analysis/BlockFrequencyInfo/bad_input.ll index 20b87e6dfcb40..39009a5ba838f 100644 --- a/test/Analysis/BlockFrequencyInfo/bad_input.ll +++ b/test/Analysis/BlockFrequencyInfo/bad_input.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -block-freq | FileCheck %s +; RUN: opt < %s -passes='print<block-freq>' -disable-output 2>&1 | FileCheck %s declare void @g(i32 %x) diff --git a/test/Analysis/BlockFrequencyInfo/basic.ll b/test/Analysis/BlockFrequencyInfo/basic.ll index 8e81cc2ea31cc..a957adc65027e 100644 --- a/test/Analysis/BlockFrequencyInfo/basic.ll +++ b/test/Analysis/BlockFrequencyInfo/basic.ll @@ -1,4 +1,6 @@ ; RUN: opt < %s -analyze -block-freq | FileCheck %s +; RUN: opt < %s -analyze -lazy-block-freq | FileCheck %s +; RUN: opt < %s -passes='print<block-freq>' -disable-output 2>&1 | FileCheck %s define i32 @test1(i32 %i, i32* %a) { ; CHECK-LABEL: Printing analysis {{.*}} for function 'test1': diff --git a/test/Analysis/BlockFrequencyInfo/double_backedge.ll b/test/Analysis/BlockFrequencyInfo/double_backedge.ll index 597bf8329b263..4431c3a68219e 100644 --- a/test/Analysis/BlockFrequencyInfo/double_backedge.ll +++ b/test/Analysis/BlockFrequencyInfo/double_backedge.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -block-freq | FileCheck %s +; RUN: opt < %s -passes='print<block-freq>' -disable-output 2>&1 | FileCheck %s define void @double_backedge(i1 %x) { ; CHECK-LABEL: Printing analysis {{.*}} for function 'double_backedge': diff --git a/test/Analysis/BlockFrequencyInfo/double_exit.ll b/test/Analysis/BlockFrequencyInfo/double_exit.ll index 3063ba7017310..5e9dded162c41 100644 --- a/test/Analysis/BlockFrequencyInfo/double_exit.ll +++ b/test/Analysis/BlockFrequencyInfo/double_exit.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -block-freq | FileCheck %s +; RUN: opt < %s -passes='print<block-freq>' -disable-output 2>&1 | FileCheck %s ; CHECK-LABEL: Printing analysis {{.*}} for function 'double_exit': ; CHECK-NEXT: block-frequency-info: double_exit diff --git a/test/Analysis/BlockFrequencyInfo/extremely-likely-loop-successor.ll b/test/Analysis/BlockFrequencyInfo/extremely-likely-loop-successor.ll index e55deaff428df..b9623683fe5a8 100644 --- a/test/Analysis/BlockFrequencyInfo/extremely-likely-loop-successor.ll +++ b/test/Analysis/BlockFrequencyInfo/extremely-likely-loop-successor.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -block-freq | FileCheck %s +; RUN: opt < %s -passes='print<block-freq>' -disable-output 2>&1 | FileCheck %s ; PR21622: Check for a crasher when the sum of exits to the same successor of a ; loop overflows. diff --git a/test/Analysis/BlockFrequencyInfo/irreducible.ll b/test/Analysis/BlockFrequencyInfo/irreducible.ll index c1b1c2a7a23c1..83b0056636cfd 100644 --- a/test/Analysis/BlockFrequencyInfo/irreducible.ll +++ b/test/Analysis/BlockFrequencyInfo/irreducible.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -block-freq | FileCheck %s +; RUN: opt < %s -passes='print<block-freq>' -disable-output 2>&1 | FileCheck %s ; A loop with multiple exits isn't irreducible. It should be handled ; correctly. diff --git a/test/Analysis/BlockFrequencyInfo/irreducible_loop_crash.ll b/test/Analysis/BlockFrequencyInfo/irreducible_loop_crash.ll index 2bcd088dd16ed..8cd334f04bca1 100644 --- a/test/Analysis/BlockFrequencyInfo/irreducible_loop_crash.ll +++ b/test/Analysis/BlockFrequencyInfo/irreducible_loop_crash.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -block-freq +; RUN: opt < %s -passes='print<block-freq>' -disable-output target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Analysis/BlockFrequencyInfo/loop_with_branch.ll b/test/Analysis/BlockFrequencyInfo/loop_with_branch.ll index 9a86564c548dd..40d9e82351fd1 100644 --- a/test/Analysis/BlockFrequencyInfo/loop_with_branch.ll +++ b/test/Analysis/BlockFrequencyInfo/loop_with_branch.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -block-freq | FileCheck %s +; RUN: opt < %s -passes='print<block-freq>' -disable-output 2>&1 | FileCheck %s ; CHECK-LABEL: Printing analysis {{.*}} for function 'loop_with_branch': ; CHECK-NEXT: block-frequency-info: loop_with_branch diff --git a/test/Analysis/BlockFrequencyInfo/loops_with_profile_info.ll b/test/Analysis/BlockFrequencyInfo/loops_with_profile_info.ll index 29a9f3b29fb08..3133e167de5fb 100644 --- a/test/Analysis/BlockFrequencyInfo/loops_with_profile_info.ll +++ b/test/Analysis/BlockFrequencyInfo/loops_with_profile_info.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -block-freq | FileCheck %s +; RUN: opt < %s -passes='print<block-freq>' -disable-output 2>&1 | FileCheck %s ; This code contains three loops. One is triple-nested, the ; second is double nested and the third is a single loop. At diff --git a/test/Analysis/BlockFrequencyInfo/nested_loop_with_branches.ll b/test/Analysis/BlockFrequencyInfo/nested_loop_with_branches.ll index 19d165805b046..7025b5d16a450 100644 --- a/test/Analysis/BlockFrequencyInfo/nested_loop_with_branches.ll +++ b/test/Analysis/BlockFrequencyInfo/nested_loop_with_branches.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -block-freq | FileCheck %s +; RUN: opt < %s -passes='print<block-freq>' -disable-output 2>&1 | FileCheck %s ; CHECK-LABEL: Printing analysis {{.*}} for function 'nested_loop_with_branches' ; CHECK-NEXT: block-frequency-info: nested_loop_with_branches diff --git a/test/Analysis/BranchProbabilityInfo/basic.ll b/test/Analysis/BranchProbabilityInfo/basic.ll index d833b8339aac4..d86709130f34c 100644 --- a/test/Analysis/BranchProbabilityInfo/basic.ll +++ b/test/Analysis/BranchProbabilityInfo/basic.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -branch-prob | FileCheck %s +; RUN: opt < %s -passes='print<branch-prob>' -disable-output 2>&1 | FileCheck %s define i32 @test1(i32 %i, i32* %a) { ; CHECK: Printing analysis {{.*}} for function 'test1' diff --git a/test/Analysis/BranchProbabilityInfo/deopt-intrinsic.ll b/test/Analysis/BranchProbabilityInfo/deopt-intrinsic.ll new file mode 100644 index 0000000000000..faa09f9e8a0c4 --- /dev/null +++ b/test/Analysis/BranchProbabilityInfo/deopt-intrinsic.ll @@ -0,0 +1,21 @@ +; RUN: opt -analyze -branch-prob < %s | FileCheck %s +; RUN: opt < %s -passes='print<branch-prob>' -disable-output 2>&1 | FileCheck %s + +declare i32 @llvm.experimental.deoptimize.i32(...) + +define i32 @test1(i32 %a, i32 %b) { +; CHECK-LABEL: Printing analysis {{.*}} for function 'test1': +entry: + %cond = icmp eq i32 %a, 42 + br i1 %cond, label %exit, label %deopt + +; CHECK: edge entry -> exit probability is 0x7ffff800 / 0x80000000 = 100.00% [HOT edge] +; CHECK: edge entry -> deopt probability is 0x00000800 / 0x80000000 = 0.00% + +deopt: + %rval = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] + ret i32 %rval + +exit: + ret i32 %b +} diff --git a/test/Analysis/BranchProbabilityInfo/loop.ll b/test/Analysis/BranchProbabilityInfo/loop.ll index 5be7adf3909df..1a37a7a4659ef 100644 --- a/test/Analysis/BranchProbabilityInfo/loop.ll +++ b/test/Analysis/BranchProbabilityInfo/loop.ll @@ -1,5 +1,6 @@ ; Test the static branch probability heuristics for no-return functions. ; RUN: opt < %s -analyze -branch-prob | FileCheck %s +; RUN: opt < %s -passes='print<branch-prob>' --disable-output 2>&1 | FileCheck %s declare void @g1() declare void @g2() diff --git a/test/Analysis/BranchProbabilityInfo/noreturn.ll b/test/Analysis/BranchProbabilityInfo/noreturn.ll index 7098c2f7b8ccf..0c2fe863d034d 100644 --- a/test/Analysis/BranchProbabilityInfo/noreturn.ll +++ b/test/Analysis/BranchProbabilityInfo/noreturn.ll @@ -1,5 +1,6 @@ ; Test the static branch probability heuristics for no-return functions. ; RUN: opt < %s -analyze -branch-prob | FileCheck %s +; RUN: opt < %s -passes='print<branch-prob>' -disable-output 2>&1 | FileCheck %s declare void @abort() noreturn diff --git a/test/Analysis/BranchProbabilityInfo/pr18705.ll b/test/Analysis/BranchProbabilityInfo/pr18705.ll index f5f9612fcdb67..74983ef1b4f01 100644 --- a/test/Analysis/BranchProbabilityInfo/pr18705.ll +++ b/test/Analysis/BranchProbabilityInfo/pr18705.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -branch-prob | FileCheck %s +; RUN: opt < %s -passes='print<branch-prob>' -disable-output 2>&1 | FileCheck %s ; Since neither of while.body's out-edges is an exit or a back edge, ; calcLoopBranchHeuristics should return early without setting the weights. diff --git a/test/Analysis/BranchProbabilityInfo/pr22718.ll b/test/Analysis/BranchProbabilityInfo/pr22718.ll index 51bbd13e83c16..66ac89793b877 100644 --- a/test/Analysis/BranchProbabilityInfo/pr22718.ll +++ b/test/Analysis/BranchProbabilityInfo/pr22718.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -branch-prob | FileCheck %s +; RUN: opt < %s -passes='print<branch-prob>' -disable-output 2>&1 | FileCheck %s ; In this test, the else clause is taken about 90% of the time. This was not ; reflected in the probability computation because the weight is larger than diff --git a/test/Analysis/CFLAliasAnalysis/Andersen/assign.ll b/test/Analysis/CFLAliasAnalysis/Andersen/assign.ll new file mode 100644 index 0000000000000..237fe72732e8d --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Andersen/assign.ll @@ -0,0 +1,24 @@ +; This testcase ensures that CFL AA handles assignment in an inclusion-based +; manner + +; RUN: opt < %s -disable-basicaa -cfl-anders-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-anders-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +; CHECK-LABEL: Function: test_assign +; CHECK: NoAlias: i64* %a, i64* %b +; CHECK: NoAlias: i32* %c, i64* %b +; CHECK: NoAlias: i32* %d, i64* %a +; CHECK: NoAlias: i32* %c, i32* %d +; CHECK: MayAlias: i32* %e, i64* %a +; CHECK: MayAlias: i32* %e, i64* %b +; CHECK: MayAlias: i32* %c, i32* %e +; CHECK: MayAlias: i32* %d, i32* %e +define void @test_assign(i1 %cond) { + %a = alloca i64, align 8 + %b = alloca i64, align 8 + + %c = bitcast i64* %a to i32* + %d = bitcast i64* %b to i32* + %e = select i1 %cond, i32* %c, i32* %d + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/Andersen/assign2.ll b/test/Analysis/CFLAliasAnalysis/Andersen/assign2.ll new file mode 100644 index 0000000000000..8bd98f388f05e --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Andersen/assign2.ll @@ -0,0 +1,23 @@ +; This testcase ensures that CFL AA handles assignment in an inclusion-based +; manner + +; RUN: opt < %s -disable-basicaa -cfl-anders-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-anders-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +; CHECK-LABEL: Function: test_assign2 +; CHECK: NoAlias: i32* %b, i64* %a +; CHECK: NoAlias: i32* %b, i32* %c +; CHECK: NoAlias: i32* %b, i32* %d +; CHECK: MayAlias: i32* %e, i64* %a +; CHECK: MayAlias: i32* %b, i32* %e +; CHECK: MayAlias: i32* %c, i32* %e +; CHECK: MayAlias: i32* %d, i32* %e +define void @test_assign2(i1 %cond) { + %a = alloca i64, align 8 + %b = alloca i32, align 4 + + %c = bitcast i64* %a to i32* + %d = bitcast i64* %a to i32* + %e = select i1 %cond, i32* %c, i32* %b + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/Andersen/attrs-below.ll b/test/Analysis/CFLAliasAnalysis/Andersen/attrs-below.ll new file mode 100644 index 0000000000000..4cf918081bb50 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Andersen/attrs-below.ll @@ -0,0 +1,61 @@ +; This testcase ensures that AliasAttrs are propagated not only on the same +; level but also downward. + +; RUN: opt < %s -disable-basicaa -cfl-anders-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-anders-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +; CHECK-LABEL: Function: test_attr_below +; CHECK: MayAlias: i64* %q, i64*** %p +; CHECK: NoAlias: i64* %esc, i64*** %p +; CHECK: NoAlias: i64* %esc, i64* %q + +; CHECK: MayAlias: i64* %unknown, i64*** %p +; CHECK: MayAlias: i64* %q, i64* %unknown +; CHECK: MayAlias: i64* %esc, i64* %unknown +; CHECK: MayAlias: i64* %q, i64** %pdrf +; CHECK: MayAlias: i64* %esc, i64** %pdrf +; CHECK: MayAlias: i64* %unknown, i64** %pdrf +; CHECK: MayAlias: i64* %pdrf2, i64* %q +; CHECK: MayAlias: i64* %esc, i64* %pdrf2 +; CHECK: MayAlias: i64* %pdrf2, i64* %unknown +define void @test_attr_below(i64*** %p, i64* %q) { + %esc = alloca i64, align 8 + %escint = ptrtoint i64* %esc to i64 + %unknown = inttoptr i64 %escint to i64* + + %pdrf = load i64**, i64*** %p + %pdrf2 = load i64*, i64** %pdrf + + ret void +} + +; CHECK-LABEL: Function: test_attr_assign_below +; CHECK: MayAlias: i64** %sel, i64*** %p +; CHECK: MayAlias: i64* %q, i64** %sel +; CHECK: MayAlias: i64** %a, i64** %sel +; CHECK: MayAlias: i64** %pdrf, i64** %sel + +; CHECK: MayAlias: i64** %c, i64*** %p +; CHECK: MayAlias: i64* %q, i64** %c +; CHECK: MayAlias: i64** %a, i64** %c +; CHECK: MayAlias: i64** %c, i64** %pdrf +; CHECK: MayAlias: i64** %c, i64** %sel + +; CHECK: MayAlias: i64* %d, i64*** %p +; CHECK: MayAlias: i64* %d, i64* %q +; CHECK: MayAlias: i64* %d, i64** %pdrf +; CHECK: MayAlias: i64* %d, i64** %sel +define void @test_attr_assign_below(i64*** %p, i64* %q, i1 %cond) { + %a = alloca i64*, align 8 + %pdrf = load i64**, i64*** %p + %sel = select i1 %cond, i64** %a, i64** %pdrf + + %b = alloca i64**, align 8 + store i64** %sel, i64*** %b + + %c = load i64**, i64*** %b + %d = load i64*, i64** %c + + ret void +} + diff --git a/test/Analysis/CFLAliasAnalysis/Andersen/attrs.ll b/test/Analysis/CFLAliasAnalysis/Andersen/attrs.ll new file mode 100644 index 0000000000000..4ba3d1510be9e --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Andersen/attrs.ll @@ -0,0 +1,94 @@ +; This testcase ensures that CFL AA handles escaped values no more conservative than it should + +; RUN: opt < %s -disable-basicaa -cfl-anders-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-anders-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +; CHECK-LABEL: Function: test_local +; CHECK: NoAlias: i32* %a, i32* %b +; CHECK: MayAlias: i32* %a, i32* %aAlias +; CHECK: NoAlias: i32* %aAlias, i32* %b +define void @test_local() { + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %aint = ptrtoint i32* %a to i64 + %aAlias = inttoptr i64 %aint to i32* + ret void +} + +; CHECK-LABEL: Function: test_global_param +; CHECK: NoAlias: i32* %a, i32** %x +; CHECK: MayAlias: i32* %a, i32* %xload +; CHECK: MayAlias: i32* %a, i32* %gload +; CHECK: MayAlias: i32* %gload, i32* %xload +; CHECK: MayAlias: i32** %x, i32** @ext_global +; CHECK: NoAlias: i32* %a, i32** @ext_global +@ext_global = external global i32* +define void @test_global_param(i32** %x) { + %a = alloca i32, align 4 + %aint = ptrtoint i32* %a to i64 + %xload = load i32*, i32** %x + %gload = load i32*, i32** @ext_global + ret void +} + +declare void @external_func(i32**) +; CHECK-LABEL: Function: test_external_call +; CHECK: NoAlias: i32* %b, i32* %x +; CHECK: NoAlias: i32* %b, i32** %a +; CHECK: MayAlias: i32* %c, i32* %x +; CHECK: MayAlias: i32* %c, i32** %a +; CHECK: NoAlias: i32* %b, i32* %c +define void @test_external_call(i32* %x) { + %a = alloca i32*, align 8 + %b = alloca i32, align 4 + call void @external_func(i32** %a) + %c = load i32*, i32** %a + ret void +} + +declare void @external_func_readonly(i32**) readonly +; CHECK-LABEL: Function: test_external_call_func_readonly +; CHECK: MayAlias: i32* %c, i32* %x +; CHECK: NoAlias: i32* %c, i32** %a +define void @test_external_call_func_readonly(i32* %x) { + %a = alloca i32*, align 8 + %b = alloca i32, align 4 + store i32* %x, i32** %a, align 4 + call void @external_func_readonly(i32** %a) + %c = load i32*, i32** %a + ret void +} + +; CHECK-LABEL: Function: test_external_call_callsite_readonly +; CHECK: MayAlias: i32* %c, i32* %x +; CHECK: NoAlias: i32* %c, i32** %a +define void @test_external_call_callsite_readonly(i32* %x) { + %a = alloca i32*, align 8 + %b = alloca i32, align 4 + store i32* %x, i32** %a, align 4 + call void @external_func(i32** %a) readonly + %c = load i32*, i32** %a + ret void +} + +declare i32* @external_func_normal_return(i32*) +; CHECK-LABEL: Function: test_external_call_normal_return +; CHECK: MayAlias: i32* %c, i32* %x +; CHECK: MayAlias: i32* %a, i32* %c +define void @test_external_call_normal_return(i32* %x) { + %a = alloca i32, align 8 + %b = alloca i32, align 4 + %c = call i32* @external_func_normal_return(i32* %a) + ret void +} + +declare noalias i32* @external_func_noalias_return(i32*) +; CHECK-LABEL: Function: test_external_call_noalias_return +; CHECK: NoAlias: i32* %c, i32* %x +; CHECK: NoAlias: i32* %a, i32* %c +define void @test_external_call_noalias_return(i32* %x) { + %a = alloca i32, align 8 + %b = alloca i32, align 4 + %c = call i32* @external_func_noalias_return(i32* %a) + ret void +} diff --git a/test/Analysis/CFLAliasAnalysis/Andersen/cycle.ll b/test/Analysis/CFLAliasAnalysis/Andersen/cycle.ll new file mode 100644 index 0000000000000..4ce9467ddc374 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Andersen/cycle.ll @@ -0,0 +1,34 @@ +; This testcase ensures that CFL AA handles assignment cycles correctly + +; RUN: opt < %s -disable-basicaa -cfl-anders-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-anders-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +; CHECK-LABEL: Function: test_cycle +; CHECK: NoAlias: i64* %a, i64** %b +; CHECK: NoAlias: i64* %a, i64*** %c +; CHECK: NoAlias: i64** %b, i64*** %c +; CHECK: NoAlias: i64* %a, i64**** %d +; CHECK: NoAlias: i64** %b, i64**** %d +; CHECK: NoAlias: i64*** %c, i64**** %d +; CHECK: NoAlias: i64* %a, i64* %e +; CHECK: NoAlias: i64* %e, i64** %b +; CHECK: NoAlias: i64* %e, i64*** %c +; CHECK: MayAlias: i64* %a, i64* %f +; CHECK: NoAlias: i64* %f, i64** %b +; CHECK: NoAlias: i64* %f, i64*** %c +; CHECK: MayAlias: i64* %f, i64**** %d +; CHECK: MayAlias: i64* %e, i64* %f +define void @test_cycle() { + %a = alloca i64, align 8 + %b = alloca i64*, align 8 + %c = alloca i64**, align 8 + %d = alloca i64***, align 8 + store i64* %a, i64** %b + store i64** %b, i64*** %c + store i64*** %c, i64**** %d + + %e = bitcast i64**** %d to i64* + store i64* %e, i64** %b + %f = load i64*, i64** %b + ret void +} diff --git a/test/Analysis/CFLAliasAnalysis/Andersen/memalias.ll b/test/Analysis/CFLAliasAnalysis/Andersen/memalias.ll new file mode 100644 index 0000000000000..d3fb09091aa0c --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Andersen/memalias.ll @@ -0,0 +1,21 @@ +; This testcase ensures that CFL AA correctly handles simple memory alias +; pattern + +; RUN: opt < %s -disable-basicaa -cfl-anders-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-anders-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +; CHECK-LABEL: Function: test_memalias +; CHECK: NoAlias: i64* %a, i64** %b +; CHECK: NoAlias: i32** %c, i64* %a +; CHECK: MayAlias: i32* %d, i64* %a +; CHECK: NoAlias: i32* %d, i64** %b +; CHECK: NoAlias: i32* %d, i32** %c +define void @test_memalias() { + %a = alloca i64, align 8 + %b = alloca i64*, align 8 + store i64* %a, i64** %b + + %c = bitcast i64** %b to i32** + %d = load i32*, i32** %c + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/arguments-globals.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/arguments-globals.ll index 4844577d6fef2..aa3cada3bec6d 100644 --- a/test/Analysis/CFLAliasAnalysis/arguments-globals.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/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 -disable-basicaa -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s ; CHECK: Function: test diff --git a/test/Analysis/CFLAliasAnalysis/arguments.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/arguments.ll index f3e6679c35e27..85f3bc64e0dcf 100644 --- a/test/Analysis/CFLAliasAnalysis/arguments.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/arguments.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 -cfl-steens-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s ; CHECK: Function: test diff --git a/test/Analysis/CFLAliasAnalysis/asm-global-bugfix.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/asm-global-bugfix.ll index ec2de54e3eee1..341aafdab8645 100644 --- a/test/Analysis/CFLAliasAnalysis/asm-global-bugfix.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/asm-global-bugfix.ll @@ -2,7 +2,7 @@ ; whether two values that didn't belong to a function (i.e. two globals, etc) ; aliased. -; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -cfl-steens-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s @G = private unnamed_addr constant [1 x i8] c"\00", align 1 diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/attr-escape.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/attr-escape.ll new file mode 100644 index 0000000000000..3adce6a923b25 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/attr-escape.ll @@ -0,0 +1,94 @@ +; This testcase ensures that CFL AA handles escaped values no more conservative than it should + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +; CHECK-LABEL: Function: test_local +; CHECK: NoAlias: i32* %a, i32* %b +; CHECK: MayAlias: i32* %a, i32* %aAlias +; CHECK: NoAlias: i32* %aAlias, i32* %b +define void @test_local() { + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %aint = ptrtoint i32* %a to i64 + %aAlias = inttoptr i64 %aint to i32* + ret void +} + +; CHECK-LABEL: Function: test_global_param +; CHECK: NoAlias: i32* %a, i32** %x +; CHECK: MayAlias: i32* %a, i32* %xload +; CHECK: MayAlias: i32* %a, i32* %gload +; CHECK: MayAlias: i32* %gload, i32* %xload +; CHECK: MayAlias: i32** %x, i32** @ext_global +; CHECK: NoAlias: i32* %a, i32** @ext_global +@ext_global = external global i32* +define void @test_global_param(i32** %x) { + %a = alloca i32, align 4 + %aint = ptrtoint i32* %a to i64 + %xload = load i32*, i32** %x + %gload = load i32*, i32** @ext_global + ret void +} + +declare void @external_func(i32**) +; CHECK-LABEL: Function: test_external_call +; CHECK: NoAlias: i32* %b, i32* %x +; CHECK: NoAlias: i32* %b, i32** %a +; CHECK: MayAlias: i32* %c, i32* %x +; CHECK: MayAlias: i32* %c, i32** %a +; CHECK: NoAlias: i32* %b, i32* %c +define void @test_external_call(i32* %x) { + %a = alloca i32*, align 8 + %b = alloca i32, align 4 + call void @external_func(i32** %a) + %c = load i32*, i32** %a + ret void +} + +declare void @external_func_readonly(i32**) readonly +; CHECK-LABEL: Function: test_external_call_func_readonly +; CHECK: MayAlias: i32* %c, i32* %x +; CHECK: NoAlias: i32* %c, i32** %a +define void @test_external_call_func_readonly(i32* %x) { + %a = alloca i32*, align 8 + %b = alloca i32, align 4 + store i32* %x, i32** %a, align 4 + call void @external_func_readonly(i32** %a) + %c = load i32*, i32** %a + ret void +} + +; CHECK-LABEL: Function: test_external_call_callsite_readonly +; CHECK: MayAlias: i32* %c, i32* %x +; CHECK: NoAlias: i32* %c, i32** %a +define void @test_external_call_callsite_readonly(i32* %x) { + %a = alloca i32*, align 8 + %b = alloca i32, align 4 + store i32* %x, i32** %a, align 4 + call void @external_func(i32** %a) readonly + %c = load i32*, i32** %a + ret void +} + +declare i32* @external_func_normal_return(i32*) +; CHECK-LABEL: Function: test_external_call_normal_return +; CHECK: MayAlias: i32* %c, i32* %x +; CHECK: MayAlias: i32* %a, i32* %c +define void @test_external_call_normal_return(i32* %x) { + %a = alloca i32, align 8 + %b = alloca i32, align 4 + %c = call i32* @external_func_normal_return(i32* %a) + ret void +} + +declare noalias i32* @external_func_noalias_return(i32*) +; CHECK-LABEL: Function: test_external_call_noalias_return +; CHECK: NoAlias: i32* %c, i32* %x +; CHECK: NoAlias: i32* %a, i32* %c +define void @test_external_call_noalias_return(i32* %x) { + %a = alloca i32, align 8 + %b = alloca i32, align 4 + %c = call i32* @external_func_noalias_return(i32* %a) + ret void +} diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/basic-interproc.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/basic-interproc.ll new file mode 100644 index 0000000000000..8a1d62ebd247b --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/basic-interproc.ll @@ -0,0 +1,22 @@ +; This testcase ensures that CFL AA won't be too conservative when trying to do +; interprocedural analysis on simple callee + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +; CHECK-LABEL: Function: noop_callee +; CHECK: MayAlias: i32* %arg1, i32* %arg2 +define void @noop_callee(i32* %arg1, i32* %arg2) { + store i32 0, i32* %arg1 + store i32 0, i32* %arg2 + ret void +} +; CHECK-LABEL: Function: test_noop +; CHECK: NoAlias: i32* %a, i32* %b +define void @test_noop() { + %a = alloca i32, align 4 + %b = alloca i32, align 4 + call void @noop_callee(i32* %a, i32* %b) + + ret void +} diff --git a/test/Analysis/CFLAliasAnalysis/branch-alias.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/branch-alias.ll index dbbf035f34401..4158d4a6464f2 100644 --- a/test/Analysis/CFLAliasAnalysis/branch-alias.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/branch-alias.ll @@ -13,7 +13,7 @@ ; int* ShouldAliasA = *AliasA1; ; } -; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-steens-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/Steensgaard/const-expr-gep.ll index 11b60dd33b55e..c35f6a03cdb9b 100644 --- a/test/Analysis/CFLAliasAnalysis/const-expr-gep.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/const-expr-gep.ll @@ -1,8 +1,8 @@ ; This testcase consists of alias relations which should be completely -; resolvable by cfl-aa, but require analysis of getelementptr constant exprs. +; resolvable by cfl-steens-aa, but require analysis of getelementptr constant exprs. ; Derived from BasicAA/2003-12-11-ConstExprGEP.ll -; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s %T = type { i32, [10 x i8] } @@ -10,7 +10,7 @@ @G2 = external global %T ; TODO: Quite a few of these are MayAlias because we don't yet consider -; constant offsets in CFLAA. If we start doing so, then we'll need to +; constant offsets in CFLSteensAA. If we start doing so, then we'll need to ; change these test cases ; CHECK: Function: test @@ -36,7 +36,7 @@ define void @simplecheck(i32* %arg0) { ret void } -; Ensure that CFLAA properly identifies and handles escaping variables (i.e. +; Ensure that CFLSteensAA properly identifies and handles escaping variables (i.e. ; globals) in nested ConstantExprs ; CHECK: Function: checkNesting diff --git a/test/Analysis/CFLAliasAnalysis/constant-over-index.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/constant-over-index.ll index a8e00aaed3786..09e62fcd85a43 100644 --- a/test/Analysis/CFLAliasAnalysis/constant-over-index.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/constant-over-index.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -cfl-aa -aa-eval -print-all-alias-modref-info 2>&1 | FileCheck %s +; RUN: opt < %s -cfl-steens-aa -aa-eval -print-all-alias-modref-info 2>&1 | FileCheck %s ; CFL AA currently returns PartialAlias, BasicAA returns MayAlias, both seem ; acceptable (although we might decide that we don't want PartialAlias, and if diff --git a/test/Analysis/CFLAliasAnalysis/empty.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/empty.ll index 907fa481d86d4..f8714de2c2fe7 100644 --- a/test/Analysis/CFLAliasAnalysis/empty.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/empty.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 -cfl-steens-aa -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" diff --git a/test/Analysis/CFLAliasAnalysis/full-store-partial-alias.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/full-store-partial-alias.ll index 3503e16898c08..39ea845f2a3a3 100644 --- a/test/Analysis/CFLAliasAnalysis/full-store-partial-alias.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/full-store-partial-alias.ll @@ -1,10 +1,10 @@ -; RUN: opt -S -disable-basicaa -tbaa -cfl-aa -gvn < %s | FileCheck -check-prefix=CFLAA %s +; RUN: opt -S -disable-basicaa -tbaa -cfl-steens-aa -gvn < %s | FileCheck -check-prefix=CFLSteensAA %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, ; so the %tmp5 load is PartialAlias with the store and suppress TBAA. -; FIXME: However, right now, CFLAA cannot prove PartialAlias here +; FIXME: However, right now, CFLSteensAA cannot prove PartialAlias here ; Without CFL AA, TBAA should say that %tmp5 is NoAlias with the store. target datalayout = "e-p:64:64:64" @@ -15,8 +15,8 @@ target datalayout = "e-p:64:64:64" @endianness_test = global i64 1, align 8 define i32 @signbit(double %x) nounwind { -; FIXME: This would be ret i32 %tmp5.lobit if CFLAA could prove PartialAlias -; CFLAA: ret i32 0 +; FIXME: This would be ret i32 %tmp5.lobit if CFLSteensAA could prove PartialAlias +; CFLSteensAA: ret i32 0 ; CHECK: ret i32 0 entry: %u = alloca %union.anon, align 8 diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/gep-index-no-alias.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/gep-index-no-alias.ll new file mode 100644 index 0000000000000..906b71c5aab32 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/gep-index-no-alias.ll @@ -0,0 +1,14 @@ +; This testcase ensures that gep result does not alias gep indices + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-no-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-no-aliases -disable-output 2>&1 | FileCheck %s + +; CHECK: Function: foo +; CHECK: [2 x i32]* %a, [2 x i32]* %b +define void @foo(i32 %n) { + %a = alloca [2 x i32], align 4 + %b = alloca [2 x i32], align 4 + %c = getelementptr inbounds [2 x i32], [2 x i32]* %a, i32 0, i32 %n + %d = getelementptr inbounds [2 x i32], [2 x i32]* %b, i32 0, i32 %n + ret void +} diff --git a/test/Analysis/CFLAliasAnalysis/gep-signed-arithmetic.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/gep-signed-arithmetic.ll index 1edbb9fff56b1..34095cedf7387 100644 --- a/test/Analysis/CFLAliasAnalysis/gep-signed-arithmetic.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/gep-signed-arithmetic.ll @@ -1,9 +1,9 @@ -; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-steens-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" -; FIXME: This could be PartialAlias but CFLAA can't currently prove it +; FIXME: This could be PartialAlias but CFLSteensAA can't currently prove it ; CHECK: 1 may alias response define i32 @test(i32 %indvar) nounwind { diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-arg-deref-escape.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-arg-deref-escape.ll new file mode 100644 index 0000000000000..8c92d281a80b7 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-arg-deref-escape.ll @@ -0,0 +1,33 @@ +; This testcase ensures that CFL AA answers queries soundly when callee tries +; to escape the memory pointed to by its parameters + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +declare void @opaque(i32*) +define void @escape_arg_deref(i32** %arg) { + %arg_deref = load i32*, i32** %arg + call void @opaque(i32* %arg_deref) + ret void +} +; CHECK-LABEL: Function: test_arg_deref_escape +; CHECK: NoAlias: i32* %a, i32** %x +; CHECK: NoAlias: i32* %b, i32** %x +; CHECK: NoAlias: i32* %a, i32* %b +; CHECK: NoAlias: i32** %p, i32** %x +; CHECK: NoAlias: i32* %a, i32** %p +; CHECK: NoAlias: i32* %b, i32** %p +; CHECK: MayAlias: i32* %a, i32* %c +; CHECK: NoAlias: i32* %b, i32* %c +; CHECK: NoAlias: i32* %c, i32** %p +define void @test_arg_deref_escape(i32** %x) { + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %p = alloca i32*, align 4 + + store i32* %a, i32** %p + call void @escape_arg_deref(i32** %p) + %c = load i32*, i32** %x + + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-arg-escape.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-arg-escape.ll new file mode 100644 index 0000000000000..0dfcae7920335 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-arg-escape.ll @@ -0,0 +1,31 @@ +; This testcase ensures that CFL AA answers queries soundly when callee tries +; to escape its parameters + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +declare void @opaque(i32*) +define void @escape_arg(i32* %arg) { + call void @opaque(i32* %arg) + ret void +} +; CHECK-LABEL: Function: test_arg_escape +; CHECK: NoAlias: i32* %a, i32** %x +; CHECK: NoAlias: i32* %b, i32** %x +; CHECK: NoAlias: i32* %a, i32* %b +; CHECK: NoAlias: i32* %c, i32** %x +; CHECK: NoAlias: i32* %a, i32* %c +; CHECK: NoAlias: i32* %b, i32* %c +; CHECK: MayAlias: i32* %a, i32* %d +; CHECK: MayAlias: i32* %b, i32* %d +; CHECK: NoAlias: i32* %c, i32* %d +define void @test_arg_escape(i32** %x) { + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %c = alloca i32, align 4 + call void @escape_arg(i32* %a) + call void @escape_arg(i32* %b) + %d = load i32*, i32** %x + + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-arg.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-arg.ll new file mode 100644 index 0000000000000..e071e7e46c25a --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-arg.ll @@ -0,0 +1,23 @@ +; This testcase ensures that CFL AA answers queries soundly when callee tries +; to return one of its parameters + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +define i32* @return_arg_callee(i32* %arg1, i32* %arg2) { + ret i32* %arg1 +} +; CHECK-LABEL: Function: test_return_arg +; CHECK: NoAlias: i32* %a, i32* %b +; CHECK: MayAlias: i32* %a, i32* %c +; CHECK: NoAlias: i32* %b, i32* %c + +; CHECK: NoModRef: Ptr: i32* %b <-> %c = call i32* @return_arg_callee(i32* %a, i32* %b) +define void @test_return_arg() { + %a = alloca i32, align 4 + %b = alloca i32, align 4 + + %c = call i32* @return_arg_callee(i32* %a, i32* %b) + + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-deref-arg-multilevel.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-deref-arg-multilevel.ll new file mode 100644 index 0000000000000..3c7c614998296 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-deref-arg-multilevel.ll @@ -0,0 +1,46 @@ +; This testcase ensures that CFL AA answers queries soundly when callee tries +; to return the multi-level dereference of one of its parameters + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +define i32* @return_deref_arg_multilevel_callee(i32*** %arg1) { + %deref = load i32**, i32*** %arg1 + %deref2 = load i32*, i32** %deref + ret i32* %deref2 +} +; CHECK-LABEL: Function: test_return_deref_arg_multilevel +; CHECK: NoAlias: i32* %a, i32* %b +; CHECK: MayAlias: i32* %a, i32* %c +; CHECK: NoAlias: i32* %b, i32* %c +; CHECK: NoAlias: i32* %c, i32** %p +; CHECK: NoAlias: i32* %c, i32*** %pp +; CHECK: MayAlias: i32** %lpp, i32** %p +; CHECK: NoAlias: i32** %lpp, i32*** %pp +; CHECK: NoAlias: i32* %c, i32** %lpp +; CHECK: MayAlias: i32* %a, i32* %lpp_deref +; CHECK: NoAlias: i32* %b, i32* %lpp_deref +; CHECK: NoAlias: i32* %lpp_deref, i32*** %pp +; CHECK: MayAlias: i32* %a, i32* %lp +; CHECK: NoAlias: i32* %b, i32* %lp +; CHECK: NoAlias: i32* %lp, i32** %p +; CHECK: NoAlias: i32* %lp, i32*** %pp +; CHECK: MayAlias: i32* %c, i32* %lp +; CHECK: NoAlias: i32* %lp, i32** %lpp +; CHECK: MayAlias: i32* %lp, i32* %lpp_deref +define void @test_return_deref_arg_multilevel() { + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %p = alloca i32*, align 8 + %pp = alloca i32**, align 8 + + store i32* %a, i32** %p + store i32** %p, i32*** %pp + %c = call i32* @return_deref_arg_multilevel_callee(i32*** %pp) + + %lpp = load i32**, i32*** %pp + %lpp_deref = load i32*, i32** %lpp + %lp = load i32*, i32** %p + + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-deref-arg.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-deref-arg.ll new file mode 100644 index 0000000000000..e1db5d34f3490 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-deref-arg.ll @@ -0,0 +1,30 @@ +; This testcase ensures that CFL AA answers queries soundly when callee tries +; to return the dereference of one of its parameters + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +define i32* @return_deref_arg_callee(i32** %arg1) { + %deref = load i32*, i32** %arg1 + ret i32* %deref +} +; CHECK-LABEL: Function: test_return_deref_arg +; CHECK: NoAlias: i32* %a, i32* %b +; CHECK: MayAlias: i32* %a, i32* %c +; CHECK: NoAlias: i32* %b, i32* %c +; CHECK: MayAlias: i32* %a, i32* %lp +; CHECK: NoAlias: i32* %b, i32* %lp +; CHECK: NoAlias: i32* %lp, i32** %p +; CHECK: MayAlias: i32* %c, i32* %lp +define void @test_return_deref_arg() { + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %p = alloca i32*, align 8 + + store i32* %a, i32** %p + %c = call i32* @return_deref_arg_callee(i32** %p) + + %lp = load i32*, i32** %p + + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-escape.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-escape.ll new file mode 100644 index 0000000000000..5019e51d7b8bf --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-escape.ll @@ -0,0 +1,33 @@ +; This testcase ensures that CFL AA answers queries soundly when callee tries +; to return an escaped pointer + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +declare noalias i8* @malloc(i64) +declare void @opaque(i32*) + +define i32* @return_escaped_callee() { + %ptr = call noalias i8* @malloc(i64 8) + %ptr_cast = bitcast i8* %ptr to i32* + call void @opaque(i32* %ptr_cast) + ret i32* %ptr_cast +} +; CHECK-LABEL: Function: test_return_escape +; CHECK: NoAlias: i32* %a, i32** %x +; CHECK: NoAlias: i32* %b, i32** %x +; CHECK: NoAlias: i32* %a, i32* %b +; CHECK: NoAlias: i32* %c, i32** %x +; CHECK: NoAlias: i32* %a, i32* %c +; CHECK: NoAlias: i32* %b, i32* %c +; CHECK: NoAlias: i32* %a, i32* %d +; CHECK: MayAlias: i32* %b, i32* %d +; CHECK: MayAlias: i32* %c, i32* %d +define void @test_return_escape(i32** %x) { + %a = alloca i32, align 4 + %b = call i32* @return_escaped_callee() + %c = call i32* @return_escaped_callee() + %d = load i32*, i32** %x + + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-ref-arg-multilevel.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-ref-arg-multilevel.ll new file mode 100644 index 0000000000000..e94cbbbdf30e1 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-ref-arg-multilevel.ll @@ -0,0 +1,51 @@ +; This testcase ensures that CFL AA answers queries soundly when callee tries +; to return the multi-level reference of one of its parameters + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +declare noalias i8* @malloc(i64) + +define i32*** @return_ref_arg_multilevel_callee(i32* %arg1) { + %ptr = call noalias i8* @malloc(i64 8) + %ptr_cast = bitcast i8* %ptr to i32*** + %ptr2 = call noalias i8* @malloc(i64 8) + %ptr_cast2 = bitcast i8* %ptr2 to i32** + store i32* %arg1, i32** %ptr_cast2 + store i32** %ptr_cast2, i32*** %ptr_cast + ret i32*** %ptr_cast +} +; CHECK-LABEL: Function: test_return_ref_arg_multilevel +; CHECK: NoAlias: i32* %a, i32*** %b +; CHECK: NoAlias: i32** %p, i32*** %b +; CHECK: NoAlias: i32* %a, i32** %lb +; CHECK: NoAlias: i32** %lb, i32*** %pp +; CHECK: NoAlias: i32** %lb, i32*** %b +; CHECK: MayAlias: i32* %a, i32* %lb_deref +; CHECK: NoAlias: i32* %lb_deref, i32** %lpp +; CHECK: MayAlias: i32* %lb_deref, i32* %lpp_deref +; CHECK: NoAlias: i32* %lpp_deref, i32** %lpp +; CHECK: MayAlias: i32* %lb_deref, i32* %lp +; CHECK: NoAlias: i32* %lp, i32** %lpp +; CHECK: MayAlias: i32* %lp, i32* %lpp_deref + +; We could've proven the following facts if the analysis were inclusion-based: +; NoAlias: i32*** %b, i32*** %pp +; NoAlias: i32** %lb, i32** %p +define void @test_return_ref_arg_multilevel() { + %a = alloca i32, align 4 + %p = alloca i32*, align 8 + %pp = alloca i32**, align 8 + + store i32* %a, i32** %p + store i32** %p, i32*** %pp + %b = call i32*** @return_ref_arg_multilevel_callee(i32* %a) + + %lb = load i32**, i32*** %b + %lb_deref = load i32*, i32** %lb + %lpp = load i32**, i32*** %pp + %lpp_deref = load i32*, i32** %lpp + %lp = load i32*, i32** %p + + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-ref-arg.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-ref-arg.ll new file mode 100644 index 0000000000000..aae642c424da3 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-ref-arg.ll @@ -0,0 +1,36 @@ +; This testcase ensures that CFL AA answers queries soundly when callee tries +; to return the reference of one of its parameters + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +declare noalias i8* @malloc(i64) + +define i32** @return_ref_arg_callee(i32* %arg1) { + %ptr = call noalias i8* @malloc(i64 8) + %ptr_cast = bitcast i8* %ptr to i32** + store i32* %arg1, i32** %ptr_cast + ret i32** %ptr_cast +} +; CHECK-LABEL: Function: test_return_ref_arg +; CHECK: MayAlias: i32* %a, i32* %lb +; CHECK: NoAlias: i32* %lb, i32** %p +; CHECK: NoAlias: i32* %lb, i32** %b +; CHECK: NoAlias: i32* %lp, i32** %p +; CHECK: NoAlias: i32* %lp, i32** %b +; CHECK: MayAlias: i32* %lb, i32* %lp + +; We could've proven the following facts if the analysis were inclusion-based: +; NoAlias: i32** %b, i32** %p +define void @test_return_ref_arg() { + %a = alloca i32, align 4 + %p = alloca i32*, align 8 + + store i32* %a, i32** %p + %b = call i32** @return_ref_arg_callee(i32* %a) + + %lb = load i32*, i32** %b + %lp = load i32*, i32** %p + + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-unknown.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-unknown.ll new file mode 100644 index 0000000000000..bc4a9bc901bc4 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-ret-unknown.ll @@ -0,0 +1,38 @@ +; This testcase ensures that CFL AA answers queries soundly when callee tries +; to return an unknown pointer + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +@g = external global i32 +define i32* @return_unknown_callee(i32* %arg1, i32* %arg2) { + ret i32* @g +} +; CHECK-LABEL: Function: test_return_unknown +; CHECK: NoAlias: i32* %a, i32* %b +; CHECK: MayAlias: i32* %c, i32* %x +; CHECK: NoAlias: i32* %a, i32* %c +; CHECK: NoAlias: i32* %b, i32* %c +define void @test_return_unknown(i32* %x) { + %a = alloca i32, align 4 + %b = alloca i32, align 4 + + %c = call i32* @return_unknown_callee(i32* %a, i32* %b) + + ret void +} + +@g2 = external global i32* +define i32** @return_unknown_callee2() { + ret i32** @g2 +} +; CHECK-LABEL: Function: test_return_unknown2 +; CHECK: MayAlias: i32* %x, i32** %a +; CHECK: MayAlias: i32* %b, i32* %x +; CHECK: MayAlias: i32* %b, i32** %a +define void @test_return_unknown2(i32* %x) { + %a = call i32** @return_unknown_callee2() + %b = load i32*, i32** %a + + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-store-arg-multilevel.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-store-arg-multilevel.ll new file mode 100644 index 0000000000000..f5b61687ad700 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-store-arg-multilevel.ll @@ -0,0 +1,48 @@ +; This testcase ensures that CFL AA answers queries soundly when callee tries +; to mutate the memory pointed to by its parameters + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +declare noalias i8* @malloc(i64) + +define void @store_arg_multilevel_callee(i32*** %arg1, i32* %arg2) { + %ptr = call noalias i8* @malloc(i64 8) + %ptr_cast = bitcast i8* %ptr to i32** + store i32* %arg2, i32** %ptr_cast + store i32** %ptr_cast, i32*** %arg1 + ret void +} +; CHECK-LABEL: Function: test_store_arg_multilevel +; CHECK: NoAlias: i32* %a, i32** %lpp +; CHECK: NoAlias: i32* %b, i32** %lpp +; CHECK: MayAlias: i32** %lpp, i32** %p +; CHECK: MayAlias: i32* %a, i32* %lpp_deref +; CHECK: MayAlias: i32* %b, i32* %lpp_deref +; CHECK: NoAlias: i32* %lpp_deref, i32** %p +; CHECK: NoAlias: i32* %lpp_deref, i32*** %pp +; CHECK: NoAlias: i32* %lpp_deref, i32** %lpp +; CHECK: MayAlias: i32* %a, i32* %lp +; CHECK: NoAlias: i32* %lp, i32*** %pp +; CHECK: NoAlias: i32* %lp, i32** %lpp +; CHECK: MayAlias: i32* %lp, i32* %lpp_deref + +; We could've proven the following facts if the analysis were inclusion-based: +; NoAlias: i32* %a, i32* %b +; NoAlias: i32* %b, i32* %lp +define void @test_store_arg_multilevel() { + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %p = alloca i32*, align 8 + %pp = alloca i32**, align 8 + + store i32* %a, i32** %p + store i32** %p, i32*** %pp + call void @store_arg_multilevel_callee(i32*** %pp, i32* %b) + + %lpp = load i32**, i32*** %pp + %lpp_deref = load i32*, i32** %lpp + %lp = load i32*, i32** %p + + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-store-arg-unknown.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-store-arg-unknown.ll new file mode 100644 index 0000000000000..a90514c58fa95 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-store-arg-unknown.ll @@ -0,0 +1,32 @@ +; This testcase ensures that CFL AA answers queries soundly when callee tries +; to mutate the memory pointed to by its parameters + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +@g = external global i32 + +define void @store_arg_unknown_callee(i32** %arg1) { + store i32* @g, i32** %arg1 + ret void +} +; CHECK-LABEL: Function: test_store_arg_unknown +; CHECK: NoAlias: i32* %x, i32** %p +; CHECK: NoAlias: i32* %a, i32** %p +; CHECK: NoAlias: i32* %b, i32** %p +; CHECK: MayAlias: i32* %lp, i32* %x +; CHECK: MayAlias: i32* %a, i32* %lp +; CHECK: NoAlias: i32* %b, i32* %lp +; CHECK: NoAlias: i32* %lp, i32** %p +define void @test_store_arg_unknown(i32* %x) { + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %p = alloca i32*, align 8 + + store i32* %a, i32** %p + call void @store_arg_unknown_callee(i32** %p) + + %lp = load i32*, i32** %p + + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-store-arg.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-store-arg.ll new file mode 100644 index 0000000000000..e520de4d0b1c1 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/interproc-store-arg.ll @@ -0,0 +1,36 @@ +; This testcase ensures that CFL AA answers queries soundly when callee tries +; to mutate the memory pointed to by its parameters + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s + +define void @store_arg_callee(i32** %arg1, i32* %arg2) { + store i32* %arg2, i32** %arg1 + ret void +} +; CHECK-LABEL: Function: test_store_arg +; CHECK: NoAlias: i32* %a, i32** %p +; CHECK: NoAlias: i32* %b, i32** %p +; CHECK: MayAlias: i32* %a, i32* %lp +; CHECK: MayAlias: i32* %b, i32* %lp +; CHECK: MayAlias: i32* %b, i32* %lq +; CHECK: MayAlias: i32* %lp, i32* %lq + +; We could've proven the following facts if the analysis were inclusion-based: +; NoAlias: i32* %a, i32* %b +; NoAlias: i32* %a, i32* %lq +define void @test_store_arg() { + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %p = alloca i32*, align 8 + %q = alloca i32*, align 8 + + store i32* %a, i32** %p + store i32* %b, i32** %q + call void @store_arg_callee(i32** %p, i32* %b) + + %lp = load i32*, i32** %p + %lq = load i32*, i32** %q + + ret void +}
\ No newline at end of file diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/malloc-and-free.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/malloc-and-free.ll new file mode 100644 index 0000000000000..76c97db8038c7 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/malloc-and-free.ll @@ -0,0 +1,30 @@ +; This testcase ensures that CFL AA handles malloc and free in a sound and precise manner + +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-no-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-no-aliases -disable-output 2>&1 | FileCheck %s + +declare noalias i8* @malloc(i64) +declare noalias i8* @calloc(i64, i64) +declare void @free(i8* nocapture) + +; CHECK: Function: test_malloc +; CHECK: NoAlias: i8* %p, i8* %q +define void @test_malloc(i8* %p) { + %q = call i8* @malloc(i64 4) + ret void +} + +; CHECK: Function: test_calloc +; CHECK: NoAlias: i8* %p, i8* %q +define void @test_calloc(i8* %p) { + %q = call i8* @calloc(i64 2, i64 4) + ret void +} + +; CHECK: Function: test_free +; CHECK: NoAlias: i8* %p, i8* %q +define void @test_free(i8* %p) { + %q = alloca i8, align 4 + call void @free(i8* %q) + ret void +} diff --git a/test/Analysis/CFLAliasAnalysis/multilevel-combine.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/multilevel-combine.ll index be671bfc4ca27..32abe9d8f744c 100644 --- a/test/Analysis/CFLAliasAnalysis/multilevel-combine.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/multilevel-combine.ll @@ -8,7 +8,7 @@ ; } ; -; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s %T = type { i32, [10 x i8] } diff --git a/test/Analysis/CFLAliasAnalysis/multilevel.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/multilevel.ll index d42dca442eab0..ea06b7430bcdb 100644 --- a/test/Analysis/CFLAliasAnalysis/multilevel.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/multilevel.ll @@ -6,7 +6,7 @@ ; *m; ; *n; -; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -cfl-steens-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/Steensgaard/must-and-partial.ll index 5bcc3f9910224..cc03870b79485 100644 --- a/test/Analysis/CFLAliasAnalysis/must-and-partial.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/must-and-partial.ll @@ -1,11 +1,11 @@ -; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-all-alias-modref-info 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info 2>&1 | FileCheck %s ; When merging MustAlias and PartialAlias, merge to PartialAlias ; instead of MayAlias. 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" -; FIXME: This could be PartialAlias but CFLAA can't currently prove it +; FIXME: This could be PartialAlias but CFLSteensAA can't currently prove it ; CHECK: MayAlias: i16* %bigbase0, i8* %phi define i8 @test0(i1 %x) { entry: @@ -25,7 +25,7 @@ green: ret i8 %loaded } -; FIXME: This could be PartialAlias but CFLAA can't currently prove it +; FIXME: This could be PartialAlias but CFLSteensAA can't currently prove it ; CHECK: MayAlias: i16* %bigbase1, i8* %sel define i8 @test1(i1 %x) { entry: diff --git a/test/Analysis/CFLAliasAnalysis/opaque-call-alias.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/opaque-call-alias.ll index 6121dca1345dd..a03b104778bdf 100644 --- a/test/Analysis/CFLAliasAnalysis/opaque-call-alias.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/opaque-call-alias.ll @@ -2,10 +2,10 @@ ; 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 +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s ; CHECK: Function: test -; CHECK: MayAlias: i8* %Arg, i8* %Escapes +; CHECK: NoAlias: i8* %Arg, i8* %Escapes ; CHECK: MayAlias: i8* %Arg, i8* %Retrieved ; CHECK: MayAlias: i8* %Escapes, i8* %Retrieved define void @test(i8* %Arg) { diff --git a/test/Analysis/CFLAliasAnalysis/phi-and-select.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/phi-and-select.ll index a0e71a7e7dcae..2af7fdea02c5e 100644 --- a/test/Analysis/CFLAliasAnalysis/phi-and-select.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/phi-and-select.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 -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s ; Derived from (a subset of) BasicAA/phi-and-select.ll ; CHECK: Function: qux diff --git a/test/Analysis/CFLAliasAnalysis/Steensgaard/pr27213.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/pr27213.ll new file mode 100644 index 0000000000000..d685cab6275e8 --- /dev/null +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/pr27213.ll @@ -0,0 +1,39 @@ +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s + +; CHECK-LABEL: Function: foo +; CHECK: MayAlias: i32* %A, i32* %B +define void @foo(i32* %A, i32* %B) { +entry: + store i32 0, i32* %A, align 4 + store i32 0, i32* %B, align 4 + ret void +} + +; CHECK-LABEL: Function: bar +; CHECK: MayAlias: i32* %A, i32* %B +; CHECK: MayAlias: i32* %A, i32* %arrayidx +; CHECK: MayAlias: i32* %B, i32* %arrayidx +define void @bar(i32* %A, i32* %B) { +entry: + store i32 0, i32* %A, align 4 + %arrayidx = getelementptr inbounds i32, i32* %B, i64 1 + store i32 0, i32* %arrayidx, align 4 + ret void +} + +@G = global i32 0 + +; CHECK-LABEL: Function: baz +; CHECK: MayAlias: i32* %A, i32* @G +define void @baz(i32* %A) { +entry: + store i32 0, i32* %A, align 4 + store i32 0, i32* @G, align 4 + ret void +} + +; CHECK-LABEL: Alias Analysis Evaluator Report +; CHECK: 5 Total Alias Queries Performed +; CHECK: 0 no alias responses +; CHECK: 5 may alias responses diff --git a/test/Analysis/CFLAliasAnalysis/simple.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/simple.ll index adc71867bfc14..17b48d48b0f24 100644 --- a/test/Analysis/CFLAliasAnalysis/simple.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/simple.ll @@ -1,7 +1,7 @@ ; This testcase consists of alias relations which should be completely -; resolvable by cfl-aa (derived from BasicAA/2003-11-04-SimpleCases.ll). +; resolvable by cfl-steens-aa (derived from BasicAA/2003-11-04-SimpleCases.ll). -; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -cfl-steens-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s %T = type { i32, [10 x i8] } diff --git a/test/Analysis/CFLAliasAnalysis/stratified-attrs-indexing.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/stratified-attrs-indexing.ll index 347528583a610..f43af93e99481 100644 --- a/test/Analysis/CFLAliasAnalysis/stratified-attrs-indexing.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/stratified-attrs-indexing.ll @@ -1,11 +1,11 @@ -; This testcase ensures that CFLAA doesn't try to access out of bounds indices +; This testcase ensures that CFLSteensAA doesn't try to access out of bounds indices ; when given functions with large amounts of arguments (specifically, more ; arguments than the StratifiedAttrs bitset can handle) ; ; Because the result on failure is effectively crashing the compiler, output ; checking is minimal. -; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -cfl-steens-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s ; CHECK: Function: test define void @test(i1 %cond, diff --git a/test/Analysis/CFLAliasAnalysis/va.ll b/test/Analysis/CFLAliasAnalysis/Steensgaard/va.ll index a432cea8a1dfb..43fca92074127 100644 --- a/test/Analysis/CFLAliasAnalysis/va.ll +++ b/test/Analysis/CFLAliasAnalysis/Steensgaard/va.ll @@ -1,16 +1,19 @@ -; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s ; CHECK-LABEL: Function: test1 -; CHECK: 0 no alias responses +; CHECK: MayAlias: i32* %X, i32* %tmp +; CHECK: MayAlias: i32* %tmp, i8** %ap +; CHECK: NoAlias: i8** %ap, i8** %aq +; CHECK: MayAlias: i32* %tmp, i8** %aq -define i32 @test1(i32 %X, ...) { +define i32* @test1(i32* %X, ...) { ; Initialize variable argument processing %ap = alloca i8* %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; Read a single integer argument - %tmp = va_arg i8** %ap, i32 + ; Read a single pointer argument + %tmp = va_arg i8** %ap, i32* ; Demonstrate usage of llvm.va_copy and llvm.va_end %aq = alloca i8* @@ -20,7 +23,7 @@ define i32 @test1(i32 %X, ...) { ; Stop processing of arguments. call void @llvm.va_end(i8* %ap2) - ret i32 %tmp + ret i32* %tmp } declare void @llvm.va_start(i8*) diff --git a/test/Analysis/CFLAliasAnalysis/basic-interproc-ret.ll b/test/Analysis/CFLAliasAnalysis/basic-interproc-ret.ll deleted file mode 100644 index d56a4552b51e1..0000000000000 --- a/test/Analysis/CFLAliasAnalysis/basic-interproc-ret.ll +++ /dev/null @@ -1,26 +0,0 @@ -; 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 - -; CHECK: Function: test -; CHECK: 4 Total Alias Queries Performed -; CHECK: 3 no alias responses -; ^ The 1 MayAlias is due to %arg1. Sadly, we don't currently have machinery -; in place to check whether %arg1 aliases %a, because BasicAA takes care of -; that for us. - -define i32* @test2(i32* %arg1) { - store i32 0, i32* %arg1 - - %a = alloca i32, align 4 - ret i32* %a -} - -define void @test() { - %a = alloca i32, align 4 - %b = alloca i32, align 4 - %c = call i32* @test2(i32* %a) - - ret void -} diff --git a/test/Analysis/CFLAliasAnalysis/basic-interproc.ll b/test/Analysis/CFLAliasAnalysis/basic-interproc.ll deleted file mode 100644 index d6515eb9ebe51..0000000000000 --- a/test/Analysis/CFLAliasAnalysis/basic-interproc.ll +++ /dev/null @@ -1,24 +0,0 @@ -; This testcase ensures that CFL AA gives conservative answers on variables -; that involve arguments. - -; 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 -; CHECK: 1 no alias responses -; ^^ In @test2, %arg1 and %arg2 may alias - -define void @test2(i32* %arg1, i32* %arg2) { - store i32 0, i32* %arg1 - store i32 0, i32* %arg2 - - ret void -} - -define void @test() { - %a = alloca i32, align 4 - %b = alloca i32, align 4 - call void @test2(i32* %a, i32* %b) - - ret void -} diff --git a/test/Analysis/CallGraph/no-intrinsics.ll b/test/Analysis/CallGraph/no-intrinsics.ll index d858907d7247b..69bfce7791851 100644 --- a/test/Analysis/CallGraph/no-intrinsics.ll +++ b/test/Analysis/CallGraph/no-intrinsics.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -print-callgraph -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -passes=print-callgraph -disable-output 2>&1 | FileCheck %s ; Check that intrinsics aren't added to the call graph diff --git a/test/Analysis/CostModel/AArch64/kryo.ll b/test/Analysis/CostModel/AArch64/kryo.ll new file mode 100644 index 0000000000000..4b916a286ea09 --- /dev/null +++ b/test/Analysis/CostModel/AArch64/kryo.ll @@ -0,0 +1,26 @@ +; RUN: opt < %s -cost-model -analyze -mcpu=kryo | FileCheck %s + +target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux-gnu" + +; CHECK-LABEL: vectorInstrCost +define void @vectorInstrCost() { + + ; Vector extracts - extracting the first element should have a zero cost; + ; all other elements should have a cost of two. + ; + ; CHECK: cost of 0 {{.*}} extractelement <2 x i64> undef, i32 0 + ; CHECK: cost of 2 {{.*}} extractelement <2 x i64> undef, i32 1 + %t1 = extractelement <2 x i64> undef, i32 0 + %t2 = extractelement <2 x i64> undef, i32 1 + + ; Vector inserts - inserting the first element should have a zero cost; all + ; other elements should have a cost of two. + ; + ; CHECK: cost of 0 {{.*}} insertelement <2 x i64> undef, i64 undef, i32 0 + ; CHECK: cost of 2 {{.*}} insertelement <2 x i64> undef, i64 undef, i32 1 + %t3 = insertelement <2 x i64> undef, i64 undef, i32 0 + %t4 = insertelement <2 x i64> undef, i64 undef, i32 1 + + ret void +} diff --git a/test/Analysis/CostModel/AMDGPU/add-sub.ll b/test/Analysis/CostModel/AMDGPU/add-sub.ll new file mode 100644 index 0000000000000..76b21d26faaa4 --- /dev/null +++ b/test/Analysis/CostModel/AMDGPU/add-sub.ll @@ -0,0 +1,138 @@ +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mattr=+half-rate-64-ops < %s | FileCheck %s +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mattr=-half-rate-64-ops < %s | FileCheck %s + +; CHECK: 'add_i32' +; CHECK: estimated cost of 1 for {{.*}} add i32 +define void @add_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %vaddr, i32 %b) #0 { + %vec = load i32, i32 addrspace(1)* %vaddr + %add = add i32 %vec, %b + store i32 %add, i32 addrspace(1)* %out + ret void +} + +; CHECK: 'add_v2i32' +; CHECK: estimated cost of 2 for {{.*}} add <2 x i32> +define void @add_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32> addrspace(1)* %vaddr, <2 x i32> %b) #0 { + %vec = load <2 x i32>, <2 x i32> addrspace(1)* %vaddr + %add = add <2 x i32> %vec, %b + store <2 x i32> %add, <2 x i32> addrspace(1)* %out + ret void +} + +; CHECK: 'add_v3i32' +; CHECK: estimated cost of 3 for {{.*}} add <3 x i32> +define void @add_v3i32(<3 x i32> addrspace(1)* %out, <3 x i32> addrspace(1)* %vaddr, <3 x i32> %b) #0 { + %vec = load <3 x i32>, <3 x i32> addrspace(1)* %vaddr + %add = add <3 x i32> %vec, %b + store <3 x i32> %add, <3 x i32> addrspace(1)* %out + ret void +} + +; CHECK: 'add_v4i32' +; CHECK: estimated cost of 4 for {{.*}} add <4 x i32> +define void @add_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32> addrspace(1)* %vaddr, <4 x i32> %b) #0 { + %vec = load <4 x i32>, <4 x i32> addrspace(1)* %vaddr + %add = add <4 x i32> %vec, %b + store <4 x i32> %add, <4 x i32> addrspace(1)* %out + ret void +} + +; CHECK: 'add_i64' +; CHECK: estimated cost of 2 for {{.*}} add i64 +define void @add_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %vaddr, i64 %b) #0 { + %vec = load i64, i64 addrspace(1)* %vaddr + %add = add i64 %vec, %b + store i64 %add, i64 addrspace(1)* %out + ret void +} + +; CHECK: 'add_v2i64' +; CHECK: estimated cost of 4 for {{.*}} add <2 x i64> +define void @add_v2i64(<2 x i64> addrspace(1)* %out, <2 x i64> addrspace(1)* %vaddr, <2 x i64> %b) #0 { + %vec = load <2 x i64>, <2 x i64> addrspace(1)* %vaddr + %add = add <2 x i64> %vec, %b + store <2 x i64> %add, <2 x i64> addrspace(1)* %out + ret void +} + +; CHECK: 'add_v3i64' +; CHECK: estimated cost of 6 for {{.*}} add <3 x i64> +define void @add_v3i64(<3 x i64> addrspace(1)* %out, <3 x i64> addrspace(1)* %vaddr, <3 x i64> %b) #0 { + %vec = load <3 x i64>, <3 x i64> addrspace(1)* %vaddr + %add = add <3 x i64> %vec, %b + store <3 x i64> %add, <3 x i64> addrspace(1)* %out + ret void +} + +; CHECK: 'add_v4i64' +; CHECK: estimated cost of 8 for {{.*}} add <4 x i64> +define void @add_v4i64(<4 x i64> addrspace(1)* %out, <4 x i64> addrspace(1)* %vaddr, <4 x i64> %b) #0 { + %vec = load <4 x i64>, <4 x i64> addrspace(1)* %vaddr + %add = add <4 x i64> %vec, %b + store <4 x i64> %add, <4 x i64> addrspace(1)* %out + ret void +} + +; CHECK: 'add_v16i64' +; CHECK: estimated cost of 32 for {{.*}} add <16 x i64> +define void @add_v16i64(<16 x i64> addrspace(1)* %out, <16 x i64> addrspace(1)* %vaddr, <16 x i64> %b) #0 { + %vec = load <16 x i64>, <16 x i64> addrspace(1)* %vaddr + %add = add <16 x i64> %vec, %b + store <16 x i64> %add, <16 x i64> addrspace(1)* %out + ret void +} + +; CHECK: 'add_i16' +; CHECK: estimated cost of 1 for {{.*}} add i16 +define void @add_i16(i16 addrspace(1)* %out, i16 addrspace(1)* %vaddr, i16 %b) #0 { + %vec = load i16, i16 addrspace(1)* %vaddr + %add = add i16 %vec, %b + store i16 %add, i16 addrspace(1)* %out + ret void +} + +; CHECK: 'add_v2i16' +; CHECK: estimated cost of 2 for {{.*}} add <2 x i16> +define void @add_v2i16(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(1)* %vaddr, <2 x i16> %b) #0 { + %vec = load <2 x i16>, <2 x i16> addrspace(1)* %vaddr + %add = add <2 x i16> %vec, %b + store <2 x i16> %add, <2 x i16> addrspace(1)* %out + ret void +} + +; CHECK: 'sub_i32' +; CHECK: estimated cost of 1 for {{.*}} sub i32 +define void @sub_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %vaddr, i32 %b) #0 { + %vec = load i32, i32 addrspace(1)* %vaddr + %sub = sub i32 %vec, %b + store i32 %sub, i32 addrspace(1)* %out + ret void +} + +; CHECK: 'sub_i64' +; CHECK: estimated cost of 2 for {{.*}} sub i64 +define void @sub_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %vaddr, i64 %b) #0 { + %vec = load i64, i64 addrspace(1)* %vaddr + %sub = sub i64 %vec, %b + store i64 %sub, i64 addrspace(1)* %out + ret void +} +; CHECK: 'sub_i16' +; CHECK: estimated cost of 1 for {{.*}} sub i16 +define void @sub_i16(i16 addrspace(1)* %out, i16 addrspace(1)* %vaddr, i16 %b) #0 { + %vec = load i16, i16 addrspace(1)* %vaddr + %sub = sub i16 %vec, %b + store i16 %sub, i16 addrspace(1)* %out + ret void +} + +; CHECK: 'sub_v2i16' +; CHECK: estimated cost of 2 for {{.*}} sub <2 x i16> +define void @sub_v2i16(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(1)* %vaddr, <2 x i16> %b) #0 { + %vec = load <2 x i16>, <2 x i16> addrspace(1)* %vaddr + %sub = sub <2 x i16> %vec, %b + store <2 x i16> %sub, <2 x i16> addrspace(1)* %out + ret void +} + +attributes #0 = { nounwind } diff --git a/test/Analysis/CostModel/AMDGPU/addrspacecast.ll b/test/Analysis/CostModel/AMDGPU/addrspacecast.ll new file mode 100644 index 0000000000000..1f6cb85a789de --- /dev/null +++ b/test/Analysis/CostModel/AMDGPU/addrspacecast.ll @@ -0,0 +1,45 @@ +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mcpu=kaveri < %s | FileCheck %s + +; CHECK: 'addrspacecast_global_to_flat' +; CHECK: estimated cost of 0 for {{.*}} addrspacecast i8 addrspace(1)* %ptr to i8 addrspace(4)* +define i8 addrspace(4)* @addrspacecast_global_to_flat(i8 addrspace(1)* %ptr) #0 { + %cast = addrspacecast i8 addrspace(1)* %ptr to i8 addrspace(4)* + ret i8 addrspace(4)* %cast +} + +; CHECK: 'addrspacecast_global_to_flat_v2' +; CHECK: estimated cost of 0 for {{.*}} addrspacecast <2 x i8 addrspace(1)*> %ptr to <2 x i8 addrspace(4)*> +define <2 x i8 addrspace(4)*> @addrspacecast_global_to_flat_v2(<2 x i8 addrspace(1)*> %ptr) #0 { + %cast = addrspacecast <2 x i8 addrspace(1)*> %ptr to <2 x i8 addrspace(4)*> + ret <2 x i8 addrspace(4)*> %cast +} + +; CHECK: 'addrspacecast_global_to_flat_v32' +; CHECK: estimated cost of 0 for {{.*}} addrspacecast <32 x i8 addrspace(1)*> %ptr to <32 x i8 addrspace(4)*> +define <32 x i8 addrspace(4)*> @addrspacecast_global_to_flat_v32(<32 x i8 addrspace(1)*> %ptr) #0 { + %cast = addrspacecast <32 x i8 addrspace(1)*> %ptr to <32 x i8 addrspace(4)*> + ret <32 x i8 addrspace(4)*> %cast +} + +; CHECK: 'addrspacecast_local_to_flat' +; CHECK: estimated cost of 1 for {{.*}} addrspacecast i8 addrspace(3)* %ptr to i8 addrspace(4)* +define i8 addrspace(4)* @addrspacecast_local_to_flat(i8 addrspace(3)* %ptr) #0 { + %cast = addrspacecast i8 addrspace(3)* %ptr to i8 addrspace(4)* + ret i8 addrspace(4)* %cast +} + +; CHECK: 'addrspacecast_local_to_flat_v2' +; CHECK: estimated cost of 2 for {{.*}} addrspacecast <2 x i8 addrspace(3)*> %ptr to <2 x i8 addrspace(4)*> +define <2 x i8 addrspace(4)*> @addrspacecast_local_to_flat_v2(<2 x i8 addrspace(3)*> %ptr) #0 { + %cast = addrspacecast <2 x i8 addrspace(3)*> %ptr to <2 x i8 addrspace(4)*> + ret <2 x i8 addrspace(4)*> %cast +} + +; CHECK: 'addrspacecast_local_to_flat_v32' +; CHECK: estimated cost of 32 for {{.*}} addrspacecast <32 x i8 addrspace(3)*> %ptr to <32 x i8 addrspace(4)*> +define <32 x i8 addrspace(4)*> @addrspacecast_local_to_flat_v32(<32 x i8 addrspace(3)*> %ptr) #0 { + %cast = addrspacecast <32 x i8 addrspace(3)*> %ptr to <32 x i8 addrspace(4)*> + ret <32 x i8 addrspace(4)*> %cast +} + +attributes #0 = { nounwind readnone } diff --git a/test/Analysis/CostModel/AMDGPU/bit-ops.ll b/test/Analysis/CostModel/AMDGPU/bit-ops.ll new file mode 100644 index 0000000000000..a809dbd77bbf8 --- /dev/null +++ b/test/Analysis/CostModel/AMDGPU/bit-ops.ll @@ -0,0 +1,59 @@ +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa < %s | FileCheck %s + +; CHECK: 'or_i32' +; CHECK: estimated cost of 1 for {{.*}} or i32 +define void @or_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %vaddr, i32 %b) #0 { + %vec = load i32, i32 addrspace(1)* %vaddr + %or = or i32 %vec, %b + store i32 %or, i32 addrspace(1)* %out + ret void +} + +; CHECK: 'or_i64' +; CHECK: estimated cost of 2 for {{.*}} or i64 +define void @or_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %vaddr, i64 %b) #0 { + %vec = load i64, i64 addrspace(1)* %vaddr + %or = or i64 %vec, %b + store i64 %or, i64 addrspace(1)* %out + ret void +} + +; CHECK: 'xor_i32' +; CHECK: estimated cost of 1 for {{.*}} xor i32 +define void @xor_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %vaddr, i32 %b) #0 { + %vec = load i32, i32 addrspace(1)* %vaddr + %or = xor i32 %vec, %b + store i32 %or, i32 addrspace(1)* %out + ret void +} + +; CHECK: 'xor_i64' +; CHECK: estimated cost of 2 for {{.*}} xor i64 +define void @xor_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %vaddr, i64 %b) #0 { + %vec = load i64, i64 addrspace(1)* %vaddr + %or = xor i64 %vec, %b + store i64 %or, i64 addrspace(1)* %out + ret void +} + + +; CHECK: 'and_i32' +; CHECK: estimated cost of 1 for {{.*}} and i32 +define void @and_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %vaddr, i32 %b) #0 { + %vec = load i32, i32 addrspace(1)* %vaddr + %or = and i32 %vec, %b + store i32 %or, i32 addrspace(1)* %out + ret void +} + +; CHECK: 'and_i64' +; CHECK: estimated cost of 2 for {{.*}} and i64 +define void @and_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %vaddr, i64 %b) #0 { + %vec = load i64, i64 addrspace(1)* %vaddr + %or = and i64 %vec, %b + store i64 %or, i64 addrspace(1)* %out + ret void +} + + +attributes #0 = { nounwind } diff --git a/test/Analysis/CostModel/AMDGPU/fabs.ll b/test/Analysis/CostModel/AMDGPU/fabs.ll new file mode 100644 index 0000000000000..9c551ec8afe51 --- /dev/null +++ b/test/Analysis/CostModel/AMDGPU/fabs.ll @@ -0,0 +1,97 @@ +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa < %s | FileCheck %s + +; CHECK: 'fabs_f32' +; CHECK: estimated cost of 0 for {{.*}} call float @llvm.fabs.f32 +define void @fabs_f32(float addrspace(1)* %out, float addrspace(1)* %vaddr) #0 { + %vec = load float, float addrspace(1)* %vaddr + %fabs = call float @llvm.fabs.f32(float %vec) #1 + store float %fabs, float addrspace(1)* %out + ret void +} + +; CHECK: 'fabs_v2f32' +; CHECK: estimated cost of 0 for {{.*}} call <2 x float> @llvm.fabs.v2f32 +define void @fabs_v2f32(<2 x float> addrspace(1)* %out, <2 x float> addrspace(1)* %vaddr) #0 { + %vec = load <2 x float>, <2 x float> addrspace(1)* %vaddr + %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %vec) #1 + store <2 x float> %fabs, <2 x float> addrspace(1)* %out + ret void +} + +; CHECK: 'fabs_v3f32' +; CHECK: estimated cost of 0 for {{.*}} call <3 x float> @llvm.fabs.v3f32 +define void @fabs_v3f32(<3 x float> addrspace(1)* %out, <3 x float> addrspace(1)* %vaddr) #0 { + %vec = load <3 x float>, <3 x float> addrspace(1)* %vaddr + %fabs = call <3 x float> @llvm.fabs.v3f32(<3 x float> %vec) #1 + store <3 x float> %fabs, <3 x float> addrspace(1)* %out + ret void +} + +; CHECK: 'fabs_f64' +; CHECK: estimated cost of 0 for {{.*}} call double @llvm.fabs.f64 +define void @fabs_f64(double addrspace(1)* %out, double addrspace(1)* %vaddr) #0 { + %vec = load double, double addrspace(1)* %vaddr + %fabs = call double @llvm.fabs.f64(double %vec) #1 + store double %fabs, double addrspace(1)* %out + ret void +} + +; CHECK: 'fabs_v2f64' +; CHECK: estimated cost of 0 for {{.*}} call <2 x double> @llvm.fabs.v2f64 +define void @fabs_v2f64(<2 x double> addrspace(1)* %out, <2 x double> addrspace(1)* %vaddr) #0 { + %vec = load <2 x double>, <2 x double> addrspace(1)* %vaddr + %fabs = call <2 x double> @llvm.fabs.v2f64(<2 x double> %vec) #1 + store <2 x double> %fabs, <2 x double> addrspace(1)* %out + ret void +} + +; CHECK: 'fabs_v3f64' +; CHECK: estimated cost of 0 for {{.*}} call <3 x double> @llvm.fabs.v3f64 +define void @fabs_v3f64(<3 x double> addrspace(1)* %out, <3 x double> addrspace(1)* %vaddr) #0 { + %vec = load <3 x double>, <3 x double> addrspace(1)* %vaddr + %fabs = call <3 x double> @llvm.fabs.v3f64(<3 x double> %vec) #1 + store <3 x double> %fabs, <3 x double> addrspace(1)* %out + ret void +} + +; CHECK: 'fabs_f16' +; CHECK: estimated cost of 0 for {{.*}} call half @llvm.fabs.f16 +define void @fabs_f16(half addrspace(1)* %out, half addrspace(1)* %vaddr) #0 { + %vec = load half, half addrspace(1)* %vaddr + %fabs = call half @llvm.fabs.f16(half %vec) #1 + store half %fabs, half addrspace(1)* %out + ret void +} + +; CHECK: 'fabs_v2f16' +; CHECK: estimated cost of 0 for {{.*}} call <2 x half> @llvm.fabs.v2f16 +define void @fabs_v2f16(<2 x half> addrspace(1)* %out, <2 x half> addrspace(1)* %vaddr) #0 { + %vec = load <2 x half>, <2 x half> addrspace(1)* %vaddr + %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %vec) #1 + store <2 x half> %fabs, <2 x half> addrspace(1)* %out + ret void +} + +; CHECK: 'fabs_v3f16' +; CHECK: estimated cost of 0 for {{.*}} call <3 x half> @llvm.fabs.v3f16 +define void @fabs_v3f16(<3 x half> addrspace(1)* %out, <3 x half> addrspace(1)* %vaddr) #0 { + %vec = load <3 x half>, <3 x half> addrspace(1)* %vaddr + %fabs = call <3 x half> @llvm.fabs.v3f16(<3 x half> %vec) #1 + store <3 x half> %fabs, <3 x half> addrspace(1)* %out + ret void +} + +declare float @llvm.fabs.f32(float) #1 +declare <2 x float> @llvm.fabs.v2f32(<2 x float>) #1 +declare <3 x float> @llvm.fabs.v3f32(<3 x float>) #1 + +declare double @llvm.fabs.f64(double) #1 +declare <2 x double> @llvm.fabs.v2f64(<2 x double>) #1 +declare <3 x double> @llvm.fabs.v3f64(<3 x double>) #1 + +declare half @llvm.fabs.f16(half) #1 +declare <2 x half> @llvm.fabs.v2f16(<2 x half>) #1 +declare <3 x half> @llvm.fabs.v3f16(<3 x half>) #1 + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } diff --git a/test/Analysis/CostModel/AMDGPU/fadd.ll b/test/Analysis/CostModel/AMDGPU/fadd.ll new file mode 100644 index 0000000000000..00e91bd6223aa --- /dev/null +++ b/test/Analysis/CostModel/AMDGPU/fadd.ll @@ -0,0 +1,88 @@ +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mattr=+half-rate-64-ops < %s | FileCheck -check-prefix=FASTF64 -check-prefix=ALL %s +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mattr=-half-rate-64-ops < %s | FileCheck -check-prefix=SLOWF64 -check-prefix=ALL %s + +; ALL: 'fadd_f32' +; ALL: estimated cost of 1 for {{.*}} fadd float +define void @fadd_f32(float addrspace(1)* %out, float addrspace(1)* %vaddr, float %b) #0 { + %vec = load float, float addrspace(1)* %vaddr + %add = fadd float %vec, %b + store float %add, float addrspace(1)* %out + ret void +} + +; ALL: 'fadd_v2f32' +; ALL: estimated cost of 2 for {{.*}} fadd <2 x float> +define void @fadd_v2f32(<2 x float> addrspace(1)* %out, <2 x float> addrspace(1)* %vaddr, <2 x float> %b) #0 { + %vec = load <2 x float>, <2 x float> addrspace(1)* %vaddr + %add = fadd <2 x float> %vec, %b + store <2 x float> %add, <2 x float> addrspace(1)* %out + ret void +} + +; ALL: 'fadd_v3f32' +; ALL: estimated cost of 3 for {{.*}} fadd <3 x float> +define void @fadd_v3f32(<3 x float> addrspace(1)* %out, <3 x float> addrspace(1)* %vaddr, <3 x float> %b) #0 { + %vec = load <3 x float>, <3 x float> addrspace(1)* %vaddr + %add = fadd <3 x float> %vec, %b + store <3 x float> %add, <3 x float> addrspace(1)* %out + ret void +} + +; ALL: 'fadd_f64' +; FASTF64: estimated cost of 2 for {{.*}} fadd double +; SLOWF64: estimated cost of 3 for {{.*}} fadd double +define void @fadd_f64(double addrspace(1)* %out, double addrspace(1)* %vaddr, double %b) #0 { + %vec = load double, double addrspace(1)* %vaddr + %add = fadd double %vec, %b + store double %add, double addrspace(1)* %out + ret void +} + +; ALL: 'fadd_v2f64' +; FASTF64: estimated cost of 4 for {{.*}} fadd <2 x double> +; SLOWF64: estimated cost of 6 for {{.*}} fadd <2 x double> +define void @fadd_v2f64(<2 x double> addrspace(1)* %out, <2 x double> addrspace(1)* %vaddr, <2 x double> %b) #0 { + %vec = load <2 x double>, <2 x double> addrspace(1)* %vaddr + %add = fadd <2 x double> %vec, %b + store <2 x double> %add, <2 x double> addrspace(1)* %out + ret void +} + +; ALL: 'fadd_v3f64' +; FASTF64: estimated cost of 6 for {{.*}} fadd <3 x double> +; SLOWF64: estimated cost of 9 for {{.*}} fadd <3 x double> +define void @fadd_v3f64(<3 x double> addrspace(1)* %out, <3 x double> addrspace(1)* %vaddr, <3 x double> %b) #0 { + %vec = load <3 x double>, <3 x double> addrspace(1)* %vaddr + %add = fadd <3 x double> %vec, %b + store <3 x double> %add, <3 x double> addrspace(1)* %out + ret void +} + +; ALL 'fadd_f16' +; ALL estimated cost of 1 for {{.*}} fadd half +define void @fadd_f16(half addrspace(1)* %out, half addrspace(1)* %vaddr, half %b) #0 { + %vec = load half, half addrspace(1)* %vaddr + %add = fadd half %vec, %b + store half %add, half addrspace(1)* %out + ret void +} + +; ALL 'fadd_v2f16' +; ALL estimated cost of 2 for {{.*}} fadd <2 x half> +define void @fadd_v2f16(<2 x half> addrspace(1)* %out, <2 x half> addrspace(1)* %vaddr, <2 x half> %b) #0 { + %vec = load <2 x half>, <2 x half> addrspace(1)* %vaddr + %add = fadd <2 x half> %vec, %b + store <2 x half> %add, <2 x half> addrspace(1)* %out + ret void +} + +; ALL 'fadd_v4f16' +; ALL estimated cost of 4 for {{.*}} fadd <4 x half> +define void @fadd_v4f16(<4 x half> addrspace(1)* %out, <4 x half> addrspace(1)* %vaddr, <4 x half> %b) #0 { + %vec = load <4 x half>, <4 x half> addrspace(1)* %vaddr + %add = fadd <4 x half> %vec, %b + store <4 x half> %add, <4 x half> addrspace(1)* %out + ret void +} + +attributes #0 = { nounwind } diff --git a/test/Analysis/CostModel/AMDGPU/fdiv.ll b/test/Analysis/CostModel/AMDGPU/fdiv.ll new file mode 100644 index 0000000000000..3f374422ad9d1 --- /dev/null +++ b/test/Analysis/CostModel/AMDGPU/fdiv.ll @@ -0,0 +1,96 @@ +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mcpu=hawaii -mattr=+half-rate-64-ops < %s | FileCheck -check-prefix=ALL -check-prefix=CIFASTF64 %s +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mcpu=kaveri -mattr=-half-rate-64-ops < %s | FileCheck -check-prefix=ALL -check-prefix=CISLOWF64 %s +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mcpu=tahiti -mattr=+half-rate-64-ops < %s | FileCheck -check-prefix=ALL -check-prefix=SIFASTF64 %s +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mcpu=verde -mattr=-half-rate-64-ops < %s | FileCheck -check-prefix=ALL -check-prefix=SISLOWF64 %s + +; CHECK: 'fdiv_f32' +; ALL: estimated cost of 10 for {{.*}} fdiv float +define void @fdiv_f32(float addrspace(1)* %out, float addrspace(1)* %vaddr, float %b) #0 { + %vec = load float, float addrspace(1)* %vaddr + %add = fdiv float %vec, %b + store float %add, float addrspace(1)* %out + ret void +} + +; ALL: 'fdiv_v2f32' +; ALL: estimated cost of 20 for {{.*}} fdiv <2 x float> +define void @fdiv_v2f32(<2 x float> addrspace(1)* %out, <2 x float> addrspace(1)* %vaddr, <2 x float> %b) #0 { + %vec = load <2 x float>, <2 x float> addrspace(1)* %vaddr + %add = fdiv <2 x float> %vec, %b + store <2 x float> %add, <2 x float> addrspace(1)* %out + ret void +} + +; ALL: 'fdiv_v3f32' +; ALL: estimated cost of 30 for {{.*}} fdiv <3 x float> +define void @fdiv_v3f32(<3 x float> addrspace(1)* %out, <3 x float> addrspace(1)* %vaddr, <3 x float> %b) #0 { + %vec = load <3 x float>, <3 x float> addrspace(1)* %vaddr + %add = fdiv <3 x float> %vec, %b + store <3 x float> %add, <3 x float> addrspace(1)* %out + ret void +} + +; ALL: 'fdiv_f64' +; CIFASTF64: estimated cost of 29 for {{.*}} fdiv double +; CISLOWF64: estimated cost of 33 for {{.*}} fdiv double +; SIFASTF64: estimated cost of 32 for {{.*}} fdiv double +; SISLOWF64: estimated cost of 36 for {{.*}} fdiv double +define void @fdiv_f64(double addrspace(1)* %out, double addrspace(1)* %vaddr, double %b) #0 { + %vec = load double, double addrspace(1)* %vaddr + %add = fdiv double %vec, %b + store double %add, double addrspace(1)* %out + ret void +} + +; ALL: 'fdiv_v2f64' +; CIFASTF64: estimated cost of 58 for {{.*}} fdiv <2 x double> +; CISLOWF64: estimated cost of 66 for {{.*}} fdiv <2 x double> +; SIFASTF64: estimated cost of 64 for {{.*}} fdiv <2 x double> +; SISLOWF64: estimated cost of 72 for {{.*}} fdiv <2 x double> +define void @fdiv_v2f64(<2 x double> addrspace(1)* %out, <2 x double> addrspace(1)* %vaddr, <2 x double> %b) #0 { + %vec = load <2 x double>, <2 x double> addrspace(1)* %vaddr + %add = fdiv <2 x double> %vec, %b + store <2 x double> %add, <2 x double> addrspace(1)* %out + ret void +} + +; ALL: 'fdiv_v3f64' +; CIFASTF64: estimated cost of 87 for {{.*}} fdiv <3 x double> +; CISLOWF64: estimated cost of 99 for {{.*}} fdiv <3 x double> +; SIFASTF64: estimated cost of 96 for {{.*}} fdiv <3 x double> +; SISLOWF64: estimated cost of 108 for {{.*}} fdiv <3 x double> +define void @fdiv_v3f64(<3 x double> addrspace(1)* %out, <3 x double> addrspace(1)* %vaddr, <3 x double> %b) #0 { + %vec = load <3 x double>, <3 x double> addrspace(1)* %vaddr + %add = fdiv <3 x double> %vec, %b + store <3 x double> %add, <3 x double> addrspace(1)* %out + ret void +} + +; ALL: 'fdiv_f16' +; ALL: estimated cost of 10 for {{.*}} fdiv half +define void @fdiv_f16(half addrspace(1)* %out, half addrspace(1)* %vaddr, half %b) #0 { + %vec = load half, half addrspace(1)* %vaddr + %add = fdiv half %vec, %b + store half %add, half addrspace(1)* %out + ret void +} + +; ALL: 'fdiv_v2f16' +; ALL: estimated cost of 20 for {{.*}} fdiv <2 x half> +define void @fdiv_v2f16(<2 x half> addrspace(1)* %out, <2 x half> addrspace(1)* %vaddr, <2 x half> %b) #0 { + %vec = load <2 x half>, <2 x half> addrspace(1)* %vaddr + %add = fdiv <2 x half> %vec, %b + store <2 x half> %add, <2 x half> addrspace(1)* %out + ret void +} + +; ALL: 'fdiv_v4f16' +; ALL: estimated cost of 40 for {{.*}} fdiv <4 x half> +define void @fdiv_v4f16(<4 x half> addrspace(1)* %out, <4 x half> addrspace(1)* %vaddr, <4 x half> %b) #0 { + %vec = load <4 x half>, <4 x half> addrspace(1)* %vaddr + %add = fdiv <4 x half> %vec, %b + store <4 x half> %add, <4 x half> addrspace(1)* %out + ret void +} + +attributes #0 = { nounwind } diff --git a/test/Analysis/CostModel/AMDGPU/fmul.ll b/test/Analysis/CostModel/AMDGPU/fmul.ll new file mode 100644 index 0000000000000..6303bb7988c54 --- /dev/null +++ b/test/Analysis/CostModel/AMDGPU/fmul.ll @@ -0,0 +1,88 @@ +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mattr=+half-rate-64-ops < %s | FileCheck -check-prefix=FASTF64 -check-prefix=ALL %s +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mattr=-half-rate-64-ops < %s | FileCheck -check-prefix=SLOWF64 -check-prefix=ALL %s + +; ALL: 'fmul_f32' +; ALL: estimated cost of 1 for {{.*}} fmul float +define void @fmul_f32(float addrspace(1)* %out, float addrspace(1)* %vaddr, float %b) #0 { + %vec = load float, float addrspace(1)* %vaddr + %add = fmul float %vec, %b + store float %add, float addrspace(1)* %out + ret void +} + +; ALL: 'fmul_v2f32' +; ALL: estimated cost of 2 for {{.*}} fmul <2 x float> +define void @fmul_v2f32(<2 x float> addrspace(1)* %out, <2 x float> addrspace(1)* %vaddr, <2 x float> %b) #0 { + %vec = load <2 x float>, <2 x float> addrspace(1)* %vaddr + %add = fmul <2 x float> %vec, %b + store <2 x float> %add, <2 x float> addrspace(1)* %out + ret void +} + +; ALL: 'fmul_v3f32' +; ALL: estimated cost of 3 for {{.*}} fmul <3 x float> +define void @fmul_v3f32(<3 x float> addrspace(1)* %out, <3 x float> addrspace(1)* %vaddr, <3 x float> %b) #0 { + %vec = load <3 x float>, <3 x float> addrspace(1)* %vaddr + %add = fmul <3 x float> %vec, %b + store <3 x float> %add, <3 x float> addrspace(1)* %out + ret void +} + +; ALL: 'fmul_f64' +; FASTF64: estimated cost of 2 for {{.*}} fmul double +; SLOWF64: estimated cost of 3 for {{.*}} fmul double +define void @fmul_f64(double addrspace(1)* %out, double addrspace(1)* %vaddr, double %b) #0 { + %vec = load double, double addrspace(1)* %vaddr + %add = fmul double %vec, %b + store double %add, double addrspace(1)* %out + ret void +} + +; ALL: 'fmul_v2f64' +; FASTF64: estimated cost of 4 for {{.*}} fmul <2 x double> +; SLOWF64: estimated cost of 6 for {{.*}} fmul <2 x double> +define void @fmul_v2f64(<2 x double> addrspace(1)* %out, <2 x double> addrspace(1)* %vaddr, <2 x double> %b) #0 { + %vec = load <2 x double>, <2 x double> addrspace(1)* %vaddr + %add = fmul <2 x double> %vec, %b + store <2 x double> %add, <2 x double> addrspace(1)* %out + ret void +} + +; ALL: 'fmul_v3f64' +; FASTF64: estimated cost of 6 for {{.*}} fmul <3 x double> +; SLOWF64: estimated cost of 9 for {{.*}} fmul <3 x double> +define void @fmul_v3f64(<3 x double> addrspace(1)* %out, <3 x double> addrspace(1)* %vaddr, <3 x double> %b) #0 { + %vec = load <3 x double>, <3 x double> addrspace(1)* %vaddr + %add = fmul <3 x double> %vec, %b + store <3 x double> %add, <3 x double> addrspace(1)* %out + ret void +} + +; ALL 'fmul_f16' +; ALL estimated cost of 1 for {{.*}} fmul half +define void @fmul_f16(half addrspace(1)* %out, half addrspace(1)* %vaddr, half %b) #0 { + %vec = load half, half addrspace(1)* %vaddr + %add = fmul half %vec, %b + store half %add, half addrspace(1)* %out + ret void +} + +; ALL 'fmul_v2f16' +; ALL estimated cost of 2 for {{.*}} fmul <2 x half> +define void @fmul_v2f16(<2 x half> addrspace(1)* %out, <2 x half> addrspace(1)* %vaddr, <2 x half> %b) #0 { + %vec = load <2 x half>, <2 x half> addrspace(1)* %vaddr + %add = fmul <2 x half> %vec, %b + store <2 x half> %add, <2 x half> addrspace(1)* %out + ret void +} + +; ALL 'fmul_v4f16' +; ALL estimated cost of 4 for {{.*}} fmul <4 x half> +define void @fmul_v4f16(<4 x half> addrspace(1)* %out, <4 x half> addrspace(1)* %vaddr, <4 x half> %b) #0 { + %vec = load <4 x half>, <4 x half> addrspace(1)* %vaddr + %add = fmul <4 x half> %vec, %b + store <4 x half> %add, <4 x half> addrspace(1)* %out + ret void +} + +attributes #0 = { nounwind } diff --git a/test/Analysis/CostModel/AMDGPU/fsub.ll b/test/Analysis/CostModel/AMDGPU/fsub.ll new file mode 100644 index 0000000000000..e0850be9867ea --- /dev/null +++ b/test/Analysis/CostModel/AMDGPU/fsub.ll @@ -0,0 +1,86 @@ +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mattr=+half-rate-64-ops < %s | FileCheck -check-prefix=FASTF64 -check-prefix=ALL %s +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mattr=-half-rate-64-ops < %s | FileCheck -check-prefix=SLOWF64 -check-prefix=ALL %s + +; ALL: 'fsub_f32' +; ALL: estimated cost of 1 for {{.*}} fsub float +define void @fsub_f32(float addrspace(1)* %out, float addrspace(1)* %vaddr, float %b) #0 { + %vec = load float, float addrspace(1)* %vaddr + %add = fsub float %vec, %b + store float %add, float addrspace(1)* %out + ret void +} + +; ALL: 'fsub_v2f32' +; ALL: estimated cost of 2 for {{.*}} fsub <2 x float> +define void @fsub_v2f32(<2 x float> addrspace(1)* %out, <2 x float> addrspace(1)* %vaddr, <2 x float> %b) #0 { + %vec = load <2 x float>, <2 x float> addrspace(1)* %vaddr + %add = fsub <2 x float> %vec, %b + store <2 x float> %add, <2 x float> addrspace(1)* %out + ret void +} + +; ALL: 'fsub_v3f32' +; ALL: estimated cost of 3 for {{.*}} fsub <3 x float> +define void @fsub_v3f32(<3 x float> addrspace(1)* %out, <3 x float> addrspace(1)* %vaddr, <3 x float> %b) #0 { + %vec = load <3 x float>, <3 x float> addrspace(1)* %vaddr + %add = fsub <3 x float> %vec, %b + store <3 x float> %add, <3 x float> addrspace(1)* %out + ret void +} + +; ALL: 'fsub_f64' +; FASTF64: estimated cost of 2 for {{.*}} fsub double +; SLOWF64: estimated cost of 3 for {{.*}} fsub double +define void @fsub_f64(double addrspace(1)* %out, double addrspace(1)* %vaddr, double %b) #0 { + %vec = load double, double addrspace(1)* %vaddr + %add = fsub double %vec, %b + store double %add, double addrspace(1)* %out + ret void +} + +; ALL: 'fsub_v2f64' +; FASTF64: estimated cost of 4 for {{.*}} fsub <2 x double> +; SLOWF64: estimated cost of 6 for {{.*}} fsub <2 x double> +define void @fsub_v2f64(<2 x double> addrspace(1)* %out, <2 x double> addrspace(1)* %vaddr, <2 x double> %b) #0 { + %vec = load <2 x double>, <2 x double> addrspace(1)* %vaddr + %add = fsub <2 x double> %vec, %b + store <2 x double> %add, <2 x double> addrspace(1)* %out + ret void +} + +; ALL: 'fsub_v3f64' +; FASTF64: estimated cost of 6 for {{.*}} fsub <3 x double> +; SLOWF64: estimated cost of 9 for {{.*}} fsub <3 x double> +define void @fsub_v3f64(<3 x double> addrspace(1)* %out, <3 x double> addrspace(1)* %vaddr, <3 x double> %b) #0 { + %vec = load <3 x double>, <3 x double> addrspace(1)* %vaddr + %add = fsub <3 x double> %vec, %b + store <3 x double> %add, <3 x double> addrspace(1)* %out + ret void +} + +; ALL: 'fsub_f16' +; ALL: estimated cost of 1 for {{.*}} fsub half +define void @fsub_f16(half addrspace(1)* %out, half addrspace(1)* %vaddr, half %b) #0 { + %vec = load half, half addrspace(1)* %vaddr + %add = fsub half %vec, %b + store half %add, half addrspace(1)* %out + ret void +} + +; ALL: 'fsub_v2f16' +; ALL: estimated cost of 2 for {{.*}} fsub <2 x half> +define void @fsub_v2f16(<2 x half> addrspace(1)* %out, <2 x half> addrspace(1)* %vaddr, <2 x half> %b) #0 { + %vec = load <2 x half>, <2 x half> addrspace(1)* %vaddr + %add = fsub <2 x half> %vec, %b + store <2 x half> %add, <2 x half> addrspace(1)* %out + ret void +} + +; ALL: 'fsub_v4f16' +; ALL: estimated cost of 4 for {{.*}} fsub <4 x half> +define void @fsub_v4f16(<4 x half> addrspace(1)* %out, <4 x half> addrspace(1)* %vaddr, <4 x half> %b) #0 { + %vec = load <4 x half>, <4 x half> addrspace(1)* %vaddr + %add = fsub <4 x half> %vec, %b + store <4 x half> %add, <4 x half> addrspace(1)* %out + ret void +} diff --git a/test/Analysis/CostModel/AMDGPU/insertelement.ll b/test/Analysis/CostModel/AMDGPU/insertelement.ll new file mode 100644 index 0000000000000..1765afe3169e1 --- /dev/null +++ b/test/Analysis/CostModel/AMDGPU/insertelement.ll @@ -0,0 +1,37 @@ +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa < %s | FileCheck %s + +; CHECK: 'insertelement_v2i32' +; CHECK: estimated cost of 0 for {{.*}} insertelement <2 x i32> +define void @insertelement_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32> addrspace(1)* %vaddr) { + %vec = load <2 x i32>, <2 x i32> addrspace(1)* %vaddr + %insert = insertelement <2 x i32> %vec, i32 1, i32 123 + store <2 x i32> %insert, <2 x i32> addrspace(1)* %out + ret void +} + +; CHECK: 'insertelement_v2i64' +; CHECK: estimated cost of 0 for {{.*}} insertelement <2 x i64> +define void @insertelement_v2i64(<2 x i64> addrspace(1)* %out, <2 x i64> addrspace(1)* %vaddr) { + %vec = load <2 x i64>, <2 x i64> addrspace(1)* %vaddr + %insert = insertelement <2 x i64> %vec, i64 1, i64 123 + store <2 x i64> %insert, <2 x i64> addrspace(1)* %out + ret void +} + +; CHECK: 'insertelement_v2i16' +; CHECK: estimated cost of 0 for {{.*}} insertelement <2 x i16> +define void @insertelement_v2i16(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(1)* %vaddr) { + %vec = load <2 x i16>, <2 x i16> addrspace(1)* %vaddr + %insert = insertelement <2 x i16> %vec, i16 1, i16 123 + store <2 x i16> %insert, <2 x i16> addrspace(1)* %out + ret void +} + +; CHECK: 'insertelement_v2i8' +; CHECK: estimated cost of 0 for {{.*}} insertelement <2 x i8> +define void @insertelement_v2i8(<2 x i8> addrspace(1)* %out, <2 x i8> addrspace(1)* %vaddr) { + %vec = load <2 x i8>, <2 x i8> addrspace(1)* %vaddr + %insert = insertelement <2 x i8> %vec, i8 1, i8 123 + store <2 x i8> %insert, <2 x i8> addrspace(1)* %out + ret void +} diff --git a/test/Analysis/CostModel/AMDGPU/mul.ll b/test/Analysis/CostModel/AMDGPU/mul.ll new file mode 100644 index 0000000000000..cbc755a6e6a97 --- /dev/null +++ b/test/Analysis/CostModel/AMDGPU/mul.ll @@ -0,0 +1,85 @@ +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa < %s | FileCheck %s + +; CHECK: 'mul_i32' +; CHECK: estimated cost of 3 for {{.*}} mul i32 +define void @mul_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %vaddr, i32 %b) #0 { + %vec = load i32, i32 addrspace(1)* %vaddr + %mul = mul i32 %vec, %b + store i32 %mul, i32 addrspace(1)* %out + ret void +} + +; CHECK: 'mul_v2i32' +; CHECK: estimated cost of 6 for {{.*}} mul <2 x i32> +define void @mul_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32> addrspace(1)* %vaddr, <2 x i32> %b) #0 { + %vec = load <2 x i32>, <2 x i32> addrspace(1)* %vaddr + %mul = mul <2 x i32> %vec, %b + store <2 x i32> %mul, <2 x i32> addrspace(1)* %out + ret void +} + +; CHECK: 'mul_v3i32' +; CHECK: estimated cost of 9 for {{.*}} mul <3 x i32> +define void @mul_v3i32(<3 x i32> addrspace(1)* %out, <3 x i32> addrspace(1)* %vaddr, <3 x i32> %b) #0 { + %vec = load <3 x i32>, <3 x i32> addrspace(1)* %vaddr + %mul = mul <3 x i32> %vec, %b + store <3 x i32> %mul, <3 x i32> addrspace(1)* %out + ret void +} + +; CHECK: 'mul_v4i32' +; CHECK: estimated cost of 12 for {{.*}} mul <4 x i32> +define void @mul_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32> addrspace(1)* %vaddr, <4 x i32> %b) #0 { + %vec = load <4 x i32>, <4 x i32> addrspace(1)* %vaddr + %mul = mul <4 x i32> %vec, %b + store <4 x i32> %mul, <4 x i32> addrspace(1)* %out + ret void +} + +; CHECK: 'mul_i64' +; CHECK: estimated cost of 16 for {{.*}} mul i64 +define void @mul_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %vaddr, i64 %b) #0 { + %vec = load i64, i64 addrspace(1)* %vaddr + %mul = mul i64 %vec, %b + store i64 %mul, i64 addrspace(1)* %out + ret void +} + +; CHECK: 'mul_v2i64' +; CHECK: estimated cost of 32 for {{.*}} mul <2 x i64> +define void @mul_v2i64(<2 x i64> addrspace(1)* %out, <2 x i64> addrspace(1)* %vaddr, <2 x i64> %b) #0 { + %vec = load <2 x i64>, <2 x i64> addrspace(1)* %vaddr + %mul = mul <2 x i64> %vec, %b + store <2 x i64> %mul, <2 x i64> addrspace(1)* %out + ret void +} + +; CHECK: 'mul_v3i64' +; CHECK: estimated cost of 48 for {{.*}} mul <3 x i64> +define void @mul_v3i64(<3 x i64> addrspace(1)* %out, <3 x i64> addrspace(1)* %vaddr, <3 x i64> %b) #0 { + %vec = load <3 x i64>, <3 x i64> addrspace(1)* %vaddr + %mul = mul <3 x i64> %vec, %b + store <3 x i64> %mul, <3 x i64> addrspace(1)* %out + ret void +} + +; CHECK: 'mul_v4i64' +; CHECK: estimated cost of 64 for {{.*}} mul <4 x i64> +define void @mul_v4i64(<4 x i64> addrspace(1)* %out, <4 x i64> addrspace(1)* %vaddr, <4 x i64> %b) #0 { + %vec = load <4 x i64>, <4 x i64> addrspace(1)* %vaddr + %mul = mul <4 x i64> %vec, %b + store <4 x i64> %mul, <4 x i64> addrspace(1)* %out + ret void +} + + +; CHECK: 'mul_v8i64' +; CHECK: estimated cost of 128 for {{.*}} mul <8 x i64> +define void @mul_v8i64(<8 x i64> addrspace(1)* %out, <8 x i64> addrspace(1)* %vaddr, <8 x i64> %b) #0 { + %vec = load <8 x i64>, <8 x i64> addrspace(1)* %vaddr + %mul = mul <8 x i64> %vec, %b + store <8 x i64> %mul, <8 x i64> addrspace(1)* %out + ret void +} + +attributes #0 = { nounwind } diff --git a/test/Analysis/CostModel/AMDGPU/shifts.ll b/test/Analysis/CostModel/AMDGPU/shifts.ll new file mode 100644 index 0000000000000..003aed7b2fc8e --- /dev/null +++ b/test/Analysis/CostModel/AMDGPU/shifts.ll @@ -0,0 +1,61 @@ +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mattr=+half-rate-64-ops < %s | FileCheck -check-prefix=ALL -check-prefix=FAST64 %s +; RUN: opt -cost-model -analyze -mtriple=amdgcn-unknown-amdhsa -mattr=-half-rate-64-ops < %s | FileCheck -check-prefix=ALL -check-prefix=SLOW64 %s + +; ALL: 'shl_i32' +; ALL: estimated cost of 1 for {{.*}} shl i32 +define void @shl_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %vaddr, i32 %b) #0 { + %vec = load i32, i32 addrspace(1)* %vaddr + %or = shl i32 %vec, %b + store i32 %or, i32 addrspace(1)* %out + ret void +} + +; ALL: 'shl_i64' +; FAST64: estimated cost of 2 for {{.*}} shl i64 +; SLOW64: estimated cost of 3 for {{.*}} shl i64 +define void @shl_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %vaddr, i64 %b) #0 { + %vec = load i64, i64 addrspace(1)* %vaddr + %or = shl i64 %vec, %b + store i64 %or, i64 addrspace(1)* %out + ret void +} + +; ALL: 'lshr_i32' +; ALL: estimated cost of 1 for {{.*}} lshr i32 +define void @lshr_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %vaddr, i32 %b) #0 { + %vec = load i32, i32 addrspace(1)* %vaddr + %or = lshr i32 %vec, %b + store i32 %or, i32 addrspace(1)* %out + ret void +} + +; ALL: 'lshr_i64' +; FAST64: estimated cost of 2 for {{.*}} lshr i64 +; SLOW64: estimated cost of 3 for {{.*}} lshr i64 +define void @lshr_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %vaddr, i64 %b) #0 { + %vec = load i64, i64 addrspace(1)* %vaddr + %or = lshr i64 %vec, %b + store i64 %or, i64 addrspace(1)* %out + ret void +} + +; ALL: 'ashr_i32' +; ALL: estimated cost of 1 for {{.*}} ashr i32 +define void @ashr_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %vaddr, i32 %b) #0 { + %vec = load i32, i32 addrspace(1)* %vaddr + %or = ashr i32 %vec, %b + store i32 %or, i32 addrspace(1)* %out + ret void +} + +; ALL: 'ashr_i64' +; FAST64: estimated cost of 2 for {{.*}} ashr i64 +; SLOW64: estimated cost of 3 for {{.*}} ashr i64 +define void @ashr_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %vaddr, i64 %b) #0 { + %vec = load i64, i64 addrspace(1)* %vaddr + %or = ashr i64 %vec, %b + store i64 %or, i64 addrspace(1)* %out + ret void +} + +attributes #0 = { nounwind } diff --git a/test/Analysis/CostModel/ARM/cast.ll b/test/Analysis/CostModel/ARM/cast.ll index 21e2928220998..72308834c5359 100644 --- a/test/Analysis/CostModel/ARM/cast.ll +++ b/test/Analysis/CostModel/ARM/cast.ll @@ -264,39 +264,39 @@ define i32 @casts() { %r116 = fptoui <4 x float> undef to <4 x i32> ; 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: Found an estimated cost of 64 for instruction: %r118 = fptoui <4 x float> undef to <4 x i64> + ; CHECK: Found an estimated cost of 65 for instruction: %r118 = fptoui <4 x float> undef to <4 x i64> %r118 = fptoui <4 x float> undef to <4 x i64> - ; CHECK: Found an estimated cost of 64 for instruction: %r119 = fptosi <4 x float> undef to <4 x i64> + ; CHECK: Found an estimated cost of 65 for instruction: %r119 = fptosi <4 x float> undef to <4 x i64> %r119 = fptosi <4 x float> undef to <4 x i64> - ; CHECK: Found an estimated cost of 32 for instruction: %r120 = fptoui <4 x double> undef to <4 x i1> + ; CHECK: Found an estimated cost of 33 for instruction: %r120 = fptoui <4 x double> undef to <4 x i1> %r120 = fptoui <4 x double> undef to <4 x i1> - ; CHECK: Found an estimated cost of 32 for instruction: %r121 = fptosi <4 x double> undef to <4 x i1> + ; CHECK: Found an estimated cost of 33 for instruction: %r121 = fptosi <4 x double> undef to <4 x i1> %r121 = fptosi <4 x double> undef to <4 x i1> - ; CHECK: Found an estimated cost of 32 for instruction: %r122 = fptoui <4 x double> undef to <4 x i8> + ; CHECK: Found an estimated cost of 33 for instruction: %r122 = fptoui <4 x double> undef to <4 x i8> %r122 = fptoui <4 x double> undef to <4 x i8> - ; CHECK: Found an estimated cost of 32 for instruction: %r123 = fptosi <4 x double> undef to <4 x i8> + ; CHECK: Found an estimated cost of 33 for instruction: %r123 = fptosi <4 x double> undef to <4 x i8> %r123 = fptosi <4 x double> undef to <4 x i8> - ; CHECK: Found an estimated cost of 32 for instruction: %r124 = fptoui <4 x double> undef to <4 x i16> + ; CHECK: Found an estimated cost of 33 for instruction: %r124 = fptoui <4 x double> undef to <4 x i16> %r124 = fptoui <4 x double> undef to <4 x i16> - ; CHECK: Found an estimated cost of 32 for instruction: %r125 = fptosi <4 x double> undef to <4 x i16> + ; CHECK: Found an estimated cost of 33 for instruction: %r125 = fptosi <4 x double> undef to <4 x i16> %r125 = fptosi <4 x double> undef to <4 x i16> - ; CHECK: Found an estimated cost of 32 for instruction: %r126 = fptoui <4 x double> undef to <4 x i32> + ; CHECK: Found an estimated cost of 5 for instruction: %r126 = fptoui <4 x double> undef to <4 x i32> %r126 = fptoui <4 x double> undef to <4 x i32> - ; CHECK: Found an estimated cost of 32 for instruction: %r127 = fptosi <4 x double> undef to <4 x i32> + ; CHECK: Found an estimated cost of 5 for instruction: %r127 = fptosi <4 x double> undef to <4 x i32> %r127 = fptosi <4 x double> undef to <4 x i32> - ; CHECK: Found an estimated cost of 64 for instruction: %r128 = fptoui <4 x double> undef to <4 x i64> + ; CHECK: Found an estimated cost of 65 for instruction: %r128 = fptoui <4 x double> undef to <4 x i64> %r128 = fptoui <4 x double> undef to <4 x i64> - ; CHECK: Found an estimated cost of 64 for instruction: %r129 = fptosi <4 x double> undef to <4 x i64> + ; CHECK: Found an estimated cost of 65 for instruction: %r129 = fptosi <4 x double> undef to <4 x i64> %r129 = fptosi <4 x double> undef to <4 x i64> - ; CHECK: Found an estimated cost of 64 for instruction: %r130 = fptoui <8 x float> undef to <8 x i1> + ; CHECK: Found an estimated cost of 65 for instruction: %r130 = fptoui <8 x float> undef to <8 x i1> %r130 = fptoui <8 x float> undef to <8 x i1> - ; CHECK: Found an estimated cost of 64 for instruction: %r131 = fptosi <8 x float> undef to <8 x i1> + ; CHECK: Found an estimated cost of 65 for instruction: %r131 = fptosi <8 x float> undef to <8 x i1> %r131 = fptosi <8 x float> undef to <8 x i1> - ; CHECK: Found an estimated cost of 64 for instruction: %r132 = fptoui <8 x float> undef to <8 x i8> + ; CHECK: Found an estimated cost of 7 for instruction: %r132 = fptoui <8 x float> undef to <8 x i8> %r132 = fptoui <8 x float> undef to <8 x i8> - ; CHECK: Found an estimated cost of 64 for instruction: %r133 = fptosi <8 x float> undef to <8 x i8> + ; CHECK: Found an estimated cost of 7 for instruction: %r133 = fptosi <8 x float> undef to <8 x i8> %r133 = fptosi <8 x float> undef to <8 x i8> ; 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> @@ -306,39 +306,39 @@ define i32 @casts() { %r136 = fptoui <8 x float> undef to <8 x i32> ; 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: Found an estimated cost of 128 for instruction: %r138 = fptoui <8 x float> undef to <8 x i64> + ; CHECK: Found an estimated cost of 131 for instruction: %r138 = fptoui <8 x float> undef to <8 x i64> %r138 = fptoui <8 x float> undef to <8 x i64> - ; CHECK: Found an estimated cost of 128 for instruction: %r139 = fptosi <8 x float> undef to <8 x i64> + ; CHECK: Found an estimated cost of 131 for instruction: %r139 = fptosi <8 x float> undef to <8 x i64> %r139 = fptosi <8 x float> undef to <8 x i64> - ; CHECK: Found an estimated cost of 64 for instruction: %r140 = fptoui <8 x double> undef to <8 x i1> + ; CHECK: Found an estimated cost of 67 for instruction: %r140 = fptoui <8 x double> undef to <8 x i1> %r140 = fptoui <8 x double> undef to <8 x i1> - ; CHECK: Found an estimated cost of 64 for instruction: %r141 = fptosi <8 x double> undef to <8 x i1> + ; CHECK: Found an estimated cost of 67 for instruction: %r141 = fptosi <8 x double> undef to <8 x i1> %r141 = fptosi <8 x double> undef to <8 x i1> - ; CHECK: Found an estimated cost of 64 for instruction: %r142 = fptoui <8 x double> undef to <8 x i8> + ; CHECK: Found an estimated cost of 67 for instruction: %r142 = fptoui <8 x double> undef to <8 x i8> %r142 = fptoui <8 x double> undef to <8 x i8> - ; CHECK: Found an estimated cost of 64 for instruction: %r143 = fptosi <8 x double> undef to <8 x i8> + ; CHECK: Found an estimated cost of 67 for instruction: %r143 = fptosi <8 x double> undef to <8 x i8> %r143 = fptosi <8 x double> undef to <8 x i8> - ; CHECK: Found an estimated cost of 64 for instruction: %r144 = fptoui <8 x double> undef to <8 x i16> + ; CHECK: Found an estimated cost of 67 for instruction: %r144 = fptoui <8 x double> undef to <8 x i16> %r144 = fptoui <8 x double> undef to <8 x i16> - ; CHECK: Found an estimated cost of 64 for instruction: %r145 = fptosi <8 x double> undef to <8 x i16> + ; CHECK: Found an estimated cost of 67 for instruction: %r145 = fptosi <8 x double> undef to <8 x i16> %r145 = fptosi <8 x double> undef to <8 x i16> - ; CHECK: Found an estimated cost of 64 for instruction: %r146 = fptoui <8 x double> undef to <8 x i32> + ; CHECK: Found an estimated cost of 11 for instruction: %r146 = fptoui <8 x double> undef to <8 x i32> %r146 = fptoui <8 x double> undef to <8 x i32> - ; CHECK: Found an estimated cost of 64 for instruction: %r147 = fptosi <8 x double> undef to <8 x i32> + ; CHECK: Found an estimated cost of 11 for instruction: %r147 = fptosi <8 x double> undef to <8 x i32> %r147 = fptosi <8 x double> undef to <8 x i32> - ; CHECK: Found an estimated cost of 128 for instruction: %r148 = fptoui <8 x double> undef to <8 x i64> + ; CHECK: Found an estimated cost of 131 for instruction: %r148 = fptoui <8 x double> undef to <8 x i64> %r148 = fptoui <8 x double> undef to <8 x i64> - ; CHECK: Found an estimated cost of 128 for instruction: %r149 = fptosi <8 x double> undef to <8 x i64> + ; CHECK: Found an estimated cost of 131 for instruction: %r149 = fptosi <8 x double> undef to <8 x i64> %r149 = fptosi <8 x double> undef to <8 x i64> - ; CHECK: Found an estimated cost of 128 for instruction: %r150 = fptoui <16 x float> undef to <16 x i1> + ; CHECK: Found an estimated cost of 131 for instruction: %r150 = fptoui <16 x float> undef to <16 x i1> %r150 = fptoui <16 x float> undef to <16 x i1> - ; CHECK: Found an estimated cost of 128 for instruction: %r151 = fptosi <16 x float> undef to <16 x i1> + ; CHECK: Found an estimated cost of 131 for instruction: %r151 = fptosi <16 x float> undef to <16 x i1> %r151 = fptosi <16 x float> undef to <16 x i1> - ; CHECK: Found an estimated cost of 128 for instruction: %r152 = fptoui <16 x float> undef to <16 x i8> + ; CHECK: Found an estimated cost of 15 for instruction: %r152 = fptoui <16 x float> undef to <16 x i8> %r152 = fptoui <16 x float> undef to <16 x i8> - ; CHECK: Found an estimated cost of 128 for instruction: %r153 = fptosi <16 x float> undef to <16 x i8> + ; CHECK: Found an estimated cost of 15 for instruction: %r153 = fptosi <16 x float> undef to <16 x i8> %r153 = fptosi <16 x float> undef to <16 x i8> ; 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> @@ -348,30 +348,30 @@ define i32 @casts() { %r156 = fptoui <16 x float> undef to <16 x i32> ; 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: Found an estimated cost of 256 for instruction: %r158 = fptoui <16 x float> undef to <16 x i64> + ; CHECK: Found an estimated cost of 263 for instruction: %r158 = fptoui <16 x float> undef to <16 x i64> %r158 = fptoui <16 x float> undef to <16 x i64> - ; CHECK: Found an estimated cost of 256 for instruction: %r159 = fptosi <16 x float> undef to <16 x i64> + ; CHECK: Found an estimated cost of 263 for instruction: %r159 = fptosi <16 x float> undef to <16 x i64> %r159 = fptosi <16 x float> undef to <16 x i64> - ; CHECK: Found an estimated cost of 128 for instruction: %r160 = fptoui <16 x double> undef to <16 x i1> + ; CHECK: Found an estimated cost of 135 for instruction: %r160 = fptoui <16 x double> undef to <16 x i1> %r160 = fptoui <16 x double> undef to <16 x i1> - ; CHECK: Found an estimated cost of 128 for instruction: %r161 = fptosi <16 x double> undef to <16 x i1> + ; CHECK: Found an estimated cost of 135 for instruction: %r161 = fptosi <16 x double> undef to <16 x i1> %r161 = fptosi <16 x double> undef to <16 x i1> - ; CHECK: Found an estimated cost of 128 for instruction: %r162 = fptoui <16 x double> undef to <16 x i8> + ; CHECK: Found an estimated cost of 135 for instruction: %r162 = fptoui <16 x double> undef to <16 x i8> %r162 = fptoui <16 x double> undef to <16 x i8> - ; CHECK: Found an estimated cost of 128 for instruction: %r163 = fptosi <16 x double> undef to <16 x i8> + ; CHECK: Found an estimated cost of 135 for instruction: %r163 = fptosi <16 x double> undef to <16 x i8> %r163 = fptosi <16 x double> undef to <16 x i8> - ; CHECK: Found an estimated cost of 128 for instruction: %r164 = fptoui <16 x double> undef to <16 x i16> + ; CHECK: Found an estimated cost of 135 for instruction: %r164 = fptoui <16 x double> undef to <16 x i16> %r164 = fptoui <16 x double> undef to <16 x i16> - ; CHECK: Found an estimated cost of 128 for instruction: %r165 = fptosi <16 x double> undef to <16 x i16> + ; CHECK: Found an estimated cost of 135 for instruction: %r165 = fptosi <16 x double> undef to <16 x i16> %r165 = fptosi <16 x double> undef to <16 x i16> - ; CHECK: Found an estimated cost of 128 for instruction: %r166 = fptoui <16 x double> undef to <16 x i32> + ; CHECK: Found an estimated cost of 23 for instruction: %r166 = fptoui <16 x double> undef to <16 x i32> %r166 = fptoui <16 x double> undef to <16 x i32> - ; CHECK: Found an estimated cost of 128 for instruction: %r167 = fptosi <16 x double> undef to <16 x i32> + ; CHECK: Found an estimated cost of 23 for instruction: %r167 = fptosi <16 x double> undef to <16 x i32> %r167 = fptosi <16 x double> undef to <16 x i32> - ; CHECK: Found an estimated cost of 256 for instruction: %r168 = fptoui <16 x double> undef to <16 x i64> + ; CHECK: Found an estimated cost of 263 for instruction: %r168 = fptoui <16 x double> undef to <16 x i64> %r168 = fptoui <16 x double> undef to <16 x i64> - ; CHECK: Found an estimated cost of 256 for instruction: %r169 = fptosi <16 x double> undef to <16 x i64> + ; CHECK: Found an estimated cost of 263 for instruction: %r169 = fptosi <16 x double> undef to <16 x i64> %r169 = fptosi <16 x double> undef to <16 x i64> ; CHECK: Found an estimated cost of 12 for instruction: %r170 = uitofp <2 x i1> undef to <2 x float> @@ -432,39 +432,39 @@ define i32 @casts() { %r196 = uitofp <4 x i32> undef to <4 x float> ; 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: Found an estimated cost of 56 for instruction: %r198 = uitofp <4 x i64> undef to <4 x float> + ; CHECK: Found an estimated cost of 57 for instruction: %r198 = uitofp <4 x i64> undef to <4 x float> %r198 = uitofp <4 x i64> undef to <4 x float> - ; CHECK: Found an estimated cost of 56 for instruction: %r199 = sitofp <4 x i64> undef to <4 x float> + ; CHECK: Found an estimated cost of 57 for instruction: %r199 = sitofp <4 x i64> undef to <4 x float> %r199 = sitofp <4 x i64> undef to <4 x float> - ; CHECK: Found an estimated cost of 16 for instruction: %r200 = uitofp <4 x i1> undef to <4 x double> + ; CHECK: Found an estimated cost of 17 for instruction: %r200 = uitofp <4 x i1> undef to <4 x double> %r200 = uitofp <4 x i1> undef to <4 x double> - ; CHECK: Found an estimated cost of 16 for instruction: %r201 = sitofp <4 x i1> undef to <4 x double> + ; CHECK: Found an estimated cost of 17 for instruction: %r201 = sitofp <4 x i1> undef to <4 x double> %r201 = sitofp <4 x i1> undef to <4 x double> - ; CHECK: Found an estimated cost of 16 for instruction: %r202 = uitofp <4 x i8> undef to <4 x double> + ; CHECK: Found an estimated cost of 9 for instruction: %r202 = uitofp <4 x i8> undef to <4 x double> %r202 = uitofp <4 x i8> undef to <4 x double> - ; CHECK: Found an estimated cost of 16 for instruction: %r203 = sitofp <4 x i8> undef to <4 x double> + ; CHECK: Found an estimated cost of 9 for instruction: %r203 = sitofp <4 x i8> undef to <4 x double> %r203 = sitofp <4 x i8> undef to <4 x double> - ; CHECK: Found an estimated cost of 16 for instruction: %r204 = uitofp <4 x i16> undef to <4 x double> + ; CHECK: Found an estimated cost of 7 for instruction: %r204 = uitofp <4 x i16> undef to <4 x double> %r204 = uitofp <4 x i16> undef to <4 x double> - ; CHECK: Found an estimated cost of 16 for instruction: %r205 = sitofp <4 x i16> undef to <4 x double> + ; CHECK: Found an estimated cost of 7 for instruction: %r205 = sitofp <4 x i16> undef to <4 x double> %r205 = sitofp <4 x i16> undef to <4 x double> - ; CHECK: Found an estimated cost of 16 for instruction: %r206 = uitofp <4 x i32> undef to <4 x double> + ; CHECK: Found an estimated cost of 5 for instruction: %r206 = uitofp <4 x i32> undef to <4 x double> %r206 = uitofp <4 x i32> undef to <4 x double> - ; CHECK: Found an estimated cost of 16 for instruction: %r207 = sitofp <4 x i32> undef to <4 x double> + ; CHECK: Found an estimated cost of 5 for instruction: %r207 = sitofp <4 x i32> undef to <4 x double> %r207 = sitofp <4 x i32> undef to <4 x double> - ; CHECK: Found an estimated cost of 48 for instruction: %r208 = uitofp <4 x i64> undef to <4 x double> + ; CHECK: Found an estimated cost of 49 for instruction: %r208 = uitofp <4 x i64> undef to <4 x double> %r208 = uitofp <4 x i64> undef to <4 x double> - ; CHECK: Found an estimated cost of 48 for instruction: %r209 = sitofp <4 x i64> undef to <4 x double> + ; CHECK: Found an estimated cost of 49 for instruction: %r209 = sitofp <4 x i64> undef to <4 x double> %r209 = sitofp <4 x i64> undef to <4 x double> - ; CHECK: Found an estimated cost of 48 for instruction: %r210 = uitofp <8 x i1> undef to <8 x float> + ; CHECK: Found an estimated cost of 7 for instruction: %r210 = uitofp <8 x i1> undef to <8 x float> %r210 = uitofp <8 x i1> undef to <8 x float> - ; CHECK: Found an estimated cost of 48 for instruction: %r211 = sitofp <8 x i1> undef to <8 x float> + ; CHECK: Found an estimated cost of 7 for instruction: %r211 = sitofp <8 x i1> undef to <8 x float> %r211 = sitofp <8 x i1> undef to <8 x float> - ; CHECK: Found an estimated cost of 48 for instruction: %r212 = uitofp <8 x i8> undef to <8 x float> + ; CHECK: Found an estimated cost of 7 for instruction: %r212 = uitofp <8 x i8> undef to <8 x float> %r212 = uitofp <8 x i8> undef to <8 x float> - ; CHECK: Found an estimated cost of 48 for instruction: %r213 = sitofp <8 x i8> undef to <8 x float> + ; CHECK: Found an estimated cost of 7 for instruction: %r213 = sitofp <8 x i8> undef to <8 x float> %r213 = sitofp <8 x i8> undef to <8 x float> ; 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> @@ -474,39 +474,39 @@ define i32 @casts() { %r216 = uitofp <8 x i32> undef to <8 x float> ; 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: Found an estimated cost of 112 for instruction: %r218 = uitofp <8 x i64> undef to <8 x float> + ; CHECK: Found an estimated cost of 115 for instruction: %r218 = uitofp <8 x i64> undef to <8 x float> %r218 = uitofp <8 x i64> undef to <8 x float> - ; CHECK: Found an estimated cost of 112 for instruction: %r219 = sitofp <8 x i64> undef to <8 x float> + ; CHECK: Found an estimated cost of 115 for instruction: %r219 = sitofp <8 x i64> undef to <8 x float> %r219 = sitofp <8 x i64> undef to <8 x float> - ; CHECK: Found an estimated cost of 32 for instruction: %r220 = uitofp <8 x i1> undef to <8 x double> + ; CHECK: Found an estimated cost of 35 for instruction: %r220 = uitofp <8 x i1> undef to <8 x double> %r220 = uitofp <8 x i1> undef to <8 x double> - ; CHECK: Found an estimated cost of 32 for instruction: %r221 = sitofp <8 x i1> undef to <8 x double> + ; CHECK: Found an estimated cost of 35 for instruction: %r221 = sitofp <8 x i1> undef to <8 x double> %r221 = sitofp <8 x i1> undef to <8 x double> - ; CHECK: Found an estimated cost of 32 for instruction: %r222 = uitofp <8 x i8> undef to <8 x double> + ; CHECK: Found an estimated cost of 19 for instruction: %r222 = uitofp <8 x i8> undef to <8 x double> %r222 = uitofp <8 x i8> undef to <8 x double> - ; CHECK: Found an estimated cost of 32 for instruction: %r223 = sitofp <8 x i8> undef to <8 x double> + ; CHECK: Found an estimated cost of 19 for instruction: %r223 = sitofp <8 x i8> undef to <8 x double> %r223 = sitofp <8 x i8> undef to <8 x double> - ; CHECK: Found an estimated cost of 32 for instruction: %r224 = uitofp <8 x i16> undef to <8 x double> + ; CHECK: Found an estimated cost of 15 for instruction: %r224 = uitofp <8 x i16> undef to <8 x double> %r224 = uitofp <8 x i16> undef to <8 x double> - ; CHECK: Found an estimated cost of 32 for instruction: %r225 = sitofp <8 x i16> undef to <8 x double> + ; CHECK: Found an estimated cost of 15 for instruction: %r225 = sitofp <8 x i16> undef to <8 x double> %r225 = sitofp <8 x i16> undef to <8 x double> - ; CHECK: Found an estimated cost of 32 for instruction: %r226 = uitofp <8 x i16> undef to <8 x double> + ; CHECK: Found an estimated cost of 15 for instruction: %r226 = uitofp <8 x i16> undef to <8 x double> %r226 = uitofp <8 x i16> undef to <8 x double> - ; CHECK: Found an estimated cost of 32 for instruction: %r227 = sitofp <8 x i16> undef to <8 x double> + ; CHECK: Found an estimated cost of 15 for instruction: %r227 = sitofp <8 x i16> undef to <8 x double> %r227 = sitofp <8 x i16> undef to <8 x double> - ; CHECK: Found an estimated cost of 96 for instruction: %r228 = uitofp <8 x i64> undef to <8 x double> + ; CHECK: Found an estimated cost of 99 for instruction: %r228 = uitofp <8 x i64> undef to <8 x double> %r228 = uitofp <8 x i64> undef to <8 x double> - ; CHECK: Found an estimated cost of 96 for instruction: %r229 = sitofp <8 x i64> undef to <8 x double> + ; CHECK: Found an estimated cost of 99 for instruction: %r229 = sitofp <8 x i64> undef to <8 x double> %r229 = sitofp <8 x i64> undef to <8 x double> - ; CHECK: Found an estimated cost of 96 for instruction: %r230 = uitofp <16 x i1> undef to <16 x float> + ; CHECK: Found an estimated cost of 15 for instruction: %r230 = uitofp <16 x i1> undef to <16 x float> %r230 = uitofp <16 x i1> undef to <16 x float> - ; CHECK: Found an estimated cost of 96 for instruction: %r231 = sitofp <16 x i1> undef to <16 x float> + ; CHECK: Found an estimated cost of 15 for instruction: %r231 = sitofp <16 x i1> undef to <16 x float> %r231 = sitofp <16 x i1> undef to <16 x float> - ; CHECK: Found an estimated cost of 96 for instruction: %r232 = uitofp <16 x i8> undef to <16 x float> + ; CHECK: Found an estimated cost of 15 for instruction: %r232 = uitofp <16 x i8> undef to <16 x float> %r232 = uitofp <16 x i8> undef to <16 x float> - ; CHECK: Found an estimated cost of 96 for instruction: %r233 = sitofp <16 x i8> undef to <16 x float> + ; CHECK: Found an estimated cost of 15 for instruction: %r233 = sitofp <16 x i8> undef to <16 x float> %r233 = sitofp <16 x i8> undef to <16 x float> ; 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> @@ -516,30 +516,30 @@ define i32 @casts() { %r236 = uitofp <16 x i32> undef to <16 x float> ; 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: Found an estimated cost of 224 for instruction: %r238 = uitofp <16 x i64> undef to <16 x float> + ; CHECK: Found an estimated cost of 231 for instruction: %r238 = uitofp <16 x i64> undef to <16 x float> %r238 = uitofp <16 x i64> undef to <16 x float> - ; CHECK: Found an estimated cost of 224 for instruction: %r239 = sitofp <16 x i64> undef to <16 x float> + ; CHECK: Found an estimated cost of 231 for instruction: %r239 = sitofp <16 x i64> undef to <16 x float> %r239 = sitofp <16 x i64> undef to <16 x float> - ; CHECK: Found an estimated cost of 64 for instruction: %r240 = uitofp <16 x i1> undef to <16 x double> + ; CHECK: Found an estimated cost of 71 for instruction: %r240 = uitofp <16 x i1> undef to <16 x double> %r240 = uitofp <16 x i1> undef to <16 x double> - ; CHECK: Found an estimated cost of 64 for instruction: %r241 = sitofp <16 x i1> undef to <16 x double> + ; CHECK: Found an estimated cost of 71 for instruction: %r241 = sitofp <16 x i1> undef to <16 x double> %r241 = sitofp <16 x i1> undef to <16 x double> - ; CHECK: Found an estimated cost of 64 for instruction: %r242 = uitofp <16 x i8> undef to <16 x double> + ; CHECK: Found an estimated cost of 39 for instruction: %r242 = uitofp <16 x i8> undef to <16 x double> %r242 = uitofp <16 x i8> undef to <16 x double> - ; CHECK: Found an estimated cost of 64 for instruction: %r243 = sitofp <16 x i8> undef to <16 x double> + ; CHECK: Found an estimated cost of 39 for instruction: %r243 = sitofp <16 x i8> undef to <16 x double> %r243 = sitofp <16 x i8> undef to <16 x double> - ; CHECK: Found an estimated cost of 64 for instruction: %r244 = uitofp <16 x i16> undef to <16 x double> + ; CHECK: Found an estimated cost of 31 for instruction: %r244 = uitofp <16 x i16> undef to <16 x double> %r244 = uitofp <16 x i16> undef to <16 x double> - ; CHECK: Found an estimated cost of 64 for instruction: %r245 = sitofp <16 x i16> undef to <16 x double> + ; CHECK: Found an estimated cost of 31 for instruction: %r245 = sitofp <16 x i16> undef to <16 x double> %r245 = sitofp <16 x i16> undef to <16 x double> - ; CHECK: Found an estimated cost of 64 for instruction: %r246 = uitofp <16 x i16> undef to <16 x double> + ; CHECK: Found an estimated cost of 31 for instruction: %r246 = uitofp <16 x i16> undef to <16 x double> %r246 = uitofp <16 x i16> undef to <16 x double> - ; CHECK: Found an estimated cost of 64 for instruction: %r247 = sitofp <16 x i16> undef to <16 x double> + ; CHECK: Found an estimated cost of 31 for instruction: %r247 = sitofp <16 x i16> undef to <16 x double> %r247 = sitofp <16 x i16> undef to <16 x double> - ; CHECK: Found an estimated cost of 192 for instruction: %r248 = uitofp <16 x i64> undef to <16 x double> + ; CHECK: Found an estimated cost of 199 for instruction: %r248 = uitofp <16 x i64> undef to <16 x double> %r248 = uitofp <16 x i64> undef to <16 x double> - ; CHECK: Found an estimated cost of 192 for instruction: %r249 = sitofp <16 x i64> undef to <16 x double> + ; CHECK: Found an estimated cost of 199 for instruction: %r249 = sitofp <16 x i64> undef to <16 x double> %r249 = sitofp <16 x i64> undef to <16 x double> ; CHECK: Found an estimated cost of 0 for instruction: ret i32 undef diff --git a/test/Analysis/CostModel/PowerPC/ext.ll b/test/Analysis/CostModel/PowerPC/ext.ll index 7d6a14e93cdf3..df9c53e6e57f5 100644 --- a/test/Analysis/CostModel/PowerPC/ext.ll +++ b/test/Analysis/CostModel/PowerPC/ext.ll @@ -13,7 +13,7 @@ define void @exts() { ; CHECK: cost of 1 {{.*}} sext %v3 = sext <4 x i16> undef to <4 x i32> - ; CHECK: cost of 112 {{.*}} sext + ; CHECK: cost of 3 {{.*}} sext %v4 = sext <8 x i16> undef to <8 x i32> ret void diff --git a/test/Analysis/CostModel/PowerPC/load_store.ll b/test/Analysis/CostModel/PowerPC/load_store.ll index 0a568b88e7269..d48be5b5f62be 100644 --- a/test/Analysis/CostModel/PowerPC/load_store.ll +++ b/test/Analysis/CostModel/PowerPC/load_store.ll @@ -31,7 +31,7 @@ define i32 @loads(i32 %arg) { ; FIXME: There actually are sub-vector Altivec loads, and so we could handle ; this with a small expense, but we don't currently. - ; CHECK: cost of 48 {{.*}} load + ; CHECK: cost of 42 {{.*}} load load <4 x i16>, <4 x i16>* undef, align 2 ; CHECK: cost of 2 {{.*}} load diff --git a/test/Analysis/CostModel/PowerPC/popcnt.ll b/test/Analysis/CostModel/PowerPC/popcnt.ll new file mode 100644 index 0000000000000..4bd842db09b65 --- /dev/null +++ b/test/Analysis/CostModel/PowerPC/popcnt.ll @@ -0,0 +1,11 @@ +; RUN: opt < %s -cost-model -analyze -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 | 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" + +define <4 x i32> @test1(<4 x i32> %arg) { + ; CHECK: cost of 1 {{.*}} call <4 x i32> @llvm.ctpop.v4i32 + %ctpop = call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %arg) + ret <4 x i32> %ctpop +} + +declare <4 x i32> @llvm.ctpop.v4i32(<4 x i32>) diff --git a/test/Analysis/CostModel/X86/arith.ll b/test/Analysis/CostModel/X86/arith.ll index 0b61d3cd42140..a35db9c68ffb6 100644 --- a/test/Analysis/CostModel/X86/arith.ll +++ b/test/Analysis/CostModel/X86/arith.ll @@ -1,128 +1,173 @@ -; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx | FileCheck %s -; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mcpu=core2 | FileCheck %s --check-prefix=SSE3 -; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mcpu=core-avx2 | FileCheck %s --check-prefix=AVX2 +; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mattr=+ssse3 | FileCheck %s --check-prefix=CHECK --check-prefix=SSSE3 +; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mattr=+sse4.2 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE42 +; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mattr=+avx | FileCheck %s --check-prefix=CHECK --check-prefix=AVX +; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mattr=+avx2 | FileCheck %s --check-prefix=CHECK --check-prefix=AVX2 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-apple-macosx10.8.0" +; CHECK-LABEL: 'add' define i32 @add(i32 %arg) { - ;CHECK: cost of 1 {{.*}} add + ; SSSE3: cost of 1 {{.*}} %A = add + ; SSE42: cost of 1 {{.*}} %A = add + ; AVX: cost of 1 {{.*}} %A = add + ; AVX2: cost of 1 {{.*}} %A = add %A = add <4 x i32> undef, undef - ;CHECK: cost of 4 {{.*}} add + ; SSSE3: cost of 2 {{.*}} %B = add + ; SSE42: cost of 2 {{.*}} %B = add + ; AVX: cost of 4 {{.*}} %B = add + ; AVX2: cost of 1 {{.*}} %B = add %B = add <8 x i32> undef, undef - ;CHECK: cost of 1 {{.*}} add + ; SSSE3: cost of 1 {{.*}} %C = add + ; SSE42: cost of 1 {{.*}} %C = add + ; AVX: cost of 1 {{.*}} %C = add + ; AVX2: cost of 1 {{.*}} %C = add %C = add <2 x i64> undef, undef - ;CHECK: cost of 4 {{.*}} add + ; SSSE3: cost of 2 {{.*}} %D = add + ; SSE42: cost of 2 {{.*}} %D = add + ; AVX: cost of 4 {{.*}} %D = add + ; AVX2: cost of 1 {{.*}} %D = add %D = add <4 x i64> undef, undef - ;CHECK: cost of 8 {{.*}} add + ; SSSE3: cost of 4 {{.*}} %E = add + ; SSE42: cost of 4 {{.*}} %E = add + ; AVX: cost of 8 {{.*}} %E = add + ; AVX2: cost of 2 {{.*}} %E = add %E = add <8 x i64> undef, undef - ;CHECK: cost of 0 {{.*}} ret ret i32 undef } - +; CHECK-LABEL: 'xor' define i32 @xor(i32 %arg) { - ;CHECK: cost of 1 {{.*}} xor + ; SSSE3: cost of 1 {{.*}} %A = xor + ; SSE42: cost of 1 {{.*}} %A = xor + ; AVX: cost of 1 {{.*}} %A = xor + ; AVX2: cost of 1 {{.*}} %A = xor %A = xor <4 x i32> undef, undef - ;CHECK: cost of 1 {{.*}} xor + ; SSSE3: cost of 2 {{.*}} %B = xor + ; SSE42: cost of 2 {{.*}} %B = xor + ; AVX: cost of 1 {{.*}} %B = xor + ; AVX2: cost of 1 {{.*}} %B = xor %B = xor <8 x i32> undef, undef - ;CHECK: cost of 1 {{.*}} xor + ; SSSE3: cost of 1 {{.*}} %C = xor + ; SSE42: cost of 1 {{.*}} %C = xor + ; AVX: cost of 1 {{.*}} %C = xor + ; AVX2: cost of 1 {{.*}} %C = xor %C = xor <2 x i64> undef, undef - ;CHECK: cost of 1 {{.*}} xor + ; SSSE3: cost of 2 {{.*}} %D = xor + ; SSE42: cost of 2 {{.*}} %D = xor + ; AVX: cost of 1 {{.*}} %D = xor + ; AVX2: cost of 1 {{.*}} %D = xor %D = xor <4 x i64> undef, undef - ;CHECK: cost of 0 {{.*}} ret ret i32 undef } -; CHECK: mul +; CHECK-LABEL: 'mul' define void @mul() { ; A <2 x i32> gets expanded to a <2 x i64> vector. ; A <2 x i64> vector multiply is implemented using ; 3 PMULUDQ and 2 PADDS and 4 shifts. - ;CHECK: cost of 9 {{.*}} mul + ; SSSE3: cost of 9 {{.*}} %A0 = mul + ; SSE42: cost of 9 {{.*}} %A0 = mul + ; AVX: cost of 9 {{.*}} %A0 = mul + ; AVX2: cost of 9 {{.*}} %A0 = mul %A0 = mul <2 x i32> undef, undef - ;CHECK: cost of 9 {{.*}} mul - %A1 = mul <2 x i64> undef, undef - ;CHECK: cost of 18 {{.*}} mul - %A2 = mul <4 x i64> undef, undef - ret void -} - -; SSE3: sse3mull -define void @sse3mull() { - ; SSE3: cost of 6 {{.*}} mul - %A0 = mul <4 x i32> undef, undef - ret void - ; SSE3: avx2mull -} - -; AVX2: avx2mull -define void @avx2mull() { - ; AVX2: cost of 9 {{.*}} mul - %A0 = mul <4 x i64> undef, undef + ; SSSE3: cost of 6 {{.*}} %A1 = mul + ; SSE42: cost of 1 {{.*}} %A1 = mul + ; AVX: cost of 1 {{.*}} %A1 = mul + ; AVX2: cost of 1 {{.*}} %A1 = mul + %A1 = mul <4 x i32> undef, undef + ; SSSE3: cost of 9 {{.*}} %A2 = mul + ; SSE42: cost of 9 {{.*}} %A2 = mul + ; AVX: cost of 9 {{.*}} %A2 = mul + ; AVX2: cost of 9 {{.*}} %A2 = mul + %A2 = mul <2 x i64> undef, undef + ; SSSE3: cost of 18 {{.*}} %A3 = mul + ; SSE42: cost of 18 {{.*}} %A3 = mul + ; AVX: cost of 18 {{.*}} %A3 = mul + ; AVX2: cost of 9 {{.*}} %A3 = mul + %A3 = mul <4 x i64> undef, undef ret void - ; AVX2: fmul } -; CHECK: fmul +; CHECK-LABEL: 'fmul' define i32 @fmul(i32 %arg) { - ;CHECK: cost of 2 {{.*}} fmul + ; SSSE3: cost of 2 {{.*}} %A = fmul + ; SSE42: cost of 2 {{.*}} %A = fmul + ; AVX: cost of 2 {{.*}} %A = fmul + ; AVX2: cost of 2 {{.*}} %A = fmul %A = fmul <4 x float> undef, undef - ;CHECK: cost of 2 {{.*}} fmul + ; SSSE3: cost of 4 {{.*}} %B = fmul + ; SSE42: cost of 4 {{.*}} %B = fmul + ; AVX: cost of 2 {{.*}} %B = fmul + ; AVX2: cost of 2 {{.*}} %B = fmul %B = fmul <8 x float> undef, undef ret i32 undef } -; AVX: shift -; AVX2: shift +; CHECK-LABEL: 'shift' define void @shift() { - ; AVX: cost of 2 {{.*}} shl - ; AVX2: cost of 1 {{.*}} shl + ; SSSE3: cost of 10 {{.*}} %A0 = shl + ; SSE42: cost of 10 {{.*}} %A0 = shl + ; AVX: cost of 10 {{.*}} %A0 = shl + ; AVX2: cost of 1 {{.*}} %A0 = shl %A0 = shl <4 x i32> undef, undef - ; AVX: cost of 2 {{.*}} shl - ; AVX2: cost of 1 {{.*}} shl + ; SSSE3: cost of 4 {{.*}} %A1 = shl + ; SSE42: cost of 4 {{.*}} %A1 = shl + ; AVX: cost of 4 {{.*}} %A1 = shl + ; AVX2: cost of 1 {{.*}} %A1 = shl %A1 = shl <2 x i64> undef, undef + ; SSSE3: cost of 20 {{.*}} %A2 = shl + ; SSE42: cost of 20 {{.*}} %A2 = shl + ; AVX: cost of 20 {{.*}} %A2 = shl + ; AVX2: cost of 1 {{.*}} %A2 = shl + %A2 = shl <8 x i32> undef, undef + ; SSSE3: cost of 8 {{.*}} %A3 = shl + ; SSE42: cost of 8 {{.*}} %A3 = shl + ; AVX: cost of 8 {{.*}} %A3 = shl + ; AVX2: cost of 1 {{.*}} %A3 = shl + %A3 = shl <4 x i64> undef, undef - ; AVX: cost of 2 {{.*}} lshr - ; AVX2: cost of 1 {{.*}} lshr + ; SSSE3: cost of 16 {{.*}} %B0 = lshr + ; SSE42: cost of 16 {{.*}} %B0 = lshr + ; AVX: cost of 16 {{.*}} %B0 = lshr + ; AVX2: cost of 1 {{.*}} %B0 = lshr %B0 = lshr <4 x i32> undef, undef - ; AVX: cost of 2 {{.*}} lshr - ; AVX2: cost of 1 {{.*}} lshr + ; SSSE3: cost of 4 {{.*}} %B1 = lshr + ; SSE42: cost of 4 {{.*}} %B1 = lshr + ; AVX: cost of 4 {{.*}} %B1 = lshr + ; AVX2: cost of 1 {{.*}} %B1 = lshr %B1 = lshr <2 x i64> undef, undef + ; SSSE3: cost of 32 {{.*}} %B2 = lshr + ; SSE42: cost of 32 {{.*}} %B2 = lshr + ; AVX: cost of 32 {{.*}} %B2 = lshr + ; AVX2: cost of 1 {{.*}} %B2 = lshr + %B2 = lshr <8 x i32> undef, undef + ; SSSE3: cost of 8 {{.*}} %B3 = lshr + ; SSE42: cost of 8 {{.*}} %B3 = lshr + ; AVX: cost of 8 {{.*}} %B3 = lshr + ; AVX2: cost of 1 {{.*}} %B3 = lshr + %B3 = lshr <4 x i64> undef, undef - ; AVX: cost of 2 {{.*}} ashr - ; AVX2: cost of 1 {{.*}} ashr + ; SSSE3: cost of 16 {{.*}} %C0 = ashr + ; SSE42: cost of 16 {{.*}} %C0 = ashr + ; AVX: cost of 16 {{.*}} %C0 = ashr + ; AVX2: cost of 1 {{.*}} %C0 = ashr %C0 = ashr <4 x i32> undef, undef - ; AVX: cost of 6 {{.*}} ashr - ; AVX2: cost of 4 {{.*}} ashr + ; SSSE3: cost of 12 {{.*}} %C1 = ashr + ; SSE42: cost of 12 {{.*}} %C1 = ashr + ; AVX: cost of 12 {{.*}} %C1 = ashr + ; AVX2: cost of 4 {{.*}} %C1 = ashr %C1 = ashr <2 x i64> undef, undef - - ret void -} - -; AVX: avx2shift -; AVX2: avx2shift -define void @avx2shift() { - ; AVX: cost of 2 {{.*}} shl - ; AVX2: cost of 1 {{.*}} shl - %A0 = shl <8 x i32> undef, undef - ; AVX: cost of 2 {{.*}} shl - ; AVX2: cost of 1 {{.*}} shl - %A1 = shl <4 x i64> undef, undef - - ; AVX: cost of 2 {{.*}} lshr - ; AVX2: cost of 1 {{.*}} lshr - %B0 = lshr <8 x i32> undef, undef - ; AVX: cost of 2 {{.*}} lshr - ; AVX2: cost of 1 {{.*}} lshr - %B1 = lshr <4 x i64> undef, undef - - ; AVX: cost of 2 {{.*}} ashr - ; AVX2: cost of 1 {{.*}} ashr - %C0 = ashr <8 x i32> undef, undef - ; AVX: cost of 12 {{.*}} ashr - ; AVX2: cost of 4 {{.*}} ashr - %C1 = ashr <4 x i64> undef, undef + ; SSSE3: cost of 32 {{.*}} %C2 = ashr + ; SSE42: cost of 32 {{.*}} %C2 = ashr + ; AVX: cost of 32 {{.*}} %C2 = ashr + ; AVX2: cost of 1 {{.*}} %C2 = ashr + %C2 = ashr <8 x i32> undef, undef + ; SSSE3: cost of 24 {{.*}} %C3 = ashr + ; SSE42: cost of 24 {{.*}} %C3 = ashr + ; AVX: cost of 24 {{.*}} %C3 = ashr + ; AVX2: cost of 4 {{.*}} %C3 = ashr + %C3 = ashr <4 x i64> undef, undef ret void } diff --git a/test/Analysis/CostModel/X86/bitreverse.ll b/test/Analysis/CostModel/X86/bitreverse.ll new file mode 100644 index 0000000000000..c9eea20c3404d --- /dev/null +++ b/test/Analysis/CostModel/X86/bitreverse.ll @@ -0,0 +1,157 @@ +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=pentium4 -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=SSE42 +; 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 scalar bitreverse instructions. + +declare i64 @llvm.bitreverse.i64(i64) +declare i32 @llvm.bitreverse.i32(i32) +declare i16 @llvm.bitreverse.i16(i16) +declare i8 @llvm.bitreverse.i8(i8) + +define i64 @var_bitreverse_i64(i64 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bitreverse_i64': +; SSE2: Found an estimated cost of 1 for instruction: %bitreverse +; SSE42: Found an estimated cost of 1 for instruction: %bitreverse +; AVX: Found an estimated cost of 1 for instruction: %bitreverse +; AVX2: Found an estimated cost of 1 for instruction: %bitreverse +; XOP: Found an estimated cost of 3 for instruction: %bitreverse + %bitreverse = call i64 @llvm.bitreverse.i64(i64 %a) + ret i64 %bitreverse +} + +define i32 @var_bitreverse_i32(i32 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bitreverse_i32': +; SSE2: Found an estimated cost of 1 for instruction: %bitreverse +; SSE42: Found an estimated cost of 1 for instruction: %bitreverse +; AVX: Found an estimated cost of 1 for instruction: %bitreverse +; AVX2: Found an estimated cost of 1 for instruction: %bitreverse +; XOP: Found an estimated cost of 3 for instruction: %bitreverse + %bitreverse = call i32 @llvm.bitreverse.i32(i32 %a) + ret i32 %bitreverse +} + +define i16 @var_bitreverse_i16(i16 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bitreverse_i16': +; SSE2: Found an estimated cost of 1 for instruction: %bitreverse +; SSE42: Found an estimated cost of 1 for instruction: %bitreverse +; AVX: Found an estimated cost of 1 for instruction: %bitreverse +; AVX2: Found an estimated cost of 1 for instruction: %bitreverse +; XOP: Found an estimated cost of 3 for instruction: %bitreverse + %bitreverse = call i16 @llvm.bitreverse.i16(i16 %a) + ret i16 %bitreverse +} + +define i8 @var_bitreverse_i8(i8 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bitreverse_i8': +; SSE2: Found an estimated cost of 1 for instruction: %bitreverse +; SSE42: Found an estimated cost of 1 for instruction: %bitreverse +; AVX: Found an estimated cost of 1 for instruction: %bitreverse +; AVX2: Found an estimated cost of 1 for instruction: %bitreverse +; XOP: Found an estimated cost of 3 for instruction: %bitreverse + %bitreverse = call i8 @llvm.bitreverse.i8(i8 %a) + ret i8 %bitreverse +} + +; Verify the cost of vector bitreverse instructions. + +declare <2 x i64> @llvm.bitreverse.v2i64(<2 x i64>) +declare <4 x i32> @llvm.bitreverse.v4i32(<4 x i32>) +declare <8 x i16> @llvm.bitreverse.v8i16(<8 x i16>) +declare <16 x i8> @llvm.bitreverse.v16i8(<16 x i8>) + +declare <4 x i64> @llvm.bitreverse.v4i64(<4 x i64>) +declare <8 x i32> @llvm.bitreverse.v8i32(<8 x i32>) +declare <16 x i16> @llvm.bitreverse.v16i16(<16 x i16>) +declare <32 x i8> @llvm.bitreverse.v32i8(<32 x i8>) + +define <2 x i64> @var_bitreverse_v2i64(<2 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bitreverse_v2i64': +; SSE2: Found an estimated cost of 6 for instruction: %bitreverse +; SSE42: Found an estimated cost of 5 for instruction: %bitreverse +; AVX: Found an estimated cost of 5 for instruction: %bitreverse +; AVX2: Found an estimated cost of 5 for instruction: %bitreverse +; XOP: Found an estimated cost of 1 for instruction: %bitreverse + %bitreverse = call <2 x i64> @llvm.bitreverse.v2i64(<2 x i64> %a) + ret <2 x i64> %bitreverse +} + +define <4 x i64> @var_bitreverse_v4i64(<4 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bitreverse_v4i64': +; SSE2: Found an estimated cost of 12 for instruction: %bitreverse +; SSE42: Found an estimated cost of 10 for instruction: %bitreverse +; AVX: Found an estimated cost of 10 for instruction: %bitreverse +; AVX2: Found an estimated cost of 5 for instruction: %bitreverse +; XOP: Found an estimated cost of 4 for instruction: %bitreverse + %bitreverse = call <4 x i64> @llvm.bitreverse.v4i64(<4 x i64> %a) + ret <4 x i64> %bitreverse +} + +define <4 x i32> @var_bitreverse_v4i32(<4 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bitreverse_v4i32': +; SSE2: Found an estimated cost of 12 for instruction: %bitreverse +; SSE42: Found an estimated cost of 5 for instruction: %bitreverse +; AVX: Found an estimated cost of 5 for instruction: %bitreverse +; AVX2: Found an estimated cost of 5 for instruction: %bitreverse +; XOP: Found an estimated cost of 1 for instruction: %bitreverse + %bitreverse = call <4 x i32> @llvm.bitreverse.v4i32(<4 x i32> %a) + ret <4 x i32> %bitreverse +} + +define <8 x i32> @var_bitreverse_v8i32(<8 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bitreverse_v8i32': +; SSE2: Found an estimated cost of 24 for instruction: %bitreverse +; SSE42: Found an estimated cost of 10 for instruction: %bitreverse +; AVX: Found an estimated cost of 10 for instruction: %bitreverse +; AVX2: Found an estimated cost of 5 for instruction: %bitreverse +; XOP: Found an estimated cost of 4 for instruction: %bitreverse + %bitreverse = call <8 x i32> @llvm.bitreverse.v8i32(<8 x i32> %a) + ret <8 x i32> %bitreverse +} + +define <8 x i16> @var_bitreverse_v8i16(<8 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bitreverse_v8i16': +; SSE2: Found an estimated cost of 24 for instruction: %bitreverse +; SSE42: Found an estimated cost of 5 for instruction: %bitreverse +; AVX: Found an estimated cost of 5 for instruction: %bitreverse +; AVX2: Found an estimated cost of 5 for instruction: %bitreverse +; XOP: Found an estimated cost of 1 for instruction: %bitreverse + %bitreverse = call <8 x i16> @llvm.bitreverse.v8i16(<8 x i16> %a) + ret <8 x i16> %bitreverse +} + +define <16 x i16> @var_bitreverse_v16i16(<16 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bitreverse_v16i16': +; SSE2: Found an estimated cost of 48 for instruction: %bitreverse +; SSE42: Found an estimated cost of 10 for instruction: %bitreverse +; AVX: Found an estimated cost of 10 for instruction: %bitreverse +; AVX2: Found an estimated cost of 5 for instruction: %bitreverse +; XOP: Found an estimated cost of 4 for instruction: %bitreverse + %bitreverse = call <16 x i16> @llvm.bitreverse.v16i16(<16 x i16> %a) + ret <16 x i16> %bitreverse +} + +define <16 x i8> @var_bitreverse_v16i8(<16 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bitreverse_v16i8': +; SSE2: Found an estimated cost of 48 for instruction: %bitreverse +; SSE42: Found an estimated cost of 5 for instruction: %bitreverse +; AVX: Found an estimated cost of 5 for instruction: %bitreverse +; AVX2: Found an estimated cost of 5 for instruction: %bitreverse +; XOP: Found an estimated cost of 1 for instruction: %bitreverse + %bitreverse = call <16 x i8> @llvm.bitreverse.v16i8(<16 x i8> %a) + ret <16 x i8> %bitreverse +} + +define <32 x i8> @var_bitreverse_v32i8(<32 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bitreverse_v32i8': +; SSE2: Found an estimated cost of 96 for instruction: %bitreverse +; SSE42: Found an estimated cost of 10 for instruction: %bitreverse +; AVX: Found an estimated cost of 10 for instruction: %bitreverse +; AVX2: Found an estimated cost of 5 for instruction: %bitreverse +; XOP: Found an estimated cost of 4 for instruction: %bitreverse + %bitreverse = call <32 x i8> @llvm.bitreverse.v32i8(<32 x i8> %a) + ret <32 x i8> %bitreverse +} diff --git a/test/Analysis/CostModel/X86/bswap.ll b/test/Analysis/CostModel/X86/bswap.ll new file mode 100644 index 0000000000000..ecbe24c861cce --- /dev/null +++ b/test/Analysis/CostModel/X86/bswap.ll @@ -0,0 +1,82 @@ +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=pentium4 -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=SSE42 +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7-avx -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=AVX -check-prefix=AVX1 +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=core-avx2 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=AVX -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=XOPAVX1 +; 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 bswap instructions. + +declare <2 x i64> @llvm.bswap.v2i64(<2 x i64>) +declare <4 x i32> @llvm.bswap.v4i32(<4 x i32>) +declare <8 x i16> @llvm.bswap.v8i16(<8 x i16>) + +declare <4 x i64> @llvm.bswap.v4i64(<4 x i64>) +declare <8 x i32> @llvm.bswap.v8i32(<8 x i32>) +declare <16 x i16> @llvm.bswap.v16i16(<16 x i16>) + +define <2 x i64> @var_bswap_v2i64(<2 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bswap_v2i64': +; SSE2: Found an estimated cost of 7 for instruction: %bswap +; SSE42: Found an estimated cost of 1 for instruction: %bswap +; AVX: Found an estimated cost of 1 for instruction: %bswap +; XOP: Found an estimated cost of 1 for instruction: %bswap + %bswap = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> %a) + ret <2 x i64> %bswap +} + +define <4 x i64> @var_bswap_v4i64(<4 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bswap_v4i64': +; SSE2: Found an estimated cost of 14 for instruction: %bswap +; SSE42: Found an estimated cost of 2 for instruction: %bswap +; AVX1: Found an estimated cost of 4 for instruction: %bswap +; AVX2: Found an estimated cost of 1 for instruction: %bswap +; XOPAVX1: Found an estimated cost of 4 for instruction: %bswap +; XOPAVX2: Found an estimated cost of 1 for instruction: %bswap + %bswap = call <4 x i64> @llvm.bswap.v4i64(<4 x i64> %a) + ret <4 x i64> %bswap +} + +define <4 x i32> @var_bswap_v4i32(<4 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bswap_v4i32': +; SSE2: Found an estimated cost of 7 for instruction: %bswap +; SSE42: Found an estimated cost of 1 for instruction: %bswap +; AVX: Found an estimated cost of 1 for instruction: %bswap +; XOP: Found an estimated cost of 1 for instruction: %bswap + %bswap = call <4 x i32> @llvm.bswap.v4i32(<4 x i32> %a) + ret <4 x i32> %bswap +} + +define <8 x i32> @var_bswap_v8i32(<8 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bswap_v8i32': +; SSE2: Found an estimated cost of 14 for instruction: %bswap +; SSE42: Found an estimated cost of 2 for instruction: %bswap +; AVX1: Found an estimated cost of 4 for instruction: %bswap +; AVX2: Found an estimated cost of 1 for instruction: %bswap +; XOPAVX1: Found an estimated cost of 4 for instruction: %bswap +; XOPAVX2: Found an estimated cost of 1 for instruction: %bswap + %bswap = call <8 x i32> @llvm.bswap.v8i32(<8 x i32> %a) + ret <8 x i32> %bswap +} + +define <8 x i16> @var_bswap_v8i16(<8 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bswap_v8i16': +; SSE2: Found an estimated cost of 7 for instruction: %bswap +; SSE42: Found an estimated cost of 1 for instruction: %bswap +; AVX: Found an estimated cost of 1 for instruction: %bswap +; XOP: Found an estimated cost of 1 for instruction: %bswap + %bswap = call <8 x i16> @llvm.bswap.v8i16(<8 x i16> %a) + ret <8 x i16> %bswap +} + +define <16 x i16> @var_bswap_v16i16(<16 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_bswap_v16i16': +; SSE2: Found an estimated cost of 14 for instruction: %bswap +; SSE42: Found an estimated cost of 2 for instruction: %bswap +; AVX1: Found an estimated cost of 4 for instruction: %bswap +; AVX2: Found an estimated cost of 1 for instruction: %bswap +; XOPAVX1: Found an estimated cost of 4 for instruction: %bswap +; XOPAVX2: Found an estimated cost of 1 for instruction: %bswap + %bswap = call <16 x i16> @llvm.bswap.v16i16(<16 x i16> %a) + ret <16 x i16> %bswap +} diff --git a/test/Analysis/CostModel/X86/cast.ll b/test/Analysis/CostModel/X86/cast.ll index c518587c0e1ae..39e03c6c3b2f9 100644 --- a/test/Analysis/CostModel/X86/cast.ll +++ b/test/Analysis/CostModel/X86/cast.ll @@ -238,21 +238,21 @@ define void @uitofp8(<8 x i1> %a, <8 x i8> %b, <8 x i16> %c, <8 x i32> %d) { 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: cost of 1 {{.*}} %A1 = fpext + %A1 = fpext <4 x float> %c to <4 x double> - ; CHECK-AVX512: cost of 1 {{.*}} fpext - %A2 = fpext <4 x float> %c to <4 x double> + ; CHECK-AVX: cost of 3 {{.*}} %A2 = fpext + ; CHECK-AVX2: cost of 3 {{.*}} %A2 = fpext + ; CHECK-AVX512: cost of 1 {{.*}} %A2 = fpext + %A2 = fpext <8 x float> %a to <8 x double> - ; CHECK-AVX2: cost of 3 {{.*}} %A3 = fpext - ; CHECK-AVX512: cost of 1 {{.*}} %A3 = fpext - %A3 = fpext <8 x float> %a to <8 x double> + ; CHECK: cost of 1 {{.*}} %A3 = fptrunc + %A3 = fptrunc <4 x double> undef to <4 x float> + ; CHECK-AVX: cost of 3 {{.*}} %A4 = fptrunc ; CHECK-AVX2: cost of 3 {{.*}} %A4 = fptrunc ; CHECK-AVX512: cost of 1 {{.*}} %A4 = fptrunc %A4 = fptrunc <8 x double> undef to <8 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/cmp.ll b/test/Analysis/CostModel/X86/cmp.ll index 469cd735f8a01..f4733d6737e12 100644 --- a/test/Analysis/CostModel/X86/cmp.ll +++ b/test/Analysis/CostModel/X86/cmp.ll @@ -1,64 +1,144 @@ -; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx | FileCheck -check-prefix=CHECK -check-prefix=AVX1 %s -; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mcpu=core-avx2 | FileCheck -check-prefix=CHECK -check-prefix=AVX2 %s -; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mcpu=knl | FileCheck -check-prefix=CHECK -check-prefix=AVX512 %s +; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mcpu=pentium4 | FileCheck --check-prefix=CHECK --check-prefix=SSE --check-prefix=SSE2 %s +; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mcpu=yonah | FileCheck --check-prefix=CHECK --check-prefix=SSE --check-prefix=SSE3 %s +; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mcpu=core2 | FileCheck --check-prefix=CHECK --check-prefix=SSE --check-prefix=SSSE3 %s +; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mcpu=penryn | FileCheck --check-prefix=CHECK --check-prefix=SSE --check-prefix=SSE41 %s +; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7 | FileCheck --check-prefix=CHECK --check-prefix=SSE --check-prefix=SSE42 %s +; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx | FileCheck --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX1 %s +; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mcpu=core-avx2 | FileCheck --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX2 %s +; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-apple-macosx10.8.0 -mcpu=knl | FileCheck --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX512 %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-apple-macosx10.8.0" define i32 @cmp(i32 %arg) { ; -- floats -- - ;AVX1: cost of 1 {{.*}} fcmp - ;AVX2: cost of 1 {{.*}} fcmp + ;SSE2: cost of 3 {{.*}} fcmp + ;SSE3: cost of 3 {{.*}} fcmp + ;SSSE3: cost of 3 {{.*}} fcmp + ;SSE41: cost of 3 {{.*}} fcmp + ;SSE42: cost of 1 {{.*}} fcmp + ;AVX: cost of 1 {{.*}} fcmp %A = fcmp olt <2 x float> undef, undef - ;AVX1: cost of 1 {{.*}} fcmp - ;AVX2: cost of 1 {{.*}} fcmp + + ;SSE2: cost of 7 {{.*}} fcmp + ;SSE3: cost of 7 {{.*}} fcmp + ;SSSE3: cost of 7 {{.*}} fcmp + ;SSE41: cost of 7 {{.*}} fcmp + ;SSE42: cost of 1 {{.*}} fcmp + ;AVX: cost of 1 {{.*}} fcmp %B = fcmp olt <4 x float> undef, undef - ;AVX1: cost of 1 {{.*}} fcmp - ;AVX2: cost of 1 {{.*}} fcmp + + ;SSE2: cost of 14 {{.*}} fcmp + ;SSE3: cost of 14 {{.*}} fcmp + ;SSSE3: cost of 14 {{.*}} fcmp + ;SSE41: cost of 14 {{.*}} fcmp + ;SSE42: cost of 2 {{.*}} fcmp + ;AVX: cost of 1 {{.*}} fcmp %C = fcmp olt <8 x float> undef, undef - ;AVX1: cost of 1 {{.*}} fcmp - ;AVX2: cost of 1 {{.*}} fcmp + + ;SSE2: cost of 3 {{.*}} fcmp + ;SSE3: cost of 3 {{.*}} fcmp + ;SSSE3: cost of 3 {{.*}} fcmp + ;SSE41: cost of 3 {{.*}} fcmp + ;SSE42: cost of 1 {{.*}} fcmp + ;AVX: cost of 1 {{.*}} fcmp %D = fcmp olt <2 x double> undef, undef - ;AVX1: cost of 1 {{.*}} fcmp - ;AVX2: cost of 1 {{.*}} fcmp + + ;SSE2: cost of 6 {{.*}} fcmp + ;SSE3: cost of 6 {{.*}} fcmp + ;SSSE3: cost of 6 {{.*}} fcmp + ;SSE41: cost of 6 {{.*}} fcmp + ;SSE42: cost of 2 {{.*}} fcmp + ;AVX: cost of 1 {{.*}} fcmp %E = fcmp olt <4 x double> undef, undef ; AVX512: cost of 1 {{.*}} %E1 = fcmp %E1 = fcmp olt <16 x float> undef, undef - ; AVX512: cost of 2 {{.*}} %E2 = fcmp - %E2 = fcmp olt <16 x double> undef, undef + + ; AVX512: cost of 1 {{.*}} %E2 = fcmp + %E2 = fcmp olt <8 x double> undef, undef + + ; AVX512: cost of 2 {{.*}} %E3 = fcmp + %E3 = fcmp olt <16 x double> undef, undef ; -- integers -- - ;AVX1: cost of 1 {{.*}} icmp - ;AVX2: cost of 1 {{.*}} icmp + ;SSE2: cost of 1 {{.*}} icmp + ;SSE3: cost of 1 {{.*}} icmp + ;SSSE3: cost of 1 {{.*}} icmp + ;SSE41: cost of 1 {{.*}} icmp + ;SSE42: cost of 1 {{.*}} icmp + ;AVX: cost of 1 {{.*}} icmp %F = icmp eq <16 x i8> undef, undef - ;AVX1: cost of 1 {{.*}} icmp - ;AVX2: cost of 1 {{.*}} icmp + + ;SSE2: cost of 1 {{.*}} icmp + ;SSE3: cost of 1 {{.*}} icmp + ;SSSE3: cost of 1 {{.*}} icmp + ;SSE41: cost of 1 {{.*}} icmp + ;SSE42: cost of 1 {{.*}} icmp + ;AVX: cost of 1 {{.*}} icmp %G = icmp eq <8 x i16> undef, undef - ;AVX1: cost of 1 {{.*}} icmp - ;AVX2: cost of 1 {{.*}} icmp + + ;SSE2: cost of 1 {{.*}} icmp + ;SSE3: cost of 1 {{.*}} icmp + ;SSSE3: cost of 1 {{.*}} icmp + ;SSE41: cost of 1 {{.*}} icmp + ;SSE42: cost of 1 {{.*}} icmp + ;AVX: cost of 1 {{.*}} icmp %H = icmp eq <4 x i32> undef, undef - ;AVX1: cost of 1 {{.*}} icmp - ;AVX2: cost of 1 {{.*}} icmp + + ;SSE2: cost of 8 {{.*}} icmp + ;SSE3: cost of 8 {{.*}} icmp + ;SSSE3: cost of 8 {{.*}} icmp + ;SSE41: cost of 8 {{.*}} icmp + ;SSE42: cost of 1 {{.*}} icmp + ;AVX: cost of 1 {{.*}} icmp %I = icmp eq <2 x i64> undef, undef - ;AVX1: cost of 4 {{.*}} icmp - ;AVX2: cost of 1 {{.*}} icmp + + ;SSE2: cost of 16 {{.*}} icmp + ;SSE3: cost of 16 {{.*}} icmp + ;SSSE3: cost of 16 {{.*}} icmp + ;SSE41: cost of 16 {{.*}} icmp + ;SSE42: cost of 2 {{.*}} icmp + ;AVX1: cost of 4 {{.*}} icmp + ;AVX2: cost of 1 {{.*}} icmp %J = icmp eq <4 x i64> undef, undef - ;AVX1: cost of 4 {{.*}} icmp - ;AVX2: cost of 1 {{.*}} icmp + + ;SSE2: cost of 2 {{.*}} icmp + ;SSE3: cost of 2 {{.*}} icmp + ;SSSE3: cost of 2 {{.*}} icmp + ;SSE41: cost of 2 {{.*}} icmp + ;SSE42: cost of 2 {{.*}} icmp + ;AVX1: cost of 4 {{.*}} icmp + ;AVX2: cost of 1 {{.*}} icmp %K = icmp eq <8 x i32> undef, undef - ;AVX1: cost of 4 {{.*}} icmp - ;AVX2: cost of 1 {{.*}} icmp + + ;SSE2: cost of 2 {{.*}} icmp + ;SSE3: cost of 2 {{.*}} icmp + ;SSSE3: cost of 2 {{.*}} icmp + ;SSE41: cost of 2 {{.*}} icmp + ;SSE42: cost of 2 {{.*}} icmp + ;AVX1: cost of 4 {{.*}} icmp + ;AVX2: cost of 1 {{.*}} icmp %L = icmp eq <16 x i16> undef, undef - ;AVX1: cost of 4 {{.*}} icmp - ;AVX2: cost of 1 {{.*}} icmp + + ;SSE2: cost of 2 {{.*}} icmp + ;SSE3: cost of 2 {{.*}} icmp + ;SSSE3: cost of 2 {{.*}} icmp + ;SSE41: cost of 2 {{.*}} icmp + ;SSE42: cost of 2 {{.*}} icmp + ;AVX1: cost of 4 {{.*}} icmp + ;AVX2: cost of 1 {{.*}} icmp %M = icmp eq <32 x i8> undef, undef ; AVX512: cost of 1 {{.*}} %M1 = icmp %M1 = icmp eq <16 x i32> undef, undef - ; AVX512: cost of 2 {{.*}} %M2 = icmp - %M2 = icmp eq <16 x i64> undef, undef + + ; AVX512: cost of 1 {{.*}} %M2 = icmp + %M2 = icmp eq <8 x i64> undef, undef + + ; AVX512: cost of 2 {{.*}} %M3 = icmp + %M3 = icmp eq <16 x i64> undef, undef ;CHECK: cost of 0 {{.*}} ret ret i32 undef diff --git a/test/Analysis/CostModel/X86/ctbits-cost.ll b/test/Analysis/CostModel/X86/ctbits-cost.ll new file mode 100644 index 0000000000000..23bfafd8bc945 --- /dev/null +++ b/test/Analysis/CostModel/X86/ctbits-cost.ll @@ -0,0 +1,567 @@ +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=pentium4 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=SSE -check-prefix=SSE2 -check-prefix=NOPOPCNT +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=SSE -check-prefix=SSE42 -check-prefix=POPCNT +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7-avx -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=AVX -check-prefix=AVX1 -check-prefix=POPCNT +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=core-avx2 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=AVX -check-prefix=AVX2 -check-prefix=POPCNT +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=bdver2 -cost-model -analyze | FileCheck %s -check-prefix=CHECK -check-prefix=XOP -check-prefix=XOPAVX1 -check-prefix=POPCNT +; 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 -check-prefix=POPCNT + +; Verify the cost of scalar population count instructions. + +declare i64 @llvm.ctpop.i64(i64) +declare i32 @llvm.ctpop.i32(i32) +declare i16 @llvm.ctpop.i16(i16) +declare i8 @llvm.ctpop.i8(i8) + +define i64 @var_ctpop_i64(i64 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctpop_i64': +; NOPOPCNT: Found an estimated cost of 4 for instruction: %ctpop +; POPCNT: Found an estimated cost of 1 for instruction: %ctpop + %ctpop = call i64 @llvm.ctpop.i64(i64 %a) + ret i64 %ctpop +} + +define i32 @var_ctpop_i32(i32 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctpop_i32': +; NOPOPCNT: Found an estimated cost of 4 for instruction: %ctpop +; POPCNT: Found an estimated cost of 1 for instruction: %ctpop + %ctpop = call i32 @llvm.ctpop.i32(i32 %a) + ret i32 %ctpop +} + +define i16 @var_ctpop_i16(i16 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctpop_i16': +; NOPOPCNT: Found an estimated cost of 4 for instruction: %ctpop +; POPCNT: Found an estimated cost of 1 for instruction: %ctpop + %ctpop = call i16 @llvm.ctpop.i16(i16 %a) + ret i16 %ctpop +} + +define i8 @var_ctpop_i8(i8 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctpop_i8': +; NOPOPCNT: Found an estimated cost of 4 for instruction: %ctpop +; POPCNT: Found an estimated cost of 1 for instruction: %ctpop + %ctpop = call i8 @llvm.ctpop.i8(i8 %a) + ret i8 %ctpop +} + +; Verify the cost of vector population count instructions. + +declare <2 x i64> @llvm.ctpop.v2i64(<2 x i64>) +declare <4 x i32> @llvm.ctpop.v4i32(<4 x i32>) +declare <8 x i16> @llvm.ctpop.v8i16(<8 x i16>) +declare <16 x i8> @llvm.ctpop.v16i8(<16 x i8>) + +declare <4 x i64> @llvm.ctpop.v4i64(<4 x i64>) +declare <8 x i32> @llvm.ctpop.v8i32(<8 x i32>) +declare <16 x i16> @llvm.ctpop.v16i16(<16 x i16>) +declare <32 x i8> @llvm.ctpop.v32i8(<32 x i8>) + +define <2 x i64> @var_ctpop_v2i64(<2 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctpop_v2i64': +; SSE: Found an estimated cost of 2 for instruction: %ctpop +; AVX: Found an estimated cost of 2 for instruction: %ctpop +; XOP: Found an estimated cost of 2 for instruction: %ctpop + %ctpop = call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %a) + ret <2 x i64> %ctpop +} + +define <4 x i64> @var_ctpop_v4i64(<4 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctpop_v4i64': +; SSE: Found an estimated cost of 4 for instruction: %ctpop +; AVX: Found an estimated cost of 2 for instruction: %ctpop +; XOP: Found an estimated cost of 2 for instruction: %ctpop + %ctpop = call <4 x i64> @llvm.ctpop.v4i64(<4 x i64> %a) + ret <4 x i64> %ctpop +} + +define <4 x i32> @var_ctpop_v4i32(<4 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctpop_v4i32': +; SSE: Found an estimated cost of 2 for instruction: %ctpop +; AVX: Found an estimated cost of 2 for instruction: %ctpop +; XOP: Found an estimated cost of 2 for instruction: %ctpop + %ctpop = call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %a) + ret <4 x i32> %ctpop +} + +define <8 x i32> @var_ctpop_v8i32(<8 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctpop_v8i32': +; SSE: Found an estimated cost of 4 for instruction: %ctpop +; AVX: Found an estimated cost of 2 for instruction: %ctpop +; XOP: Found an estimated cost of 2 for instruction: %ctpop + %ctpop = call <8 x i32> @llvm.ctpop.v8i32(<8 x i32> %a) + ret <8 x i32> %ctpop +} + +define <8 x i16> @var_ctpop_v8i16(<8 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctpop_v8i16': +; SSE: Found an estimated cost of 2 for instruction: %ctpop +; AVX: Found an estimated cost of 2 for instruction: %ctpop +; XOP: Found an estimated cost of 2 for instruction: %ctpop + %ctpop = call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %a) + ret <8 x i16> %ctpop +} + +define <16 x i16> @var_ctpop_v16i16(<16 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctpop_v16i16': +; SSE: Found an estimated cost of 4 for instruction: %ctpop +; AVX: Found an estimated cost of 2 for instruction: %ctpop +; XOP: Found an estimated cost of 2 for instruction: %ctpop + %ctpop = call <16 x i16> @llvm.ctpop.v16i16(<16 x i16> %a) + ret <16 x i16> %ctpop +} + +define <16 x i8> @var_ctpop_v16i8(<16 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctpop_v16i8': +; SSE: Found an estimated cost of 2 for instruction: %ctpop +; AVX: Found an estimated cost of 2 for instruction: %ctpop +; XOP: Found an estimated cost of 2 for instruction: %ctpop + %ctpop = call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %a) + ret <16 x i8> %ctpop +} + +define <32 x i8> @var_ctpop_v32i8(<32 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctpop_v32i8': +; SSE: Found an estimated cost of 4 for instruction: %ctpop +; AVX: Found an estimated cost of 2 for instruction: %ctpop +; XOP: Found an estimated cost of 2 for instruction: %ctpop + %ctpop = call <32 x i8> @llvm.ctpop.v32i8(<32 x i8> %a) + ret <32 x i8> %ctpop +} + +; Verify the cost of scalar leading zero count instructions. + +declare i64 @llvm.ctlz.i64(i64, i1) +declare i32 @llvm.ctlz.i32(i32, i1) +declare i16 @llvm.ctlz.i16(i16, i1) +declare i8 @llvm.ctlz.i8(i8, i1) + +define i64 @var_ctlz_i64(i64 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_i64': +; CHECK: Found an estimated cost of 1 for instruction: %ctlz + %ctlz = call i64 @llvm.ctlz.i64(i64 %a, i1 0) + ret i64 %ctlz +} + +define i64 @var_ctlz_i64u(i64 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_i64u': +; CHECK: Found an estimated cost of 1 for instruction: %ctlz + %ctlz = call i64 @llvm.ctlz.i64(i64 %a, i1 1) + ret i64 %ctlz +} + +define i32 @var_ctlz_i32(i32 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_i32': +; CHECK: Found an estimated cost of 1 for instruction: %ctlz + %ctlz = call i32 @llvm.ctlz.i32(i32 %a, i1 0) + ret i32 %ctlz +} + +define i32 @var_ctlz_i32u(i32 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_i32u': +; CHECK: Found an estimated cost of 1 for instruction: %ctlz + %ctlz = call i32 @llvm.ctlz.i32(i32 %a, i1 1) + ret i32 %ctlz +} + +define i16 @var_ctlz_i16(i16 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_i16': +; CHECK: Found an estimated cost of 1 for instruction: %ctlz + %ctlz = call i16 @llvm.ctlz.i16(i16 %a, i1 0) + ret i16 %ctlz +} + +define i16 @var_ctlz_i16u(i16 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_i16u': +; CHECK: Found an estimated cost of 1 for instruction: %ctlz + %ctlz = call i16 @llvm.ctlz.i16(i16 %a, i1 1) + ret i16 %ctlz +} + +define i8 @var_ctlz_i8(i8 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_i8': +; CHECK: Found an estimated cost of 1 for instruction: %ctlz + %ctlz = call i8 @llvm.ctlz.i8(i8 %a, i1 0) + ret i8 %ctlz +} + +define i8 @var_ctlz_i8u(i8 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_i8u': +; CHECK: Found an estimated cost of 1 for instruction: %ctlz + %ctlz = call i8 @llvm.ctlz.i8(i8 %a, i1 1) + ret i8 %ctlz +} + +; Verify the cost of vector leading zero count instructions. + +declare <2 x i64> @llvm.ctlz.v2i64(<2 x i64>, i1) +declare <4 x i32> @llvm.ctlz.v4i32(<4 x i32>, i1) +declare <8 x i16> @llvm.ctlz.v8i16(<8 x i16>, i1) +declare <16 x i8> @llvm.ctlz.v16i8(<16 x i8>, i1) + +declare <4 x i64> @llvm.ctlz.v4i64(<4 x i64>, i1) +declare <8 x i32> @llvm.ctlz.v8i32(<8 x i32>, i1) +declare <16 x i16> @llvm.ctlz.v16i16(<16 x i16>, i1) +declare <32 x i8> @llvm.ctlz.v32i8(<32 x i8>, i1) + +define <2 x i64> @var_ctlz_v2i64(<2 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v2i64': +; SSE: Found an estimated cost of 6 for instruction: %ctlz +; AVX: Found an estimated cost of 6 for instruction: %ctlz +; XOP: Found an estimated cost of 6 for instruction: %ctlz + %ctlz = call <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %a, i1 0) + ret <2 x i64> %ctlz +} + +define <2 x i64> @var_ctlz_v2i64u(<2 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v2i64u': +; SSE: Found an estimated cost of 6 for instruction: %ctlz +; AVX: Found an estimated cost of 6 for instruction: %ctlz +; XOP: Found an estimated cost of 6 for instruction: %ctlz + %ctlz = call <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %a, i1 1) + ret <2 x i64> %ctlz +} + +define <4 x i64> @var_ctlz_v4i64(<4 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v4i64': +; SSE: Found an estimated cost of 12 for instruction: %ctlz +; AVX: Found an estimated cost of 12 for instruction: %ctlz +; XOP: Found an estimated cost of 12 for instruction: %ctlz + %ctlz = call <4 x i64> @llvm.ctlz.v4i64(<4 x i64> %a, i1 0) + ret <4 x i64> %ctlz +} + +define <4 x i64> @var_ctlz_v4i64u(<4 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v4i64u': +; SSE: Found an estimated cost of 12 for instruction: %ctlz +; AVX: Found an estimated cost of 12 for instruction: %ctlz +; XOP: Found an estimated cost of 12 for instruction: %ctlz + %ctlz = call <4 x i64> @llvm.ctlz.v4i64(<4 x i64> %a, i1 1) + ret <4 x i64> %ctlz +} + +define <4 x i32> @var_ctlz_v4i32(<4 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v4i32': +; SSE: Found an estimated cost of 12 for instruction: %ctlz +; AVX: Found an estimated cost of 12 for instruction: %ctlz +; XOP: Found an estimated cost of 12 for instruction: %ctlz + %ctlz = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %a, i1 0) + ret <4 x i32> %ctlz +} + +define <4 x i32> @var_ctlz_v4i32u(<4 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v4i32u': +; SSE: Found an estimated cost of 12 for instruction: %ctlz +; AVX: Found an estimated cost of 12 for instruction: %ctlz +; XOP: Found an estimated cost of 12 for instruction: %ctlz + %ctlz = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %a, i1 1) + ret <4 x i32> %ctlz +} + +define <8 x i32> @var_ctlz_v8i32(<8 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v8i32': +; SSE: Found an estimated cost of 24 for instruction: %ctlz +; AVX: Found an estimated cost of 24 for instruction: %ctlz +; XOP: Found an estimated cost of 24 for instruction: %ctlz + %ctlz = call <8 x i32> @llvm.ctlz.v8i32(<8 x i32> %a, i1 0) + ret <8 x i32> %ctlz +} + +define <8 x i32> @var_ctlz_v8i32u(<8 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v8i32u': +; SSE: Found an estimated cost of 24 for instruction: %ctlz +; AVX: Found an estimated cost of 24 for instruction: %ctlz +; XOP: Found an estimated cost of 24 for instruction: %ctlz + %ctlz = call <8 x i32> @llvm.ctlz.v8i32(<8 x i32> %a, i1 1) + ret <8 x i32> %ctlz +} + +define <8 x i16> @var_ctlz_v8i16(<8 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v8i16': +; SSE: Found an estimated cost of 24 for instruction: %ctlz +; AVX: Found an estimated cost of 24 for instruction: %ctlz +; XOP: Found an estimated cost of 24 for instruction: %ctlz + %ctlz = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %a, i1 0) + ret <8 x i16> %ctlz +} + +define <8 x i16> @var_ctlz_v8i16u(<8 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v8i16u': +; SSE: Found an estimated cost of 24 for instruction: %ctlz +; AVX: Found an estimated cost of 24 for instruction: %ctlz +; XOP: Found an estimated cost of 24 for instruction: %ctlz + %ctlz = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %a, i1 1) + ret <8 x i16> %ctlz +} + +define <16 x i16> @var_ctlz_v16i16(<16 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v16i16': +; SSE: Found an estimated cost of 48 for instruction: %ctlz +; AVX: Found an estimated cost of 48 for instruction: %ctlz +; XOP: Found an estimated cost of 48 for instruction: %ctlz + %ctlz = call <16 x i16> @llvm.ctlz.v16i16(<16 x i16> %a, i1 0) + ret <16 x i16> %ctlz +} + +define <16 x i16> @var_ctlz_v16i16u(<16 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v16i16u': +; SSE: Found an estimated cost of 48 for instruction: %ctlz +; AVX: Found an estimated cost of 48 for instruction: %ctlz +; XOP: Found an estimated cost of 48 for instruction: %ctlz + %ctlz = call <16 x i16> @llvm.ctlz.v16i16(<16 x i16> %a, i1 1) + ret <16 x i16> %ctlz +} + +define <16 x i8> @var_ctlz_v16i8(<16 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v16i8': +; SSE: Found an estimated cost of 48 for instruction: %ctlz +; AVX: Found an estimated cost of 48 for instruction: %ctlz +; XOP: Found an estimated cost of 48 for instruction: %ctlz + %ctlz = call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %a, i1 0) + ret <16 x i8> %ctlz +} + +define <16 x i8> @var_ctlz_v16i8u(<16 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v16i8u': +; SSE: Found an estimated cost of 48 for instruction: %ctlz +; AVX: Found an estimated cost of 48 for instruction: %ctlz +; XOP: Found an estimated cost of 48 for instruction: %ctlz + %ctlz = call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %a, i1 1) + ret <16 x i8> %ctlz +} + +define <32 x i8> @var_ctlz_v32i8(<32 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v32i8': +; SSE: Found an estimated cost of 96 for instruction: %ctlz +; AVX: Found an estimated cost of 96 for instruction: %ctlz +; XOP: Found an estimated cost of 96 for instruction: %ctlz + %ctlz = call <32 x i8> @llvm.ctlz.v32i8(<32 x i8> %a, i1 0) + ret <32 x i8> %ctlz +} + +define <32 x i8> @var_ctlz_v32i8u(<32 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_ctlz_v32i8u': +; SSE: Found an estimated cost of 96 for instruction: %ctlz +; AVX: Found an estimated cost of 96 for instruction: %ctlz +; XOP: Found an estimated cost of 96 for instruction: %ctlz + %ctlz = call <32 x i8> @llvm.ctlz.v32i8(<32 x i8> %a, i1 1) + ret <32 x i8> %ctlz +} + +; Verify the cost of scalar trailing zero count instructions. + +declare i64 @llvm.cttz.i64(i64, i1) +declare i32 @llvm.cttz.i32(i32, i1) +declare i16 @llvm.cttz.i16(i16, i1) +declare i8 @llvm.cttz.i8(i8, i1) + +define i64 @var_cttz_i64(i64 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_i64': +; CHECK: Found an estimated cost of 1 for instruction: %cttz + %cttz = call i64 @llvm.cttz.i64(i64 %a, i1 0) + ret i64 %cttz +} + +define i64 @var_cttz_i64u(i64 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_i64u': +; CHECK: Found an estimated cost of 1 for instruction: %cttz + %cttz = call i64 @llvm.cttz.i64(i64 %a, i1 1) + ret i64 %cttz +} + +define i32 @var_cttz_i32(i32 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_i32': +; CHECK: Found an estimated cost of 1 for instruction: %cttz + %cttz = call i32 @llvm.cttz.i32(i32 %a, i1 0) + ret i32 %cttz +} + +define i32 @var_cttz_i32u(i32 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_i32u': +; CHECK: Found an estimated cost of 1 for instruction: %cttz + %cttz = call i32 @llvm.cttz.i32(i32 %a, i1 1) + ret i32 %cttz +} + +define i16 @var_cttz_i16(i16 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_i16': +; CHECK: Found an estimated cost of 1 for instruction: %cttz + %cttz = call i16 @llvm.cttz.i16(i16 %a, i1 0) + ret i16 %cttz +} + +define i16 @var_cttz_i16u(i16 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_i16u': +; CHECK: Found an estimated cost of 1 for instruction: %cttz + %cttz = call i16 @llvm.cttz.i16(i16 %a, i1 1) + ret i16 %cttz +} + +define i8 @var_cttz_i8(i8 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_i8': +; CHECK: Found an estimated cost of 1 for instruction: %cttz + %cttz = call i8 @llvm.cttz.i8(i8 %a, i1 0) + ret i8 %cttz +} + +define i8 @var_cttz_i8u(i8 %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_i8u': +; CHECK: Found an estimated cost of 1 for instruction: %cttz + %cttz = call i8 @llvm.cttz.i8(i8 %a, i1 1) + ret i8 %cttz +} + +; Verify the cost of vector trailing zero count instructions. + +declare <2 x i64> @llvm.cttz.v2i64(<2 x i64>, i1) +declare <4 x i32> @llvm.cttz.v4i32(<4 x i32>, i1) +declare <8 x i16> @llvm.cttz.v8i16(<8 x i16>, i1) +declare <16 x i8> @llvm.cttz.v16i8(<16 x i8>, i1) + +declare <4 x i64> @llvm.cttz.v4i64(<4 x i64>, i1) +declare <8 x i32> @llvm.cttz.v8i32(<8 x i32>, i1) +declare <16 x i16> @llvm.cttz.v16i16(<16 x i16>, i1) +declare <32 x i8> @llvm.cttz.v32i8(<32 x i8>, i1) + +define <2 x i64> @var_cttz_v2i64(<2 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v2i64': +; SSE: Found an estimated cost of 6 for instruction: %cttz +; AVX: Found an estimated cost of 6 for instruction: %cttz +; XOP: Found an estimated cost of 6 for instruction: %cttz + %cttz = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %a, i1 0) + ret <2 x i64> %cttz +} + +define <2 x i64> @var_cttz_v2i64u(<2 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v2i64u': +; SSE: Found an estimated cost of 6 for instruction: %cttz +; AVX: Found an estimated cost of 6 for instruction: %cttz +; XOP: Found an estimated cost of 6 for instruction: %cttz + %cttz = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %a, i1 1) + ret <2 x i64> %cttz +} + +define <4 x i64> @var_cttz_v4i64(<4 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v4i64': +; SSE: Found an estimated cost of 12 for instruction: %cttz +; AVX: Found an estimated cost of 12 for instruction: %cttz +; XOP: Found an estimated cost of 12 for instruction: %cttz + %cttz = call <4 x i64> @llvm.cttz.v4i64(<4 x i64> %a, i1 0) + ret <4 x i64> %cttz +} + +define <4 x i64> @var_cttz_v4i64u(<4 x i64> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v4i64u': +; SSE: Found an estimated cost of 12 for instruction: %cttz +; AVX: Found an estimated cost of 12 for instruction: %cttz +; XOP: Found an estimated cost of 12 for instruction: %cttz + %cttz = call <4 x i64> @llvm.cttz.v4i64(<4 x i64> %a, i1 1) + ret <4 x i64> %cttz +} + +define <4 x i32> @var_cttz_v4i32(<4 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v4i32': +; SSE: Found an estimated cost of 12 for instruction: %cttz +; AVX: Found an estimated cost of 12 for instruction: %cttz +; XOP: Found an estimated cost of 12 for instruction: %cttz + %cttz = call <4 x i32> @llvm.cttz.v4i32(<4 x i32> %a, i1 0) + ret <4 x i32> %cttz +} + +define <4 x i32> @var_cttz_v4i32u(<4 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v4i32u': +; SSE: Found an estimated cost of 12 for instruction: %cttz +; AVX: Found an estimated cost of 12 for instruction: %cttz +; XOP: Found an estimated cost of 12 for instruction: %cttz + %cttz = call <4 x i32> @llvm.cttz.v4i32(<4 x i32> %a, i1 1) + ret <4 x i32> %cttz +} + +define <8 x i32> @var_cttz_v8i32(<8 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v8i32': +; SSE: Found an estimated cost of 24 for instruction: %cttz +; AVX: Found an estimated cost of 24 for instruction: %cttz +; XOP: Found an estimated cost of 24 for instruction: %cttz + %cttz = call <8 x i32> @llvm.cttz.v8i32(<8 x i32> %a, i1 0) + ret <8 x i32> %cttz +} + +define <8 x i32> @var_cttz_v8i32u(<8 x i32> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v8i32u': +; SSE: Found an estimated cost of 24 for instruction: %cttz +; AVX: Found an estimated cost of 24 for instruction: %cttz +; XOP: Found an estimated cost of 24 for instruction: %cttz + %cttz = call <8 x i32> @llvm.cttz.v8i32(<8 x i32> %a, i1 1) + ret <8 x i32> %cttz +} + +define <8 x i16> @var_cttz_v8i16(<8 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v8i16': +; SSE: Found an estimated cost of 24 for instruction: %cttz +; AVX: Found an estimated cost of 24 for instruction: %cttz +; XOP: Found an estimated cost of 24 for instruction: %cttz + %cttz = call <8 x i16> @llvm.cttz.v8i16(<8 x i16> %a, i1 0) + ret <8 x i16> %cttz +} + +define <8 x i16> @var_cttz_v8i16u(<8 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v8i16u': +; SSE: Found an estimated cost of 24 for instruction: %cttz +; AVX: Found an estimated cost of 24 for instruction: %cttz +; XOP: Found an estimated cost of 24 for instruction: %cttz + %cttz = call <8 x i16> @llvm.cttz.v8i16(<8 x i16> %a, i1 1) + ret <8 x i16> %cttz +} + +define <16 x i16> @var_cttz_v16i16(<16 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v16i16': +; SSE: Found an estimated cost of 48 for instruction: %cttz +; AVX: Found an estimated cost of 48 for instruction: %cttz +; XOP: Found an estimated cost of 48 for instruction: %cttz + %cttz = call <16 x i16> @llvm.cttz.v16i16(<16 x i16> %a, i1 0) + ret <16 x i16> %cttz +} + +define <16 x i16> @var_cttz_v16i16u(<16 x i16> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v16i16u': +; SSE: Found an estimated cost of 48 for instruction: %cttz +; AVX: Found an estimated cost of 48 for instruction: %cttz +; XOP: Found an estimated cost of 48 for instruction: %cttz + %cttz = call <16 x i16> @llvm.cttz.v16i16(<16 x i16> %a, i1 1) + ret <16 x i16> %cttz +} + +define <16 x i8> @var_cttz_v16i8(<16 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v16i8': +; SSE: Found an estimated cost of 48 for instruction: %cttz +; AVX: Found an estimated cost of 48 for instruction: %cttz +; XOP: Found an estimated cost of 48 for instruction: %cttz + %cttz = call <16 x i8> @llvm.cttz.v16i8(<16 x i8> %a, i1 0) + ret <16 x i8> %cttz +} + +define <16 x i8> @var_cttz_v16i8u(<16 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v16i8u': +; SSE: Found an estimated cost of 48 for instruction: %cttz +; AVX: Found an estimated cost of 48 for instruction: %cttz +; XOP: Found an estimated cost of 48 for instruction: %cttz + %cttz = call <16 x i8> @llvm.cttz.v16i8(<16 x i8> %a, i1 1) + ret <16 x i8> %cttz +} + +define <32 x i8> @var_cttz_v32i8(<32 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v32i8': +; SSE: Found an estimated cost of 96 for instruction: %cttz +; AVX: Found an estimated cost of 96 for instruction: %cttz +; XOP: Found an estimated cost of 96 for instruction: %cttz + %cttz = call <32 x i8> @llvm.cttz.v32i8(<32 x i8> %a, i1 0) + ret <32 x i8> %cttz +} + +define <32 x i8> @var_cttz_v32i8u(<32 x i8> %a) { +; CHECK: 'Cost Model Analysis' for function 'var_cttz_v32i8u': +; SSE: Found an estimated cost of 96 for instruction: %cttz +; AVX: Found an estimated cost of 96 for instruction: %cttz +; XOP: Found an estimated cost of 96 for instruction: %cttz + %cttz = call <32 x i8> @llvm.cttz.v32i8(<32 x i8> %a, i1 1) + ret <32 x i8> %cttz +} diff --git a/test/Analysis/CostModel/X86/masked-intrinsic-cost.ll b/test/Analysis/CostModel/X86/masked-intrinsic-cost.ll index 61d3e0116e8b4..f2d3f3f0ce639 100644 --- a/test/Analysis/CostModel/X86/masked-intrinsic-cost.ll +++ b/test/Analysis/CostModel/X86/masked-intrinsic-cost.ll @@ -7,7 +7,7 @@ ; AVX2: Found an estimated cost of 4 {{.*}}.masked define <2 x double> @test1(<2 x i64> %trigger, <2 x double>* %addr, <2 x double> %dst) { %mask = icmp eq <2 x i64> %trigger, zeroinitializer - %res = call <2 x double> @llvm.masked.load.v2f64(<2 x double>* %addr, i32 4, <2 x i1>%mask, <2 x double>%dst) + %res = call <2 x double> @llvm.masked.load.v2f64.p0v2f64(<2 x double>* %addr, i32 4, <2 x i1>%mask, <2 x double>%dst) ret <2 x double> %res } @@ -15,7 +15,7 @@ define <2 x double> @test1(<2 x i64> %trigger, <2 x double>* %addr, <2 x double> ; AVX2: Found an estimated cost of 4 {{.*}}.masked define <4 x i32> @test2(<4 x i32> %trigger, <4 x i32>* %addr, <4 x i32> %dst) { %mask = icmp eq <4 x i32> %trigger, zeroinitializer - %res = call <4 x i32> @llvm.masked.load.v4i32(<4 x i32>* %addr, i32 4, <4 x i1>%mask, <4 x i32>%dst) + %res = call <4 x i32> @llvm.masked.load.v4i32.p0v4i32(<4 x i32>* %addr, i32 4, <4 x i1>%mask, <4 x i32>%dst) ret <4 x i32> %res } @@ -23,7 +23,7 @@ define <4 x i32> @test2(<4 x i32> %trigger, <4 x i32>* %addr, <4 x i32> %dst) { ; AVX2: Found an estimated cost of 4 {{.*}}.masked define void @test3(<4 x i32> %trigger, <4 x i32>* %addr, <4 x i32> %val) { %mask = icmp eq <4 x i32> %trigger, zeroinitializer - call void @llvm.masked.store.v4i32(<4 x i32>%val, <4 x i32>* %addr, i32 4, <4 x i1>%mask) + call void @llvm.masked.store.v4i32.p0v4i32(<4 x i32>%val, <4 x i32>* %addr, i32 4, <4 x i1>%mask) ret void } @@ -31,7 +31,7 @@ define void @test3(<4 x i32> %trigger, <4 x i32>* %addr, <4 x i32> %val) { ; AVX2: Found an estimated cost of 4 {{.*}}.masked define <8 x float> @test4(<8 x i32> %trigger, <8 x float>* %addr, <8 x float> %dst) { %mask = icmp eq <8 x i32> %trigger, zeroinitializer - %res = call <8 x float> @llvm.masked.load.v8f32(<8 x float>* %addr, i32 4, <8 x i1>%mask, <8 x float>%dst) + %res = call <8 x float> @llvm.masked.load.v8f32.p0v8f32(<8 x float>* %addr, i32 4, <8 x i1>%mask, <8 x float>%dst) ret <8 x float> %res } @@ -39,7 +39,7 @@ define <8 x float> @test4(<8 x i32> %trigger, <8 x float>* %addr, <8 x float> %d ; AVX2: Found an estimated cost of 5 {{.*}}.masked define void @test5(<2 x i32> %trigger, <2 x float>* %addr, <2 x float> %val) { %mask = icmp eq <2 x i32> %trigger, zeroinitializer - call void @llvm.masked.store.v2f32(<2 x float>%val, <2 x float>* %addr, i32 4, <2 x i1>%mask) + call void @llvm.masked.store.v2f32.p0v2f32(<2 x float>%val, <2 x float>* %addr, i32 4, <2 x i1>%mask) ret void } @@ -47,7 +47,7 @@ define void @test5(<2 x i32> %trigger, <2 x float>* %addr, <2 x float> %val) { ; AVX2: Found an estimated cost of 6 {{.*}}.masked define void @test6(<2 x i32> %trigger, <2 x i32>* %addr, <2 x i32> %val) { %mask = icmp eq <2 x i32> %trigger, zeroinitializer - call void @llvm.masked.store.v2i32(<2 x i32>%val, <2 x i32>* %addr, i32 4, <2 x i1>%mask) + call void @llvm.masked.store.v2i32.p0v2i32(<2 x i32>%val, <2 x i32>* %addr, i32 4, <2 x i1>%mask) ret void } @@ -55,7 +55,7 @@ define void @test6(<2 x i32> %trigger, <2 x i32>* %addr, <2 x i32> %val) { ; AVX2: Found an estimated cost of 5 {{.*}}.masked define <2 x float> @test7(<2 x i32> %trigger, <2 x float>* %addr, <2 x float> %dst) { %mask = icmp eq <2 x i32> %trigger, zeroinitializer - %res = call <2 x float> @llvm.masked.load.v2f32(<2 x float>* %addr, i32 4, <2 x i1>%mask, <2 x float>%dst) + %res = call <2 x float> @llvm.masked.load.v2f32.p0v2f32(<2 x float>* %addr, i32 4, <2 x i1>%mask, <2 x float>%dst) ret <2 x float> %res } @@ -63,7 +63,7 @@ define <2 x float> @test7(<2 x i32> %trigger, <2 x float>* %addr, <2 x float> %d ; AVX2: Found an estimated cost of 6 {{.*}}.masked define <2 x i32> @test8(<2 x i32> %trigger, <2 x i32>* %addr, <2 x i32> %dst) { %mask = icmp eq <2 x i32> %trigger, zeroinitializer - %res = call <2 x i32> @llvm.masked.load.v2i32(<2 x i32>* %addr, i32 4, <2 x i1>%mask, <2 x i32>%dst) + %res = call <2 x i32> @llvm.masked.load.v2i32.p0v2i32(<2 x i32>* %addr, i32 4, <2 x i1>%mask, <2 x i32>%dst) ret <2 x i32> %res } @@ -279,24 +279,22 @@ declare void @llvm.masked.scatter.v4i32(<4 x i32> %a1, <4 x i32*> %ptr, i32, <4 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>) -declare <2 x i32> @llvm.masked.load.v2i32(<2 x i32>*, i32, <2 x i1>, <2 x i32>) -declare void @llvm.masked.store.v16i32(<16 x i32>, <16 x i32>*, i32, <16 x i1>) -declare void @llvm.masked.store.v8i32(<8 x i32>, <8 x i32>*, i32, <8 x i1>) -declare void @llvm.masked.store.v4i32(<4 x i32>, <4 x i32>*, i32, <4 x i1>) -declare void @llvm.masked.store.v2f32(<2 x float>, <2 x float>*, i32, <2 x i1>) -declare void @llvm.masked.store.v2i32(<2 x i32>, <2 x i32>*, i32, <2 x i1>) -declare void @llvm.masked.store.v16f32(<16 x float>, <16 x float>*, i32, <16 x i1>) -declare void @llvm.masked.store.v16f32p(<16 x float>*, <16 x float>**, i32, <16 x i1>) -declare <16 x float> @llvm.masked.load.v16f32(<16 x float>*, i32, <16 x i1>, <16 x float>) -declare <8 x float> @llvm.masked.load.v8f32(<8 x float>*, i32, <8 x i1>, <8 x float>) -declare <4 x float> @llvm.masked.load.v4f32(<4 x float>*, i32, <4 x i1>, <4 x float>) -declare <2 x float> @llvm.masked.load.v2f32(<2 x float>*, i32, <2 x i1>, <2 x float>) -declare <8 x double> @llvm.masked.load.v8f64(<8 x double>*, i32, <8 x i1>, <8 x double>) -declare <4 x double> @llvm.masked.load.v4f64(<4 x double>*, i32, <4 x i1>, <4 x double>) -declare <2 x double> @llvm.masked.load.v2f64(<2 x double>*, i32, <2 x i1>, <2 x double>) -declare void @llvm.masked.store.v8f64(<8 x double>, <8 x double>*, i32, <8 x i1>) -declare void @llvm.masked.store.v2f64(<2 x double>, <2 x double>*, i32, <2 x i1>) -declare void @llvm.masked.store.v2i64(<2 x i64>, <2 x i64>*, i32, <2 x i1>) - +declare <16 x i32> @llvm.masked.load.v16i32.p0v16i32(<16 x i32>*, i32, <16 x i1>, <16 x i32>) +declare <4 x i32> @llvm.masked.load.v4i32.p0v4i32(<4 x i32>*, i32, <4 x i1>, <4 x i32>) +declare <2 x i32> @llvm.masked.load.v2i32.p0v2i32(<2 x i32>*, i32, <2 x i1>, <2 x i32>) +declare void @llvm.masked.store.v16i32.p0v16i32(<16 x i32>, <16 x i32>*, i32, <16 x i1>) +declare void @llvm.masked.store.v8i32.p0v8i32(<8 x i32>, <8 x i32>*, i32, <8 x i1>) +declare void @llvm.masked.store.v4i32.p0v4i32(<4 x i32>, <4 x i32>*, i32, <4 x i1>) +declare void @llvm.masked.store.v2f32.p0v2f32(<2 x float>, <2 x float>*, i32, <2 x i1>) +declare void @llvm.masked.store.v2i32.p0v2i32(<2 x i32>, <2 x i32>*, i32, <2 x i1>) +declare void @llvm.masked.store.v16f32.p0v16f32(<16 x float>, <16 x float>*, i32, <16 x i1>) +declare <16 x float> @llvm.masked.load.v16f32.p0v16f32(<16 x float>*, i32, <16 x i1>, <16 x float>) +declare <8 x float> @llvm.masked.load.v8f32.p0v8f32(<8 x float>*, i32, <8 x i1>, <8 x float>) +declare <4 x float> @llvm.masked.load.v4f32.p0v4f32(<4 x float>*, i32, <4 x i1>, <4 x float>) +declare <2 x float> @llvm.masked.load.v2f32.p0v2f32(<2 x float>*, i32, <2 x i1>, <2 x float>) +declare <8 x double> @llvm.masked.load.v8f64.p0v8f64(<8 x double>*, i32, <8 x i1>, <8 x double>) +declare <4 x double> @llvm.masked.load.v4f64.p0v4f64(<4 x double>*, i32, <4 x i1>, <4 x double>) +declare <2 x double> @llvm.masked.load.v2f64.p0v2f64(<2 x double>*, i32, <2 x i1>, <2 x double>) +declare void @llvm.masked.store.v8f64.p0v8f64(<8 x double>, <8 x double>*, i32, <8 x i1>) +declare void @llvm.masked.store.v2f64.p0v2f64(<2 x double>, <2 x double>*, i32, <2 x i1>) +declare void @llvm.masked.store.v2i64.p0v2i64(<2 x i64>, <2 x i64>*, i32, <2 x i1>) diff --git a/test/Analysis/CostModel/X86/scalarize.ll b/test/Analysis/CostModel/X86/scalarize.ll index fc25fcbc563f6..fd4e3005bd9f8 100644 --- a/test/Analysis/CostModel/X86/scalarize.ll +++ b/test/Analysis/CostModel/X86/scalarize.ll @@ -13,27 +13,27 @@ declare %i4 @llvm.bswap.v4i32(%i4) declare %i8 @llvm.bswap.v2i64(%i8) -declare %i4 @llvm.ctpop.v4i32(%i4) -declare %i8 @llvm.ctpop.v2i64(%i8) +declare %i4 @llvm.cttz.v4i32(%i4) +declare %i8 @llvm.cttz.v2i64(%i8) ; CHECK32-LABEL: test_scalarized_intrinsics ; CHECK64-LABEL: test_scalarized_intrinsics define void @test_scalarized_intrinsics() { %r1 = add %i8 undef, undef -; CHECK32: cost of 12 {{.*}}bswap.v4i32 -; CHECK64: cost of 12 {{.*}}bswap.v4i32 +; CHECK32: cost of 1 {{.*}}bswap.v4i32 +; CHECK64: cost of 1 {{.*}}bswap.v4i32 %r2 = call %i4 @llvm.bswap.v4i32(%i4 undef) -; CHECK32: cost of 10 {{.*}}bswap.v2i64 -; CHECK64: cost of 6 {{.*}}bswap.v2i64 +; CHECK32: cost of 1 {{.*}}bswap.v2i64 +; CHECK64: cost of 1 {{.*}}bswap.v2i64 %r3 = call %i8 @llvm.bswap.v2i64(%i8 undef) -; CHECK32: cost of 12 {{.*}}ctpop.v4i32 -; CHECK64: cost of 12 {{.*}}ctpop.v4i32 - %r4 = call %i4 @llvm.ctpop.v4i32(%i4 undef) -; CHECK32: cost of 10 {{.*}}ctpop.v2i64 -; CHECK64: cost of 6 {{.*}}ctpop.v2i64 - %r5 = call %i8 @llvm.ctpop.v2i64(%i8 undef) +; CHECK32: cost of 12 {{.*}}cttz.v4i32 +; CHECK64: cost of 12 {{.*}}cttz.v4i32 + %r4 = call %i4 @llvm.cttz.v4i32(%i4 undef) +; CHECK32: cost of 10 {{.*}}cttz.v2i64 +; CHECK64: cost of 6 {{.*}}cttz.v2i64 + %r5 = call %i8 @llvm.cttz.v2i64(%i8 undef) ; CHECK32: ret ; CHECK64: ret diff --git a/test/Analysis/CostModel/X86/sitofp.ll b/test/Analysis/CostModel/X86/sitofp.ll index 9f0c4065c1788..fb390a2b17aa9 100644 --- a/test/Analysis/CostModel/X86/sitofp.ll +++ b/test/Analysis/CostModel/X86/sitofp.ll @@ -40,10 +40,10 @@ define <8 x double> @sitofpv8i8v8double(<8 x i8> %a) { ; SSE2: cost of 80 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv8i8v8double - ; AVX1: cost of 20 {{.*}} sitofp + ; AVX1: cost of 7 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv8i8v8double - ; AVX2: cost of 20 {{.*}} sitofp + ; AVX2: cost of 7 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv8i8v8double ; AVX512F: cost of 2 {{.*}} sitofp @@ -56,13 +56,13 @@ define <16 x double> @sitofpv16i8v16double(<16 x i8> %a) { ; SSE2: cost of 160 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv16i8v16double - ; AVX1: cost of 40 {{.*}} sitofp + ; AVX1: cost of 15 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv16i8v16double - ; AVX2: cost of 40 {{.*}} sitofp + ; AVX2: cost of 15 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv16i8v16double - ; AVX512F: cost of 44 {{.*}} sitofp + ; AVX512F: cost of 5 {{.*}} sitofp %1 = sitofp <16 x i8> %a to <16 x double> ret <16 x double> %1 } @@ -72,13 +72,13 @@ define <32 x double> @sitofpv32i8v32double(<32 x i8> %a) { ; SSE2: cost of 320 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv32i8v32double - ; AVX1: cost of 80 {{.*}} sitofp + ; AVX1: cost of 31 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv32i8v32double - ; AVX2: cost of 80 {{.*}} sitofp + ; AVX2: cost of 31 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv32i8v32double - ; AVX512F: cost of 88 {{.*}} sitofp + ; AVX512F: cost of 11 {{.*}} sitofp %1 = sitofp <32 x i8> %a to <32 x double> ret <32 x double> %1 } @@ -120,10 +120,10 @@ define <8 x double> @sitofpv8i16v8double(<8 x i16> %a) { ; SSE2: cost of 80 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv8i16v8double - ; AVX1: cost of 20 {{.*}} sitofp + ; AVX1: cost of 7 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv8i16v8double - ; AVX2: cost of 20 {{.*}} sitofp + ; AVX2: cost of 7 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv8i16v8double ; AVX512F: cost of 2 {{.*}} sitofp @@ -136,13 +136,13 @@ define <16 x double> @sitofpv16i16v16double(<16 x i16> %a) { ; SSE2: cost of 160 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv16i16v16double - ; AVX1: cost of 40 {{.*}} sitofp + ; AVX1: cost of 15 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv16i16v16double - ; AVX2: cost of 40 {{.*}} sitofp + ; AVX2: cost of 15 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv16i16v16double - ; AVX512F: cost of 44 {{.*}} sitofp + ; AVX512F: cost of 5 {{.*}} sitofp %1 = sitofp <16 x i16> %a to <16 x double> ret <16 x double> %1 } @@ -152,13 +152,13 @@ define <32 x double> @sitofpv32i16v32double(<32 x i16> %a) { ; SSE2: cost of 320 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv32i16v32double - ; AVX1: cost of 80 {{.*}} sitofp + ; AVX1: cost of 31 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv32i16v32double - ; AVX2: cost of 80 {{.*}} sitofp + ; AVX2: cost of 31 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv32i16v32double - ; AVX512F: cost of 88 {{.*}} sitofp + ; AVX512F: cost of 11 {{.*}} sitofp %1 = sitofp <32 x i16> %a to <32 x double> ret <32 x double> %1 } @@ -200,10 +200,10 @@ define <8 x double> @sitofpv8i32v8double(<8 x i32> %a) { ; SSE2: cost of 80 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv8i32v8double - ; AVX1: cost of 20 {{.*}} sitofp + ; AVX1: cost of 3 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv8i32v8double - ; AVX2: cost of 20 {{.*}} sitofp + ; AVX2: cost of 3 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv8i32v8double ; AVX512F: cost of 1 {{.*}} sitofp @@ -216,13 +216,13 @@ define <16 x double> @sitofpv16i32v16double(<16 x i32> %a) { ; SSE2: cost of 160 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv16i32v16double - ; AVX1: cost of 40 {{.*}} sitofp + ; AVX1: cost of 7 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv16i32v16double - ; AVX2: cost of 40 {{.*}} sitofp + ; AVX2: cost of 7 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv16i32v16double - ; AVX512F: cost of 44 {{.*}} sitofp + ; AVX512F: cost of 3 {{.*}} sitofp %1 = sitofp <16 x i32> %a to <16 x double> ret <16 x double> %1 } @@ -232,13 +232,13 @@ define <32 x double> @sitofpv32i32v32double(<32 x i32> %a) { ; SSE2: cost of 320 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv32i32v32double - ; AVX1: cost of 80 {{.*}} sitofp + ; AVX1: cost of 15 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv32i32v32double - ; AVX2: cost of 80 {{.*}} sitofp + ; AVX2: cost of 15 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv32i32v32double - ; AVX512F: cost of 88 {{.*}} sitofp + ; AVX512F: cost of 7 {{.*}} sitofp %1 = sitofp <32 x i32> %a to <32 x double> ret <32 x double> %1 } @@ -264,13 +264,13 @@ define <4 x double> @sitofpv4i64v4double(<4 x i64> %a) { ; SSE2: cost of 40 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv4i64v4double - ; AVX1: cost of 10 {{.*}} sitofp + ; AVX1: cost of 13 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv4i64v4double - ; AVX2: cost of 10 {{.*}} sitofp + ; AVX2: cost of 13 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv4i64v4double - ; AVX512F: cost of 10 {{.*}} sitofp + ; AVX512F: cost of 13 {{.*}} sitofp %1 = sitofp <4 x i64> %a to <4 x double> ret <4 x double> %1 } @@ -280,10 +280,10 @@ define <8 x double> @sitofpv8i64v8double(<8 x i64> %a) { ; SSE2: cost of 80 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv8i64v8double - ; AVX1: cost of 20 {{.*}} sitofp + ; AVX1: cost of 27 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv8i64v8double - ; AVX2: cost of 20 {{.*}} sitofp + ; AVX2: cost of 27 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv8i64v8double ; AVX512F: cost of 22 {{.*}} sitofp @@ -296,13 +296,13 @@ define <16 x double> @sitofpv16i64v16double(<16 x i64> %a) { ; SSE2: cost of 160 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv16i64v16double - ; AVX1: cost of 40 {{.*}} sitofp + ; AVX1: cost of 55 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv16i64v16double - ; AVX2: cost of 40 {{.*}} sitofp + ; AVX2: cost of 55 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv16i64v16double - ; AVX512F: cost of 44 {{.*}} sitofp + ; AVX512F: cost of 45 {{.*}} sitofp %1 = sitofp <16 x i64> %a to <16 x double> ret <16 x double> %1 } @@ -312,13 +312,13 @@ define <32 x double> @sitofpv32i64v32double(<32 x i64> %a) { ; SSE2: cost of 320 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv32i64v32double - ; AVX1: cost of 80 {{.*}} sitofp + ; AVX1: cost of 111 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv32i64v32double - ; AVX2: cost of 80 {{.*}} sitofp + ; AVX2: cost of 111 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv32i64v32double - ; AVX512F: cost of 88 {{.*}} sitofp + ; AVX512F: cost of 91 {{.*}} sitofp %1 = sitofp <32 x i64> %a to <32 x double> ret <32 x double> %1 } @@ -341,7 +341,7 @@ define <2 x float> @sitofpv2i8v2float(<2 x i8> %a) { define <4 x float> @sitofpv4i8v4float(<4 x i8> %a) { ; SSE2-LABEL: sitofpv4i8v4float - ; SSE2: cost of 15 {{.*}} sitofp + ; SSE2: cost of 5 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv4i8v4float ; AVX1: cost of 3 {{.*}} sitofp @@ -376,10 +376,10 @@ define <16 x float> @sitofpv16i8v16float(<16 x i8> %a) { ; SSE2: cost of 8 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv16i8v16float - ; AVX1: cost of 44 {{.*}} sitofp + ; AVX1: cost of 17 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv16i8v16float - ; AVX2: cost of 44 {{.*}} sitofp + ; AVX2: cost of 17 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv16i8v16float ; AVX512F: cost of 2 {{.*}} sitofp @@ -392,13 +392,13 @@ define <32 x float> @sitofpv32i8v32float(<32 x i8> %a) { ; SSE2: cost of 16 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv32i8v32float - ; AVX1: cost of 88 {{.*}} sitofp + ; AVX1: cost of 35 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv32i8v32float - ; AVX2: cost of 88 {{.*}} sitofp + ; AVX2: cost of 35 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv32i8v32float - ; AVX512F: cost of 92 {{.*}} sitofp + ; AVX512F: cost of 5 {{.*}} sitofp %1 = sitofp <32 x i8> %a to <32 x float> ret <32 x float> %1 } @@ -421,7 +421,7 @@ define <2 x float> @sitofpv2i16v2float(<2 x i16> %a) { define <4 x float> @sitofpv4i16v4float(<4 x i16> %a) { ; SSE2-LABEL: sitofpv4i16v4float - ; SSE2: cost of 15 {{.*}} sitofp + ; SSE2: cost of 5 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv4i16v4float ; AVX1: cost of 3 {{.*}} sitofp @@ -456,10 +456,10 @@ define <16 x float> @sitofpv16i16v16float(<16 x i16> %a) { ; SSE2: cost of 30 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv16i16v16float - ; AVX1: cost of 44 {{.*}} sitofp + ; AVX1: cost of 11 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv16i16v16float - ; AVX2: cost of 44 {{.*}} sitofp + ; AVX2: cost of 11 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv16i16v16float ; AVX512F: cost of 2 {{.*}} sitofp @@ -472,13 +472,13 @@ define <32 x float> @sitofpv32i16v32float(<32 x i16> %a) { ; SSE2: cost of 60 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv32i16v32float - ; AVX1: cost of 88 {{.*}} sitofp + ; AVX1: cost of 23 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv32i16v32float - ; AVX2: cost of 88 {{.*}} sitofp + ; AVX2: cost of 23 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv32i16v32float - ; AVX512F: cost of 92 {{.*}} sitofp + ; AVX512F: cost of 5 {{.*}} sitofp %1 = sitofp <32 x i16> %a to <32 x float> ret <32 x float> %1 } @@ -501,7 +501,7 @@ define <2 x float> @sitofpv2i32v2float(<2 x i32> %a) { define <4 x float> @sitofpv4i32v4float(<4 x i32> %a) { ; SSE2-LABEL: sitofpv4i32v4float - ; SSE2: cost of 15 {{.*}} sitofp + ; SSE2: cost of 5 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv4i32v4float ; AVX1: cost of 1 {{.*}} sitofp @@ -517,7 +517,7 @@ define <4 x float> @sitofpv4i32v4float(<4 x i32> %a) { define <8 x float> @sitofpv8i32v8float(<8 x i32> %a) { ; SSE2-LABEL: sitofpv8i32v8float - ; SSE2: cost of 30 {{.*}} sitofp + ; SSE2: cost of 10 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv8i32v8float ; AVX1: cost of 1 {{.*}} sitofp @@ -533,13 +533,13 @@ define <8 x float> @sitofpv8i32v8float(<8 x i32> %a) { define <16 x float> @sitofpv16i32v16float(<16 x i32> %a) { ; SSE2-LABEL: sitofpv16i32v16float - ; SSE2: cost of 60 {{.*}} sitofp + ; SSE2: cost of 20 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv16i32v16float - ; AVX1: cost of 44 {{.*}} sitofp + ; AVX1: cost of 3 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv16i32v16float - ; AVX2: cost of 44 {{.*}} sitofp + ; AVX2: cost of 3 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv16i32v16float ; AVX512F: cost of 1 {{.*}} sitofp @@ -549,16 +549,16 @@ define <16 x float> @sitofpv16i32v16float(<16 x i32> %a) { define <32 x float> @sitofpv32i32v32float(<32 x i32> %a) { ; SSE2-LABEL: sitofpv32i32v32float - ; SSE2: cost of 120 {{.*}} sitofp + ; SSE2: cost of 40 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv32i32v32float - ; AVX1: cost of 88 {{.*}} sitofp + ; AVX1: cost of 7 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv32i32v32float - ; AVX2: cost of 88 {{.*}} sitofp + ; AVX2: cost of 7 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv32i32v32float - ; AVX512F: cost of 92 {{.*}} sitofp + ; AVX512F: cost of 3 {{.*}} sitofp %1 = sitofp <32 x i32> %a to <32 x float> ret <32 x float> %1 } @@ -600,10 +600,10 @@ define <8 x float> @sitofpv8i64v8float(<8 x i64> %a) { ; SSE2: cost of 60 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv8i64v8float - ; AVX1: cost of 22 {{.*}} sitofp + ; AVX1: cost of 21 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv8i64v8float - ; AVX2: cost of 22 {{.*}} sitofp + ; AVX2: cost of 21 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv8i64v8float ; AVX512F: cost of 22 {{.*}} sitofp @@ -616,13 +616,13 @@ define <16 x float> @sitofpv16i64v16float(<16 x i64> %a) { ; SSE2: cost of 120 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv16i64v16float - ; AVX1: cost of 44 {{.*}} sitofp + ; AVX1: cost of 43 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv16i64v16float - ; AVX2: cost of 44 {{.*}} sitofp + ; AVX2: cost of 43 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv16i64v16float - ; AVX512F: cost of 46 {{.*}} sitofp + ; AVX512F: cost of 45 {{.*}} sitofp %1 = sitofp <16 x i64> %a to <16 x float> ret <16 x float> %1 } @@ -632,13 +632,13 @@ define <32 x float> @sitofpv32i64v32float(<32 x i64> %a) { ; SSE2: cost of 240 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv32i64v32float - ; AVX1: cost of 88 {{.*}} sitofp + ; AVX1: cost of 87 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv32i64v32float - ; AVX2: cost of 88 {{.*}} sitofp + ; AVX2: cost of 87 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv32i64v32float - ; AVX512F: cost of 92 {{.*}} sitofp + ; AVX512F: cost of 91 {{.*}} sitofp %1 = sitofp <32 x i64> %a to <32 x float> ret <32 x float> %1 } @@ -648,10 +648,10 @@ define <8 x double> @sitofpv8i1v8double(<8 x double> %a) { ; SSE2: cost of 80 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv8i1v8double - ; AVX1: cost of 20 {{.*}} sitofp + ; AVX1: cost of 7 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv8i1v8double - ; AVX2: cost of 20 {{.*}} sitofp + ; AVX2: cost of 7 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv8i1v8double ; AVX512F: cost of 4 {{.*}} sitofp @@ -665,10 +665,10 @@ define <16 x float> @sitofpv16i1v16float(<16 x float> %a) { ; SSE2: cost of 8 {{.*}} sitofp ; ; AVX1-LABEL: sitofpv16i1v16float - ; AVX1: cost of 44 {{.*}} sitofp + ; AVX1: cost of 17 {{.*}} sitofp ; ; AVX2-LABEL: sitofpv16i1v16float - ; AVX2: cost of 44 {{.*}} sitofp + ; AVX2: cost of 17 {{.*}} sitofp ; ; AVX512F-LABEL: sitofpv16i1v16float ; AVX512F: cost of 3 {{.*}} sitofp diff --git a/test/Analysis/CostModel/X86/sse-itoi.ll b/test/Analysis/CostModel/X86/sse-itoi.ll index 9e7f26e54d29a..46d9935646098 100644 --- a/test/Analysis/CostModel/X86/sse-itoi.ll +++ b/test/Analysis/CostModel/X86/sse-itoi.ll @@ -1,6 +1,85 @@ ; 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_v4i8_to_v4i64(<4 x i8>* %a) { +; SSE2: zext_v4i8_to_v4i64 +; SSE2: cost of 4 {{.*}} zext +; +; SSE41: zext_v4i8_to_v4i64 +; SSE41: cost of 2 {{.*}} zext +; + %1 = load <4 x i8>, <4 x i8>* %a + %2 = zext <4 x i8> %1 to <4 x i64> + store <4 x i64> %2, <4 x i64>* undef, align 4 + ret void +} + +define void @sext_v4i8_to_v4i64(<4 x i8>* %a) { +; SSE2: sext_v4i8_to_v4i64 +; SSE2: cost of 8 {{.*}} sext +; +; SSE41: sext_v4i8_to_v4i64 +; SSE41: cost of 2 {{.*}} sext +; + %1 = load <4 x i8>, <4 x i8>* %a + %2 = sext <4 x i8> %1 to <4 x i64> + store <4 x i64> %2, <4 x i64>* undef, align 4 + ret void +} + +define void @zext_v4i16_to_v4i64(<4 x i16>* %a) { +; SSE2: zext_v4i16_to_v4i64 +; SSE2: cost of 3 {{.*}} zext +; +; SSE41: zext_v4i16_to_v4i64 +; SSE41: cost of 2 {{.*}} zext +; + %1 = load <4 x i16>, <4 x i16>* %a + %2 = zext <4 x i16> %1 to <4 x i64> + store <4 x i64> %2, <4 x i64>* undef, align 4 + ret void +} + +define void @sext_v4i16_to_v4i64(<4 x i16>* %a) { +; SSE2: sext_v4i16_to_v4i64 +; SSE2: cost of 10 {{.*}} sext +; +; SSE41: sext_v4i16_to_v4i64 +; SSE41: cost of 2 {{.*}} sext +; + %1 = load <4 x i16>, <4 x i16>* %a + %2 = sext <4 x i16> %1 to <4 x i64> + store <4 x i64> %2, <4 x i64>* undef, align 4 + ret void +} + + +define void @zext_v4i32_to_v4i64(<4 x i32>* %a) { +; SSE2: zext_v4i32_to_v4i64 +; SSE2: cost of 3 {{.*}} zext +; +; SSE41: zext_v4i32_to_v4i64 +; SSE41: cost of 2 {{.*}} zext +; + %1 = load <4 x i32>, <4 x i32>* %a + %2 = zext <4 x i32> %1 to <4 x i64> + store <4 x i64> %2, <4 x i64>* undef, align 4 + ret void +} + +define void @sext_v4i32_to_v4i64(<4 x i32>* %a) { +; SSE2: sext_v4i32_to_v4i64 +; SSE2: cost of 5 {{.*}} sext +; +; SSE41: sext_v4i32_to_v4i64 +; SSE41: cost of 2 {{.*}} sext +; + %1 = load <4 x i32>, <4 x i32>* %a + %2 = sext <4 x i32> %1 to <4 x i64> + store <4 x i64> %2, <4 x i64>* undef, align 4 + ret void +} + define void @zext_v16i16_to_v16i32(<16 x i16>* %a) { ; SSE2: zext_v16i16_to_v16i32 ; SSE2: cost of 6 {{.*}} zext @@ -279,7 +358,7 @@ define void @truncate_v16i32_to_v16i8(<16 x i32>* %a) { ; SSE2: cost of 7 {{.*}} trunc ; ; SSE41: truncate_v16i32_to_v16i8 -; SSE41: cost of 30 {{.*}} trunc +; SSE41: cost of 7 {{.*}} trunc ; %1 = load <16 x i32>, <16 x i32>* %a %2 = trunc <16 x i32> %1 to <16 x i8> diff --git a/test/Analysis/CostModel/X86/uitofp.ll b/test/Analysis/CostModel/X86/uitofp.ll index 08e36650bec47..2eb8407974f79 100644 --- a/test/Analysis/CostModel/X86/uitofp.ll +++ b/test/Analysis/CostModel/X86/uitofp.ll @@ -41,10 +41,10 @@ define <8 x double> @uitofpv8i8v8double(<8 x i8> %a) { ; SSE2: cost of 80 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv8i8v8double - ; AVX1: cost of 20 {{.*}} uitofp + ; AVX1: cost of 5 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv8i8v8double - ; AVX2: cost of 20 {{.*}} uitofp + ; AVX2: cost of 5 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv8i8v8double ; AVX512F: cost of 2 {{.*}} uitofp @@ -57,13 +57,13 @@ define <16 x double> @uitofpv16i8v16double(<16 x i8> %a) { ; SSE2: cost of 160 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv16i8v16double - ; AVX1: cost of 40 {{.*}} uitofp + ; AVX1: cost of 11 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv16i8v16double - ; AVX2: cost of 40 {{.*}} uitofp + ; AVX2: cost of 11 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv16i8v16double - ; AVX512F: cost of 44 {{.*}} uitofp + ; AVX512F: cost of 5 {{.*}} uitofp %1 = uitofp <16 x i8> %a to <16 x double> ret <16 x double> %1 } @@ -73,13 +73,13 @@ define <32 x double> @uitofpv32i8v32double(<32 x i8> %a) { ; SSE2: cost of 320 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv32i8v32double - ; AVX1: cost of 80 {{.*}} uitofp + ; AVX1: cost of 23 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv32i8v32double - ; AVX2: cost of 80 {{.*}} uitofp + ; AVX2: cost of 23 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv32i8v32double - ; AVX512F: cost of 88 {{.*}} uitofp + ; AVX512F: cost of 11 {{.*}} uitofp %1 = uitofp <32 x i8> %a to <32 x double> ret <32 x double> %1 } @@ -121,10 +121,10 @@ define <8 x double> @uitofpv8i16v8double(<8 x i16> %a) { ; SSE2: cost of 80 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv8i16v8double - ; AVX1: cost of 20 {{.*}} uitofp + ; AVX1: cost of 5 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv8i16v8double - ; AVX2: cost of 20 {{.*}} uitofp + ; AVX2: cost of 5 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv8i16v8double ; AVX512F: cost of 2 {{.*}} uitofp @@ -137,13 +137,13 @@ define <16 x double> @uitofpv16i16v16double(<16 x i16> %a) { ; SSE2: cost of 160 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv16i16v16double - ; AVX1: cost of 40 {{.*}} uitofp + ; AVX1: cost of 11 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv16i16v16double - ; AVX2: cost of 40 {{.*}} uitofp + ; AVX2: cost of 11 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv16i16v16double - ; AVX512F: cost of 44 {{.*}} uitofp + ; AVX512F: cost of 5 {{.*}} uitofp %1 = uitofp <16 x i16> %a to <16 x double> ret <16 x double> %1 } @@ -153,13 +153,13 @@ define <32 x double> @uitofpv32i16v32double(<32 x i16> %a) { ; SSE2: cost of 320 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv32i16v32double - ; AVX1: cost of 80 {{.*}} uitofp + ; AVX1: cost of 23 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv32i16v32double - ; AVX2: cost of 80 {{.*}} uitofp + ; AVX2: cost of 23 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv32i16v32double - ; AVX512F: cost of 88 {{.*}} uitofp + ; AVX512F: cost of 11 {{.*}} uitofp %1 = uitofp <32 x i16> %a to <32 x double> ret <32 x double> %1 } @@ -169,13 +169,13 @@ define <2 x double> @uitofpv2i32v2double(<2 x i32> %a) { ; SSE2: cost of 20 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv2i32v2double - ; AVX1: cost of 4 {{.*}} uitofp + ; AVX1: cost of 6 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv2i32v2double - ; AVX2: cost of 4 {{.*}} uitofp + ; AVX2: cost of 6 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv2i32v2double - ; AVX512F: cost of 4 {{.*}} uitofp + ; AVX512F: cost of 1 {{.*}} uitofp %1 = uitofp <2 x i32> %a to <2 x double> ret <2 x double> %1 } @@ -201,10 +201,10 @@ define <8 x double> @uitofpv8i32v8double(<8 x i32> %a) { ; SSE2: cost of 80 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv8i32v8double - ; AVX1: cost of 20 {{.*}} uitofp + ; AVX1: cost of 13 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv8i32v8double - ; AVX2: cost of 20 {{.*}} uitofp + ; AVX2: cost of 13 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv8i32v8double ; AVX512F: cost of 1 {{.*}} uitofp @@ -217,13 +217,13 @@ define <16 x double> @uitofpv16i32v16double(<16 x i32> %a) { ; SSE2: cost of 160 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv16i32v16double - ; AVX1: cost of 40 {{.*}} uitofp + ; AVX1: cost of 27 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv16i32v16double - ; AVX2: cost of 40 {{.*}} uitofp + ; AVX2: cost of 27 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv16i32v16double - ; AVX512F: cost of 44 {{.*}} uitofp + ; AVX512F: cost of 3 {{.*}} uitofp %1 = uitofp <16 x i32> %a to <16 x double> ret <16 x double> %1 } @@ -233,13 +233,13 @@ define <32 x double> @uitofpv32i32v32double(<32 x i32> %a) { ; SSE2: cost of 320 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv32i32v32double - ; AVX1: cost of 80 {{.*}} uitofp + ; AVX1: cost of 55 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv32i32v32double - ; AVX2: cost of 80 {{.*}} uitofp + ; AVX2: cost of 55 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv32i32v32double - ; AVX512F: cost of 88 {{.*}} uitofp + ; AVX512F: cost of 7 {{.*}} uitofp %1 = uitofp <32 x i32> %a to <32 x double> ret <32 x double> %1 } @@ -249,15 +249,15 @@ define <2 x double> @uitofpv2i64v2double(<2 x i64> %a) { ; SSE2: cost of 20 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv2i64v2double - ; AVX1: cost of 20 {{.*}} uitofp + ; AVX1: cost of 10 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv2i64v2double - ; AVX2: cost of 20 {{.*}} uitofp + ; AVX2: cost of 10 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv2i64v2double ; AVX512F: cost of 5 {{.*}} uitofp ; - ; AVX512DQ: uitofpv2i64v2double + ; AVX512DQ-LABEL: uitofpv2i64v2double ; AVX512DQ: cost of 1 {{.*}} uitofp %1 = uitofp <2 x i64> %a to <2 x double> ret <2 x double> %1 @@ -268,15 +268,15 @@ define <4 x double> @uitofpv4i64v4double(<4 x i64> %a) { ; SSE2: cost of 40 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv4i64v4double - ; AVX1: cost of 40 {{.*}} uitofp + ; AVX1: cost of 20 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv4i64v4double - ; AVX2: cost of 40 {{.*}} uitofp + ; AVX2: cost of 20 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv4i64v4double ; AVX512F: cost of 12 {{.*}} uitofp ; - ; AVX512DQ: uitofpv4i64v4double + ; AVX512DQ-LABEL: uitofpv4i64v4double ; AVX512DQ: cost of 1 {{.*}} uitofp %1 = uitofp <4 x i64> %a to <4 x double> ret <4 x double> %1 @@ -287,15 +287,15 @@ define <8 x double> @uitofpv8i64v8double(<8 x i64> %a) { ; SSE2: cost of 80 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv8i64v8double - ; AVX1: cost of 20 {{.*}} uitofp + ; AVX1: cost of 41 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv8i64v8double - ; AVX2: cost of 20 {{.*}} uitofp + ; AVX2: cost of 41 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv8i64v8double ; AVX512F: cost of 26 {{.*}} uitofp ; - ; AVX512DQ: uitofpv8i64v8double + ; AVX512DQ-LABEL: uitofpv8i64v8double ; AVX512DQ: cost of 1 {{.*}} uitofp %1 = uitofp <8 x i64> %a to <8 x double> ret <8 x double> %1 @@ -306,16 +306,16 @@ define <16 x double> @uitofpv16i64v16double(<16 x i64> %a) { ; SSE2: cost of 160 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv16i64v16double - ; AVX1: cost of 40 {{.*}} uitofp + ; AVX1: cost of 83 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv16i64v16double - ; AVX2: cost of 40 {{.*}} uitofp + ; AVX2: cost of 83 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv16i64v16double - ; AVX512F: cost of 44 {{.*}} uitofp + ; AVX512F: cost of 53 {{.*}} uitofp ; - ; AVX512DQ: uitofpv16i64v16double - ; AVX512DQ: cost of 44 {{.*}} uitofp + ; AVX512DQ-LABEL: uitofpv16i64v16double + ; AVX512DQ: cost of 3 {{.*}} uitofp %1 = uitofp <16 x i64> %a to <16 x double> ret <16 x double> %1 } @@ -325,16 +325,16 @@ define <32 x double> @uitofpv32i64v32double(<32 x i64> %a) { ; SSE2: cost of 320 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv32i64v32double - ; AVX1: cost of 80 {{.*}} uitofp + ; AVX1: cost of 167 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv32i64v32double - ; AVX2: cost of 80 {{.*}} uitofp + ; AVX2: cost of 167 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv32i64v32double - ; AVX512F: cost of 88 {{.*}} uitofp + ; AVX512F: cost of 107 {{.*}} uitofp ; - ; AVX512DQ: uitofpv32i64v32double - ; AVX512DQ: cost of 88 {{.*}} uitofp + ; AVX512DQ-LABEL: uitofpv32i64v32double + ; AVX512DQ: cost of 2 {{.*}} uitofp %1 = uitofp <32 x i64> %a to <32 x double> ret <32 x double> %1 } @@ -392,10 +392,10 @@ define <16 x float> @uitofpv16i8v16float(<16 x i8> %a) { ; SSE2: cost of 8 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv16i8v16float - ; AVX1: cost of 44 {{.*}} uitofp + ; AVX1: cost of 11 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv16i8v16float - ; AVX2: cost of 44 {{.*}} uitofp + ; AVX2: cost of 11 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv16i8v16float ; AVX512F: cost of 2 {{.*}} uitofp @@ -408,13 +408,13 @@ define <32 x float> @uitofpv32i8v32float(<32 x i8> %a) { ; SSE2: cost of 16 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv32i8v32float - ; AVX1: cost of 88 {{.*}} uitofp + ; AVX1: cost of 23 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv32i8v32float - ; AVX2: cost of 88 {{.*}} uitofp + ; AVX2: cost of 23 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv32i8v32float - ; AVX512F: cost of 92 {{.*}} uitofp + ; AVX512F: cost of 5 {{.*}} uitofp %1 = uitofp <32 x i8> %a to <32 x float> ret <32 x float> %1 } @@ -472,10 +472,10 @@ define <16 x float> @uitofpv16i16v16float(<16 x i16> %a) { ; SSE2: cost of 30 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv16i16v16float - ; AVX1: cost of 44 {{.*}} uitofp + ; AVX1: cost of 11 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv16i16v16float - ; AVX2: cost of 44 {{.*}} uitofp + ; AVX2: cost of 11 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv16i16v16float ; AVX512F: cost of 2 {{.*}} uitofp @@ -488,13 +488,13 @@ define <32 x float> @uitofpv32i16v32float(<32 x i16> %a) { ; SSE2: cost of 60 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv32i16v32float - ; AVX1: cost of 88 {{.*}} uitofp + ; AVX1: cost of 23 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv32i16v32float - ; AVX2: cost of 88 {{.*}} uitofp + ; AVX2: cost of 23 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv32i16v32float - ; AVX512F: cost of 92 {{.*}} uitofp + ; AVX512F: cost of 5 {{.*}} uitofp %1 = uitofp <32 x i16> %a to <32 x float> ret <32 x float> %1 } @@ -552,10 +552,10 @@ define <16 x float> @uitofpv16i32v16float(<16 x i32> %a) { ; SSE2: cost of 32 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv16i32v16float - ; AVX1: cost of 44 {{.*}} uitofp + ; AVX1: cost of 19 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv16i32v16float - ; AVX2: cost of 44 {{.*}} uitofp + ; AVX2: cost of 17 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv16i32v16float ; AVX512F: cost of 1 {{.*}} uitofp @@ -568,13 +568,13 @@ define <32 x float> @uitofpv32i32v32float(<32 x i32> %a) { ; SSE2: cost of 64 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv32i32v32float - ; AVX1: cost of 88 {{.*}} uitofp + ; AVX1: cost of 39 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv32i32v32float - ; AVX2: cost of 88 {{.*}} uitofp + ; AVX2: cost of 35 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv32i32v32float - ; AVX512F: cost of 92 {{.*}} uitofp + ; AVX512F: cost of 3 {{.*}} uitofp %1 = uitofp <32 x i32> %a to <32 x float> ret <32 x float> %1 } @@ -590,7 +590,7 @@ define <2 x float> @uitofpv2i64v2float(<2 x i64> %a) { ; AVX2: cost of 4 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv2i64v2float - ; AVX512F: cost of 4 {{.*}} uitofp + ; AVX512F: cost of 5 {{.*}} uitofp %1 = uitofp <2 x i64> %a to <2 x float> ret <2 x float> %1 } @@ -616,13 +616,13 @@ define <8 x float> @uitofpv8i64v8float(<8 x i64> %a) { ; SSE2: cost of 60 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv8i64v8float - ; AVX1: cost of 22 {{.*}} uitofp + ; AVX1: cost of 21 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv8i64v8float - ; AVX2: cost of 22 {{.*}} uitofp + ; AVX2: cost of 21 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv8i64v8float - ; AVX512F: cost of 22 {{.*}} uitofp + ; AVX512F: cost of 26 {{.*}} uitofp %1 = uitofp <8 x i64> %a to <8 x float> ret <8 x float> %1 } @@ -632,13 +632,13 @@ define <16 x float> @uitofpv16i64v16float(<16 x i64> %a) { ; SSE2: cost of 120 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv16i64v16float - ; AVX1: cost of 44 {{.*}} uitofp + ; AVX1: cost of 43 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv16i64v16float - ; AVX2: cost of 44 {{.*}} uitofp + ; AVX2: cost of 43 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv16i64v16float - ; AVX512F: cost of 46 {{.*}} uitofp + ; AVX512F: cost of 53 {{.*}} uitofp %1 = uitofp <16 x i64> %a to <16 x float> ret <16 x float> %1 } @@ -648,13 +648,13 @@ define <32 x float> @uitofpv32i64v32float(<32 x i64> %a) { ; SSE2: cost of 240 {{.*}} uitofp ; ; AVX1-LABEL: uitofpv32i64v32float - ; AVX1: cost of 88 {{.*}} uitofp + ; AVX1: cost of 87 {{.*}} uitofp ; ; AVX2-LABEL: uitofpv32i64v32float - ; AVX2: cost of 88 {{.*}} uitofp + ; AVX2: cost of 87 {{.*}} uitofp ; ; AVX512F-LABEL: uitofpv32i64v32float - ; AVX512F: cost of 92 {{.*}} uitofp + ; AVX512F: cost of 107 {{.*}} uitofp %1 = uitofp <32 x i64> %a to <32 x float> ret <32 x float> %1 } diff --git a/test/Analysis/DemandedBits/basic.ll b/test/Analysis/DemandedBits/basic.ll index 3fd1b3212883d..5b8652396b3a1 100644 --- a/test/Analysis/DemandedBits/basic.ll +++ b/test/Analysis/DemandedBits/basic.ll @@ -1,6 +1,6 @@ ; RUN: opt -S -demanded-bits -analyze < %s | FileCheck %s - -; CHECK-LABEL: 'test_mul' +; RUN: opt -S -disable-output -passes="print<demanded-bits>" < %s 2>&1 | FileCheck %s + ; 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 diff --git a/test/Analysis/DependenceAnalysis/MIVCheckConst.ll b/test/Analysis/DependenceAnalysis/MIVCheckConst.ll new file mode 100644 index 0000000000000..64e72df55b857 --- /dev/null +++ b/test/Analysis/DependenceAnalysis/MIVCheckConst.ll @@ -0,0 +1,73 @@ +; RUN: opt < %s -analyze -basicaa -da + +; Test that the dependence analysis pass does seg-fault due to a null pointer +; dereference. The code in gcdMIVTest requires a null check for the result of +; getConstantPart. + +target datalayout = "e-m:e-p:32:32-i1:32-i64:64-a:0-v32:32-n16:32" + +%0 = type { i32 } +%1 = type { [2 x [512 x %0]], [512 x %0], %2, [144 x i8], %9, %10, %11, %12, %17, [12 x i8], %18, %19, %21, [128 x i8] } +%2 = type { [64 x i16], [64 x i16], [64 x %0], [64 x %0], [128 x %0], [128 x %0], [256 x %0], [256 x %0], [32 x %0], [32 x %0], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16], %3, %4, %5, [32 x i32], [32 x i32], [32 x i32], [32 x i32], [32 x i32], [32 x i32], %6, %7, [32 x i32], [32 x i32], [32 x i32], [64 x i16], %8, [8 x i64], [4 x i64], [2 x i64], [256 x i8], [256 x i32], [64 x i16], [64 x i16] } +%3 = type { [64 x i32], [32 x i32], [32 x i32], [32 x i32], [32 x i32], [32 x i32], [32 x i32], [32 x i32], [32 x i32], [32 x i32], [32 x i32], [32 x i32], [32 x i32], [32 x i32], [32 x i32], [64 x i32], [64 x i32], [64 x i32], [64 x i32], [64 x i32], [64 x i32], [64 x i32], [64 x i32], [64 x i32], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [32 x %0], [32 x %0], [128 x i8] } +%4 = type { [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16] } +%5 = type { [128 x i8], [256 x i8], [256 x i8] } +%6 = type { [64 x i32], [128 x i16], [64 x i16], [64 x i16], [64 x i16] } +%7 = type { [192 x %0], [192 x %0], [384 x %0], [1984 x %0] } +%8 = type { [128 x i8], [128 x i8], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16], [64 x i16] } +%9 = type { [32 x %0], [32 x %0], [64 x i32], [64 x i32], [64 x i32], [64 x i32] } +%10 = type { [1536 x %0], [2048 x %0], [512 x i32], [256 x i32], [32 x %0], [64 x i32], [128 x i8], [512 x i32], [1024 x %0] } +%11 = type { [512 x i32], [512 x i32], [1024 x %0], [512 x i32], [512 x %0] } +%12 = type { %13, [2048 x %0], [2048 x %0], [256 x i32], [1024 x i32], %14, [512 x %0], [256 x i32], %15, [4 x [256 x %0]], [4 x [256 x %0]], [256 x i32], [8 x [32 x i32]], [8 x [32 x %0]], [384 x %0], [256 x i32], %16 } +%13 = type { [2048 x %0] } +%14 = type { [1024 x %0], [1024 x %0] } +%15 = type { [256 x %0], [256 x %0] } +%16 = type { [128 x %0], [128 x %0] } +%17 = type { [32 x %0], [32 x i32], [32 x i32], [32 x i32], [32 x i32], [2 x [8 x [32 x %0]]], [512 x %0], [512 x %0], [58 x i16] } +%18 = type { [512 x i8] } +%19 = type { [2048 x %0], [2560 x i16], %20, [512 x i32], [256 x i32], [512 x i8] } +%20 = type { [768 x i32] } +%21 = type { [416 x i32] } + +define void @test(%1* %A) #0 align 2 { +entry: + %v1 = load i32, i32* undef, align 4 + br label %bb13 + +bb13: + %v2 = phi i32 [ undef, %entry ], [ %v39, %bb38 ] + br i1 undef, label %bb15, label %bb38 + +bb15: + %v3 = mul nsw i32 %v2, undef + br label %bb17 + +bb17: + br i1 undef, label %bb21, label %bb37 + +bb21: + %v22 = add nsw i32 undef, 1 + %v23 = add i32 %v22, %v3 + %v24 = mul nsw i32 %v23, %v1 + %v25 = getelementptr inbounds %1, %1* %A, i32 0, i32 7, i32 1, i32 %v24 + %v26 = bitcast %0* %v25 to <32 x i32>* + %v27 = load <32 x i32>, <32 x i32>* %v26, align 256 + %v28 = add i32 undef, %v3 + %v29 = mul nsw i32 %v28, 32 + %v30 = getelementptr inbounds %1, %1* %A, i32 0, i32 7, i32 14, i32 %v29 + %v31 = bitcast %0* %v30 to <32 x i32>* + %v32 = load <32 x i32>, <32 x i32>* %v31, align 128 + br i1 undef, label %bb21, label %bb37 + +bb37: + br i1 undef, label %bb17, label %bb38 + +bb38: + %v39 = add nsw i32 %v2, 1 + br label %bb13 + +bb40: + ret void +} + +attributes #0 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/test/Analysis/DivergenceAnalysis/AMDGPU/atomics.ll b/test/Analysis/DivergenceAnalysis/AMDGPU/atomics.ll new file mode 100644 index 0000000000000..e3323dc5e21c2 --- /dev/null +++ b/test/Analysis/DivergenceAnalysis/AMDGPU/atomics.ll @@ -0,0 +1,15 @@ +; RUN: opt -mtriple=amdgcn-- -analyze -divergence %s | FileCheck %s + +; CHECK: DIVERGENT: %orig = atomicrmw xchg i32* %ptr, i32 %val seq_cst +define i32 @test1(i32* %ptr, i32 %val) #0 { + %orig = atomicrmw xchg i32* %ptr, i32 %val seq_cst + ret i32 %orig +} + +; CHECK: DIVERGENT: %orig = cmpxchg i32* %ptr, i32 %cmp, i32 %new seq_cst seq_cst +define {i32, i1} @test2(i32* %ptr, i32 %cmp, i32 %new) { + %orig = cmpxchg i32* %ptr, i32 %cmp, i32 %new seq_cst seq_cst + ret {i32, i1} %orig +} + +attributes #0 = { nounwind } diff --git a/test/Analysis/DivergenceAnalysis/AMDGPU/interp-intrinsics.ll b/test/Analysis/DivergenceAnalysis/AMDGPU/interp-intrinsics.ll new file mode 100644 index 0000000000000..d1c90ba608c8d --- /dev/null +++ b/test/Analysis/DivergenceAnalysis/AMDGPU/interp-intrinsics.ll @@ -0,0 +1,22 @@ +; RUN: opt -mtriple amdgcn--- -analyze -divergence %s | FileCheck %s + +; CHECK-LABEL: 'fs_interp' +; CHECK: DIVERGENT: %v = call float @llvm.SI.fs.interp( +define amdgpu_ps void @fs_interp(i32 inreg %prim_mask, <2 x i32> %interp_param) #1 { + %v = call float @llvm.SI.fs.interp(i32 0, i32 0, i32 %prim_mask, <2 x i32> %interp_param) + store volatile float %v, float addrspace(1)* undef + ret void +} + +; CHECK-LABEL: 'fs_constant' +; CHECK: DIVERGENT: %v = call float @llvm.SI.fs.constant( +define amdgpu_ps void @fs_constant(i32 inreg %prim_mask, <2 x i32> %interp_param) #1 { + %v = call float @llvm.SI.fs.constant(i32 0, i32 0, i32 %prim_mask) + store volatile float %v, float addrspace(1)* undef + ret void +} + +declare float @llvm.SI.fs.interp(i32, i32, i32, <2 x i32>) #0 +declare float @llvm.SI.fs.constant(i32, i32, i32) #0 + +attributes #0 = { nounwind readnone } diff --git a/test/Analysis/DivergenceAnalysis/AMDGPU/kernel-args.ll b/test/Analysis/DivergenceAnalysis/AMDGPU/kernel-args.ll index 63e6c5c50ded9..73674d0599e25 100644 --- a/test/Analysis/DivergenceAnalysis/AMDGPU/kernel-args.ll +++ b/test/Analysis/DivergenceAnalysis/AMDGPU/kernel-args.ll @@ -9,8 +9,8 @@ ; 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 { +define amdgpu_ps 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" } +attributes #0 = { nounwind } diff --git a/test/Analysis/DivergenceAnalysis/AMDGPU/llvm.amdgcn.buffer.atomic.ll b/test/Analysis/DivergenceAnalysis/AMDGPU/llvm.amdgcn.buffer.atomic.ll new file mode 100644 index 0000000000000..1d016453301f7 --- /dev/null +++ b/test/Analysis/DivergenceAnalysis/AMDGPU/llvm.amdgcn.buffer.atomic.ll @@ -0,0 +1,103 @@ +;RUN: opt -mtriple=amdgcn-mesa-mesa3d -analyze -divergence %s | FileCheck %s + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.buffer.atomic.swap( +define float @buffer_atomic_swap(<4 x i32> inreg %rsrc, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.buffer.atomic.swap(i32 %data, <4 x i32> %rsrc, i32 0, i32 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.buffer.atomic.add( +define float @buffer_atomic_add(<4 x i32> inreg %rsrc, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.buffer.atomic.add(i32 %data, <4 x i32> %rsrc, i32 0, i32 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.buffer.atomic.sub( +define float @buffer_atomic_sub(<4 x i32> inreg %rsrc, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.buffer.atomic.sub(i32 %data, <4 x i32> %rsrc, i32 0, i32 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.buffer.atomic.smin( +define float @buffer_atomic_smin(<4 x i32> inreg %rsrc, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.buffer.atomic.smin(i32 %data, <4 x i32> %rsrc, i32 0, i32 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.buffer.atomic.umin( +define float @buffer_atomic_umin(<4 x i32> inreg %rsrc, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.buffer.atomic.umin(i32 %data, <4 x i32> %rsrc, i32 0, i32 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.buffer.atomic.smax( +define float @buffer_atomic_smax(<4 x i32> inreg %rsrc, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.buffer.atomic.smax(i32 %data, <4 x i32> %rsrc, i32 0, i32 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.buffer.atomic.umax( +define float @buffer_atomic_umax(<4 x i32> inreg %rsrc, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.buffer.atomic.umax(i32 %data, <4 x i32> %rsrc, i32 0, i32 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.buffer.atomic.and( +define float @buffer_atomic_and(<4 x i32> inreg %rsrc, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.buffer.atomic.and(i32 %data, <4 x i32> %rsrc, i32 0, i32 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.buffer.atomic.or( +define float @buffer_atomic_or(<4 x i32> inreg %rsrc, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.buffer.atomic.or(i32 %data, <4 x i32> %rsrc, i32 0, i32 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.buffer.atomic.xor( +define float @buffer_atomic_xor(<4 x i32> inreg %rsrc, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.buffer.atomic.xor(i32 %data, <4 x i32> %rsrc, i32 0, i32 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.buffer.atomic.cmpswap( +define float @buffer_atomic_cmpswap(<4 x i32> inreg %rsrc, i32 inreg %data, i32 inreg %cmp) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.buffer.atomic.cmpswap(i32 %data, i32 %cmp, <4 x i32> %rsrc, i32 0, i32 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +declare i32 @llvm.amdgcn.buffer.atomic.swap(i32, <4 x i32>, i32, i32, i1) #0 +declare i32 @llvm.amdgcn.buffer.atomic.add(i32, <4 x i32>, i32, i32, i1) #0 +declare i32 @llvm.amdgcn.buffer.atomic.sub(i32, <4 x i32>, i32, i32, i1) #0 +declare i32 @llvm.amdgcn.buffer.atomic.smin(i32, <4 x i32>, i32, i32, i1) #0 +declare i32 @llvm.amdgcn.buffer.atomic.umin(i32, <4 x i32>, i32, i32, i1) #0 +declare i32 @llvm.amdgcn.buffer.atomic.smax(i32, <4 x i32>, i32, i32, i1) #0 +declare i32 @llvm.amdgcn.buffer.atomic.umax(i32, <4 x i32>, i32, i32, i1) #0 +declare i32 @llvm.amdgcn.buffer.atomic.and(i32, <4 x i32>, i32, i32, i1) #0 +declare i32 @llvm.amdgcn.buffer.atomic.or(i32, <4 x i32>, i32, i32, i1) #0 +declare i32 @llvm.amdgcn.buffer.atomic.xor(i32, <4 x i32>, i32, i32, i1) #0 +declare i32 @llvm.amdgcn.buffer.atomic.cmpswap(i32, i32, <4 x i32>, i32, i32, i1) #0 + +attributes #0 = { nounwind } diff --git a/test/Analysis/DivergenceAnalysis/AMDGPU/llvm.amdgcn.image.atomic.ll b/test/Analysis/DivergenceAnalysis/AMDGPU/llvm.amdgcn.image.atomic.ll new file mode 100644 index 0000000000000..4a3b60f08de2e --- /dev/null +++ b/test/Analysis/DivergenceAnalysis/AMDGPU/llvm.amdgcn.image.atomic.ll @@ -0,0 +1,121 @@ +;RUN: opt -mtriple=amdgcn-mesa-mesa3d -analyze -divergence %s | FileCheck %s + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.image.atomic.swap.i32( +define float @image_atomic_swap(<8 x i32> inreg %rsrc, i32 inreg %addr, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.image.atomic.swap.i32(i32 %data, i32 %addr, <8 x i32> %rsrc, i1 0, i1 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.image.atomic.add.i32( +define float @image_atomic_add(<8 x i32> inreg %rsrc, i32 inreg %addr, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.image.atomic.add.i32(i32 %data, i32 %addr, <8 x i32> %rsrc, i1 0, i1 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.image.atomic.sub.i32( +define float @image_atomic_sub(<8 x i32> inreg %rsrc, i32 inreg %addr, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.image.atomic.sub.i32(i32 %data, i32 %addr, <8 x i32> %rsrc, i1 0, i1 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.image.atomic.smin.i32( +define float @image_atomic_smin(<8 x i32> inreg %rsrc, i32 inreg %addr, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.image.atomic.smin.i32(i32 %data, i32 %addr, <8 x i32> %rsrc, i1 0, i1 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.image.atomic.umin.i32( +define float @image_atomic_umin(<8 x i32> inreg %rsrc, i32 inreg %addr, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.image.atomic.umin.i32(i32 %data, i32 %addr, <8 x i32> %rsrc, i1 0, i1 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.image.atomic.smax.i32( +define float @image_atomic_smax(<8 x i32> inreg %rsrc, i32 inreg %addr, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.image.atomic.smax.i32(i32 %data, i32 %addr, <8 x i32> %rsrc, i1 0, i1 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.image.atomic.umax.i32( +define float @image_atomic_umax(<8 x i32> inreg %rsrc, i32 inreg %addr, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.image.atomic.umax.i32(i32 %data, i32 %addr, <8 x i32> %rsrc, i1 0, i1 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.image.atomic.and.i32( +define float @image_atomic_and(<8 x i32> inreg %rsrc, i32 inreg %addr, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.image.atomic.and.i32(i32 %data, i32 %addr, <8 x i32> %rsrc, i1 0, i1 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.image.atomic.or.i32( +define float @image_atomic_or(<8 x i32> inreg %rsrc, i32 inreg %addr, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.image.atomic.or.i32(i32 %data, i32 %addr, <8 x i32> %rsrc, i1 0, i1 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.image.atomic.xor.i32( +define float @image_atomic_xor(<8 x i32> inreg %rsrc, i32 inreg %addr, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.image.atomic.xor.i32(i32 %data, i32 %addr, <8 x i32> %rsrc, i1 0, i1 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.image.atomic.inc.i32( +define float @image_atomic_inc(<8 x i32> inreg %rsrc, i32 inreg %addr, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.image.atomic.inc.i32(i32 %data, i32 %addr, <8 x i32> %rsrc, i1 0, i1 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.image.atomic.dec.i32( +define float @image_atomic_dec(<8 x i32> inreg %rsrc, i32 inreg %addr, i32 inreg %data) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.image.atomic.dec.i32(i32 %data, i32 %addr, <8 x i32> %rsrc, i1 0, i1 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +;CHECK: DIVERGENT: %orig = call i32 @llvm.amdgcn.image.atomic.cmpswap.i32( +define float @image_atomic_cmpswap(<8 x i32> inreg %rsrc, i32 inreg %addr, i32 inreg %data, i32 inreg %cmp) #0 { +main_body: + %orig = call i32 @llvm.amdgcn.image.atomic.cmpswap.i32(i32 %data, i32 %cmp, i32 %addr, <8 x i32> %rsrc, i1 0, i1 0, i1 0) + %r = bitcast i32 %orig to float + ret float %r +} + +declare i32 @llvm.amdgcn.image.atomic.swap.i32(i32, i32, <8 x i32>, i1, i1, i1) #0 +declare i32 @llvm.amdgcn.image.atomic.add.i32(i32, i32, <8 x i32>, i1, i1, i1) #0 +declare i32 @llvm.amdgcn.image.atomic.sub.i32(i32, i32, <8 x i32>, i1, i1, i1) #0 +declare i32 @llvm.amdgcn.image.atomic.smin.i32(i32, i32, <8 x i32>, i1, i1, i1) #0 +declare i32 @llvm.amdgcn.image.atomic.umin.i32(i32, i32, <8 x i32>, i1, i1, i1) #0 +declare i32 @llvm.amdgcn.image.atomic.smax.i32(i32, i32, <8 x i32>, i1, i1, i1) #0 +declare i32 @llvm.amdgcn.image.atomic.umax.i32(i32, i32, <8 x i32>, i1, i1, i1) #0 +declare i32 @llvm.amdgcn.image.atomic.and.i32(i32, i32, <8 x i32>, i1, i1, i1) #0 +declare i32 @llvm.amdgcn.image.atomic.or.i32(i32, i32, <8 x i32>, i1, i1, i1) #0 +declare i32 @llvm.amdgcn.image.atomic.xor.i32(i32, i32, <8 x i32>, i1, i1, i1) #0 +declare i32 @llvm.amdgcn.image.atomic.inc.i32(i32, i32, <8 x i32>, i1, i1, i1) #0 +declare i32 @llvm.amdgcn.image.atomic.dec.i32(i32, i32, <8 x i32>, i1, i1, i1) #0 +declare i32 @llvm.amdgcn.image.atomic.cmpswap.i32(i32, i32, i32, <8 x i32>,i1, i1, i1) #0 + +attributes #0 = { nounwind } diff --git a/test/Analysis/DivergenceAnalysis/AMDGPU/no-return-blocks.ll b/test/Analysis/DivergenceAnalysis/AMDGPU/no-return-blocks.ll new file mode 100644 index 0000000000000..b4fa79a6ba9f9 --- /dev/null +++ b/test/Analysis/DivergenceAnalysis/AMDGPU/no-return-blocks.ll @@ -0,0 +1,30 @@ +; RUN: opt %s -mtriple amdgcn-- -analyze -divergence | FileCheck %s + +; CHECK: DIVERGENT: %tmp5 = getelementptr inbounds float, float addrspace(1)* %arg, i64 %tmp2 +; CHECK: DIVERGENT: %tmp10 = load volatile float, float addrspace(1)* %tmp5, align 4 +; CHECK: DIVERGENT: %tmp11 = load volatile float, float addrspace(1)* %tmp5, align 4 + +; The post dominator tree does not have a root node in this case +define void @no_return_blocks(float addrspace(1)* noalias nocapture readonly %arg, float addrspace(1)* noalias nocapture readonly %arg1) #0 { +bb0: + %tmp = tail call i32 @llvm.amdgcn.workitem.id.x() #0 + %tmp2 = sext i32 %tmp to i64 + %tmp5 = getelementptr inbounds float, float addrspace(1)* %arg, i64 %tmp2 + %tmp6 = load volatile float, float addrspace(1)* %tmp5, align 4 + %tmp8 = fcmp olt float %tmp6, 0.000000e+00 + br i1 %tmp8, label %bb1, label %bb2 + +bb1: + %tmp10 = load volatile float, float addrspace(1)* %tmp5, align 4 + br label %bb2 + +bb2: + %tmp11 = load volatile float, float addrspace(1)* %tmp5, align 4 + br label %bb1 +} + +; Function Attrs: nounwind readnone +declare i32 @llvm.amdgcn.workitem.id.x() #1 + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } diff --git a/test/Analysis/DivergenceAnalysis/AMDGPU/phi-undef.ll b/test/Analysis/DivergenceAnalysis/AMDGPU/phi-undef.ll new file mode 100644 index 0000000000000..da9c3a9391be4 --- /dev/null +++ b/test/Analysis/DivergenceAnalysis/AMDGPU/phi-undef.ll @@ -0,0 +1,28 @@ +; RUN: opt -mtriple=amdgcn-- -analyze -divergence %s | FileCheck %s + +; CHECK-LABEL: 'test1': +; CHECK-NEXT: DIVERGENT: i32 %bound +; CHECK-NEXT: DIVERGENT: %break = icmp sge i32 %counter, %bound +; CHECK-NEXT: DIVERGENT: br i1 %break, label %footer, label %body +; CHECK-NEXT: DIVERGENT: br i1 %break, label %end, label %header +; Note: %counter is not divergent! +define amdgpu_ps void @test1(i32 %bound) { +entry: + br label %header + +header: + %counter = phi i32 [ 0, %entry ], [ %counter.footer, %footer ] + %break = icmp sge i32 %counter, %bound + br i1 %break, label %footer, label %body + +body: + %counter.next = add i32 %counter, 1 + br label %footer + +footer: + %counter.footer = phi i32 [ %counter.next, %body ], [ undef, %header ] + br i1 %break, label %end, label %header + +end: + ret void +} diff --git a/test/Analysis/DivergenceAnalysis/AMDGPU/unreachable-loop-block.ll b/test/Analysis/DivergenceAnalysis/AMDGPU/unreachable-loop-block.ll new file mode 100644 index 0000000000000..ca93dda2c5739 --- /dev/null +++ b/test/Analysis/DivergenceAnalysis/AMDGPU/unreachable-loop-block.ll @@ -0,0 +1,17 @@ +; RUN: opt %s -mtriple amdgcn-- -analyze -divergence | FileCheck %s + +; CHECK: DIVERGENT: %tmp = cmpxchg volatile +define void @unreachable_loop(i32 %tidx) #0 { +entry: + unreachable + +unreachable_loop: ; preds = %do.body.i, %if.then11 + %tmp = cmpxchg volatile i32 addrspace(1)* null, i32 0, i32 0 seq_cst seq_cst + %cmp.i = extractvalue { i32, i1 } %tmp, 1 + br i1 %cmp.i, label %unreachable_loop, label %end + +end: ; preds = %do.body.i51, %atomicAdd_g_f.exit + unreachable +} + +attributes #0 = { norecurse nounwind } diff --git a/test/Analysis/DivergenceAnalysis/AMDGPU/workitem-intrinsics.ll b/test/Analysis/DivergenceAnalysis/AMDGPU/workitem-intrinsics.ll new file mode 100644 index 0000000000000..669ee802c516b --- /dev/null +++ b/test/Analysis/DivergenceAnalysis/AMDGPU/workitem-intrinsics.ll @@ -0,0 +1,45 @@ +; RUN: opt -mtriple amdgcn-unknown-amdhsa -analyze -divergence %s | FileCheck %s + +declare i32 @llvm.amdgcn.workitem.id.x() #0 +declare i32 @llvm.amdgcn.workitem.id.y() #0 +declare i32 @llvm.amdgcn.workitem.id.z() #0 +declare i32 @llvm.amdgcn.mbcnt.lo(i32, i32) #0 +declare i32 @llvm.amdgcn.mbcnt.hi(i32, i32) #0 + +; CHECK: DIVERGENT: %id.x = call i32 @llvm.amdgcn.workitem.id.x() +define void @workitem_id_x() #1 { + %id.x = call i32 @llvm.amdgcn.workitem.id.x() + store volatile i32 %id.x, i32 addrspace(1)* undef + ret void +} + +; CHECK: DIVERGENT: %id.y = call i32 @llvm.amdgcn.workitem.id.y() +define void @workitem_id_y() #1 { + %id.y = call i32 @llvm.amdgcn.workitem.id.y() + store volatile i32 %id.y, i32 addrspace(1)* undef + ret void +} + +; CHECK: DIVERGENT: %id.z = call i32 @llvm.amdgcn.workitem.id.z() +define void @workitem_id_z() #1 { + %id.z = call i32 @llvm.amdgcn.workitem.id.z() + store volatile i32 %id.z, i32 addrspace(1)* undef + ret void +} + +; CHECK: DIVERGENT: %mbcnt.lo = call i32 @llvm.amdgcn.mbcnt.lo(i32 0, i32 0) +define void @mbcnt_lo() #1 { + %mbcnt.lo = call i32 @llvm.amdgcn.mbcnt.lo(i32 0, i32 0) + store volatile i32 %mbcnt.lo, i32 addrspace(1)* undef + ret void +} + +; CHECK: DIVERGENT: %mbcnt.hi = call i32 @llvm.amdgcn.mbcnt.hi(i32 0, i32 0) +define void @mbcnt_hi() #1 { + %mbcnt.hi = call i32 @llvm.amdgcn.mbcnt.hi(i32 0, i32 0) + store volatile i32 %mbcnt.hi, i32 addrspace(1)* undef + ret void +} + +attributes #0 = { nounwind readnone } +attributes #1 = { nounwind } diff --git a/test/Analysis/DivergenceAnalysis/NVPTX/diverge.ll b/test/Analysis/DivergenceAnalysis/NVPTX/diverge.ll index fc63038e77cc1..cbfd2901442b4 100644 --- a/test/Analysis/DivergenceAnalysis/NVPTX/diverge.ll +++ b/test/Analysis/DivergenceAnalysis/NVPTX/diverge.ll @@ -100,7 +100,7 @@ merge: define i32 @loop() { ; CHECK-LABEL: Printing analysis 'Divergence Analysis' for function 'loop' entry: - %laneid = call i32 @llvm.ptx.read.laneid() + %laneid = call i32 @llvm.nvvm.read.ptx.sreg.laneid() br label %loop loop: %i = phi i32 [ 0, %entry ], [ %i1, %loop ] @@ -208,7 +208,7 @@ bb3: 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() +declare i32 @llvm.nvvm.read.ptx.sreg.laneid() !nvvm.annotations = !{!0, !1, !2, !3, !4, !5} !0 = !{i32 (i32, i32, i32)* @no_diverge, !"kernel", i32 1} diff --git a/test/Analysis/DominanceFrontier/new_pm_test.ll b/test/Analysis/DominanceFrontier/new_pm_test.ll new file mode 100644 index 0000000000000..7ab1fca80532a --- /dev/null +++ b/test/Analysis/DominanceFrontier/new_pm_test.ll @@ -0,0 +1,50 @@ +; REQUIRES: asserts +; RUN: opt < %s -passes='print<domfrontier>' 2>&1 | FileCheck %s + +define void @a_linear_impl_fig_1() nounwind { +0: + br label %"1" +1: + br label %"2" +2: + br label %"3" +3: + br i1 1, label %"13", label %"4" +4: + br i1 1, label %"5", label %"1" +5: + br i1 1, label %"8", label %"6" +6: + br i1 1, label %"7", label %"4" +7: + ret void +8: + br i1 1, label %"9", label %"1" +9: + br label %"10" +10: + br i1 1, label %"12", label %"11" +11: + br i1 1, label %"9", label %"8" +13: + br i1 1, label %"2", label %"1" +12: + switch i32 0, label %"1" [ i32 0, label %"9" + i32 1, label %"8"] +} + +; CHECK: DominanceFrontier for function: a_linear_impl_fig_1 +; CHECK-DAG: DomFrontier for BB %"0" is: +; CHECK-DAG: DomFrontier for BB %"11" is: %"{{[8|9]}}" %"{{[8|9]}}" +; CHECK-DAG: DomFrontier for BB %"1" is: %"1" +; CHECK-DAG: DomFrontier for BB %"2" is: %"{{[1|2]}}" %"{{[1|2]}}" +; CHECK-DAG: DomFrontier for BB %"3" is: %"{{[1|2]}}" %"{{[1|2]}}" +; CHECK-DAG: DomFrontier for BB %"13" is: %"{{[1|2]}}" %"{{[1|2]}}" +; CHECK-DAG: DomFrontier for BB %"4" is: %"{{[1|4]}}" %"{{[1|4]}}" +; CHECK-DAG: DomFrontier for BB %"5" is: %"{{[1|4]}}" %"{{[1|4]}}" +; CHECK-DAG: DomFrontier for BB %"8" is: %"{{[1|8]}}" %"{{[1|8]}}" +; CHECK-DAG: DomFrontier for BB %"6" is: %"4" +; CHECK-DAG: DomFrontier for BB %"7" is: +; CHECK-DAG: DomFrontier for BB %"9" is: %"{{[1|8|9]}}" %"{{[1|8|9]}}" %"{{[1|8|9]}}" +; CHECK-DAG: DomFrontier for BB %"10" is: %"{{[1|8|9]}}" %"{{[1|8|9]}}" %"{{[1|8|9]}}" +; CHECK-DAG: DomFrontier for BB %"12" is: %"{{[1|8|9]}}" %"{{[1|8|9]}}" %"{{[1|8|9]}}" diff --git a/test/Analysis/GlobalsModRef/aliastest.ll b/test/Analysis/GlobalsModRef/aliastest.ll index ecc6bcc55d1dc..3a0eee84e881c 100644 --- a/test/Analysis/GlobalsModRef/aliastest.ll +++ b/test/Analysis/GlobalsModRef/aliastest.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -basicaa -globals-aa -gvn -S -enable-unsafe-globalsmodref-alias-results | FileCheck %s +; RUN: opt < %s -aa-pipeline=basic-aa,globals-aa -passes="require<globals-aa>,function(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. diff --git a/test/Analysis/GlobalsModRef/comdat-ipo.ll b/test/Analysis/GlobalsModRef/comdat-ipo.ll new file mode 100644 index 0000000000000..a9cc821e7afb2 --- /dev/null +++ b/test/Analysis/GlobalsModRef/comdat-ipo.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -basicaa -globals-aa -gvn -S | FileCheck %s + +; See PR26774 + +@X = internal global i32 4 + +define i32 @test(i32* %P) { +; CHECK: @test +; CHECK-NEXT: store i32 12, i32* @X +; CHECK-NEXT: call void @doesnotmodX() +; CHECK-NEXT: %V = load i32, i32* @X +; CHECK-NEXT: ret i32 %V + store i32 12, i32* @X + call void @doesnotmodX( ) + %V = load i32, i32* @X + ret i32 %V +} + +define linkonce_odr void @doesnotmodX() { + ret void +} diff --git a/test/Analysis/GlobalsModRef/func-memattributes.ll b/test/Analysis/GlobalsModRef/func-memattributes.ll new file mode 100644 index 0000000000000..5494512592e33 --- /dev/null +++ b/test/Analysis/GlobalsModRef/func-memattributes.ll @@ -0,0 +1,31 @@ +; RUN: opt < %s -disable-basicaa -globals-aa -dse -S | FileCheck %s + +@X = internal global i32 4 + +define void @test0() { +; CHECK-LABEL: @test0 +; CHECK: store i32 0, i32* @X +; CHECK-NEXT: call void @func_readonly() #0 +; CHECK-NEXT: store i32 1, i32* @X + store i32 0, i32* @X + call void @func_readonly() #0 + store i32 1, i32* @X + ret void +} + +define void @test1() { +; CHECK-LABEL: @test1 +; CHECK-NOT: store +; CHECK: call void @func_read_argmem_only() #1 +; CHECK-NEXT: store i32 3, i32* @X + store i32 2, i32* @X + call void @func_read_argmem_only() #1 + store i32 3, i32* @X + ret void +} + +declare void @func_readonly() #0 +declare void @func_read_argmem_only() #1 + +attributes #0 = { readonly } +attributes #1 = { readonly argmemonly } diff --git a/test/Analysis/GlobalsModRef/indirect-global.ll b/test/Analysis/GlobalsModRef/indirect-global.ll index a51f54b075032..39d5260b950ac 100644 --- a/test/Analysis/GlobalsModRef/indirect-global.ll +++ b/test/Analysis/GlobalsModRef/indirect-global.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -basicaa -globals-aa -gvn -instcombine -S -enable-unsafe-globalsmodref-alias-results | FileCheck %s +; RUN: opt < %s -aa-pipeline=basic-aa,globals-aa -passes="require<globals-aa>,function(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. diff --git a/test/Analysis/GlobalsModRef/no-escape.ll b/test/Analysis/GlobalsModRef/no-escape.ll new file mode 100644 index 0000000000000..d813a92268c69 --- /dev/null +++ b/test/Analysis/GlobalsModRef/no-escape.ll @@ -0,0 +1,65 @@ +; RUN: opt < %s -basicaa -globals-aa -S -enable-non-lto-gmr=true -licm | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.10.0" + +@b = common global i32 0, align 4 +@c = internal global i32 0, align 4 +@d = common global i32 0, align 4 +@e = common global i32* null, align 4 + +define void @foo(i32* %P) noinline { +; CHECK: define void @foo + %loadp = load i32, i32* %P, align 4 + store i32 %loadp, i32* @d, align 4 + ret void +} + +define void @bar() noinline { +; CHECK: define void @bar + %loadp = load i32, i32* @d, align 4 + store i32 %loadp, i32* @c, align 4 + ret void +} + +define i32 @main() { +entry: + %retval = alloca i32, align 4 + %c = alloca [1 x i32], align 4 + store i32 0, i32* %retval, align 4 + call void @bar() + store i32 0, i32* @b, align 4 + br label %for.cond + ;; Check that @c is LICM'ed out. +; CHECK: load i32, i32* @c +for.cond: ; preds = %for.inc, %entry +; CHECK-LABEL: for.cond: +; CHECK: load i32, i32* @b + %a1 = load i32, i32* @b, align 4 + %aa2 = load i32, i32* @c, align 4 + %add = add nsw i32 %a1, %aa2 + %p1 = load i32*, i32** @e, align 4 + call void @foo(i32* %p1) + %cmp = icmp slt i32 %add, 3 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %a2 = load i32, i32* @b, align 4 + %idxprom = sext i32 %a2 to i64 + br label %for.inc + +for.inc: ; preds = %for.body + %a3 = load i32, i32* @b, align 4 + %inc = add nsw i32 %a3, 1 + store i32 %inc, i32* @b, align 4 + br label %for.cond + +for.end: ; preds = %for.cond + 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/LazyCallGraph/basic.ll b/test/Analysis/LazyCallGraph/basic.ll index fce453bc15de7..0d05a7a6514ec 100644 --- a/test/Analysis/LazyCallGraph/basic.ll +++ b/test/Analysis/LazyCallGraph/basic.ll @@ -1,9 +1,9 @@ -; RUN: opt -disable-output -passes=print-cg %s 2>&1 | FileCheck %s +; RUN: opt -disable-output -passes=print-lcg %s 2>&1 | FileCheck %s ; ; Basic validation of the call graph analysis used in the new pass manager. define void @f() { -; CHECK-LABEL: Call edges in function: f +; CHECK-LABEL: Edges in function: f ; CHECK-NOT: -> entry: @@ -51,8 +51,8 @@ define void @f12() { declare i32 @__gxx_personality_v0(...) define void @test0() { -; CHECK-LABEL: Call edges in function: test0 -; CHECK-NEXT: -> f +; CHECK-LABEL: Edges in function: test0 +; CHECK-NEXT: call -> f ; CHECK-NOT: -> entry: @@ -64,19 +64,19 @@ entry: } define void ()* @test1(void ()** %x) personality i32 (...)* @__gxx_personality_v0 { -; CHECK-LABEL: Call edges in function: test1 -; CHECK-NEXT: -> f12 -; CHECK-NEXT: -> f11 -; CHECK-NEXT: -> f10 -; CHECK-NEXT: -> f7 -; CHECK-NEXT: -> f9 -; CHECK-NEXT: -> f8 -; CHECK-NEXT: -> f6 -; CHECK-NEXT: -> f5 -; CHECK-NEXT: -> f4 -; CHECK-NEXT: -> f3 -; CHECK-NEXT: -> f2 -; CHECK-NEXT: -> f1 +; CHECK-LABEL: Edges in function: test1 +; CHECK-NEXT: call -> f6 +; CHECK-NEXT: call -> f10 +; CHECK-NEXT: ref -> f12 +; CHECK-NEXT: ref -> f11 +; CHECK-NEXT: ref -> f7 +; CHECK-NEXT: ref -> f9 +; CHECK-NEXT: ref -> f8 +; CHECK-NEXT: ref -> f5 +; CHECK-NEXT: ref -> f4 +; CHECK-NEXT: ref -> f3 +; CHECK-NEXT: ref -> f2 +; CHECK-NEXT: ref -> f1 ; CHECK-NOT: -> entry: @@ -108,14 +108,14 @@ unwind: @h = constant void ()* @f7 define void @test2() { -; CHECK-LABEL: Call edges in function: test2 -; CHECK-NEXT: -> f7 -; CHECK-NEXT: -> f6 -; CHECK-NEXT: -> f5 -; CHECK-NEXT: -> f4 -; CHECK-NEXT: -> f3 -; CHECK-NEXT: -> f2 -; CHECK-NEXT: -> f1 +; CHECK-LABEL: Edges in function: test2 +; CHECK-NEXT: ref -> f7 +; CHECK-NEXT: ref -> f6 +; CHECK-NEXT: ref -> f5 +; CHECK-NEXT: ref -> f4 +; CHECK-NEXT: ref -> f3 +; CHECK-NEXT: ref -> f2 +; CHECK-NEXT: ref -> f1 ; CHECK-NOT: -> load i8*, i8** bitcast (void ()** @g to i8**) @@ -125,52 +125,219 @@ define void @test2() { ret void } +@test3_ptr = external global void ()* + +define void @test3_aa1() { +; CHECK-LABEL: Edges in function: test3_aa1 +; CHECK-NEXT: call -> test3_aa2 +; CHECK-NEXT: ref -> test3_ab1 +; CHECK-NOT: -> + +entry: + call void @test3_aa2() + store void ()* @test3_ab1, void ()** @test3_ptr + ret void +} + +define void @test3_aa2() { +; CHECK-LABEL: Edges in function: test3_aa2 +; CHECK-NEXT: call -> test3_aa1 +; CHECK-NEXT: call -> test3_ab2 +; CHECK-NOT: -> + +entry: + call void @test3_aa1() + call void @test3_ab2() + ret void +} + +define void @test3_ab1() { +; CHECK-LABEL: Edges in function: test3_ab1 +; CHECK-NEXT: call -> test3_ab2 +; CHECK-NEXT: call -> test3_ac1 +; CHECK-NOT: -> + +entry: + call void @test3_ab2() + call void @test3_ac1() + ret void +} + +define void @test3_ab2() { +; CHECK-LABEL: Edges in function: test3_ab2 +; CHECK-NEXT: call -> test3_ab1 +; CHECK-NEXT: call -> test3_ba1 +; CHECK-NOT: -> + +entry: + call void @test3_ab1() + call void @test3_ba1() + ret void +} + +define void @test3_ac1() { +; CHECK-LABEL: Edges in function: test3_ac1 +; CHECK-NEXT: call -> test3_ac2 +; CHECK-NEXT: ref -> test3_aa2 +; CHECK-NOT: -> + +entry: + call void @test3_ac2() + store void ()* @test3_aa2, void ()** @test3_ptr + ret void +} + +define void @test3_ac2() { +; CHECK-LABEL: Edges in function: test3_ac2 +; CHECK-NEXT: call -> test3_ac1 +; CHECK-NEXT: ref -> test3_ba1 +; CHECK-NOT: -> + +entry: + call void @test3_ac1() + store void ()* @test3_ba1, void ()** @test3_ptr + ret void +} + +define void @test3_ba1() { +; CHECK-LABEL: Edges in function: test3_ba1 +; CHECK-NEXT: call -> test3_bb1 +; CHECK-NEXT: ref -> test3_ca1 +; CHECK-NOT: -> + +entry: + call void @test3_bb1() + store void ()* @test3_ca1, void ()** @test3_ptr + ret void +} + +define void @test3_bb1() { +; CHECK-LABEL: Edges in function: test3_bb1 +; CHECK-NEXT: call -> test3_ca2 +; CHECK-NEXT: ref -> test3_ba1 +; CHECK-NOT: -> + +entry: + call void @test3_ca2() + store void ()* @test3_ba1, void ()** @test3_ptr + ret void +} + +define void @test3_ca1() { +; CHECK-LABEL: Edges in function: test3_ca1 +; CHECK-NEXT: call -> test3_ca2 +; CHECK-NOT: -> + +entry: + call void @test3_ca2() + ret void +} + +define void @test3_ca2() { +; CHECK-LABEL: Edges in function: test3_ca2 +; CHECK-NEXT: call -> test3_ca3 +; CHECK-NOT: -> + +entry: + call void @test3_ca3() + ret void +} + +define void @test3_ca3() { +; CHECK-LABEL: Edges in function: test3_ca3 +; CHECK-NEXT: call -> test3_ca1 +; CHECK-NOT: -> + +entry: + call void @test3_ca1() + ret void +} + ; Verify the SCCs formed. ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: f7 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 3 functions: +; CHECK-NEXT: test3_ca3 +; CHECK-NEXT: test3_ca1 +; CHECK-NEXT: test3_ca2 +; +; CHECK-LABEL: RefSCC with 2 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: test3_bb1 +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: test3_ba1 +; +; CHECK-LABEL: RefSCC with 3 call SCCs: +; CHECK-NEXT: SCC with 2 functions: +; CHECK-NEXT: test3_ac2 +; CHECK-NEXT: test3_ac1 +; CHECK-NEXT: SCC with 2 functions: +; CHECK-NEXT: test3_ab2 +; CHECK-NEXT: test3_ab1 +; CHECK-NEXT: SCC with 2 functions: +; CHECK-NEXT: test3_aa2 +; CHECK-NEXT: test3_aa1 +; +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: f7 ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: f6 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: f6 ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: f5 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: f5 ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: f4 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: f4 ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: f3 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: f3 ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: f2 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: f2 ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: f1 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: f1 ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: test2 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: test2 ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: f12 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: f10 ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: f11 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: f12 ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: f10 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: f11 ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: f9 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: f9 ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: f8 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: f8 ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: test1 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: test1 ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: f +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: f ; -; CHECK-LABEL: SCC with 1 functions: -; CHECK-NEXT: test0 +; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: test0 diff --git a/test/Analysis/LazyCallGraph/non-leaf-intrinsics.ll b/test/Analysis/LazyCallGraph/non-leaf-intrinsics.ll index 89a21e542f747..f5dc72ff9e97e 100644 --- a/test/Analysis/LazyCallGraph/non-leaf-intrinsics.ll +++ b/test/Analysis/LazyCallGraph/non-leaf-intrinsics.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -disable-output -passes=print-cg < %s 2>&1 | FileCheck %s +; RUN: opt -S -disable-output -passes=print-lcg < %s 2>&1 | FileCheck %s declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...) declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) @@ -8,7 +8,7 @@ define private void @f() { } define void @calls_statepoint(i8 addrspace(1)* %arg) gc "statepoint-example" { -; CHECK: Call edges in function: calls_statepoint +; CHECK: Edges in function: calls_statepoint ; CHECK-NEXT: -> f entry: %cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)* @@ -17,7 +17,7 @@ entry: } define void @calls_patchpoint() { -; CHECK: Call edges in function: calls_patchpoint +; CHECK: Edges in function: calls_patchpoint ; CHECK-NEXT: -> f entry: %c = bitcast void()* @f to i8* diff --git a/test/Analysis/LoopAccessAnalysis/backward-dep-different-types.ll b/test/Analysis/LoopAccessAnalysis/backward-dep-different-types.ll index 5d4fb7d3d66cb..d8040a31a8dc3 100644 --- a/test/Analysis/LoopAccessAnalysis/backward-dep-different-types.ll +++ b/test/Analysis/LoopAccessAnalysis/backward-dep-different-types.ll @@ -1,4 +1,5 @@ ; RUN: opt -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s ; In this loop just because we access A through different types (int, float) ; we still have a dependence cycle: diff --git a/test/Analysis/LoopAccessAnalysis/forward-loop-carried.ll b/test/Analysis/LoopAccessAnalysis/forward-loop-carried.ll index e18ec2357fdb2..7d3ac09dbb9c4 100644 --- a/test/Analysis/LoopAccessAnalysis/forward-loop-carried.ll +++ b/test/Analysis/LoopAccessAnalysis/forward-loop-carried.ll @@ -1,4 +1,5 @@ ; RUN: opt -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s ; for (unsigned i = 0; i < 100; i++) { ; A[i+8] = B[i] + 2; diff --git a/test/Analysis/LoopAccessAnalysis/forward-loop-independent.ll b/test/Analysis/LoopAccessAnalysis/forward-loop-independent.ll index e1ba674ce80ad..41e2a2904fb2f 100644 --- a/test/Analysis/LoopAccessAnalysis/forward-loop-independent.ll +++ b/test/Analysis/LoopAccessAnalysis/forward-loop-independent.ll @@ -1,4 +1,5 @@ ; RUN: opt -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s ; Check that loop-indepedent forward dependences are discovered properly. ; diff --git a/test/Analysis/LoopAccessAnalysis/independent-interleaved.ll b/test/Analysis/LoopAccessAnalysis/independent-interleaved.ll new file mode 100644 index 0000000000000..fe56ea9ab5939 --- /dev/null +++ b/test/Analysis/LoopAccessAnalysis/independent-interleaved.ll @@ -0,0 +1,46 @@ +; RUN: opt < %s -store-to-load-forwarding-conflict-detection=false -loop-accesses -analyze | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -store-to-load-forwarding-conflict-detection=false -disable-output < %s 2>&1 | FileCheck %s + +; This test checks that we prove the strided accesses to be independent before +; concluding that there is a forward dependence. + +; struct pair { +; int x; +; int y; +; }; +; +; int independent_interleaved(struct pair *p, int z, int n) { +; int s = 0; +; for (int i = 0; i < n; i++) { +; p[i].y = z; +; s += p[i].x; +; } +; return s; +; } + +; CHECK: for.body: +; CHECK-NOT: Forward: +; CHECK-NOT: store i32 %z, i32* %p_i.y, align 8 -> +; CHECK-NOT: %0 = load i32, i32* %p_i.x, align 8 + +%pair = type { i32, i32 } +define i32 @independent_interleaved(%pair *%p, i64 %n, i32 %z) { +entry: + br label %for.body + +for.body: + %i = phi i64 [ %i.next, %for.body ], [ 0, %entry ] + %s = phi i32 [ %1, %for.body ], [ 0, %entry ] + %p_i.x = getelementptr inbounds %pair, %pair* %p, i64 %i, i32 0 + %p_i.y = getelementptr inbounds %pair, %pair* %p, i64 %i, i32 1 + store i32 %z, i32* %p_i.y, align 8 + %0 = load i32, i32* %p_i.x, align 8 + %1 = add nsw i32 %0, %s + %i.next = add nuw nsw i64 %i, 1 + %cond = icmp slt i64 %i.next, %n + br i1 %cond, label %for.body, label %for.end + +for.end: + %2 = phi i32 [ %1, %for.body ] + ret i32 %2 +} diff --git a/test/Analysis/LoopAccessAnalysis/memcheck-for-loop-invariant.ll b/test/Analysis/LoopAccessAnalysis/memcheck-for-loop-invariant.ll new file mode 100644 index 0000000000000..f06bb00ec64aa --- /dev/null +++ b/test/Analysis/LoopAccessAnalysis/memcheck-for-loop-invariant.ll @@ -0,0 +1,39 @@ +; RUN: opt -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s + +; Handle memchecks involving loop-invariant addresses: +; +; extern int *A, *b; +; for (i = 0; i < N; ++i) { +; A[i] = b; +; } + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + +; CHECK: Memory dependences are safe with run-time checks +; CHECK: Run-time memory checks: +; CHECK-NEXT: Check 0: +; CHECK-NEXT: Comparing group ({{.*}}): +; CHECK-NEXT: %arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind +; CHECK-NEXT: Against group ({{.*}}): +; CHECK-NEXT: i32* %b + +define void @f(i32* %a, i32* %b) { +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %ind = phi i64 [ 0, %entry ], [ %inc, %for.body ] + + %arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind + + %loadB = load i32, i32* %b, align 4 + store i32 %loadB, i32* %arrayidxA, align 4 + + %inc = add nuw nsw i64 %ind, 1 + %exitcond = icmp eq i64 %inc, 20 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} diff --git a/test/Analysis/LoopAccessAnalysis/multiple-strides-rt-memory-checks.ll b/test/Analysis/LoopAccessAnalysis/multiple-strides-rt-memory-checks.ll new file mode 100644 index 0000000000000..87a6c18ab3034 --- /dev/null +++ b/test/Analysis/LoopAccessAnalysis/multiple-strides-rt-memory-checks.ll @@ -0,0 +1,68 @@ +; RUN: opt -loop-accesses -analyze -S < %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s + +; This is the test case from PR26314. +; When we were retrying dependence checking with memchecks only, +; the loop-invariant access in the inner loop was incorrectly determined to be wrapping +; because it was not strided in the inner loop. + +; #define Z 32 +; typedef struct s { +; int v1[Z]; +; int v2[Z]; +; int v3[Z][Z]; +; } s; +; +; void slow_function (s* const obj) { +; for (int j=0; j<Z; j++) { +; for (int k=0; k<Z; k++) { +; int x = obj->v1[k] + obj->v2[j]; +; obj->v3[j][k] += x; +; } +; } +; } + +; CHECK: function 'Test': +; CHECK: .inner: +; CHECK-NEXT: Memory dependences are safe +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Run-time memory checks: +; CHECK: Check 0: +; CHECK: Check 1: + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.s = type { [32 x i32], [32 x i32], [32 x [32 x i32]] } + +define void @Test(%struct.s* nocapture %obj) #0 { + br label %.outer.preheader + + +.outer.preheader: + %i = phi i64 [ 0, %0 ], [ %i.next, %.outer ] + %1 = getelementptr inbounds %struct.s, %struct.s* %obj, i64 0, i32 1, i64 %i + br label %.inner + +.exit: + ret void + +.outer: + %i.next = add nuw nsw i64 %i, 1 + %exitcond.outer = icmp eq i64 %i.next, 32 + br i1 %exitcond.outer, label %.exit, label %.outer.preheader + +.inner: + %j = phi i64 [ 0, %.outer.preheader ], [ %j.next, %.inner ] + %2 = getelementptr inbounds %struct.s, %struct.s* %obj, i64 0, i32 0, i64 %j + %3 = load i32, i32* %2 + %4 = load i32, i32* %1 + %5 = add nsw i32 %4, %3 + %6 = getelementptr inbounds %struct.s, %struct.s* %obj, i64 0, i32 2, i64 %i, i64 %j + %7 = load i32, i32* %6 + %8 = add nsw i32 %5, %7 + store i32 %8, i32* %6 + %j.next = add nuw nsw i64 %j, 1 + %exitcond.inner = icmp eq i64 %j.next, 32 + br i1 %exitcond.inner, label %.outer, label %.inner +} diff --git a/test/Analysis/LoopAccessAnalysis/non-wrapping-pointer.ll b/test/Analysis/LoopAccessAnalysis/non-wrapping-pointer.ll index 0de1cd1bea6de..94080f05bde26 100644 --- a/test/Analysis/LoopAccessAnalysis/non-wrapping-pointer.ll +++ b/test/Analysis/LoopAccessAnalysis/non-wrapping-pointer.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<aa>,require<scalar-evolution>,require<aa>,loop(print-access-info)' -aa-pipeline='basic-aa' -disable-output < %s 2>&1 | FileCheck %s ; For this loop: ; for (int i = 0; i < n; i++) diff --git a/test/Analysis/LoopAccessAnalysis/nullptr.ll b/test/Analysis/LoopAccessAnalysis/nullptr.ll index a72b48cc352d7..476cf3208c84c 100644 --- a/test/Analysis/LoopAccessAnalysis/nullptr.ll +++ b/test/Analysis/LoopAccessAnalysis/nullptr.ll @@ -1,4 +1,5 @@ ; RUN: opt -loop-accesses -analyze %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s ; Test that the loop accesses are proven safe in this case. ; The analyzer uses to be confused by the "diamond" because GetUnderlyingObjects diff --git a/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll b/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll index 01b3eda3e123b..a9626f4dc7103 100644 --- a/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll +++ b/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll @@ -1,4 +1,5 @@ ; RUN: opt -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" target triple = "aarch64--linux-gnueabi" @@ -96,11 +97,11 @@ for.end: ; preds = %for.body ; CHECK-NEXT: Grouped accesses: ; CHECK-NEXT: Group {{.*}}[[ZERO]]: ; CHECK-NEXT: (Low: %c High: (78 + %c)) -; CHECK-NEXT: Member: {(2 + %c),+,4} +; CHECK-NEXT: Member: {(2 + %c)<nsw>,+,4} ; CHECK-NEXT: Member: {%c,+,4} ; CHECK-NEXT: Group {{.*}}[[ONE]]: ; CHECK-NEXT: (Low: %a High: (40 + %a)) -; CHECK-NEXT: Member: {(2 + %a),+,2} +; CHECK-NEXT: Member: {(2 + %a)<nsw>,+,2} ; CHECK-NEXT: Member: {%a,+,2} ; CHECK-NEXT: Group {{.*}}[[TWO]]: ; CHECK-NEXT: (Low: %b High: (38 + %b)) @@ -168,7 +169,7 @@ for.end: ; preds = %for.body ; CHECK-NEXT: Grouped accesses: ; CHECK-NEXT: Group {{.*}}[[ZERO]]: ; CHECK-NEXT: (Low: %c High: (78 + %c)) -; CHECK-NEXT: Member: {(2 + %c),+,4} +; CHECK-NEXT: Member: {(2 + %c)<nsw>,+,4} ; CHECK-NEXT: Member: {%c,+,4} ; CHECK-NEXT: Group {{.*}}[[ONE]]: ; CHECK-NEXT: (Low: %a High: (40 + %a)) @@ -246,8 +247,8 @@ for.end: ; preds = %for.body ; CHECK-NEXT: %arrayidxA2 = getelementptr i16, i16* %a, i64 %ind2 ; CHECK-NEXT: Grouped accesses: ; 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: (Low: ((2 * %offset) + %a)<nsw> High: (9998 + (2 * %offset) + %a)) +; CHECK-NEXT: Member: {((2 * %offset) + %a)<nsw>,+,2}<nsw><%for.body> ; CHECK-NEXT: Group {{.*}}[[ONE]]: ; CHECK-NEXT: (Low: %a High: (9998 + %a)) ; CHECK-NEXT: Member: {%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 20b7fb2c63353..a10b851bcd1a2 100644 --- a/test/Analysis/LoopAccessAnalysis/pointer-with-unknown-bounds.ll +++ b/test/Analysis/LoopAccessAnalysis/pointer-with-unknown-bounds.ll @@ -1,4 +1,5 @@ ; RUN: opt -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" diff --git a/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll b/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll index 9412028fc7026..921fd4d06314d 100644 --- a/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll +++ b/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll @@ -1,4 +1,5 @@ ; RUN: opt -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s ; 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 diff --git a/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll b/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll index 2053e49826b99..607e007f7a2d1 100644 --- a/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll +++ b/test/Analysis/LoopAccessAnalysis/reverse-memcheck-bounds.ll @@ -1,4 +1,5 @@ ; RUN: opt -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s ; The runtime memory check code and the access grouping ; algorithm both assume that the start and end values @@ -15,7 +16,7 @@ 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)) +; CHECK: (Low: (20000 + %a) High: (60000 + %a)<nsw>) @B = common global i32* null, align 8 @A = common global i32* null, align 8 @@ -58,7 +59,7 @@ for.end: ; preds = %for.body ; 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)) +; CHECK: High: ((60000 + %a)<nsw> umax (60000 + (-40000 * %step) + %a)) define void @g(i64 %step) { entry: diff --git a/test/Analysis/LoopAccessAnalysis/safe-no-checks.ll b/test/Analysis/LoopAccessAnalysis/safe-no-checks.ll index d85258f75aaef..8018994009957 100644 --- a/test/Analysis/LoopAccessAnalysis/safe-no-checks.ll +++ b/test/Analysis/LoopAccessAnalysis/safe-no-checks.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<aa>,require<scalar-evolution>,require<aa>,loop(print-access-info)' -aa-pipeline='basic-aa' -disable-output < %s 2>&1 | FileCheck %s ; If the arrays don't alias this loop is safe with no memchecks: ; for (i = 0; i < n; i++) diff --git a/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance.ll b/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance.ll new file mode 100644 index 0000000000000..910d49edbb181 --- /dev/null +++ b/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance.ll @@ -0,0 +1,38 @@ +; RUN: opt -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s + +; Analyze this loop: +; for (i = 0; i < n; i++) +; A[i + 4] = A[i] * 2; + +; CHECK: Memory dependences are safe with a maximum dependence distance of 8 bytes + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.10.0" + +@A = common global i16* null, align 8 + +define void @f() { +entry: + %a = load i16*, i16** @A, align 8 + br label %for.body + +for.body: ; preds = %for.body, %entry + %ind = phi i64 [ 0, %entry ], [ %add, %for.body ] + + %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind + %loadA = load i16, i16* %arrayidxA, align 2 + + %mul = mul i16 %loadA, 2 + + %next = add nuw nsw i64 %ind, 4 + %arrayidxA_next = getelementptr inbounds i16, i16* %a, i64 %next + store i16 %mul, i16* %arrayidxA_next, align 2 + + %add = add nuw nsw i64 %ind, 1 + %exitcond = icmp eq i64 %add, 20 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} diff --git a/test/Analysis/LoopAccessAnalysis/store-to-invariant-check1.ll b/test/Analysis/LoopAccessAnalysis/store-to-invariant-check1.ll index 8ab8ab2a55b6b..ac8803ea9ebca 100644 --- a/test/Analysis/LoopAccessAnalysis/store-to-invariant-check1.ll +++ b/test/Analysis/LoopAccessAnalysis/store-to-invariant-check1.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -loop-accesses -analyze | FileCheck %s +; RUN: opt < %s -loop-accesses -analyze | FileCheck -check-prefix=OLDPM %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck -check-prefix=NEWPM %s ; Test to confirm LAA will find store to invariant address. ; Inner loop has a store to invariant address. @@ -9,8 +10,17 @@ ; } ; } -; CHECK: Store to invariant address was found in loop. -; CHECK-NOT: Store to invariant address was not found in loop. +; The LAA with the new PM is a loop pass so we go from inner to outer loops. + +; OLDPM: for.cond1.preheader: +; OLDPM: Store to invariant address was not found in loop. +; OLDPM: for.body3: +; OLDPM: Store to invariant address was found in loop. + +; NEWPM: for.body3: +; NEWPM: Store to invariant address was found in loop. +; NEWPM: for.cond1.preheader: +; NEWPM: Store to invariant address was not found in loop. define i32 @foo(i32* nocapture %var1, i32* nocapture readonly %var2, i32 %itr) #0 { entry: diff --git a/test/Analysis/LoopAccessAnalysis/store-to-invariant-check2.ll b/test/Analysis/LoopAccessAnalysis/store-to-invariant-check2.ll index 4da0906894926..711c14ef7728d 100644 --- a/test/Analysis/LoopAccessAnalysis/store-to-invariant-check2.ll +++ b/test/Analysis/LoopAccessAnalysis/store-to-invariant-check2.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -loop-accesses -analyze | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s ; Test to confirm LAA will not find store to invariant address. ; Inner loop has no store to invariant address. diff --git a/test/Analysis/LoopAccessAnalysis/store-to-invariant-check3.ll b/test/Analysis/LoopAccessAnalysis/store-to-invariant-check3.ll index 18315a59dc3a7..85fea798071f0 100644 --- a/test/Analysis/LoopAccessAnalysis/store-to-invariant-check3.ll +++ b/test/Analysis/LoopAccessAnalysis/store-to-invariant-check3.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -loop-accesses -analyze | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s ; Test to confirm LAA will find store to invariant address. ; Inner loop has a store to invariant address. diff --git a/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll b/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll index 5fc353e70cf83..4fe6f9f704f71 100644 --- a/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll +++ b/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll @@ -1,4 +1,5 @@ ; RUN: opt -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" @@ -384,7 +385,7 @@ for.body: ; preds = %entry, %for.body ; return sum; ; } -; CHECK: for function 'vectorizable_unscaled_Write_Read': +; CHECK: function 'vectorizable_unscaled_Write_Read': ; CHECK-NEXT: for.body: ; CHECK-NEXT: Memory dependences are safe ; CHECK-NEXT: Dependences: diff --git a/test/Analysis/LoopAccessAnalysis/underlying-objects-1.ll b/test/Analysis/LoopAccessAnalysis/underlying-objects-1.ll index 44820ed372221..705453b65cc50 100644 --- a/test/Analysis/LoopAccessAnalysis/underlying-objects-1.ll +++ b/test/Analysis/LoopAccessAnalysis/underlying-objects-1.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s ; In: ; diff --git a/test/Analysis/LoopAccessAnalysis/underlying-objects-2.ll b/test/Analysis/LoopAccessAnalysis/underlying-objects-2.ll index d388151365f18..f9d88e891be9b 100644 --- a/test/Analysis/LoopAccessAnalysis/underlying-objects-2.ll +++ b/test/Analysis/LoopAccessAnalysis/underlying-objects-2.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s ; This loop: ; diff --git a/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll b/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll index 7157b954c5b6d..7fbed6fcc15cf 100644 --- a/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll +++ b/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll @@ -1,4 +1,5 @@ ; RUN: opt -loop-accesses -analyze < %s | FileCheck %s +; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s ; Analyze this loop: ; for (i = 0; i < n; i++) diff --git a/test/Analysis/LoopAccessAnalysis/wrapping-pointer-versioning.ll b/test/Analysis/LoopAccessAnalysis/wrapping-pointer-versioning.ll new file mode 100644 index 0000000000000..75a71b444283f --- /dev/null +++ b/test/Analysis/LoopAccessAnalysis/wrapping-pointer-versioning.ll @@ -0,0 +1,429 @@ +; RUN: opt -basicaa -loop-accesses -analyze < %s | FileCheck %s -check-prefix=LAA +; RUN: opt -passes='require<aa>,require<scalar-evolution>,require<aa>,loop(print-access-info)' -aa-pipeline='basic-aa' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=LAA +; RUN: opt -loop-versioning -S < %s | FileCheck %s -check-prefix=LV + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + +; For this loop: +; unsigned index = 0; +; for (int i = 0; i < n; i++) { +; A[2 * index] = A[2 * index] + B[i]; +; index++; +; } +; +; SCEV is unable to prove that A[2 * i] does not overflow. +; +; Analyzing the IR does not help us because the GEPs are not +; affine AddRecExprs. However, we can turn them into AddRecExprs +; using SCEV Predicates. +; +; Once we have an affine expression we need to add an additional NUSW +; to check that the pointers don't wrap since the GEPs are not +; inbound. + +; LAA-LABEL: f1 +; LAA: Memory dependences are safe{{$}} +; LAA: SCEV assumptions: +; LAA-NEXT: {0,+,2}<%for.body> Added Flags: <nusw> +; LAA-NEXT: {%a,+,4}<%for.body> Added Flags: <nusw> + +; The expression for %mul_ext as analyzed by SCEV is +; (zext i32 {0,+,2}<%for.body> to i64) +; We have added the nusw flag to turn this expression into the SCEV expression: +; i64 {0,+,2}<%for.body> + +; LAA: [PSE] %arrayidxA = getelementptr i16, i16* %a, i64 %mul_ext: +; LAA-NEXT: ((2 * (zext i32 {0,+,2}<%for.body> to i64)) + %a) +; LAA-NEXT: --> {%a,+,4}<%for.body> + + +; LV-LABEL: f1 +; LV-LABEL: for.body.lver.check + +; LV: [[BETrunc:%[^ ]*]] = trunc i64 [[BE:%[^ ]*]] to i32 +; LV-NEXT: [[OFMul:%[^ ]*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 2, i32 [[BETrunc]]) +; LV-NEXT: [[OFMulResult:%[^ ]*]] = extractvalue { i32, i1 } [[OFMul]], 0 +; LV-NEXT: [[OFMulOverflow:%[^ ]*]] = extractvalue { i32, i1 } [[OFMul]], 1 +; LV-NEXT: [[AddEnd:%[^ ]*]] = add i32 0, [[OFMulResult]] +; LV-NEXT: [[SubEnd:%[^ ]*]] = sub i32 0, [[OFMulResult]] +; LV-NEXT: [[CmpNeg:%[^ ]*]] = icmp ugt i32 [[SubEnd]], 0 +; LV-NEXT: [[CmpPos:%[^ ]*]] = icmp ult i32 [[AddEnd]], 0 +; LV-NEXT: [[Cmp:%[^ ]*]] = select i1 false, i1 [[CmpNeg]], i1 [[CmpPos]] +; LV-NEXT: [[BECheck:%[^ ]*]] = icmp ugt i64 [[BE]], 4294967295 +; LV-NEXT: [[CheckOr0:%[^ ]*]] = or i1 [[Cmp]], [[BECheck]] +; LV-NEXT: [[PredCheck0:%[^ ]*]] = or i1 [[CheckOr0]], [[OFMulOverflow]] + +; LV-NEXT: [[Or0:%[^ ]*]] = or i1 false, [[PredCheck0]] + +; LV-NEXT: [[OFMul1:%[^ ]*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 4, i64 [[BE]]) +; LV-NEXT: [[OFMulResult1:%[^ ]*]] = extractvalue { i64, i1 } [[OFMul1]], 0 +; LV-NEXT: [[OFMulOverflow1:%[^ ]*]] = extractvalue { i64, i1 } [[OFMul1]], 1 +; LV-NEXT: [[AddEnd1:%[^ ]*]] = add i64 %a2, [[OFMulResult1]] +; LV-NEXT: [[SubEnd1:%[^ ]*]] = sub i64 %a2, [[OFMulResult1]] +; LV-NEXT: [[CmpNeg1:%[^ ]*]] = icmp ugt i64 [[SubEnd1]], %a2 +; LV-NEXT: [[CmpPos1:%[^ ]*]] = icmp ult i64 [[AddEnd1]], %a2 +; LV-NEXT: [[Cmp:%[^ ]*]] = select i1 false, i1 [[CmpNeg1]], i1 [[CmpPos1]] +; LV-NEXT: [[PredCheck1:%[^ ]*]] = or i1 [[Cmp]], [[OFMulOverflow1]] + +; LV: [[FinalCheck:%[^ ]*]] = or i1 [[Or0]], [[PredCheck1]] +; LV: br i1 [[FinalCheck]], label %for.body.ph.lver.orig, label %for.body.ph +define void @f1(i16* noalias %a, + i16* noalias %b, i64 %N) { +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %ind = phi i64 [ 0, %entry ], [ %inc, %for.body ] + %ind1 = phi i32 [ 0, %entry ], [ %inc1, %for.body ] + + %mul = mul i32 %ind1, 2 + %mul_ext = zext i32 %mul to i64 + + %arrayidxA = getelementptr i16, i16* %a, i64 %mul_ext + %loadA = load i16, i16* %arrayidxA, align 2 + + %arrayidxB = getelementptr i16, i16* %b, i64 %ind + %loadB = load i16, i16* %arrayidxB, align 2 + + %add = mul i16 %loadA, %loadB + + store i16 %add, i16* %arrayidxA, align 2 + + %inc = add nuw nsw i64 %ind, 1 + %inc1 = add i32 %ind1, 1 + + %exitcond = icmp eq i64 %inc, %N + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} + +; For this loop: +; unsigned index = n; +; for (int i = 0; i < n; i++) { +; A[2 * index] = A[2 * index] + B[i]; +; index--; +; } +; +; the SCEV expression for 2 * index is not an AddRecExpr +; (and implictly not affine). However, we are able to make assumptions +; that will turn the expression into an affine one and continue the +; analysis. +; +; Once we have an affine expression we need to add an additional NUSW +; to check that the pointers don't wrap since the GEPs are not +; inbounds. +; +; This loop has a negative stride for A, and the nusw flag is required in +; order to properly extend the increment from i32 -4 to i64 -4. + +; LAA-LABEL: f2 +; LAA: Memory dependences are safe{{$}} +; LAA: SCEV assumptions: +; LAA-NEXT: {(2 * (trunc i64 %N to i32)),+,-2}<%for.body> Added Flags: <nusw> +; LAA-NEXT: {((2 * (zext i32 (2 * (trunc i64 %N to i32)) to i64)) + %a),+,-4}<%for.body> Added Flags: <nusw> + +; The expression for %mul_ext as analyzed by SCEV is +; (zext i32 {(2 * (trunc i64 %N to i32)),+,-2}<%for.body> to i64) +; We have added the nusw flag to turn this expression into the following SCEV: +; i64 {zext i32 (2 * (trunc i64 %N to i32)) to i64,+,-2}<%for.body> + +; LAA: [PSE] %arrayidxA = getelementptr i16, i16* %a, i64 %mul_ext: +; LAA-NEXT: ((2 * (zext i32 {(2 * (trunc i64 %N to i32)),+,-2}<%for.body> to i64)) + %a) +; LAA-NEXT: --> {((2 * (zext i32 (2 * (trunc i64 %N to i32)) to i64)) + %a),+,-4}<%for.body> + +; LV-LABEL: f2 +; LV-LABEL: for.body.lver.check + +; LV: [[OFMul:%[^ ]*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 2, i32 [[BETrunc:%[^ ]*]]) +; LV-NEXT: [[OFMulResult:%[^ ]*]] = extractvalue { i32, i1 } [[OFMul]], 0 +; LV-NEXT: [[OFMulOverflow:%[^ ]*]] = extractvalue { i32, i1 } [[OFMul]], 1 +; LV-NEXT: [[AddEnd:%[^ ]*]] = add i32 [[Start:%[^ ]*]], [[OFMulResult]] +; LV-NEXT: [[SubEnd:%[^ ]*]] = sub i32 [[Start]], [[OFMulResult]] +; LV-NEXT: [[CmpNeg:%[^ ]*]] = icmp ugt i32 [[SubEnd]], [[Start]] +; LV-NEXT: [[CmpPos:%[^ ]*]] = icmp ult i32 [[AddEnd]], [[Start]] +; LV-NEXT: [[Cmp:%[^ ]*]] = select i1 true, i1 [[CmpNeg]], i1 [[CmpPos]] +; LV-NEXT: [[BECheck:%[^ ]*]] = icmp ugt i64 [[BE]], 4294967295 +; LV-NEXT: [[CheckOr0:%[^ ]*]] = or i1 [[Cmp]], [[BECheck]] +; LV-NEXT: [[PredCheck0:%[^ ]*]] = or i1 [[CheckOr0]], [[OFMulOverflow]] + +; LV-NEXT: [[Or0:%[^ ]*]] = or i1 false, [[PredCheck0]] + +; LV: [[OFMul1:%[^ ]*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 4, i64 [[BE]]) +; LV-NEXT: [[OFMulResult1:%[^ ]*]] = extractvalue { i64, i1 } [[OFMul1]], 0 +; LV-NEXT: [[OFMulOverflow1:%[^ ]*]] = extractvalue { i64, i1 } [[OFMul1]], 1 +; LV-NEXT: [[AddEnd1:%[^ ]*]] = add i64 [[Start:%[^ ]*]], [[OFMulResult1]] +; LV-NEXT: [[SubEnd1:%[^ ]*]] = sub i64 [[Start]], [[OFMulResult1]] +; LV-NEXT: [[CmpNeg1:%[^ ]*]] = icmp ugt i64 [[SubEnd1]], [[Start]] +; LV-NEXT: [[CmpPos1:%[^ ]*]] = icmp ult i64 [[AddEnd1]], [[Start]] +; LV-NEXT: [[Cmp:%[^ ]*]] = select i1 true, i1 [[CmpNeg1]], i1 [[CmpPos1]] +; LV-NEXT: [[PredCheck1:%[^ ]*]] = or i1 [[Cmp]], [[OFMulOverflow1]] + +; LV: [[FinalCheck:%[^ ]*]] = or i1 [[Or0]], [[PredCheck1]] +; LV: br i1 [[FinalCheck]], label %for.body.ph.lver.orig, label %for.body.ph +define void @f2(i16* noalias %a, + i16* noalias %b, i64 %N) { +entry: + %TruncN = trunc i64 %N to i32 + br label %for.body + +for.body: ; preds = %for.body, %entry + %ind = phi i64 [ 0, %entry ], [ %inc, %for.body ] + %ind1 = phi i32 [ %TruncN, %entry ], [ %dec, %for.body ] + + %mul = mul i32 %ind1, 2 + %mul_ext = zext i32 %mul to i64 + + %arrayidxA = getelementptr i16, i16* %a, i64 %mul_ext + %loadA = load i16, i16* %arrayidxA, align 2 + + %arrayidxB = getelementptr i16, i16* %b, i64 %ind + %loadB = load i16, i16* %arrayidxB, align 2 + + %add = mul i16 %loadA, %loadB + + store i16 %add, i16* %arrayidxA, align 2 + + %inc = add nuw nsw i64 %ind, 1 + %dec = sub i32 %ind1, 1 + + %exitcond = icmp eq i64 %inc, %N + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} + +; We replicate the tests above, but this time sign extend 2 * index instead +; of zero extending it. + +; LAA-LABEL: f3 +; LAA: Memory dependences are safe{{$}} +; LAA: SCEV assumptions: +; LAA-NEXT: {0,+,2}<%for.body> Added Flags: <nssw> +; LAA-NEXT: {%a,+,4}<%for.body> Added Flags: <nusw> + +; The expression for %mul_ext as analyzed by SCEV is +; i64 (sext i32 {0,+,2}<%for.body> to i64) +; We have added the nssw flag to turn this expression into the following SCEV: +; i64 {0,+,2}<%for.body> + +; LAA: [PSE] %arrayidxA = getelementptr i16, i16* %a, i64 %mul_ext: +; LAA-NEXT: ((2 * (sext i32 {0,+,2}<%for.body> to i64)) + %a) +; LAA-NEXT: --> {%a,+,4}<%for.body> + +; LV-LABEL: f3 +; LV-LABEL: for.body.lver.check + +; LV: [[OFMul:%[^ ]*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 2, i32 [[BETrunc:%[^ ]*]]) +; LV-NEXT: [[OFMulResult:%[^ ]*]] = extractvalue { i32, i1 } [[OFMul]], 0 +; LV-NEXT: [[OFMulOverflow:%[^ ]*]] = extractvalue { i32, i1 } [[OFMul]], 1 +; LV-NEXT: [[AddEnd:%[^ ]*]] = add i32 0, [[OFMulResult]] +; LV-NEXT: [[SubEnd:%[^ ]*]] = sub i32 0, [[OFMulResult]] +; LV-NEXT: [[CmpNeg:%[^ ]*]] = icmp sgt i32 [[SubEnd]], 0 +; LV-NEXT: [[CmpPos:%[^ ]*]] = icmp slt i32 [[AddEnd]], 0 +; LV-NEXT: [[Cmp:%[^ ]*]] = select i1 false, i1 [[CmpNeg]], i1 [[CmpPos]] +; LV-NEXT: [[BECheck:%[^ ]*]] = icmp ugt i64 [[BE]], 4294967295 +; LV-NEXT: [[CheckOr0:%[^ ]*]] = or i1 [[Cmp]], [[BECheck]] +; LV-NEXT: [[PredCheck0:%[^ ]*]] = or i1 [[CheckOr0]], [[OFMulOverflow]] + +; LV-NEXT: [[Or0:%[^ ]*]] = or i1 false, [[PredCheck0]] + +; LV: [[OFMul1:%[^ ]*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 4, i64 [[BE:%[^ ]*]]) +; LV-NEXT: [[OFMulResult1:%[^ ]*]] = extractvalue { i64, i1 } [[OFMul1]], 0 +; LV-NEXT: [[OFMulOverflow1:%[^ ]*]] = extractvalue { i64, i1 } [[OFMul1]], 1 +; LV-NEXT: [[AddEnd1:%[^ ]*]] = add i64 %a2, [[OFMulResult1]] +; LV-NEXT: [[SubEnd1:%[^ ]*]] = sub i64 %a2, [[OFMulResult1]] +; LV-NEXT: [[CmpNeg1:%[^ ]*]] = icmp ugt i64 [[SubEnd1]], %a2 +; LV-NEXT: [[CmpPos1:%[^ ]*]] = icmp ult i64 [[AddEnd1]], %a2 +; LV-NEXT: [[Cmp:%[^ ]*]] = select i1 false, i1 [[CmpNeg1]], i1 [[CmpPos1]] +; LV-NEXT: [[PredCheck1:%[^ ]*]] = or i1 [[Cmp]], [[OFMulOverflow1]] + +; LV: [[FinalCheck:%[^ ]*]] = or i1 [[Or0]], [[PredCheck1]] +; LV: br i1 [[FinalCheck]], label %for.body.ph.lver.orig, label %for.body.ph +define void @f3(i16* noalias %a, + i16* noalias %b, i64 %N) { +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %ind = phi i64 [ 0, %entry ], [ %inc, %for.body ] + %ind1 = phi i32 [ 0, %entry ], [ %inc1, %for.body ] + + %mul = mul i32 %ind1, 2 + %mul_ext = sext i32 %mul to i64 + + %arrayidxA = getelementptr i16, i16* %a, i64 %mul_ext + %loadA = load i16, i16* %arrayidxA, align 2 + + %arrayidxB = getelementptr i16, i16* %b, i64 %ind + %loadB = load i16, i16* %arrayidxB, align 2 + + %add = mul i16 %loadA, %loadB + + store i16 %add, i16* %arrayidxA, align 2 + + %inc = add nuw nsw i64 %ind, 1 + %inc1 = add i32 %ind1, 1 + + %exitcond = icmp eq i64 %inc, %N + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} + +; LAA-LABEL: f4 +; LAA: Memory dependences are safe{{$}} +; LAA: SCEV assumptions: +; LAA-NEXT: {(2 * (trunc i64 %N to i32)),+,-2}<%for.body> Added Flags: <nssw> +; LAA-NEXT: {((2 * (sext i32 (2 * (trunc i64 %N to i32)) to i64)) + %a),+,-4}<%for.body> Added Flags: <nusw> + +; The expression for %mul_ext as analyzed by SCEV is +; i64 (sext i32 {(2 * (trunc i64 %N to i32)),+,-2}<%for.body> to i64) +; We have added the nssw flag to turn this expression into the following SCEV: +; i64 {sext i32 (2 * (trunc i64 %N to i32)) to i64,+,-2}<%for.body> + +; LAA: [PSE] %arrayidxA = getelementptr i16, i16* %a, i64 %mul_ext: +; LAA-NEXT: ((2 * (sext i32 {(2 * (trunc i64 %N to i32)),+,-2}<%for.body> to i64)) + %a) +; LAA-NEXT: --> {((2 * (sext i32 (2 * (trunc i64 %N to i32)) to i64)) + %a),+,-4}<%for.body> + +; LV-LABEL: f4 +; LV-LABEL: for.body.lver.check + +; LV: [[OFMul:%[^ ]*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 2, i32 [[BETrunc:%[^ ]*]]) +; LV-NEXT: [[OFMulResult:%[^ ]*]] = extractvalue { i32, i1 } [[OFMul]], 0 +; LV-NEXT: [[OFMulOverflow:%[^ ]*]] = extractvalue { i32, i1 } [[OFMul]], 1 +; LV-NEXT: [[AddEnd:%[^ ]*]] = add i32 [[Start:%[^ ]*]], [[OFMulResult]] +; LV-NEXT: [[SubEnd:%[^ ]*]] = sub i32 [[Start]], [[OFMulResult]] +; LV-NEXT: [[CmpNeg:%[^ ]*]] = icmp sgt i32 [[SubEnd]], [[Start]] +; LV-NEXT: [[CmpPos:%[^ ]*]] = icmp slt i32 [[AddEnd]], [[Start]] +; LV-NEXT: [[Cmp:%[^ ]*]] = select i1 true, i1 [[CmpNeg]], i1 [[CmpPos]] +; LV-NEXT: [[BECheck:%[^ ]*]] = icmp ugt i64 [[BE]], 4294967295 +; LV-NEXT: [[CheckOr0:%[^ ]*]] = or i1 [[Cmp]], [[BECheck]] +; LV-NEXT: [[PredCheck0:%[^ ]*]] = or i1 [[CheckOr0]], [[OFMulOverflow]] + +; LV-NEXT: [[Or0:%[^ ]*]] = or i1 false, [[PredCheck0]] + +; LV: [[OFMul1:%[^ ]*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 4, i64 [[BE:%[^ ]*]]) +; LV-NEXT: [[OFMulResult1:%[^ ]*]] = extractvalue { i64, i1 } [[OFMul1]], 0 +; LV-NEXT: [[OFMulOverflow1:%[^ ]*]] = extractvalue { i64, i1 } [[OFMul1]], 1 +; LV-NEXT: [[AddEnd1:%[^ ]*]] = add i64 [[Start:%[^ ]*]], [[OFMulResult1]] +; LV-NEXT: [[SubEnd1:%[^ ]*]] = sub i64 [[Start]], [[OFMulResult1]] +; LV-NEXT: [[CmpNeg1:%[^ ]*]] = icmp ugt i64 [[SubEnd1]], [[Start]] +; LV-NEXT: [[CmpPos1:%[^ ]*]] = icmp ult i64 [[AddEnd1]], [[Start]] +; LV-NEXT: [[Cmp:%[^ ]*]] = select i1 true, i1 [[CmpNeg1]], i1 [[CmpPos1]] +; LV-NEXT: [[PredCheck1:%[^ ]*]] = or i1 [[Cmp]], [[OFMulOverflow1]] + +; LV: [[FinalCheck:%[^ ]*]] = or i1 [[Or0]], [[PredCheck1]] +; LV: br i1 [[FinalCheck]], label %for.body.ph.lver.orig, label %for.body.ph +define void @f4(i16* noalias %a, + i16* noalias %b, i64 %N) { +entry: + %TruncN = trunc i64 %N to i32 + br label %for.body + +for.body: ; preds = %for.body, %entry + %ind = phi i64 [ 0, %entry ], [ %inc, %for.body ] + %ind1 = phi i32 [ %TruncN, %entry ], [ %dec, %for.body ] + + %mul = mul i32 %ind1, 2 + %mul_ext = sext i32 %mul to i64 + + %arrayidxA = getelementptr i16, i16* %a, i64 %mul_ext + %loadA = load i16, i16* %arrayidxA, align 2 + + %arrayidxB = getelementptr i16, i16* %b, i64 %ind + %loadB = load i16, i16* %arrayidxB, align 2 + + %add = mul i16 %loadA, %loadB + + store i16 %add, i16* %arrayidxA, align 2 + + %inc = add nuw nsw i64 %ind, 1 + %dec = sub i32 %ind1, 1 + + %exitcond = icmp eq i64 %inc, %N + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} + +; The following function is similar to the one above, but has the GEP +; to pointer %A inbounds. The index %mul doesn't have the nsw flag. +; This means that the SCEV expression for %mul can wrap and we need +; a SCEV predicate to continue analysis. +; +; We can still analyze this by adding the required no wrap SCEV predicates. + +; LAA-LABEL: f5 +; LAA: Memory dependences are safe{{$}} +; LAA: SCEV assumptions: +; LAA-NEXT: {(2 * (trunc i64 %N to i32)),+,-2}<%for.body> Added Flags: <nssw> +; LAA-NEXT: {((2 * (sext i32 (2 * (trunc i64 %N to i32)) to i64)) + %a),+,-4}<%for.body> Added Flags: <nusw> + +; LAA: [PSE] %arrayidxA = getelementptr inbounds i16, i16* %a, i32 %mul: +; LAA-NEXT: ((2 * (sext i32 {(2 * (trunc i64 %N to i32)),+,-2}<%for.body> to i64))<nsw> + %a)<nsw> +; LAA-NEXT: --> {((2 * (sext i32 (2 * (trunc i64 %N to i32)) to i64)) + %a),+,-4}<%for.body> + +; LV-LABEL: f5 +; LV-LABEL: for.body.lver.check +; LV: [[OFMul:%[^ ]*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 2, i32 [[BETrunc:%[^ ]*]]) +; LV-NEXT: [[OFMulResult:%[^ ]*]] = extractvalue { i32, i1 } [[OFMul]], 0 +; LV-NEXT: [[OFMulOverflow:%[^ ]*]] = extractvalue { i32, i1 } [[OFMul]], 1 +; LV-NEXT: [[AddEnd:%[^ ]*]] = add i32 [[Start:%[^ ]*]], [[OFMulResult]] +; LV-NEXT: [[SubEnd:%[^ ]*]] = sub i32 [[Start]], [[OFMulResult]] +; LV-NEXT: [[CmpNeg:%[^ ]*]] = icmp sgt i32 [[SubEnd]], [[Start]] +; LV-NEXT: [[CmpPos:%[^ ]*]] = icmp slt i32 [[AddEnd]], [[Start]] +; LV-NEXT: [[Cmp:%[^ ]*]] = select i1 true, i1 [[CmpNeg]], i1 [[CmpPos]] +; LV-NEXT: [[BECheck:%[^ ]*]] = icmp ugt i64 [[BE]], 4294967295 +; LV-NEXT: [[CheckOr0:%[^ ]*]] = or i1 [[Cmp]], [[BECheck]] +; LV-NEXT: [[PredCheck0:%[^ ]*]] = or i1 [[CheckOr0]], [[OFMulOverflow]] + +; LV-NEXT: [[Or0:%[^ ]*]] = or i1 false, [[PredCheck0]] + +; LV: [[OFMul1:%[^ ]*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 4, i64 [[BE:%[^ ]*]]) +; LV-NEXT: [[OFMulResult1:%[^ ]*]] = extractvalue { i64, i1 } [[OFMul1]], 0 +; LV-NEXT: [[OFMulOverflow1:%[^ ]*]] = extractvalue { i64, i1 } [[OFMul1]], 1 +; LV-NEXT: [[AddEnd1:%[^ ]*]] = add i64 [[Start:%[^ ]*]], [[OFMulResult1]] +; LV-NEXT: [[SubEnd1:%[^ ]*]] = sub i64 [[Start]], [[OFMulResult1]] +; LV-NEXT: [[CmpNeg1:%[^ ]*]] = icmp ugt i64 [[SubEnd1]], [[Start]] +; LV-NEXT: [[CmpPos1:%[^ ]*]] = icmp ult i64 [[AddEnd1]], [[Start]] +; LV-NEXT: [[Cmp:%[^ ]*]] = select i1 true, i1 [[CmpNeg1]], i1 [[CmpPos1]] +; LV-NEXT: [[PredCheck1:%[^ ]*]] = or i1 [[Cmp]], [[OFMulOverflow1]] + +; LV: [[FinalCheck:%[^ ]*]] = or i1 [[Or0]], [[PredCheck1]] +; LV: br i1 [[FinalCheck]], label %for.body.ph.lver.orig, label %for.body.ph +define void @f5(i16* noalias %a, + i16* noalias %b, i64 %N) { +entry: + %TruncN = trunc i64 %N to i32 + br label %for.body + +for.body: ; preds = %for.body, %entry + %ind = phi i64 [ 0, %entry ], [ %inc, %for.body ] + %ind1 = phi i32 [ %TruncN, %entry ], [ %dec, %for.body ] + + %mul = mul i32 %ind1, 2 + + %arrayidxA = getelementptr inbounds i16, i16* %a, i32 %mul + %loadA = load i16, i16* %arrayidxA, align 2 + + %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind + %loadB = load i16, i16* %arrayidxB, align 2 + + %add = mul i16 %loadA, %loadB + + store i16 %add, i16* %arrayidxA, align 2 + + %inc = add nuw nsw i64 %ind, 1 + %dec = sub i32 %ind1, 1 + + %exitcond = icmp eq i64 %inc, %N + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} diff --git a/test/Analysis/PostDominators/pr1098.ll b/test/Analysis/PostDominators/pr1098.ll index 2eed21371276e..1dae0c566f055 100644 --- a/test/Analysis/PostDominators/pr1098.ll +++ b/test/Analysis/PostDominators/pr1098.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -postdomtree -analyze | FileCheck %s +; RUN: opt < %s -passes='print<postdomtree>' 2>&1 | FileCheck %s ; PR932 define void @foo(i1 %x) { diff --git a/test/Analysis/ProfileSummary/basic.ll b/test/Analysis/ProfileSummary/basic.ll new file mode 100644 index 0000000000000..e417e459f04ca --- /dev/null +++ b/test/Analysis/ProfileSummary/basic.ll @@ -0,0 +1,39 @@ +; RUN: opt < %s -disable-output -passes=print-profile-summary -S 2>&1 | FileCheck %s + +define void @f1() !prof !20 { +; CHECK-LABEL: f1 :hot + + ret void +} + +define void @f2() !prof !21 { +; CHECK-LABEL: f2 :cold + + ret void +} + +define void @f3() !prof !22 { +; CHECK-LABEL: f3 + + ret void +} + +!llvm.module.flags = !{!1} +!20 = !{!"function_entry_count", i64 400} +!21 = !{!"function_entry_count", i64 1} +!22 = !{!"function_entry_count", i64 100} + +!1 = !{i32 1, !"ProfileSummary", !2} +!2 = !{!3, !4, !5, !6, !7, !8, !9, !10} +!3 = !{!"ProfileFormat", !"InstrProf"} +!4 = !{!"TotalCount", i64 10000} +!5 = !{!"MaxCount", i64 10} +!6 = !{!"MaxInternalCount", i64 1} +!7 = !{!"MaxFunctionCount", i64 1000} +!8 = !{!"NumCounts", i64 3} +!9 = !{!"NumFunctions", i64 3} +!10 = !{!"DetailedSummary", !11} +!11 = !{!12, !13, !14} +!12 = !{i32 10000, i64 100, i32 1} +!13 = !{i32 999000, i64 100, i32 1} +!14 = !{i32 999999, i64 1, i32 2} diff --git a/test/Analysis/RegionInfo/20100809_bb_not_in_domtree.ll b/test/Analysis/RegionInfo/20100809_bb_not_in_domtree.ll index 0dfa0bf9cd8d7..84e72783dcde4 100644 --- a/test/Analysis/RegionInfo/20100809_bb_not_in_domtree.ll +++ b/test/Analysis/RegionInfo/20100809_bb_not_in_domtree.ll @@ -1,4 +1,6 @@ ; RUN: opt -regions < %s +; RUN: opt < %s -passes='print<regions>' + define i32 @main() nounwind { entry: br label %for.cond diff --git a/test/Analysis/RegionInfo/block_sort.ll b/test/Analysis/RegionInfo/block_sort.ll index d7ef79cf6b557..ce1a48132901e 100644 --- a/test/Analysis/RegionInfo/block_sort.ll +++ b/test/Analysis/RegionInfo/block_sort.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define void @BZ2_blockSort() nounwind { start: br label %while diff --git a/test/Analysis/RegionInfo/cond_loop.ll b/test/Analysis/RegionInfo/cond_loop.ll index 0da4e5dca3d39..333cdffacd107 100644 --- a/test/Analysis/RegionInfo/cond_loop.ll +++ b/test/Analysis/RegionInfo/cond_loop.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define void @normal_condition() nounwind { 5: br label %"0" diff --git a/test/Analysis/RegionInfo/condition_complicated.ll b/test/Analysis/RegionInfo/condition_complicated.ll index 53f13c10eaf39..ba107bfd5dee5 100644 --- a/test/Analysis/RegionInfo/condition_complicated.ll +++ b/test/Analysis/RegionInfo/condition_complicated.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define internal fastcc zeroext i8 @handle_compress() nounwind { end165: br i1 1, label %false239, label %true181 diff --git a/test/Analysis/RegionInfo/condition_complicated_2.ll b/test/Analysis/RegionInfo/condition_complicated_2.ll index fd04afc20dcad..90717712489a6 100644 --- a/test/Analysis/RegionInfo/condition_complicated_2.ll +++ b/test/Analysis/RegionInfo/condition_complicated_2.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define internal fastcc void @compress() nounwind { end33: br i1 1, label %end124, label %lor.lhs.false95 diff --git a/test/Analysis/RegionInfo/condition_forward_edge.ll b/test/Analysis/RegionInfo/condition_forward_edge.ll index 88c45c2e6efd3..9c1ac752bc6ba 100644 --- a/test/Analysis/RegionInfo/condition_forward_edge.ll +++ b/test/Analysis/RegionInfo/condition_forward_edge.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define void @normal_condition() nounwind { 0: br label %"1" diff --git a/test/Analysis/RegionInfo/condition_same_exit.ll b/test/Analysis/RegionInfo/condition_same_exit.ll index bfb0df84b44de..570c772ea741c 100644 --- a/test/Analysis/RegionInfo/condition_same_exit.ll +++ b/test/Analysis/RegionInfo/condition_same_exit.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define void @normal_condition() nounwind { 0: br i1 1, label %"1", label %"4" diff --git a/test/Analysis/RegionInfo/condition_simple.ll b/test/Analysis/RegionInfo/condition_simple.ll index 3f93a6ecd3589..46c1b940a517d 100644 --- a/test/Analysis/RegionInfo/condition_simple.ll +++ b/test/Analysis/RegionInfo/condition_simple.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define void @normal_condition() nounwind { 0: br label %"1" diff --git a/test/Analysis/RegionInfo/exit_in_condition.ll b/test/Analysis/RegionInfo/exit_in_condition.ll index ac409ec1bb25c..4eb3be4b6be08 100644 --- a/test/Analysis/RegionInfo/exit_in_condition.ll +++ b/test/Analysis/RegionInfo/exit_in_condition.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define internal fastcc zeroext i8 @handle_compress() nounwind { entry: br label %outer diff --git a/test/Analysis/RegionInfo/loop_with_condition.ll b/test/Analysis/RegionInfo/loop_with_condition.ll index 4c1c8654ca4ff..4122b20029499 100644 --- a/test/Analysis/RegionInfo/loop_with_condition.ll +++ b/test/Analysis/RegionInfo/loop_with_condition.ll @@ -5,6 +5,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define void @normal_condition() nounwind { 0: br label %"1" diff --git a/test/Analysis/RegionInfo/loops_1.ll b/test/Analysis/RegionInfo/loops_1.ll index 9efe619ad9d7f..aedb4842f99c3 100644 --- a/test/Analysis/RegionInfo/loops_1.ll +++ b/test/Analysis/RegionInfo/loops_1.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define internal fastcc zeroext i8 @loops_1() nounwind { entry: br i1 1, label %outer , label %a diff --git a/test/Analysis/RegionInfo/loops_2.ll b/test/Analysis/RegionInfo/loops_2.ll index ca7eca75affd2..3ac83b01d43e1 100644 --- a/test/Analysis/RegionInfo/loops_2.ll +++ b/test/Analysis/RegionInfo/loops_2.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define void @meread_() nounwind { entry: br label %bb23 diff --git a/test/Analysis/RegionInfo/mix_1.ll b/test/Analysis/RegionInfo/mix_1.ll index 55001c7f435c2..3ae22af9e3d0a 100644 --- a/test/Analysis/RegionInfo/mix_1.ll +++ b/test/Analysis/RegionInfo/mix_1.ll @@ -5,6 +5,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define void @a_linear_impl_fig_1() nounwind { 0: diff --git a/test/Analysis/RegionInfo/nested_loops.ll b/test/Analysis/RegionInfo/nested_loops.ll index 3e73b3a328f63..6db32376fd7ef 100644 --- a/test/Analysis/RegionInfo/nested_loops.ll +++ b/test/Analysis/RegionInfo/nested_loops.ll @@ -5,6 +5,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define internal fastcc zeroext i8 @handle_compress() nounwind { entry: br label %outer diff --git a/test/Analysis/RegionInfo/next.ll b/test/Analysis/RegionInfo/next.ll index b22bbcc2b6d5c..617273f759739 100644 --- a/test/Analysis/RegionInfo/next.ll +++ b/test/Analysis/RegionInfo/next.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define void @MAIN__() nounwind { entry: br label %__label_002001.outer diff --git a/test/Analysis/RegionInfo/paper.ll b/test/Analysis/RegionInfo/paper.ll index 0398d2baa2256..3e592f4f9e931 100644 --- a/test/Analysis/RegionInfo/paper.ll +++ b/test/Analysis/RegionInfo/paper.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define void @a_linear_impl_fig_1() nounwind { 0: br label %"1" diff --git a/test/Analysis/RegionInfo/two_loops_same_header.ll b/test/Analysis/RegionInfo/two_loops_same_header.ll index 25713420a3b7a..2d5fa080c3b6b 100644 --- a/test/Analysis/RegionInfo/two_loops_same_header.ll +++ b/test/Analysis/RegionInfo/two_loops_same_header.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s + define internal fastcc zeroext i8 @handle_compress() nounwind { entry: br label %outer diff --git a/test/Analysis/RegionInfo/unreachable_bb.ll b/test/Analysis/RegionInfo/unreachable_bb.ll index 626ccbe304c30..5dd1be958e71a 100644 --- a/test/Analysis/RegionInfo/unreachable_bb.ll +++ b/test/Analysis/RegionInfo/unreachable_bb.ll @@ -1,4 +1,5 @@ ; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s ; We should not crash if there are some bbs that are not reachable. define void @f() { diff --git a/test/Analysis/ScalarEvolution/exhaustive-trip-counts.ll b/test/Analysis/ScalarEvolution/exhaustive-trip-counts.ll new file mode 100644 index 0000000000000..16d9cc5443872 --- /dev/null +++ b/test/Analysis/ScalarEvolution/exhaustive-trip-counts.ll @@ -0,0 +1,26 @@ +; 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 @f_0() { +; CHECK-LABEL: Printing analysis 'Scalar Evolution Analysis' for function 'f_0': +; CHECK: Loop %for.body: backedge-taken count is 5 +; CHECK: Loop %for.body: max backedge-taken count is 5 +; CHECK: Loop %for.body: Predicated backedge-taken count is 5 + +entry: + br label %for.body + +for.body: + %i.05 = phi i32 [ 32, %entry ], [ %div4, %for.body ] + tail call void @dummy() + %div4 = lshr i32 %i.05, 1 + %cmp = icmp eq i32 %div4, 0 + br i1 %cmp, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: + ret void +} + +declare void @dummy() diff --git a/test/Analysis/ScalarEvolution/expander-replace-congruent-ivs.ll b/test/Analysis/ScalarEvolution/expander-replace-congruent-ivs.ll new file mode 100644 index 0000000000000..0adb92d671b16 --- /dev/null +++ b/test/Analysis/ScalarEvolution/expander-replace-congruent-ivs.ll @@ -0,0 +1,111 @@ +; RUN: opt -S -indvars < %s | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.11.0" + +; SCEVExpander would try to RAUW %val_2 with %c.lcssa, breaking "def +; dominates uses". + +define void @pr27232(i32 %val) { +; CHECK-LABEL: @pr27232( +entry: + br i1 undef, label %loop_0.cond, label %for.body.us + +for.body.us: + br label %loop_0.cond + +loop_0.cond: + %val_2 = phi i32 [ %val, %for.body.us ], [ undef, %entry ] + br i1 true, label %loop_0.ph, label %loop_1.ph + +loop_0.ph: + br label %loop_0 + +loop_1.exit: + br label %loop_1.ph + +loop_1.ph: + %c.lcssa = phi i32 [ 0, %loop_0.cond ], [ %val_2, %loop_1.exit ] + br label %loop_1 + +loop_0: + br i1 undef, label %loop_0, label %loop_1.exit + +loop_1: + %d.1 = phi i32 [ %c.lcssa, %loop_1 ], [ %val_2, %loop_1.ph ] + %t.1 = phi i32 [ %val_2, %loop_1 ], [ %c.lcssa, %loop_1.ph ] + br i1 undef, label %leave, label %loop_1 + +leave: + ret void +} + + +; @ReplaceArg_0 and @ReplaceArg_1 used to trigger a failed cast<> +; assertion in SCEVExpander. + +define void @ReplaceArg_0(i32 %val) { +; CHECK-LABEL: @ReplaceArg_0( +entry: + br i1 undef, label %loop_0.cond, label %for.body.us + +for.body.us: + br label %loop_0.cond + +loop_0.cond: + br i1 true, label %loop_0.ph, label %loop_1.ph + +loop_0.ph: + br label %loop_0 + +loop_1.exit: + br label %loop_1.ph + +loop_1.ph: + %c.lcssa = phi i32 [ 0, %loop_0.cond ], [ %val, %loop_1.exit ] + br label %loop_1 + +loop_0: + br i1 undef, label %loop_0, label %loop_1.exit + +loop_1: + %d.1 = phi i32 [ %c.lcssa, %loop_1 ], [ %val, %loop_1.ph ] + %t.1 = phi i32 [ %val, %loop_1 ], [ %c.lcssa, %loop_1.ph ] + br i1 undef, label %leave, label %loop_1 + +leave: + ret void +} + +define void @ReplaceArg_1(i32 %val) { +; CHECK-LABEL: @ReplaceArg_1( +entry: + br i1 undef, label %loop_0.cond, label %for.body.us + +for.body.us: + br label %loop_0.cond + +loop_0.cond: + br i1 true, label %loop_0.ph, label %loop_1.ph + +loop_0.ph: + br label %loop_0 + +loop_1.exit: + br label %loop_1.ph + +loop_1.ph: + %c.lcssa = phi i32 [ 0, %loop_0.cond ], [ %val, %loop_1.exit ] + br label %loop_1 + +loop_0: + br i1 undef, label %loop_0, label %loop_1.exit + +loop_1: + %t.1 = phi i32 [ %val, %loop_1 ], [ %c.lcssa, %loop_1.ph ] + %d.1 = phi i32 [ %c.lcssa, %loop_1 ], [ %val, %loop_1.ph ] + br i1 undef, label %leave, label %loop_1 + +leave: + ret void +} diff --git a/test/Analysis/ScalarEvolution/flags-from-poison-dbg.ll b/test/Analysis/ScalarEvolution/flags-from-poison-dbg.ll new file mode 100644 index 0000000000000..30b83578137af --- /dev/null +++ b/test/Analysis/ScalarEvolution/flags-from-poison-dbg.ll @@ -0,0 +1,75 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +; Make sure poison value tracking works in the presence of @llvm.dbg +; intrinsics. Unfortunately, I was not able to reduce this file +; further while still keeping the debug info well formed. + +define void @foo(i32 %n, i32* %arr) !dbg !7 { +; CHECK-LABEL: Classifying expressions for: @foo +entry: + %cmp1 = icmp slt i32 0, %n, !dbg !12 + br i1 %cmp1, label %for.body.lr.ph, label %for.end, !dbg !15 + +for.body.lr.ph: ; preds = %entry + br label %for.body, !dbg !15 + +for.body: ; preds = %for.inc, %for.body.lr.ph + %i.02 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ] + %add = add nsw i32 %i.02, 50, !dbg !16 + call void @llvm.dbg.value(metadata i32 %add, i64 0, metadata !18, metadata !19), !dbg !20 + %idxprom = sext i32 %add to i64, !dbg !21 + +; CHECK: %idxprom = sext i32 %add to i64 +; CHECK-NEXT: --> {50,+,1}<nuw><nsw><%for.body> + + %arrayidx = getelementptr inbounds i32, i32* %arr, i64 %idxprom, !dbg !21 + store i32 100, i32* %arrayidx, align 4, !dbg !22 + br label %for.inc, !dbg !23 + +for.inc: ; preds = %for.body + %inc = add nsw i32 %i.02, 1, !dbg !24 + %cmp = icmp slt i32 %inc, %n, !dbg !12 + br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge, !dbg !15, !llvm.loop !25 + +for.cond.for.end_crit_edge: ; preds = %for.inc + br label %for.end, !dbg !15 + +for.end: ; preds = %for.cond.for.end_crit_edge, %entry + ret void, !dbg !27 +} + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (llvm/trunk 271857)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "x.c", directory: "/Users/sanjoy/Code/clang/build/debug+asserts-x86") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 2} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"PIC Level", i32 2} +!6 = !{!"clang version 3.9.0 (llvm/trunk 271857)"} +!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{null, !10, !11} +!10 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64, align: 64) +!12 = !DILocation(line: 2, column: 24, scope: !13) +!13 = distinct !DILexicalBlock(scope: !14, file: !1, line: 2, column: 6) +!14 = distinct !DILexicalBlock(scope: !7, file: !1, line: 2, column: 6) +!15 = !DILocation(line: 2, column: 6, scope: !14) +!16 = !DILocation(line: 3, column: 14, scope: !17) +!17 = distinct !DILexicalBlock(scope: !13, file: !1, line: 2, column: 34) +!18 = !DILocalVariable(name: "k", scope: !17, file: !1, line: 3, type: !10) +!19 = !DIExpression() +!20 = !DILocation(line: 3, column: 8, scope: !17) +!21 = !DILocation(line: 4, column: 4, scope: !17) +!22 = !DILocation(line: 4, column: 11, scope: !17) +!23 = !DILocation(line: 5, column: 6, scope: !17) +!24 = !DILocation(line: 2, column: 30, scope: !13) +!25 = distinct !{!25, !26} +!26 = !DILocation(line: 2, column: 6, scope: !7) +!27 = !DILocation(line: 6, column: 1, scope: !7) diff --git a/test/Analysis/ScalarEvolution/flags-from-poison.ll b/test/Analysis/ScalarEvolution/flags-from-poison.ll index b1fe7f1138b6c..2fcb4c038f205 100644 --- a/test/Analysis/ScalarEvolution/flags-from-poison.ll +++ b/test/Analysis/ScalarEvolution/flags-from-poison.ll @@ -57,6 +57,30 @@ exit: ret void } +define void @test-add-nuw-from-icmp(float* %input, i32 %offset, + i32 %numIterations) { +; CHECK-LABEL: @test-add-nuw-from-icmp +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] + +; CHECK: %index32 = +; CHECK: --> {%offset,+,1}<nuw> + %index32 = add nuw i32 %i, %offset + %cmp = icmp sgt i32 %index32, 0 + %cmp.idx = sext i1 %cmp to i32 + + %ptr = getelementptr inbounds float, float* %input, i32 %cmp.idx + %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 @@ -113,11 +137,65 @@ loop: %i = phi i32 [ %nexti, %loop2 ], [ 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 + 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 +} + +; Similar to test-add-not-header, but in this case the load +; instruction may not be executed. +define void @test-add-not-header3(float* %input, i32 %offset, i32 %numIterations, + i1* %cond_buf) { +; CHECK-LABEL: @test-add-not-header3 +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 + %cond = load volatile i1, i1* %cond_buf + br i1 %cond, label %loop2, label %exit +loop2: + %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-header2, except we have a few extra +; blocks. +define void @test-add-not-header4(float* %input, i32 %offset, i32 %numIterations) { +; CHECK-LABEL: @test-add-not-header4 +entry: + br label %loop +loop: + %i = phi i32 [ %nexti, %loop2 ], [ 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 + br label %loop3 +loop3: + br label %loop4 +loop4: br label %loop2 loop2: %f = load float, float* %ptr, align 4 @@ -127,6 +205,26 @@ exit: ret void } +; Demonstrate why we need a Visited set in llvm::isKnownNotFullPoison. +define void @test-add-not-header5(float* %input, i32 %offset) { +; CHECK-LABEL: @test-add-not-header5 +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 + br 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. @@ -346,7 +444,7 @@ loop: %j = add nsw i32 %i, 1 ; CHECK: %index32 = -; CHECK: --> {(1 + %offset),+,1}<nsw> +; CHECK: --> {(1 + %offset)<nsw>,+,1}<nsw> %index32 = add nsw i32 %j, %offset %ptr = getelementptr inbounds float, float* %input, i32 %index32 @@ -488,7 +586,7 @@ loop: %i = phi i32 [ %nexti, %loop ], [ %start, %entry ] ; CHECK: %index32 = -; CHECK: --> {((-1 * %halfsub)<nsw> + %start),+,1}<nsw> +; CHECK: --> {((-1 * %halfsub)<nsw> + %start)<nsw>,+,1}<nsw> %index32 = sub nsw i32 %i, %halfsub %index64 = sext i32 %index32 to i64 @@ -547,7 +645,7 @@ loop: %j = add nsw i32 %i, 1 ; CHECK: %index32 = -; CHECK: --> {(1 + (-1 * %offset)),+,1}<nsw> +; CHECK: --> {(1 + (-1 * %offset))<nsw>,+,1}<nsw> %index32 = sub nsw i32 %j, %offset %ptr = getelementptr inbounds float, float* %input, i32 %index32 diff --git a/test/Analysis/ScalarEvolution/guards.ll b/test/Analysis/ScalarEvolution/guards.ll new file mode 100644 index 0000000000000..52ad4dc73d417 --- /dev/null +++ b/test/Analysis/ScalarEvolution/guards.ll @@ -0,0 +1,141 @@ +; RUN: opt -S -indvars < %s | FileCheck %s + +; Check that SCEV is able to recognize and use guards to prove +; conditions gaurding loop entries and backedges. This isn't intended +; to be a comprehensive test of SCEV's simplification capabilities, +; tests directly testing e.g. if SCEV can elide a sext should go +; elsewhere. + +target datalayout = "n8:16:32:64" + +declare void @llvm.experimental.guard(i1, ...) + +define void @test_1(i1* %cond_buf, i32* %len_buf) { +; CHECK-LABEL: @test_1( +entry: + %len = load i32, i32* %len_buf, !range !{i32 1, i32 2147483648} + br label %loop + +loop: +; CHECK: loop: +; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] +; CHECK: %iv.inc.cmp = icmp slt i32 %iv.inc, %len +; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] +; CHECK: leave: + + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] + %iv.inc = add i32 %iv, 1 + + %iv.cmp = icmp slt i32 %iv, %len + call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ] + + %iv.inc.cmp = icmp slt i32 %iv.inc, %len + call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] + + %becond = load volatile i1, i1* %cond_buf + br i1 %becond, label %loop, label %leave + +leave: + ret void +} + +define void @test_2(i32 %n, i32* %len_buf) { +; CHECK-LABEL: @test_2( +; CHECK: [[LEN_SEXT:%[^ ]+]] = sext i32 %len to i64 +; CHECK: br label %loop + +entry: + %len = load i32, i32* %len_buf, !range !{i32 0, i32 2147483648} + br label %loop + +loop: +; CHECK: loop: +; CHECK: %indvars.iv = phi i64 [ %indvars.iv.next, %loop ], [ 0, %entry ] +; CHECK: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 +; CHECK: %iv.inc.cmp = icmp slt i64 %indvars.iv.next, [[LEN_SEXT]] +; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] +; CHECK: leave: + + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] + %iv.inc = add i32 %iv, 1 + + %iv.sext = sext i32 %iv to i64 + + %iv.inc.cmp = icmp slt i32 %iv.inc, %len + call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] + + %becond = icmp ne i32 %iv, %n + br i1 %becond, label %loop, label %leave + +leave: + ret void +} + +define void @test_3(i1* %cond_buf, i32* %len_buf) { +; CHECK-LABEL: @test_3( + +entry: + %len = load i32, i32* %len_buf + %entry.cond = icmp sgt i32 %len, 0 + call void(i1, ...) @llvm.experimental.guard(i1 %entry.cond) [ "deopt"() ] + br label %loop + +loop: +; CHECK: loop: +; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] +; CHECK: %iv.inc.cmp = icmp slt i32 %iv.inc, %len +; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] +; CHECK: leave: + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] + %iv.inc = add i32 %iv, 1 + + %iv.cmp = icmp slt i32 %iv, %len + call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ] + + %iv.inc.cmp = icmp slt i32 %iv.inc, %len + call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] + + %becond = load volatile i1, i1* %cond_buf + br i1 %becond, label %loop, label %leave + +leave: + ret void +} + +define void @test_4(i1* %cond_buf, i32* %len_buf) { +; CHECK-LABEL: @test_4( + +entry: + %len = load i32, i32* %len_buf + %entry.cond = icmp sgt i32 %len, 0 + call void(i1, ...) @llvm.experimental.guard(i1 %entry.cond) [ "deopt"() ] + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ] + %iv.inc = add i32 %iv, 1 + + %cond = load volatile i1, i1* %cond_buf + br i1 %cond, label %left, label %be + +left: + ; Does not dominate the backedge, so cannot be used in the inductive proof + %iv.inc.cmp = icmp slt i32 %iv.inc, %len + call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] + br label %be + +be: +; CHECK: be: +; CHECK-NEXT: %iv.cmp = icmp slt i32 %iv, %len +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ] +; CHECK: leave: + + %iv.cmp = icmp slt i32 %iv, %len + call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ] + + %becond = load volatile i1, i1* %cond_buf + br i1 %becond, label %loop, label %leave + +leave: + ret void +} diff --git a/test/Analysis/ScalarEvolution/incorrect-offset-scaling.ll b/test/Analysis/ScalarEvolution/incorrect-offset-scaling.ll new file mode 100644 index 0000000000000..7ffb0936d105a --- /dev/null +++ b/test/Analysis/ScalarEvolution/incorrect-offset-scaling.ll @@ -0,0 +1,48 @@ +; RUN: opt -S -loop-reduce < %s | FileCheck %s + +target triple = "x86_64-unknown-unknown" +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + +define void @incorrect_offset_scaling(i64, i64*) { +top: + br label %L + +L: ; preds = %idxend.10, %idxend, %L2, %top + br i1 undef, label %L, label %L1 + +L1: ; preds = %L1.preheader, %L2 + %r13 = phi i64 [ %r1, %L2 ], [ 1, %L ] +; CHECK: %lsr.iv = phi i64 [ 0, %L{{[^ ]+}} ], [ %lsr.iv.next, %L2 ] +; CHECK-NOT: %lsr.iv = phi i64 [ -1, %L{{[^ ]+}} ], [ %lsr.iv.next, %L2 ] +; CHECK: br + %r0 = add i64 %r13, -1 + br label %idxend.8 + +L2: ; preds = %idxend.8 + %r1 = add i64 %r13, 1 + br i1 undef, label %L, label %L1 + +if6: ; preds = %idxend.8 + %r2 = add i64 %0, -1 + %r3 = load i64, i64* %1, align 8 +; CHECK-NOT: %r2 +; CHECK: %r3 = load i64 + br label %ib + +idxend.8: ; preds = %L1 + br i1 undef, label %if6, label %L2 + +ib: ; preds = %if6 + %r4 = mul i64 %r3, %r0 + %r5 = add i64 %r2, %r4 + %r6 = icmp ult i64 %r5, undef +; CHECK %2 = mul i64 %lsr.iv, %r3 +; CHECK %3 = add i64 %1, -1 +; CHECK %4 = add i64 %0, %r3 +; CHECK %r6 + %r7 = getelementptr i64, i64* undef, i64 %r5 + store i64 1, i64* %r7, align 8 +; CHECK %5 = mul i64 %lsr.iv, %r3 +; CHECK %6 = add i64 %5, -1 + br label %L +} diff --git a/test/Analysis/ScalarEvolution/increasing-or-decreasing-iv.ll b/test/Analysis/ScalarEvolution/increasing-or-decreasing-iv.ll new file mode 100644 index 0000000000000..ae5e360932652 --- /dev/null +++ b/test/Analysis/ScalarEvolution/increasing-or-decreasing-iv.ll @@ -0,0 +1,247 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +define void @f0(i1 %c) { +; CHECK-LABEL: Classifying expressions for: @f0 +entry: + %start = select i1 %c, i32 127, i32 0 + %step = select i1 %c, i32 -1, i32 1 + br label %loop + +loop: + %loop.iv = phi i32 [ 0, %entry ], [ %loop.iv.inc, %loop ] + %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] +; CHECK: %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] +; CHECK-NEXT: --> {%start,+,%step}<%loop> U: [0,128) S: [0,128) + %iv.next = add i32 %iv, %step + %loop.iv.inc = add i32 %loop.iv, 1 + %be.cond = icmp ne i32 %loop.iv.inc, 128 + br i1 %be.cond, label %loop, label %leave + +leave: + ret void +} + +define void @f1(i1 %c) { +; CHECK-LABEL: Classifying expressions for: @f1 +entry: + %start = select i1 %c, i32 120, i32 0 + %step = select i1 %c, i32 -8, i32 8 + br label %loop + +loop: + %loop.iv = phi i32 [ 0, %entry ], [ %loop.iv.inc, %loop ] + %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] + +; CHECK: %iv.1 = add i32 %iv, 1 +; CHECK-NEXT: --> {(1 + %start)<nuw><nsw>,+,%step}<%loop> U: [1,122) S: [1,122) +; CHECK: %iv.2 = add i32 %iv, 2 +; CHECK-NEXT: --> {(2 + %start)<nuw><nsw>,+,%step}<%loop> U: [2,123) S: [2,123) +; CHECK: %iv.3 = add i32 %iv, 3 +; CHECK-NEXT: --> {(3 + %start)<nuw><nsw>,+,%step}<%loop> U: [3,124) S: [3,124) +; CHECK: %iv.4 = add i32 %iv, 4 +; CHECK-NEXT: --> {(4 + %start)<nuw><nsw>,+,%step}<%loop> U: [4,125) S: [4,125) +; CHECK: %iv.5 = add i32 %iv, 5 +; CHECK-NEXT: --> {(5 + %start)<nuw><nsw>,+,%step}<%loop> U: [5,126) S: [5,126) +; CHECK: %iv.6 = add i32 %iv, 6 +; CHECK-NEXT: --> {(6 + %start)<nuw><nsw>,+,%step}<%loop> U: [6,127) S: [6,127) +; CHECK: %iv.7 = add i32 %iv, 7 +; CHECK-NEXT: --> {(7 + %start)<nuw><nsw>,+,%step}<%loop> U: [7,128) S: [7,128) + + %iv.1 = add i32 %iv, 1 + %iv.2 = add i32 %iv, 2 + %iv.3 = add i32 %iv, 3 + %iv.4 = add i32 %iv, 4 + %iv.5 = add i32 %iv, 5 + %iv.6 = add i32 %iv, 6 + %iv.7 = add i32 %iv, 7 + +; CHECK: %iv.m1 = sub i32 %iv, 1 +; CHECK-NEXT: --> {(-1 + %start)<nsw>,+,%step}<%loop> U: [-1,120) S: [-1,120) +; CHECK: %iv.m2 = sub i32 %iv, 2 +; CHECK-NEXT: --> {(-2 + %start)<nsw>,+,%step}<%loop> U: [-2,119) S: [-2,119) +; CHECK: %iv.m3 = sub i32 %iv, 3 +; CHECK-NEXT: --> {(-3 + %start)<nsw>,+,%step}<%loop> U: [-3,118) S: [-3,118) +; CHECK: %iv.m4 = sub i32 %iv, 4 +; CHECK-NEXT: --> {(-4 + %start)<nsw>,+,%step}<%loop> U: [-4,117) S: [-4,117) +; CHECK: %iv.m5 = sub i32 %iv, 5 +; CHECK-NEXT: --> {(-5 + %start)<nsw>,+,%step}<%loop> U: [-5,116) S: [-5,116) +; CHECK: %iv.m6 = sub i32 %iv, 6 +; CHECK-NEXT: --> {(-6 + %start)<nsw>,+,%step}<%loop> U: [-6,115) S: [-6,115) +; CHECK: %iv.m7 = sub i32 %iv, 7 +; CHECK-NEXT: --> {(-7 + %start)<nsw>,+,%step}<%loop> U: [-7,114) S: [-7,114) + + %iv.m1 = sub i32 %iv, 1 + %iv.m2 = sub i32 %iv, 2 + %iv.m3 = sub i32 %iv, 3 + %iv.m4 = sub i32 %iv, 4 + %iv.m5 = sub i32 %iv, 5 + %iv.m6 = sub i32 %iv, 6 + %iv.m7 = sub i32 %iv, 7 + + %iv.next = add i32 %iv, %step + %loop.iv.inc = add i32 %loop.iv, 1 + %be.cond = icmp sgt i32 %loop.iv, 14 + br i1 %be.cond, label %leave, label %loop + +leave: + ret void +} + +define void @f2(i1 %c) { +; CHECK-LABEL: Classifying expressions for: @f2 +entry: + %start = select i1 %c, i32 127, i32 0 + %step = select i1 %c, i32 -1, i32 1 + br label %loop + +loop: + %loop.iv = phi i32 [ 0, %entry ], [ %loop.iv.inc, %loop ] + %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] + %iv.sext = sext i32 %iv to i64 + %iv.next = add i32 %iv, %step +; CHECK: %iv.sext = sext i32 %iv to i64 +; CHECK-NEXT: --> {(sext i32 %start to i64),+,(sext i32 %step to i64)}<nsw><%loop> U: [0,128) S: [0,128) + %loop.iv.inc = add i32 %loop.iv, 1 + %be.cond = icmp ne i32 %loop.iv.inc, 128 + br i1 %be.cond, label %loop, label %leave + +leave: + ret void +} + +define void @f3(i1 %c) { +; CHECK-LABEL: Classifying expressions for: @f3 +entry: + +; NB! the i16 type (as opposed to i32), the choice of the constant 509 +; and the trip count are all related and not arbitrary. We want an +; add recurrence that will look like it can unsign-overflow *unless* +; SCEV is able to see the correlation between the two selects feeding +; into the initial value and the step increment. + + %start = select i1 %c, i16 1000, i16 0 + %step = select i1 %c, i16 1, i16 509 + br label %loop + +loop: + %loop.iv = phi i16 [ 0, %entry ], [ %loop.iv.inc, %loop ] + %iv = phi i16 [ %start, %entry ], [ %iv.next, %loop ] + %iv.zext = zext i16 %iv to i64 +; CHECK: %iv.zext = zext i16 %iv to i64 +; CHECK-NEXT: --> {(zext i16 %start to i64),+,(zext i16 %step to i64)}<nuw><%loop> U: [0,64644) S: [0,64644) + %iv.next = add i16 %iv, %step + %loop.iv.inc = add i16 %loop.iv, 1 + %be.cond = icmp ne i16 %loop.iv.inc, 128 + br i1 %be.cond, label %loop, label %leave + +leave: + ret void +} + +define void @f4(i1 %c) { +; CHECK-LABEL: Classifying expressions for: @f4 + +; @f4() demonstrates a case where SCEV is not able to compute a +; precise range for %iv.trunc, though it should be able to, in theory. +; This is because SCEV looks into affine add recurrences only when the +; backedge taken count of the loop has the same bitwidth as the +; induction variable. +entry: + %start = select i1 %c, i32 127, i32 0 + %step = select i1 %c, i32 -1, i32 1 + br label %loop + +loop: + %loop.iv = phi i32 [ 0, %entry ], [ %loop.iv.inc, %loop ] + %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] + %iv.trunc = trunc i32 %iv to i16 +; CHECK: %iv.trunc = trunc i32 %iv to i16 +; CHECK-NEXT: --> {(trunc i32 %start to i16),+,(trunc i32 %step to i16)}<%loop> U: full-set S: full-set + %iv.next = add i32 %iv, %step + %loop.iv.inc = add i32 %loop.iv, 1 + %be.cond = icmp ne i32 %loop.iv.inc, 128 + br i1 %be.cond, label %loop, label %leave + +leave: + ret void +} + +define void @f5(i1 %c) { +; CHECK-LABEL: Classifying expressions for: @f5 +entry: + %start = select i1 %c, i32 127, i32 0 + %step = select i1 %c, i32 -1, i32 1 + br label %loop + +loop: + %loop.iv = phi i16 [ 0, %entry ], [ %loop.iv.inc, %loop ] + %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] + %iv.trunc = trunc i32 %iv to i16 +; CHECK: %iv.trunc = trunc i32 %iv to i16 +; CHECK-NEXT: --> {(trunc i32 %start to i16),+,(trunc i32 %step to i16)}<%loop> U: [0,128) S: [0,128) + %iv.next = add i32 %iv, %step + + %loop.iv.inc = add i16 %loop.iv, 1 + %be.cond = icmp ne i16 %loop.iv.inc, 128 + br i1 %be.cond, label %loop, label %leave + +leave: + ret void +} + +define void @f6(i1 %c) { +; CHECK-LABEL: Classifying expressions for: @f6 +entry: + %start = select i1 %c, i32 127, i32 0 + %step = select i1 %c, i32 -2, i32 0 + br label %loop + +loop: + %loop.iv = phi i16 [ 0, %entry ], [ %loop.iv.inc, %loop ] + %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] +; CHECK: %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] +; CHECK-NEXT: --> {%start,+,(1 + %step)<nuw><nsw>}<%loop> U: [0,128) S: [0,128) + + %step.plus.one = add i32 %step, 1 + %iv.next = add i32 %iv, %step.plus.one + %iv.sext = sext i32 %iv to i64 +; CHECK: %iv.sext = sext i32 %iv to i64 +; CHECK-NEXT: --> {(sext i32 %start to i64),+,(1 + (sext i32 %step to i64))<nsw>}<nsw><%loop> U: [0,128) S: [0,128) + %loop.iv.inc = add i16 %loop.iv, 1 + %be.cond = icmp ne i16 %loop.iv.inc, 128 + br i1 %be.cond, label %loop, label %leave + +leave: + ret void +} + +define void @f7(i1 %c) { +; CHECK-LABEL: Classifying expressions for: @f7 +entry: + %start = select i1 %c, i32 127, i32 0 + %step = select i1 %c, i32 -1, i32 1 + br label %loop + +loop: + %loop.iv = phi i16 [ 0, %entry ], [ %loop.iv.inc, %loop ] + %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] + %iv.trunc = trunc i32 %iv to i16 +; CHECK: %iv.trunc = trunc i32 %iv to i16 +; CHECK-NEXT: --> {(trunc i32 %start to i16),+,(trunc i32 %step to i16)}<%loop> U: [0,128) S: [0,128) + %iv.next = add i32 %iv, %step + + %iv.trunc.plus.one = add i16 %iv.trunc, 1 +; CHECK: %iv.trunc.plus.one = add i16 %iv.trunc, 1 +; CHECK-NEXT: --> {(1 + (trunc i32 %start to i16))<nuw><nsw>,+,(trunc i32 %step to i16)}<%loop> U: [1,129) S: [1,129) + + %iv.trunc.plus.two = add i16 %iv.trunc, 2 +; CHECK: %iv.trunc.plus.two = add i16 %iv.trunc, 2 +; CHECK-NEXT: --> {(2 + (trunc i32 %start to i16))<nuw><nsw>,+,(trunc i32 %step to i16)}<%loop> U: [2,130) S: [2,130) + + %loop.iv.inc = add i16 %loop.iv, 1 + %be.cond = icmp ne i16 %loop.iv.inc, 128 + br i1 %be.cond, label %loop, label %leave + +leave: + ret void +} diff --git a/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll b/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll index 5c372b5d7b8a1..f28e66716e1a5 100644 --- a/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll +++ b/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll @@ -1,6 +1,6 @@ ; ; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s -define void @infer.sext.0(i1* %c, i32 %start) { +define void @infer.sext.0(i1* %c, i32 %start, i32* %buf) { ; CHECK-LABEL: Classifying expressions for: @infer.sext.0 entry: br label %loop @@ -12,6 +12,10 @@ define void @infer.sext.0(i1* %c, i32 %start) { %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))<nsw>,+,1}<nsw><%loop> + + %buf.gep = getelementptr inbounds i32, i32* %buf, i32 %idx.inc + %val = load i32, i32* %buf.gep + %condition = icmp eq i32 %counter, 1 %counter.inc = add i32 %counter, 1 br i1 %condition, label %exit, label %loop @@ -20,7 +24,7 @@ define void @infer.sext.0(i1* %c, i32 %start) { ret void } -define void @infer.zext.0(i1* %c, i32 %start) { +define void @infer.zext.0(i1* %c, i32 %start, i32* %buf) { ; CHECK-LABEL: Classifying expressions for: @infer.zext.0 entry: br label %loop @@ -32,6 +36,10 @@ define void @infer.zext.0(i1* %c, i32 %start) { %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))<nuw><nsw>,+,1}<nuw><%loop> + + %buf.gep = getelementptr inbounds i32, i32* %buf, i32 %idx.inc + %val = load i32, i32* %buf.gep + %condition = icmp eq i32 %counter, 1 %counter.inc = add i32 %counter, 1 br i1 %condition, label %exit, label %loop diff --git a/test/Analysis/ScalarEvolution/no-wrap-unknown-becount.ll b/test/Analysis/ScalarEvolution/no-wrap-unknown-becount.ll new file mode 100644 index 0000000000000..1f972f3f6d932 --- /dev/null +++ b/test/Analysis/ScalarEvolution/no-wrap-unknown-becount.ll @@ -0,0 +1,124 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +declare void @llvm.experimental.guard(i1, ...) +declare void @llvm.assume(i1) + +define void @s_0(i32 %n, i1* %cond) { +; CHECK-LABEL: Classifying expressions for: @s_0 +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] + %iv.inc = add i32 %iv, 1 + %iv.sext = sext i32 %iv to i64 +; CHECK: %iv.sext = sext i32 %iv to i64 +; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> + %cmp = icmp slt i32 %iv, %n + call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ] + %c = load volatile i1, i1* %cond + br i1 %c, label %loop, label %leave + +leave: + ret void +} + +define void @s_1(i1* %cond) { +; CHECK-LABEL: Classifying expressions for: @s_1 +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] + %iv.inc = add i32 %iv, 3 + %iv.sext = sext i32 %iv to i64 +; CHECK: %iv.sext = sext i32 %iv to i64 +; CHECK-NEXT: --> {0,+,3}<nuw><nsw><%loop> + %cmp = icmp slt i32 %iv, 10000 + call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ] + %c = load volatile i1, i1* %cond + br i1 %c, label %loop, label %leave + +leave: + ret void +} + +define void @s_2(i1* %cond) { +; CHECK-LABEL: Classifying expressions for: @s_2 +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] + %iv.inc = add i32 %iv, 3 + %iv.sext = sext i32 %iv to i64 + %cmp = icmp slt i32 %iv, 10000 +; CHECK: %iv.sext = sext i32 %iv to i64 +; CHECK-NEXT: --> {0,+,3}<nuw><nsw><%loop> + call void @llvm.assume(i1 %cmp) + %c = load volatile i1, i1* %cond + br i1 %c, label %loop, label %leave + +leave: + ret void +} + +define void @u_0(i32 %n, i1* %cond) { +; CHECK-LABEL: Classifying expressions for: @u_0 +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] + %iv.inc = add i32 %iv, 1 + %iv.zext = zext i32 %iv to i64 +; CHECK: %iv.zext = zext i32 %iv to i64 +; CHECK-NEXT: --> {0,+,1}<nuw><%loop> + %cmp = icmp ult i32 %iv, %n + call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ] + %c = load volatile i1, i1* %cond + br i1 %c, label %loop, label %leave + +leave: + ret void +} + +define void @u_1(i1* %cond) { +; CHECK-LABEL: Classifying expressions for: @u_1 +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] + %iv.inc = add i32 %iv, 3 + %iv.zext = zext i32 %iv to i64 +; CHECK: %iv.zext = zext i32 %iv to i64 +; CHECK-NEXT: --> {0,+,3}<nuw><%loop> + %cmp = icmp ult i32 %iv, 10000 + call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ] + %c = load volatile i1, i1* %cond + br i1 %c, label %loop, label %leave + +leave: + ret void +} + +define void @u_2(i1* %cond) { +; CHECK-LABEL: Classifying expressions for: @u_2 +entry: + br label %loop + +loop: + %iv = phi i32 [ 30000, %entry ], [ %iv.inc, %loop ] + %iv.inc = add i32 %iv, -2 + %iv.zext = zext i32 %iv to i64 + %cmp = icmp ugt i32 %iv.inc, -10000 +; CHECK: %iv.zext = zext i32 %iv to i64 +; CHECK-NEXT: --> {30000,+,-2}<nw><%loop> + call void @llvm.assume(i1 %cmp) + %c = load volatile i1, i1* %cond + br i1 %c, label %loop, label %leave + +leave: + ret void +} diff --git a/test/Analysis/ScalarEvolution/nowrap-preinc-limits.ll b/test/Analysis/ScalarEvolution/nowrap-preinc-limits.ll index 1a5409d01f641..fa5ab82e064c6 100644 --- a/test/Analysis/ScalarEvolution/nowrap-preinc-limits.ll +++ b/test/Analysis/ScalarEvolution/nowrap-preinc-limits.ll @@ -36,7 +36,8 @@ define void @g(i1* %condition) { ; CHECK: %idx.inc2.sext = sext i32 %idx.inc2 to i64 ; CHECK-NEXT: --> {2,+,3}<nuw><nsw><%loop> - %c = load volatile i1, i1* %condition + %cond.gep = getelementptr inbounds i1, i1* %condition, i32 %idx.inc + %c = load volatile i1, i1* %cond.gep br i1 %c, label %loop, label %exit exit: diff --git a/test/Analysis/ScalarEvolution/nsw-offset-assume.ll b/test/Analysis/ScalarEvolution/nsw-offset-assume.ll index bef1070bbcb04..5413b477df589 100644 --- a/test/Analysis/ScalarEvolution/nsw-offset-assume.ll +++ b/test/Analysis/ScalarEvolution/nsw-offset-assume.ll @@ -39,7 +39,7 @@ bb: ; preds = %bb.nph, %bb1 %8 = sext i32 %7 to i64 ; <i64> [#uses=1] ; CHECK: %9 = getelementptr inbounds double, double* %q, i64 %8 -; CHECK: {(8 + %q),+,16}<nsw><%bb> +; CHECK: {(8 + %q)<nsw>,+,16}<nsw><%bb> %9 = getelementptr inbounds double, double* %q, i64 %8 ; <double*> [#uses=1] ; Artificially repeat the above three instructions, this time using @@ -51,7 +51,7 @@ bb: ; preds = %bb.nph, %bb1 %t8 = sext i32 %t7 to i64 ; <i64> [#uses=1] ; CHECK: %t9 = getelementptr inbounds double, double* %q, i64 %t8 -; CHECK: {(8 + %q),+,16}<nsw><%bb> +; CHECK: {(8 + %q)<nsw>,+,16}<nsw><%bb> %t9 = getelementptr inbounds double, double* %q, i64 %t8 ; <double*> [#uses=1] %10 = load double, double* %9, align 8 ; <double> [#uses=1] diff --git a/test/Analysis/ScalarEvolution/nsw-offset.ll b/test/Analysis/ScalarEvolution/nsw-offset.ll index 127bb19bff025..f8ed8f003ff1e 100644 --- a/test/Analysis/ScalarEvolution/nsw-offset.ll +++ b/test/Analysis/ScalarEvolution/nsw-offset.ll @@ -37,7 +37,7 @@ bb: ; preds = %bb.nph, %bb1 %8 = sext i32 %7 to i64 ; <i64> [#uses=1] ; CHECK: %9 = getelementptr inbounds double, double* %q, i64 %8 -; CHECK: {(8 + %q),+,16}<nsw><%bb> +; CHECK: {(8 + %q)<nsw>,+,16}<nsw><%bb> %9 = getelementptr inbounds double, double* %q, i64 %8 ; <double*> [#uses=1] ; Artificially repeat the above three instructions, this time using @@ -49,7 +49,7 @@ bb: ; preds = %bb.nph, %bb1 %t8 = sext i32 %t7 to i64 ; <i64> [#uses=1] ; CHECK: %t9 = getelementptr inbounds double, double* %q, i64 %t8 -; CHECK: {(8 + %q),+,16}<nsw><%bb> +; CHECK: {(8 + %q)<nsw>,+,16}<nsw><%bb> %t9 = getelementptr inbounds double, double* %q, i64 %t8 ; <double*> [#uses=1] %10 = load double, double* %9, align 8 ; <double> [#uses=1] diff --git a/test/Analysis/ScalarEvolution/nsw.ll b/test/Analysis/ScalarEvolution/nsw.ll index 15444e38b83cb..a3752919d334d 100644 --- a/test/Analysis/ScalarEvolution/nsw.ll +++ b/test/Analysis/ScalarEvolution/nsw.ll @@ -30,15 +30,17 @@ bb: ; preds = %bb1, %bb.nph %tmp8 = add nsw i32 %i.01, 1 ; <i32> [#uses=2] ; CHECK: %tmp8 ; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%bb> + %p.gep = getelementptr double, double* %p, i32 %tmp8 + %p.val = load double, double* %p.gep br label %bb1 bb1: ; preds = %bb %phitmp = sext i32 %tmp8 to i64 ; <i64> [#uses=1] ; CHECK: %phitmp ; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%bb> - %tmp9 = getelementptr double, double* %p, i64 %phitmp ; <double*> [#uses=1] + %tmp9 = getelementptr inbounds double, double* %p, i64 %phitmp ; <double*> [#uses=1] ; CHECK: %tmp9 -; CHECK-NEXT: --> {(8 + %p),+,8}<%bb> +; CHECK-NEXT: --> {(8 + %p)<nsw>,+,8}<nsw><%bb> %tmp10 = load double, double* %tmp9, align 8 ; <double> [#uses=1] %tmp11 = fcmp ogt double %tmp10, 2.000000e+00 ; <i1> [#uses=1] br i1 %tmp11, label %bb, label %bb1.return_crit_edge @@ -66,7 +68,7 @@ for.body.i.i: ; preds = %for.body.i.i, %for. store i32 0, i32* %__first.addr.02.i.i, align 4 %ptrincdec.i.i = getelementptr inbounds i32, i32* %__first.addr.02.i.i, i64 1 ; CHECK: %ptrincdec.i.i -; CHECK-NEXT: --> {(4 + %begin),+,4}<nuw><%for.body.i.i> +; CHECK-NEXT: --> {(4 + %begin)<nsw>,+,4}<nuw><%for.body.i.i> %cmp.i.i = icmp eq i32* %ptrincdec.i.i, %end br i1 %cmp.i.i, label %for.cond.for.end_crit_edge.i.i, label %for.body.i.i @@ -92,7 +94,7 @@ for.body.i.i: ; preds = %entry, %for.body.i. ; CHECK: {1,+,1}<nuw><nsw><%for.body.i.i> %ptrincdec.i.i = getelementptr inbounds i32, i32* %begin, i64 %tmp ; CHECK: %ptrincdec.i.i = -; CHECK: {(4 + %begin),+,4}<nsw><%for.body.i.i> +; CHECK: {(4 + %begin)<nsw>,+,4}<nsw><%for.body.i.i> %__first.addr.08.i.i = getelementptr inbounds i32, i32* %begin, i64 %indvar.i.i ; CHECK: %__first.addr.08.i.i ; CHECK: {%begin,+,4}<nsw><%for.body.i.i> @@ -124,7 +126,7 @@ exit: } ; CHECK-LABEL: PR12375 -; CHECK: --> {(4 + %arg),+,4}<nuw><%bb1>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (8 + %arg)<nsw> +; CHECK: --> {(4 + %arg)<nsw>,+,4}<nuw><%bb1>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (4 + (4 * ((-1 + (-1 * %arg) + ((4 + %arg)<nsw> umax (8 + %arg)<nsw>)) /u 4)) + %arg) define i32 @PR12375(i32* readnone %arg) { bb: %tmp = getelementptr inbounds i32, i32* %arg, i64 2 @@ -143,15 +145,15 @@ bb7: ; preds = %bb1 } ; CHECK-LABEL: PR12376 -; CHECK: --> {(4 + %arg),+,4}<nuw><%bb2>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (4 + (4 * ((3 + (-1 * %arg) + (%arg umax %arg1)) /u 4)) + %arg) +; CHECK: --> {(4 + %arg)<nsw>,+,4}<nuw><%bb2>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (4 + (4 * ((-1 + (-1 * %arg) + ((4 + %arg)<nsw> umax %arg1)) /u 4)) + %arg) define void @PR12376(i32* nocapture %arg, i32* nocapture %arg1) { bb: br label %bb2 bb2: ; preds = %bb2, %bb %tmp = phi i32* [ %arg, %bb ], [ %tmp4, %bb2 ] - %tmp3 = icmp ult i32* %tmp, %arg1 %tmp4 = getelementptr inbounds i32, i32* %tmp, i64 1 + %tmp3 = icmp ult i32* %tmp4, %arg1 br i1 %tmp3, label %bb2, label %bb5 bb5: ; preds = %bb2 @@ -161,8 +163,8 @@ bb5: ; preds = %bb2 declare void @f(i32) ; CHECK-LABEL: nswnowrap -; CHECK: --> {(1 + %v),+,1}<nsw><%for.body>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (2 + %v) -define void @nswnowrap(i32 %v) { +; CHECK: --> {(1 + %v)<nsw>,+,1}<nsw><%for.body>{{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: (1 + ((1 + %v)<nsw> smax %v)) +define void @nswnowrap(i32 %v, i32* %buf) { entry: %add = add nsw i32 %v, 1 br label %for.body @@ -170,10 +172,91 @@ entry: for.body: %i.04 = phi i32 [ %v, %entry ], [ %inc, %for.body ] %inc = add nsw i32 %i.04, 1 - tail call void @f(i32 %i.04) + %buf.gep = getelementptr inbounds i32, i32* %buf, i32 %inc + %buf.val = load i32, i32* %buf.gep %cmp = icmp slt i32 %i.04, %add + tail call void @f(i32 %i.04) br i1 %cmp, label %for.body, label %for.end for.end: ret void } + +; This test checks if no-wrap flags are propagated when folding {S,+,X}+T ==> {S+T,+,X} +; CHECK-LABEL: test4 +; CHECK: %idxprom +; CHECK-NEXT: --> {(-2 + (sext i32 %arg to i64))<nsw>,+,1}<nsw><%for.body> +define void @test4(i32 %arg) { +entry: + %array = alloca [10 x i32], align 4 + br label %for.body + +for.body: + %index = phi i32 [ %inc5, %for.body ], [ %arg, %entry ] + %sub = add nsw i32 %index, -2 + %idxprom = sext i32 %sub to i64 + %arrayidx = getelementptr inbounds [10 x i32], [10 x i32]* %array, i64 0, i64 %idxprom + %data = load i32, i32* %arrayidx, align 4 + %inc5 = add nsw i32 %index, 1 + %cmp2 = icmp slt i32 %inc5, 10 + br i1 %cmp2, label %for.body, label %for.end + +for.end: + ret void +} + + +define void @bad_postinc_nsw_a(i32 %n) { +; CHECK-LABEL: Classifying expressions for: @bad_postinc_nsw_a +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] + %iv.inc = add nsw i32 %iv, 7 +; CHECK: %iv.inc = add nsw i32 %iv, 7 +; CHECK-NEXT: --> {7,+,7}<nuw><%loop> + %becond = icmp ult i32 %iv, %n + br i1 %becond, label %loop, label %leave + +leave: + ret void +} + +define void @bad_postinc_nsw_b(i32 %n) { +; CHECK-LABEL: Classifying expressions for: @bad_postinc_nsw_b +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] + %iv.inc = add nsw i32 %iv, 7 + %iv.inc.and = and i32 %iv.inc, 0 +; CHECK: %iv.inc = add nsw i32 %iv, 7 +; CHECK-NEXT: --> {7,+,7}<nuw><%loop> + %becond = icmp ult i32 %iv.inc.and, %n + br i1 %becond, label %loop, label %leave + +leave: + ret void +} + +declare void @may_exit() nounwind + +define void @pr28012(i32 %n) { +; CHECK-LABEL: Classifying expressions for: @pr28012 +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] + %iv.inc = add nsw i32 %iv, 7 +; CHECK: %iv.inc = add nsw i32 %iv, 7 +; CHECK-NEXT: --> {7,+,7}<nuw><%loop> + %becond = icmp ult i32 %iv.inc, %n + call void @may_exit() + br i1 %becond, label %loop, label %leave + +leave: + ret void +} diff --git a/test/Analysis/ScalarEvolution/overflow-intrinsics.ll b/test/Analysis/ScalarEvolution/overflow-intrinsics.ll new file mode 100644 index 0000000000000..fb3d816c9fab4 --- /dev/null +++ b/test/Analysis/ScalarEvolution/overflow-intrinsics.ll @@ -0,0 +1,309 @@ +; 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 @f_sadd_0(i8* %a) { +; CHECK-LABEL: Classifying expressions for: @f_sadd_0 +entry: + br label %for.body + +for.cond.cleanup: ; preds = %cont + ret void + +for.body: ; preds = %entry, %cont +; CHECK: %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ] +; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%for.body> U: [0,16) S: [0,16) + + %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ] + %idxprom = sext i32 %i.04 to i64 + %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom + store i8 0, i8* %arrayidx, align 1 + %tmp0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1) + %tmp1 = extractvalue { i32, i1 } %tmp0, 1 + br i1 %tmp1, label %trap, label %cont, !nosanitize !{} + +trap: ; preds = %for.body + tail call void @llvm.trap() #2, !nosanitize !{} + unreachable, !nosanitize !{} + +cont: ; preds = %for.body + %tmp2 = extractvalue { i32, i1 } %tmp0, 0 + %cmp = icmp slt i32 %tmp2, 16 + br i1 %cmp, label %for.body, label %for.cond.cleanup +; CHECK: Loop %for.body: max backedge-taken count is 15 +} + +define void @f_sadd_1(i8* %a) { +; CHECK-LABEL: Classifying expressions for: @f_sadd_1 +entry: + br label %for.body + +for.cond.cleanup: ; preds = %cont + ret void + +for.body: ; preds = %entry, %cont +; CHECK: %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ] +; CHECK-NEXT: --> {0,+,1}<%for.body> U: [0,16) S: [0,16) + +; SCEV can prove <nsw> for the above induction variable; but it does +; not bother so before it sees the sext below since it is not a 100% +; obvious. + + %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ] + %idxprom = sext i32 %i.04 to i64 + %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom + store i8 0, i8* %arrayidx, align 1 + %tmp0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1) + %tmp1 = extractvalue { i32, i1 } %tmp0, 1 + br i1 %tmp1, label %trap, label %cont, !nosanitize !{} + +trap: ; preds = %for.body + + br label %cont + +cont: ; preds = %for.body + %tmp2 = extractvalue { i32, i1 } %tmp0, 0 + %cmp = icmp slt i32 %tmp2, 16 + br i1 %cmp, label %for.body, label %for.cond.cleanup +; CHECK: Loop %for.body: max backedge-taken count is 15 +} + +define void @f_sadd_2(i8* %a, i1* %c) { +; CHECK-LABEL: Classifying expressions for: @f_sadd_2 +entry: + br label %for.body + +for.cond.cleanup: ; preds = %cont + ret void + +for.body: ; preds = %entry, %cont +; CHECK: %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ] +; CHECK-NEXT: --> {0,+,1}<%for.body> + + %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ] + %idxprom = sext i32 %i.04 to i64 + %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom + store i8 0, i8* %arrayidx, align 1 + %tmp0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1) + %tmp1 = extractvalue { i32, i1 } %tmp0, 1 + br i1 %tmp1, label %trap, label %cont, !nosanitize !{} + +trap: ; preds = %for.body + + br label %cont + +cont: ; preds = %for.body + %tmp2 = extractvalue { i32, i1 } %tmp0, 0 + %cond = load volatile i1, i1* %c + br i1 %cond, label %for.body, label %for.cond.cleanup +} + +define void @f_sadd_3(i8* %a, i1* %c) { +; CHECK-LABEL: Classifying expressions for: @f_sadd_3 +entry: + br label %for.body + +for.cond.cleanup: ; preds = %cont + ret void + +for.body: ; preds = %entry, %cont +; CHECK: %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %for.body ] +; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%for.body> + + %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %for.body ] + %idxprom = sext i32 %i.04 to i64 + %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom + store i8 0, i8* %arrayidx, align 1 + %tmp0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1) + %tmp1 = extractvalue { i32, i1 } %tmp0, 1 + %tmp2 = extractvalue { i32, i1 } %tmp0, 0 + br i1 %tmp1, label %trap, label %for.body, !nosanitize !{} + +trap: ; preds = %for.body + tail call void @llvm.trap() #2, !nosanitize !{} + unreachable, !nosanitize !{} +} + +define void @f_sadd_4(i8* %a, i1* %c) { +; CHECK-LABEL: Classifying expressions for: @f_sadd_4 +entry: + br label %for.body + +for.cond.cleanup: ; preds = %cont + ret void + +for.body: ; preds = %entry, %cont +; CHECK: %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %merge ] +; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%for.body> + + %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %merge ] + %idxprom = sext i32 %i.04 to i64 + %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom + store i8 0, i8* %arrayidx, align 1 + %tmp0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1) + %tmp1 = extractvalue { i32, i1 } %tmp0, 1 + %tmp2 = extractvalue { i32, i1 } %tmp0, 0 + br i1 %tmp1, label %notrap, label %merge + +notrap: + br label %merge + +merge: + %tmp3 = extractvalue { i32, i1 } %tmp0, 1 + br i1 %tmp3, label %trap, label %for.body, !nosanitize !{} + +trap: ; preds = %for.body + tail call void @llvm.trap() #2, !nosanitize !{} + unreachable, !nosanitize !{} +} + +define void @f_sadd_may_overflow(i8* %a, i1* %c) { +; CHECK-LABEL: Classifying expressions for: @f_sadd_may_overflow +entry: + br label %for.body + +for.cond.cleanup: ; preds = %cont + ret void + +for.body: ; preds = %entry, %cont +; CHECK: %i.04 = phi i32 [ 0, %entry ], [ %tmp1, %cont ] +; CHECK-NEXT: --> {0,+,1}<%for.body> U: full-set S: full-set + + %i.04 = phi i32 [ 0, %entry ], [ %tmp1, %cont ] + %idxprom = sext i32 %i.04 to i64 + %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom + store i8 0, i8* %arrayidx, align 1 + %tmp0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1) + %cond1 = load volatile i1, i1* %c + br i1 %cond1, label %trap, label %cont, !nosanitize !{} + +trap: ; preds = %for.body + tail call void @llvm.trap() #2, !nosanitize !{} + unreachable, !nosanitize !{} + +cont: ; preds = %for.body + %tmp1 = extractvalue { i32, i1 } %tmp0, 0 + %cond = load volatile i1, i1* %c + br i1 %cond, label %for.body, label %for.cond.cleanup +} + +define void @f_uadd(i8* %a) { +; CHECK-LABEL: Classifying expressions for: @f_uadd +entry: + br label %for.body + +for.cond.cleanup: ; preds = %cont + ret void + +for.body: ; preds = %entry, %cont +; CHECK: %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ] +; CHECK-NEXT: --> {0,+,1}<nuw><%for.body> U: [0,16) S: [0,16) + + %i.04 = phi i32 [ 0, %entry ], [ %tmp2, %cont ] + %idxprom = sext i32 %i.04 to i64 + %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom + store i8 0, i8* %arrayidx, align 1 + %tmp0 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %i.04, i32 1) + %tmp1 = extractvalue { i32, i1 } %tmp0, 1 + br i1 %tmp1, label %trap, label %cont, !nosanitize !{} + +trap: ; preds = %for.body + tail call void @llvm.trap(), !nosanitize !{} + unreachable, !nosanitize !{} + +cont: ; preds = %for.body + %tmp2 = extractvalue { i32, i1 } %tmp0, 0 + %cmp = icmp slt i32 %tmp2, 16 + br i1 %cmp, label %for.body, label %for.cond.cleanup +; CHECK: Loop %for.body: max backedge-taken count is 15 +} + +define void @f_ssub(i8* nocapture %a) { +; CHECK-LABEL: Classifying expressions for: @f_ssub +entry: + br label %for.body + +for.cond.cleanup: ; preds = %cont + ret void + +for.body: ; preds = %entry, %cont +; CHECK: %i.04 = phi i32 [ 15, %entry ], [ %tmp2, %cont ] +; CHECK-NEXT: --> {15,+,-1}<%for.body> U: [0,16) S: [0,16) + + %i.04 = phi i32 [ 15, %entry ], [ %tmp2, %cont ] + %idxprom = sext i32 %i.04 to i64 + %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom + store i8 0, i8* %arrayidx, align 1 + %tmp0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %i.04, i32 1) + %tmp1 = extractvalue { i32, i1 } %tmp0, 1 + br i1 %tmp1, label %trap, label %cont, !nosanitize !{} + +trap: ; preds = %for.body + tail call void @llvm.trap(), !nosanitize !{} + unreachable, !nosanitize !{} + +cont: ; preds = %for.body + %tmp2 = extractvalue { i32, i1 } %tmp0, 0 + %cmp = icmp sgt i32 %tmp2, -1 + br i1 %cmp, label %for.body, label %for.cond.cleanup +; CHECK: Loop %for.body: max backedge-taken count is 15 +} + +define void @f_usub(i8* nocapture %a) { +; CHECK-LABEL: Classifying expressions for: @f_usub +entry: + br label %for.body + +for.cond.cleanup: ; preds = %cont + ret void + +for.body: ; preds = %entry, %cont +; CHECK: %i.04 = phi i32 [ 15, %entry ], [ %tmp2, %cont ] +; CHECK-NEXT: --> {15,+,-1}<%for.body> U: [0,16) S: [0,16) + + %i.04 = phi i32 [ 15, %entry ], [ %tmp2, %cont ] + %idxprom = sext i32 %i.04 to i64 + %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom + store i8 0, i8* %arrayidx, align 1 + %tmp0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %i.04, i32 1) + %tmp1 = extractvalue { i32, i1 } %tmp0, 1 + br i1 %tmp1, label %trap, label %cont, !nosanitize !{} + +trap: ; preds = %for.body + tail call void @llvm.trap(), !nosanitize !{} + unreachable, !nosanitize !{} + +cont: ; preds = %for.body + %tmp2 = extractvalue { i32, i1 } %tmp0, 0 + %cmp = icmp sgt i32 %tmp2, -1 + br i1 %cmp, label %for.body, label %for.cond.cleanup +; CHECK: Loop %for.body: max backedge-taken count is 15 +} + +define i32 @f_smul(i32 %val_a, i32 %val_b) { +; CHECK-LABEL: Classifying expressions for: @f_smul + %agg = tail call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %val_a, i32 %val_b) +; CHECK: %mul = extractvalue { i32, i1 } %agg, 0 +; CHECK-NEXT: --> (%val_a * %val_b) U: full-set S: full-set + %mul = extractvalue { i32, i1 } %agg, 0 + ret i32 %mul +} + +define i32 @f_umul(i32 %val_a, i32 %val_b) { +; CHECK-LABEL: Classifying expressions for: @f_umul + %agg = tail call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %val_a, i32 %val_b) +; CHECK: %mul = extractvalue { i32, i1 } %agg, 0 +; CHECK-NEXT: --> (%val_a * %val_b) U: full-set S: full-set + %mul = extractvalue { i32, i1 } %agg, 0 + ret i32 %mul +} + +declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone +declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone +declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone +declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone +declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone +declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone + +declare void @llvm.trap() #2 diff --git a/test/Analysis/ScalarEvolution/pr27315.ll b/test/Analysis/ScalarEvolution/pr27315.ll new file mode 100644 index 0000000000000..8f5f79df563b9 --- /dev/null +++ b/test/Analysis/ScalarEvolution/pr27315.ll @@ -0,0 +1,31 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +declare i1 @use(i64) + +define void @f_0() { +; CHECK-LABEL: Classifying expressions for: @f_0 + +; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.inc.nowrap, %be ] +; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> +; CHECK: %iv.inc.maywrap = add i32 %iv, 1 +; CHECK-NEXT: --> {1,+,1}<nuw><%loop> +; CHECK: %iv.inc.maywrap.sext = sext i32 %iv.inc.maywrap to i64 +; CHECK-NEXT: --> (sext i32 {1,+,1}<nuw><%loop> to i64) +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.inc.nowrap, %be ] + %iv.inc.maywrap = add i32 %iv, 1 + %iv.inc.maywrap.sext = sext i32 %iv.inc.maywrap to i64 + %cond0 = call i1 @use(i64 %iv.inc.maywrap.sext) + br i1 %cond0, label %be, label %leave + +be: + %iv.inc.nowrap = add nsw i32 %iv, 1 + %be.cond = call i1 @use(i64 0) ;; Get an unanalyzable value + br i1 %be.cond, label %loop, label %leave + +leave: + ret void +} diff --git a/test/Analysis/ScalarEvolution/predicated-trip-count.ll b/test/Analysis/ScalarEvolution/predicated-trip-count.ll new file mode 100644 index 0000000000000..2db0a8b577745 --- /dev/null +++ b/test/Analysis/ScalarEvolution/predicated-trip-count.ll @@ -0,0 +1,109 @@ +; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +@A = weak global [1000 x i32] zeroinitializer, align 32 + +; The resulting predicate is i16 {0,+,1} <nssw>, meanining +; that the resulting backedge expression will be valid for: +; (1 + (-1 smax %M)) <= MAX_INT16 +; +; At the limit condition for M (MAX_INT16 - 1) we have in the +; last iteration: +; i0 <- MAX_INT16 +; i0.ext <- MAX_INT16 +; +; and therefore no wrapping happend for i0 or i0.ext +; throughout the execution of the loop. The resulting predicated +; backedge taken count is correct. + +; CHECK: Classifying expressions for: @test1 +; CHECK: %i.0.ext = sext i16 %i.0 to i32 +; CHECK-NEXT: --> (sext i16 {0,+,1}<%bb3> to i32) +; CHECK: Loop %bb3: Unpredictable backedge-taken count. +; CHECK-NEXT: Loop %bb3: Unpredictable max backedge-taken count. +; CHECK-NEXT: Loop %bb3: Predicated backedge-taken count is (1 + (-1 smax %M)) +; CHECK-NEXT: Predicates: +; CHECK-NEXT: {0,+,1}<%bb3> Added Flags: <nssw> +define void @test1(i32 %N, i32 %M) { +entry: + br label %bb3 + +bb: ; preds = %bb3 + %tmp = getelementptr [1000 x i32], [1000 x i32]* @A, i32 0, i16 %i.0 ; <i32*> [#uses=1] + store i32 123, i32* %tmp + %tmp2 = add i16 %i.0, 1 ; <i32> [#uses=1] + br label %bb3 + +bb3: ; preds = %bb, %entry + %i.0 = phi i16 [ 0, %entry ], [ %tmp2, %bb ] ; <i32> [#uses=3] + %i.0.ext = sext i16 %i.0 to i32 + %tmp3 = icmp sle i32 %i.0.ext, %M ; <i1> [#uses=1] + br i1 %tmp3, label %bb, label %bb5 + +bb5: ; preds = %bb3 + br label %return + +return: ; preds = %bb5 + ret void +} + +; The predicated backedge taken count is: +; (2 + (zext i16 %Start to i32) + ((-2 + (-1 * (sext i16 %Start to i32))) +; smax (-1 + (-1 * %M))) +; ) + +; -1 + (-1 * %M) <= (-2 + (-1 * (sext i16 %Start to i32)) +; The predicated backedge taken count is 0. +; From the IR, this is correct since we will bail out at the +; first iteration. + + +; * -1 + (-1 * %M) > (-2 + (-1 * (sext i16 %Start to i32)) +; or: %M < 1 + (sext i16 %Start to i32) +; +; The predicated backedge taken count is 1 + (zext i16 %Start to i32) - %M +; +; If %M >= MIN_INT + 1, this predicated backedge taken count would be correct (even +; without predicates). However, for %M < MIN_INT this would be an infinite loop. +; In these cases, the {%Start,+,-1} <nusw> predicate would be false, as the +; final value of the expression {%Start,+,-1} expression (%M - 1) would not be +; representable as an i16. + +; There is also a limit case here where the value of %M is MIN_INT. In this case +; we still have an infinite loop, since icmp sge %x, MIN_INT will always return +; true. + +; CHECK: Classifying expressions for: @test2 + +; CHECK: %i.0.ext = sext i16 %i.0 to i32 +; CHECK-NEXT: --> (sext i16 {%Start,+,-1}<%bb3> to i32) +; CHECK: Loop %bb3: Unpredictable backedge-taken count. +; CHECK-NEXT: Loop %bb3: Unpredictable max backedge-taken count. +; CHECK-NEXT: Loop %bb3: Predicated backedge-taken count is (2 + (sext i16 %Start to i32) + ((-2 + (-1 * (sext i16 %Start to i32))) smax (-1 + (-1 * %M)))) +; CHECK-NEXT: Predicates: +; CHECK-NEXT: {%Start,+,-1}<%bb3> Added Flags: <nssw> + +define void @test2(i32 %N, i32 %M, i16 %Start) { +entry: + br label %bb3 + +bb: ; preds = %bb3 + %tmp = getelementptr [1000 x i32], [1000 x i32]* @A, i32 0, i16 %i.0 ; <i32*> [#uses=1] + store i32 123, i32* %tmp + %tmp2 = sub i16 %i.0, 1 ; <i32> [#uses=1] + br label %bb3 + +bb3: ; preds = %bb, %entry + %i.0 = phi i16 [ %Start, %entry ], [ %tmp2, %bb ] ; <i32> [#uses=3] + %i.0.ext = sext i16 %i.0 to i32 + %tmp3 = icmp sge i32 %i.0.ext, %M ; <i1> [#uses=1] + br i1 %tmp3, label %bb, label %bb5 + +bb5: ; preds = %bb3 + br label %return + +return: ; preds = %bb5 + ret void +} + diff --git a/test/Analysis/ScalarEvolution/returned.ll b/test/Analysis/ScalarEvolution/returned.ll new file mode 100644 index 0000000000000..4c07cd1346657 --- /dev/null +++ b/test/Analysis/ScalarEvolution/returned.ll @@ -0,0 +1,16 @@ +; RUN: opt < %s -S -analyze -scalar-evolution | 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" + +define i8* @foo(i32 %no, i8* nocapture %d) nounwind { +entry: + %v = call i8* @func1(i8* %d) + %w = getelementptr i8, i8* %v, i64 5 + ret i8* %w +} + +; CHECK-LABEL: Classifying expressions for: @foo +; CHECK: %w = getelementptr i8, i8* %v, i64 5 +; CHECK-NEXT: (5 + %d) + +declare i8* @func1(i8* returned) nounwind argmemonly + diff --git a/test/Analysis/ScalarEvolution/scev-aa.ll b/test/Analysis/ScalarEvolution/scev-aa.ll index 47a84d57c3b3c..682bd2134afc7 100644 --- a/test/Analysis/ScalarEvolution/scev-aa.ll +++ b/test/Analysis/ScalarEvolution/scev-aa.ll @@ -1,5 +1,7 @@ ; RUN: opt -disable-output < %s -disable-basicaa -scev-aa -aa-eval -print-all-alias-modref-info \ ; RUN: 2>&1 | FileCheck %s +; RUN: opt -disable-output < %s -aa-pipeline=scev-aa -passes=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 ; A[i+(j+1)] != A[i+j], which can arise from multi-dimensional array references, diff --git a/test/Analysis/ScalarEvolution/scev-canonical-mode.ll b/test/Analysis/ScalarEvolution/scev-canonical-mode.ll new file mode 100644 index 0000000000000..0aa7ff08f926b --- /dev/null +++ b/test/Analysis/ScalarEvolution/scev-canonical-mode.ll @@ -0,0 +1,32 @@ +; PR26529: Check the assumption of IndVarSimplify to do SCEV expansion in literal mode +; instead of CanonicalMode is properly maintained in SCEVExpander::expand. +; RUN: opt -indvars < %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: norecurse nounwind uwtable +define void @ehF() #0 { +entry: + br i1 undef, label %if.then.i, label %hup.exit + +if.then.i: ; preds = %entry + br i1 undef, label %for.body.lr.ph.i, label %hup.exit + +for.body.lr.ph.i: ; preds = %if.then.i + br label %for.body.i + +for.body.i: ; preds = %for.body.i, %for.body.lr.ph.i + %i.03.i = phi i32 [ 0, %for.body.lr.ph.i ], [ %inc.i, %for.body.i ] + %k.02.i = phi i32 [ 1, %for.body.lr.ph.i ], [ %inc5.i, %for.body.i ] + %inc.i = add nsw i32 %i.03.i, 1 + %idxprom.i = sext i32 %i.03.i to i64 + %idxprom2.i = sext i32 %k.02.i to i64 + %inc5.i = add nsw i32 %k.02.i, 1 + br i1 false, label %for.body.i, label %hup.exit + +hup.exit: ; preds = %for.body.i, %if.then.i, %entry + ret void +} + +attributes #0 = { norecurse nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/test/Analysis/ScalarEvolution/scev-dispositions.ll b/test/Analysis/ScalarEvolution/scev-dispositions.ll new file mode 100644 index 0000000000000..4e382a93cda95 --- /dev/null +++ b/test/Analysis/ScalarEvolution/scev-dispositions.ll @@ -0,0 +1,73 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +define void @single_loop(i32* %buf, i32 %start) { +; CHECK-LABEL: Classifying expressions for: @single_loop + entry: + %val = add i32 %start, 400 + br label %loop + + loop: + %counter = phi i32 [ 0, %entry ], [ %counter.inc, %loop ] + %idx = phi i32 [ %start, %entry ], [ %idx.inc, %loop ] + +; CHECK: %counter = phi i32 [ 0, %entry ], [ %counter.inc, %loop ] +; CHECK-NEXT: --> {{.*}} LoopDispositions: { %loop: Computable } +; CHECK: %idx = phi i32 [ %start, %entry ], [ %idx.inc, %loop ] +; CHECK-NEXT: --> {{.*}} LoopDispositions: { %loop: Computable } +; CHECK: %val2 = add i32 %start, 400 +; CHECK-NEXT: --> {{.*}} LoopDispositions: { %loop: Invariant } +; CHECK: %idx.inc = add nsw i32 %idx, 1 +; CHECK-NEXT: --> {{.*}} LoopDispositions: { %loop: Computable } +; CHECK: %val3 = load volatile i32, i32* %buf +; CHECK-NEXT: --> {{.*}} LoopDispositions: { %loop: Variant } + + %val2 = add i32 %start, 400 + %idx.inc = add nsw i32 %idx, 1 + %idx.inc.sext = sext i32 %idx.inc to i64 + %condition = icmp eq i32 %counter, 1 + %counter.inc = add i32 %counter, 1 + %val3 = load volatile i32, i32* %buf + br i1 %condition, label %exit, label %loop + + exit: + ret void +} + + +define void @nested_loop(double* %p, i64 %m) { +; CHECK-LABEL: Classifying expressions for: @nested_loop + +; CHECK: %j = phi i64 [ 0, %entry ], [ %j.next, %outer.latch ] +; CHECK-NEXT: --> {{.*}} LoopDispositions: { %outer.loop: Computable, %bb: Invariant } +; CHECK: %i = phi i64 [ 0, %outer.loop ], [ %i.next, %bb ] +; CHECK-NEXT: --> {{.*}} LoopDispositions: { %bb: Computable, %outer.loop: Variant } +; CHECK: %j.add = add i64 %j, 100 +; CHECK-NEXT: --> {{.*}} LoopDispositions: { %bb: Invariant, %outer.loop: Computable } +; CHECK: %i.next = add i64 %i, 1 +; CHECK-NEXT: --> {{.*}} LoopDispositions: { %bb: Computable, %outer.loop: Variant } +; CHECK: %j.next = add i64 %j, 91 +; CHECK-NEXT: --> {{.*}} LoopDispositions: { %outer.loop: Computable, %bb: Invariant } + +entry: + %k = icmp sgt i64 %m, 0 + br i1 %k, label %outer.loop, label %return + +outer.loop: + %j = phi i64 [ 0, %entry ], [ %j.next, %outer.latch ] + br label %bb + +bb: + %i = phi i64 [ 0, %outer.loop ], [ %i.next, %bb ] + %j.add = add i64 %j, 100 + %i.next = add i64 %i, 1 + %exitcond = icmp eq i64 %i.next, 91 + br i1 %exitcond, label %outer.latch, label %bb + +outer.latch: + %j.next = add i64 %j, 91 + %h = icmp eq i64 %j.next, %m + br i1 %h, label %return, label %outer.loop + +return: + ret void +} diff --git a/test/Analysis/ScalarEvolution/scev-expander-existing-value.ll b/test/Analysis/ScalarEvolution/scev-expander-existing-value.ll new file mode 100644 index 0000000000000..0c1d6766869d3 --- /dev/null +++ b/test/Analysis/ScalarEvolution/scev-expander-existing-value.ll @@ -0,0 +1,38 @@ +; RUN: opt < %s -loop-vectorize -force-vector-width=4 -verify-scev-maps -S |FileCheck %s + +; SCEV expansion uses existing value when the SCEV has no AddRec expr. +; CHECK: select +; CHECK-NOT: select + +@a = common global [1000 x i16] zeroinitializer, align 16 + +define i32 @foo(i32 %x, i32 %y) { +entry: + %cmp = icmp slt i32 %x, %y + %cond = select i1 %cmp, i32 %x, i32 %y + %cmp1.10 = icmp sgt i32 %cond, 0 + br i1 %cmp1.10, label %for.body.lr.ph, label %for.end + +for.body.lr.ph: ; preds = %entry + %tmp = sext i32 %cond to i64 + br label %for.body + +for.body: ; preds = %for.body, %for.body.lr.ph + %indvars.iv = phi i64 [ 0, %for.body.lr.ph ], [ %indvars.iv.next, %for.body ] + %total.011 = phi i32 [ 0, %for.body.lr.ph ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds [1000 x i16], [1000 x i16]* @a, i64 0, i64 %indvars.iv + %tmp1 = load i16, i16* %arrayidx, align 2 + %conv = sext i16 %tmp1 to i32 + %add = add nsw i32 %conv, %total.011 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %cmp1 = icmp slt i64 %indvars.iv.next, %tmp + br i1 %cmp1, label %for.body, label %for.end.loopexit + +for.end.loopexit: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + br label %for.end + +for.end: ; preds = %for.end.loopexit, %entry + %total.0.lcssa = phi i32 [ 0, %entry ], [ %add.lcssa, %for.end.loopexit ] + ret i32 %total.0.lcssa +} diff --git a/test/Analysis/ScalarEvolution/sext-to-zext.ll b/test/Analysis/ScalarEvolution/sext-to-zext.ll new file mode 100644 index 0000000000000..ca9c6de0d50d5 --- /dev/null +++ b/test/Analysis/ScalarEvolution/sext-to-zext.ll @@ -0,0 +1,23 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +define void @f(i1 %c) { +; CHECK-LABEL: Classifying expressions for: @f +entry: + %start = select i1 %c, i32 100, i32 0 + %step = select i1 %c, i32 -1, i32 1 + br label %loop + +loop: + %iv = phi i32 [ %start, %entry ], [ %iv.dec, %loop ] + %iv.tc = phi i32 [ 0, %entry ], [ %iv.tc.inc, %loop ] + %iv.tc.inc = add i32 %iv.tc, 1 + %iv.dec = add nsw i32 %iv, %step + %iv.sext = sext i32 %iv to i64 +; CHECK: %iv.sext = sext i32 %iv to i64 +; CHECK-NEXT: --> {(sext i32 %start to i64),+,(sext i32 %step to i64)}<nsw><%loop> + %be = icmp ne i32 %iv.tc.inc, 100 + br i1 %be, label %loop, label %leave + +leave: + ret void +} diff --git a/test/Analysis/ScalarEvolution/trip-count.ll b/test/Analysis/ScalarEvolution/trip-count.ll index 89750810d1b72..d21ace9f25016 100644 --- a/test/Analysis/ScalarEvolution/trip-count.ll +++ b/test/Analysis/ScalarEvolution/trip-count.ll @@ -89,3 +89,25 @@ for.inc.1: ; preds = %for.body.1, %for.in ; Function Attrs: nounwind declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) #0 + +declare void @may_exit() nounwind + +define void @pr28012(i32 %n) { +; CHECK-LABEL: Classifying expressions for: @pr28012 +; CHECK: Loop %loop: backedge-taken count is -1431655751 +; CHECK: Loop %loop: max backedge-taken count is -1431655751 +; CHECK: Loop %loop: Predicated backedge-taken count is -1431655751 + +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ] + %iv.inc = add nsw i32 %iv, 3 + call void @may_exit() + %becond = icmp ne i32 %iv.inc, 46 + br i1 %becond, label %loop, label %leave + +leave: + ret void +} diff --git a/test/Analysis/ScalarEvolution/trip-count13.ll b/test/Analysis/ScalarEvolution/trip-count13.ll new file mode 100644 index 0000000000000..37ef2fd500a0e --- /dev/null +++ b/test/Analysis/ScalarEvolution/trip-count13.ll @@ -0,0 +1,81 @@ +; RUN: opt -S -analyze -scalar-evolution < %s | FileCheck %s + +define void @u_0(i8 %rhs) { +; E.g.: %rhs = 255, %start = 99, backedge taken 156 times +entry: + %start = add i8 %rhs, 100 + br label %loop + +loop: + %iv = phi i8 [ %start, %entry ], [ %iv.inc, %loop ] + %iv.inc = add nuw i8 %iv, 1 ;; Note: this never unsigned-wraps + %iv.cmp = icmp ult i8 %iv, %rhs + br i1 %iv.cmp, label %loop, label %leave + +; CHECK-LABEL: Determining loop execution counts for: @u_0 +; CHECK-NEXT: Loop %loop: backedge-taken count is (-100 + (-1 * %rhs) + ((100 + %rhs) umax %rhs)) +; CHECK-NEXT: Loop %loop: max backedge-taken count is -1 + +leave: + ret void +} + +define void @u_1(i8 %start) { +entry: +; E.g.: %start = 99, %rhs = 255, backedge taken 156 times + %rhs = add i8 %start, -100 + br label %loop + +loop: + %iv = phi i8 [ %start, %entry ], [ %iv.inc, %loop ] + %iv.inc = add nuw i8 %iv, 1 ;; Note: this never unsigned-wraps + %iv.cmp = icmp ult i8 %iv, %rhs + br i1 %iv.cmp, label %loop, label %leave + +; CHECK-LABEL: Determining loop execution counts for: @u_1 +; CHECK-NEXT: Loop %loop: backedge-taken count is ((-1 * %start) + ((-100 + %start) umax %start)) +; CHECK-NEXT: Loop %loop: max backedge-taken count is -1 + +leave: + ret void +} + +define void @s_0(i8 %rhs) { +entry: +; E.g.: %rhs = 127, %start = -29, backedge taken 156 times + %start = add i8 %rhs, 100 + br label %loop + +loop: + %iv = phi i8 [ %start, %entry ], [ %iv.inc, %loop ] + %iv.inc = add nsw i8 %iv, 1 ;; Note: this never signed-wraps + %iv.cmp = icmp slt i8 %iv, %rhs + br i1 %iv.cmp, label %loop, label %leave + +; CHECK-LABEL: Determining loop execution counts for: @s_0 +; CHECK-NEXT: Loop %loop: backedge-taken count is (-100 + (-1 * %rhs) + ((100 + %rhs) smax %rhs)) +; CHECK-NEXT: Loop %loop: max backedge-taken count is -1 + +leave: + ret void +} + +define void @s_1(i8 %start) { +entry: +; E.g.: start = -29, %rhs = 127, %backedge taken 156 times + %rhs = add i8 %start, -100 + br label %loop + +loop: + %iv = phi i8 [ %start, %entry ], [ %iv.inc, %loop ] + %iv.inc = add nsw i8 %iv, 1 + %iv.cmp = icmp slt i8 %iv, %rhs + br i1 %iv.cmp, label %loop, label %leave + +; CHECK-LABEL: Determining loop execution counts for: @s_1 +; CHECK-NEXT: Loop %loop: backedge-taken count is ((-1 * %start) + ((-100 + %start) smax %start)) +; CHECK-NEXT: Loop %loop: max backedge-taken count is -1 + +leave: + ret void +} diff --git a/test/Analysis/ScopedNoAliasAA/basic.ll b/test/Analysis/ScopedNoAliasAA/basic.ll index 26258341cc14e..69e088e89763e 100644 --- a/test/Analysis/ScopedNoAliasAA/basic.ll +++ b/test/Analysis/ScopedNoAliasAA/basic.ll @@ -1,13 +1,14 @@ ; RUN: opt < %s -basicaa -scoped-noalias -aa-eval -evaluate-aa-metadata -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=basic-aa,scoped-noalias-aa -passes=aa-eval -evaluate-aa-metadata -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" define void @foo1(float* nocapture %a, float* nocapture readonly %c) #0 { entry: ; CHECK-LABEL: Function: foo1 - %0 = load float, float* %c, align 4, !alias.scope !1 + %0 = load float, float* %c, align 4, !alias.scope !2 %arrayidx.i = getelementptr inbounds float, float* %a, i64 5 - store float %0, float* %arrayidx.i, align 4, !noalias !1 + store float %0, float* %arrayidx.i, align 4, !noalias !2 %1 = load float, float* %c, align 4 %arrayidx = getelementptr inbounds float, float* %a, i64 7 store float %1, float* %arrayidx, align 4 @@ -24,4 +25,4 @@ attributes #0 = { nounwind uwtable } !0 = !{!0, !"some domain"} !1 = !{!1, !0, !"some scope"} - +!2 = !{!1} diff --git a/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll b/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll index fe2fdd74b411d..ed091466165e0 100644 --- a/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll +++ b/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll @@ -43,13 +43,13 @@ define void @test1_no(i32* %p) nounwind { ; This is unusual, since the function is memcpy, but as above, this ; isn't necessarily invalid. -; CHECK: define void @test2_yes(i8* nocapture %p, i8* nocapture %q, i64 %n) #0 { +; CHECK: define void @test2_yes(i8* nocapture %p, i8* nocapture %q, i64 %n) #4 { define void @test2_yes(i8* %p, i8* %q, i64 %n) nounwind { call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, i64 %n, i32 1, i1 false), !tbaa !1 ret void } -; CHECK: define void @test2_no(i8* nocapture %p, i8* nocapture readonly %q, i64 %n) #1 { +; CHECK: define void @test2_no(i8* nocapture %p, i8* nocapture readonly %q, i64 %n) #3 { define void @test2_no(i8* %p, i8* %q, i64 %n) nounwind { call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, i64 %n, i32 1, i1 false), !tbaa !2 ret void @@ -76,7 +76,8 @@ declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i32, i1) nounwind ; CHECK: attributes #1 = { norecurse nounwind } ; CHECK: attributes #2 = { nounwind readonly } ; CHECK: attributes #3 = { nounwind } -; CHECK: attributes #4 = { argmemonly nounwind } +; CHECK: attributes #4 = { nounwind readnone } +; CHECK: attributes #5 = { argmemonly nounwind } ; Root note. !0 = !{ } diff --git a/test/Analysis/TypeBasedAliasAnalysis/placement-tbaa.ll b/test/Analysis/TypeBasedAliasAnalysis/placement-tbaa.ll index aa91020f12d67..54d57133b99c6 100644 --- a/test/Analysis/TypeBasedAliasAnalysis/placement-tbaa.ll +++ b/test/Analysis/TypeBasedAliasAnalysis/placement-tbaa.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -tbaa -basicaa -aa-eval -evaluate-aa-metadata -print-no-aliases -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -aa-pipeline=type-based-aa,basic-aa -passes=aa-eval -evaluate-aa-metadata -print-no-aliases -print-may-aliases -disable-output 2>&1 | FileCheck %s ; Generated with "clang -cc1 -disable-llvm-optzns -O1 -emit-llvm" ; #include <new> diff --git a/test/Analysis/ValueTracking/deref-bitcast-of-gep.ll b/test/Analysis/ValueTracking/deref-bitcast-of-gep.ll new file mode 100644 index 0000000000000..38a8da8c09823 --- /dev/null +++ b/test/Analysis/ValueTracking/deref-bitcast-of-gep.ll @@ -0,0 +1,82 @@ +; RUN: opt -S -licm < %s | FileCheck %s + +; Note: the !invariant.load is there just solely to let us call @use() +; to add a fake use, and still have the aliasing work out. The call +; to @use(0) is just to provide a may-unwind exit out of the loop, so +; that LICM cannot hoist out the load simply because it is guaranteed +; to execute. + +declare void @use(i32) + +define void @f_0(i8* align 4 dereferenceable(1024) %ptr) { +; CHECK-LABEL: @f_0( +; CHECK: entry: +; CHECK: %val = load i32, i32* %ptr.i32 +; CHECK: br label %loop +; CHECK: loop: +; CHECK: call void @use(i32 0) +; CHECK-NEXT: call void @use(i32 %val) + + +entry: + %ptr.gep = getelementptr i8, i8* %ptr, i32 32 + %ptr.i32 = bitcast i8* %ptr.gep to i32* + br label %loop + +loop: + call void @use(i32 0) + %val = load i32, i32* %ptr.i32, !invariant.load !{} + call void @use(i32 %val) + br label %loop +} + +define void @f_1(i8* align 4 dereferenceable_or_null(1024) %ptr) { +; CHECK-LABEL: @f_1( +entry: + %ptr.gep = getelementptr i8, i8* %ptr, i32 32 + %ptr.i32 = bitcast i8* %ptr.gep to i32* + %ptr_is_null = icmp eq i8* %ptr, null + br i1 %ptr_is_null, label %leave, label %loop + +; CHECK: loop.preheader: +; CHECK: %val = load i32, i32* %ptr.i32 +; CHECK: br label %loop +; CHECK: loop: +; CHECK: call void @use(i32 0) +; CHECK-NEXT: call void @use(i32 %val) + +loop: + call void @use(i32 0) + %val = load i32, i32* %ptr.i32, !invariant.load !{} + call void @use(i32 %val) + br label %loop + +leave: + ret void +} + +define void @f_2(i8* align 4 dereferenceable_or_null(1024) %ptr) { +; CHECK-LABEL: @f_2( +; CHECK-NOT: load +; CHECK: call void @use(i32 0) +; CHECK-NEXT: %val = load i32, i32* %ptr.i32, !invariant.load !0 +; CHECK-NEXT: call void @use(i32 %val) + +entry: + ;; Can't hoist, since the alignment does not work out -- (<4 byte + ;; aligned> + 30) is not necessarily 4 byte aligned. + + %ptr.gep = getelementptr i8, i8* %ptr, i32 30 + %ptr.i32 = bitcast i8* %ptr.gep to i32* + %ptr_is_null = icmp eq i8* %ptr, null + br i1 %ptr_is_null, label %leave, label %loop + +loop: + call void @use(i32 0) + %val = load i32, i32* %ptr.i32, !invariant.load !{} + call void @use(i32 %val) + br label %loop + +leave: + ret void +} diff --git a/test/Analysis/ValueTracking/dom-cond.ll b/test/Analysis/ValueTracking/dom-cond.ll deleted file mode 100644 index c0cafdd0ade08..0000000000000 --- a/test/Analysis/ValueTracking/dom-cond.ll +++ /dev/null @@ -1,18 +0,0 @@ -; RUN: opt < %s -instcombine -value-tracking-dom-conditions -S | FileCheck %s - -define i32 @dom_cond(i32 %a, i32 %b) { -; CHECK-LABEL: @dom_cond( -entry: - %v = add i32 %a, %b - %cond = icmp ule i32 %v, 7 - br i1 %cond, label %then, label %exit - -then: - %v2 = add i32 %v, 8 -; CHECK: or i32 %v, 8 - br label %exit - -exit: - %v3 = phi i32 [ %v, %entry ], [ %v2, %then ] - ret i32 %v3 -} diff --git a/test/Analysis/ValueTracking/known-bits-from-range-md.ll b/test/Analysis/ValueTracking/known-bits-from-range-md.ll index e1de089b3501c..3bd8c287af963 100644 --- a/test/Analysis/ValueTracking/known-bits-from-range-md.ll +++ b/test/Analysis/ValueTracking/known-bits-from-range-md.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -instsimplify < %s | FileCheck %s +; RUN: opt -S -instsimplify -instcombine < %s | FileCheck %s define i1 @test0(i8* %ptr) { ; CHECK-LABEL: @test0( @@ -23,10 +23,10 @@ define i1 @test1(i8* %ptr) { define i1 @test2(i8* %ptr) { ; CHECK-LABEL: @test2( entry: -; CHECK: load -; CHECK: and -; CHECK: icmp eq -; CHECK: ret +; CHECK: %val = load i8 +; CHECK: %and = and i8 %val +; CHECK: %is.eq = icmp ne i8 %and, 0 +; CHECK: ret i1 %is.eq %val = load i8, i8* %ptr, !range !{i8 64, i8 129} %and = and i8 %val, 64 %is.eq = icmp eq i8 %and, 64 diff --git a/test/Analysis/ValueTracking/memory-dereferenceable.ll b/test/Analysis/ValueTracking/memory-dereferenceable.ll index 5b45172f695e1..29c31b95b188e 100644 --- a/test/Analysis/ValueTracking/memory-dereferenceable.ll +++ b/test/Analysis/ValueTracking/memory-dereferenceable.ll @@ -3,7 +3,7 @@ ; Uses the print-deref (+ analyze to print) pass to run ; isDereferenceablePointer() on many load instruction operands -target datalayout = "e" +target datalayout = "e-i32:32:64" %TypeOpaque = type opaque @@ -43,7 +43,8 @@ entry: %load4 = load i32, i32 addrspace(1)* %relocate ; CHECK-NOT: %nparam - %nparam = getelementptr i32, i32 addrspace(1)* %dparam, i32 5 + %dpa = call i32 addrspace(1)* @func1(i32 addrspace(1)* %dparam) + %nparam = getelementptr i32, i32 addrspace(1)* %dpa, i32 5 %load5 = load i32, i32 addrspace(1)* %nparam ; Load from a non-dereferenceable load @@ -133,6 +134,12 @@ entry: %load26 = load i32, i32* %d4_unaligned_load, align 16 %load27 = load i32, i32* %d4_aligned_load, align 16 + ; Alloca with no explicit alignment is aligned to preferred alignment of + ; the type (specified by datalayout string). +; CHECK: %alloca.noalign{{.*}}(aligned) + %alloca.noalign = alloca i32 + %load28 = load i32, i32* %alloca.noalign, align 8 + ret void } @@ -156,6 +163,8 @@ if.end: 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) +declare i32 addrspace(1)* @func1(i32 addrspace(1)* returned) nounwind argmemonly + !0 = !{i64 4} !1 = !{i64 2} !2 = !{} diff --git a/test/Analysis/ValueTracking/pr24866.ll b/test/Analysis/ValueTracking/pr24866.ll deleted file mode 100644 index b146b4ac05643..0000000000000 --- a/test/Analysis/ValueTracking/pr24866.ll +++ /dev/null @@ -1,44 +0,0 @@ -; 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 -} diff --git a/test/Analysis/alias-analysis-uses.ll b/test/Analysis/alias-analysis-uses.ll new file mode 100644 index 0000000000000..4163ec25584c6 --- /dev/null +++ b/test/Analysis/alias-analysis-uses.ll @@ -0,0 +1,10 @@ +; RUN: opt -debug-pass=Executions -globals-aa -functionattrs -disable-output < %s 2>&1 | FileCheck %s + +; CHECK: Executing Pass 'Globals Alias Analysis' +; CHECK-NOT: Freeing Pass 'Globals Alias Analysis' +; CHECK: Executing Pass 'Deduce function attributes' +; CHECK: Freeing Pass 'Globals Alias Analysis' + +define void @test(i8* %p) { + ret void +} |
