1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple riscv32 -mattr=+experimental-zicfilp < %s | FileCheck %s --check-prefixes=CHECK,RV32 3; RUN: llc -mtriple riscv64 -mattr=+experimental-zicfilp < %s | FileCheck %s --check-prefixes=CHECK,RV64 4; RUN: llc -mtriple riscv32 -mattr=+experimental-zicfilp \ 5; RUN: -riscv-landing-pad-label=1 < %s | FileCheck %s --check-prefixes=FIXED-ONE,FIXED-ONE-RV32 6; RUN: llc -mtriple riscv64 -mattr=+experimental-zicfilp \ 7; RUN: -riscv-landing-pad-label=1 < %s | FileCheck %s --check-prefixes=FIXED-ONE,FIXED-ONE-RV64 8 9; Check indirectbr. 10@__const.indirctbr.addr = private unnamed_addr constant [2 x ptr] [ptr blockaddress(@indirctbr, %labelA), ptr blockaddress(@indirctbr, %labelB)], align 8 11define void @indirctbr(i32 %i, ptr %p) { 12; RV32-LABEL: indirctbr: 13; RV32: # %bb.0: # %entry 14; RV32-NEXT: lpad 0 15; RV32-NEXT: slli a0, a0, 2 16; RV32-NEXT: lui a2, %hi(.L__const.indirctbr.addr) 17; RV32-NEXT: addi a2, a2, %lo(.L__const.indirctbr.addr) 18; RV32-NEXT: add a0, a2, a0 19; RV32-NEXT: lw a0, 0(a0) 20; RV32-NEXT: jr a0 21; RV32-NEXT: .p2align 2 22; RV32-NEXT: .Ltmp3: # Block address taken 23; RV32-NEXT: .LBB0_1: # %labelA 24; RV32-NEXT: lpad 0 25; RV32-NEXT: li a0, 1 26; RV32-NEXT: sw a0, 0(a1) 27; RV32-NEXT: .p2align 2 28; RV32-NEXT: .Ltmp4: # Block address taken 29; RV32-NEXT: .LBB0_2: # %labelB 30; RV32-NEXT: lpad 0 31; RV32-NEXT: li a0, 2 32; RV32-NEXT: sw a0, 0(a1) 33; RV32-NEXT: ret 34; 35; RV64-LABEL: indirctbr: 36; RV64: # %bb.0: # %entry 37; RV64-NEXT: lpad 0 38; RV64-NEXT: sext.w a0, a0 39; RV64-NEXT: slli a0, a0, 3 40; RV64-NEXT: lui a2, %hi(.L__const.indirctbr.addr) 41; RV64-NEXT: addi a2, a2, %lo(.L__const.indirctbr.addr) 42; RV64-NEXT: add a0, a2, a0 43; RV64-NEXT: ld a0, 0(a0) 44; RV64-NEXT: jr a0 45; RV64-NEXT: .p2align 2 46; RV64-NEXT: .Ltmp3: # Block address taken 47; RV64-NEXT: .LBB0_1: # %labelA 48; RV64-NEXT: lpad 0 49; RV64-NEXT: li a0, 1 50; RV64-NEXT: sw a0, 0(a1) 51; RV64-NEXT: .p2align 2 52; RV64-NEXT: .Ltmp4: # Block address taken 53; RV64-NEXT: .LBB0_2: # %labelB 54; RV64-NEXT: lpad 0 55; RV64-NEXT: li a0, 2 56; RV64-NEXT: sw a0, 0(a1) 57; RV64-NEXT: ret 58; 59; FIXED-ONE-RV32-LABEL: indirctbr: 60; FIXED-ONE-RV32: # %bb.0: # %entry 61; FIXED-ONE-RV32-NEXT: lpad 1 62; FIXED-ONE-RV32-NEXT: slli a0, a0, 2 63; FIXED-ONE-RV32-NEXT: lui a2, %hi(.L__const.indirctbr.addr) 64; FIXED-ONE-RV32-NEXT: addi a2, a2, %lo(.L__const.indirctbr.addr) 65; FIXED-ONE-RV32-NEXT: add a0, a2, a0 66; FIXED-ONE-RV32-NEXT: lw a0, 0(a0) 67; FIXED-ONE-RV32-NEXT: lui t2, 1 68; FIXED-ONE-RV32-NEXT: jr a0 69; FIXED-ONE-RV32-NEXT: .p2align 2 70; FIXED-ONE-RV32-NEXT: .Ltmp3: # Block address taken 71; FIXED-ONE-RV32-NEXT: .LBB0_1: # %labelA 72; FIXED-ONE-RV32-NEXT: lpad 1 73; FIXED-ONE-RV32-NEXT: li a0, 1 74; FIXED-ONE-RV32-NEXT: sw a0, 0(a1) 75; FIXED-ONE-RV32-NEXT: .p2align 2 76; FIXED-ONE-RV32-NEXT: .Ltmp4: # Block address taken 77; FIXED-ONE-RV32-NEXT: .LBB0_2: # %labelB 78; FIXED-ONE-RV32-NEXT: lpad 1 79; FIXED-ONE-RV32-NEXT: li a0, 2 80; FIXED-ONE-RV32-NEXT: sw a0, 0(a1) 81; FIXED-ONE-RV32-NEXT: ret 82; 83; FIXED-ONE-RV64-LABEL: indirctbr: 84; FIXED-ONE-RV64: # %bb.0: # %entry 85; FIXED-ONE-RV64-NEXT: lpad 1 86; FIXED-ONE-RV64-NEXT: sext.w a0, a0 87; FIXED-ONE-RV64-NEXT: slli a0, a0, 3 88; FIXED-ONE-RV64-NEXT: lui a2, %hi(.L__const.indirctbr.addr) 89; FIXED-ONE-RV64-NEXT: addi a2, a2, %lo(.L__const.indirctbr.addr) 90; FIXED-ONE-RV64-NEXT: add a0, a2, a0 91; FIXED-ONE-RV64-NEXT: ld a0, 0(a0) 92; FIXED-ONE-RV64-NEXT: lui t2, 1 93; FIXED-ONE-RV64-NEXT: jr a0 94; FIXED-ONE-RV64-NEXT: .p2align 2 95; FIXED-ONE-RV64-NEXT: .Ltmp3: # Block address taken 96; FIXED-ONE-RV64-NEXT: .LBB0_1: # %labelA 97; FIXED-ONE-RV64-NEXT: lpad 1 98; FIXED-ONE-RV64-NEXT: li a0, 1 99; FIXED-ONE-RV64-NEXT: sw a0, 0(a1) 100; FIXED-ONE-RV64-NEXT: .p2align 2 101; FIXED-ONE-RV64-NEXT: .Ltmp4: # Block address taken 102; FIXED-ONE-RV64-NEXT: .LBB0_2: # %labelB 103; FIXED-ONE-RV64-NEXT: lpad 1 104; FIXED-ONE-RV64-NEXT: li a0, 2 105; FIXED-ONE-RV64-NEXT: sw a0, 0(a1) 106; FIXED-ONE-RV64-NEXT: ret 107entry: 108 %arrayidx = getelementptr inbounds [2 x ptr], ptr @__const.indirctbr.addr, i64 0, i32 %i 109 %0 = load ptr, ptr %arrayidx 110 indirectbr ptr %0, [label %labelA, label %labelB] 111 112labelA: ; preds = %entry 113 store volatile i32 1, ptr %p 114 br label %labelB 115 116labelB: ; preds = %labelA, %entry 117 store volatile i32 2, ptr %p 118 ret void 119} 120 121; Check indirect call. 122define void @call(ptr %0) { 123; CHECK-LABEL: call: 124; CHECK: # %bb.0: 125; CHECK-NEXT: lpad 0 126; CHECK-NEXT: jr a0 127; 128; FIXED-ONE-LABEL: call: 129; FIXED-ONE: # %bb.0: 130; FIXED-ONE-NEXT: lpad 1 131; FIXED-ONE-NEXT: lui t2, 1 132; FIXED-ONE-NEXT: jr a0 133 tail call void %0() 134 ret void 135} 136 137; Check invoke. 138declare dso_local i32 @__gxx_personality_v0(...) 139define void @invoke(ptr %f) personality ptr @__gxx_personality_v0 { 140; RV32-LABEL: invoke: 141; RV32: # %bb.0: # %entry 142; RV32-NEXT: lpad 0 143; RV32-NEXT: addi sp, sp, -16 144; RV32-NEXT: .cfi_def_cfa_offset 16 145; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 146; RV32-NEXT: .cfi_offset ra, -4 147; RV32-NEXT: .cfi_remember_state 148; RV32-NEXT: .Ltmp0: 149; RV32-NEXT: jalr a0 150; RV32-NEXT: .Ltmp1: 151; RV32-NEXT: .LBB2_1: # %try.cont 152; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 153; RV32-NEXT: .cfi_restore ra 154; RV32-NEXT: addi sp, sp, 16 155; RV32-NEXT: .cfi_def_cfa_offset 0 156; RV32-NEXT: ret 157; RV32-NEXT: .LBB2_2: # %lpad 158; RV32-NEXT: .cfi_restore_state 159; RV32-NEXT: .Ltmp2: 160; RV32-NEXT: j .LBB2_1 161; 162; RV64-LABEL: invoke: 163; RV64: # %bb.0: # %entry 164; RV64-NEXT: lpad 0 165; RV64-NEXT: addi sp, sp, -16 166; RV64-NEXT: .cfi_def_cfa_offset 16 167; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 168; RV64-NEXT: .cfi_offset ra, -8 169; RV64-NEXT: .cfi_remember_state 170; RV64-NEXT: .Ltmp0: 171; RV64-NEXT: jalr a0 172; RV64-NEXT: .Ltmp1: 173; RV64-NEXT: .LBB2_1: # %try.cont 174; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 175; RV64-NEXT: .cfi_restore ra 176; RV64-NEXT: addi sp, sp, 16 177; RV64-NEXT: .cfi_def_cfa_offset 0 178; RV64-NEXT: ret 179; RV64-NEXT: .LBB2_2: # %lpad 180; RV64-NEXT: .cfi_restore_state 181; RV64-NEXT: .Ltmp2: 182; RV64-NEXT: j .LBB2_1 183; 184; FIXED-ONE-RV32-LABEL: invoke: 185; FIXED-ONE-RV32: # %bb.0: # %entry 186; FIXED-ONE-RV32-NEXT: lpad 1 187; FIXED-ONE-RV32-NEXT: addi sp, sp, -16 188; FIXED-ONE-RV32-NEXT: .cfi_def_cfa_offset 16 189; FIXED-ONE-RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 190; FIXED-ONE-RV32-NEXT: .cfi_offset ra, -4 191; FIXED-ONE-RV32-NEXT: .cfi_remember_state 192; FIXED-ONE-RV32-NEXT: .Ltmp0: 193; FIXED-ONE-RV32-NEXT: lui t2, 1 194; FIXED-ONE-RV32-NEXT: jalr a0 195; FIXED-ONE-RV32-NEXT: .Ltmp1: 196; FIXED-ONE-RV32-NEXT: .LBB2_1: # %try.cont 197; FIXED-ONE-RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 198; FIXED-ONE-RV32-NEXT: .cfi_restore ra 199; FIXED-ONE-RV32-NEXT: addi sp, sp, 16 200; FIXED-ONE-RV32-NEXT: .cfi_def_cfa_offset 0 201; FIXED-ONE-RV32-NEXT: ret 202; FIXED-ONE-RV32-NEXT: .LBB2_2: # %lpad 203; FIXED-ONE-RV32-NEXT: .cfi_restore_state 204; FIXED-ONE-RV32-NEXT: .Ltmp2: 205; FIXED-ONE-RV32-NEXT: j .LBB2_1 206; 207; FIXED-ONE-RV64-LABEL: invoke: 208; FIXED-ONE-RV64: # %bb.0: # %entry 209; FIXED-ONE-RV64-NEXT: lpad 1 210; FIXED-ONE-RV64-NEXT: addi sp, sp, -16 211; FIXED-ONE-RV64-NEXT: .cfi_def_cfa_offset 16 212; FIXED-ONE-RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 213; FIXED-ONE-RV64-NEXT: .cfi_offset ra, -8 214; FIXED-ONE-RV64-NEXT: .cfi_remember_state 215; FIXED-ONE-RV64-NEXT: .Ltmp0: 216; FIXED-ONE-RV64-NEXT: lui t2, 1 217; FIXED-ONE-RV64-NEXT: jalr a0 218; FIXED-ONE-RV64-NEXT: .Ltmp1: 219; FIXED-ONE-RV64-NEXT: .LBB2_1: # %try.cont 220; FIXED-ONE-RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 221; FIXED-ONE-RV64-NEXT: .cfi_restore ra 222; FIXED-ONE-RV64-NEXT: addi sp, sp, 16 223; FIXED-ONE-RV64-NEXT: .cfi_def_cfa_offset 0 224; FIXED-ONE-RV64-NEXT: ret 225; FIXED-ONE-RV64-NEXT: .LBB2_2: # %lpad 226; FIXED-ONE-RV64-NEXT: .cfi_restore_state 227; FIXED-ONE-RV64-NEXT: .Ltmp2: 228; FIXED-ONE-RV64-NEXT: j .LBB2_1 229entry: 230 invoke void %f() to label %try.cont unwind label %lpad 231 232lpad: 233 %0 = landingpad { ptr, i32 } cleanup 234 br label %try.cont 235 236try.cont: 237 ret void 238} 239 240; Check external linkage function. 241define void @external() { 242; CHECK-LABEL: external: 243; CHECK: # %bb.0: 244; CHECK-NEXT: lpad 0 245; CHECK-NEXT: ret 246; 247; FIXED-ONE-LABEL: external: 248; FIXED-ONE: # %bb.0: 249; FIXED-ONE-NEXT: lpad 1 250; FIXED-ONE-NEXT: ret 251 ret void 252} 253 254; Check internal linkage function. 255define internal void @internal() { 256; CHECK-LABEL: internal: 257; CHECK: # %bb.0: 258; CHECK-NEXT: ret 259; 260; FIXED-ONE-LABEL: internal: 261; FIXED-ONE: # %bb.0: 262; FIXED-ONE-NEXT: ret 263 ret void 264} 265 266; Check internal linkage function with taken address. 267@foo = constant ptr @internal2 268define internal void @internal2() { 269; CHECK-LABEL: internal2: 270; CHECK: # %bb.0: 271; CHECK-NEXT: lpad 0 272; CHECK-NEXT: ret 273; 274; FIXED-ONE-LABEL: internal2: 275; FIXED-ONE: # %bb.0: 276; FIXED-ONE-NEXT: lpad 1 277; FIXED-ONE-NEXT: ret 278 ret void 279} 280 281; Check interrupt function does not need landing pad. 282define void @interrupt() "interrupt"="user" { 283; CHECK-LABEL: interrupt: 284; CHECK: # %bb.0: 285; CHECK-NEXT: mret 286; 287; FIXED-ONE-LABEL: interrupt: 288; FIXED-ONE: # %bb.0: 289; FIXED-ONE-NEXT: mret 290 ret void 291} 292