1; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ 2; RUN: -mcpu=pwr10 -ppc-asm-full-reg-names < %s \ 3; RUN: | FileCheck %s --check-prefixes=CHECK-S,CHECK-ALL 4; RUN: llc -verify-machineinstrs -target-abi=elfv2 -mtriple=powerpc64-- \ 5; RUN: -mcpu=pwr10 -ppc-asm-full-reg-names < %s \ 6; RUN: | FileCheck %s --check-prefixes=CHECK-S,CHECK-ALL 7; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ 8; RUN: -mcpu=pwr9 -ppc-asm-full-reg-names < %s \ 9; RUN: | FileCheck %s --check-prefixes=CHECK-P9,CHECK-ALL 10 11@globalVar = common dso_local local_unnamed_addr global i32 0, align 4 12@externGlobalVar = external local_unnamed_addr global i32, align 4 13@indirectCall = common dso_local local_unnamed_addr global i32 (i32)* null, align 8 14 15; This funcion needs to remain as noinline. 16; The compiler needs to know this function is local but must be forced to call 17; it. The only thing we really need to check here is that st_other=0 and 18; so we make sure that there is no .localentry. 19define dso_local signext i32 @localCall(i32 signext %a) local_unnamed_addr #0 { 20; CHECK-ALL-LABEL: localCall: 21; CHECK-S-NOT: .localentry 22; CHECK-S: addi r3, r3, 5 23; CHECK-S-NEXT: extsw r3, r3 24; CHECK-S-NEXT: blr 25entry: 26 %add = add nsw i32 %a, 5 27 ret i32 %add 28} 29 30define dso_local signext i32 @DirectCallLocal1(i32 signext %a, i32 signext %b) local_unnamed_addr { 31; CHECK-ALL-LABEL: DirectCallLocal1: 32; CHECK-S: .localentry DirectCallLocal1 33; CHECK-S: # %bb.0: # %entry 34; CHECK-S-NEXT: mflr r0 35; CHECK-S-NEXT: std r0, 16(r1) 36; CHECK-S-NEXT: stdu r1, -32(r1) 37; CHECK-S-NEXT: .cfi_def_cfa_offset 32 38; CHECK-S-NEXT: .cfi_offset lr, 16 39; CHECK-S-NEXT: add r3, r4, r3 40; CHECK-S-NEXT: extsw r3, r3 41; CHECK-S-NEXT: bl localCall@notoc 42; CHECK-S-NEXT: plwz r4, globalVar@PCREL(0), 1 43; CHECK-S-NEXT: mullw r3, r4, r3 44; CHECK-S-NEXT: extsw r3, r3 45; CHECK-S-NEXT: addi r1, r1, 32 46; CHECK-S-NEXT: ld r0, 16(r1) 47; CHECK-S-NEXT: mtlr r0 48; CHECK-S-NEXT: blr 49entry: 50 %add = add nsw i32 %b, %a 51 %call = tail call signext i32 @localCall(i32 signext %add) 52 %0 = load i32, i32* @globalVar, align 4 53 %mul = mul nsw i32 %0, %call 54 ret i32 %mul 55} 56 57define dso_local signext i32 @DirectCallLocal2(i32 signext %a, i32 signext %b) local_unnamed_addr { 58; CHECK-ALL-LABEL: DirectCallLocal2: 59; CHECK-S: .localentry DirectCallLocal2 60; CHECK-S: # %bb.0: # %entry 61; CHECK-S-NEXT: mflr r0 62; CHECK-S-NEXT: std r0, 16(r1) 63; CHECK-S-NEXT: stdu r1, -32(r1) 64; CHECK-S-NEXT: .cfi_def_cfa_offset 32 65; CHECK-S-NEXT: .cfi_offset lr, 16 66; CHECK-S-NEXT: add r3, r4, r3 67; CHECK-S-NEXT: extsw r3, r3 68; CHECK-S-NEXT: bl localCall@notoc 69; CHECK-S-NEXT: pld r4, externGlobalVar@got@pcrel(0), 1 70; CHECK-S-NEXT: .Lpcrel: 71; CHECK-S-NEXT: .reloc .Lpcrel-8,R_PPC64_PCREL_OPT,.-(.Lpcrel-8) 72; CHECK-S-NEXT: lwz r4, 0(r4) 73; CHECK-S-NEXT: mullw r3, r4, r3 74; CHECK-S-NEXT: extsw r3, r3 75; CHECK-S-NEXT: addi r1, r1, 32 76; CHECK-S-NEXT: ld r0, 16(r1) 77; CHECK-S-NEXT: mtlr r0 78; CHECK-S-NEXT: blr 79entry: 80 %add = add nsw i32 %b, %a 81 %call = tail call signext i32 @localCall(i32 signext %add) 82 %0 = load i32, i32* @externGlobalVar, align 4 83 %mul = mul nsw i32 %0, %call 84 ret i32 %mul 85} 86 87define dso_local signext i32 @DirectCallLocalNoGlobal(i32 signext %a, i32 signext %b) local_unnamed_addr { 88; CHECK-ALL-LABEL: DirectCallLocalNoGlobal: 89; CHECK-S: .localentry DirectCallLocalNoGlobal, 1 90; CHECK-S-NEXT: # %bb.0: # %entry 91; CHECK-S-NEXT: mflr r0 92; CHECK-S-NEXT: .cfi_def_cfa_offset 48 93; CHECK-S-NEXT: .cfi_offset lr, 16 94; CHECK-S-NEXT: .cfi_offset r30, -16 95; CHECK-S-NEXT: std r30, -16(r1) # 8-byte Folded Spill 96; CHECK-S-NEXT: std r0, 16(r1) 97; CHECK-S-NEXT: stdu r1, -48(r1) 98; CHECK-S-NEXT: mr r30, r4 99; CHECK-S-NEXT: bl localCall@notoc 100; CHECK-S-NEXT: add r3, r3, r30 101; CHECK-S-NEXT: extsw r3, r3 102; CHECK-S-NEXT: addi r1, r1, 48 103; CHECK-S-NEXT: ld r0, 16(r1) 104; CHECK-S-NEXT: ld r30, -16(r1) # 8-byte Folded Reload 105; CHECK-S-NEXT: mtlr r0 106; CHECK-S-NEXT: blr 107entry: 108 %call = tail call signext i32 @localCall(i32 signext %a) 109 %add = add nsw i32 %call, %b 110 ret i32 %add 111} 112 113define dso_local signext i32 @DirectCallExtern1(i32 signext %a, i32 signext %b) local_unnamed_addr { 114; CHECK-ALL-LABEL: DirectCallExtern1: 115; CHECK-S: .localentry DirectCallExtern1 116; CHECK-S: # %bb.0: # %entry 117; CHECK-S-NEXT: mflr r0 118; CHECK-S-NEXT: std r0, 16(r1) 119; CHECK-S-NEXT: stdu r1, -32(r1) 120; CHECK-S-NEXT: .cfi_def_cfa_offset 32 121; CHECK-S-NEXT: .cfi_offset lr, 16 122; CHECK-S-NEXT: add r3, r4, r3 123; CHECK-S-NEXT: extsw r3, r3 124; CHECK-S-NEXT: bl externCall@notoc 125; CHECK-S-NEXT: plwz r4, globalVar@PCREL(0), 1 126; CHECK-S-NEXT: mullw r3, r4, r3 127; CHECK-S-NEXT: extsw r3, r3 128; CHECK-S-NEXT: addi r1, r1, 32 129; CHECK-S-NEXT: ld r0, 16(r1) 130; CHECK-S-NEXT: mtlr r0 131; CHECK-S-NEXT: blr 132entry: 133 %add = add nsw i32 %b, %a 134 %call = tail call signext i32 @externCall(i32 signext %add) 135 %0 = load i32, i32* @globalVar, align 4 136 %mul = mul nsw i32 %0, %call 137 ret i32 %mul 138} 139 140declare signext i32 @externCall(i32 signext) local_unnamed_addr 141 142define dso_local signext i32 @DirectCallExtern2(i32 signext %a, i32 signext %b) local_unnamed_addr { 143; CHECK-ALL-LABEL: DirectCallExtern2: 144; CHECK-S: .localentry DirectCallExtern2 145; CHECK-S: # %bb.0: # %entry 146; CHECK-S-NEXT: mflr r0 147; CHECK-S-NEXT: std r0, 16(r1) 148; CHECK-S-NEXT: stdu r1, -32(r1) 149; CHECK-S-NEXT: .cfi_def_cfa_offset 32 150; CHECK-S-NEXT: .cfi_offset lr, 16 151; CHECK-S-NEXT: add r3, r4, r3 152; CHECK-S-NEXT: extsw r3, r3 153; CHECK-S-NEXT: bl externCall@notoc 154; CHECK-S-NEXT: pld r4, externGlobalVar@got@pcrel(0), 1 155; CHECK-S-NEXT: .Lpcrel0: 156; CHECK-S-NEXT: .reloc .Lpcrel0-8,R_PPC64_PCREL_OPT,.-(.Lpcrel0-8) 157; CHECK-S-NEXT: lwz r4, 0(r4) 158; CHECK-S-NEXT: mullw r3, r4, r3 159; CHECK-S-NEXT: extsw r3, r3 160; CHECK-S-NEXT: addi r1, r1, 32 161; CHECK-S-NEXT: ld r0, 16(r1) 162; CHECK-S-NEXT: mtlr r0 163; CHECK-S-NEXT: blr 164entry: 165 %add = add nsw i32 %b, %a 166 %call = tail call signext i32 @externCall(i32 signext %add) 167 %0 = load i32, i32* @externGlobalVar, align 4 168 %mul = mul nsw i32 %0, %call 169 ret i32 %mul 170} 171 172define dso_local signext i32 @DirectCallExternNoGlobal(i32 signext %a, i32 signext %b) local_unnamed_addr { 173; CHECK-ALL-LABEL: DirectCallExternNoGlobal: 174; CHECK-S: .localentry DirectCallExternNoGlobal, 1 175; CHECK-P9: .localentry DirectCallExternNoGlobal, .Lfunc_lep6-.Lfunc_gep6 176; CHECK-ALL: # %bb.0: # %entry 177; CHECK-S-NEXT: mflr r0 178; CHECK-S-NEXT: .cfi_def_cfa_offset 48 179; CHECK-S-NEXT: .cfi_offset lr, 16 180; CHECK-S-NEXT: .cfi_offset r30, -16 181; CHECK-S-NEXT: std r30, -16(r1) # 8-byte Folded Spill 182; CHECK-S-NEXT: std r0, 16(r1) 183; CHECK-S-NEXT: stdu r1, -48(r1) 184; CHECK-S-NEXT: mr r30, r4 185; CHECK-S-NEXT: bl externCall@notoc 186; CHECK-S-NEXT: add r3, r3, r30 187; CHECK-S-NEXT: extsw r3, r3 188; CHECK-S-NEXT: addi r1, r1, 48 189; CHECK-S-NEXT: ld r0, 16(r1) 190; CHECK-S-NEXT: ld r30, -16(r1) # 8-byte Folded Reload 191; CHECK-S-NEXT: mtlr r0 192; CHECK-S-NEXT: blr 193entry: 194 %call = tail call signext i32 @externCall(i32 signext %a) 195 %add = add nsw i32 %call, %b 196 ret i32 %add 197} 198 199define dso_local signext i32 @TailCallLocal1(i32 signext %a) local_unnamed_addr { 200; CHECK-ALL-LABEL: TailCallLocal1: 201; CHECK-S: .localentry TailCallLocal1 202; CHECK-S: # %bb.0: # %entry 203; CHECK-S: plwz r4, globalVar@PCREL(0), 1 204; CHECK-S-NEXT: add r3, r4, r3 205; CHECK-S-NEXT: extsw r3, r3 206; CHECK-S-NEXT: b localCall@notoc 207entry: 208 %0 = load i32, i32* @globalVar, align 4 209 %add = add nsw i32 %0, %a 210 %call = tail call signext i32 @localCall(i32 signext %add) 211 ret i32 %call 212} 213 214define dso_local signext i32 @TailCallLocal2(i32 signext %a) local_unnamed_addr { 215; CHECK-ALL-LABEL: TailCallLocal2: 216; CHECK-S: .localentry TailCallLocal2 217; CHECK-S: # %bb.0: # %entry 218; CHECK-S: pld r4, externGlobalVar@got@pcrel(0), 1 219; CHECK-S-NEXT: .Lpcrel1: 220; CHECK-S-NEXT: .reloc .Lpcrel1-8,R_PPC64_PCREL_OPT,.-(.Lpcrel1-8) 221; CHECK-S-NEXT: lwz r4, 0(r4) 222; CHECK-S-NEXT: add r3, r4, r3 223; CHECK-S-NEXT: extsw r3, r3 224; CHECK-S-NEXT: b localCall@notoc 225entry: 226 %0 = load i32, i32* @externGlobalVar, align 4 227 %add = add nsw i32 %0, %a 228 %call = tail call signext i32 @localCall(i32 signext %add) 229 ret i32 %call 230} 231 232define dso_local signext i32 @TailCallLocalNoGlobal(i32 signext %a) local_unnamed_addr { 233; CHECK-ALL-LABEL: TailCallLocalNoGlobal: 234; CHECK-S: .localentry TailCallLocalNoGlobal, 1 235; CHECK-P9: .localentry TailCallLocalNoGlobal, .Lfunc_lep9-.Lfunc_gep9 236; CHECK-ALL: # %bb.0: # %entry 237; CHECK-S: b localCall@notoc 238entry: 239 %call = tail call signext i32 @localCall(i32 signext %a) 240 ret i32 %call 241} 242 243define dso_local signext i32 @TailCallExtern1(i32 signext %a) local_unnamed_addr { 244; CHECK-ALL-LABEL: TailCallExtern1: 245; CHECK-S: .localentry TailCallExtern1 246; CHECK-S: # %bb.0: # %entry 247; CHECK-S: plwz r4, globalVar@PCREL(0), 1 248; CHECK-S-NEXT: add r3, r4, r3 249; CHECK-S-NEXT: extsw r3, r3 250; CHECK-S-NEXT: b externCall@notoc 251entry: 252 %0 = load i32, i32* @globalVar, align 4 253 %add = add nsw i32 %0, %a 254 %call = tail call signext i32 @externCall(i32 signext %add) 255 ret i32 %call 256} 257 258define dso_local signext i32 @TailCallExtern2(i32 signext %a) local_unnamed_addr { 259; CHECK-ALL-LABEL: TailCallExtern2: 260; CHECK-S: .localentry TailCallExtern2 261; CHECK-S: # %bb.0: # %entry 262; CHECK-S: pld r4, externGlobalVar@got@pcrel(0), 1 263; CHECK-S-NEXT: .Lpcrel2: 264; CHECK-S-NEXT: .reloc .Lpcrel2-8,R_PPC64_PCREL_OPT,.-(.Lpcrel2-8) 265; CHECK-S-NEXT: lwz r4, 0(r4) 266; CHECK-S-NEXT: add r3, r4, r3 267; CHECK-S-NEXT: extsw r3, r3 268; CHECK-S-NEXT: b externCall@notoc 269entry: 270 %0 = load i32, i32* @externGlobalVar, align 4 271 %add = add nsw i32 %0, %a 272 %call = tail call signext i32 @externCall(i32 signext %add) 273 ret i32 %call 274} 275 276define dso_local signext i32 @TailCallExternNoGlobal(i32 signext %a) local_unnamed_addr { 277; CHECK-ALL-LABEL: TailCallExternNoGlobal: 278; CHECK-S: .localentry TailCallExternNoGlobal, 1 279; CHECK-S-NEXT: # %bb.0: # %entry 280; CHECK-S-NEXT: b externCall@notoc 281; CHECK-S-NEXT: #TC_RETURNd8 externCall@notoc 282entry: 283 %call = tail call signext i32 @externCall(i32 signext %a) 284 ret i32 %call 285} 286 287define dso_local signext i32 @IndirectCall1(i32 signext %a, i32 signext %b) local_unnamed_addr { 288; CHECK-ALL-LABEL: IndirectCall1: 289; CHECK-S: # %bb.0: # %entry 290; CHECK-S-NEXT: mflr r0 291; CHECK-S-NEXT: std r0, 16(r1) 292; CHECK-S-NEXT: stdu r1, -32(r1) 293; CHECK-S-NEXT: .cfi_def_cfa_offset 32 294; CHECK-S-NEXT: .cfi_offset lr, 16 295; CHECK-S-NEXT: pld r12, indirectCall@PCREL(0), 1 296; CHECK-S-NEXT: add r3, r4, r3 297; CHECK-S-NEXT: extsw r3, r3 298; CHECK-S-NEXT: mtctr r12 299; CHECK-S-NEXT: bctrl 300; CHECK-S-NEXT: plwz r4, globalVar@PCREL(0), 1 301; CHECK-S-NEXT: mullw r3, r4, r3 302; CHECK-S-NEXT: extsw r3, r3 303; CHECK-S-NEXT: addi r1, r1, 32 304; CHECK-S-NEXT: ld r0, 16(r1) 305; CHECK-S-NEXT: mtlr r0 306; CHECK-S-NEXT: blr 307entry: 308 %add = add nsw i32 %b, %a 309 %0 = load i32 (i32)*, i32 (i32)** @indirectCall, align 8 310 %call = tail call signext i32 %0(i32 signext %add) 311 %1 = load i32, i32* @globalVar, align 4 312 %mul = mul nsw i32 %1, %call 313 ret i32 %mul 314} 315 316define dso_local signext i32 @IndirectCall2(i32 signext %a, i32 signext %b) local_unnamed_addr { 317; CHECK-ALL-LABEL: IndirectCall2: 318; CHECK-S: # %bb.0: # %entry 319; CHECK-S-NEXT: mflr r0 320; CHECK-S-NEXT: std r0, 16(r1) 321; CHECK-S-NEXT: stdu r1, -32(r1) 322; CHECK-S-NEXT: .cfi_def_cfa_offset 32 323; CHECK-S-NEXT: .cfi_offset lr, 16 324; CHECK-S-NEXT: pld r12, indirectCall@PCREL(0), 1 325; CHECK-S-NEXT: add r3, r4, r3 326; CHECK-S-NEXT: extsw r3, r3 327; CHECK-S-NEXT: mtctr r12 328; CHECK-S-NEXT: bctrl 329; CHECK-S-NEXT: pld r4, externGlobalVar@got@pcrel(0), 1 330; CHECK-S-NEXT: .Lpcrel3: 331; CHECK-S-NEXT: .reloc .Lpcrel3-8,R_PPC64_PCREL_OPT,.-(.Lpcrel3-8) 332; CHECK-S-NEXT: lwz r4, 0(r4) 333; CHECK-S-NEXT: mullw r3, r4, r3 334; CHECK-S-NEXT: extsw r3, r3 335; CHECK-S-NEXT: addi r1, r1, 32 336; CHECK-S-NEXT: ld r0, 16(r1) 337; CHECK-S-NEXT: mtlr r0 338; CHECK-S-NEXT: blr 339entry: 340 %add = add nsw i32 %b, %a 341 %0 = load i32 (i32)*, i32 (i32)** @indirectCall, align 8 342 %call = tail call signext i32 %0(i32 signext %add) 343 %1 = load i32, i32* @externGlobalVar, align 4 344 %mul = mul nsw i32 %1, %call 345 ret i32 %mul 346} 347 348define dso_local signext i32 @IndirectCall3(i32 signext %a, i32 signext %b, i32 (i32)* nocapture %call_param) local_unnamed_addr { 349; CHECK-ALL-LABEL: IndirectCall3: 350; CHECK-S: # %bb.0: # %entry 351; CHECK-S-NEXT: mflr r0 352; CHECK-S-NEXT: std r0, 16(r1) 353; CHECK-S-NEXT: stdu r1, -32(r1) 354; CHECK-S-NEXT: .cfi_def_cfa_offset 32 355; CHECK-S-NEXT: .cfi_offset lr, 16 356; CHECK-S-NEXT: mtctr r5 357; CHECK-S-NEXT: add r3, r4, r3 358; CHECK-S-NEXT: mr r12, r5 359; CHECK-S-NEXT: extsw r3, r3 360; CHECK-S-NEXT: bctrl 361; CHECK-S-NEXT: plwz r4, globalVar@PCREL(0), 1 362; CHECK-S-NEXT: mullw r3, r4, r3 363; CHECK-S-NEXT: extsw r3, r3 364; CHECK-S-NEXT: addi r1, r1, 32 365; CHECK-S-NEXT: ld r0, 16(r1) 366; CHECK-S-NEXT: mtlr r0 367; CHECK-S-NEXT: blr 368entry: 369 %add = add nsw i32 %b, %a 370 %call = tail call signext i32 %call_param(i32 signext %add) 371 %0 = load i32, i32* @globalVar, align 4 372 %mul = mul nsw i32 %0, %call 373 ret i32 %mul 374} 375 376define dso_local signext i32 @IndirectCallNoGlobal(i32 signext %a, i32 signext %b, i32 (i32)* nocapture %call_param) local_unnamed_addr { 377; CHECK-ALL-LABEL: IndirectCallNoGlobal: 378; CHECK-S: # %bb.0: # %entry 379; CHECK-S-NEXT: mflr r0 380; CHECK-S-NEXT: .cfi_def_cfa_offset 48 381; CHECK-S-NEXT: .cfi_offset lr, 16 382; CHECK-S-NEXT: .cfi_offset r30, -16 383; CHECK-S-NEXT: std r30, -16(r1) # 8-byte Folded Spill 384; CHECK-S-NEXT: std r0, 16(r1) 385; CHECK-S-NEXT: stdu r1, -48(r1) 386; CHECK-S-NEXT: mtctr r5 387; CHECK-S-NEXT: mr r12, r5 388; CHECK-S-NEXT: mr r30, r4 389; CHECK-S-NEXT: bctrl 390; CHECK-S-NEXT: add r3, r3, r30 391; CHECK-S-NEXT: extsw r3, r3 392; CHECK-S-NEXT: addi r1, r1, 48 393; CHECK-S-NEXT: ld r0, 16(r1) 394; CHECK-S-NEXT: ld r30, -16(r1) # 8-byte Folded Reload 395; CHECK-S-NEXT: mtlr r0 396; CHECK-S-NEXT: blr 397entry: 398 %call = tail call signext i32 %call_param(i32 signext %a) 399 %add = add nsw i32 %call, %b 400 ret i32 %add 401} 402 403define dso_local signext i32 @IndirectCallOnly(i32 signext %a, i32 (i32)* nocapture %call_param) local_unnamed_addr { 404; CHECK-ALL-LABEL: IndirectCallOnly: 405; CHECK-S: # %bb.0: # %entry 406; CHECK-S-NEXT: mtctr r4 407; CHECK-S-NEXT: mr r12, r4 408; CHECK-S-NEXT: bctr 409; CHECK-S-NEXT: #TC_RETURNr8 ctr 410entry: 411 %call = tail call signext i32 %call_param(i32 signext %a) 412 ret i32 %call 413} 414 415attributes #0 = { noinline } 416 417