diff options
Diffstat (limited to 'test/Transforms/SimplifyCFG')
30 files changed, 1245 insertions, 291 deletions
diff --git a/test/Transforms/SimplifyCFG/2007-11-22-InvokeNoUnwind.ll b/test/Transforms/SimplifyCFG/2007-11-22-InvokeNoUnwind.ll index a90e072..76f41e8 100644 --- a/test/Transforms/SimplifyCFG/2007-11-22-InvokeNoUnwind.ll +++ b/test/Transforms/SimplifyCFG/2007-11-22-InvokeNoUnwind.ll @@ -12,5 +12,9 @@ Cont: ; preds = %0 ret i32 0 Other: ; preds = %0 + landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 + catch i8* null ret i32 1 } + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/SimplifyCFG/2008-01-02-hoist-fp-add.ll b/test/Transforms/SimplifyCFG/2008-01-02-hoist-fp-add.ll index cf29b71..8e15637 100644 --- a/test/Transforms/SimplifyCFG/2008-01-02-hoist-fp-add.ll +++ b/test/Transforms/SimplifyCFG/2008-01-02-hoist-fp-add.ll @@ -1,27 +1,27 @@ -; The phi should not be eliminated in this case, because the fp op could trap. +; The phi should not be eliminated in this case, because the divide op could trap. ; RUN: opt < %s -simplifycfg -S | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i686-apple-darwin8" -@G = weak global double 0.000000e+00, align 8 ; <double*> [#uses=2] +@G = weak global i32 0, align 8 ; <i32*> [#uses=2] -define void @test(i32 %X, i32 %Y, double %Z) { +define void @test(i32 %X, i32 %Y, i32 %Z) { entry: %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] - %tmp = load double* @G, align 8 ; <double> [#uses=2] + %tmp = load i32* @G, align 8 ; <i32> [#uses=2] %tmp3 = icmp eq i32 %X, %Y ; <i1> [#uses=1] %tmp34 = zext i1 %tmp3 to i8 ; <i8> [#uses=1] %toBool = icmp ne i8 %tmp34, 0 ; <i1> [#uses=1] br i1 %toBool, label %cond_true, label %cond_next cond_true: ; preds = %entry - %tmp7 = fadd double %tmp, %Z ; <double> [#uses=1] + %tmp7 = udiv i32 %tmp, %Z ; <i32> [#uses=1] br label %cond_next cond_next: ; preds = %cond_true, %entry -; CHECK: = phi double - %F.0 = phi double [ %tmp, %entry ], [ %tmp7, %cond_true ] ; <double> [#uses=1] - store double %F.0, double* @G, align 8 +; CHECK: = phi i32 + %F.0 = phi i32 [ %tmp, %entry ], [ %tmp7, %cond_true ] ; <i32> [#uses=1] + store i32 %F.0, i32* @G, align 8 ret void } diff --git a/test/Transforms/SimplifyCFG/AArch64/lit.local.cfg b/test/Transforms/SimplifyCFG/AArch64/lit.local.cfg new file mode 100644 index 0000000..6642d28 --- /dev/null +++ b/test/Transforms/SimplifyCFG/AArch64/lit.local.cfg @@ -0,0 +1,5 @@ +config.suffixes = ['.ll'] + +targets = set(config.root.targets_to_build.split()) +if not 'AArch64' in targets: + config.unsupported = True diff --git a/test/Transforms/SimplifyCFG/AArch64/prefer-fma.ll b/test/Transforms/SimplifyCFG/AArch64/prefer-fma.ll new file mode 100644 index 0000000..076cb58 --- /dev/null +++ b/test/Transforms/SimplifyCFG/AArch64/prefer-fma.ll @@ -0,0 +1,72 @@ +; RUN: opt < %s -mtriple=aarch64-linux-gnu -simplifycfg -enable-unsafe-fp-math -S >%t +; RUN: FileCheck %s < %t +; ModuleID = 't.cc' + +; Function Attrs: nounwind +define double @_Z3fooRdS_S_S_(double* dereferenceable(8) %x, double* dereferenceable(8) %y, double* dereferenceable(8) %a) #0 { +entry: + %0 = load double* %y, align 8 + %cmp = fcmp oeq double %0, 0.000000e+00 + %1 = load double* %x, align 8 + br i1 %cmp, label %if.then, label %if.else + +; fadd (const, (fmul x, y)) +if.then: ; preds = %entry +; CHECK-LABEL: if.then: +; CHECK: %3 = fmul fast double %1, %2 +; CHECK-NEXT: %mul = fadd fast double 1.000000e+00, %3 + %2 = load double* %a, align 8 + %3 = fmul fast double %1, %2 + %mul = fadd fast double 1.000000e+00, %3 + store double %mul, double* %y, align 8 + br label %if.end + +; fsub ((fmul x, y), z) +if.else: ; preds = %entry +; CHECK-LABEL: if.else: +; CHECK: %mul1 = fmul fast double %1, %2 +; CHECK-NEXT: %sub1 = fsub fast double %mul1, %0 + %4 = load double* %a, align 8 + %mul1 = fmul fast double %1, %4 + %sub1 = fsub fast double %mul1, %0 + store double %sub1, double* %y, align 8 + br label %if.end + +if.end: ; preds = %if.else, %if.then + %5 = load double* %y, align 8 + %cmp2 = fcmp oeq double %5, 2.000000e+00 + %6 = load double* %x, align 8 + br i1 %cmp2, label %if.then2, label %if.else2 + +; fsub (x, (fmul y, z)) +if.then2: ; preds = %entry +; CHECK-LABEL: if.then2: +; CHECK: %7 = fmul fast double %5, 3.000000e+00 +; CHECK-NEXT: %mul2 = fsub fast double %6, %7 + %7 = load double* %a, align 8 + %8 = fmul fast double %6, 3.0000000e+00 + %mul2 = fsub fast double %7, %8 + store double %mul2, double* %y, align 8 + br label %if.end2 + +; fsub (fneg((fmul x, y)), const) +if.else2: ; preds = %entry +; CHECK-LABEL: if.else2: +; CHECK: %mul3 = fmul fast double %5, 3.000000e+00 +; CHECK-NEXT: %neg = fsub fast double 0.000000e+00, %mul3 +; CHECK-NEXT: %sub2 = fsub fast double %neg, 3.000000e+00 + %mul3 = fmul fast double %6, 3.0000000e+00 + %neg = fsub fast double 0.0000000e+00, %mul3 + %sub2 = fsub fast double %neg, 3.0000000e+00 + store double %sub2, double* %y, align 8 + br label %if.end2 + +if.end2: ; preds = %if.else, %if.then + %9 = load double* %x, align 8 + %10 = load double* %y, align 8 + %add = fadd fast double %9, %10 + %11 = load double* %a, align 8 + %add2 = fadd fast double %add, %11 + ret double %add2 +} + diff --git a/test/Transforms/SimplifyCFG/PhiBlockMerge.ll b/test/Transforms/SimplifyCFG/PhiBlockMerge.ll index 36b52f5..5550829 100644 --- a/test/Transforms/SimplifyCFG/PhiBlockMerge.ll +++ b/test/Transforms/SimplifyCFG/PhiBlockMerge.ll @@ -4,9 +4,7 @@ ; define i32 @test(i1 %a, i1 %b) { -; CHECK: br i1 %a br i1 %a, label %M, label %O -; CHECK: O: O: ; preds = %0 ; CHECK: select i1 %b, i32 0, i32 1 ; CHECK-NOT: phi @@ -18,9 +16,9 @@ N: ; preds = %Q, %O %Wp = phi i32 [ 0, %O ], [ 1, %Q ] ; <i32> [#uses=1] br label %M M: ; preds = %N, %0 -; CHECK: %W = phi i32 %W = phi i32 [ %Wp, %N ], [ 2, %0 ] ; <i32> [#uses=1] %R = add i32 %W, 1 ; <i32> [#uses=1] ret i32 %R +; CHECK: ret } diff --git a/test/Transforms/SimplifyCFG/PowerPC/cttz-ctlz-spec.ll b/test/Transforms/SimplifyCFG/PowerPC/cttz-ctlz-spec.ll new file mode 100644 index 0000000..fa74549 --- /dev/null +++ b/test/Transforms/SimplifyCFG/PowerPC/cttz-ctlz-spec.ll @@ -0,0 +1,45 @@ +; RUN: opt -S -simplifycfg < %s | FileCheck %s +target datalayout = "E-m:e-i64:64-n32:64" +target triple = "powerpc64-unknown-linux-gnu" + +define i64 @test1(i64 %A) { +; CHECK-LABEL: @test1( +; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; CHECK-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) +; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 64, i64 [[CTLZ]] +; CHECK-NEXT: ret i64 [[SEL]] +entry: + %tobool = icmp eq i64 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] + ret i64 %cond +} + +define i64 @test1b(i64 %A) { +; CHECK-LABEL: @test1b( +; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; CHECK-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) +; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 64, i64 [[CTLZ]] +; CHECK-NEXT: ret i64 [[SEL]] +entry: + %tobool = icmp eq i64 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] + ret i64 %cond +} + +declare i64 @llvm.ctlz.i64(i64, i1) +declare i64 @llvm.cttz.i64(i64, i1) + diff --git a/test/Transforms/SimplifyCFG/PowerPC/lit.local.cfg b/test/Transforms/SimplifyCFG/PowerPC/lit.local.cfg new file mode 100644 index 0000000..0913324 --- /dev/null +++ b/test/Transforms/SimplifyCFG/PowerPC/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'PowerPC' in config.root.targets: + config.unsupported = True diff --git a/test/Transforms/SimplifyCFG/R600/cttz-ctlz.ll b/test/Transforms/SimplifyCFG/R600/cttz-ctlz.ll new file mode 100644 index 0000000..5b27994 --- /dev/null +++ b/test/Transforms/SimplifyCFG/R600/cttz-ctlz.ll @@ -0,0 +1,249 @@ +; RUN: opt -S -simplifycfg -mtriple=r600-unknown-unknown -mcpu=SI < %s | FileCheck -check-prefix=SI -check-prefix=ALL %s +; RUN: opt -S -simplifycfg -mtriple=r600-unknown-unknown -mcpu=tonga < %s | FileCheck -check-prefix=SI -check-prefix=ALL %s + + +define i64 @test1(i64 %A) { +; ALL-LABEL: @test1( +; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; SI-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) +; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 64, i64 [[CTLZ]] +; SI-NEXT: ret i64 [[SEL]] +entry: + %tobool = icmp eq i64 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] + ret i64 %cond +} + + +define i32 @test2(i32 %A) { +; ALL-LABEL: @test2( +; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; SI-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) +; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTLZ]] +; SI-NEXT: ret i32 [[SEL]] +entry: + %tobool = icmp eq i32 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] + ret i32 %cond +} + + +define signext i16 @test3(i16 signext %A) { +; ALL-LABEL: @test3( +; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 +; SI-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) +; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i16 16, i16 [[CTLZ]] +; SI-NEXT: ret i16 [[SEL]] +entry: + %tobool = icmp eq i16 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] + ret i16 %cond +} + + +define i64 @test1b(i64 %A) { +; ALL-LABEL: @test1b( +; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; SI-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) +; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 64, i64 [[CTTZ]] +; SI-NEXT: ret i64 [[SEL]] +entry: + %tobool = icmp eq i64 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] + ret i64 %cond +} + + +define i32 @test2b(i32 %A) { +; ALL-LABEL: @test2b( +; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; SI-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) +; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTTZ]] +; SI-NEXT: ret i32 [[SEL]] +entry: + %tobool = icmp eq i32 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] + ret i32 %cond +} + + +define signext i16 @test3b(i16 signext %A) { +; ALL-LABEL: @test3b( +; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 +; SI-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) +; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i16 16, i16 [[CTTZ]] +; SI-NEXT: ret i16 [[SEL]] +entry: + %tobool = icmp eq i16 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] + ret i16 %cond +} + + +define i64 @test1c(i64 %A) { +; ALL-LABEL: @test1c( +; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; ALL-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) +; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 63, i64 [[CTLZ]] +; ALL-NEXT: ret i64 [[SEL]] +entry: + %tobool = icmp eq i64 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ] + ret i64 %cond +} + +define i32 @test2c(i32 %A) { +; ALL-LABEL: @test2c( +; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; ALL-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) +; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 31, i32 [[CTLZ]] +; ALL-NEXT: ret i32 [[SEL]] +entry: + %tobool = icmp eq i32 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ] + ret i32 %cond +} + + +define signext i16 @test3c(i16 signext %A) { +; ALL-LABEL: @test3c( +; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 +; ALL-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) +; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i16 15, i16 [[CTLZ]] +; ALL-NEXT: ret i16 [[SEL]] +entry: + %tobool = icmp eq i16 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ] + ret i16 %cond +} + + +define i64 @test1d(i64 %A) { +; ALL-LABEL: @test1d( +; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; ALL-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) +; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 63, i64 [[CTTZ]] +; ALL-NEXT: ret i64 [[SEL]] +entry: + %tobool = icmp eq i64 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ] + ret i64 %cond +} + + +define i32 @test2d(i32 %A) { +; ALL-LABEL: @test2d( +; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; ALL-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) +; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 31, i32 [[CTTZ]] +; ALL-NEXT: ret i32 [[SEL]] +entry: + %tobool = icmp eq i32 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ] + ret i32 %cond +} + + +define signext i16 @test3d(i16 signext %A) { +; ALL-LABEL: @test3d( +; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 +; ALL-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) +; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i16 15, i16 [[CTTZ]] +; ALL-NEXT: ret i16 [[SEL]] +entry: + %tobool = icmp eq i16 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ] + ret i16 %cond +} + + +declare i64 @llvm.ctlz.i64(i64, i1) +declare i32 @llvm.ctlz.i32(i32, i1) +declare i16 @llvm.ctlz.i16(i16, i1) +declare i64 @llvm.cttz.i64(i64, i1) +declare i32 @llvm.cttz.i32(i32, i1) +declare i16 @llvm.cttz.i16(i16, i1) diff --git a/test/Transforms/SimplifyCFG/R600/lit.local.cfg b/test/Transforms/SimplifyCFG/R600/lit.local.cfg new file mode 100644 index 0000000..ad9ce25 --- /dev/null +++ b/test/Transforms/SimplifyCFG/R600/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'R600' in config.root.targets: + config.unsupported = True diff --git a/test/Transforms/SimplifyCFG/SpeculativeExec.ll b/test/Transforms/SimplifyCFG/SpeculativeExec.ll index 83fa419..31de3c8 100644 --- a/test/Transforms/SimplifyCFG/SpeculativeExec.ll +++ b/test/Transforms/SimplifyCFG/SpeculativeExec.ll @@ -28,22 +28,6 @@ bb3: ; preds = %bb2, %entry ret i32 %tmp5 } -declare i8 @llvm.cttz.i8(i8, i1) - -define i8 @test2(i8 %a) { -; CHECK-LABEL: @test2( - br i1 undef, label %bb_true, label %bb_false -bb_true: - %b = tail call i8 @llvm.cttz.i8(i8 %a, i1 false) - br label %join -bb_false: - br label %join -join: - %c = phi i8 [%b, %bb_true], [%a, %bb_false] -; CHECK: select - ret i8 %c -} - define i8* @test4(i1* %dummy, i8* %a, i8* %b) { ; Test that we don't speculate an arbitrarily large number of unfolded constant ; expressions. diff --git a/test/Transforms/SimplifyCFG/UnreachableEliminate.ll b/test/Transforms/SimplifyCFG/UnreachableEliminate.ll index 21428c6..22b144b 100644 --- a/test/Transforms/SimplifyCFG/UnreachableEliminate.ll +++ b/test/Transforms/SimplifyCFG/UnreachableEliminate.ll @@ -46,32 +46,6 @@ T: ret i32 2 } -; PR9450 -define i32 @test4(i32 %v, i32 %w) { -; CHECK: entry: -; CHECK-NEXT: switch i32 %v, label %T [ -; CHECK-NEXT: i32 3, label %V -; CHECK-NEXT: i32 2, label %U -; CHECK-NEXT: ] - -entry: - br label %SWITCH -V: - ret i32 7 -SWITCH: - switch i32 %v, label %default [ - i32 1, label %T - i32 2, label %U - i32 3, label %V - ] -default: - unreachable -U: - ret i32 %w -T: - ret i32 2 -} - ;; We can either convert the following control-flow to a select or remove the ;; unreachable control flow because of the undef store of null. Make sure we do diff --git a/test/Transforms/SimplifyCFG/X86/speculate-cttz-ctlz.ll b/test/Transforms/SimplifyCFG/X86/speculate-cttz-ctlz.ll new file mode 100644 index 0000000..69f6c69 --- /dev/null +++ b/test/Transforms/SimplifyCFG/X86/speculate-cttz-ctlz.ll @@ -0,0 +1,330 @@ +; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+bmi < %s | FileCheck %s --check-prefix=ALL --check-prefix=BMI +; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+lzcnt < %s | FileCheck %s --check-prefix=ALL --check-prefix=LZCNT +; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown < %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC + + +define i64 @test1(i64 %A) { +; ALL-LABEL: @test1( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) +; LZCNT-NEXT: select i1 [[COND]], i64 64, i64 [[CTLZ]] +; BMI-NOT: select +; GENERIC-NOT: select +; ALL: ret +entry: + %tobool = icmp eq i64 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] + ret i64 %cond +} + +define i32 @test2(i32 %A) { +; ALL-LABEL: @test2( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) +; LZCNT-NEXT: select i1 [[COND]], i32 32, i32 [[CTLZ]] +; BMI-NOT: select +; GENERIC-NOT: select +; ALL: ret +entry: + %tobool = icmp eq i32 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] + ret i32 %cond +} + + +define signext i16 @test3(i16 signext %A) { +; ALL-LABEL: @test3( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 +; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) +; LZCNT-NEXT: select i1 [[COND]], i16 16, i16 [[CTLZ]] +; BMI-NOT: select +; GENERIC-NOT: select +; ALL: ret +entry: + %tobool = icmp eq i16 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] + ret i16 %cond +} + + +define i64 @test1b(i64 %A) { +; ALL-LABEL: @test1b( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) +; BMI-NEXT: select i1 [[COND]], i64 64, i64 [[CTTZ]] +; LZCNT-NOT: select +; GENERIC-NOT: select +; ALL: ret +entry: + %tobool = icmp eq i64 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] + ret i64 %cond +} + + +define i32 @test2b(i32 %A) { +; ALL-LABEL: @test2b( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) +; BMI-NEXT: select i1 [[COND]], i32 32, i32 [[CTTZ]] +; LZCNT-NOT: select +; GENERIC-NOT: select +; ALL: ret +entry: + %tobool = icmp eq i32 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] + ret i32 %cond +} + + +define signext i16 @test3b(i16 signext %A) { +; ALL-LABEL: @test3b( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 +; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) +; BMI-NEXT: select i1 [[COND]], i16 16, i16 [[CTTZ]] +; LZCNT-NOT: select +; GENERIC-NOT: select +; ALL: ret +entry: + %tobool = icmp eq i16 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] + ret i16 %cond +} + +; The following tests verify that calls to cttz/ctlz are speculated even if +; basic block %cond.true has an extra zero extend/truncate which is "free" +; for the target. + +define i64 @test1e(i32 %x) { +; ALL-LABEL: @test1e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 +; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) +; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTTZ]] to i64 +; BMI-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]] +; LZCNT-NOT: select +; GENERIC-NOT: select +; ALL: ret +entry: + %tobool = icmp eq i32 %x, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) + %phitmp2 = zext i32 %0 to i64 + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ] + ret i64 %cond +} + +define i32 @test2e(i64 %x) { +; ALL-LABEL: @test2e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 +; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) +; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i32 +; BMI-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]] +; LZCNT-NOT: select +; GENERIC-NOT: select +; ALL: ret +entry: + %tobool = icmp eq i64 %x, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) + %cast = trunc i64 %0 to i32 + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ] + ret i32 %cond +} + +define i64 @test3e(i32 %x) { +; ALL-LABEL: @test3e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 +; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) +; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTLZ]] to i64 +; LZCNT-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]] +; BMI-NOT: select +; GENERIC-NOT: select +; ALL: ret +entry: + %tobool = icmp eq i32 %x, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) + %phitmp2 = zext i32 %0 to i64 + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ] + ret i64 %cond +} + +define i32 @test4e(i64 %x) { +; ALL-LABEL: @test4e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 +; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) +; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i32 +; LZCNT-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]] +; BMI-NOT: select +; GENERIC-NOT: select +; ALL: ret +entry: + %tobool = icmp eq i64 %x, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) + %cast = trunc i64 %0 to i32 + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ] + ret i32 %cond +} + +define i16 @test5e(i64 %x) { +; ALL-LABEL: @test5e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 +; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) +; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i16 +; LZCNT-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]] +; BMI-NOT: select +; GENERIC-NOT: select +; ALL: ret +entry: + %tobool = icmp eq i64 %x, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) + %cast = trunc i64 %0 to i16 + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ] + ret i16 %cond +} + +define i16 @test6e(i32 %x) { +; ALL-LABEL: @test6e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 +; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) +; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTLZ]] to i16 +; LZCNT-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]] +; BMI-NOT: select +; GENERIC-NOT: select +; ALL: ret +entry: + %tobool = icmp eq i32 %x, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) + %cast = trunc i32 %0 to i16 + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ] + ret i16 %cond +} + +define i16 @test7e(i64 %x) { +; ALL-LABEL: @test7e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 +; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) +; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i16 +; BMI-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]] +; LZCNT-NOT: select +; GENERIC-NOT: select +; ALL: ret +entry: + %tobool = icmp eq i64 %x, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) + %cast = trunc i64 %0 to i16 + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ] + ret i16 %cond +} + +define i16 @test8e(i32 %x) { +; ALL-LABEL: @test8e( +; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 +; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) +; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTTZ]] to i16 +; BMI-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]] +; LZCNT-NOT: select +; GENERIC-NOT: select +; ALL: ret +entry: + %tobool = icmp eq i32 %x, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) + %cast = trunc i32 %0 to i16 + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ] + ret i16 %cond +} + + +declare i64 @llvm.ctlz.i64(i64, i1) +declare i32 @llvm.ctlz.i32(i32, i1) +declare i16 @llvm.ctlz.i16(i16, i1) +declare i64 @llvm.cttz.i64(i64, i1) +declare i32 @llvm.cttz.i32(i32, i1) +declare i16 @llvm.cttz.i16(i16, i1) diff --git a/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll b/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll index fc22e7e..ea3b575 100644 --- a/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll +++ b/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll @@ -21,8 +21,8 @@ target triple = "x86_64-unknown-linux-gnu" ; The table for @cprop ; CHECK: @switch.table5 = private unnamed_addr constant [7 x i32] [i32 5, i32 42, i32 126, i32 -452, i32 128, i32 6, i32 7] -; The table for @unreachable -; CHECK: @switch.table6 = private unnamed_addr constant [5 x i32] [i32 0, i32 0, i32 0, i32 1, i32 -1] +; The table for @unreachable_case +; CHECK: @switch.table6 = private unnamed_addr constant [9 x i32] [i32 0, i32 0, i32 0, i32 2, i32 -1, i32 1, i32 1, i32 1, i32 1] ; A simple int-to-int selection switch. ; It is dense enough to be replaced by table lookup. @@ -752,7 +752,7 @@ return: ; CHECK: %switch.gep = getelementptr inbounds [7 x i32]* @switch.table5, i32 0, i32 %switch.tableidx } -define i32 @unreachable(i32 %x) { +define i32 @unreachable_case(i32 %x) { entry: switch i32 %x, label %sw.default [ i32 0, label %sw.bb @@ -770,19 +770,47 @@ sw.bb: br label %return sw.bb1: unreachable sw.bb2: br label %return sw.bb3: br label %return -sw.default: unreachable +sw.default: br label %return return: - %retval.0 = phi i32 [ 1, %sw.bb3 ], [ -1, %sw.bb2 ], [ 0, %sw.bb ] + %retval.0 = phi i32 [ 1, %sw.bb3 ], [ -1, %sw.bb2 ], [ 0, %sw.bb ], [ 2, %sw.default ] ret i32 %retval.0 -; CHECK-LABEL: @unreachable( +; CHECK-LABEL: @unreachable_case( ; CHECK: switch.lookup: -; CHECK: getelementptr inbounds [5 x i32]* @switch.table6, i32 0, i32 %switch.tableidx +; CHECK: getelementptr inbounds [9 x i32]* @switch.table6, i32 0, i32 %switch.tableidx +} + +define i32 @unreachable_default(i32 %x) { +entry: + switch i32 %x, label %default [ + i32 0, label %bb0 + i32 1, label %bb1 + i32 2, label %bb2 + i32 3, label %bb3 + ] + +bb0: br label %return +bb1: br label %return +bb2: br label %return +bb3: br label %return +default: unreachable + +return: + %retval = phi i32 [ 42, %bb0 ], [ 52, %bb1 ], [ 1, %bb2 ], [ 2, %bb3 ] + ret i32 %retval + +; CHECK-LABEL: @unreachable_default( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i32 %x, 0 +; CHECK-NOT: icmp +; CHECK-NOT: br 1i +; CHECK-NEXT: %switch.gep = getelementptr inbounds [4 x i32]* @switch.table7, i32 0, i32 %switch.tableidx +; CHECK-NEXT: %switch.load = load i32* %switch.gep +; CHECK-NEXT: ret i32 %switch.load } ; Don't create a table with illegal type -; rdar://12779436 define i96 @illegaltype(i32 %c) { entry: switch i32 %c, label %sw.default [ @@ -1078,3 +1106,170 @@ return: ; CHECK-NEXT: ret i8 %switch.idx.cast } +; Reuse the inverted table range compare. +define i32 @reuse_cmp1(i32 %x) { +entry: + switch i32 %x, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + ] +sw.bb: br label %sw.epilog +sw.bb1: br label %sw.epilog +sw.bb2: br label %sw.epilog +sw.bb3: br label %sw.epilog +sw.default: br label %sw.epilog +sw.epilog: + %r.0 = phi i32 [ 0, %sw.default ], [ 13, %sw.bb3 ], [ 12, %sw.bb2 ], [ 11, %sw.bb1 ], [ 10, %sw.bb ] + %cmp = icmp eq i32 %r.0, 0 ; This compare can be "replaced". + br i1 %cmp, label %if.then, label %if.end +if.then: br label %return +if.end: br label %return +return: + %retval.0 = phi i32 [ 100, %if.then ], [ %r.0, %if.end ] + ret i32 %retval.0 +; CHECK-LABEL: @reuse_cmp1( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i32 %x, 0 +; CHECK-NEXT: [[C:%.+]] = icmp ult i32 %switch.tableidx, 4 +; CHECK-NEXT: %inverted.cmp = xor i1 [[C]], true +; CHECK: [[R:%.+]] = select i1 %inverted.cmp, i32 100, i32 {{.*}} +; CHECK-NEXT: ret i32 [[R]] +} + +; Reuse the table range compare. +define i32 @reuse_cmp2(i32 %x) { +entry: + switch i32 %x, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + ] +sw.bb: br label %sw.epilog +sw.bb1: br label %sw.epilog +sw.bb2: br label %sw.epilog +sw.bb3: br label %sw.epilog +sw.default: br label %sw.epilog +sw.epilog: + %r.0 = phi i32 [ 4, %sw.default ], [ 3, %sw.bb3 ], [ 2, %sw.bb2 ], [ 1, %sw.bb1 ], [ 0, %sw.bb ] + %cmp = icmp ne i32 %r.0, 4 ; This compare can be "replaced". + br i1 %cmp, label %if.then, label %if.end +if.then: br label %return +if.end: br label %return +return: + %retval.0 = phi i32 [ %r.0, %if.then ], [ 100, %if.end ] + ret i32 %retval.0 +; CHECK-LABEL: @reuse_cmp2( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i32 %x, 0 +; CHECK-NEXT: [[C:%.+]] = icmp ult i32 %switch.tableidx, 4 +; CHECK: [[R:%.+]] = select i1 [[C]], i32 {{.*}}, i32 100 +; CHECK-NEXT: ret i32 [[R]] +} + +; Cannot reuse the table range compare, because the default value is the same +; as one of the case values. +define i32 @no_reuse_cmp(i32 %x) { +entry: + switch i32 %x, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + ] +sw.bb: br label %sw.epilog +sw.bb1: br label %sw.epilog +sw.bb2: br label %sw.epilog +sw.bb3: br label %sw.epilog +sw.default: br label %sw.epilog +sw.epilog: + %r.0 = phi i32 [ 12, %sw.default ], [ 13, %sw.bb3 ], [ 12, %sw.bb2 ], [ 11, %sw.bb1 ], [ 10, %sw.bb ] + %cmp = icmp ne i32 %r.0, 0 + br i1 %cmp, label %if.then, label %if.end +if.then: br label %return +if.end: br label %return +return: + %retval.0 = phi i32 [ %r.0, %if.then ], [ 100, %if.end ] + ret i32 %retval.0 +; CHECK-LABEL: @no_reuse_cmp( +; CHECK: [[S:%.+]] = select +; CHECK-NEXT: %cmp = icmp ne i32 [[S]], 0 +; CHECK-NEXT: [[R:%.+]] = select i1 %cmp, i32 [[S]], i32 100 +; CHECK-NEXT: ret i32 [[R]] +} + +; Cannot reuse the table range compare, because the phi at the switch merge +; point is not dominated by the switch. +define i32 @no_reuse_cmp2(i32 %x, i32 %y) { +entry: + %ec = icmp ne i32 %y, 0 + br i1 %ec, label %switch.entry, label %sw.epilog +switch.entry: + switch i32 %x, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + ] +sw.bb: br label %sw.epilog +sw.bb1: br label %sw.epilog +sw.bb2: br label %sw.epilog +sw.bb3: br label %sw.epilog +sw.default: br label %sw.epilog +sw.epilog: + %r.0 = phi i32 [100, %entry], [ 0, %sw.default ], [ 13, %sw.bb3 ], [ 12, %sw.bb2 ], [ 11, %sw.bb1 ], [ 10, %sw.bb ] + %cmp = icmp eq i32 %r.0, 0 ; This compare can be "replaced". + br i1 %cmp, label %if.then, label %if.end +if.then: br label %return +if.end: br label %return +return: + %retval.0 = phi i32 [ 100, %if.then ], [ %r.0, %if.end ] + ret i32 %retval.0 +; CHECK-LABEL: @no_reuse_cmp2( +; CHECK: %r.0 = phi +; CHECK-NEXT: %cmp = icmp eq i32 %r.0, 0 +; CHECK-NEXT: [[R:%.+]] = select i1 %cmp +; CHECK-NEXT: ret i32 [[R]] +} + +define void @pr20210(i8 %x, i1 %y) { +; %z has uses outside of its BB or the phi it feeds into, +; so doing a table lookup and jumping directly to while.cond would +; cause %z to cease dominating all its uses. + +entry: + br i1 %y, label %sw, label %intermediate + +sw: + switch i8 %x, label %end [ + i8 7, label %intermediate + i8 3, label %intermediate + i8 2, label %intermediate + i8 1, label %intermediate + i8 0, label %intermediate + ] + +intermediate: + %z = zext i8 %x to i32 + br label %while.cond + +while.cond: + %i = phi i32 [ %z, %intermediate ], [ %j, %while.body ] + %b = icmp ne i32 %i, 7 + br i1 %b, label %while.body, label %while.end + +while.body: + %j = add i32 %i, 1 + br label %while.cond + +while.end: + call void @exit(i32 %z) + unreachable + +end: + ret void +; CHECK-LABEL: @pr20210 +; CHECK: switch i8 %x +} diff --git a/test/Transforms/SimplifyCFG/basictest.ll b/test/Transforms/SimplifyCFG/basictest.ll index d6958a9..5d9dad4 100644 --- a/test/Transforms/SimplifyCFG/basictest.ll +++ b/test/Transforms/SimplifyCFG/basictest.ll @@ -1,6 +1,7 @@ ; Test CFG simplify removal of branch instructions. ; ; RUN: opt < %s -simplifycfg -S | FileCheck %s +; RUN: opt < %s -passes=simplify-cfg -S | FileCheck %s define void @test1() { br label %1 @@ -68,6 +69,6 @@ bb3: } declare i8 @test6g(i8*) -!0 = metadata !{metadata !1, metadata !1, i64 0} -!1 = metadata !{metadata !"foo"} -!2 = metadata !{i8 0, i8 2} +!0 = !{!1, !1, i64 0} +!1 = !{!"foo"} +!2 = !{i8 0, i8 2} diff --git a/test/Transforms/SimplifyCFG/branch-fold-dbg.ll b/test/Transforms/SimplifyCFG/branch-fold-dbg.ll index 9235f62..f715a0c 100644 --- a/test/Transforms/SimplifyCFG/branch-fold-dbg.ll +++ b/test/Transforms/SimplifyCFG/branch-fold-dbg.ll @@ -25,7 +25,7 @@ BB2: ; preds = %BB1 BB3: ; preds = %BB2 %6 = getelementptr inbounds [5 x %0]* @0, i32 0, i32 %0, !dbg !6 - call void @llvm.dbg.value(metadata !{%0* %6}, i64 0, metadata !7, metadata !{}), !dbg !12 + call void @llvm.dbg.value(metadata %0* %6, i64 0, metadata !7, metadata !{}), !dbg !12 %7 = icmp eq %0* %6, null, !dbg !13 br i1 %7, label %BB5, label %BB4, !dbg !13 @@ -41,19 +41,19 @@ declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnon !llvm.dbg.sp = !{!0} -!0 = metadata !{metadata !"0x2e\00foo\00foo\00\00231\000\001\000\006\00256\000\000", metadata !15, metadata !1, metadata !3, null, void (i32)* @foo, null, null, null} ; [ DW_TAG_subprogram ] [line 231] [def] [scope 0] [foo] -!1 = metadata !{metadata !"0x29", metadata !15} ; [ DW_TAG_file_type ] -!2 = metadata !{metadata !"0x11\0012\00clang (trunk 129006)\001\00\000\00\000", metadata !15, metadata !4, metadata !4, null, null, null} ; [ DW_TAG_compile_unit ] -!3 = metadata !{metadata !"0x15\00\000\000\000\000\000\000", metadata !15, metadata !1, null, metadata !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!4 = metadata !{null} -!5 = metadata !{i32 131, i32 2, metadata !0, null} -!6 = metadata !{i32 134, i32 2, metadata !0, null} -!7 = metadata !{metadata !"0x100\00bar\00232\000", metadata !8, metadata !1, metadata !9} ; [ DW_TAG_auto_variable ] -!8 = metadata !{metadata !"0xb\00231\001\003", metadata !15, metadata !0} ; [ DW_TAG_lexical_block ] -!9 = metadata !{metadata !"0xf\00\000\0032\0032\000\000", null, metadata !2, metadata !10} ; [ DW_TAG_pointer_type ] -!10 = metadata !{metadata !"0x26\00\000\000\000\000\000", null, metadata !2, metadata !11} ; [ DW_TAG_const_type ] -!11 = metadata !{metadata !"0x24\00unsigned int\000\0032\0032\000\000\007", null, metadata !2} ; [ DW_TAG_base_type ] -!12 = metadata !{i32 232, i32 40, metadata !8, null} -!13 = metadata !{i32 234, i32 2, metadata !8, null} -!14 = metadata !{i32 274, i32 1, metadata !8, null} -!15 = metadata !{metadata !"a.c", metadata !"/private/tmp"} +!0 = !{!"0x2e\00foo\00foo\00\00231\000\001\000\006\00256\000\000", !15, !1, !3, null, void (i32)* @foo, null, null, null} ; [ DW_TAG_subprogram ] [line 231] [def] [scope 0] [foo] +!1 = !{!"0x29", !15} ; [ DW_TAG_file_type ] +!2 = !{!"0x11\0012\00clang (trunk 129006)\001\00\000\00\000", !15, !4, !4, null, null, null} ; [ DW_TAG_compile_unit ] +!3 = !{!"0x15\00\000\000\000\000\000\000", !15, !1, null, !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!4 = !{null} +!5 = !MDLocation(line: 131, column: 2, scope: !0) +!6 = !MDLocation(line: 134, column: 2, scope: !0) +!7 = !{!"0x100\00bar\00232\000", !8, !1, !9} ; [ DW_TAG_auto_variable ] +!8 = !{!"0xb\00231\001\003", !15, !0} ; [ DW_TAG_lexical_block ] +!9 = !{!"0xf\00\000\0032\0032\000\000", null, !2, !10} ; [ DW_TAG_pointer_type ] +!10 = !{!"0x26\00\000\000\000\000\000", null, !2, !11} ; [ DW_TAG_const_type ] +!11 = !{!"0x24\00unsigned int\000\0032\0032\000\000\007", null, !2} ; [ DW_TAG_base_type ] +!12 = !MDLocation(line: 232, column: 40, scope: !8) +!13 = !MDLocation(line: 234, column: 2, scope: !8) +!14 = !MDLocation(line: 274, column: 1, scope: !8) +!15 = !{!"a.c", !"/private/tmp"} diff --git a/test/Transforms/SimplifyCFG/clamp.ll b/test/Transforms/SimplifyCFG/clamp.ll new file mode 100644 index 0000000..d21894a --- /dev/null +++ b/test/Transforms/SimplifyCFG/clamp.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -simplifycfg -S | FileCheck %s + +define float @clamp(float %a, float %b, float %c) { +; CHECK-LABEL: @clamp +; CHECK: %cmp = fcmp ogt float %a, %c +; CHECK: %cmp1 = fcmp olt float %a, %b +; CHECK: %cond = select i1 %cmp1, float %b, float %a +; CHECK: %cond5 = select i1 %cmp, float %c, float %cond +; CHECK: ret float %cond5 +entry: + %cmp = fcmp ogt float %a, %c + br i1 %cmp, label %cond.end4, label %cond.false + +cond.false: ; preds = %entry + %cmp1 = fcmp olt float %a, %b + %cond = select i1 %cmp1, float %b, float %a + br label %cond.end4 + +cond.end4: ; preds = %entry, %cond.false + %cond5 = phi float [ %cond, %cond.false ], [ %c, %entry ] + ret float %cond5 +} diff --git a/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll b/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll index cc382be..869ce09 100644 --- a/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll +++ b/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll @@ -1,8 +1,8 @@ ; RUN: opt -simplifycfg -S < %s | FileCheck %s define i32 @foo(i32 %i) nounwind ssp { - call void @llvm.dbg.value(metadata !{i32 %i}, i64 0, metadata !6, metadata !{}), !dbg !7 - call void @llvm.dbg.value(metadata !8, i64 0, metadata !9, metadata !{}), !dbg !11 + call void @llvm.dbg.value(metadata i32 %i, i64 0, metadata !6, metadata !{}), !dbg !7 + call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !9, metadata !{}), !dbg !11 %1 = icmp ne i32 %i, 0, !dbg !12 ;CHECK: call i32 (...)* @bar() ;CHECK-NEXT: llvm.dbg.value @@ -10,12 +10,12 @@ define i32 @foo(i32 %i) nounwind ssp { ; <label>:2 ; preds = %0 %3 = call i32 (...)* @bar(), !dbg !13 - call void @llvm.dbg.value(metadata !{i32 %3}, i64 0, metadata !9, metadata !{}), !dbg !13 + call void @llvm.dbg.value(metadata i32 %3, i64 0, metadata !9, metadata !{}), !dbg !13 br label %6, !dbg !15 ; <label>:4 ; preds = %0 %5 = call i32 (...)* @bar(), !dbg !16 - call void @llvm.dbg.value(metadata !{i32 %5}, i64 0, metadata !9, metadata !{}), !dbg !16 + call void @llvm.dbg.value(metadata i32 %5, i64 0, metadata !9, metadata !{}), !dbg !16 br label %6, !dbg !18 ; <label>:6 ; preds = %4, %2 @@ -32,25 +32,25 @@ declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnon !llvm.module.flags = !{!21} !llvm.dbg.sp = !{!0} -!0 = metadata !{metadata !"0x2e\00foo\00foo\00\002\000\001\000\006\00256\000\000", metadata !20, metadata !1, metadata !3, null, i32 (i32)* @foo, null, null, null} ; [ DW_TAG_subprogram ] [line 2] [def] [scope 0] [foo] -!1 = metadata !{metadata !"0x29", metadata !20} ; [ DW_TAG_file_type ] -!2 = metadata !{metadata !"0x11\0012\00clang\001\00\000\00\000", metadata !20, metadata !8, metadata !8, null, null, null} ; [ DW_TAG_compile_unit ] -!3 = metadata !{metadata !"0x15\00\000\000\000\000\000\000", metadata !20, metadata !1, null, metadata !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!4 = metadata !{metadata !5} -!5 = metadata !{metadata !"0x24\00int\000\0032\0032\000\000\005", null, metadata !2} ; [ DW_TAG_base_type ] -!6 = metadata !{metadata !"0x101\00i\0016777218\000", metadata !0, metadata !1, metadata !5} ; [ DW_TAG_arg_variable ] -!7 = metadata !{i32 2, i32 13, metadata !0, null} -!8 = metadata !{i32 0} -!9 = metadata !{metadata !"0x100\00k\003\000", metadata !10, metadata !1, metadata !5} ; [ DW_TAG_auto_variable ] -!10 = metadata !{metadata !"0xb\002\0016\000", metadata !20, metadata !0} ; [ DW_TAG_lexical_block ] -!11 = metadata !{i32 3, i32 12, metadata !10, null} -!12 = metadata !{i32 4, i32 3, metadata !10, null} -!13 = metadata !{i32 5, i32 5, metadata !14, null} -!14 = metadata !{metadata !"0xb\004\0010\001", metadata !20, metadata !10} ; [ DW_TAG_lexical_block ] -!15 = metadata !{i32 6, i32 3, metadata !14, null} -!16 = metadata !{i32 7, i32 5, metadata !17, null} -!17 = metadata !{metadata !"0xb\006\0010\002", metadata !20, metadata !10} ; [ DW_TAG_lexical_block ] -!18 = metadata !{i32 8, i32 3, metadata !17, null} -!19 = metadata !{i32 9, i32 3, metadata !10, null} -!20 = metadata !{metadata !"b.c", metadata !"/private/tmp"} -!21 = metadata !{i32 1, metadata !"Debug Info Version", i32 2} +!0 = !{!"0x2e\00foo\00foo\00\002\000\001\000\006\00256\000\000", !20, !1, !3, null, i32 (i32)* @foo, null, null, null} ; [ DW_TAG_subprogram ] [line 2] [def] [scope 0] [foo] +!1 = !{!"0x29", !20} ; [ DW_TAG_file_type ] +!2 = !{!"0x11\0012\00clang\001\00\000\00\000", !20, !8, !8, null, null, null} ; [ DW_TAG_compile_unit ] +!3 = !{!"0x15\00\000\000\000\000\000\000", !20, !1, null, !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!4 = !{!5} +!5 = !{!"0x24\00int\000\0032\0032\000\000\005", null, !2} ; [ DW_TAG_base_type ] +!6 = !{!"0x101\00i\0016777218\000", !0, !1, !5} ; [ DW_TAG_arg_variable ] +!7 = !MDLocation(line: 2, column: 13, scope: !0) +!8 = !{i32 0} +!9 = !{!"0x100\00k\003\000", !10, !1, !5} ; [ DW_TAG_auto_variable ] +!10 = !{!"0xb\002\0016\000", !20, !0} ; [ DW_TAG_lexical_block ] +!11 = !MDLocation(line: 3, column: 12, scope: !10) +!12 = !MDLocation(line: 4, column: 3, scope: !10) +!13 = !MDLocation(line: 5, column: 5, scope: !14) +!14 = !{!"0xb\004\0010\001", !20, !10} ; [ DW_TAG_lexical_block ] +!15 = !MDLocation(line: 6, column: 3, scope: !14) +!16 = !MDLocation(line: 7, column: 5, scope: !17) +!17 = !{!"0xb\006\0010\002", !20, !10} ; [ DW_TAG_lexical_block ] +!18 = !MDLocation(line: 8, column: 3, scope: !17) +!19 = !MDLocation(line: 9, column: 3, scope: !10) +!20 = !{!"b.c", !"/private/tmp"} +!21 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/SimplifyCFG/hoist-with-range.ll b/test/Transforms/SimplifyCFG/hoist-with-range.ll index 362aa9a..7ca3ff2 100644 --- a/test/Transforms/SimplifyCFG/hoist-with-range.ll +++ b/test/Transforms/SimplifyCFG/hoist-with-range.ll @@ -3,7 +3,7 @@ define void @foo(i1 %c, i8* %p) { ; CHECK: if: ; CHECK-NEXT: load i8* %p, !range !0 -; CHECK: !0 = metadata !{i8 0, i8 1, i8 3, i8 5} +; CHECK: !0 = !{i8 0, i8 1, i8 3, i8 5} if: br i1 %c, label %then, label %else then: @@ -16,5 +16,5 @@ out: ret void } -!0 = metadata !{ i8 0, i8 1 } -!1 = metadata !{ i8 3, i8 5 } +!0 = !{ i8 0, i8 1 } +!1 = !{ i8 3, i8 5 } diff --git a/test/Transforms/SimplifyCFG/preserve-branchweights-partial.ll b/test/Transforms/SimplifyCFG/preserve-branchweights-partial.ll index 8cc07e3..b2b3841 100644 --- a/test/Transforms/SimplifyCFG/preserve-branchweights-partial.ll +++ b/test/Transforms/SimplifyCFG/preserve-branchweights-partial.ll @@ -34,4 +34,4 @@ if.end: ret void } -!0 = metadata !{metadata !"branch_weights", i32 1, i32 0} +!0 = !{!"branch_weights", i32 1, i32 0} diff --git a/test/Transforms/SimplifyCFG/preserve-branchweights-switch-create.ll b/test/Transforms/SimplifyCFG/preserve-branchweights-switch-create.ll index 941f5ad..32a30c3 100644 --- a/test/Transforms/SimplifyCFG/preserve-branchweights-switch-create.ll +++ b/test/Transforms/SimplifyCFG/preserve-branchweights-switch-create.ll @@ -129,12 +129,12 @@ sw.epilog: ret void } -!0 = metadata !{metadata !"branch_weights", i32 64, i32 4} -!1 = metadata !{metadata !"branch_weights", i32 4, i32 64} -; CHECK: !0 = metadata !{metadata !"branch_weights", i32 256, i32 4352, i32 16} -!2 = metadata !{metadata !"branch_weights", i32 4, i32 4, i32 8} -!3 = metadata !{metadata !"branch_weights", i32 8, i32 8, i32 4} -; CHECK: !1 = metadata !{metadata !"branch_weights", i32 32, i32 48, i32 96, i32 16} -!4 = metadata !{metadata !"branch_weights", i32 7, i32 6, i32 4, i32 3} -!5 = metadata !{metadata !"branch_weights", i32 17, i32 13, i32 9} -; CHECK: !3 = metadata !{metadata !"branch_weights", i32 7, i32 3, i32 4, i32 6} +!0 = !{!"branch_weights", i32 64, i32 4} +!1 = !{!"branch_weights", i32 4, i32 64} +; CHECK: !0 = !{!"branch_weights", i32 256, i32 4352, i32 16} +!2 = !{!"branch_weights", i32 4, i32 4, i32 8} +!3 = !{!"branch_weights", i32 8, i32 8, i32 4} +; CHECK: !1 = !{!"branch_weights", i32 32, i32 48, i32 96, i32 16} +!4 = !{!"branch_weights", i32 7, i32 6, i32 4, i32 3} +!5 = !{!"branch_weights", i32 17, i32 13, i32 9} +; CHECK: !3 = !{!"branch_weights", i32 7, i32 3, i32 4, i32 6} diff --git a/test/Transforms/SimplifyCFG/preserve-branchweights.ll b/test/Transforms/SimplifyCFG/preserve-branchweights.ll index bdd25ba..7802a05 100644 --- a/test/Transforms/SimplifyCFG/preserve-branchweights.ll +++ b/test/Transforms/SimplifyCFG/preserve-branchweights.ll @@ -364,29 +364,29 @@ for.exit: ret void } -!0 = metadata !{metadata !"branch_weights", i32 3, i32 5} -!1 = metadata !{metadata !"branch_weights", i32 1, i32 1} -!2 = metadata !{metadata !"branch_weights", i32 1, i32 2} -!3 = metadata !{metadata !"branch_weights", i32 4, i32 3, i32 2, i32 1} -!4 = metadata !{metadata !"branch_weights", i32 4, i32 3, i32 2, i32 1} -!5 = metadata !{metadata !"branch_weights", i32 7, i32 6, i32 5} -!6 = metadata !{metadata !"branch_weights", i32 1, i32 3} -!7 = metadata !{metadata !"branch_weights", i32 33, i32 9, i32 8, i32 7} -!8 = metadata !{metadata !"branch_weights", i32 33, i32 9, i32 8} -!9 = metadata !{metadata !"branch_weights", i32 7, i32 6} -!10 = metadata !{metadata !"branch_weights", i32 672646, i32 21604207} -!11 = metadata !{metadata !"branch_weights", i32 6960, i32 21597248} - -; CHECK: !0 = metadata !{metadata !"branch_weights", i32 5, i32 11} -; CHECK: !1 = metadata !{metadata !"branch_weights", i32 1, i32 5} -; CHECK: !2 = metadata !{metadata !"branch_weights", i32 7, i32 1, i32 2} -; CHECK: !3 = metadata !{metadata !"branch_weights", i32 49, i32 12, i32 24, i32 35} -; CHECK: !4 = metadata !{metadata !"branch_weights", i32 11, i32 5} -; CHECK: !5 = metadata !{metadata !"branch_weights", i32 17, i32 15} -; CHECK: !6 = metadata !{metadata !"branch_weights", i32 9, i32 7} -; CHECK: !7 = metadata !{metadata !"branch_weights", i32 17, i32 9, i32 8, i32 7, i32 17} -; CHECK: !8 = metadata !{metadata !"branch_weights", i32 24, i32 33} -; CHECK: !9 = metadata !{metadata !"branch_weights", i32 8, i32 33} +!0 = !{!"branch_weights", i32 3, i32 5} +!1 = !{!"branch_weights", i32 1, i32 1} +!2 = !{!"branch_weights", i32 1, i32 2} +!3 = !{!"branch_weights", i32 4, i32 3, i32 2, i32 1} +!4 = !{!"branch_weights", i32 4, i32 3, i32 2, i32 1} +!5 = !{!"branch_weights", i32 7, i32 6, i32 5} +!6 = !{!"branch_weights", i32 1, i32 3} +!7 = !{!"branch_weights", i32 33, i32 9, i32 8, i32 7} +!8 = !{!"branch_weights", i32 33, i32 9, i32 8} +!9 = !{!"branch_weights", i32 7, i32 6} +!10 = !{!"branch_weights", i32 672646, i32 21604207} +!11 = !{!"branch_weights", i32 6960, i32 21597248} + +; CHECK: !0 = !{!"branch_weights", i32 5, i32 11} +; CHECK: !1 = !{!"branch_weights", i32 1, i32 5} +; CHECK: !2 = !{!"branch_weights", i32 7, i32 1, i32 2} +; CHECK: !3 = !{!"branch_weights", i32 49, i32 12, i32 24, i32 35} +; CHECK: !4 = !{!"branch_weights", i32 11, i32 5} +; CHECK: !5 = !{!"branch_weights", i32 17, i32 15} +; CHECK: !6 = !{!"branch_weights", i32 9, i32 7} +; CHECK: !7 = !{!"branch_weights", i32 17, i32 9, i32 8, i32 7, i32 17} +; CHECK: !8 = !{!"branch_weights", i32 24, i32 33} +; CHECK: !9 = !{!"branch_weights", i32 8, i32 33} ;; The false weight prints out as a negative integer here, but inside llvm, we ;; treat the weight as an unsigned integer. -; CHECK: !10 = metadata !{metadata !"branch_weights", i32 112017436, i32 -735157296} +; CHECK: !10 = !{!"branch_weights", i32 112017436, i32 -735157296} diff --git a/test/Transforms/SimplifyCFG/seh-nounwind.ll b/test/Transforms/SimplifyCFG/seh-nounwind.ll new file mode 100644 index 0000000..3845e31 --- /dev/null +++ b/test/Transforms/SimplifyCFG/seh-nounwind.ll @@ -0,0 +1,31 @@ +; RUN: opt -S -simplifycfg < %s | FileCheck %s + +; Don't remove invokes of nounwind functions if the personality handles async +; exceptions. The @div function in this test can fault, even though it can't +; throw a synchronous exception. + +define i32 @div(i32 %n, i32 %d) nounwind { +entry: + %div = sdiv i32 %n, %d + ret i32 %div +} + +define i32 @main() nounwind { +entry: + %call = invoke i32 @div(i32 10, i32 0) + to label %__try.cont unwind label %lpad + +lpad: + %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) + catch i8* null + br label %__try.cont + +__try.cont: + %retval.0 = phi i32 [ %call, %entry ], [ 0, %lpad ] + ret i32 %retval.0 +} + +; CHECK-LABEL: define i32 @main() +; CHECK: invoke i32 @div(i32 10, i32 0) + +declare i32 @__C_specific_handler(...) diff --git a/test/Transforms/SimplifyCFG/select-gep.ll b/test/Transforms/SimplifyCFG/select-gep.ll index 96c214c..43e46ca 100644 --- a/test/Transforms/SimplifyCFG/select-gep.ll +++ b/test/Transforms/SimplifyCFG/select-gep.ll @@ -1,27 +1,8 @@ ; RUN: opt -S -simplifycfg < %s | FileCheck %s -define i8* @test1(i8* %x, i64 %y) nounwind { -entry: - %tmp1 = load i8* %x, align 1 - %cmp = icmp eq i8 %tmp1, 47 - br i1 %cmp, label %if.then, label %if.end - -if.then: - %incdec.ptr = getelementptr inbounds i8* %x, i64 %y - br label %if.end - -if.end: - %x.addr = phi i8* [ %incdec.ptr, %if.then ], [ %x, %entry ] - ret i8* %x.addr - -; CHECK-LABEL: @test1( -; CHECK-NOT: select -; CHECK: ret i8* %x.addr -} - %ST = type { i8, i8 } -define i8* @test2(%ST* %x, i8* %y) nounwind { +define i8* @test1(%ST* %x, i8* %y) nounwind { entry: %cmp = icmp eq %ST* %x, null br i1 %cmp, label %if.then, label %if.end @@ -34,7 +15,7 @@ if.end: %x.addr = phi i8* [ %incdec.ptr, %if.then ], [ %y, %entry ] ret i8* %x.addr -; CHECK-LABEL: @test2( +; CHECK-LABEL: @test1( ; CHECK: %incdec.ptr.y = select i1 %cmp, i8* %incdec.ptr, i8* %y ; CHECK: ret i8* %incdec.ptr.y } diff --git a/test/Transforms/SimplifyCFG/sink-common-code.ll b/test/Transforms/SimplifyCFG/sink-common-code.ll index 28d7279..cdb6ed2 100644 --- a/test/Transforms/SimplifyCFG/sink-common-code.ll +++ b/test/Transforms/SimplifyCFG/sink-common-code.ll @@ -4,7 +4,7 @@ define zeroext i1 @test1(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks) { entry: br i1 %flag, label %if.then, label %if.else -; CHECK: test1 +; CHECK-LABEL: test1 ; CHECK: add ; CHECK: select ; CHECK: icmp @@ -30,7 +30,7 @@ define zeroext i1 @test2(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks) { entry: br i1 %flag, label %if.then, label %if.else -; CHECK: test2 +; CHECK-LABEL: test2 ; CHECK: add ; CHECK: select ; CHECK: icmp @@ -51,3 +51,33 @@ if.end: %tobool4 = icmp ne i8 %obeys.0, 0 ret i1 %tobool4 } + +declare i32 @foo(i32, i32) nounwind readnone + +define i32 @test3(i1 zeroext %flag, i32 %x, i32 %y) { +entry: + br i1 %flag, label %if.then, label %if.else + +if.then: + %x0 = call i32 @foo(i32 %x, i32 0) nounwind readnone + %y0 = call i32 @foo(i32 %x, i32 1) nounwind readnone + br label %if.end + +if.else: + %x1 = call i32 @foo(i32 %y, i32 0) nounwind readnone + %y1 = call i32 @foo(i32 %y, i32 1) nounwind readnone + br label %if.end + +if.end: + %xx = phi i32 [ %x0, %if.then ], [ %x1, %if.else ] + %yy = phi i32 [ %y0, %if.then ], [ %y1, %if.else ] + %ret = add i32 %xx, %yy + ret i32 %ret +} + +; CHECK-LABEL: test3 +; CHECK: select +; CHECK: call +; CHECK: call +; CHECK: add +; CHECK-NOT: br diff --git a/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll b/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll new file mode 100644 index 0000000..a109b31 --- /dev/null +++ b/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll @@ -0,0 +1,77 @@ +; RUN: opt %s -simplifycfg -S | FileCheck %s + +declare i32 @f(i32) + +define i32 @basic(i32 %x) { +; CHECK-LABEL: @basic +; CHECK: x.off = add i32 %x, -5 +; CHECK: %switch = icmp ult i32 %x.off, 3 +; CHECK: br i1 %switch, label %a, label %default + +entry: + switch i32 %x, label %default [ + i32 5, label %a + i32 6, label %a + i32 7, label %a + ] +default: + %0 = call i32 @f(i32 0) + ret i32 %0 +a: + %1 = call i32 @f(i32 1) + ret i32 %1 +} + + +define i32 @unreachable(i32 %x) { +; CHECK-LABEL: @unreachable +; CHECK: x.off = add i32 %x, -5 +; CHECK: %switch = icmp ult i32 %x.off, 3 +; CHECK: br i1 %switch, label %a, label %b + +entry: + switch i32 %x, label %unreachable [ + i32 5, label %a + i32 6, label %a + i32 7, label %a + i32 10, label %b + i32 20, label %b + i32 30, label %b + i32 40, label %b + ] +unreachable: + unreachable +a: + %0 = call i32 @f(i32 0) + ret i32 %0 +b: + %1 = call i32 @f(i32 1) + ret i32 %1 +} + + +define i32 @unreachable2(i32 %x) { +; CHECK-LABEL: @unreachable2 +; CHECK: x.off = add i32 %x, -5 +; CHECK: %switch = icmp ult i32 %x.off, 3 +; CHECK: br i1 %switch, label %a, label %b + +entry: + ; Note: folding the most popular case destination into the default + ; would prevent switch-to-icmp here. + switch i32 %x, label %unreachable [ + i32 5, label %a + i32 6, label %a + i32 7, label %a + i32 10, label %b + i32 20, label %b + ] +unreachable: + unreachable +a: + %0 = call i32 @f(i32 0) + ret i32 %0 +b: + %1 = call i32 @f(i32 1) + ret i32 %1 +} diff --git a/test/Transforms/SimplifyCFG/switch-to-br.ll b/test/Transforms/SimplifyCFG/switch-to-br.ll new file mode 100644 index 0000000..01484cd --- /dev/null +++ b/test/Transforms/SimplifyCFG/switch-to-br.ll @@ -0,0 +1,64 @@ +; RUN: opt %s -simplifycfg -S | FileCheck %s + +declare i32 @f(i32) + +define i32 @basic(i32 %x) { +; CHECK-LABEL: @basic +; CHECK-LABEL: entry: +; CHECK-NEXT: call i32 @f(i32 0) +; CHECK-NEXT: ret i32 %0 + +entry: + switch i32 %x, label %default [ + i32 5, label %default + i32 6, label %default + i32 7, label %default + ] +default: + %0 = call i32 @f(i32 0) + ret i32 %0 +} + + +define i32 @constant() { +; CHECK-LABEL: @constant +; CHECK-LABEL: entry: +; CHECK-NEXT: call i32 @f(i32 1) +; CHECK-NEXT: ret i32 %0 + +entry: + switch i32 42, label %default [ + i32 41, label %default + i32 42, label %a + i32 43, label %b + ] +default: + %0 = call i32 @f(i32 0) + ret i32 %0 +a: + %1 = call i32 @f(i32 1) + ret i32 %1 +b: + %2 = call i32 @f(i32 2) + ret i32 %2 +} + + +define i32 @unreachable(i32 %x) { +; CHECK-LABEL: @unreachable +; CHECK-LABEL: entry: +; CHECK-NEXT: call i32 @f(i32 0) +; CHECK-NEXT: ret i32 %0 + +entry: + switch i32 %x, label %unreachable [ + i32 5, label %a + i32 6, label %a + i32 7, label %a + ] +unreachable: + unreachable +a: + %0 = call i32 @f(i32 0) + ret i32 %0 +} diff --git a/test/Transforms/SimplifyCFG/switch-to-select-two-case.ll b/test/Transforms/SimplifyCFG/switch-to-select-two-case.ll index 69f97e5..f4d171a 100644 --- a/test/Transforms/SimplifyCFG/switch-to-select-two-case.ll +++ b/test/Transforms/SimplifyCFG/switch-to-select-two-case.ll @@ -35,38 +35,3 @@ return: %retval.0 = phi i32 [ 4, %sw.epilog ], [ 2, %sw.bb1 ], [ 10, %sw.bb ] ret i32 %retval.0 } - -; int foo1_without_default(int a) { -; switch(a) { -; case 10: -; return 10; -; case 20: -; return 2; -; } -; __builtin_unreachable(); -; } - -define i32 @foo1_without_default(i32 %a) { -; CHECK-LABEL: @foo1_without_default -; CHECK: %switch.selectcmp = icmp eq i32 %a, 10 -; CHECK-NEXT: %switch.select = select i1 %switch.selectcmp, i32 10, i32 2 -; CHECK-NOT: %switch.selectcmp1 -entry: - switch i32 %a, label %sw.epilog [ - i32 10, label %sw.bb - i32 20, label %sw.bb1 - ] - -sw.bb: - br label %return - -sw.bb1: - br label %return - -sw.epilog: - unreachable - -return: - %retval.0 = phi i32 [ 2, %sw.bb1 ], [ 10, %sw.bb ] - ret i32 %retval.0 -} diff --git a/test/Transforms/SimplifyCFG/trap-debugloc.ll b/test/Transforms/SimplifyCFG/trap-debugloc.ll index adf4215..24a286f 100644 --- a/test/Transforms/SimplifyCFG/trap-debugloc.ll +++ b/test/Transforms/SimplifyCFG/trap-debugloc.ll @@ -11,14 +11,14 @@ define void @foo() nounwind ssp { !llvm.module.flags = !{!10} !llvm.dbg.sp = !{!0} -!0 = metadata !{metadata !"0x2e\00foo\00foo\00\003\000\001\000\006\000\000\000", metadata !8, metadata !1, metadata !3, null, void ()* @foo, null, null, null} ; [ DW_TAG_subprogram ] [line 3] [def] [scope 0] [foo] -!1 = metadata !{metadata !"0x29", metadata !8} ; [ DW_TAG_file_type ] -!2 = metadata !{metadata !"0x11\0012\00Apple clang version 3.0 (tags/Apple/clang-206.1) (based on LLVM 3.0svn)\001\00\000\00\000", metadata !8, metadata !4, metadata !4, metadata !9, null, null} ; [ DW_TAG_compile_unit ] -!3 = metadata !{metadata !"0x15\00\000\000\000\000\000\000", metadata !8, metadata !1, null, metadata !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!4 = metadata !{null} -!5 = metadata !{i32 4, i32 2, metadata !6, null} -!6 = metadata !{metadata !"0xb\003\0012\000", metadata !8, metadata !0} ; [ DW_TAG_lexical_block ] -!7 = metadata !{i32 5, i32 1, metadata !6, null} -!8 = metadata !{metadata !"foo.c", metadata !"/private/tmp"} -!9 = metadata !{metadata !0} -!10 = metadata !{i32 1, metadata !"Debug Info Version", i32 2} +!0 = !{!"0x2e\00foo\00foo\00\003\000\001\000\006\000\000\000", !8, !1, !3, null, void ()* @foo, null, null, null} ; [ DW_TAG_subprogram ] [line 3] [def] [scope 0] [foo] +!1 = !{!"0x29", !8} ; [ DW_TAG_file_type ] +!2 = !{!"0x11\0012\00Apple clang version 3.0 (tags/Apple/clang-206.1) (based on LLVM 3.0svn)\001\00\000\00\000", !8, !4, !4, !9, null, null} ; [ DW_TAG_compile_unit ] +!3 = !{!"0x15\00\000\000\000\000\000\000", !8, !1, null, !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!4 = !{null} +!5 = !MDLocation(line: 4, column: 2, scope: !6) +!6 = !{!"0xb\003\0012\000", !8, !0} ; [ DW_TAG_lexical_block ] +!7 = !MDLocation(line: 5, column: 1, scope: !6) +!8 = !{!"foo.c", !"/private/tmp"} +!9 = !{!0} +!10 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/SimplifyCFG/trivial-throw.ll b/test/Transforms/SimplifyCFG/trivial-throw.ll deleted file mode 100644 index ca2b569..0000000 --- a/test/Transforms/SimplifyCFG/trivial-throw.ll +++ /dev/null @@ -1,77 +0,0 @@ -; RUN: opt -simplifycfg -S < %s | FileCheck %s -; <rdar://problem/13360379> - -@_ZTVN10__cxxabiv117__class_type_infoE = external global i8* -@_ZTS13TestException = linkonce_odr constant [16 x i8] c"13TestException\00" -@_ZTI13TestException = linkonce_odr unnamed_addr constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([16 x i8]* @_ZTS13TestException, i32 0, i32 0) } - -define void @throw(i32 %n) #0 { -entry: - %exception = call i8* @__cxa_allocate_exception(i64 1) #4 - call void @__cxa_throw(i8* %exception, i8* bitcast ({ i8*, i8* }* @_ZTI13TestException to i8*), i8* null) #2 - unreachable -} - -define void @func() #0 { -entry: -; CHECK: func() -; CHECK: invoke void @throw -; CHECK-NOT: call void @throw - invoke void @throw(i32 42) #0 - to label %exit unwind label %lpad - -lpad: - %tmp0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) - cleanup - resume { i8*, i32 } %tmp0 - -exit: - invoke void @abort() #2 - to label %invoke.cont unwind label %lpad1 - -invoke.cont: - unreachable - -lpad1: - %tmp1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) - catch i8* bitcast ({ i8*, i8* }* @_ZTI13TestException to i8*) - %tmp2 = extractvalue { i8*, i32 } %tmp1, 1 - %tmp3 = call i32 @llvm.eh.typeid.for(i8* bitcast ({ i8*, i8* }* @_ZTI13TestException to i8*)) #4 - %matches = icmp eq i32 %tmp2, %tmp3 - br i1 %matches, label %catch, label %eh.resume - -catch: - ret void - -eh.resume: - resume { i8*, i32 } %tmp1 -} - -define linkonce_odr hidden void @__clang_call_terminate(i8*) #1 { - %2 = call i8* @__cxa_begin_catch(i8* %0) #4 - call void @_ZSt9terminatev() #5 - unreachable -} - -declare void @abort() #2 - -declare i32 @llvm.eh.typeid.for(i8*) #3 - -declare void @__cxa_end_catch() - -declare i8* @__cxa_allocate_exception(i64) - -declare i32 @__gxx_personality_v0(...) - -declare void @__cxa_throw(i8*, i8*, i8*) - -declare i8* @__cxa_begin_catch(i8*) - -declare void @_ZSt9terminatev() - -attributes #0 = { ssp uwtable } -attributes #1 = { noinline noreturn nounwind } -attributes #2 = { noreturn } -attributes #3 = { nounwind readnone } -attributes #4 = { nounwind } -attributes #5 = { noreturn nounwind } diff --git a/test/Transforms/SimplifyCFG/volatile-phioper.ll b/test/Transforms/SimplifyCFG/volatile-phioper.ll index 1ef3a7c..6367451 100644 --- a/test/Transforms/SimplifyCFG/volatile-phioper.ll +++ b/test/Transforms/SimplifyCFG/volatile-phioper.ll @@ -45,4 +45,4 @@ attributes #0 = { nounwind ssp uwtable "fp-contract-model"="standard" "no-frame- attributes #1 = { "fp-contract-model"="standard" "no-frame-pointer-elim" "no-frame-pointer-elim-non-leaf" "relocation-model"="pic" "ssp-buffers-size"="8" } attributes #2 = { nounwind } -!0 = metadata !{i32 1039} +!0 = !{i32 1039} |