1*8ed8353fSOliver Stannard; RUN: llc -mtriple armv7a--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLED 2*8ed8353fSOliver Stannard; RUN: llc -mtriple armv7a--none-eabi < %s -enable-ipra | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLED 3*8ed8353fSOliver Stannard 4*8ed8353fSOliver Stannarddefine void @leaf() { 5*8ed8353fSOliver Stannardentry: 6*8ed8353fSOliver Stannard tail call void asm sideeffect "", ""() 7*8ed8353fSOliver Stannard ret void 8*8ed8353fSOliver Stannard} 9*8ed8353fSOliver Stannard 10*8ed8353fSOliver Stannarddefine void @leaf_r3() { 11*8ed8353fSOliver Stannardentry: 12*8ed8353fSOliver Stannard tail call void asm sideeffect "", "~{r3}"() 13*8ed8353fSOliver Stannard ret void 14*8ed8353fSOliver Stannard} 15*8ed8353fSOliver Stannard 16*8ed8353fSOliver Stannarddefine void @leaf_r4() { 17*8ed8353fSOliver Stannardentry: 18*8ed8353fSOliver Stannard tail call void asm sideeffect "", "~{r4}"() 19*8ed8353fSOliver Stannard ret void 20*8ed8353fSOliver Stannard} 21*8ed8353fSOliver Stannard 22*8ed8353fSOliver Stannarddefine void @leaf_s0() { 23*8ed8353fSOliver Stannardentry: 24*8ed8353fSOliver Stannard tail call void asm sideeffect "", "~{s0}"() 25*8ed8353fSOliver Stannard ret void 26*8ed8353fSOliver Stannard} 27*8ed8353fSOliver Stannard 28*8ed8353fSOliver Stannarddefine void @leaf_d0() { 29*8ed8353fSOliver Stannardentry: 30*8ed8353fSOliver Stannard tail call void asm sideeffect "", "~{d0}"() 31*8ed8353fSOliver Stannard ret void 32*8ed8353fSOliver Stannard} 33*8ed8353fSOliver Stannard 34*8ed8353fSOliver Stannard; r3 is normally caller-saved, but with IPRA we can see that it isn't used in 35*8ed8353fSOliver Stannard; the callee, so can leave a live value in it. 36*8ed8353fSOliver Stannarddefine void @test_r3_presrved() { 37*8ed8353fSOliver Stannard; CHECK-LABEL: test_r3_presrved: 38*8ed8353fSOliver Stannardentry: 39*8ed8353fSOliver Stannard; CHECK: ASM1: r3 40*8ed8353fSOliver Stannard; DISABLED: mov [[TEMP:r[0-9]+]], r3 41*8ed8353fSOliver Stannard; ENABLED-NOT: r3 42*8ed8353fSOliver Stannard; CHECK: bl leaf 43*8ed8353fSOliver Stannard; DISABLED: mov r3, [[TEMP]] 44*8ed8353fSOliver Stannard; ENABLED-NOT: r3 45*8ed8353fSOliver Stannard; CHECK: ASM2: r3 46*8ed8353fSOliver Stannard %a = tail call i32 asm sideeffect "// ASM1: $0", "={r3},0"(i32 undef) 47*8ed8353fSOliver Stannard tail call void @leaf() 48*8ed8353fSOliver Stannard %b = tail call i32 asm sideeffect "// ASM2: $0", "={r3},0"(i32 %a) 49*8ed8353fSOliver Stannard ret void 50*8ed8353fSOliver Stannard} 51*8ed8353fSOliver Stannard 52*8ed8353fSOliver Stannard; Same as above, but r3 is clobbered in the callee, so it is clobbered by the 53*8ed8353fSOliver Stannard; call as normal. 54*8ed8353fSOliver Stannarddefine void @test_r3_clobbered() { 55*8ed8353fSOliver Stannard; CHECK-LABEL: test_r3_clobbered: 56*8ed8353fSOliver Stannardentry: 57*8ed8353fSOliver Stannard; CHECK: ASM1: r3 58*8ed8353fSOliver Stannard; CHECK: mov [[TEMP:r[0-9]+]], r3 59*8ed8353fSOliver Stannard; CHECK: bl leaf 60*8ed8353fSOliver Stannard; CHECK: mov r3, [[TEMP]] 61*8ed8353fSOliver Stannard; CHECK: ASM2: r3 62*8ed8353fSOliver Stannard %a = tail call i32 asm sideeffect "// ASM1: $0", "={r3},0"(i32 undef) 63*8ed8353fSOliver Stannard tail call void @leaf_r3() 64*8ed8353fSOliver Stannard %b = tail call i32 asm sideeffect "// ASM2: $0", "={r3},0"(i32 %a) 65*8ed8353fSOliver Stannard ret void 66*8ed8353fSOliver Stannard} 67*8ed8353fSOliver Stannard 68*8ed8353fSOliver Stannard; r4 is a callee-saved register, so IPRA has no effect. 69*8ed8353fSOliver Stannarddefine void @test_r4_preserved() { 70*8ed8353fSOliver Stannard; CHECK-LABEL: test_r4_preserved: 71*8ed8353fSOliver Stannardentry: 72*8ed8353fSOliver Stannard; CHECK: ASM1: r4 73*8ed8353fSOliver Stannard; CHECK-NOT: r4 74*8ed8353fSOliver Stannard; CHECK: bl leaf 75*8ed8353fSOliver Stannard; CHECK-NOT: r4 76*8ed8353fSOliver Stannard; CHECK: ASM2: r4 77*8ed8353fSOliver Stannard %a = tail call i32 asm sideeffect "// ASM1: $0", "={r4},0"(i32 undef) 78*8ed8353fSOliver Stannard tail call void @leaf() 79*8ed8353fSOliver Stannard %b = tail call i32 asm sideeffect "// ASM2: $0", "={r4},0"(i32 %a) 80*8ed8353fSOliver Stannard ret void 81*8ed8353fSOliver Stannard} 82*8ed8353fSOliver Stannarddefine void @test_r4_clobbered() { 83*8ed8353fSOliver Stannard; CHECK-LABEL: test_r4_clobbered: 84*8ed8353fSOliver Stannardentry: 85*8ed8353fSOliver Stannard; CHECK: ASM1: r4 86*8ed8353fSOliver Stannard; CHECK-NOT: r4 87*8ed8353fSOliver Stannard; CHECK: bl leaf_r4 88*8ed8353fSOliver Stannard; CHECK-NOT: r4 89*8ed8353fSOliver Stannard; CHECK: ASM2: r4 90*8ed8353fSOliver Stannard %a = tail call i32 asm sideeffect "// ASM1: $0", "={r4},0"(i32 undef) 91*8ed8353fSOliver Stannard tail call void @leaf_r4() 92*8ed8353fSOliver Stannard %b = tail call i32 asm sideeffect "// ASM2: $0", "={r4},0"(i32 %a) 93*8ed8353fSOliver Stannard ret void 94*8ed8353fSOliver Stannard} 95*8ed8353fSOliver Stannard 96*8ed8353fSOliver Stannard; r12 is the intra-call scratch register, so we have to assume it is clobbered 97*8ed8353fSOliver Stannard; even if we can see that the callee does not touch it. 98*8ed8353fSOliver Stannarddefine void @test_r12() { 99*8ed8353fSOliver Stannard; CHECK-LABEL: test_r12: 100*8ed8353fSOliver Stannardentry: 101*8ed8353fSOliver Stannard; CHECK: ASM1: r12 102*8ed8353fSOliver Stannard; CHECK: mov [[TEMP:r[0-9]+]], r12 103*8ed8353fSOliver Stannard; CHECK: bl leaf 104*8ed8353fSOliver Stannard; CHECK: mov r12, [[TEMP]] 105*8ed8353fSOliver Stannard; CHECK: ASM2: r12 106*8ed8353fSOliver Stannard %a = tail call i32 asm sideeffect "// ASM1: $0", "={r12},0"(i32 undef) 107*8ed8353fSOliver Stannard tail call void @leaf() 108*8ed8353fSOliver Stannard %b = tail call i32 asm sideeffect "// ASM2: $0", "={r12},0"(i32 %a) 109*8ed8353fSOliver Stannard ret void 110*8ed8353fSOliver Stannard} 111*8ed8353fSOliver Stannard 112*8ed8353fSOliver Stannard; s0 and d0 are caller-saved, IPRA allows us to keep them live in the caller if 113*8ed8353fSOliver Stannard; the callee doesn't modify them. 114*8ed8353fSOliver Stannarddefine void @test_s0_preserved() { 115*8ed8353fSOliver Stannard; CHECK-LABEL: test_s0_preserved: 116*8ed8353fSOliver Stannardentry: 117*8ed8353fSOliver Stannard; CHECK: ASM1: s0 118*8ed8353fSOliver Stannard; DISABLED: vmov.f32 [[TEMP:s[0-9]+]], s0 119*8ed8353fSOliver Stannard; ENABLED-NOT: s0 120*8ed8353fSOliver Stannard; CHECK: bl leaf 121*8ed8353fSOliver Stannard; DISABLED: vmov.f32 s0, [[TEMP]] 122*8ed8353fSOliver Stannard; ENABLED-NOT: s0 123*8ed8353fSOliver Stannard; CHECK: ASM2: s0 124*8ed8353fSOliver Stannard %a = tail call float asm sideeffect "// ASM1: $0", "={s0},0"(float undef) 125*8ed8353fSOliver Stannard tail call void @leaf() 126*8ed8353fSOliver Stannard %b = tail call float asm sideeffect "// ASM2: $0", "={s0},0"(float %a) 127*8ed8353fSOliver Stannard ret void 128*8ed8353fSOliver Stannard} 129*8ed8353fSOliver Stannard 130*8ed8353fSOliver Stannarddefine void @test_s0_clobbered() { 131*8ed8353fSOliver Stannard; CHECK-LABEL: test_s0_clobbered: 132*8ed8353fSOliver Stannardentry: 133*8ed8353fSOliver Stannard; CHECK: ASM1: s0 134*8ed8353fSOliver Stannard; CHECK: vmov.f32 [[TEMP:s[0-9]+]], s0 135*8ed8353fSOliver Stannard; CHECK: bl leaf_s0 136*8ed8353fSOliver Stannard; CHECK: vmov.f32 s0, [[TEMP]] 137*8ed8353fSOliver Stannard; CHECK: ASM2: s0 138*8ed8353fSOliver Stannard %a = tail call float asm sideeffect "// ASM1: $0", "={s0},0"(float undef) 139*8ed8353fSOliver Stannard tail call void @leaf_s0() 140*8ed8353fSOliver Stannard %b = tail call float asm sideeffect "// ASM2: $0", "={s0},0"(float %a) 141*8ed8353fSOliver Stannard ret void 142*8ed8353fSOliver Stannard} 143*8ed8353fSOliver Stannard 144*8ed8353fSOliver Stannarddefine void @test_d0_preserved() { 145*8ed8353fSOliver Stannard; CHECK-LABEL: test_d0_preserved: 146*8ed8353fSOliver Stannardentry: 147*8ed8353fSOliver Stannard; CHECK: ASM1: d0 148*8ed8353fSOliver Stannard; DISABLED: vmov.f64 [[TEMP:d[0-9]+]], d0 149*8ed8353fSOliver Stannard; ENABLED-NOT: d0 150*8ed8353fSOliver Stannard; CHECK: bl leaf 151*8ed8353fSOliver Stannard; DISABLED: vmov.f64 d0, [[TEMP]] 152*8ed8353fSOliver Stannard; ENABLED-NOT: d0 153*8ed8353fSOliver Stannard; CHECK: ASM2: d0 154*8ed8353fSOliver Stannard %a = tail call double asm sideeffect "// ASM1: $0", "={d0},0"(double undef) 155*8ed8353fSOliver Stannard tail call void @leaf() 156*8ed8353fSOliver Stannard %b = tail call double asm sideeffect "// ASM2: $0", "={d0},0"(double %a) 157*8ed8353fSOliver Stannard ret void 158*8ed8353fSOliver Stannard} 159*8ed8353fSOliver Stannard 160*8ed8353fSOliver Stannarddefine void @test_d0_clobbered() { 161*8ed8353fSOliver Stannard; CHECK-LABEL: test_d0_clobbered: 162*8ed8353fSOliver Stannardentry: 163*8ed8353fSOliver Stannard; CHECK: ASM1: d0 164*8ed8353fSOliver Stannard; CHECK: vmov.f64 [[TEMP:d[0-9]+]], d0 165*8ed8353fSOliver Stannard; CHECK: bl leaf_d0 166*8ed8353fSOliver Stannard; CHECK: vmov.f64 d0, [[TEMP]] 167*8ed8353fSOliver Stannard; CHECK: ASM2: d0 168*8ed8353fSOliver Stannard %a = tail call double asm sideeffect "// ASM1: $0", "={d0},0"(double undef) 169*8ed8353fSOliver Stannard tail call void @leaf_d0() 170*8ed8353fSOliver Stannard %b = tail call double asm sideeffect "// ASM2: $0", "={d0},0"(double %a) 171*8ed8353fSOliver Stannard ret void 172*8ed8353fSOliver Stannard} 173*8ed8353fSOliver Stannard 174*8ed8353fSOliver Stannard; s0 and d0 overlap, so clobbering one in the callee prevents the other from 175*8ed8353fSOliver Stannard; being kept live across the call. 176*8ed8353fSOliver Stannarddefine void @test_s0_clobber_d0() { 177*8ed8353fSOliver Stannard; CHECK-LABEL: test_s0_clobber_d0: 178*8ed8353fSOliver Stannardentry: 179*8ed8353fSOliver Stannard; CHECK: ASM1: s0 180*8ed8353fSOliver Stannard; CHECK: vmov.f32 [[TEMP:s[0-9]+]], s0 181*8ed8353fSOliver Stannard; CHECK: bl leaf_d0 182*8ed8353fSOliver Stannard; CHECK: vmov.f32 s0, [[TEMP]] 183*8ed8353fSOliver Stannard; CHECK: ASM2: s0 184*8ed8353fSOliver Stannard %a = tail call float asm sideeffect "// ASM1: $0", "={s0},0"(float undef) 185*8ed8353fSOliver Stannard tail call void @leaf_d0() 186*8ed8353fSOliver Stannard %b = tail call float asm sideeffect "// ASM2: $0", "={s0},0"(float %a) 187*8ed8353fSOliver Stannard ret void 188*8ed8353fSOliver Stannard} 189*8ed8353fSOliver Stannard 190*8ed8353fSOliver Stannarddefine void @test_d0_clobber_s0() { 191*8ed8353fSOliver Stannard; CHECK-LABEL: test_d0_clobber_s0: 192*8ed8353fSOliver Stannardentry: 193*8ed8353fSOliver Stannard; CHECK: ASM1: d0 194*8ed8353fSOliver Stannard; CHECK: vmov.f64 [[TEMP:d[0-9]+]], d0 195*8ed8353fSOliver Stannard; CHECK: bl leaf_s0 196*8ed8353fSOliver Stannard; CHECK: vmov.f64 d0, [[TEMP]] 197*8ed8353fSOliver Stannard; CHECK: ASM2: d0 198*8ed8353fSOliver Stannard %a = tail call double asm sideeffect "// ASM1: $0", "={d0},0"(double undef) 199*8ed8353fSOliver Stannard tail call void @leaf_s0() 200*8ed8353fSOliver Stannard %b = tail call double asm sideeffect "// ASM2: $0", "={d0},0"(double %a) 201*8ed8353fSOliver Stannard ret void 202*8ed8353fSOliver Stannard} 203