Putting both variants of this function in the same place, in advance of code resuse. Note that I tweaked the API slightly in advance of additional callers without the alignment requirement. Some of the existing callers may also be okay with weaker alignment requirements, but that should be it's own set of changes.
const DebugLoc &DL, Register DestReg,
Register SrcReg, int64_t Val,
MachineInstr::MIFlag Flag) const {
- MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
- const RISCVInstrInfo *TII = STI.getInstrInfo();
-
- if (DestReg == SrcReg && Val == 0)
- return;
-
- if (isInt<12>(Val)) {
- BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg)
- .addReg(SrcReg)
- .addImm(Val)
- .setMIFlag(Flag);
- return;
- }
-
- // Try to split the offset across two ADDIs. We need to keep the stack pointer
- // aligned after each ADDI. We need to determine the maximum value we can put
- // in each ADDI. In the negative direction, we can use -2048 which is always
- // sufficiently aligned. In the positive direction, we need to find the
- // largest 12-bit immediate that is aligned. Exclude -4096 since it can be
- // created with LUI.
- assert(getStackAlign().value() < 2048 && "Stack alignment too large");
- int64_t MaxPosAdjStep = 2048 - getStackAlign().value();
- if (Val > -4096 && Val <= (2 * MaxPosAdjStep)) {
- int64_t FirstAdj = Val < 0 ? -2048 : MaxPosAdjStep;
- Val -= FirstAdj;
- BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg)
- .addReg(SrcReg)
- .addImm(FirstAdj)
- .setMIFlag(Flag);
- BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg)
- .addReg(DestReg, RegState::Kill)
- .addImm(Val)
- .setMIFlag(Flag);
- return;
- }
-
- unsigned Opc = RISCV::ADD;
- if (Val < 0) {
- Val = -Val;
- Opc = RISCV::SUB;
- }
-
- Register ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
- TII->movImm(MBB, MBBI, DL, ScratchReg, Val, Flag);
- BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg)
- .addReg(SrcReg)
- .addReg(ScratchReg, RegState::Kill)
- .setMIFlag(Flag);
+ // We must keep the stack pointer aligned through any intermediate
+ // updates.
+ const RISCVRegisterInfo &RI = *STI.getRegisterInfo();
+ RI.adjustReg(MBB, MBBI, DL, DestReg, SrcReg, Val, Flag, getStackAlign());
}
// Returns the register used to hold the frame pointer.
return true;
}
+void RISCVRegisterInfo::adjustReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ const DebugLoc &DL, Register DestReg,
+ Register SrcReg, int64_t Val,
+ MachineInstr::MIFlag Flag,
+ MaybeAlign RequiredAlign) const {
+ const uint64_t Align = RequiredAlign.valueOrOne().value();
+ MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
+ const RISCVSubtarget &ST = MBB.getParent()->getSubtarget<RISCVSubtarget>();
+ const RISCVInstrInfo *TII = ST.getInstrInfo();
+
+ if (DestReg == SrcReg && Val == 0)
+ return;
+
+ if (isInt<12>(Val)) {
+ BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg)
+ .addReg(SrcReg)
+ .addImm(Val)
+ .setMIFlag(Flag);
+ return;
+ }
+
+ // Try to split the offset across two ADDIs. We need to keep the intermediate
+ // result aligned after each ADDI. We need to determine the maximum value we
+ // can put in each ADDI. In the negative direction, we can use -2048 which is
+ // always sufficiently aligned. In the positive direction, we need to find the
+ // largest 12-bit immediate that is aligned. Exclude -4096 since it can be
+ // created with LUI.
+ assert(Align < 2048 && "Required alignment too large");
+ int64_t MaxPosAdjStep = 2048 - Align;
+ if (Val > -4096 && Val <= (2 * MaxPosAdjStep)) {
+ int64_t FirstAdj = Val < 0 ? -2048 : MaxPosAdjStep;
+ Val -= FirstAdj;
+ BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg)
+ .addReg(SrcReg)
+ .addImm(FirstAdj)
+ .setMIFlag(Flag);
+ BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DestReg)
+ .addReg(DestReg, RegState::Kill)
+ .addImm(Val)
+ .setMIFlag(Flag);
+ return;
+ }
+
+ unsigned Opc = RISCV::ADD;
+ if (Val < 0) {
+ Val = -Val;
+ Opc = RISCV::SUB;
+ }
+
+ Register ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ TII->movImm(MBB, MBBI, DL, ScratchReg, Val, Flag);
+ BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg)
+ .addReg(SrcReg)
+ .addReg(ScratchReg, RegState::Kill)
+ .setMIFlag(Flag);
+}
+
void RISCVRegisterInfo::adjustReg(MachineBasicBlock::iterator II, Register DestReg,
Register SrcReg, StackOffset Offset) const {
bool hasReservedSpillSlot(const MachineFunction &MF, Register Reg,
int &FrameIdx) const override;
+ // Update DestReg to have the value SrcReg plus an offset. This is
+ // used during frame layout, and we may need to ensure that if we
+ // split the offset internally that the DestReg is always aligned,
+ // assuming that source reg was.
+ void adjustReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+ const DebugLoc &DL, Register DestReg, Register SrcReg,
+ int64_t Val, MachineInstr::MIFlag Flag,
+ MaybeAlign RequiredAlign) const;
+
// Update DestReg to have the value of SrcReg plus an Offset.
void adjustReg(MachineBasicBlock::iterator II, Register DestReg,
Register SrcReg, StackOffset Offset) const;