1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=thumbv7m-arm-none-eabi | FileCheck %s 3 4define internal i32 @table_switch(i32 %x) "branch-target-enforcement" { 5; CHECK-LABEL: table_switch: 6; CHECK: @ %bb.0: @ %entry 7; CHECK-NEXT: bti 8; CHECK-NEXT: subs r1, r0, #1 9; CHECK-NEXT: cmp r1, #3 10; CHECK-NEXT: bhi .LBB0_6 11; CHECK-NEXT: @ %bb.1: @ %entry 12; CHECK-NEXT: .LCPI0_0: 13; CHECK-NEXT: tbb [pc, r1] 14; CHECK-NEXT: @ %bb.2: 15; CHECK-NEXT: .LJTI0_0: 16; CHECK-NEXT: .byte (.LBB0_7-(.LCPI0_0+4))/2 17; CHECK-NEXT: .byte (.LBB0_3-(.LCPI0_0+4))/2 18; CHECK-NEXT: .byte (.LBB0_4-(.LCPI0_0+4))/2 19; CHECK-NEXT: .byte (.LBB0_5-(.LCPI0_0+4))/2 20; CHECK-NEXT: .p2align 1 21; CHECK-NEXT: .LBB0_3: @ %bb2 22; CHECK-NEXT: movs r0, #2 23; CHECK-NEXT: bx lr 24; CHECK-NEXT: .LBB0_4: @ %bb3 25; CHECK-NEXT: movs r0, #3 26; CHECK-NEXT: bx lr 27; CHECK-NEXT: .LBB0_5: @ %bb4 28; CHECK-NEXT: movs r0, #4 29; CHECK-NEXT: bx lr 30; CHECK-NEXT: .LBB0_6: @ %sw.epilog 31; CHECK-NEXT: movs r0, #0 32; CHECK-NEXT: .LBB0_7: @ %return 33; CHECK-NEXT: bx lr 34entry: 35 switch i32 %x, label %sw.epilog [ 36 i32 1, label %bb1 37 i32 2, label %bb2 38 i32 3, label %bb3 39 i32 4, label %bb4 40 ] 41 42bb1: 43 br label %return 44bb2: 45 br label %return 46bb3: 47 br label %return 48bb4: 49 br label %return 50sw.epilog: 51 br label %return 52 53return: 54 %ret = phi i32 [ 0, %sw.epilog ], [ 1, %bb1 ], [ 2, %bb2 ], [ 3, %bb3 ], [ 4, %bb4 ] 55 ret i32 %ret 56} 57 58@computed_goto_cases = private unnamed_addr constant [2 x ptr] [ptr blockaddress(@computed_goto, %return), ptr blockaddress(@computed_goto, %case_1)], align 4 59 60define internal i32 @computed_goto(i32 %x) "branch-target-enforcement" { 61; CHECK-LABEL: computed_goto: 62; CHECK: @ %bb.0: @ %entry 63; CHECK-NEXT: bti 64; CHECK-NEXT: movw r1, :lower16:.Lcomputed_goto_cases 65; CHECK-NEXT: movt r1, :upper16:.Lcomputed_goto_cases 66; CHECK-NEXT: ldr.w r0, [r1, r0, lsl #2] 67; CHECK-NEXT: mov pc, r0 68; CHECK-NEXT: .Ltmp3: @ Block address taken 69; CHECK-NEXT: .LBB1_1: @ %return 70; CHECK-NEXT: bti 71; CHECK-NEXT: movs r0, #2 72; CHECK-NEXT: bx lr 73; CHECK-NEXT: .Ltmp4: @ Block address taken 74; CHECK-NEXT: .LBB1_2: @ %case_1 75; CHECK-NEXT: bti 76; CHECK-NEXT: movs r0, #1 77; CHECK-NEXT: bx lr 78entry: 79 %arrayidx = getelementptr inbounds [2 x ptr], ptr @computed_goto_cases, i32 0, i32 %x 80 %0 = load ptr, ptr %arrayidx, align 4 81 indirectbr ptr %0, [label %return, label %case_1] 82 83case_1: 84 br label %return 85 86return: 87 %ret = phi i32 [ 1, %case_1 ], [ 2, %entry ] 88 ret i32 %ret 89} 90 91declare void @may_throw() 92declare void @consume_exception(ptr) 93declare i32 @__gxx_personality_v0(...) 94 95define internal i32 @exception_handling(i32 %0) "branch-target-enforcement" personality ptr @__gxx_personality_v0 { 96; CHECK-LABEL: exception_handling: 97; CHECK: @ %bb.0: 98; CHECK-NEXT: bti 99; CHECK-NEXT: .save {r7, lr} 100; CHECK-NEXT: push {r7, lr} 101; CHECK-NEXT: .Ltmp0: 102; CHECK-NEXT: bl may_throw 103; CHECK-NEXT: .Ltmp1: 104; CHECK-NEXT: @ %bb.1: 105; CHECK-NEXT: movs r0, #0 106; CHECK-NEXT: pop {r7, pc} 107; CHECK-NEXT: .LBB2_2: 108; CHECK-NEXT: .Ltmp2: 109; CHECK-NEXT: bti 110; CHECK-NEXT: bl consume_exception 111; CHECK-NEXT: movs r0, #1 112; CHECK-NEXT: pop {r7, pc} 113entry: 114 invoke void @may_throw() 115 to label %return unwind label %lpad 116 117lpad: 118 %1 = landingpad { ptr, i32 } 119 catch ptr null 120 %2 = extractvalue { ptr, i32 } %1, 0 121 call void @consume_exception(ptr %2) 122 br label %return 123 124return: 125 %retval.0 = phi i32 [ 1, %lpad ], [ 0, %entry ] 126 ret i32 %retval.0 127} 128