; RUN: opt -S -jump-threading < %s | FileCheck %s declare void @foo() declare void @bar() declare void @baz() declare void @quux() ; Jump threading of branch with select as condition. ; Mostly theoretical since instruction combining simplifies all selects of ; booleans where at least one operand is true/false/undef. ; CHECK: @test_br ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 %cond, label %L1, define void @test_br(i1 %cond, i1 %value) nounwind { entry: br i1 %cond, label %L0, label %L3 L0: %expr = select i1 %cond, i1 true, i1 %value br i1 %expr, label %L1, label %L2 L1: call void @foo() ret void L2: call void @bar() ret void L3: call void @baz() br label %L0 } ; Jump threading of switch with select as condition. ; CHECK: @test_switch ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 %cond, label %L1, define void @test_switch(i1 %cond, i8 %value) nounwind { entry: br i1 %cond, label %L0, label %L4 L0: %expr = select i1 %cond, i8 1, i8 %value switch i8 %expr, label %L3 [i8 1, label %L1 i8 2, label %L2] L1: call void @foo() ret void L2: call void @bar() ret void L3: call void @baz() ret void L4: call void @quux() br label %L0 } ; Make sure the blocks in the indirectbr test aren't trivially removable as ; successors by taking their addresses. @anchor = constant [3 x i8*] [ i8* blockaddress(@test_indirectbr, %L1), i8* blockaddress(@test_indirectbr, %L2), i8* blockaddress(@test_indirectbr, %L3) ] ; Jump threading of indirectbr with select as address. ; CHECK: @test_indirectbr ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 %cond, label %L1, label %L3 define void @test_indirectbr(i1 %cond, i8* %address) nounwind { entry: br i1 %cond, label %L0, label %L3 L0: %indirect.goto.dest = select i1 %cond, i8* blockaddress(@test_indirectbr, %L1), i8* %address indirectbr i8* %indirect.goto.dest, [label %L1, label %L2, label %L3] L1: call void @foo() ret void L2: call void @bar() ret void L3: call void @baz() ret void } ; A more complicated case: the condition is a select based on a comparison. ; CHECK: @test_switch_cmp ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 %cond, label %L0, label %[[THREADED:[A-Za-z.0-9]+]] ; CHECK: [[THREADED]]: ; CHECK-NEXT: call void @quux ; CHECK-NEXT: br label %L1 define void @test_switch_cmp(i1 %cond, i32 %val, i8 %value) nounwind { entry: br i1 %cond, label %L0, label %L4 L0: %val.phi = phi i32 [%val, %entry], [-1, %L4] %cmp = icmp slt i32 %val.phi, 0 %expr = select i1 %cmp, i8 1, i8 %value switch i8 %expr, label %L3 [i8 1, label %L1 i8 2, label %L2] L1: call void @foo() ret void L2: call void @bar() ret void L3: call void @baz() ret void L4: call void @quux() br label %L0 }