Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions llvm/lib/Target/AIE/AIE2FrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,31 @@ void AIE2FrameLowering::adjustSPReg(MachineBasicBlock &MBB,
.addImm(StackPtrIncr)
.setMIFlag(Flag);
} else {
LLVM_DEBUG(dbgs() << "Adjust Stack by " << StackPtrIncr << " bytes\n.");
report_fatal_error(
"adjustSPReg cannot yet handle adjustments > +-2^17 bytes");
// AIE2 has no register-form SP pointer add (only the sp_imm forms), and SP
// is reserved, so it cannot be an explicit operand of the general pointer
// add. Copy SP into a scratch pointer register, add the materialized offset
// there, and copy the result back to SP. This is the same sequence the
// backend already uses to update SP for a dynamic stack allocation. The
// scratch registers are resolved by the register scavenger.
MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
auto *RI = static_cast<const AIEBaseRegisterInfo *>(STI.getRegisterInfo());
Register SPReg = RI->getStackPointerRegister();
Register ScratchP = MRI.createVirtualRegister(&AIE2::ePRegClass);
Register ModReg = MRI.createVirtualRegister(&AIE2::eMRegClass);
BuildMI(MBB, MBBI, DL, TII->get(TII->getMvSclOpcode()), ScratchP)
.addReg(SPReg)
.setMIFlag(Flag);
BuildMI(MBB, MBBI, DL, TII->get(AIE2::MOVXM_lng_cg), ModReg)
.addImm(StackPtrIncr)
.setMIFlag(Flag);
BuildMI(MBB, MBBI, DL, TII->get(AIE2::PADDA_lda_ptr_inc_idx))
.addDef(ScratchP)
.addUse(ScratchP)
.addUse(ModReg)
.setMIFlag(Flag);
BuildMI(MBB, MBBI, DL, TII->get(TII->getMvSclOpcode()), SPReg)
.addReg(ScratchP, RegState::Kill)
.setMIFlag(Flag);
}
}

Expand Down
16 changes: 13 additions & 3 deletions llvm/lib/Target/AIE/aie2p/AIE2PFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,19 @@ void AIE2PFrameLowering::adjustSPReg(MachineBasicBlock &MBB,
.addImm(StackPtrIncr)
.setMIFlag(Flag);
} else {
LLVM_DEBUG(dbgs() << "Adjust Stack by " << StackPtrIncr << " bytes\n.");
report_fatal_error(
"adjustSPReg cannot yet handle adjustments > +-2^18 bytes");
// The sp_imm form cannot encode an offset this large. Materialize it in a
// modifier register and use the register form of the SP pointer add, which
// is the sibling of the sp_imm instruction used above. The register
// scavenger resolves the virtual register using the emergency slots that
// processFunctionBeforeFrameFinalized() reserves for large stack frames.
MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
Register ModReg = MRI.createVirtualRegister(&AIE2P::eMRegClass);
BuildMI(MBB, MBBI, DL, TII->get(AIE2P::MOVXM), ModReg)
.addImm(StackPtrIncr)
.setMIFlag(Flag);
BuildMI(MBB, MBBI, DL, TII->get(AIE2P::PADDXM_pstm_sp))
.addReg(ModReg)
.setMIFlag(Flag);
}
}
void AIE2PFrameLowering::determineCalleeSaves(MachineFunction &MF,
Expand Down
16 changes: 13 additions & 3 deletions llvm/lib/Target/AIE/aie2ps/AIE2PSFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,19 @@ void AIE2PSFrameLowering::adjustSPReg(MachineBasicBlock &MBB,
.addImm(StackPtrIncr)
.setMIFlag(Flag);
} else {
LLVM_DEBUG(dbgs() << "Adjust Stack by " << StackPtrIncr << " bytes\n.");
report_fatal_error(
"adjustSPReg cannot yet handle adjustments > +-2^18 bytes");
// The sp_imm form cannot encode an offset this large. Materialize it in a
// modifier register and use the register form of the SP pointer add, which
// is the sibling of the sp_imm instruction used above. The register
// scavenger resolves the virtual register using the emergency slots that
// processFunctionBeforeFrameFinalized() reserves for large stack frames.
MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
Register ModReg = MRI.createVirtualRegister(&AIE2PS::eMRegClass);
BuildMI(MBB, MBBI, DL, TII->get(AIE2PS::MOVXM_lng_cg), ModReg)
.addImm(StackPtrIncr)
.setMIFlag(Flag);
BuildMI(MBB, MBBI, DL, TII->get(AIE2PS::PADDXM_pstm_sp))
.addReg(ModReg)
.setMIFlag(Flag);
}
}

Expand Down
41 changes: 41 additions & 0 deletions llvm/test/CodeGen/AIE/aie2/large-stack-frame.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
;
; This file is licensed under the Apache License v2.0 with LLVM Exceptions.
; See https://llvm.org/LICENSE.txt for license information.
; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
;
; (c) Copyright 2025 Advanced Micro Devices, Inc. or its affiliates
;
; RUN: llc -O0 -verify-machineinstrs -mtriple=aie2 %s -o - | FileCheck %s

; AIE2 has no register-form SP pointer add (only the sp_imm forms) and SP is
; reserved, so a stack frame larger than the sp_imm range (+-2^17 bytes) is
; adjusted by copying SP into a scratch pointer register, adding the materialized
; offset there, and copying back, rather than triggering the "adjustSPReg cannot
; yet handle adjustments > +-2^17 bytes" fatal error.
define void @big_frame(ptr %out) {
; CHECK-LABEL: big_frame:
; CHECK: mov [[P:p[0-9]+]], sp
; CHECK: movxm [[M:m[0-9]+]], #200000
; CHECK: padda {{\[}}[[P]]{{\]}}, [[M]]
; CHECK: mov sp, [[P]]
%buf = alloca [200000 x i8], align 32
%p = getelementptr [200000 x i8], ptr %buf, i64 0, i64 0
store volatile i8 42, ptr %p
%v = load volatile i8, ptr %p
store i8 %v, ptr %out
ret void
}

; A frame within range still uses the compact sp_imm form (no regression, and the
; scratch-register sequence is only used for large frames).
define void @small_frame(ptr %out) {
; CHECK-LABEL: small_frame:
; CHECK-NOT: mov sp, p
; CHECK: paddb [sp], #-32
%buf = alloca [32 x i8], align 32
%p = getelementptr [32 x i8], ptr %buf, i64 0, i64 0
store volatile i8 42, ptr %p
%v = load volatile i8, ptr %p
store i8 %v, ptr %out
ret void
}
41 changes: 41 additions & 0 deletions llvm/test/CodeGen/AIE/aie2p/large-stack-frame.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
;
; This file is licensed under the Apache License v2.0 with LLVM Exceptions.
; See https://llvm.org/LICENSE.txt for license information.
; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
;
; (c) Copyright 2025 Advanced Micro Devices, Inc. or its affiliates
;
; RUN: llc -O0 -verify-machineinstrs -mtriple=aie2p %s -o - | FileCheck %s

; A stack frame larger than the sp_imm encodable range (+-2^18 bytes) must be
; materialized in a modifier register and applied with the register form of the
; SP pointer add, rather than triggering the "adjustSPReg cannot yet handle
; adjustments > +-2^18 bytes" fatal error.
define void @big_frame(ptr %out) {
; CHECK-LABEL: big_frame:
; CHECK: movxm [[M:m[0-9]+]], #300032
; CHECK: paddxm [sp], [[M]]
; CHECK: movxm [[M2:m[0-9]+]], #-300032
; CHECK: paddxm [sp], [[M2]]
%buf = alloca [300000 x i8], align 64
%p = getelementptr [300000 x i8], ptr %buf, i64 0, i64 0
store volatile i8 42, ptr %p
%v = load volatile i8, ptr %p
store i8 %v, ptr %out
ret void
}

; A frame within range still uses the compact sp_imm form (no regression, and the
; register fallback is only taken for large frames).
define void @small_frame(ptr %out) {
; CHECK-LABEL: small_frame:
; CHECK: paddxm [sp], #64
; CHECK-NOT: paddxm [sp], m
; CHECK: paddxm [sp], #-64
%buf = alloca [64 x i8], align 64
%p = getelementptr [64 x i8], ptr %buf, i64 0, i64 0
store volatile i8 42, ptr %p
%v = load volatile i8, ptr %p
store i8 %v, ptr %out
ret void
}
41 changes: 41 additions & 0 deletions llvm/test/CodeGen/AIE/aie2ps/large-stack-frame.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
;
; This file is licensed under the Apache License v2.0 with LLVM Exceptions.
; See https://llvm.org/LICENSE.txt for license information.
; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
;
; (c) Copyright 2025 Advanced Micro Devices, Inc. or its affiliates
;
; RUN: llc -O0 -verify-machineinstrs -mtriple=aie2ps %s -o - | FileCheck %s

; A stack frame larger than the sp_imm encodable range (+-2^18 bytes) must be
; materialized in a modifier register and applied with the register form of the
; SP pointer add, rather than triggering the "adjustSPReg cannot yet handle
; adjustments > +-2^18 bytes" fatal error.
define void @big_frame(ptr %out) {
; CHECK-LABEL: big_frame:
; CHECK: movxm [[M:m[0-9]+]], #300032
; CHECK: paddxm [sp], [[M]]
; CHECK: movxm [[M2:m[0-9]+]], #-300032
; CHECK: paddxm [sp], [[M2]]
%buf = alloca [300000 x i8], align 64
%p = getelementptr [300000 x i8], ptr %buf, i64 0, i64 0
store volatile i8 42, ptr %p
%v = load volatile i8, ptr %p
store i8 %v, ptr %out
ret void
}

; A frame within range still uses the compact sp_imm form (no regression, and the
; register fallback is only taken for large frames).
define void @small_frame(ptr %out) {
; CHECK-LABEL: small_frame:
; CHECK: paddxm [sp], #64
; CHECK-NOT: paddxm [sp], m
; CHECK: paddxm [sp], #-64
%buf = alloca [64 x i8], align 64
%p = getelementptr [64 x i8], ptr %buf, i64 0, i64 0
store volatile i8 42, ptr %p
%v = load volatile i8, ptr %p
store i8 %v, ptr %out
ret void
}