1; RUN: opt < %s -O1 -S | FileCheck %s 2 3; The attribute nomerge prevents the 3 bar() calls from being sunk/hoisted into 4; one inside a function. Check that there are still 3 tail calls. 5 6; Test case for preventing sinking 7; CHECK-LABEL: define void @sink 8; CHECK: if.then: 9; CHECK-NEXT: tail call void @bar() 10; CHECK: if.then2: 11; CHECK-NEXT: tail call void @bar() 12; CHECK: if.end3: 13; CHECK-NEXT: tail call void @bar() 14define void @sink(i32 %i) { 15entry: 16 switch i32 %i, label %if.end3 [ 17 i32 5, label %if.then 18 i32 7, label %if.then2 19 ] 20 21if.then: 22 tail call void @bar() #0 23 br label %if.end3 24 25if.then2: 26 tail call void @bar() #0 27 br label %if.end3 28 29if.end3: 30 tail call void @bar() #0 31 ret void 32} 33 34; Test case for preventing hoisting 35; CHECK-LABEL: define void @hoist 36; CHECK: if.then: 37; CHECK-NEXT: tail call void @bar() 38; CHECK: if.then2: 39; CHECK-NEXT: tail call void @bar() 40; CHECK: if.end: 41; CHECK-NEXT: tail call void @bar() 42define void @hoist(i32 %i) { 43entry: 44 %i.addr = alloca i32, align 4 45 store i32 %i, i32* %i.addr, align 4 46 %0 = load i32, i32* %i.addr, align 4 47 %cmp = icmp eq i32 %0, 5 48 br i1 %cmp, label %if.then, label %if.else 49 50if.then: 51 tail call void @bar() #1 52 unreachable 53 54if.else: 55 %1 = load i32, i32* %i.addr, align 4 56 %cmp1 = icmp eq i32 %i, 7 57 br i1 %cmp1, label %if.then2, label %if.end 58 59if.then2: 60 tail call void @bar() #1 61 unreachable 62 63if.end: 64 tail call void @bar() #1 65 unreachable 66} 67 68declare void @bar() 69 70attributes #0 = { nomerge } 71attributes #1 = { noreturn nomerge } 72