Index: llvm/lib/Target/Sparc/SparcFrameLowering.cpp =================================================================== --- llvm/lib/Target/Sparc/SparcFrameLowering.cpp +++ llvm/lib/Target/Sparc/SparcFrameLowering.cpp @@ -326,10 +326,11 @@ MachineRegisterInfo &MRI = MF.getRegInfo(); MachineFrameInfo &MFI = MF.getFrameInfo(); - return !(MFI.hasCalls() // has calls - || MRI.isPhysRegUsed(SP::L0) // Too many registers needed - || MRI.isPhysRegUsed(SP::O6) // %sp is used - || hasFP(MF)); // need %fp + return !(MFI.hasCalls() // has calls + || MRI.isPhysRegUsed(SP::L0) // Too many registers needed + || MRI.isPhysRegUsed(SP::O6) // %sp is used + || hasFP(MF) // need %fp + || MF.hasInlineAsm()); // has inline assembly } void SparcFrameLowering::remapRegsForLeafProc(MachineFunction &MF) const { Index: llvm/test/CodeGen/SPARC/LeonSMACUMACInstructionUT.ll =================================================================== --- llvm/test/CodeGen/SPARC/LeonSMACUMACInstructionUT.ll +++ llvm/test/CodeGen/SPARC/LeonSMACUMACInstructionUT.ll @@ -3,7 +3,7 @@ ; RUN: llc %s -O0 -march=sparc -mcpu=leon4 -o - | FileCheck %s ; CHECK-LABEL: smac_test: -; CHECK: smac %o1, %o0, %o0 +; CHECK: smac %i1, %i0, %i0 define i32 @smac_test(i16* %a, i16* %b) { entry: ; %0 = tail call i32 asm sideeffect "smac $2, $1, $0", "={r2},{r3},{r4}"(i16* %a, i16* %b) @@ -12,7 +12,7 @@ } ; CHECK-LABEL: umac_test: -; CHECK: umac %o1, %o0, %o0 +; CHECK: umac %i1, %i0, %i0 define i32 @umac_test(i16* %a, i16* %b) { entry: %0 = tail call i32 asm sideeffect "umac $2, $1, $0", "=r,rI,r"(i16* %a, i16* %b) Index: llvm/test/CodeGen/SPARC/inlineasm-v9.ll =================================================================== --- llvm/test/CodeGen/SPARC/inlineasm-v9.ll +++ llvm/test/CodeGen/SPARC/inlineasm-v9.ll @@ -42,7 +42,7 @@ ;; Ensure that 64-bit immediates aren't truncated ; CHECK-LABEL: test_large_immediate -; CHECK: or %o0, %lo(4294967296), %o0 +; CHECK: or %i0, %lo(4294967296), %i0 define i64 @test_large_immediate(i64) { entry: %1 = tail call i64 asm "or $0, %lo($1), $0", "=r,i,r"(i64 4294967296, i64 %0) @@ -51,7 +51,7 @@ ; Ensure that the input register value is not truncated to 32bit. ; CHECK-LABEL: test_constraint_input_type -; CHECK: ldx [%o0], %o0 +; CHECK: ldx [%i0], %o0 define void @test_constraint_input_type(i64* %arg1) { Entry: %val = load i64, i64* %arg1 Index: llvm/test/CodeGen/SPARC/inlineasm.ll =================================================================== --- llvm/test/CodeGen/SPARC/inlineasm.ll +++ llvm/test/CodeGen/SPARC/inlineasm.ll @@ -1,7 +1,7 @@ ; RUN: llc -march=sparc <%s | FileCheck %s ; CHECK-LABEL: test_constraint_r -; CHECK: add %o1, %o0, %o0 +; CHECK: add %i1, %i0, %i0 define i32 @test_constraint_r(i32 %a, i32 %b) { entry: %0 = tail call i32 asm sideeffect "add $2, $1, $0", "=r,r,r"(i32 %a, i32 %b) @@ -21,7 +21,7 @@ } ; CHECK-LABEL: test_constraint_I: -; CHECK: add %o0, 1023, %o0 +; CHECK: add %i0, 1023, %i0 define i32 @test_constraint_I(i32 %a) { entry: %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 1023) @@ -29,7 +29,7 @@ } ; CHECK-LABEL: test_constraint_I_neg: -; CHECK: add %o0, -4096, %o0 +; CHECK: add %i0, -4096, %i0 define i32 @test_constraint_I_neg(i32 %a) { entry: %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 -4096) @@ -39,7 +39,7 @@ ; CHECK-LABEL: test_constraint_I_largeimm: ; CHECK: sethi 9, [[R0:%[gilo][0-7]]] ; CHECK: or [[R0]], 784, [[R1:%[gilo][0-7]]] -; CHECK: add %o0, [[R1]], %o0 +; CHECK: add %i0, [[R1]], %i0 define i32 @test_constraint_I_largeimm(i32 %a) { entry: %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 10000) @@ -47,8 +47,8 @@ } ; CHECK-LABEL: test_constraint_reg: -; CHECK: ldda [%o1] 43, %g2 -; CHECK: ldda [%o1] 43, %g4 +; CHECK: ldda [%i1] 43, %g2 +; CHECK: ldda [%i1] 43, %g4 define void @test_constraint_reg(i32 %s, i32* %ptr) { entry: %0 = tail call i64 asm sideeffect "ldda [$1] $2, $0", "={r2},r,n"(i32* %ptr, i32 43) @@ -57,11 +57,11 @@ } ;; Ensure that i64 args to asm are allocated to the IntPair register class. -;; Also checks that register renaming for leaf proc works. +;; Also checks that there's no register renaming for leaf proc if it has inline asm. ; CHECK-LABEL: test_constraint_r_i64: -; CHECK: mov %o0, %o5 -; CHECK: sra %o5, 31, %o4 -; CHECK: std %o4, [%o1] +; CHECK: mov %i0, %i5 +; CHECK: sra %i5, 31, %i4 +; CHECK: std %i4, [%i1] define i32 @test_constraint_r_i64(i32 %foo, i64* %out, i32 %o) { entry: %conv = sext i32 %foo to i64 @@ -84,10 +84,10 @@ ;; Ensures that tied in and out gets allocated properly. ; CHECK-LABEL: test_i64_inout: -; CHECK: mov %g0, %o2 -; CHECK: mov 5, %o3 -; CHECK: xor %o2, %g0, %o2 -; CHECK: mov %o2, %o0 +; CHECK: mov %g0, %i2 +; CHECK: mov 5, %i3 +; CHECK: xor %i2, %g0, %i2 +; CHECK: mov %i2, %i0 ; CHECK: ret define i64 @test_i64_inout() { entry: @@ -114,7 +114,7 @@ } ; CHECK-LABEL: test_addressing_mode_i64: -; CHECK: std %l0, [%o0] +; CHECK: std %l0, [%i0] define void @test_addressing_mode_i64(i64* %out) { entry: call void asm "std %l0, $0", "=*m,r"(i64* elementtype(i64) nonnull %out, i64 0) @@ -132,8 +132,8 @@ } ; CHECK-LABEL: test_constraint_f_e_i32_i64: -; CHECK: ld [%o0+%lo(.LCPI13_0)], %f0 -; CHECK: ldd [%o0+%lo(.LCPI13_1)], %f2 +; CHECK: ld [%i0+%lo(.LCPI13_0)], %f0 +; CHECK: ldd [%i0+%lo(.LCPI13_1)], %f2 ; CHECK: fadds %f0, %f0, %f0 ; CHECK: faddd %f2, %f2, %f0 Index: llvm/test/CodeGen/SPARC/leafproc.ll =================================================================== --- llvm/test/CodeGen/SPARC/leafproc.ll +++ llvm/test/CodeGen/SPARC/leafproc.ll @@ -78,3 +78,25 @@ %4 = load i32, i32* %3, align 4 ret i32 %4 } + +; Here we have a leaf function where it contains inline assembly, which means +; that register renumbering might interfere with the register constraints. +; As a result the function is not marked as being a leaf one. + +; CHECK-LABEL: leaf_proc_give_up +; CHECK: save %sp, -96, %sp +; CHECK: ld [%fp+92], %o5 +; CHECK: mov %i0, %g1 +; CHECK: mov %i1, %o0 +; CHECK: mov %i2, %o1 +; CHECK: mov %i3, %o2 +; CHECK: mov %i4, %o3 +; CHECK: mov %i5, %o4 +; CHECK: ret +; CHECK-NEXT: restore %g0, %o0, %o0 + +define i32 @leaf_proc_give_up(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6) { +Entry: + %g = call i32 asm sideeffect "", "={o0},{g1},{o0},{o1},{o2},{o3},{o4},{o5}"(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6) + ret i32 %g +}