1; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ 2; RUN: -mcpu=future -ppc-asm-full-reg-names < %s \ 3; RUN: | FileCheck %s --check-prefixes=CHECK-S,CHECK-ALL 4; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ 5; RUN: -mcpu=pwr9 -ppc-asm-full-reg-names < %s \ 6; RUN: | FileCheck %s --check-prefixes=CHECK-P9,CHECK-ALL 7; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ 8; RUN: -mcpu=pwr9 --code-model=large -ppc-asm-full-reg-names < %s \ 9; RUN: | FileCheck %s --check-prefixes=CHECK-LARGE,CHECK-ALL 10 11@global_int = common dso_local local_unnamed_addr global i32 0, align 4 12 13define dso_local signext i32 @NoTOC() local_unnamed_addr { 14; CHECK-ALL-LABEL: NoTOC: 15; CHECK-S-NOT: .localentry 16; CHECK-S: li r3, 42 17; CHECK-S-NEXT: blr 18entry: 19 ret i32 42 20} 21 22define dso_local signext i32 @AsmClobberX2(i32 signext %a, i32 signext %b) local_unnamed_addr { 23; CHECK-ALL-LABEL: AsmClobberX2: 24; CHECK-S: .localentry AsmClobberX2, 1 25; CHECK-S: add r3, r4, r3 26; CHECK-S: #APP 27; CHECK-S-NEXT: nop 28; CHECK-S-NEXT: #NO_APP 29; CHECK-S: blr 30entry: 31 %add = add nsw i32 %b, %a 32 tail call void asm sideeffect "nop", "~{r2}"() 33 ret i32 %add 34} 35 36; FIXME: This is actually a test case that shows a bug. On power9 and earlier 37; this test should not compile. On later CPUs (like this test) the @toc 38; should be replaced with @pcrel and we won't need R2 and so the problem 39; goes away. 40define dso_local signext i32 @AsmClobberX2WithTOC(i32 signext %a, i32 signext %b) local_unnamed_addr { 41; CHECK-ALL-LABEL: AsmClobberX2WithTOC: 42; CHECK-S: addis r2, r12, .TOC.-.Lfunc_gep2@ha 43; CHECK-S-NEXT: addi r2, r2, .TOC.-.Lfunc_gep2@l 44; CHECK-LARGE: ld r2, .Lfunc_toc2-.Lfunc_gep2(r12) 45; CHECK-LARGE: add r2, r2, r12 46; CHECK-S: .localentry AsmClobberX2WithTOC, .Lfunc_lep2-.Lfunc_gep2 47; CHECK-S: #APP 48; CHECK-S-NEXT: li r2, 0 49; CHECK-S-NEXT: #NO_APP 50; CHECK-S-NEXT: addis r5, r2, global_int@toc@ha 51; CHECK-S-NEXT: lwz r5, global_int@toc@l(r5) 52; CHECK-S-NEXT: add r3, r4, r3 53; CHECK-S-NEXT: add r3, r3, r5 54; CHECK-S-NEXT: extsw r3, r3 55; CHECK-S-NEXT: blr 56entry: 57 %add = add nsw i32 %b, %a 58 tail call void asm sideeffect "li 2, 0", "~{r2}"() 59 %0 = load i32, i32* @global_int, align 4 60 %add1 = add nsw i32 %add, %0 61 ret i32 %add1 62} 63 64define dso_local signext i32 @AsmClobberX5(i32 signext %a, i32 signext %b) local_unnamed_addr { 65; CHECK-ALL-LABEL: AsmClobberX5: 66; CHECK-S: .localentry AsmClobberX5, 1 67; CHECK-P9-NOT: .localentry 68; CHECK-ALL: # %bb.0: # %entry 69; CHECK-S-NEXT: add r3, r4, r3 70; CHECK-S-NEXT: extsw r3, r3 71; CHECK-S-NEXT: #APP 72; CHECK-S-NEXT: nop 73; CHECK-S-NEXT: #NO_APP 74; CHECK-S-NEXT: blr 75entry: 76 %add = add nsw i32 %b, %a 77 tail call void asm sideeffect "nop", "~{r5}"() 78 ret i32 %add 79} 80 81; Clobber all GPRs except R2. 82define dso_local signext i32 @AsmClobberNotR2(i32 signext %a, i32 signext %b) local_unnamed_addr { 83; CHECK-ALL-LABEL: AsmClobberNotR2: 84; CHECK-S: .localentry AsmClobberNotR2, 1 85; CHECK-P9-NOT: .localentry 86; CHECK-S: add r3, r4, r3 87; CHECK-S: stw r3, -148(r1) # 4-byte Folded Spill 88; CHECK-S-NEXT: #APP 89; CHECK-S-NEXT: nop 90; CHECK-S-NEXT: #NO_APP 91; CHECK-S-NEXT: lwz r3, -148(r1) # 4-byte Folded Reload 92; CHECK-S: blr 93entry: 94 %add = add nsw i32 %b, %a 95 tail call void asm sideeffect "nop", "~{r0},~{r1},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{r16},~{r17},~{r18},~{r19},~{r20},~{r21},~{r22},~{r23},~{r24},~{r25},~{r26},~{r27},~{r28},~{r29},~{r30},~{r31}"() 96 ret i32 %add 97} 98 99; Increase register pressure enough to force the register allocator to 100; make use of R2. 101define dso_local signext i32 @X2IsCallerSaved(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e, i32 signext %f, i32 signext %g, i32 signext %h) local_unnamed_addr { 102; CHECK-ALL-LABEL: X2IsCallerSaved: 103; CHECK-S: .localentry X2IsCallerSaved, 1 104; CHECK-P9-NOT: .localentry 105; CHECK-ALL: # %bb.0: # %entry 106; CHECK-S-NEXT: std r29, -24(r1) # 8-byte Folded Spill 107; CHECK-S-NEXT: add r11, r4, r3 108; CHECK-S-NEXT: subf r29, r9, r8 109; CHECK-S-NEXT: add r9, r10, r9 110; CHECK-S-NEXT: subf r10, r3, r10 111; CHECK-S-NEXT: mullw r3, r4, r3 112; CHECK-S-NEXT: mullw r3, r3, r11 113; CHECK-S-NEXT: mullw r3, r3, r5 114; CHECK-S-NEXT: subf r12, r5, r4 115; CHECK-S-NEXT: mullw r3, r3, r6 116; CHECK-S-NEXT: add r0, r6, r5 117; CHECK-S-NEXT: mullw r3, r3, r12 118; CHECK-S-NEXT: mullw r3, r3, r0 119; CHECK-S-NEXT: mullw r3, r3, r7 120; CHECK-S-NEXT: subf r2, r7, r6 121; CHECK-S-NEXT: mullw r3, r3, r8 122; CHECK-S-NEXT: std r30, -16(r1) # 8-byte Folded Spill 123; CHECK-S-NEXT: add r30, r8, r7 124; CHECK-S-NEXT: mullw r3, r3, r2 125; CHECK-S-NEXT: mullw r3, r3, r30 126; CHECK-S-NEXT: mullw r3, r3, r29 127; CHECK-S-NEXT: mullw r3, r3, r9 128; CHECK-S-NEXT: ld r30, -16(r1) # 8-byte Folded Reload 129; CHECK-S-NEXT: ld r29, -24(r1) # 8-byte Folded Reload 130; CHECK-S-NEXT: mullw r3, r3, r10 131; CHECK-S-NEXT: extsw r3, r3 132; CHECK-S-NEXT: blr 133entry: 134 %add = add nsw i32 %b, %a 135 %sub = sub nsw i32 %b, %c 136 %add1 = add nsw i32 %d, %c 137 %sub2 = sub nsw i32 %d, %e 138 %add3 = add nsw i32 %f, %e 139 %sub4 = sub nsw i32 %f, %g 140 %add5 = add nsw i32 %h, %g 141 %sub6 = sub nsw i32 %h, %a 142 %mul = mul i32 %b, %a 143 %mul7 = mul i32 %mul, %add 144 %mul8 = mul i32 %mul7, %c 145 %mul9 = mul i32 %mul8, %d 146 %mul10 = mul i32 %mul9, %sub 147 %mul11 = mul i32 %mul10, %add1 148 %mul12 = mul i32 %mul11, %e 149 %mul13 = mul i32 %mul12, %f 150 %mul14 = mul i32 %mul13, %sub2 151 %mul15 = mul i32 %mul14, %add3 152 %mul16 = mul i32 %mul15, %sub4 153 %mul17 = mul i32 %mul16, %add5 154 %mul18 = mul i32 %mul17, %sub6 155 ret i32 %mul18 156} 157 158 159define dso_local signext i32 @UsesX2AsTOC() local_unnamed_addr { 160; CHECK-ALL-LABEL: UsesX2AsTOC: 161; CHECK-S: addis r2, r12, .TOC.-.Lfunc_gep6@ha 162; CHECK-S-NEXT: addi r2, r2, .TOC.-.Lfunc_gep6@l 163; CHECK-LARGE: ld r2, .Lfunc_toc6-.Lfunc_gep6(r12) 164; CHECK-LARGE: add r2, r2, r12 165; CHECK-S: .localentry UsesX2AsTOC, .Lfunc_lep6-.Lfunc_gep6 166; CHECK-ALL: # %bb.0: # %entry 167; CHECK-S-NEXT: addis r3, r2, global_int@toc@ha 168; CHECK-S-NEXT: lwa r3, global_int@toc@l(r3) 169; CHECK-S-NEXT: blr 170entry: 171 %0 = load i32, i32* @global_int, align 4 172 ret i32 %0 173} 174 175 176define dso_local double @UsesX2AsConstPoolTOC() local_unnamed_addr { 177; CHECK-ALL-LABEL: UsesX2AsConstPoolTOC: 178; CHECK-LARGE: ld r2, .Lfunc_toc7-.Lfunc_gep7(r12) 179; CHECK-LARGE: add r2, r2, r12 180; CHECK-S-NOT: .localentry 181; CHECK-ALL: # %bb.0: # %entry 182; CHECK-S-NEXT: plfd f1, .LCPI7_0@PCREL(0), 1 183; CHECK-S-NEXT: blr 184entry: 185 ret double 0x404124A4EBDD334C 186} 187 188 189