diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
commit | e6d1592492a3a379186bfb02bd0f4eda0669c0d5 (patch) | |
tree | 599ab169a01f1c86eda9adc774edaedde2f2db5b /lib/Target/AArch64/AArch64InstrInfo.cpp | |
parent | 1a56a5ead7a2e84bee8240f5f6b033b5f1707154 (diff) |
Notes
Diffstat (limited to 'lib/Target/AArch64/AArch64InstrInfo.cpp')
-rw-r--r-- | lib/Target/AArch64/AArch64InstrInfo.cpp | 472 |
1 files changed, 246 insertions, 226 deletions
diff --git a/lib/Target/AArch64/AArch64InstrInfo.cpp b/lib/Target/AArch64/AArch64InstrInfo.cpp index ada067888572..215e96a82d0e 100644 --- a/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -1,9 +1,8 @@ //===- AArch64InstrInfo.cpp - AArch64 Instruction Information -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -77,8 +76,11 @@ unsigned AArch64InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { const MachineFunction *MF = MBB.getParent(); const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo(); - if (MI.getOpcode() == AArch64::INLINEASM) - return getInlineAsmLength(MI.getOperand(0).getSymbolName(), *MAI); + { + auto Op = MI.getOpcode(); + if (Op == AArch64::INLINEASM || Op == AArch64::INLINEASM_BR) + return getInlineAsmLength(MI.getOperand(0).getSymbolName(), *MAI); + } // FIXME: We currently only handle pseudoinstructions that don't get expanded // before the assembly printer. @@ -928,9 +930,9 @@ bool AArch64InstrInfo::isCoalescableExtInstr(const MachineInstr &MI, } bool AArch64InstrInfo::areMemAccessesTriviallyDisjoint( - MachineInstr &MIa, MachineInstr &MIb, AliasAnalysis *AA) const { + const MachineInstr &MIa, const MachineInstr &MIb, AliasAnalysis *AA) const { const TargetRegisterInfo *TRI = &getRegisterInfo(); - MachineOperand *BaseOpA = nullptr, *BaseOpB = nullptr; + const MachineOperand *BaseOpA = nullptr, *BaseOpB = nullptr; int64_t OffsetA = 0, OffsetB = 0; unsigned WidthA = 0, WidthB = 0; @@ -1715,6 +1717,69 @@ bool AArch64InstrInfo::isUnscaledLdSt(unsigned Opc) { } } +Optional<unsigned> AArch64InstrInfo::getUnscaledLdSt(unsigned Opc) { + switch (Opc) { + default: return {}; + case AArch64::PRFMui: return AArch64::PRFUMi; + case AArch64::LDRXui: return AArch64::LDURXi; + case AArch64::LDRWui: return AArch64::LDURWi; + case AArch64::LDRBui: return AArch64::LDURBi; + case AArch64::LDRHui: return AArch64::LDURHi; + case AArch64::LDRSui: return AArch64::LDURSi; + case AArch64::LDRDui: return AArch64::LDURDi; + case AArch64::LDRQui: return AArch64::LDURQi; + case AArch64::LDRBBui: return AArch64::LDURBBi; + case AArch64::LDRHHui: return AArch64::LDURHHi; + case AArch64::LDRSBXui: return AArch64::LDURSBXi; + case AArch64::LDRSBWui: return AArch64::LDURSBWi; + case AArch64::LDRSHXui: return AArch64::LDURSHXi; + case AArch64::LDRSHWui: return AArch64::LDURSHWi; + case AArch64::LDRSWui: return AArch64::LDURSWi; + case AArch64::STRXui: return AArch64::STURXi; + case AArch64::STRWui: return AArch64::STURWi; + case AArch64::STRBui: return AArch64::STURBi; + case AArch64::STRHui: return AArch64::STURHi; + case AArch64::STRSui: return AArch64::STURSi; + case AArch64::STRDui: return AArch64::STURDi; + case AArch64::STRQui: return AArch64::STURQi; + case AArch64::STRBBui: return AArch64::STURBBi; + case AArch64::STRHHui: return AArch64::STURHHi; + } +} + +unsigned AArch64InstrInfo::getLoadStoreImmIdx(unsigned Opc) { + switch (Opc) { + default: + return 2; + case AArch64::LDPXi: + case AArch64::LDPDi: + case AArch64::STPXi: + case AArch64::STPDi: + case AArch64::LDNPXi: + case AArch64::LDNPDi: + case AArch64::STNPXi: + case AArch64::STNPDi: + case AArch64::LDPQi: + case AArch64::STPQi: + case AArch64::LDNPQi: + case AArch64::STNPQi: + case AArch64::LDPWi: + case AArch64::LDPSi: + case AArch64::STPWi: + case AArch64::STPSi: + case AArch64::LDNPWi: + case AArch64::LDNPSi: + case AArch64::STNPWi: + case AArch64::STNPSi: + case AArch64::LDG: + case AArch64::STGPi: + return 3; + case AArch64::ADDG: + case AArch64::STGOffset: + return 2; + } +} + bool AArch64InstrInfo::isPairableLdStInst(const MachineInstr &MI) { switch (MI.getOpcode()) { default: @@ -1837,7 +1902,7 @@ unsigned AArch64InstrInfo::convertToFlagSettingOpc(unsigned Opc, // Is this a candidate for ld/st merging or pairing? For example, we don't // touch volatiles or load/stores that have a hint to avoid pair formation. -bool AArch64InstrInfo::isCandidateToMergeOrPair(MachineInstr &MI) const { +bool AArch64InstrInfo::isCandidateToMergeOrPair(const MachineInstr &MI) const { // If this is a volatile load/store, don't mess with it. if (MI.hasOrderedMemoryRef()) return false; @@ -1879,8 +1944,8 @@ bool AArch64InstrInfo::isCandidateToMergeOrPair(MachineInstr &MI) const { return true; } -bool AArch64InstrInfo::getMemOperandWithOffset(MachineInstr &LdSt, - MachineOperand *&BaseOp, +bool AArch64InstrInfo::getMemOperandWithOffset(const MachineInstr &LdSt, + const MachineOperand *&BaseOp, int64_t &Offset, const TargetRegisterInfo *TRI) const { unsigned Width; @@ -1888,7 +1953,7 @@ bool AArch64InstrInfo::getMemOperandWithOffset(MachineInstr &LdSt, } bool AArch64InstrInfo::getMemOperandWithOffsetWidth( - MachineInstr &LdSt, MachineOperand *&BaseOp, int64_t &Offset, + const MachineInstr &LdSt, const MachineOperand *&BaseOp, int64_t &Offset, unsigned &Width, const TargetRegisterInfo *TRI) const { assert(LdSt.mayLoadOrStore() && "Expected a memory operation."); // Handle only loads/stores with base register followed by immediate offset. @@ -1944,7 +2009,7 @@ AArch64InstrInfo::getMemOpBaseRegImmOfsOffsetOperand(MachineInstr &LdSt) const { bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, unsigned &Scale, unsigned &Width, int64_t &MinOffset, - int64_t &MaxOffset) const { + int64_t &MaxOffset) { switch (Opcode) { // Not a memory operation or something we want to handle. default: @@ -1965,6 +2030,7 @@ bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, unsigned &Scale, MinOffset = -256; MaxOffset = 255; break; + case AArch64::PRFUMi: case AArch64::LDURXi: case AArch64::LDURDi: case AArch64::STURXi: @@ -2034,6 +2100,7 @@ bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, unsigned &Scale, MinOffset = -64; MaxOffset = 63; break; + case AArch64::PRFMui: case AArch64::LDRXui: case AArch64::LDRDui: case AArch64::STRXui: @@ -2066,6 +2133,8 @@ bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, unsigned &Scale, break; case AArch64::LDRHui: case AArch64::LDRHHui: + case AArch64::LDRSHWui: + case AArch64::LDRSHXui: case AArch64::STRHui: case AArch64::STRHHui: Scale = Width = 2; @@ -2074,12 +2143,40 @@ bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, unsigned &Scale, break; case AArch64::LDRBui: case AArch64::LDRBBui: + case AArch64::LDRSBWui: + case AArch64::LDRSBXui: case AArch64::STRBui: case AArch64::STRBBui: Scale = Width = 1; MinOffset = 0; MaxOffset = 4095; break; + case AArch64::ADDG: + case AArch64::TAGPstack: + Scale = 16; + Width = 0; + MinOffset = 0; + MaxOffset = 63; + break; + case AArch64::LDG: + case AArch64::STGOffset: + case AArch64::STZGOffset: + Scale = Width = 16; + MinOffset = -256; + MaxOffset = 255; + break; + case AArch64::ST2GOffset: + case AArch64::STZ2GOffset: + Scale = 16; + Width = 32; + MinOffset = -256; + MaxOffset = 255; + break; + case AArch64::STGPi: + Scale = Width = 16; + MinOffset = -64; + MaxOffset = 63; + break; } return true; @@ -2181,11 +2278,11 @@ static bool shouldClusterFI(const MachineFrameInfo &MFI, int FI1, /// Detect opportunities for ldp/stp formation. /// /// Only called for LdSt for which getMemOperandWithOffset returns true. -bool AArch64InstrInfo::shouldClusterMemOps(MachineOperand &BaseOp1, - MachineOperand &BaseOp2, +bool AArch64InstrInfo::shouldClusterMemOps(const MachineOperand &BaseOp1, + const MachineOperand &BaseOp2, unsigned NumLoads) const { - MachineInstr &FirstLdSt = *BaseOp1.getParent(); - MachineInstr &SecondLdSt = *BaseOp2.getParent(); + const MachineInstr &FirstLdSt = *BaseOp1.getParent(); + const MachineInstr &SecondLdSt = *BaseOp2.getParent(); if (BaseOp1.getType() != BaseOp2.getType()) return false; @@ -2292,6 +2389,31 @@ void AArch64InstrInfo::copyPhysRegTuple(MachineBasicBlock &MBB, } } +void AArch64InstrInfo::copyGPRRegTuple(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + DebugLoc DL, unsigned DestReg, + unsigned SrcReg, bool KillSrc, + unsigned Opcode, unsigned ZeroReg, + llvm::ArrayRef<unsigned> Indices) const { + const TargetRegisterInfo *TRI = &getRegisterInfo(); + unsigned NumRegs = Indices.size(); + +#ifndef NDEBUG + uint16_t DestEncoding = TRI->getEncodingValue(DestReg); + uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg); + assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 && + "GPR reg sequences should not be able to overlap"); +#endif + + for (unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) { + const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode)); + AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI); + MIB.addReg(ZeroReg); + AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI); + MIB.addImm(0); + } +} + void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, unsigned DestReg, @@ -2431,6 +2553,22 @@ void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB, return; } + if (AArch64::XSeqPairsClassRegClass.contains(DestReg) && + AArch64::XSeqPairsClassRegClass.contains(SrcReg)) { + static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64}; + copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRXrs, + AArch64::XZR, Indices); + return; + } + + if (AArch64::WSeqPairsClassRegClass.contains(DestReg) && + AArch64::WSeqPairsClassRegClass.contains(SrcReg)) { + static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32}; + copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRWrs, + AArch64::WZR, Indices); + return; + } + if (AArch64::FPR128RegClass.contains(DestReg) && AArch64::FPR128RegClass.contains(SrcReg)) { if (Subtarget.hasNEON()) { @@ -2839,7 +2977,7 @@ void llvm::emitFrameOffset(MachineBasicBlock &MBB, unsigned DestReg, unsigned SrcReg, int Offset, const TargetInstrInfo *TII, MachineInstr::MIFlag Flag, bool SetNZCV, - bool NeedsWinCFI) { + bool NeedsWinCFI, bool *HasWinCFI) { if (DestReg == SrcReg && Offset == 0) return; @@ -2884,10 +3022,13 @@ void llvm::emitFrameOffset(MachineBasicBlock &MBB, .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftSize)) .setMIFlag(Flag); - if (NeedsWinCFI && SrcReg == AArch64::SP && DestReg == AArch64::SP) - BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc)) - .addImm(ThisVal) - .setMIFlag(Flag); + if (NeedsWinCFI && SrcReg == AArch64::SP && DestReg == AArch64::SP) { + if (HasWinCFI) + *HasWinCFI = true; + BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc)) + .addImm(ThisVal) + .setMIFlag(Flag); + } SrcReg = DestReg; Offset -= ThisVal; @@ -2903,6 +3044,8 @@ void llvm::emitFrameOffset(MachineBasicBlock &MBB, if (NeedsWinCFI) { if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) || (SrcReg == AArch64::FP && DestReg == AArch64::SP)) { + if (HasWinCFI) + *HasWinCFI = true; if (Offset == 0) BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_SetFP)). setMIFlag(Flag); @@ -2910,6 +3053,8 @@ void llvm::emitFrameOffset(MachineBasicBlock &MBB, BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AddFP)). addImm(Offset).setMIFlag(Flag); } else if (DestReg == AArch64::SP) { + if (HasWinCFI) + *HasWinCFI = true; BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc)). addImm(Offset).setMIFlag(Flag); } @@ -2919,7 +3064,7 @@ void llvm::emitFrameOffset(MachineBasicBlock &MBB, MachineInstr *AArch64InstrInfo::foldMemoryOperandImpl( MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops, MachineBasicBlock::iterator InsertPt, int FrameIndex, - LiveIntervals *LIS) const { + LiveIntervals *LIS, VirtRegMap *VRM) const { // This is a bit of a hack. Consider this instruction: // // %0 = COPY %sp; GPR64all:%0 @@ -3102,11 +3247,6 @@ int llvm::isAArch64FrameOffsetLegal(const MachineInstr &MI, int &Offset, bool *OutUseUnscaledOp, unsigned *OutUnscaledOp, int *EmittableOffset) { - int Scale = 1; - bool IsSigned = false; - // The ImmIdx should be changed case by case if it is not 2. - unsigned ImmIdx = 2; - unsigned UnscaledOp = 0; // Set output values in case of early exit. if (EmittableOffset) *EmittableOffset = 0; @@ -3114,10 +3254,12 @@ int llvm::isAArch64FrameOffsetLegal(const MachineInstr &MI, int &Offset, *OutUseUnscaledOp = false; if (OutUnscaledOp) *OutUnscaledOp = 0; + + // Exit early for structured vector spills/fills as they can't take an + // immediate offset. switch (MI.getOpcode()) { default: - llvm_unreachable("unhandled opcode in rewriteAArch64FrameIndex"); - // Vector spills/fills can't take an immediate offset. + break; case AArch64::LD1Twov2d: case AArch64::LD1Threev2d: case AArch64::LD1Fourv2d: @@ -3130,208 +3272,53 @@ int llvm::isAArch64FrameOffsetLegal(const MachineInstr &MI, int &Offset, case AArch64::ST1Twov1d: case AArch64::ST1Threev1d: case AArch64::ST1Fourv1d: + case AArch64::IRG: + case AArch64::IRGstack: return AArch64FrameOffsetCannotUpdate; - case AArch64::PRFMui: - Scale = 8; - UnscaledOp = AArch64::PRFUMi; - break; - case AArch64::LDRXui: - Scale = 8; - UnscaledOp = AArch64::LDURXi; - break; - case AArch64::LDRWui: - Scale = 4; - UnscaledOp = AArch64::LDURWi; - break; - case AArch64::LDRBui: - Scale = 1; - UnscaledOp = AArch64::LDURBi; - break; - case AArch64::LDRHui: - Scale = 2; - UnscaledOp = AArch64::LDURHi; - break; - case AArch64::LDRSui: - Scale = 4; - UnscaledOp = AArch64::LDURSi; - break; - case AArch64::LDRDui: - Scale = 8; - UnscaledOp = AArch64::LDURDi; - break; - case AArch64::LDRQui: - Scale = 16; - UnscaledOp = AArch64::LDURQi; - break; - case AArch64::LDRBBui: - Scale = 1; - UnscaledOp = AArch64::LDURBBi; - break; - case AArch64::LDRHHui: - Scale = 2; - UnscaledOp = AArch64::LDURHHi; - break; - case AArch64::LDRSBXui: - Scale = 1; - UnscaledOp = AArch64::LDURSBXi; - break; - case AArch64::LDRSBWui: - Scale = 1; - UnscaledOp = AArch64::LDURSBWi; - break; - case AArch64::LDRSHXui: - Scale = 2; - UnscaledOp = AArch64::LDURSHXi; - break; - case AArch64::LDRSHWui: - Scale = 2; - UnscaledOp = AArch64::LDURSHWi; - break; - case AArch64::LDRSWui: - Scale = 4; - UnscaledOp = AArch64::LDURSWi; - break; - - case AArch64::STRXui: - Scale = 8; - UnscaledOp = AArch64::STURXi; - break; - case AArch64::STRWui: - Scale = 4; - UnscaledOp = AArch64::STURWi; - break; - case AArch64::STRBui: - Scale = 1; - UnscaledOp = AArch64::STURBi; - break; - case AArch64::STRHui: - Scale = 2; - UnscaledOp = AArch64::STURHi; - break; - case AArch64::STRSui: - Scale = 4; - UnscaledOp = AArch64::STURSi; - break; - case AArch64::STRDui: - Scale = 8; - UnscaledOp = AArch64::STURDi; - break; - case AArch64::STRQui: - Scale = 16; - UnscaledOp = AArch64::STURQi; - break; - case AArch64::STRBBui: - Scale = 1; - UnscaledOp = AArch64::STURBBi; - break; - case AArch64::STRHHui: - Scale = 2; - UnscaledOp = AArch64::STURHHi; - break; - - case AArch64::LDPXi: - case AArch64::LDPDi: - case AArch64::STPXi: - case AArch64::STPDi: - case AArch64::LDNPXi: - case AArch64::LDNPDi: - case AArch64::STNPXi: - case AArch64::STNPDi: - ImmIdx = 3; - IsSigned = true; - Scale = 8; - break; - case AArch64::LDPQi: - case AArch64::STPQi: - case AArch64::LDNPQi: - case AArch64::STNPQi: - ImmIdx = 3; - IsSigned = true; - Scale = 16; - break; - case AArch64::LDPWi: - case AArch64::LDPSi: - case AArch64::STPWi: - case AArch64::STPSi: - case AArch64::LDNPWi: - case AArch64::LDNPSi: - case AArch64::STNPWi: - case AArch64::STNPSi: - ImmIdx = 3; - IsSigned = true; - Scale = 4; - break; - - case AArch64::LDURXi: - case AArch64::LDURWi: - case AArch64::LDURBi: - case AArch64::LDURHi: - case AArch64::LDURSi: - case AArch64::LDURDi: - case AArch64::LDURQi: - case AArch64::LDURHHi: - case AArch64::LDURBBi: - case AArch64::LDURSBXi: - case AArch64::LDURSBWi: - case AArch64::LDURSHXi: - case AArch64::LDURSHWi: - case AArch64::LDURSWi: - case AArch64::STURXi: - case AArch64::STURWi: - case AArch64::STURBi: - case AArch64::STURHi: - case AArch64::STURSi: - case AArch64::STURDi: - case AArch64::STURQi: - case AArch64::STURBBi: - case AArch64::STURHHi: - Scale = 1; - break; } - Offset += MI.getOperand(ImmIdx).getImm() * Scale; + // Get the min/max offset and the scale. + unsigned Scale, Width; + int64_t MinOff, MaxOff; + if (!AArch64InstrInfo::getMemOpInfo(MI.getOpcode(), Scale, Width, MinOff, + MaxOff)) + llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal"); + + // Construct the complete offset. + const MachineOperand &ImmOpnd = + MI.getOperand(AArch64InstrInfo::getLoadStoreImmIdx(MI.getOpcode())); + Offset += ImmOpnd.getImm() * Scale; - bool useUnscaledOp = false; // If the offset doesn't match the scale, we rewrite the instruction to // use the unscaled instruction instead. Likewise, if we have a negative - // offset (and have an unscaled op to use). - if ((Offset & (Scale - 1)) != 0 || (Offset < 0 && UnscaledOp != 0)) - useUnscaledOp = true; - - // Use an unscaled addressing mode if the instruction has a negative offset - // (or if the instruction is already using an unscaled addressing mode). - unsigned MaskBits; - if (IsSigned) { - // ldp/stp instructions. - MaskBits = 7; - Offset /= Scale; - } else if (UnscaledOp == 0 || useUnscaledOp) { - MaskBits = 9; - IsSigned = true; - Scale = 1; - } else { - MaskBits = 12; - IsSigned = false; - Offset /= Scale; + // offset and there is an unscaled op to use. + Optional<unsigned> UnscaledOp = + AArch64InstrInfo::getUnscaledLdSt(MI.getOpcode()); + bool useUnscaledOp = UnscaledOp && (Offset % Scale || Offset < 0); + if (useUnscaledOp && + !AArch64InstrInfo::getMemOpInfo(*UnscaledOp, Scale, Width, MinOff, MaxOff)) + llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal"); + + int64_t Remainder = Offset % Scale; + assert(!(Remainder && useUnscaledOp) && + "Cannot have remainder when using unscaled op"); + + assert(MinOff < MaxOff && "Unexpected Min/Max offsets"); + int NewOffset = Offset / Scale; + if (MinOff <= NewOffset && NewOffset <= MaxOff) + Offset = Remainder; + else { + NewOffset = NewOffset < 0 ? MinOff : MaxOff; + Offset = Offset - NewOffset * Scale + Remainder; } - // Attempt to fold address computation. - int MaxOff = (1 << (MaskBits - IsSigned)) - 1; - int MinOff = (IsSigned ? (-MaxOff - 1) : 0); - if (Offset >= MinOff && Offset <= MaxOff) { - if (EmittableOffset) - *EmittableOffset = Offset; - Offset = 0; - } else { - int NewOff = Offset < 0 ? MinOff : MaxOff; - if (EmittableOffset) - *EmittableOffset = NewOff; - Offset = (Offset - NewOff) * Scale; - } + if (EmittableOffset) + *EmittableOffset = NewOffset; if (OutUseUnscaledOp) *OutUseUnscaledOp = useUnscaledOp; - if (OutUnscaledOp) - *OutUnscaledOp = UnscaledOp; + if (OutUnscaledOp && UnscaledOp) + *OutUnscaledOp = *UnscaledOp; + return AArch64FrameOffsetCanUpdate | (Offset == 0 ? AArch64FrameOffsetIsLegal : 0); } @@ -4974,8 +4961,8 @@ AArch64InstrInfo::getOutliningCandidateInfo( // At this point, we have a stack instruction that we might need to // fix up. We'll handle it if it's a load or store. if (MI.mayLoadOrStore()) { - MachineOperand *Base; // Filled with the base operand of MI. - int64_t Offset; // Filled with the offset of MI. + const MachineOperand *Base; // Filled with the base operand of MI. + int64_t Offset; // Filled with the offset of MI. // Does it allow us to offset the base operand and is the base the // register SP? @@ -5331,12 +5318,20 @@ AArch64InstrInfo::getOutliningType(MachineBasicBlock::iterator &MIT, MI.modifiesRegister(AArch64::W30, &getRegisterInfo())) return outliner::InstrType::Illegal; + // Don't outline BTI instructions, because that will prevent the outlining + // site from being indirectly callable. + if (MI.getOpcode() == AArch64::HINT) { + int64_t Imm = MI.getOperand(0).getImm(); + if (Imm == 32 || Imm == 34 || Imm == 36 || Imm == 38) + return outliner::InstrType::Illegal; + } + return outliner::InstrType::Legal; } void AArch64InstrInfo::fixupPostOutline(MachineBasicBlock &MBB) const { for (MachineInstr &MI : MBB) { - MachineOperand *Base; + const MachineOperand *Base; unsigned Width; int64_t Offset; @@ -5534,7 +5529,32 @@ MachineBasicBlock::iterator AArch64InstrInfo::insertOutlinedCall( bool AArch64InstrInfo::shouldOutlineFromFunctionByDefault( MachineFunction &MF) const { - return MF.getFunction().optForMinSize(); + return MF.getFunction().hasMinSize(); +} + +bool AArch64InstrInfo::isCopyInstrImpl( + const MachineInstr &MI, const MachineOperand *&Source, + const MachineOperand *&Destination) const { + + // AArch64::ORRWrs and AArch64::ORRXrs with WZR/XZR reg + // and zero immediate operands used as an alias for mov instruction. + if (MI.getOpcode() == AArch64::ORRWrs && + MI.getOperand(1).getReg() == AArch64::WZR && + MI.getOperand(3).getImm() == 0x0) { + Destination = &MI.getOperand(0); + Source = &MI.getOperand(2); + return true; + } + + if (MI.getOpcode() == AArch64::ORRXrs && + MI.getOperand(1).getReg() == AArch64::XZR && + MI.getOperand(3).getImm() == 0x0) { + Destination = &MI.getOperand(0); + Source = &MI.getOperand(2); + return true; + } + + return false; } #define GET_INSTRINFO_HELPERS |