Skip to content

Commit ad7e95d

Browse files
committed
[AArch64] NFC: Generalize emitFrameOffset to support more than byte offsets.
Refactor emitFrameOffset to accept a StackOffset struct as its offset argument. This method currently only supports byte offsets (MVT::i8) but will be extended in a later patch to support scalable offsets (MVT::nxv1i8) as well. Reviewers: thegameg, rovka, t.p.northover, efriedma, greened Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D61436 llvm-svn: 368049
1 parent fc34a53 commit ad7e95d

File tree

1 file changed

+83
-65
lines changed

1 file changed

+83
-65
lines changed

llvm/lib/Target/AArch64/AArch64InstrInfo.cpp

Lines changed: 83 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2972,23 +2972,29 @@ void AArch64InstrInfo::loadRegFromStackSlot(
29722972
MI.addMemOperand(MMO);
29732973
}
29742974

2975-
void llvm::emitFrameOffset(MachineBasicBlock &MBB,
2976-
MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
2977-
unsigned DestReg, unsigned SrcReg,
2978-
StackOffset SOffset, const TargetInstrInfo *TII,
2979-
MachineInstr::MIFlag Flag, bool SetNZCV,
2980-
bool NeedsWinCFI, bool *HasWinCFI) {
2981-
int64_t Offset;
2982-
SOffset.getForFrameOffset(Offset);
2983-
if (DestReg == SrcReg && Offset == 0)
2984-
return;
2985-
2986-
assert((DestReg != AArch64::SP || Offset % 16 == 0) &&
2987-
"SP increment/decrement not 16-byte aligned");
2988-
2989-
bool isSub = Offset < 0;
2990-
if (isSub)
2991-
Offset = -Offset;
2975+
// Helper function to emit a frame offset adjustment from a given
2976+
// pointer (SrcReg), stored into DestReg. This function is explicit
2977+
// in that it requires the opcode.
2978+
static void emitFrameOffsetAdj(MachineBasicBlock &MBB,
2979+
MachineBasicBlock::iterator MBBI,
2980+
const DebugLoc &DL, unsigned DestReg,
2981+
unsigned SrcReg, int64_t Offset, unsigned Opc,
2982+
const TargetInstrInfo *TII,
2983+
MachineInstr::MIFlag Flag, bool NeedsWinCFI,
2984+
bool *HasWinCFI) {
2985+
int Sign = 1;
2986+
unsigned MaxEncoding, ShiftSize;
2987+
switch (Opc) {
2988+
case AArch64::ADDXri:
2989+
case AArch64::ADDSXri:
2990+
case AArch64::SUBXri:
2991+
case AArch64::SUBSXri:
2992+
MaxEncoding = 0xfff;
2993+
ShiftSize = 12;
2994+
break;
2995+
default:
2996+
llvm_unreachable("Unsupported opcode");
2997+
}
29922998

29932999
// FIXME: If the offset won't fit in 24-bits, compute the offset into a
29943000
// scratch register. If DestReg is a virtual register, use it as the
@@ -3001,65 +3007,77 @@ void llvm::emitFrameOffset(MachineBasicBlock &MBB,
30013007
// of code.
30023008
// assert(Offset < (1 << 24) && "unimplemented reg plus immediate");
30033009

3004-
unsigned Opc;
3005-
if (SetNZCV)
3006-
Opc = isSub ? AArch64::SUBSXri : AArch64::ADDSXri;
3007-
else
3008-
Opc = isSub ? AArch64::SUBXri : AArch64::ADDXri;
3009-
const unsigned MaxEncoding = 0xfff;
3010-
const unsigned ShiftSize = 12;
30113010
const unsigned MaxEncodableValue = MaxEncoding << ShiftSize;
3012-
while (((unsigned)Offset) >= (1 << ShiftSize)) {
3013-
unsigned ThisVal;
3014-
if (((unsigned)Offset) > MaxEncodableValue) {
3015-
ThisVal = MaxEncodableValue;
3016-
} else {
3017-
ThisVal = Offset & MaxEncodableValue;
3011+
do {
3012+
unsigned ThisVal = std::min<unsigned>(Offset, MaxEncodableValue);
3013+
unsigned LocalShiftSize = 0;
3014+
if (ThisVal > MaxEncoding) {
3015+
ThisVal = ThisVal >> ShiftSize;
3016+
LocalShiftSize = ShiftSize;
30183017
}
30193018
assert((ThisVal >> ShiftSize) <= MaxEncoding &&
30203019
"Encoding cannot handle value that big");
3021-
BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg)
3022-
.addReg(SrcReg)
3023-
.addImm(ThisVal >> ShiftSize)
3024-
.addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftSize))
3025-
.setMIFlag(Flag);
3026-
3027-
if (NeedsWinCFI && SrcReg == AArch64::SP && DestReg == AArch64::SP) {
3020+
auto MBI = BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg)
3021+
.addReg(SrcReg)
3022+
.addImm(Sign * (int)ThisVal);
3023+
if (ShiftSize)
3024+
MBI = MBI.addImm(
3025+
AArch64_AM::getShifterImm(AArch64_AM::LSL, LocalShiftSize));
3026+
MBI = MBI.setMIFlag(Flag);
3027+
3028+
if (NeedsWinCFI) {
3029+
assert(Sign == 1 && "SEH directives should always have a positive sign");
3030+
int Imm = (int)(ThisVal << LocalShiftSize);
3031+
if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) ||
3032+
(SrcReg == AArch64::FP && DestReg == AArch64::SP)) {
3033+
if (HasWinCFI)
3034+
*HasWinCFI = true;
3035+
if (Imm == 0)
3036+
BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_SetFP)).setMIFlag(Flag);
3037+
else
3038+
BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AddFP))
3039+
.addImm(Imm)
3040+
.setMIFlag(Flag);
3041+
assert((Offset - Imm) == 0 && "Expected remaining offset to be zero to "
3042+
"emit a single SEH directive");
3043+
} else if (DestReg == AArch64::SP) {
3044+
if (HasWinCFI)
3045+
*HasWinCFI = true;
3046+
assert(SrcReg == AArch64::SP && "Unexpected SrcReg for SEH_StackAlloc");
3047+
BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
3048+
.addImm(Imm)
3049+
.setMIFlag(Flag);
3050+
}
30283051
if (HasWinCFI)
30293052
*HasWinCFI = true;
3030-
BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
3031-
.addImm(ThisVal)
3032-
.setMIFlag(Flag);
30333053
}
30343054

30353055
SrcReg = DestReg;
3036-
Offset -= ThisVal;
3037-
if (Offset == 0)
3038-
return;
3039-
}
3040-
BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg)
3041-
.addReg(SrcReg)
3042-
.addImm(Offset)
3043-
.addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, 0))
3044-
.setMIFlag(Flag);
3056+
Offset -= ThisVal << LocalShiftSize;
3057+
} while (Offset);
3058+
}
30453059

3046-
if (NeedsWinCFI) {
3047-
if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) ||
3048-
(SrcReg == AArch64::FP && DestReg == AArch64::SP)) {
3049-
if (HasWinCFI)
3050-
*HasWinCFI = true;
3051-
if (Offset == 0)
3052-
BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_SetFP)).
3053-
setMIFlag(Flag);
3054-
else
3055-
BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AddFP)).
3056-
addImm(Offset).setMIFlag(Flag);
3057-
} else if (DestReg == AArch64::SP) {
3058-
if (HasWinCFI)
3059-
*HasWinCFI = true;
3060-
BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc)).
3061-
addImm(Offset).setMIFlag(Flag);
3060+
void llvm::emitFrameOffset(MachineBasicBlock &MBB,
3061+
MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
3062+
unsigned DestReg, unsigned SrcReg,
3063+
StackOffset Offset, const TargetInstrInfo *TII,
3064+
MachineInstr::MIFlag Flag, bool SetNZCV,
3065+
bool NeedsWinCFI, bool *HasWinCFI) {
3066+
int64_t Bytes;
3067+
Offset.getForFrameOffset(Bytes);
3068+
3069+
// First emit non-scalable frame offsets, or a simple 'mov'.
3070+
if (Bytes || (!Offset && SrcReg != DestReg)) {
3071+
assert((DestReg != AArch64::SP || Bytes % 16 == 0) &&
3072+
"SP increment/decrement not 16-byte aligned");
3073+
unsigned Opc = SetNZCV ? AArch64::ADDSXri : AArch64::ADDXri;
3074+
if (Bytes < 0) {
3075+
Bytes = -Bytes;
3076+
Opc = SetNZCV ? AArch64::SUBSXri : AArch64::SUBXri;
30623077
}
3078+
emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, Bytes, Opc, TII, Flag,
3079+
NeedsWinCFI, HasWinCFI);
3080+
SrcReg = DestReg;
30633081
}
30643082
}
30653083

0 commit comments

Comments
 (0)