Index: lib/Target/AArch64/AArch64FrameLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64FrameLowering.cpp +++ lib/Target/AArch64/AArch64FrameLowering.cpp @@ -349,13 +349,16 @@ // Allocate space for the rest of the frame. const unsigned Alignment = MFI->getMaxAlignment(); - const bool NeedsRealignment = (Alignment > 16); + const bool NeedsRealignment = RegInfo->needsStackRealignment(MF); unsigned scratchSPReg = AArch64::SP; - if (NeedsRealignment) { + if (NumBytes && NeedsRealignment) { // Use the first callee-saved register as a scratch register - assert(MF.getRegInfo().isPhysRegUsed(AArch64::X9) && + if (RegInfo->hasBasePointer(MF)) + scratchSPReg = RegInfo->getBaseRegister(); + else + scratchSPReg = AArch64::X9; + assert(MF.getRegInfo().isPhysRegUsed(scratchSPReg) && "No scratch register to align SP!"); - scratchSPReg = AArch64::X9; } // If we're a leaf function, try using the red zone. @@ -366,9 +369,6 @@ emitFrameOffset(MBB, MBBI, DL, scratchSPReg, AArch64::SP, -NumBytes, TII, MachineInstr::FrameSetup); - assert(!(NeedsRealignment && NumBytes==0) && - "NumBytes should never be 0 when realignment is needed"); - if (NumBytes && NeedsRealignment) { const unsigned NrBitsToZero = countTrailingZeros(Alignment); assert(NrBitsToZero > 1); Index: test/CodeGen/AArch64/aarch64-dynamic-stack-layout.ll =================================================================== --- test/CodeGen/AArch64/aarch64-dynamic-stack-layout.ll +++ test/CodeGen/AArch64/aarch64-dynamic-stack-layout.ll @@ -345,8 +345,8 @@ ; bytes & the base pointer (x19) gets initialized to ; this 128-byte aligned area for local variables & ; spill slots -; CHECK: sub x9, sp, #80 // =80 -; CHECK: and sp, x9, #0xffffffffffffff80 +; CHECK: sub x19, sp, #80 // =80 +; CHECK: and sp, x19, #0xffffffffffffff80 ; CHECK: mov x19, sp ; Check correctness of cfi pseudo-instructions ; CHECK: .cfi_def_cfa w29, 16 @@ -406,8 +406,8 @@ ; bytes & the base pointer (x19) gets initialized to ; this 128-byte aligned area for local variables & ; spill slots -; CHECK: sub x9, sp, #96 -; CHECK: and sp, x9, #0xffffffffffffff80 +; CHECK: sub x19, sp, #96 +; CHECK: and sp, x19, #0xffffffffffffff80 ; CHECK: mov x19, sp ; Check correct access to arguments passed on the stack, through frame pointer ; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] @@ -457,8 +457,8 @@ ; bytes & the base pointer (x19) gets initialized to ; this 128-byte aligned area for local variables & ; spill slots -; CHECK: sub x9, sp, #7, lsl #12 -; CHECK: and sp, x9, #0xffffffffffff8000 +; CHECK: sub x19, sp, #7, lsl #12 +; CHECK: and sp, x19, #0xffffffffffff8000 ; CHECK: mov x19, sp ; Check correct access to arguments passed on the stack, through frame pointer ; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] @@ -482,6 +482,58 @@ ; CHECK: ldp x20, x19, [sp], #32 ; CHECK: ret + +define void @realign_conditional(i1 %b) { +entry: + br i1 %b, label %bb0, label %bb1 + +bb0: + %MyAlloca = alloca i8, i64 64, align 32 + br label %bb1 + +bb1: + ret void +} + +; CHECK-LABEL: realign_conditional +; No realignment in the prologue. +; CHECK-NOT: and +; CHECK-NOT: 0xffffffffffffffe0 +; CHECK: tbz {{.*}} .[[LABEL:.*]] +; Stack is realigned in a non-entry BB. +; CHECK: sub [[REG:x[01-9]+]], sp, #64 +; CHECK: and sp, [[REG]], #0xffffffffffffffe0 +; CHECK: .[[LABEL]]: +; CHECK: ret + + +define void @realign_conditional2(i1 %b) { +entry: + %tmp = alloca i8, i32 4 + br i1 %b, label %bb0, label %bb1 + +bb0: + %MyAlloca = alloca i8, i64 64, align 32 + br label %bb1 + +bb1: + ret void +} + +; CHECK-LABEL: realign_conditional2 +; Extra realignment in the prologue (performance issue). +; X19 is used as a scratch register for SP realignment before it is assigned the +; base pointer. +; CHECK: sub x19, sp, #32 // =32 +; CHECK: and sp, x19, #0xffffffffffffffe0 +; CHECK: mov x19, sp +; CHECK: tbz {{.*}} .[[LABEL:.*]] +; Stack is realigned in a non-entry BB. +; CHECK: sub [[REG:x[01-9]+]], sp, #64 +; CHECK: and sp, [[REG]], #0xffffffffffffffe0 +; CHECK: .[[LABEL]]: +; CHECK: ret + attributes #0 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }