diff options
Diffstat (limited to 'llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp')
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp | 140 |
1 files changed, 116 insertions, 24 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp index 14f839cd4f81..886158ca4490 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -43,24 +43,27 @@ AArch64RegisterInfo::AArch64RegisterInfo(const Triple &TT) const MCPhysReg * AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { assert(MF && "Invalid MachineFunction pointer."); - if (MF->getFunction().getCallingConv() == CallingConv::CFGuard_Check) - return CSR_Win_AArch64_CFGuard_Check_SaveList; - if (MF->getSubtarget<AArch64Subtarget>().isTargetWindows()) - return CSR_Win_AArch64_AAPCS_SaveList; + if (MF->getFunction().getCallingConv() == CallingConv::GHC) // GHC set of callee saved regs is empty as all those regs are // used for passing STG regs around return CSR_AArch64_NoRegs_SaveList; if (MF->getFunction().getCallingConv() == CallingConv::AnyReg) return CSR_AArch64_AllRegs_SaveList; + + // Darwin has its own CSR_AArch64_AAPCS_SaveList, which means most CSR save + // lists depending on that will need to have their Darwin variant as well. + if (MF->getSubtarget<AArch64Subtarget>().isTargetDarwin()) + return getDarwinCalleeSavedRegs(MF); + + if (MF->getFunction().getCallingConv() == CallingConv::CFGuard_Check) + return CSR_Win_AArch64_CFGuard_Check_SaveList; + if (MF->getSubtarget<AArch64Subtarget>().isTargetWindows()) + return CSR_Win_AArch64_AAPCS_SaveList; if (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall) return CSR_AArch64_AAVPCS_SaveList; if (MF->getFunction().getCallingConv() == CallingConv::AArch64_SVE_VectorCall) return CSR_AArch64_SVE_AAPCS_SaveList; - if (MF->getFunction().getCallingConv() == CallingConv::CXX_FAST_TLS) - return MF->getInfo<AArch64FunctionInfo>()->isSplitCSR() ? - CSR_AArch64_CXX_TLS_Darwin_PE_SaveList : - CSR_AArch64_CXX_TLS_Darwin_SaveList; if (MF->getSubtarget<AArch64Subtarget>().getTargetLowering() ->supportSwiftError() && MF->getFunction().getAttributes().hasAttrSomewhere( @@ -68,17 +71,47 @@ AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { return CSR_AArch64_AAPCS_SwiftError_SaveList; if (MF->getFunction().getCallingConv() == CallingConv::PreserveMost) return CSR_AArch64_RT_MostRegs_SaveList; - if (MF->getSubtarget<AArch64Subtarget>().isTargetDarwin()) - return CSR_Darwin_AArch64_AAPCS_SaveList; + if (MF->getFunction().getCallingConv() == CallingConv::Win64) + // This is for OSes other than Windows; Windows is a separate case further + // above. + return CSR_AArch64_AAPCS_X18_SaveList; return CSR_AArch64_AAPCS_SaveList; } +const MCPhysReg * +AArch64RegisterInfo::getDarwinCalleeSavedRegs(const MachineFunction *MF) const { + assert(MF && "Invalid MachineFunction pointer."); + assert(MF->getSubtarget<AArch64Subtarget>().isTargetDarwin() && + "Invalid subtarget for getDarwinCalleeSavedRegs"); + + if (MF->getFunction().getCallingConv() == CallingConv::CFGuard_Check) + report_fatal_error( + "Calling convention CFGuard_Check is unsupported on Darwin."); + if (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall) + return CSR_Darwin_AArch64_AAVPCS_SaveList; + if (MF->getFunction().getCallingConv() == CallingConv::AArch64_SVE_VectorCall) + report_fatal_error( + "Calling convention SVE_VectorCall is unsupported on Darwin."); + if (MF->getFunction().getCallingConv() == CallingConv::CXX_FAST_TLS) + return MF->getInfo<AArch64FunctionInfo>()->isSplitCSR() + ? CSR_Darwin_AArch64_CXX_TLS_PE_SaveList + : CSR_Darwin_AArch64_CXX_TLS_SaveList; + if (MF->getSubtarget<AArch64Subtarget>().getTargetLowering() + ->supportSwiftError() && + MF->getFunction().getAttributes().hasAttrSomewhere( + Attribute::SwiftError)) + return CSR_Darwin_AArch64_AAPCS_SwiftError_SaveList; + if (MF->getFunction().getCallingConv() == CallingConv::PreserveMost) + return CSR_Darwin_AArch64_RT_MostRegs_SaveList; + return CSR_Darwin_AArch64_AAPCS_SaveList; +} + const MCPhysReg *AArch64RegisterInfo::getCalleeSavedRegsViaCopy( const MachineFunction *MF) const { assert(MF && "Invalid MachineFunction pointer."); if (MF->getFunction().getCallingConv() == CallingConv::CXX_FAST_TLS && MF->getInfo<AArch64FunctionInfo>()->isSplitCSR()) - return CSR_AArch64_CXX_TLS_Darwin_ViaCopy_SaveList; + return CSR_Darwin_AArch64_CXX_TLS_ViaCopy_SaveList; return nullptr; } @@ -113,6 +146,32 @@ AArch64RegisterInfo::getSubClassWithSubReg(const TargetRegisterClass *RC, } const uint32_t * +AArch64RegisterInfo::getDarwinCallPreservedMask(const MachineFunction &MF, + CallingConv::ID CC) const { + assert(MF.getSubtarget<AArch64Subtarget>().isTargetDarwin() && + "Invalid subtarget for getDarwinCallPreservedMask"); + + if (CC == CallingConv::CXX_FAST_TLS) + return CSR_Darwin_AArch64_CXX_TLS_RegMask; + if (CC == CallingConv::AArch64_VectorCall) + return CSR_Darwin_AArch64_AAVPCS_RegMask; + if (CC == CallingConv::AArch64_SVE_VectorCall) + report_fatal_error( + "Calling convention SVE_VectorCall is unsupported on Darwin."); + if (CC == CallingConv::CFGuard_Check) + report_fatal_error( + "Calling convention CFGuard_Check is unsupported on Darwin."); + if (MF.getSubtarget<AArch64Subtarget>() + .getTargetLowering() + ->supportSwiftError() && + MF.getFunction().getAttributes().hasAttrSomewhere(Attribute::SwiftError)) + return CSR_Darwin_AArch64_AAPCS_SwiftError_RegMask; + if (CC == CallingConv::PreserveMost) + return CSR_Darwin_AArch64_RT_MostRegs_RegMask; + return CSR_Darwin_AArch64_AAPCS_RegMask; +} + +const uint32_t * AArch64RegisterInfo::getCallPreservedMask(const MachineFunction &MF, CallingConv::ID CC) const { bool SCS = MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack); @@ -121,9 +180,14 @@ AArch64RegisterInfo::getCallPreservedMask(const MachineFunction &MF, return SCS ? CSR_AArch64_NoRegs_SCS_RegMask : CSR_AArch64_NoRegs_RegMask; if (CC == CallingConv::AnyReg) return SCS ? CSR_AArch64_AllRegs_SCS_RegMask : CSR_AArch64_AllRegs_RegMask; - if (CC == CallingConv::CXX_FAST_TLS) - return SCS ? CSR_AArch64_CXX_TLS_Darwin_SCS_RegMask - : CSR_AArch64_CXX_TLS_Darwin_RegMask; + + // All the following calling conventions are handled differently on Darwin. + if (MF.getSubtarget<AArch64Subtarget>().isTargetDarwin()) { + if (SCS) + report_fatal_error("ShadowCallStack attribute not supported on Darwin."); + return getDarwinCallPreservedMask(MF, CC); + } + if (CC == CallingConv::AArch64_VectorCall) return SCS ? CSR_AArch64_AAVPCS_SCS_RegMask : CSR_AArch64_AAVPCS_RegMask; if (CC == CallingConv::AArch64_SVE_VectorCall) @@ -145,7 +209,7 @@ AArch64RegisterInfo::getCallPreservedMask(const MachineFunction &MF, const uint32_t *AArch64RegisterInfo::getTLSCallPreservedMask() const { if (TT.isOSDarwin()) - return CSR_AArch64_TLS_Darwin_RegMask; + return CSR_Darwin_AArch64_TLS_RegMask; assert(TT.isOSBinFormatELF() && "Invalid target"); return CSR_AArch64_TLS_ELF_RegMask; @@ -186,6 +250,8 @@ AArch64RegisterInfo::getThisReturnPreservedMask(const MachineFunction &MF, // In case that the calling convention does not use the same register for // both, the function should return NULL (does not currently apply) assert(CC != CallingConv::GHC && "should not be GHC calling convention."); + if (MF.getSubtarget<AArch64Subtarget>().isTargetDarwin()) + return CSR_Darwin_AArch64_AAPCS_ThisReturn_RegMask; return CSR_AArch64_AAPCS_ThisReturn_RegMask; } @@ -222,7 +288,7 @@ AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const { } bool AArch64RegisterInfo::isReservedReg(const MachineFunction &MF, - unsigned Reg) const { + MCRegister Reg) const { return getReservedRegs(MF)[Reg]; } @@ -240,11 +306,11 @@ void AArch64RegisterInfo::emitReservedArgRegCallError( } bool AArch64RegisterInfo::isAsmClobberable(const MachineFunction &MF, - unsigned PhysReg) const { + MCRegister PhysReg) const { return !isReservedReg(MF, PhysReg); } -bool AArch64RegisterInfo::isConstantPhysReg(unsigned PhysReg) const { +bool AArch64RegisterInfo::isConstantPhysReg(MCRegister PhysReg) const { return PhysReg == AArch64::WZR || PhysReg == AArch64::XZR; } @@ -390,12 +456,16 @@ bool AArch64RegisterInfo::needsFrameBaseReg(MachineInstr *MI, if (isFrameOffsetLegal(MI, AArch64::SP, Offset)) return false; + // If even offset 0 is illegal, we don't want a virtual base register. + if (!isFrameOffsetLegal(MI, AArch64::SP, 0)) + return false; + // The offset likely isn't legal; we want to allocate a virtual base register. return true; } bool AArch64RegisterInfo::isFrameOffsetLegal(const MachineInstr *MI, - unsigned BaseReg, + Register BaseReg, int64_t Offset) const { assert(MI && "Unable to get the legal offset for nil instruction."); StackOffset SaveOffset(Offset, MVT::i8); @@ -405,7 +475,7 @@ bool AArch64RegisterInfo::isFrameOffsetLegal(const MachineInstr *MI, /// Insert defining instruction(s) for BaseReg to be a pointer to FrameIdx /// at the beginning of the basic block. void AArch64RegisterInfo::materializeFrameBaseRegister(MachineBasicBlock *MBB, - unsigned BaseReg, + Register BaseReg, int FrameIdx, int64_t Offset) const { MachineBasicBlock::iterator Ins = MBB->begin(); @@ -426,7 +496,7 @@ void AArch64RegisterInfo::materializeFrameBaseRegister(MachineBasicBlock *MBB, .addImm(Shifter); } -void AArch64RegisterInfo::resolveFrameIndex(MachineInstr &MI, unsigned BaseReg, +void AArch64RegisterInfo::resolveFrameIndex(MachineInstr &MI, Register BaseReg, int64_t Offset) const { // ARM doesn't need the general 64-bit offsets StackOffset Off(Offset, MVT::i8); @@ -445,6 +515,27 @@ void AArch64RegisterInfo::resolveFrameIndex(MachineInstr &MI, unsigned BaseReg, (void)Done; } +// Create a scratch register for the frame index elimination in an instruction. +// This function has special handling of stack tagging loop pseudos, in which +// case it can also change the instruction opcode (but not the operands). +static Register +createScratchRegisterForInstruction(MachineInstr &MI, + const AArch64InstrInfo *TII) { + // ST*Gloop have a reserved scratch register in operand 1. Use it, and also + // replace the instruction with the writeback variant because it will now + // satisfy the operand constraints for it. + if (MI.getOpcode() == AArch64::STGloop) { + MI.setDesc(TII->get(AArch64::STGloop_wback)); + return MI.getOperand(1).getReg(); + } else if (MI.getOpcode() == AArch64::STZGloop) { + MI.setDesc(TII->get(AArch64::STZGloop_wback)); + return MI.getOperand(1).getReg(); + } else { + return MI.getMF()->getRegInfo().createVirtualRegister( + &AArch64::GPR64RegClass); + } +} + void AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS) const { @@ -461,7 +552,7 @@ void AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); bool Tagged = MI.getOperand(FIOperandNum).getTargetFlags() & AArch64II::MO_TAGGED; - unsigned FrameReg; + Register FrameReg; // Special handling of dbg_value, stackmap and patchpoint instructions. if (MI.isDebugValue() || MI.getOpcode() == TargetOpcode::STACKMAP || @@ -531,8 +622,7 @@ void AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, // If we get here, the immediate doesn't fit into the instruction. We folded // as much as possible above. Handle the rest, providing a register that is // SP+LargeImm. - Register ScratchReg = - MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass); + Register ScratchReg = createScratchRegisterForInstruction(MI, TII); emitFrameOffset(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg, Offset, TII); MI.getOperand(FIOperandNum).ChangeToRegister(ScratchReg, false, false, true); } @@ -572,6 +662,8 @@ unsigned AArch64RegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, return 32; case AArch64::FPR128_loRegClassID: + case AArch64::FPR64_loRegClassID: + case AArch64::FPR16_loRegClassID: return 16; } } |
