diff options
Diffstat (limited to 'test/Transforms')
34 files changed, 905 insertions, 127 deletions
diff --git a/test/Transforms/FunctionAttrs/norecurse.ll b/test/Transforms/FunctionAttrs/norecurse.ll index 4748119..d5a2d82 100644 --- a/test/Transforms/FunctionAttrs/norecurse.ll +++ b/test/Transforms/FunctionAttrs/norecurse.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -basicaa -functionattrs -S | FileCheck %s +; RUN: opt < %s -basicaa -functionattrs -rpo-functionattrs -S | FileCheck %s ; CHECK: define i32 @leaf() #0 define i32 @leaf() { diff --git a/test/Transforms/FunctionImport/Inputs/funcimport.ll b/test/Transforms/FunctionImport/Inputs/funcimport.ll index 9655589..79b766b 100644 --- a/test/Transforms/FunctionImport/Inputs/funcimport.ll +++ b/test/Transforms/FunctionImport/Inputs/funcimport.ll @@ -10,6 +10,7 @@ define void @globalfunc1() #0 { entry: + call void @funcwithpersonality() ret void } @@ -79,6 +80,20 @@ entry: ret i32 1 } +declare i32 @__gxx_personality_v0(...) + +; Add enough instructions to prevent import with inst limit of 5 +define internal void @funcwithpersonality() #2 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +entry: + call void @globalfunc2() + call void @globalfunc2() + call void @globalfunc2() + call void @globalfunc2() + call void @globalfunc2() + call void @globalfunc2() + ret void +} + define internal void @staticfunc2() #0 { entry: ret void diff --git a/test/Transforms/FunctionImport/Inputs/funcimport_alias.ll b/test/Transforms/FunctionImport/Inputs/funcimport_alias.ll new file mode 100644 index 0000000..f897aed --- /dev/null +++ b/test/Transforms/FunctionImport/Inputs/funcimport_alias.ll @@ -0,0 +1,7 @@ +declare void @analias() + +define void @callanalias() #0 { +entry: + call void @analias() + ret void +} diff --git a/test/Transforms/FunctionImport/funcimport.ll b/test/Transforms/FunctionImport/funcimport.ll index c099b97..52fd53d 100644 --- a/test/Transforms/FunctionImport/funcimport.ll +++ b/test/Transforms/FunctionImport/funcimport.ll @@ -73,3 +73,5 @@ declare void @callfuncptr(...) #1 ; CHECK-DAG: declare void @weakfunc(...) declare void @weakfunc(...) #1 +; INSTLIMDEF-DAG: define available_externally hidden void @funcwithpersonality.llvm.2() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +; INSTLIM5-DAG: declare hidden void @funcwithpersonality.llvm.2() diff --git a/test/Transforms/FunctionImport/funcimport_alias.ll b/test/Transforms/FunctionImport/funcimport_alias.ll new file mode 100644 index 0000000..8c7f00f --- /dev/null +++ b/test/Transforms/FunctionImport/funcimport_alias.ll @@ -0,0 +1,25 @@ +; Do setup work for all below tests: generate bitcode and combined index +; RUN: llvm-as -function-summary %s -o %t.bc +; RUN: llvm-as -function-summary %p/Inputs/funcimport_alias.ll -o %t2.bc +; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc + +; Do the import now. Ensures that the importer handles an external call +; from imported callanalias() to a function that is defined already in +; the dest module, but as an alias. +; RUN: opt -function-import -summary-file %t3.thinlto.bc %s -S | FileCheck %s + +define i32 @main() #0 { +entry: + call void @callanalias() + ret i32 0 +} + +@analias = alias void (), void ()* @globalfunc + +define void @globalfunc() #0 { +entry: + ret void +} + +declare void @callanalias() #1 +; CHECK-DAG: define available_externally void @callanalias() diff --git a/test/Transforms/FunctionImport/funcimport_debug.ll b/test/Transforms/FunctionImport/funcimport_debug.ll index c57b5e1..96b73a3 100644 --- a/test/Transforms/FunctionImport/funcimport_debug.ll +++ b/test/Transforms/FunctionImport/funcimport_debug.ll @@ -7,8 +7,18 @@ ; RUN: opt -function-import -summary-file %t3.thinlto.bc %s -S | FileCheck %s ; CHECK: define available_externally void @func() -; CHECK: distinct !DISubprogram(name: "main" -; CHECK: distinct !DISubprogram(name: "func" + +; Check that we have exactly two subprograms (that func's subprogram wasn't +; linked more than once for example), and that they are connected to +; the subprogram list on a compute unit. +; CHECK: !{{[0-9]+}} = distinct !DICompileUnit({{.*}} subprograms: ![[SPs1:[0-9]+]] +; CHECK: ![[SPs1]] = !{![[MAINSP:[0-9]+]]} +; CHECK: ![[MAINSP]] = distinct !DISubprogram(name: "main" +; CHECK: !{{[0-9]+}} = distinct !DICompileUnit({{.*}} subprograms: ![[SPs2:[0-9]+]] +; CHECK-NOT: ![[SPs2]] = !{{{.*}}null{{.*}}} +; CHECK: ![[SPs2]] = !{![[FUNCSP:[0-9]+]]} +; CHECK: ![[FUNCSP]] = distinct !DISubprogram(name: "func" +; CHECK-NOT: distinct !DISubprogram ; ModuleID = 'funcimport_debug.o' target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/test/Transforms/IPConstantProp/PR16052.ll b/test/Transforms/IPConstantProp/PR16052.ll new file mode 100644 index 0000000..959074d --- /dev/null +++ b/test/Transforms/IPConstantProp/PR16052.ll @@ -0,0 +1,26 @@ +; RUN: opt < %s -S -ipsccp | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i64 @fn2() { +entry: + %conv = sext i32 undef to i64 + %div = sdiv i64 8, %conv + %call2 = call i64 @fn1(i64 %div) + ret i64 %call2 +} + +; CHECK-DAG: define i64 @fn2( +; CHECK: %[[CALL:.*]] = call i64 @fn1(i64 undef) + +define internal i64 @fn1(i64 %p1) { +entry: + %tobool = icmp ne i64 %p1, 0 + %cond = select i1 %tobool, i64 %p1, i64 %p1 + ret i64 %cond +} + +; CHECK-DAG: define internal i64 @fn1( +; CHECK: %[[SEL:.*]] = select i1 undef, i64 undef, i64 undef +; CHECK: ret i64 %[[SEL]] diff --git a/test/Transforms/IPConstantProp/PR26044.ll b/test/Transforms/IPConstantProp/PR26044.ll new file mode 100644 index 0000000..9e8c61e --- /dev/null +++ b/test/Transforms/IPConstantProp/PR26044.ll @@ -0,0 +1,31 @@ +; RUN: opt < %s -S -ipsccp | 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 @fn2() { +entry: + br label %if.end + +for.cond1: ; preds = %if.end, %for.end + br i1 undef, label %if.end, label %if.end + +if.end: ; preds = %lbl, %for.cond1 + %e.2 = phi i32* [ undef, %entry ], [ null, %for.cond1 ], [ null, %for.cond1 ] + %0 = load i32, i32* %e.2, align 4 + %call = call i32 @fn1(i32 %0) + br label %for.cond1 +} + +define internal i32 @fn1(i32 %p1) { +entry: + %tobool = icmp ne i32 %p1, 0 + %cond = select i1 %tobool, i32 %p1, i32 %p1 + ret i32 %cond +} + +; CHECK-LABEL: define void @fn2( +; CHECK: call i32 @fn1(i32 undef) + +; CHECK-LABEL: define internal i32 @fn1( +; CHECK:%[[COND:.*]] = select i1 undef, i32 undef, i32 undef +; CHECK: ret i32 %[[COND]] diff --git a/test/Transforms/Inline/attributes.ll b/test/Transforms/Inline/attributes.ll index a97e6a6..0458fa2 100644 --- a/test/Transforms/Inline/attributes.ll +++ b/test/Transforms/Inline/attributes.ll @@ -160,3 +160,87 @@ define i32 @test_target_features1(i32 %i) "target-features"="+sse4.2" { ; CHECK-NEXT: @test_target_features_callee1 ; CHECK-NEXT: ret i32 } + +define i32 @less-precise-fpmad_callee0(i32 %i) "less-precise-fpmad"="false" { + ret i32 %i +; CHECK: @less-precise-fpmad_callee0(i32 %i) [[FPMAD_FALSE:#[0-9]+]] { +; CHECK-NEXT: ret i32 +} + +define i32 @less-precise-fpmad_callee1(i32 %i) "less-precise-fpmad"="true" { + ret i32 %i +; CHECK: @less-precise-fpmad_callee1(i32 %i) [[FPMAD_TRUE:#[0-9]+]] { +; CHECK-NEXT: ret i32 +} + +define i32 @test_less-precise-fpmad0(i32 %i) "less-precise-fpmad"="false" { + %1 = call i32 @less-precise-fpmad_callee0(i32 %i) + ret i32 %1 +; CHECK: @test_less-precise-fpmad0(i32 %i) [[FPMAD_FALSE]] { +; CHECK-NEXT: ret i32 +} + +define i32 @test_less-precise-fpmad1(i32 %i) "less-precise-fpmad"="false" { + %1 = call i32 @less-precise-fpmad_callee1(i32 %i) + ret i32 %1 +; CHECK: @test_less-precise-fpmad1(i32 %i) [[FPMAD_FALSE]] { +; CHECK-NEXT: ret i32 +} + +define i32 @test_less-precise-fpmad2(i32 %i) "less-precise-fpmad"="true" { + %1 = call i32 @less-precise-fpmad_callee0(i32 %i) + ret i32 %1 +; CHECK: @test_less-precise-fpmad2(i32 %i) [[FPMAD_FALSE]] { +; CHECK-NEXT: ret i32 +} + +define i32 @test_less-precise-fpmad3(i32 %i) "less-precise-fpmad"="true" { + %1 = call i32 @less-precise-fpmad_callee1(i32 %i) + ret i32 %1 +; CHECK: @test_less-precise-fpmad3(i32 %i) [[FPMAD_TRUE]] { +; CHECK-NEXT: ret i32 +} + +define i32 @no-implicit-float_callee0(i32 %i) { + ret i32 %i +; CHECK: @no-implicit-float_callee0(i32 %i) { +; CHECK-NEXT: ret i32 +} + +define i32 @no-implicit-float_callee1(i32 %i) noimplicitfloat { + ret i32 %i +; CHECK: @no-implicit-float_callee1(i32 %i) [[NOIMPLICITFLOAT:#[0-9]+]] { +; CHECK-NEXT: ret i32 +} + +define i32 @test_no-implicit-float0(i32 %i) { + %1 = call i32 @no-implicit-float_callee0(i32 %i) + ret i32 %1 +; CHECK: @test_no-implicit-float0(i32 %i) { +; CHECK-NEXT: ret i32 +} + +define i32 @test_no-implicit-float1(i32 %i) { + %1 = call i32 @no-implicit-float_callee1(i32 %i) + ret i32 %1 +; CHECK: @test_no-implicit-float1(i32 %i) [[NOIMPLICITFLOAT]] { +; CHECK-NEXT: ret i32 +} + +define i32 @test_no-implicit-float2(i32 %i) noimplicitfloat { + %1 = call i32 @no-implicit-float_callee0(i32 %i) + ret i32 %1 +; CHECK: @test_no-implicit-float2(i32 %i) [[NOIMPLICITFLOAT]] { +; CHECK-NEXT: ret i32 +} + +define i32 @test_no-implicit-float3(i32 %i) noimplicitfloat { + %1 = call i32 @no-implicit-float_callee1(i32 %i) + ret i32 %1 +; CHECK: @test_no-implicit-float3(i32 %i) [[NOIMPLICITFLOAT]] { +; CHECK-NEXT: ret i32 +} + +; CHECK: attributes [[FPMAD_FALSE]] = { "less-precise-fpmad"="false" } +; CHECK: attributes [[FPMAD_TRUE]] = { "less-precise-fpmad"="true" } +; CHECK: attributes [[NOIMPLICITFLOAT]] = { noimplicitfloat } diff --git a/test/Transforms/InstCombine/fast-math.ll b/test/Transforms/InstCombine/fast-math.ll index 5bdf48b..6ccf6e9 100644 --- a/test/Transforms/InstCombine/fast-math.ll +++ b/test/Transforms/InstCombine/fast-math.ll @@ -555,18 +555,12 @@ define float @fact_div6(float %x) { ; A squared factor fed into a square root intrinsic should be hoisted out ; as a fabs() value. -; We have to rely on a function-level attribute to enable this optimization -; because intrinsics don't currently have access to IR-level fast-math -; flags. If that changes, we can relax the requirement on all of these -; tests to just specify 'fast' on the sqrt. - -attributes #0 = { "unsafe-fp-math" = "true" } declare double @llvm.sqrt.f64(double) -define double @sqrt_intrinsic_arg_squared(double %x) #0 { +define double @sqrt_intrinsic_arg_squared(double %x) { %mul = fmul fast double %x, %x - %sqrt = call double @llvm.sqrt.f64(double %mul) + %sqrt = call fast double @llvm.sqrt.f64(double %mul) ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_arg_squared( @@ -577,10 +571,10 @@ define double @sqrt_intrinsic_arg_squared(double %x) #0 { ; Check all 6 combinations of a 3-way multiplication tree where ; one factor is repeated. -define double @sqrt_intrinsic_three_args1(double %x, double %y) #0 { +define double @sqrt_intrinsic_three_args1(double %x, double %y) { %mul = fmul fast double %y, %x %mul2 = fmul fast double %mul, %x - %sqrt = call double @llvm.sqrt.f64(double %mul2) + %sqrt = call fast double @llvm.sqrt.f64(double %mul2) ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_three_args1( @@ -590,10 +584,10 @@ define double @sqrt_intrinsic_three_args1(double %x, double %y) #0 { ; CHECK-NEXT: ret double %1 } -define double @sqrt_intrinsic_three_args2(double %x, double %y) #0 { +define double @sqrt_intrinsic_three_args2(double %x, double %y) { %mul = fmul fast double %x, %y %mul2 = fmul fast double %mul, %x - %sqrt = call double @llvm.sqrt.f64(double %mul2) + %sqrt = call fast double @llvm.sqrt.f64(double %mul2) ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_three_args2( @@ -603,10 +597,10 @@ define double @sqrt_intrinsic_three_args2(double %x, double %y) #0 { ; CHECK-NEXT: ret double %1 } -define double @sqrt_intrinsic_three_args3(double %x, double %y) #0 { +define double @sqrt_intrinsic_three_args3(double %x, double %y) { %mul = fmul fast double %x, %x %mul2 = fmul fast double %mul, %y - %sqrt = call double @llvm.sqrt.f64(double %mul2) + %sqrt = call fast double @llvm.sqrt.f64(double %mul2) ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_three_args3( @@ -616,10 +610,10 @@ define double @sqrt_intrinsic_three_args3(double %x, double %y) #0 { ; CHECK-NEXT: ret double %1 } -define double @sqrt_intrinsic_three_args4(double %x, double %y) #0 { +define double @sqrt_intrinsic_three_args4(double %x, double %y) { %mul = fmul fast double %y, %x %mul2 = fmul fast double %x, %mul - %sqrt = call double @llvm.sqrt.f64(double %mul2) + %sqrt = call fast double @llvm.sqrt.f64(double %mul2) ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_three_args4( @@ -629,10 +623,10 @@ define double @sqrt_intrinsic_three_args4(double %x, double %y) #0 { ; CHECK-NEXT: ret double %1 } -define double @sqrt_intrinsic_three_args5(double %x, double %y) #0 { +define double @sqrt_intrinsic_three_args5(double %x, double %y) { %mul = fmul fast double %x, %y %mul2 = fmul fast double %x, %mul - %sqrt = call double @llvm.sqrt.f64(double %mul2) + %sqrt = call fast double @llvm.sqrt.f64(double %mul2) ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_three_args5( @@ -642,10 +636,10 @@ define double @sqrt_intrinsic_three_args5(double %x, double %y) #0 { ; CHECK-NEXT: ret double %1 } -define double @sqrt_intrinsic_three_args6(double %x, double %y) #0 { +define double @sqrt_intrinsic_three_args6(double %x, double %y) { %mul = fmul fast double %x, %x %mul2 = fmul fast double %y, %mul - %sqrt = call double @llvm.sqrt.f64(double %mul2) + %sqrt = call fast double @llvm.sqrt.f64(double %mul2) ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_three_args6( @@ -655,10 +649,25 @@ define double @sqrt_intrinsic_three_args6(double %x, double %y) #0 { ; CHECK-NEXT: ret double %1 } -define double @sqrt_intrinsic_arg_4th(double %x) #0 { +; If any operation is not 'fast', we can't simplify. + +define double @sqrt_intrinsic_not_so_fast(double %x, double %y) { + %mul = fmul double %x, %x + %mul2 = fmul fast double %mul, %y + %sqrt = call fast double @llvm.sqrt.f64(double %mul2) + ret double %sqrt + +; CHECK-LABEL: sqrt_intrinsic_not_so_fast( +; CHECK-NEXT: %mul = fmul double %x, %x +; CHECK-NEXT: %mul2 = fmul fast double %mul, %y +; CHECK-NEXT: %sqrt = call fast double @llvm.sqrt.f64(double %mul2) +; CHECK-NEXT: ret double %sqrt +} + +define double @sqrt_intrinsic_arg_4th(double %x) { %mul = fmul fast double %x, %x %mul2 = fmul fast double %mul, %mul - %sqrt = call double @llvm.sqrt.f64(double %mul2) + %sqrt = call fast double @llvm.sqrt.f64(double %mul2) ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_arg_4th( @@ -666,11 +675,11 @@ define double @sqrt_intrinsic_arg_4th(double %x) #0 { ; CHECK-NEXT: ret double %mul } -define double @sqrt_intrinsic_arg_5th(double %x) #0 { +define double @sqrt_intrinsic_arg_5th(double %x) { %mul = fmul fast double %x, %x %mul2 = fmul fast double %mul, %x %mul3 = fmul fast double %mul2, %mul - %sqrt = call double @llvm.sqrt.f64(double %mul3) + %sqrt = call fast double @llvm.sqrt.f64(double %mul3) ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_arg_5th( @@ -686,9 +695,9 @@ declare float @sqrtf(float) declare double @sqrt(double) declare fp128 @sqrtl(fp128) -define float @sqrt_call_squared_f32(float %x) #0 { +define float @sqrt_call_squared_f32(float %x) { %mul = fmul fast float %x, %x - %sqrt = call float @sqrtf(float %mul) + %sqrt = call fast float @sqrtf(float %mul) ret float %sqrt ; CHECK-LABEL: sqrt_call_squared_f32( @@ -696,9 +705,9 @@ define float @sqrt_call_squared_f32(float %x) #0 { ; CHECK-NEXT: ret float %fabs } -define double @sqrt_call_squared_f64(double %x) #0 { +define double @sqrt_call_squared_f64(double %x) { %mul = fmul fast double %x, %x - %sqrt = call double @sqrt(double %mul) + %sqrt = call fast double @sqrt(double %mul) ret double %sqrt ; CHECK-LABEL: sqrt_call_squared_f64( @@ -706,9 +715,9 @@ define double @sqrt_call_squared_f64(double %x) #0 { ; CHECK-NEXT: ret double %fabs } -define fp128 @sqrt_call_squared_f128(fp128 %x) #0 { +define fp128 @sqrt_call_squared_f128(fp128 %x) { %mul = fmul fast fp128 %x, %x - %sqrt = call fp128 @sqrtl(fp128 %mul) + %sqrt = call fast fp128 @sqrtl(fp128 %mul) ret fp128 %sqrt ; CHECK-LABEL: sqrt_call_squared_f128( diff --git a/test/Transforms/InstCombine/inline-intrinsic-assert.ll b/test/Transforms/InstCombine/inline-intrinsic-assert.ll index c6446d4..8eecb3f 100644 --- a/test/Transforms/InstCombine/inline-intrinsic-assert.ll +++ b/test/Transforms/InstCombine/inline-intrinsic-assert.ll @@ -4,7 +4,7 @@ ; The inliner should not add an edge to an intrinsic and ; then assert that it did not add an edge to an intrinsic! -define float @foo(float %f1) #0 { +define float @foo(float %f1) { %call = call float @bar(float %f1) ret float %call @@ -13,18 +13,16 @@ define float @foo(float %f1) #0 { ; CHECK-NEXT: ret float } -define float @bar(float %f1) #0 { +define float @bar(float %f1) { %call = call float @sqr(float %f1) - %call1 = call float @sqrtf(float %call) #0 + %call1 = call fast float @sqrtf(float %call) ret float %call1 } -define float @sqr(float %f) #0 { +define float @sqr(float %f) { %mul = fmul fast float %f, %f ret float %mul } -declare float @sqrtf(float) #0 - -attributes #0 = { "unsafe-fp-math"="true" } +declare float @sqrtf(float) diff --git a/test/Transforms/InstCombine/insert-extract-shuffle.ll b/test/Transforms/InstCombine/insert-extract-shuffle.ll index 4223660..47c2a13 100644 --- a/test/Transforms/InstCombine/insert-extract-shuffle.ll +++ b/test/Transforms/InstCombine/insert-extract-shuffle.ll @@ -125,3 +125,53 @@ end: ret <8 x i16> %t6 } +; The widening shuffle must be inserted at a valid point (after the PHIs). + +define <4 x double> @pr25999_phis1(i1 %c, <2 x double> %a, <4 x double> %b) { +; CHECK-LABEL: @pr25999_phis1( +; CHECK: %tmp1 = phi <2 x double> [ %a, %bb1 ], [ %r, %bb2 ] +; CHECK-NEXT: %tmp2 = phi <4 x double> [ %b, %bb1 ], [ zeroinitializer, %bb2 ] +; CHECK-NEXT: %[[WIDEVEC:.*]] = shufflevector <2 x double> %tmp1, <2 x double> undef, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef> +; CHECK-NEXT: %tmp4 = shufflevector <4 x double> %tmp2, <4 x double> %[[WIDEVEC]], <4 x i32> <i32 0, i32 1, i32 4, i32 3> +; CHECK-NEXT: ret <4 x double> %tmp4 +bb1: + br i1 %c, label %bb2, label %bb3 + +bb2: + %r = call <2 x double> @dummy(<2 x double> %a) + br label %bb3 + +bb3: + %tmp1 = phi <2 x double> [ %a, %bb1 ], [ %r, %bb2 ] + %tmp2 = phi <4 x double> [ %b, %bb1 ], [ zeroinitializer, %bb2 ] + %tmp3 = extractelement <2 x double> %tmp1, i32 0 + %tmp4 = insertelement <4 x double> %tmp2, double %tmp3, i32 2 + ret <4 x double> %tmp4 +} + +declare <2 x double> @dummy(<2 x double>) + +define <4 x double> @pr25999_phis2(i1 %c, <2 x double> %a, <4 x double> %b) { +; CHECK-LABEL: @pr25999_phis2( +; CHECK: %tmp1 = phi <2 x double> [ %a, %bb1 ], [ %r, %bb2 ] +; CHECK-NEXT: %tmp2 = phi <4 x double> [ %b, %bb1 ], [ zeroinitializer, %bb2 ] +; CHECK-NEXT: %d = fadd <2 x double> %tmp1, %tmp1 +; CHECK-NEXT: %[[WIDEVEC:.*]] = shufflevector <2 x double> %d, <2 x double> undef, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef> +; CHECK-NEXT: %tmp4 = shufflevector <4 x double> %tmp2, <4 x double> %[[WIDEVEC]], <4 x i32> <i32 0, i32 1, i32 4, i32 3> +; CHECK-NEXT: ret <4 x double> %tmp4 +bb1: + br i1 %c, label %bb2, label %bb3 + +bb2: + %r = call <2 x double> @dummy(<2 x double> %a) + br label %bb3 + +bb3: + %tmp1 = phi <2 x double> [ %a, %bb1 ], [ %r, %bb2 ] + %tmp2 = phi <4 x double> [ %b, %bb1 ], [ zeroinitializer, %bb2 ] + %d = fadd <2 x double> %tmp1, %tmp1 + %tmp3 = extractelement <2 x double> %d, i32 0 + %tmp4 = insertelement <4 x double> %tmp2, double %tmp3, i32 2 + ret <4 x double> %tmp4 +} + diff --git a/test/Transforms/InstCombine/log-pow.ll b/test/Transforms/InstCombine/log-pow.ll index c5ca168..a0c10d0 100644 --- a/test/Transforms/InstCombine/log-pow.ll +++ b/test/Transforms/InstCombine/log-pow.ll @@ -1,41 +1,61 @@ ; RUN: opt < %s -instcombine -S | FileCheck %s -define double @mylog(double %x, double %y) #0 { -entry: +define double @log_pow(double %x, double %y) { + %pow = call fast double @llvm.pow.f64(double %x, double %y) + %call = call fast double @log(double %pow) + ret double %call +} + +; CHECK-LABEL: define double @log_pow( +; CHECK-NEXT: %log = call fast double @log(double %x) +; CHECK-NEXT: %mul = fmul fast double %log, %y +; CHECK-NEXT: ret double %mul + +define double @log_pow_not_fast(double %x, double %y) { %pow = call double @llvm.pow.f64(double %x, double %y) - %call = call double @log(double %pow) #0 + %call = call fast double @log(double %pow) ret double %call } -; CHECK-LABEL: define double @mylog( -; CHECK: %log = call fast double @log(double %x) #0 -; CHECK: %mul = fmul fast double %log, %y -; CHECK: ret double %mul -; CHECK: } +; CHECK-LABEL: define double @log_pow_not_fast( +; CHECK-NEXT: %pow = call double @llvm.pow.f64(double %x, double %y) +; CHECK-NEXT: %call = call fast double @log(double %pow) +; CHECK-NEXT: ret double %call -define double @test2(double ()* %fptr, double %p1) #0 { +define double @function_pointer(double ()* %fptr, double %p1) { %call1 = call double %fptr() %pow = call double @log(double %call1) ret double %pow } -; CHECK-LABEL: @test2 -; CHECK: log +; CHECK-LABEL: @function_pointer +; CHECK-NEXT: %call1 = call double %fptr() +; CHECK-NEXT: %pow = call double @log(double %call1) +; CHECK-NEXT: ret double %pow + +define double @log_exp2(double %x) { + %call2 = call fast double @exp2(double %x) + %call3 = call fast double @log(double %call2) + ret double %call3 +} + +; CHECK-LABEL: @log_exp2 +; CHECK-NEXT: %call2 = call fast double @exp2(double %x) +; CHECK-NEXT: %logmul = fmul fast double %x, 0x3FE62E42FEFA39EF +; CHECK-NEXT: ret double %logmul -define double @test3(double %x) #0 { - %call2 = call double @exp2(double %x) #0 - %call3 = call double @log(double %call2) #0 +define double @log_exp2_not_fast(double %x) { + %call2 = call double @exp2(double %x) + %call3 = call fast double @log(double %call2) ret double %call3 } -; CHECK-LABEL: @test3 -; CHECK: %call2 = call double @exp2(double %x) #0 -; CHECK: %logmul = fmul fast double %x, 0x3FE62E42FEFA39EF -; CHECK: ret double %logmul -; CHECK: } +; CHECK-LABEL: @log_exp2_not_fast +; CHECK-NEXT: %call2 = call double @exp2(double %x) +; CHECK-NEXT: %call3 = call fast double @log(double %call2) +; CHECK-NEXT: ret double %call3 -declare double @log(double) #0 -declare double @exp2(double) #0 +declare double @log(double) +declare double @exp2(double) declare double @llvm.pow.f64(double, double) -attributes #0 = { "unsafe-fp-math"="true" } diff --git a/test/Transforms/InstCombine/no_cgscc_assert.ll b/test/Transforms/InstCombine/no_cgscc_assert.ll index 3df04d2..677066f 100644 --- a/test/Transforms/InstCombine/no_cgscc_assert.ll +++ b/test/Transforms/InstCombine/no_cgscc_assert.ll @@ -6,7 +6,7 @@ define float @bar(float %f) #0 { %mul = fmul fast float %f, %f - %call1 = call float @sqrtf(float %mul) #0 + %call1 = call fast float @sqrtf(float %mul) ret float %call1 ; CHECK-LABEL: @bar( @@ -14,6 +14,5 @@ define float @bar(float %f) #0 { ; CHECK-NEXT: ret float } -declare float @sqrtf(float) #0 +declare float @sqrtf(float) -attributes #0 = { readnone "unsafe-fp-math"="true" } diff --git a/test/Transforms/InstCombine/pow-exp.ll b/test/Transforms/InstCombine/pow-exp.ll index acc5127..594594a 100644 --- a/test/Transforms/InstCombine/pow-exp.ll +++ b/test/Transforms/InstCombine/pow-exp.ll @@ -1,28 +1,49 @@ ; RUN: opt < %s -instcombine -S | FileCheck %s -define double @mypow(double %x, double %y) #0 { -entry: +define double @pow_exp(double %x, double %y) { + %call = call fast double @exp(double %x) nounwind readnone + %pow = call fast double @llvm.pow.f64(double %call, double %y) + ret double %pow +} + +; CHECK-LABEL: define double @pow_exp( +; CHECK-NEXT: %mul = fmul fast double %x, %y +; CHECK-NEXT: %exp = call fast double @exp(double %mul) +; CHECK-NEXT: ret double %exp + +define double @pow_exp2(double %x, double %y) { + %call = call fast double @exp2(double %x) nounwind readnone + %pow = call fast double @llvm.pow.f64(double %call, double %y) + ret double %pow +} + +; CHECK-LABEL: define double @pow_exp2( +; CHECK-NEXT: %mul = fmul fast double %x, %y +; CHECK-NEXT: %exp2 = call fast double @exp2(double %mul) +; CHECK-NEXT: ret double %exp2 + +define double @pow_exp_not_fast(double %x, double %y) { %call = call double @exp(double %x) - %pow = call double @llvm.pow.f64(double %call, double %y) + %pow = call fast double @llvm.pow.f64(double %call, double %y) ret double %pow } -; CHECK-LABEL: define double @mypow( -; CHECK: %mul = fmul fast double %x, %y -; CHECK: %exp = call fast double @exp(double %mul) #0 -; CHECK: ret double %exp -; CHECK: } +; CHECK-LABEL: define double @pow_exp_not_fast( +; CHECK-NEXT: %call = call double @exp(double %x) +; CHECK-NEXT: %pow = call fast double @llvm.pow.f64(double %call, double %y) +; CHECK-NEXT: ret double %pow -define double @test2(double ()* %fptr, double %p1) #0 { - %call1 = call double %fptr() - %pow = call double @llvm.pow.f64(double %call1, double %p1) +define double @function_pointer(double ()* %fptr, double %p1) { + %call1 = call fast double %fptr() + %pow = call fast double @llvm.pow.f64(double %call1, double %p1) ret double %pow } -; CHECK-LABEL: @test2 -; CHECK: llvm.pow.f64 +; CHECK-LABEL: @function_pointer +; CHECK-NEXT: %call1 = call fast double %fptr() +; CHECK-NEXT: %pow = call fast double @llvm.pow.f64(double %call1, double %p1) -declare double @exp(double) #1 +declare double @exp(double) +declare double @exp2(double) declare double @llvm.pow.f64(double, double) -attributes #0 = { "unsafe-fp-math"="true" } -attributes #1 = { "unsafe-fp-math"="true" } + diff --git a/test/Transforms/InstCombine/pow-exp2.ll b/test/Transforms/InstCombine/pow-exp2.ll deleted file mode 100644 index c42cab3..0000000 --- a/test/Transforms/InstCombine/pow-exp2.ll +++ /dev/null @@ -1,19 +0,0 @@ -; RUN: opt < %s -instcombine -S | FileCheck %s - -define double @mypow(double %x, double %y) #0 { -entry: - %call = call double @exp2(double %x) - %pow = call double @llvm.pow.f64(double %call, double %y) - ret double %pow -} - -; CHECK-LABEL: define double @mypow( -; CHECK: %mul = fmul fast double %x, %y -; CHECK: %exp2 = call fast double @exp2(double %mul) #0 -; CHECK: ret double %exp2 -; CHECK: } - -declare double @exp2(double) #1 -declare double @llvm.pow.f64(double, double) -attributes #0 = { "unsafe-fp-math"="true" } -attributes #1 = { "unsafe-fp-math"="true" } diff --git a/test/Transforms/InstCombine/pow-sqrt.ll b/test/Transforms/InstCombine/pow-sqrt.ll index 8fc74e4..1e6166c 100644 --- a/test/Transforms/InstCombine/pow-sqrt.ll +++ b/test/Transforms/InstCombine/pow-sqrt.ll @@ -1,15 +1,13 @@ ; RUN: opt < %s -instcombine -S | FileCheck %s -define double @mypow(double %x) #0 { -entry: - %pow = call double @llvm.pow.f64(double %x, double 5.000000e-01) +define double @pow_half(double %x) { + %pow = call fast double @llvm.pow.f64(double %x, double 5.000000e-01) ret double %pow } -; CHECK-LABEL: define double @mypow( -; CHECK: %sqrt = call double @sqrt(double %x) #1 -; CHECK: ret double %sqrt -; CHECK: } +; CHECK-LABEL: define double @pow_half( +; CHECK-NEXT: %sqrt = call fast double @sqrt(double %x) +; CHECK-NEXT: ret double %sqrt declare double @llvm.pow.f64(double, double) -attributes #0 = { "unsafe-fp-math"="true" } + diff --git a/test/Transforms/InstCombine/printf-3.ll b/test/Transforms/InstCombine/printf-3.ll new file mode 100644 index 0000000..8f3a36a --- /dev/null +++ b/test/Transforms/InstCombine/printf-3.ll @@ -0,0 +1,39 @@ +; Test that the printf library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc18.0.0" + +@.str = private unnamed_addr constant [2 x i8] c"\0A\00", align 1 + +define void @test1() personality i32 (...)* @__CxxFrameHandler3 { +entry: + invoke void @_CxxThrowException(i8* null, i8* null) + to label %unreachable unwind label %catch.dispatch + +catch.dispatch: + %cs = catchswitch within none [label %catch] unwind to caller + +catch: + %cp = catchpad within %cs [i8* null, i32 64, i8* null] + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0)) [ "funclet"(token %cp) ] + catchret from %cp to label %try.cont + +try.cont: + ret void + +unreachable: + unreachable +} + +; CHECK-DAG: define void @test1( +; CHECK: %[[CS:.*]] = catchswitch within none +; CHECK: %[[CP:.*]] = catchpad within %[[CS]] [i8* null, i32 64, i8* null] +; CHECK: call i32 @putchar(i32 10) [ "funclet"(token %[[CP]]) ] + +declare void @_CxxThrowException(i8*, i8*) + +declare i32 @__CxxFrameHandler3(...) + +declare i32 @printf(i8*, ...) diff --git a/test/Transforms/InstCombine/tan.ll b/test/Transforms/InstCombine/tan.ll index 15a832f..6ea1168 100644 --- a/test/Transforms/InstCombine/tan.ll +++ b/test/Transforms/InstCombine/tan.ll @@ -1,24 +1,23 @@ ; RUN: opt < %s -instcombine -S | FileCheck %s -define float @mytan(float %x) #0 { -entry: - %call = call float @atanf(float %x) - %call1 = call float @tanf(float %call) +define float @mytan(float %x) { + %call = call fast float @atanf(float %x) + %call1 = call fast float @tanf(float %call) ret float %call1 } ; CHECK-LABEL: define float @mytan( ; CHECK: ret float %x -define float @test2(float ()* %fptr) #0 { - %call1 = call float %fptr() - %tan = call float @tanf(float %call1) +define float @test2(float ()* %fptr) { + %call1 = call fast float %fptr() + %tan = call fast float @tanf(float %call1) ret float %tan } ; CHECK-LABEL: @test2 ; CHECK: tanf -declare float @tanf(float) #0 -declare float @atanf(float) #0 -attributes #0 = { "unsafe-fp-math"="true" } +declare float @tanf(float) +declare float @atanf(float) + diff --git a/test/Transforms/InstSimplify/floating-point-compare.ll b/test/Transforms/InstSimplify/floating-point-compare.ll index 8174f58..b148d99 100644 --- a/test/Transforms/InstSimplify/floating-point-compare.ll +++ b/test/Transforms/InstSimplify/floating-point-compare.ll @@ -8,6 +8,8 @@ declare float @llvm.fabs.f32(float) declare float @llvm.sqrt.f32(float) declare double @llvm.powi.f64(double,i32) declare float @llvm.exp.f32(float) +declare float @llvm.minnum.f32(float, float) +declare float @llvm.maxnum.f32(float, float) declare double @llvm.exp2.f64(double) declare float @llvm.fma.f32(float,float,float) @@ -58,6 +60,45 @@ define i1 @orderedLessZeroPowi(double,double) { ret i1 %olt } +; CHECK-LABEL: @orderedLessZeroUIToFP( +define i1 @orderedLessZeroUIToFP(i32) { + %a = uitofp i32 %0 to float + %uge = fcmp uge float %a, 0.000000e+00 +; CHECK: ret i1 true + ret i1 %uge +} + +; CHECK-LABEL: @orderedLessZeroSelect( +define i1 @orderedLessZeroSelect(float, float) { + %a = call float @llvm.exp.f32(float %0) + %b = call float @llvm.fabs.f32(float %1) + %c = fcmp olt float %0, %1 + %d = select i1 %c, float %a, float %b + %e = fadd float %d, 1.0 + %uge = fcmp uge float %e, 0.000000e+00 +; CHECK: ret i1 true + ret i1 %uge +} + +; CHECK-LABEL: @orderedLessZeroMinNum( +define i1 @orderedLessZeroMinNum(float, float) { + %a = call float @llvm.exp.f32(float %0) + %b = call float @llvm.fabs.f32(float %1) + %c = call float @llvm.minnum.f32(float %a, float %b) + %uge = fcmp uge float %c, 0.000000e+00 +; CHECK: ret i1 true + ret i1 %uge +} + +; CHECK-LABEL: @orderedLessZeroMaxNum( +define i1 @orderedLessZeroMaxNum(float, float) { + %a = call float @llvm.exp.f32(float %0) + %b = call float @llvm.maxnum.f32(float %a, float %1) + %uge = fcmp uge float %b, 0.000000e+00 +; CHECK: ret i1 true + ret i1 %uge +} + define i1 @nonans1(double %in1, double %in2) { %cmp = fcmp nnan uno double %in1, %in2 ret i1 %cmp diff --git a/test/Transforms/JumpThreading/pr26096.ll b/test/Transforms/JumpThreading/pr26096.ll new file mode 100644 index 0000000..2671e82 --- /dev/null +++ b/test/Transforms/JumpThreading/pr26096.ll @@ -0,0 +1,68 @@ +; RUN: opt -prune-eh -inline -jump-threading -S < %s | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@d = external global i32*, align 8 + +define void @fn3(i1 %B) { +entry: + br i1 %B, label %if.end, label %if.then + +if.then: ; preds = %entry + call void @fn2() + ret void + +if.end: ; preds = %entry + call void @fn2() + ret void +} + +define internal void @fn2() unnamed_addr { +entry: + call void @fn1() + call void @fn1() + call void @fn1() + unreachable +} + +; CHECK-LABEL: define internal void @fn2( +; CHECK: %[[LOAD:.*]] = load i32*, i32** @d, align 8 +; CHECK: %tobool1.i = icmp eq i32* %[[LOAD]], null + +define internal void @fn1() unnamed_addr { +entry: + br label %for.body + +for.body: ; preds = %entry + %0 = load i32*, i32** @d, align 8 + %tobool1 = icmp eq i32* %0, null + br i1 %tobool1, label %cond.false, label %cond.end + +cond.false: ; preds = %for.body + call void @__assert_fail(i8* null) + unreachable + +cond.end: ; preds = %for.body + %1 = load i32*, i32** @d, align 8 + %cmp = icmp eq i32* %1, null + br i1 %cmp, label %cond.end4, label %cond.false3 + +cond.false3: ; preds = %cond.end + call void @__assert_fail(i8* null) + unreachable + +cond.end4: ; preds = %cond.end + call void @__assert_fail(i8* null) + unreachable + +for.end: ; No predecessors! + ret void +} + +declare void @__assert_fail(i8*) + +; Function Attrs: noreturn nounwind +declare void @llvm.trap() #0 + +attributes #0 = { noreturn nounwind } diff --git a/test/Transforms/JumpThreading/select.ll b/test/Transforms/JumpThreading/select.ll index 595cacb..6a3cf7e 100644 --- a/test/Transforms/JumpThreading/select.ll +++ b/test/Transforms/JumpThreading/select.ll @@ -250,3 +250,40 @@ if.end: ; preds = %if.then, %cond.end4 ; CHECK: br i1 %cmp6, label %if.then, label %if.end ; CHECK: br label %if.end } + + +define i32 @unfold3(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind { +entry: + %add3 = add nsw i32 %j, 2 + %cmp.i = icmp slt i32 %u, %v + br i1 %cmp.i, label %.exit, label %cond.false.i + +cond.false.i: ; preds = %entry + %cmp4.i = icmp sgt i32 %u, %v + br i1 %cmp4.i, label %.exit, label %cond.false.6.i + +cond.false.6.i: ; preds = %cond.false.i + %cmp8.i = icmp slt i32 %w, %x + br i1 %cmp8.i, label %.exit, label %cond.false.10.i + +cond.false.10.i: ; preds = %cond.false.6.i + %cmp13.i = icmp sgt i32 %w, %x + br i1 %cmp13.i, label %.exit, label %cond.false.15.i + +cond.false.15.i: ; preds = %cond.false.10.i + %phitmp = icmp sge i32 %y, %z + br label %.exit + +.exit: ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i + %cond23.i = phi i1 [ false, %entry ], [ true, %cond.false.i ], [ false, %cond.false.6.i ], [ %phitmp, %cond.false.15.i ], [ true, %cond.false.10.i ] + %j.add3 = select i1 %cond23.i, i32 %j, i32 %add3 + ret i32 %j.add3 + +; CHECK-LABEL: @unfold3 +; CHECK: br i1 %cmp.i, label %.exit.thread2, label %cond.false.i +; CHECK: br i1 %cmp4.i, label %.exit.thread, label %cond.false.6.i +; CHECK: br i1 %cmp8.i, label %.exit.thread2, label %cond.false.10.i +; CHECK: br i1 %cmp13.i, label %.exit.thread, label %.exit +; CHECK: br i1 %phitmp, label %.exit.thread, label %.exit.thread2 +; CHECK: br label %.exit.thread2 +} diff --git a/test/Transforms/LoopUnroll/partial-unroll-optsize.ll b/test/Transforms/LoopUnroll/partial-unroll-optsize.ll index a650317..e5e0151 100644 --- a/test/Transforms/LoopUnroll/partial-unroll-optsize.ll +++ b/test/Transforms/LoopUnroll/partial-unroll-optsize.ll @@ -1,4 +1,6 @@ ; RUN: opt < %s -S -loop-unroll -unroll-allow-partial | FileCheck %s +; RUN: sed -e 's/optsize/minsize/' %s | opt -S -loop-unroll -unroll-allow-partial | FileCheck %s + ; Loop size = 3, when the function has the optsize attribute, the ; OptSizeUnrollThreshold, i.e. 50, is used, hence the loop should be unrolled ; by 32 times because (1 * 32) + 2 < 50 (whereas (1 * 64 + 2) is not). @@ -49,4 +51,3 @@ exit: ; CHECK-NEXT: add ; CHECK-NEXT: add ; CHECK-NEXT: icmp - diff --git a/test/Transforms/LoopUnroll/unloop.ll b/test/Transforms/LoopUnroll/unloop.ll index b98b4a3..720b2ae 100644 --- a/test/Transforms/LoopUnroll/unloop.ll +++ b/test/Transforms/LoopUnroll/unloop.ll @@ -1,6 +1,6 @@ ; RUN: opt < %s -S -loop-unroll -verify-loop-info | FileCheck %s ; -; Unit tests for LoopInfo::updateUnloop. +; Unit tests for LoopInfo::markAsRemoved. declare i1 @check() nounwind diff --git a/test/Transforms/MemCpyOpt/fca2memcpy.ll b/test/Transforms/MemCpyOpt/fca2memcpy.ll index 75a1a8f..c8a1268 100644 --- a/test/Transforms/MemCpyOpt/fca2memcpy.ll +++ b/test/Transforms/MemCpyOpt/fca2memcpy.ll @@ -3,7 +3,7 @@ target datalayout = "e-i64:64-f80:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" -%S = type { i8*, i32 } +%S = type { i8*, i8, i32 } define void @copy(%S* %src, %S* %dst) { ; CHECK-LABEL: copy @@ -37,8 +37,10 @@ define void @noaliasdst(%S* %src, %S* noalias %dst) { define void @destroysrc(%S* %src, %S* %dst) { ; CHECK-LABEL: destroysrc -; CHECK-NOT: call -; CHECK: ret void +; CHECK: load %S, %S* %src +; CHECK: call void @llvm.memset.p0i8.i64 +; CHECK-NEXT: store %S %1, %S* %dst +; CHECK-NEXT: ret void %1 = load %S, %S* %src store %S zeroinitializer, %S* %src store %S %1, %S* %dst @@ -49,7 +51,7 @@ define void @destroynoaliassrc(%S* noalias %src, %S* %dst) { ; CHECK-LABEL: destroynoaliassrc ; CHECK-NOT: load ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 -; CHECK-NEXT: store %S zeroinitializer, %S* %src +; CHECK-NEXT: call void @llvm.memset.p0i8.i64 ; CHECK-NEXT: ret void %1 = load %S, %S* %src store %S zeroinitializer, %S* %src @@ -70,3 +72,17 @@ define void @copyalias(%S* %src, %S* %dst) { store %S %2, %S* %dst ret void } + + +; The GEP is present after the aliasing store, preventing to move the memcpy before +; (without further analysis/transformation) +define void @copyaliaswithproducerinbetween(%S* %src, %S* %dst) { +; CHECK-LABEL: copyalias +; CHECK-NEXT: [[LOAD:%[a-z0-9\.]+]] = load %S, %S* %src +; CHECK-NOT: call + %1 = load %S, %S* %src + store %S undef, %S* %dst + %dst2 = getelementptr %S , %S* %dst, i64 1 + store %S %1, %S* %dst2 + ret void +} diff --git a/test/Transforms/Reassociate/add_across_block_crash.ll b/test/Transforms/Reassociate/add_across_block_crash.ll new file mode 100644 index 0000000..07be752 --- /dev/null +++ b/test/Transforms/Reassociate/add_across_block_crash.ll @@ -0,0 +1,20 @@ +; RUN: opt < %s -reassociate -S | FileCheck %s +; CHECK-LABEL: main +; This test is to make sure while processing a block, uses of instructions +; from a different basic block don't get added to be re-optimized +define void @main() { +entry: + %0 = fadd fast float undef, undef + br i1 undef, label %bb1, label %bb2 + +bb1: + %1 = fmul fast float undef, -2.000000e+00 + %2 = fmul fast float %1, 2.000000e+00 + %3 = fadd fast float %2, 2.000000e+00 + %4 = fadd fast float %3, %0 + %mul351 = fmul fast float %4, 5.000000e-01 + ret void + +bb2: + ret void +} diff --git a/test/Transforms/RewriteStatepointsForGC/constants.ll b/test/Transforms/RewriteStatepointsForGC/constants.ll index b30f64b..0f600f2 100644 --- a/test/Transforms/RewriteStatepointsForGC/constants.ll +++ b/test/Transforms/RewriteStatepointsForGC/constants.ll @@ -92,4 +92,13 @@ use: ret i8 addrspace(1)* %res } - +; Globals don't move and thus don't get relocated +define i8 addrspace(1)* @test5(i1 %always_true) gc "statepoint-example" { +; CHECK-LABEL: @test5 +; CHECK: gc.statepoint +; CHECK-NEXT: %res = extractelement <2 x i8 addrspace(1)*> <i8 addrspace(1)* @G, i8 addrspace(1)* @G>, i32 0 +entry: + call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) + %res = extractelement <2 x i8 addrspace(1)*> <i8 addrspace(1)* @G, i8 addrspace(1)* @G>, i32 0 + ret i8 addrspace(1)* %res +} diff --git a/test/Transforms/RewriteStatepointsForGC/deopt-bundles/live-vector-nosplit.ll b/test/Transforms/RewriteStatepointsForGC/deopt-bundles/live-vector-nosplit.ll new file mode 100644 index 0000000..ee578eb --- /dev/null +++ b/test/Transforms/RewriteStatepointsForGC/deopt-bundles/live-vector-nosplit.ll @@ -0,0 +1,112 @@ +; Test that we can correctly handle vectors of pointers in statepoint +; rewriting. +; RUN: opt %s -rewrite-statepoints-for-gc -rs4gc-use-deopt-bundles -rs4gc-split-vector-values=0 -S | FileCheck %s + +; A non-vector relocation for comparison +define i64 addrspace(1)* @test(i64 addrspace(1)* %obj) gc "statepoint-example" { +; CHECK-LABEL: test +; CHECK: gc.statepoint +; CHECK-NEXT: gc.relocate +; CHECK-NEXT: bitcast +; CHECK-NEXT: ret i64 addrspace(1)* +; A base vector from a argument +entry: + call void @do_safepoint() [ "deopt"() ] + ret i64 addrspace(1)* %obj +} + +; A vector argument +define <2 x i64 addrspace(1)*> @test2(<2 x i64 addrspace(1)*> %obj) gc "statepoint-example" { +; CHECK-LABEL: test2 +; CHECK-NEXT: gc.statepoint +; CHECK-NEXT: gc.relocate +; CHECK-NEXT: bitcast +; CHECK-NEXT: ret <2 x i64 addrspace(1)*> + call void @do_safepoint() [ "deopt"() ] + ret <2 x i64 addrspace(1)*> %obj +} + +; A load +define <2 x i64 addrspace(1)*> @test3(<2 x i64 addrspace(1)*>* %ptr) gc "statepoint-example" { +; CHECK-LABEL: test3 +; CHECK: load +; CHECK-NEXT: gc.statepoint +; CHECK-NEXT: gc.relocate +; CHECK-NEXT: bitcast +; CHECK-NEXT: ret <2 x i64 addrspace(1)*> +entry: + %obj = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr + call void @do_safepoint() [ "deopt"() ] + ret <2 x i64 addrspace(1)*> %obj +} + +declare i32 @fake_personality_function() + +; When a statepoint is an invoke rather than a call +define <2 x i64 addrspace(1)*> @test4(<2 x i64 addrspace(1)*>* %ptr) gc "statepoint-example" personality i32 ()* @fake_personality_function { +; CHECK-LABEL: test4 +; CHECK: load +; CHECK-NEXT: gc.statepoint +entry: + %obj = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr + invoke void @do_safepoint() [ "deopt"() ] + to label %normal_return unwind label %exceptional_return + +normal_return: ; preds = %entry +; CHECK-LABEL: normal_return: +; CHECK: gc.relocate +; CHECK-NEXT: bitcast +; CHECK-NEXT: ret <2 x i64 addrspace(1)*> + ret <2 x i64 addrspace(1)*> %obj + +exceptional_return: ; preds = %entry +; CHECK-LABEL: exceptional_return: +; CHECK: gc.relocate +; CHECK-NEXT: bitcast +; CHECK-NEXT: ret <2 x i64 addrspace(1)*> + %landing_pad4 = landingpad token + cleanup + ret <2 x i64 addrspace(1)*> %obj +} + +; A newly created vector +define <2 x i64 addrspace(1)*> @test5(i64 addrspace(1)* %p) gc "statepoint-example" { +; CHECK-LABEL: test5 +; CHECK: insertelement +; CHECK-NEXT: gc.statepoint +; CHECK-NEXT: gc.relocate +; CHECK-NEXT: bitcast +; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %vec.relocated.casted +entry: + %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %p, i32 0 + call void @do_safepoint() [ "deopt"() ] + ret <2 x i64 addrspace(1)*> %vec +} + +; A merge point +define <2 x i64 addrspace(1)*> @test6(i1 %cnd, <2 x i64 addrspace(1)*>* %ptr) gc "statepoint-example" { +; CHECK-LABEL: test6 +entry: + br i1 %cnd, label %taken, label %untaken + +taken: ; preds = %entry + %obja = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr + br label %merge + +untaken: ; preds = %entry + %objb = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr + br label %merge + +merge: ; preds = %untaken, %taken +; CHECK-LABEL: merge: +; CHECK-NEXT: = phi +; CHECK-NEXT: gc.statepoint +; CHECK-NEXT: gc.relocate +; CHECK-NEXT: bitcast +; CHECK-NEXT: ret <2 x i64 addrspace(1)*> + %obj = phi <2 x i64 addrspace(1)*> [ %obja, %taken ], [ %objb, %untaken ] + call void @do_safepoint() [ "deopt"() ] + ret <2 x i64 addrspace(1)*> %obj +} + +declare void @do_safepoint() diff --git a/test/Transforms/RewriteStatepointsForGC/deopt-bundles/live-vector.ll b/test/Transforms/RewriteStatepointsForGC/deopt-bundles/live-vector.ll index 00f2893..284a993 100644 --- a/test/Transforms/RewriteStatepointsForGC/deopt-bundles/live-vector.ll +++ b/test/Transforms/RewriteStatepointsForGC/deopt-bundles/live-vector.ll @@ -1,6 +1,6 @@ ; Test that we can correctly handle vectors of pointers in statepoint ; rewriting. Currently, we scalarize, but that's an implementation detail. -; RUN: opt %s -rewrite-statepoints-for-gc -rs4gc-use-deopt-bundles -S | FileCheck %s +; RUN: opt %s -rewrite-statepoints-for-gc -rs4gc-use-deopt-bundles -rs4gc-split-vector-values -S | FileCheck %s ; A non-vector relocation for comparison diff --git a/test/Transforms/RewriteStatepointsForGC/live-vector.ll b/test/Transforms/RewriteStatepointsForGC/live-vector.ll index 584fd7a..2ec09d6 100644 --- a/test/Transforms/RewriteStatepointsForGC/live-vector.ll +++ b/test/Transforms/RewriteStatepointsForGC/live-vector.ll @@ -1,6 +1,6 @@ ; Test that we can correctly handle vectors of pointers in statepoint ; rewriting. Currently, we scalarize, but that's an implementation detail. -; RUN: opt %s -rewrite-statepoints-for-gc -S | FileCheck %s +; RUN: opt %s -rewrite-statepoints-for-gc -rs4gc-split-vector-values -S | FileCheck %s ; A non-vector relocation for comparison define i64 addrspace(1)* @test(i64 addrspace(1)* %obj) gc "statepoint-example" { diff --git a/test/Transforms/RewriteStatepointsForGC/two-invokes-one-landingpad.ll b/test/Transforms/RewriteStatepointsForGC/two-invokes-one-landingpad.ll new file mode 100644 index 0000000..d3d3c5a --- /dev/null +++ b/test/Transforms/RewriteStatepointsForGC/two-invokes-one-landingpad.ll @@ -0,0 +1,33 @@ +; RUN: opt %s -rewrite-statepoints-for-gc -rs4gc-use-deopt-bundles -S | FileCheck %s + +declare void @some_call(i64 addrspace(1)*) + +declare i32 @"dummy_personality_function"() + +define i64 addrspace(1)* @test(i64 addrspace(1)* %obj, i64 addrspace(1)* %obj1) + gc "statepoint-example" + personality i32 ()* @"dummy_personality_function" { +entry: + invoke void @some_call(i64 addrspace(1)* %obj) [ "deopt"() ] + to label %second_invoke unwind label %exceptional_return + +second_invoke: ; preds = %entry + invoke void @some_call(i64 addrspace(1)* %obj) [ "deopt"() ] + to label %normal_return unwind label %exceptional_return + +normal_return: ; preds = %second_invoke + ret i64 addrspace(1)* %obj + +; CHECK: exceptional_return1: +; CHECK-NEXT: %lpad2 = landingpad token + +; CHECK: exceptional_return.split-lp: +; CHECK-NEXT: %lpad.split-lp = landingpad token + +; CHECK: exceptional_return: +; CHECK-NOT: phi token + +exceptional_return: ; preds = %second_invoke, %entry + %lpad = landingpad token cleanup + ret i64 addrspace(1)* %obj1 +} diff --git a/test/Transforms/SimplifyCFG/bug-25299.ll b/test/Transforms/SimplifyCFG/bug-25299.ll new file mode 100644 index 0000000..706afbe --- /dev/null +++ b/test/Transforms/SimplifyCFG/bug-25299.ll @@ -0,0 +1,40 @@ +; RUN: opt < %s -simplifycfg -S | FileCheck %s + +;; Test case for bug 25299, contributed by David Majnemer. + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @f(i1 %B) personality i1 undef { +entry: +;CHECK: entry +;CHECK-NEXT: call void @g() + invoke void @g() + to label %continue unwind label %unwind + +unwind: ; preds = %entry + %tmp101 = landingpad { i8*, i32 } + cleanup + br i1 %B, label %resume, label %then + +then: ; preds = %cleanup1 + br label %resume + +resume: ; preds = %cleanup2, %then, %cleanup1, %unwind + %tmp104 = phi { i8*, i32 } [ %tmp101, %then ], [ %tmp106, %cleanup2 ], [ %tmp101, %unwind ] +;CHECK-NOT: resume { i8*, i32 } %tmp104 + resume { i8*, i32 } %tmp104 + +continue: ; preds = %entry, %continue +;CHECK: continue: ; preds = %entry, %continue +;CHECK-NEXT: call void @g() + invoke void @g() + to label %continue unwind label %cleanup2 + +cleanup2: ; preds = %continue + %tmp106 = landingpad { i8*, i32 } + cleanup + br label %resume +} + +declare void @g()
\ No newline at end of file diff --git a/test/Transforms/SimplifyCFG/invoke_unwind.ll b/test/Transforms/SimplifyCFG/invoke_unwind.ll index 100bfd4..b11b7c1 100644 --- a/test/Transforms/SimplifyCFG/invoke_unwind.ll +++ b/test/Transforms/SimplifyCFG/invoke_unwind.ll @@ -30,4 +30,46 @@ Rethrow: resume { i8*, i32 } %exn } +declare i64 @dummy1() +declare i64 @dummy2() + +; This testcase checks to see if simplifycfg pass can convert two invoke +; instructions to call instructions if they share a common trivial unwind +; block. +define i64 @test3(i1 %cond) personality i32 (...)* @__gxx_personality_v0 { +entry: +; CHECK-LABEL: @test3( +; CHECK: %call1 = call i64 @dummy1() +; CHECK: %call2 = call i64 @dummy2() +; CHECK-NOT: resume { i8*, i32 } %lp + br i1 %cond, label %br1, label %br2 + +br1: + %call1 = invoke i64 @dummy1() + to label %invoke.cont unwind label %lpad1 + +br2: + %call2 = invoke i64 @dummy2() + to label %invoke.cont unwind label %lpad2 + +invoke.cont: + %c = phi i64 [%call1, %br1], [%call2, %br2] + ret i64 %c + + +lpad1: + %0 = landingpad { i8*, i32 } + cleanup + br label %rethrow + +rethrow: + %lp = phi { i8*, i32 } [%0, %lpad1], [%1, %lpad2] + resume { i8*, i32 } %lp + +lpad2: + %1 = landingpad { i8*, i32 } + cleanup + br label %rethrow +} + declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/Util/split-bit-piece.ll b/test/Transforms/Util/split-bit-piece.ll new file mode 100644 index 0000000..6945bec --- /dev/null +++ b/test/Transforms/Util/split-bit-piece.ll @@ -0,0 +1,45 @@ +; Checks that llvm.dbg.declare -> llvm.dbg.value conversion utility +; (here exposed through the SROA) pass, properly inserts bit_piece expressions +; if it only describes part of the variable. +; RUN: opt -S -sroa %s | FileCheck %s + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) #0 + +; Function Attrs: nounwind uwtable +define hidden void @_ZN6__tsan9FastState14SetHistorySizeEi(i32 %hs) #1 align 2 { +entry: + %hs.addr = alloca i32, align 4 + %v1 = alloca i64, align 8 + %v2 = alloca i64, align 8 + store i32 %hs, i32* %hs.addr, align 4 +; CHECK: call void @llvm.dbg.value(metadata i32 %hs, i64 0, metadata !{{[0-9]+}}, metadata ![[EXPR:[0-9]+]]) +; CHECK: ![[EXPR]] = !DIExpression(DW_OP_bit_piece, 0 + call void @llvm.dbg.declare(metadata i64* %v1, metadata !9, metadata !12), !dbg !13 + %0 = load i32, i32* %hs.addr, align 4 + %conv = sext i32 %0 to i64 + store i64 %conv, i64* %v1, align 8 + %1 = load i64, i64* %v2, align 8 + unreachable +} + +attributes #0 = { nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.8.0 (trunk 256979) (llvm/trunk 257107)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, retainedTypes: !2) +!1 = !DIFile(filename: "tsan_shadow_test.cc", directory: "/tmp") +!2 = !{!3, !5} +!3 = !DICompositeType(tag: DW_TAG_class_type, name: "FastState", file: !4, line: 91, size: 64, align: 64, identifier: "_ZTSN6__tsan9FastStateE") +!4 = !DIFile(filename: "/mnt/extra/llvm/projects/compiler-rt/lib/tsan/rtl/tsan_rtl.h", directory: "/tmp") +!5 = distinct !DIDerivedType(tag: DW_TAG_typedef, name: "u64", line: 78, baseType: !6) +!6 = !DIBasicType(name: "long long unsigned int", size: 64, align: 64, encoding: DW_ATE_unsigned) +!7 = !{i32 2, !"Debug Info Version", i32 3} +!8 = !{!"clang version 3.8.0 (trunk 256979) (llvm/trunk 257107)"} +!9 = !DILocalVariable(name: "v1", scope: !10, file: !4, line: 136, type: !5) +!10 = distinct !DILexicalBlock(scope: !11, file: !4, line: 136, column: 5) +!11 = distinct !DISubprogram(name: "SetHistorySize", linkageName: "_ZN6__tsan9FastState14SetHistorySizeEi", scope: !"_ZTSN6__tsan9FastStateE", file: !4, line: 135, isLocal: false, isDefinition: true, scopeLine: 135, flags: DIFlagPrototyped, isOptimized: false) +!12 = !DIExpression() +!13 = !DILocation(line: 136, column: 5, scope: !10) |