@@ -2972,23 +2972,29 @@ void AArch64InstrInfo::loadRegFromStackSlot(
2972
2972
MI.addMemOperand (MMO);
2973
2973
}
2974
2974
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
+ }
2992
2998
2993
2999
// FIXME: If the offset won't fit in 24-bits, compute the offset into a
2994
3000
// scratch register. If DestReg is a virtual register, use it as the
@@ -3001,65 +3007,77 @@ void llvm::emitFrameOffset(MachineBasicBlock &MBB,
3001
3007
// of code.
3002
3008
// assert(Offset < (1 << 24) && "unimplemented reg plus immediate");
3003
3009
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 ;
3011
3010
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 ;
3018
3017
}
3019
3018
assert ((ThisVal >> ShiftSize) <= MaxEncoding &&
3020
3019
" 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
+ }
3028
3051
if (HasWinCFI)
3029
3052
*HasWinCFI = true ;
3030
- BuildMI (MBB, MBBI, DL, TII->get (AArch64::SEH_StackAlloc))
3031
- .addImm (ThisVal)
3032
- .setMIFlag (Flag);
3033
3053
}
3034
3054
3035
3055
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
+ }
3045
3059
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;
3062
3077
}
3078
+ emitFrameOffsetAdj (MBB, MBBI, DL, DestReg, SrcReg, Bytes, Opc, TII, Flag,
3079
+ NeedsWinCFI, HasWinCFI);
3080
+ SrcReg = DestReg;
3063
3081
}
3064
3082
}
3065
3083
0 commit comments