return &X86::GR16_NOREXRegClass;
else if (A == &X86::GR16_ABCDRegClass)
return &X86::GR16_ABCDRegClass;
+ } else if (B == &X86::FR32RegClass) {
+ return A;
}
break;
case 2:
else if (A == &X86::GR16RegClass || A == &X86::GR16_ABCDRegClass ||
A == &X86::GR16_NOREXRegClass)
return &X86::GR16_ABCDRegClass;
+ } else if (B == &X86::FR64RegClass) {
+ return A;
}
break;
case 3:
return &X86::GR32_NOREXRegClass;
else if (A == &X86::GR32_ABCDRegClass)
return &X86::GR64_ABCDRegClass;
+ } else if (B == &X86::VR128RegClass) {
+ return A;
}
break;
case 4:
const unsigned *
X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
bool callsEHReturn = false;
+ bool ghcCall = false;
if (MF) {
- const MachineFrameInfo *MFI = MF->getFrameInfo();
- const MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
- callsEHReturn = (MMI ? MMI->callsEHReturn() : false);
+ callsEHReturn = MF->getMMI().callsEHReturn();
+ const Function *F = MF->getFunction();
+ ghcCall = (F ? F->getCallingConv() == CallingConv::GHC : false);
}
+ static const unsigned GhcCalleeSavedRegs[] = {
+ 0
+ };
+
static const unsigned CalleeSavedRegs32Bit[] = {
X86::ESI, X86::EDI, X86::EBX, X86::EBP, 0
};
X86::XMM14, X86::XMM15, 0
};
- if (Is64Bit) {
+ if (ghcCall) {
+ return GhcCalleeSavedRegs;
+ } else if (Is64Bit) {
if (IsWin64)
return CalleeSavedRegsWin64;
else
const TargetRegisterClass* const*
X86RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
bool callsEHReturn = false;
-
- if (MF) {
- const MachineFrameInfo *MFI = MF->getFrameInfo();
- const MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
- callsEHReturn = (MMI ? MMI->callsEHReturn() : false);
- }
+ if (MF)
+ callsEHReturn = MF->getMMI().callsEHReturn();
static const TargetRegisterClass * const CalleeSavedRegClasses32Bit[] = {
&X86::GR32RegClass, &X86::GR32RegClass,
/// or if frame pointer elimination is disabled.
bool X86RegisterInfo::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
- const MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
+ const MachineModuleInfo &MMI = MF.getMMI();
return (NoFramePointerElim ||
needsStackRealignment(MF) ||
MFI->hasVarSizedObjects() ||
MFI->isFrameAddressTaken() ||
MF.getInfo<X86MachineFunctionInfo>()->getForceFramePointer() ||
- (MMI && MMI->callsUnwindInit()));
+ MMI.callsUnwindInit());
}
bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const {
unsigned
X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, int *Value,
+ int SPAdj, FrameIndexValue *Value,
RegScavenger *RS) const{
assert(SPAdj == 0 && "Unexpected");
}
void X86RegisterInfo::emitCalleeSavedFrameMoves(MachineFunction &MF,
- unsigned LabelId,
+ MCSymbol *Label,
unsigned FramePtr) const {
MachineFrameInfo *MFI = MF.getFrameInfo();
- MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
- if (!MMI) return;
+ MachineModuleInfo &MMI = MF.getMMI();
// Add callee saved registers to move list.
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
if (CSI.empty()) return;
- std::vector<MachineMove> &Moves = MMI->getFrameMoves();
+ std::vector<MachineMove> &Moves = MMI.getFrameMoves();
const TargetData *TD = MF.getTarget().getTargetData();
bool HasFP = hasFP(MF);
MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
MachineLocation CSSrc(Reg);
- Moves.push_back(MachineMove(LabelId, CSDst, CSSrc));
+ Moves.push_back(MachineMove(Label, CSDst, CSSrc));
}
}
MachineFrameInfo *MFI = MF.getFrameInfo();
const Function *Fn = MF.getFunction();
const X86Subtarget *Subtarget = &MF.getTarget().getSubtarget<X86Subtarget>();
- MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
+ MachineModuleInfo &MMI = MF.getMMI();
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
- bool needsFrameMoves = (MMI && MMI->hasDebugInfo()) ||
+ bool needsFrameMoves = MMI.hasDebugInfo() ||
!Fn->doesNotThrow() || UnwindTablesMandatory;
uint64_t MaxAlign = MFI->getMaxAlignment(); // Desired stack alignment.
uint64_t StackSize = MFI->getStackSize(); // Number of bytes to allocate.
// REG < 64 => DW_CFA_offset + Reg
// ELSE => DW_CFA_offset_extended
- std::vector<MachineMove> &Moves = MMI->getFrameMoves();
+ std::vector<MachineMove> &Moves = MMI.getFrameMoves();
const TargetData *TD = MF.getTarget().getTargetData();
uint64_t NumBytes = 0;
- int stackGrowth =
- (MF.getTarget().getFrameInfo()->getStackGrowthDirection() ==
- TargetFrameInfo::StackGrowsUp ?
- TD->getPointerSize() : -TD->getPointerSize());
+ int stackGrowth = -TD->getPointerSize();
if (HasFP) {
// Calculate required stack adjustment.
if (needsFrameMoves) {
// Mark the place where EBP/RBP was saved.
- unsigned FrameLabelId = MMI->NextLabelID();
- BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addImm(FrameLabelId);
+ MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol();
+ BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addSym(FrameLabel);
// Define the current CFA rule to use the provided offset.
if (StackSize) {
MachineLocation SPDst(MachineLocation::VirtualFP);
MachineLocation SPSrc(MachineLocation::VirtualFP, 2 * stackGrowth);
- Moves.push_back(MachineMove(FrameLabelId, SPDst, SPSrc));
+ Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
} else {
// FIXME: Verify & implement for FP
MachineLocation SPDst(StackPtr);
MachineLocation SPSrc(StackPtr, stackGrowth);
- Moves.push_back(MachineMove(FrameLabelId, SPDst, SPSrc));
+ Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
}
// Change the rule for the FramePtr to be an "offset" rule.
- MachineLocation FPDst(MachineLocation::VirtualFP,
- 2 * stackGrowth);
+ MachineLocation FPDst(MachineLocation::VirtualFP, 2 * stackGrowth);
MachineLocation FPSrc(FramePtr);
- Moves.push_back(MachineMove(FrameLabelId, FPDst, FPSrc));
+ Moves.push_back(MachineMove(FrameLabel, FPDst, FPSrc));
}
// Update EBP with the new base value...
if (needsFrameMoves) {
// Mark effective beginning of when frame pointer becomes valid.
- unsigned FrameLabelId = MMI->NextLabelID();
- BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addImm(FrameLabelId);
+ MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol();
+ BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addSym(FrameLabel);
// Define the current CFA to use the EBP/RBP register.
MachineLocation FPDst(FramePtr);
MachineLocation FPSrc(MachineLocation::VirtualFP);
- Moves.push_back(MachineMove(FrameLabelId, FPDst, FPSrc));
+ Moves.push_back(MachineMove(FrameLabel, FPDst, FPSrc));
}
// Mark the FramePtr as live-in in every block except the entry.
if (!HasFP && needsFrameMoves) {
// Mark callee-saved push instruction.
- unsigned LabelId = MMI->NextLabelID();
- BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addImm(LabelId);
+ MCSymbol *Label = MMI.getContext().CreateTempSymbol();
+ BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addSym(Label);
// Define the current CFA rule to use the provided offset.
unsigned Ptr = StackSize ?
MachineLocation::VirtualFP : StackPtr;
MachineLocation SPDst(Ptr);
MachineLocation SPSrc(Ptr, StackOffset);
- Moves.push_back(MachineMove(LabelId, SPDst, SPSrc));
+ Moves.push_back(MachineMove(Label, SPDst, SPSrc));
StackOffset += stackGrowth;
}
}
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
.addImm(NumBytes);
BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32))
- .addExternalSymbol("_alloca");
+ .addExternalSymbol("_alloca")
+ .addReg(StackPtr, RegState::Define | RegState::Implicit);
} else {
// Save EAX
BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH32r))
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
.addImm(NumBytes - 4);
BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32))
- .addExternalSymbol("_alloca");
+ .addExternalSymbol("_alloca")
+ .addReg(StackPtr, RegState::Define | RegState::Implicit);
// Restore EAX
MachineInstr *MI = addRegOffset(BuildMI(MF, DL, TII.get(X86::MOV32rm),
if ((NumBytes || PushedRegs) && needsFrameMoves) {
// Mark end of stack pointer adjustment.
- unsigned LabelId = MMI->NextLabelID();
- BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addImm(LabelId);
+ MCSymbol *Label = MMI.getContext().CreateTempSymbol();
+ BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addSym(Label);
if (!HasFP && NumBytes) {
// Define the current CFA rule to use the provided offset.
MachineLocation SPDst(MachineLocation::VirtualFP);
MachineLocation SPSrc(MachineLocation::VirtualFP,
-StackSize + stackGrowth);
- Moves.push_back(MachineMove(LabelId, SPDst, SPSrc));
+ Moves.push_back(MachineMove(Label, SPDst, SPSrc));
} else {
// FIXME: Verify & implement for FP
MachineLocation SPDst(StackPtr);
MachineLocation SPSrc(StackPtr, stackGrowth);
- Moves.push_back(MachineMove(LabelId, SPDst, SPSrc));
+ Moves.push_back(MachineMove(Label, SPDst, SPSrc));
}
}
// Emit DWARF info specifying the offsets of the callee-saved registers.
if (PushedRegs)
- emitCalleeSavedFrameMoves(MF, LabelId, HasFP ? FramePtr : StackPtr);
+ emitCalleeSavedFrameMoves(MF, Label, HasFP ? FramePtr : StackPtr);
}
}
case X86::RETI:
case X86::TCRETURNdi:
case X86::TCRETURNri:
- case X86::TCRETURNri64:
+ case X86::TCRETURNmi:
case X86::TCRETURNdi64:
+ case X86::TCRETURNri64:
+ case X86::TCRETURNmi64:
case X86::EH_RETURN:
case X86::EH_RETURN64:
- case X86::TAILJMPd:
- case X86::TAILJMPr:
- case X86::TAILJMPm:
break; // These are ok
}
TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr),
StackPtr).addReg(DestAddr.getReg());
} else if (RetOpcode == X86::TCRETURNri || RetOpcode == X86::TCRETURNdi ||
- RetOpcode== X86::TCRETURNri64 || RetOpcode == X86::TCRETURNdi64) {
+ RetOpcode == X86::TCRETURNmi ||
+ RetOpcode == X86::TCRETURNri64 || RetOpcode == X86::TCRETURNdi64 ||
+ RetOpcode == X86::TCRETURNmi64) {
+ bool isMem = RetOpcode == X86::TCRETURNmi || RetOpcode == X86::TCRETURNmi64;
// Tail call return: adjust the stack pointer and jump to callee.
MBBI = prior(MBB.end());
MachineOperand &JumpTarget = MBBI->getOperand(0);
- MachineOperand &StackAdjust = MBBI->getOperand(1);
+ MachineOperand &StackAdjust = MBBI->getOperand(isMem ? 5 : 1);
assert(StackAdjust.isImm() && "Expecting immediate value.");
// Adjust stack pointer.
}
// Jump to label or value in register.
- if (RetOpcode == X86::TCRETURNdi|| RetOpcode == X86::TCRETURNdi64) {
- BuildMI(MBB, MBBI, DL, TII.get(X86::TAILJMPd)).
+ if (RetOpcode == X86::TCRETURNdi || RetOpcode == X86::TCRETURNdi64) {
+ BuildMI(MBB, MBBI, DL, TII.get((RetOpcode == X86::TCRETURNdi)
+ ? X86::TAILJMPd : X86::TAILJMPd64)).
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
JumpTarget.getTargetFlags());
+ } else if (RetOpcode == X86::TCRETURNmi || RetOpcode == X86::TCRETURNmi64) {
+ MachineInstrBuilder MIB =
+ BuildMI(MBB, MBBI, DL, TII.get((RetOpcode == X86::TCRETURNmi)
+ ? X86::TAILJMPm : X86::TAILJMPm64));
+ for (unsigned i = 0; i != 5; ++i)
+ MIB.addOperand(MBBI->getOperand(i));
} else if (RetOpcode == X86::TCRETURNri64) {
BuildMI(MBB, MBBI, DL, TII.get(X86::TAILJMPr64), JumpTarget.getReg());
} else {
}
#include "X86GenRegisterInfo.inc"
+
+namespace {
+ struct MSAH : public MachineFunctionPass {
+ static char ID;
+ MSAH() : MachineFunctionPass(&ID) {}
+
+ virtual bool runOnMachineFunction(MachineFunction &MF) {
+ const X86TargetMachine *TM =
+ static_cast<const X86TargetMachine *>(&MF.getTarget());
+ const X86RegisterInfo *X86RI = TM->getRegisterInfo();
+ MachineRegisterInfo &RI = MF.getRegInfo();
+ X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
+ unsigned StackAlignment = X86RI->getStackAlignment();
+
+ // Be over-conservative: scan over all vreg defs and find whether vector
+ // registers are used. If yes, there is a possibility that vector register
+ // will be spilled and thus require dynamic stack realignment.
+ for (unsigned RegNum = TargetRegisterInfo::FirstVirtualRegister;
+ RegNum < RI.getLastVirtReg(); ++RegNum)
+ if (RI.getRegClass(RegNum)->getAlignment() > StackAlignment) {
+ FuncInfo->setReserveFP(true);
+ return true;
+ }
+
+ // Nothing to do
+ return false;
+ }
+
+ virtual const char *getPassName() const {
+ return "X86 Maximal Stack Alignment Check";
+ }
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesCFG();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+ };
+
+ char MSAH::ID = 0;
+}
+
+FunctionPass*
+llvm::createX86MaxStackAlignmentHeuristicPass() { return new MSAH(); }