mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	Merge r242733, r242734, r242735 and r242742
(r242742 is the interesting patch here, but I picked the others too to get a clean merge since there's been some back-and-forth on this file.) ------------------------------------------------------------------------ r242733 | matze | 2015-07-20 16:17:14 -0700 (Mon, 20 Jul 2015) | 3 lines Revert "ARM: Use SpecificBumpPtrAllocator to fix leak introduced in r241920" This reverts commit r241951. It caused http://llvm.org/PR24190 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r242734 | matze | 2015-07-20 16:17:16 -0700 (Mon, 20 Jul 2015) | 3 lines Revert "ARMLoadStoreOpt: Merge subs/adds into LDRD/STRD; Factor out common code" This reverts commit r241928. This caused http://llvm.org/PR24190 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r242735 | matze | 2015-07-20 16:17:20 -0700 (Mon, 20 Jul 2015) | 3 lines Revert "ARMLoadStoreOptimizer: Create LDRD/STRD on thumb2" This reverts commit r241926. This caused http://llvm.org/PR24190 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r242742 | matze | 2015-07-20 17:18:59 -0700 (Mon, 20 Jul 2015) | 7 lines ARMLoadStoreOptimizer: Create LDRD/STRD on thumb2 Re-apply r241926 with an additional check that r13 and r15 are not used for LDRD/STRD. See http://llvm.org/PR24190. This also already includes the fix from r241951. Differential Revision: http://reviews.llvm.org/D10623 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_37@242907 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		| @@ -118,7 +118,6 @@ namespace { | |||||||
|     }; |     }; | ||||||
|     SpecificBumpPtrAllocator<MergeCandidate> Allocator; |     SpecificBumpPtrAllocator<MergeCandidate> Allocator; | ||||||
|     SmallVector<const MergeCandidate*,4> Candidates; |     SmallVector<const MergeCandidate*,4> Candidates; | ||||||
|     SmallVector<MachineInstr*,4> MergeBaseCandidates; |  | ||||||
|  |  | ||||||
|     void moveLiveRegsBefore(const MachineBasicBlock &MBB, |     void moveLiveRegsBefore(const MachineBasicBlock &MBB, | ||||||
|                             MachineBasicBlock::const_iterator Before); |                             MachineBasicBlock::const_iterator Before); | ||||||
| @@ -141,7 +140,6 @@ namespace { | |||||||
|                              MachineBasicBlock::iterator &MBBI); |                              MachineBasicBlock::iterator &MBBI); | ||||||
|     bool MergeBaseUpdateLoadStore(MachineInstr *MI); |     bool MergeBaseUpdateLoadStore(MachineInstr *MI); | ||||||
|     bool MergeBaseUpdateLSMultiple(MachineInstr *MI); |     bool MergeBaseUpdateLSMultiple(MachineInstr *MI); | ||||||
|     bool MergeBaseUpdateLSDouble(MachineInstr &MI) const; |  | ||||||
|     bool LoadStoreMultipleOpti(MachineBasicBlock &MBB); |     bool LoadStoreMultipleOpti(MachineBasicBlock &MBB); | ||||||
|     bool MergeReturnIntoLDM(MachineBasicBlock &MBB); |     bool MergeReturnIntoLDM(MachineBasicBlock &MBB); | ||||||
|   }; |   }; | ||||||
| @@ -933,6 +931,11 @@ void ARMLoadStoreOpt::FormCandidates(const MemOpQueue &MemOps) { | |||||||
|     if (STI->isSwift() && !isNotVFP && (PRegNum % 2) == 1) |     if (STI->isSwift() && !isNotVFP && (PRegNum % 2) == 1) | ||||||
|       CanMergeToLSMulti = false; |       CanMergeToLSMulti = false; | ||||||
|  |  | ||||||
|  |     // LDRD/STRD do not allow SP/PC. LDM/STM do not support it or have it | ||||||
|  |     // deprecated; LDM to PC is fine but cannot happen here. | ||||||
|  |     if (PReg == ARM::SP || PReg == ARM::PC) | ||||||
|  |       CanMergeToLSMulti = CanMergeToLSDouble = false; | ||||||
|  |  | ||||||
|     // Merge following instructions where possible. |     // Merge following instructions where possible. | ||||||
|     for (unsigned I = SIndex+1; I < EIndex; ++I, ++Count) { |     for (unsigned I = SIndex+1; I < EIndex; ++I, ++Count) { | ||||||
|       int NewOffset = MemOps[I].Offset; |       int NewOffset = MemOps[I].Offset; | ||||||
| @@ -940,16 +943,15 @@ void ARMLoadStoreOpt::FormCandidates(const MemOpQueue &MemOps) { | |||||||
|         break; |         break; | ||||||
|       const MachineOperand &MO = getLoadStoreRegOp(*MemOps[I].MI); |       const MachineOperand &MO = getLoadStoreRegOp(*MemOps[I].MI); | ||||||
|       unsigned Reg = MO.getReg(); |       unsigned Reg = MO.getReg(); | ||||||
|       unsigned RegNum = MO.isUndef() ? UINT_MAX : TRI->getEncodingValue(Reg); |       if (Reg == ARM::SP || Reg == ARM::PC) | ||||||
|  |         break; | ||||||
|  |  | ||||||
|       // See if the current load/store may be part of a multi load/store. |       // See if the current load/store may be part of a multi load/store. | ||||||
|  |       unsigned RegNum = MO.isUndef() ? UINT_MAX : TRI->getEncodingValue(Reg); | ||||||
|       bool PartOfLSMulti = CanMergeToLSMulti; |       bool PartOfLSMulti = CanMergeToLSMulti; | ||||||
|       if (PartOfLSMulti) { |       if (PartOfLSMulti) { | ||||||
|         // Cannot load from SP |  | ||||||
|         if (Reg == ARM::SP) |  | ||||||
|           PartOfLSMulti = false; |  | ||||||
|         // Register numbers must be in ascending order. |         // Register numbers must be in ascending order. | ||||||
|         else if (RegNum <= PRegNum) |         if (RegNum <= PRegNum) | ||||||
|           PartOfLSMulti = false; |           PartOfLSMulti = false; | ||||||
|         // For VFP / NEON load/store multiples, the registers must be |         // For VFP / NEON load/store multiples, the registers must be | ||||||
|         // consecutive and within the limit on the number of registers per |         // consecutive and within the limit on the number of registers per | ||||||
| @@ -993,6 +995,76 @@ void ARMLoadStoreOpt::FormCandidates(const MemOpQueue &MemOps) { | |||||||
|   } while (SIndex < EIndex); |   } while (SIndex < EIndex); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static bool isMatchingDecrement(MachineInstr *MI, unsigned Base, | ||||||
|  |                                 unsigned Bytes, unsigned Limit, | ||||||
|  |                                 ARMCC::CondCodes Pred, unsigned PredReg) { | ||||||
|  |   unsigned MyPredReg = 0; | ||||||
|  |   if (!MI) | ||||||
|  |     return false; | ||||||
|  |  | ||||||
|  |   bool CheckCPSRDef = false; | ||||||
|  |   switch (MI->getOpcode()) { | ||||||
|  |   default: return false; | ||||||
|  |   case ARM::tSUBi8: | ||||||
|  |   case ARM::t2SUBri: | ||||||
|  |   case ARM::SUBri: | ||||||
|  |     CheckCPSRDef = true; | ||||||
|  |     break; | ||||||
|  |   case ARM::tSUBspi: | ||||||
|  |     break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Make sure the offset fits in 8 bits. | ||||||
|  |   if (Bytes == 0 || (Limit && Bytes >= Limit)) | ||||||
|  |     return false; | ||||||
|  |  | ||||||
|  |   unsigned Scale = (MI->getOpcode() == ARM::tSUBspi || | ||||||
|  |                     MI->getOpcode() == ARM::tSUBi8) ? 4 : 1; // FIXME | ||||||
|  |   if (!(MI->getOperand(0).getReg() == Base && | ||||||
|  |         MI->getOperand(1).getReg() == Base && | ||||||
|  |         (MI->getOperand(2).getImm() * Scale) == Bytes && | ||||||
|  |         getInstrPredicate(MI, MyPredReg) == Pred && | ||||||
|  |         MyPredReg == PredReg)) | ||||||
|  |     return false; | ||||||
|  |  | ||||||
|  |   return CheckCPSRDef ? !definesCPSR(MI) : true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static bool isMatchingIncrement(MachineInstr *MI, unsigned Base, | ||||||
|  |                                 unsigned Bytes, unsigned Limit, | ||||||
|  |                                 ARMCC::CondCodes Pred, unsigned PredReg) { | ||||||
|  |   unsigned MyPredReg = 0; | ||||||
|  |   if (!MI) | ||||||
|  |     return false; | ||||||
|  |  | ||||||
|  |   bool CheckCPSRDef = false; | ||||||
|  |   switch (MI->getOpcode()) { | ||||||
|  |   default: return false; | ||||||
|  |   case ARM::tADDi8: | ||||||
|  |   case ARM::t2ADDri: | ||||||
|  |   case ARM::ADDri: | ||||||
|  |     CheckCPSRDef = true; | ||||||
|  |     break; | ||||||
|  |   case ARM::tADDspi: | ||||||
|  |     break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (Bytes == 0 || (Limit && Bytes >= Limit)) | ||||||
|  |     // Make sure the offset fits in 8 bits. | ||||||
|  |     return false; | ||||||
|  |  | ||||||
|  |   unsigned Scale = (MI->getOpcode() == ARM::tADDspi || | ||||||
|  |                     MI->getOpcode() == ARM::tADDi8) ? 4 : 1; // FIXME | ||||||
|  |   if (!(MI->getOperand(0).getReg() == Base && | ||||||
|  |         MI->getOperand(1).getReg() == Base && | ||||||
|  |         (MI->getOperand(2).getImm() * Scale) == Bytes && | ||||||
|  |         getInstrPredicate(MI, MyPredReg) == Pred && | ||||||
|  |         MyPredReg == PredReg)) | ||||||
|  |     return false; | ||||||
|  |  | ||||||
|  |   return CheckCPSRDef ? !definesCPSR(MI) : true; | ||||||
|  | } | ||||||
|  |  | ||||||
| static unsigned getUpdatingLSMultipleOpcode(unsigned Opc, | static unsigned getUpdatingLSMultipleOpcode(unsigned Opc, | ||||||
|                                             ARM_AM::AMSubMode Mode) { |                                             ARM_AM::AMSubMode Mode) { | ||||||
|   switch (Opc) { |   switch (Opc) { | ||||||
| @@ -1060,75 +1132,6 @@ static unsigned getUpdatingLSMultipleOpcode(unsigned Opc, | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Check if the given instruction increments or decrements a register and |  | ||||||
| /// return the amount it is incremented/decremented. Returns 0 if the CPSR flags |  | ||||||
| /// generated by the instruction are possibly read as well. |  | ||||||
| static int isIncrementOrDecrement(const MachineInstr &MI, unsigned Reg, |  | ||||||
|                                   ARMCC::CondCodes Pred, unsigned PredReg) { |  | ||||||
|   bool CheckCPSRDef; |  | ||||||
|   int Scale; |  | ||||||
|   switch (MI.getOpcode()) { |  | ||||||
|   case ARM::tADDi8:  Scale =  4; CheckCPSRDef = true; break; |  | ||||||
|   case ARM::tSUBi8:  Scale = -4; CheckCPSRDef = true; break; |  | ||||||
|   case ARM::t2SUBri: |  | ||||||
|   case ARM::SUBri:   Scale = -1; CheckCPSRDef = true; break; |  | ||||||
|   case ARM::t2ADDri: |  | ||||||
|   case ARM::ADDri:   Scale =  1; CheckCPSRDef = true; break; |  | ||||||
|   case ARM::tADDspi: Scale =  4; CheckCPSRDef = false; break; |  | ||||||
|   case ARM::tSUBspi: Scale = -4; CheckCPSRDef = false; break; |  | ||||||
|   default: return 0; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   unsigned MIPredReg; |  | ||||||
|   if (MI.getOperand(0).getReg() != Reg || |  | ||||||
|       MI.getOperand(1).getReg() != Reg || |  | ||||||
|       getInstrPredicate(&MI, MIPredReg) != Pred || |  | ||||||
|       MIPredReg != PredReg) |  | ||||||
|     return 0; |  | ||||||
|  |  | ||||||
|   if (CheckCPSRDef && definesCPSR(&MI)) |  | ||||||
|     return 0; |  | ||||||
|   return MI.getOperand(2).getImm() * Scale; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Searches for an increment or decrement of \p Reg before \p MBBI. |  | ||||||
| static MachineBasicBlock::iterator |  | ||||||
| findIncDecBefore(MachineBasicBlock::iterator MBBI, unsigned Reg, |  | ||||||
|                  ARMCC::CondCodes Pred, unsigned PredReg, int &Offset) { |  | ||||||
|   Offset = 0; |  | ||||||
|   MachineBasicBlock &MBB = *MBBI->getParent(); |  | ||||||
|   MachineBasicBlock::iterator BeginMBBI = MBB.begin(); |  | ||||||
|   MachineBasicBlock::iterator EndMBBI = MBB.end(); |  | ||||||
|   if (MBBI == BeginMBBI) |  | ||||||
|     return EndMBBI; |  | ||||||
|  |  | ||||||
|   // Skip debug values. |  | ||||||
|   MachineBasicBlock::iterator PrevMBBI = std::prev(MBBI); |  | ||||||
|   while (PrevMBBI->isDebugValue() && PrevMBBI != BeginMBBI) |  | ||||||
|     --PrevMBBI; |  | ||||||
|  |  | ||||||
|   Offset = isIncrementOrDecrement(*PrevMBBI, Reg, Pred, PredReg); |  | ||||||
|   return Offset == 0 ? EndMBBI : PrevMBBI; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Searches for a increment or decrement of \p Reg after \p MBBI. |  | ||||||
| static MachineBasicBlock::iterator |  | ||||||
| findIncDecAfter(MachineBasicBlock::iterator MBBI, unsigned Reg, |  | ||||||
|                 ARMCC::CondCodes Pred, unsigned PredReg, int &Offset) { |  | ||||||
|   Offset = 0; |  | ||||||
|   MachineBasicBlock &MBB = *MBBI->getParent(); |  | ||||||
|   MachineBasicBlock::iterator EndMBBI = MBB.end(); |  | ||||||
|   MachineBasicBlock::iterator NextMBBI = std::next(MBBI); |  | ||||||
|   // Skip debug values. |  | ||||||
|   while (NextMBBI != EndMBBI && NextMBBI->isDebugValue()) |  | ||||||
|     ++NextMBBI; |  | ||||||
|   if (NextMBBI == EndMBBI) |  | ||||||
|     return EndMBBI; |  | ||||||
|  |  | ||||||
|   Offset = isIncrementOrDecrement(*NextMBBI, Reg, Pred, PredReg); |  | ||||||
|   return Offset == 0 ? EndMBBI : NextMBBI; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Fold proceeding/trailing inc/dec of base register into the | /// Fold proceeding/trailing inc/dec of base register into the | ||||||
| /// LDM/STM/VLDM{D|S}/VSTM{D|S} op when possible: | /// LDM/STM/VLDM{D|S}/VSTM{D|S} op when possible: | ||||||
| /// | /// | ||||||
| @@ -1148,6 +1151,7 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineInstr *MI) { | |||||||
|   const MachineOperand &BaseOP = MI->getOperand(0); |   const MachineOperand &BaseOP = MI->getOperand(0); | ||||||
|   unsigned Base = BaseOP.getReg(); |   unsigned Base = BaseOP.getReg(); | ||||||
|   bool BaseKill = BaseOP.isKill(); |   bool BaseKill = BaseOP.isKill(); | ||||||
|  |   unsigned Bytes = getLSMultipleTransferSize(MI); | ||||||
|   unsigned PredReg = 0; |   unsigned PredReg = 0; | ||||||
|   ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg); |   ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg); | ||||||
|   unsigned Opcode = MI->getOpcode(); |   unsigned Opcode = MI->getOpcode(); | ||||||
| @@ -1159,24 +1163,49 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineInstr *MI) { | |||||||
|     if (MI->getOperand(i).getReg() == Base) |     if (MI->getOperand(i).getReg() == Base) | ||||||
|       return false; |       return false; | ||||||
|  |  | ||||||
|   int Bytes = getLSMultipleTransferSize(MI); |   bool DoMerge = false; | ||||||
|   MachineBasicBlock &MBB = *MI->getParent(); |  | ||||||
|   MachineBasicBlock::iterator MBBI(MI); |  | ||||||
|   int Offset; |  | ||||||
|   MachineBasicBlock::iterator MergeInstr |  | ||||||
|     = findIncDecBefore(MBBI, Base, Pred, PredReg, Offset); |  | ||||||
|   ARM_AM::AMSubMode Mode = getLoadStoreMultipleSubMode(Opcode); |   ARM_AM::AMSubMode Mode = getLoadStoreMultipleSubMode(Opcode); | ||||||
|   if (Mode == ARM_AM::ia && Offset == -Bytes) { |  | ||||||
|  |   // Try merging with the previous instruction. | ||||||
|  |   MachineBasicBlock &MBB = *MI->getParent(); | ||||||
|  |   MachineBasicBlock::iterator BeginMBBI = MBB.begin(); | ||||||
|  |   MachineBasicBlock::iterator MBBI(MI); | ||||||
|  |   if (MBBI != BeginMBBI) { | ||||||
|  |     MachineBasicBlock::iterator PrevMBBI = std::prev(MBBI); | ||||||
|  |     while (PrevMBBI != BeginMBBI && PrevMBBI->isDebugValue()) | ||||||
|  |       --PrevMBBI; | ||||||
|  |     if (Mode == ARM_AM::ia && | ||||||
|  |         isMatchingDecrement(PrevMBBI, Base, Bytes, 0, Pred, PredReg)) { | ||||||
|       Mode = ARM_AM::db; |       Mode = ARM_AM::db; | ||||||
|   } else if (Mode == ARM_AM::ib && Offset == -Bytes) { |       DoMerge = true; | ||||||
|  |     } else if (Mode == ARM_AM::ib && | ||||||
|  |                isMatchingDecrement(PrevMBBI, Base, Bytes, 0, Pred, PredReg)) { | ||||||
|       Mode = ARM_AM::da; |       Mode = ARM_AM::da; | ||||||
|   } else { |       DoMerge = true; | ||||||
|     MergeInstr = findIncDecAfter(MBBI, Base, Pred, PredReg, Offset); |  | ||||||
|     if (((Mode != ARM_AM::ia && Mode != ARM_AM::ib) || Offset != Bytes) && |  | ||||||
|         ((Mode != ARM_AM::da && Mode != ARM_AM::db) || Offset != -Bytes)) |  | ||||||
|       return false; |  | ||||||
|     } |     } | ||||||
|   MBB.erase(MergeInstr); |     if (DoMerge) | ||||||
|  |       MBB.erase(PrevMBBI); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Try merging with the next instruction. | ||||||
|  |   MachineBasicBlock::iterator EndMBBI = MBB.end(); | ||||||
|  |   if (!DoMerge && MBBI != EndMBBI) { | ||||||
|  |     MachineBasicBlock::iterator NextMBBI = std::next(MBBI); | ||||||
|  |     while (NextMBBI != EndMBBI && NextMBBI->isDebugValue()) | ||||||
|  |       ++NextMBBI; | ||||||
|  |     if ((Mode == ARM_AM::ia || Mode == ARM_AM::ib) && | ||||||
|  |         isMatchingIncrement(NextMBBI, Base, Bytes, 0, Pred, PredReg)) { | ||||||
|  |       DoMerge = true; | ||||||
|  |     } else if ((Mode == ARM_AM::da || Mode == ARM_AM::db) && | ||||||
|  |                isMatchingDecrement(NextMBBI, Base, Bytes, 0, Pred, PredReg)) { | ||||||
|  |       DoMerge = true; | ||||||
|  |     } | ||||||
|  |     if (DoMerge) | ||||||
|  |       MBB.erase(NextMBBI); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (!DoMerge) | ||||||
|  |     return false; | ||||||
|  |  | ||||||
|   unsigned NewOpc = getUpdatingLSMultipleOpcode(Opcode, Mode); |   unsigned NewOpc = getUpdatingLSMultipleOpcode(Opcode, Mode); | ||||||
|   MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc)) |   MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc)) | ||||||
| @@ -1254,6 +1283,7 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) { | |||||||
|  |  | ||||||
|   unsigned Base = getLoadStoreBaseOp(*MI).getReg(); |   unsigned Base = getLoadStoreBaseOp(*MI).getReg(); | ||||||
|   bool BaseKill = getLoadStoreBaseOp(*MI).isKill(); |   bool BaseKill = getLoadStoreBaseOp(*MI).isKill(); | ||||||
|  |   unsigned Bytes = getLSMultipleTransferSize(MI); | ||||||
|   unsigned Opcode = MI->getOpcode(); |   unsigned Opcode = MI->getOpcode(); | ||||||
|   DebugLoc DL = MI->getDebugLoc(); |   DebugLoc DL = MI->getDebugLoc(); | ||||||
|   bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS || |   bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS || | ||||||
| @@ -1265,6 +1295,7 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) { | |||||||
|   if (isAM5 && ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0) |   if (isAM5 && ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0) | ||||||
|     return false; |     return false; | ||||||
|  |  | ||||||
|  |   bool isLd = isLoadSingle(Opcode); | ||||||
|   // Can't do the merge if the destination register is the same as the would-be |   // Can't do the merge if the destination register is the same as the would-be | ||||||
|   // writeback register. |   // writeback register. | ||||||
|   if (MI->getOperand(0).getReg() == Base) |   if (MI->getOperand(0).getReg() == Base) | ||||||
| @@ -1272,31 +1303,55 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) { | |||||||
|  |  | ||||||
|   unsigned PredReg = 0; |   unsigned PredReg = 0; | ||||||
|   ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg); |   ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg); | ||||||
|   int Bytes = getLSMultipleTransferSize(MI); |   bool DoMerge = false; | ||||||
|  |   ARM_AM::AddrOpc AddSub = ARM_AM::add; | ||||||
|  |   unsigned NewOpc = 0; | ||||||
|  |   // AM2 - 12 bits, thumb2 - 8 bits. | ||||||
|  |   unsigned Limit = isAM5 ? 0 : (isAM2 ? 0x1000 : 0x100); | ||||||
|  |  | ||||||
|  |   // Try merging with the previous instruction. | ||||||
|   MachineBasicBlock &MBB = *MI->getParent(); |   MachineBasicBlock &MBB = *MI->getParent(); | ||||||
|  |   MachineBasicBlock::iterator BeginMBBI = MBB.begin(); | ||||||
|   MachineBasicBlock::iterator MBBI(MI); |   MachineBasicBlock::iterator MBBI(MI); | ||||||
|   int Offset; |   if (MBBI != BeginMBBI) { | ||||||
|   MachineBasicBlock::iterator MergeInstr |     MachineBasicBlock::iterator PrevMBBI = std::prev(MBBI); | ||||||
|     = findIncDecBefore(MBBI, Base, Pred, PredReg, Offset); |     while (PrevMBBI != BeginMBBI && PrevMBBI->isDebugValue()) | ||||||
|   unsigned NewOpc; |       --PrevMBBI; | ||||||
|   if (!isAM5 && Offset == Bytes) { |     if (isMatchingDecrement(PrevMBBI, Base, Bytes, Limit, Pred, PredReg)) { | ||||||
|     NewOpc = getPreIndexedLoadStoreOpcode(Opcode, ARM_AM::add); |       DoMerge = true; | ||||||
|   } else if (Offset == -Bytes) { |       AddSub = ARM_AM::sub; | ||||||
|     NewOpc = getPreIndexedLoadStoreOpcode(Opcode, ARM_AM::sub); |     } else if (!isAM5 && | ||||||
|   } else { |                isMatchingIncrement(PrevMBBI, Base, Bytes, Limit,Pred,PredReg)) { | ||||||
|     MergeInstr = findIncDecAfter(MBBI, Base, Pred, PredReg, Offset); |       DoMerge = true; | ||||||
|     if (Offset == Bytes) { |     } | ||||||
|       NewOpc = getPostIndexedLoadStoreOpcode(Opcode, ARM_AM::add); |     if (DoMerge) { | ||||||
|     } else if (!isAM5 && Offset == -Bytes) { |       NewOpc = getPreIndexedLoadStoreOpcode(Opcode, AddSub); | ||||||
|       NewOpc = getPostIndexedLoadStoreOpcode(Opcode, ARM_AM::sub); |       MBB.erase(PrevMBBI); | ||||||
|     } else |     } | ||||||
|       return false; |  | ||||||
|   } |   } | ||||||
|   MBB.erase(MergeInstr); |  | ||||||
|  |  | ||||||
|   ARM_AM::AddrOpc AddSub = Offset < 0 ? ARM_AM::sub : ARM_AM::add; |   // Try merging with the next instruction. | ||||||
|  |   MachineBasicBlock::iterator EndMBBI = MBB.end(); | ||||||
|  |   if (!DoMerge && MBBI != EndMBBI) { | ||||||
|  |     MachineBasicBlock::iterator NextMBBI = std::next(MBBI); | ||||||
|  |     while (NextMBBI != EndMBBI && NextMBBI->isDebugValue()) | ||||||
|  |       ++NextMBBI; | ||||||
|  |     if (!isAM5 && | ||||||
|  |         isMatchingDecrement(NextMBBI, Base, Bytes, Limit, Pred, PredReg)) { | ||||||
|  |       DoMerge = true; | ||||||
|  |       AddSub = ARM_AM::sub; | ||||||
|  |     } else if (isMatchingIncrement(NextMBBI, Base, Bytes, Limit,Pred,PredReg)) { | ||||||
|  |       DoMerge = true; | ||||||
|  |     } | ||||||
|  |     if (DoMerge) { | ||||||
|  |       NewOpc = getPostIndexedLoadStoreOpcode(Opcode, AddSub); | ||||||
|  |       MBB.erase(NextMBBI); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (!DoMerge) | ||||||
|  |     return false; | ||||||
|  |  | ||||||
|   bool isLd = isLoadSingle(Opcode); |  | ||||||
|   if (isAM5) { |   if (isAM5) { | ||||||
|     // VLDM[SD]_UPD, VSTM[SD]_UPD |     // VLDM[SD]_UPD, VSTM[SD]_UPD | ||||||
|     // (There are no base-updating versions of VLDR/VSTR instructions, but the |     // (There are no base-updating versions of VLDR/VSTR instructions, but the | ||||||
| @@ -1313,16 +1368,18 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) { | |||||||
|     if (isAM2) { |     if (isAM2) { | ||||||
|       // LDR_PRE, LDR_POST |       // LDR_PRE, LDR_POST | ||||||
|       if (NewOpc == ARM::LDR_PRE_IMM || NewOpc == ARM::LDRB_PRE_IMM) { |       if (NewOpc == ARM::LDR_PRE_IMM || NewOpc == ARM::LDRB_PRE_IMM) { | ||||||
|  |         int Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes; | ||||||
|         BuildMI(MBB, MBBI, DL, TII->get(NewOpc), MI->getOperand(0).getReg()) |         BuildMI(MBB, MBBI, DL, TII->get(NewOpc), MI->getOperand(0).getReg()) | ||||||
|           .addReg(Base, RegState::Define) |           .addReg(Base, RegState::Define) | ||||||
|           .addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg); |           .addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg); | ||||||
|       } else { |       } else { | ||||||
|         int Imm = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift); |         int Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift); | ||||||
|         BuildMI(MBB, MBBI, DL, TII->get(NewOpc), MI->getOperand(0).getReg()) |         BuildMI(MBB, MBBI, DL, TII->get(NewOpc), MI->getOperand(0).getReg()) | ||||||
|           .addReg(Base, RegState::Define) |           .addReg(Base, RegState::Define) | ||||||
|           .addReg(Base).addReg(0).addImm(Imm).addImm(Pred).addReg(PredReg); |           .addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg); | ||||||
|       } |       } | ||||||
|     } else { |     } else { | ||||||
|  |       int Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes; | ||||||
|       // t2LDR_PRE, t2LDR_POST |       // t2LDR_PRE, t2LDR_POST | ||||||
|       BuildMI(MBB, MBBI, DL, TII->get(NewOpc), MI->getOperand(0).getReg()) |       BuildMI(MBB, MBBI, DL, TII->get(NewOpc), MI->getOperand(0).getReg()) | ||||||
|         .addReg(Base, RegState::Define) |         .addReg(Base, RegState::Define) | ||||||
| @@ -1334,12 +1391,13 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) { | |||||||
|     // the vestigal zero-reg offset register. When that's fixed, this clause |     // the vestigal zero-reg offset register. When that's fixed, this clause | ||||||
|     // can be removed entirely. |     // can be removed entirely. | ||||||
|     if (isAM2 && NewOpc == ARM::STR_POST_IMM) { |     if (isAM2 && NewOpc == ARM::STR_POST_IMM) { | ||||||
|       int Imm = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift); |       int Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift); | ||||||
|       // STR_PRE, STR_POST |       // STR_PRE, STR_POST | ||||||
|       BuildMI(MBB, MBBI, DL, TII->get(NewOpc), Base) |       BuildMI(MBB, MBBI, DL, TII->get(NewOpc), Base) | ||||||
|         .addReg(MO.getReg(), getKillRegState(MO.isKill())) |         .addReg(MO.getReg(), getKillRegState(MO.isKill())) | ||||||
|         .addReg(Base).addReg(0).addImm(Imm).addImm(Pred).addReg(PredReg); |         .addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg); | ||||||
|     } else { |     } else { | ||||||
|  |       int Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes; | ||||||
|       // t2STR_PRE, t2STR_POST |       // t2STR_PRE, t2STR_POST | ||||||
|       BuildMI(MBB, MBBI, DL, TII->get(NewOpc), Base) |       BuildMI(MBB, MBBI, DL, TII->get(NewOpc), Base) | ||||||
|         .addReg(MO.getReg(), getKillRegState(MO.isKill())) |         .addReg(MO.getReg(), getKillRegState(MO.isKill())) | ||||||
| @@ -1351,66 +1409,6 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) { | |||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool ARMLoadStoreOpt::MergeBaseUpdateLSDouble(MachineInstr &MI) const { |  | ||||||
|   unsigned Opcode = MI.getOpcode(); |  | ||||||
|   assert((Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) && |  | ||||||
|          "Must have t2STRDi8 or t2LDRDi8"); |  | ||||||
|   if (MI.getOperand(3).getImm() != 0) |  | ||||||
|     return false; |  | ||||||
|  |  | ||||||
|   // Behaviour for writeback is undefined if base register is the same as one |  | ||||||
|   // of the others. |  | ||||||
|   const MachineOperand &BaseOp = MI.getOperand(2); |  | ||||||
|   unsigned Base = BaseOp.getReg(); |  | ||||||
|   const MachineOperand &Reg0Op = MI.getOperand(0); |  | ||||||
|   const MachineOperand &Reg1Op = MI.getOperand(1); |  | ||||||
|   if (Reg0Op.getReg() == Base || Reg1Op.getReg() == Base) |  | ||||||
|     return false; |  | ||||||
|  |  | ||||||
|   unsigned PredReg; |  | ||||||
|   ARMCC::CondCodes Pred = getInstrPredicate(&MI, PredReg); |  | ||||||
|   MachineBasicBlock::iterator MBBI(MI); |  | ||||||
|   MachineBasicBlock &MBB = *MI.getParent(); |  | ||||||
|   int Offset; |  | ||||||
|   MachineBasicBlock::iterator MergeInstr = findIncDecBefore(MBBI, Base, Pred, |  | ||||||
|                                                             PredReg, Offset); |  | ||||||
|   unsigned NewOpc; |  | ||||||
|   if (Offset == 8 || Offset == -8) { |  | ||||||
|     NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_PRE : ARM::t2STRD_PRE; |  | ||||||
|   } else { |  | ||||||
|     MergeInstr = findIncDecAfter(MBBI, Base, Pred, PredReg, Offset); |  | ||||||
|     if (Offset == 8 || Offset == -8) { |  | ||||||
|       NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_POST : ARM::t2STRD_POST; |  | ||||||
|     } else |  | ||||||
|       return false; |  | ||||||
|   } |  | ||||||
|   MBB.erase(MergeInstr); |  | ||||||
|  |  | ||||||
|   DebugLoc DL = MI.getDebugLoc(); |  | ||||||
|   MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc)); |  | ||||||
|   if (NewOpc == ARM::t2LDRD_PRE || NewOpc == ARM::t2LDRD_POST) { |  | ||||||
|     MIB.addOperand(Reg0Op).addOperand(Reg1Op) |  | ||||||
|        .addReg(BaseOp.getReg(), RegState::Define); |  | ||||||
|   } else { |  | ||||||
|     assert(NewOpc == ARM::t2STRD_PRE || NewOpc == ARM::t2STRD_POST); |  | ||||||
|     MIB.addReg(BaseOp.getReg(), RegState::Define) |  | ||||||
|        .addOperand(Reg0Op).addOperand(Reg1Op); |  | ||||||
|   } |  | ||||||
|   MIB.addReg(BaseOp.getReg(), RegState::Kill) |  | ||||||
|      .addImm(Offset).addImm(Pred).addReg(PredReg); |  | ||||||
|   assert(TII->get(Opcode).getNumOperands() == 6 && |  | ||||||
|          TII->get(NewOpc).getNumOperands() == 7 && |  | ||||||
|          "Unexpected number of operands in Opcode specification."); |  | ||||||
|  |  | ||||||
|   // Transfer implicit operands. |  | ||||||
|   for (const MachineOperand &MO : MI.implicit_operands()) |  | ||||||
|     MIB.addOperand(MO); |  | ||||||
|   MIB->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); |  | ||||||
|  |  | ||||||
|   MBB.erase(MBBI); |  | ||||||
|   return true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Returns true if instruction is a memory operation that this pass is capable | /// Returns true if instruction is a memory operation that this pass is capable | ||||||
| /// of operating on. | /// of operating on. | ||||||
| static bool isMemoryOp(const MachineInstr *MI) { | static bool isMemoryOp(const MachineInstr *MI) { | ||||||
| @@ -1618,7 +1616,6 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) { | |||||||
|   ARMCC::CondCodes CurrPred = ARMCC::AL; |   ARMCC::CondCodes CurrPred = ARMCC::AL; | ||||||
|   unsigned Position = 0; |   unsigned Position = 0; | ||||||
|   assert(Candidates.size() == 0); |   assert(Candidates.size() == 0); | ||||||
|   assert(MergeBaseCandidates.size() == 0); |  | ||||||
|   LiveRegsValid = false; |   LiveRegsValid = false; | ||||||
|  |  | ||||||
|   for (MachineBasicBlock::iterator I = MBB.end(), MBBI; I != MBB.begin(); |   for (MachineBasicBlock::iterator I = MBB.end(), MBBI; I != MBB.begin(); | ||||||
| @@ -1697,15 +1694,8 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) { | |||||||
|       MBBI = I; |       MBBI = I; | ||||||
|       --Position; |       --Position; | ||||||
|       // Fallthrough to look into existing chain. |       // Fallthrough to look into existing chain. | ||||||
|     } else if (MBBI->isDebugValue()) { |     } else if (MBBI->isDebugValue()) | ||||||
|       continue; |       continue; | ||||||
|     } else if (MBBI->getOpcode() == ARM::t2LDRDi8 || |  | ||||||
|                MBBI->getOpcode() == ARM::t2STRDi8) { |  | ||||||
|       // ARMPreAllocLoadStoreOpt has already formed some LDRD/STRD instructions |  | ||||||
|       // remember them because we may still be able to merge add/sub into them. |  | ||||||
|       MergeBaseCandidates.push_back(MBBI); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     // If we are here then the chain is broken; Extract candidates for a merge. |     // If we are here then the chain is broken; Extract candidates for a merge. | ||||||
|     if (MemOps.size() > 0) { |     if (MemOps.size() > 0) { | ||||||
| @@ -1736,9 +1726,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) { | |||||||
|       if (Merged) { |       if (Merged) { | ||||||
|         Changed = true; |         Changed = true; | ||||||
|         unsigned Opcode = Merged->getOpcode(); |         unsigned Opcode = Merged->getOpcode(); | ||||||
|         if (Opcode == ARM::t2STRDi8 || Opcode == ARM::t2LDRDi8) |         if (Opcode != ARM::t2STRDi8 && Opcode != ARM::t2LDRDi8) | ||||||
|           MergeBaseUpdateLSDouble(*Merged); |  | ||||||
|         else |  | ||||||
|           MergeBaseUpdateLSMultiple(Merged); |           MergeBaseUpdateLSMultiple(Merged); | ||||||
|       } else { |       } else { | ||||||
|         for (MachineInstr *MI : Candidate->Instrs) { |         for (MachineInstr *MI : Candidate->Instrs) { | ||||||
| @@ -1753,10 +1741,6 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   Candidates.clear(); |   Candidates.clear(); | ||||||
|   // Try to fold add/sub into the LDRD/STRD formed by ARMPreAllocLoadStoreOpt. |  | ||||||
|   for (MachineInstr *MI : MergeBaseCandidates) |  | ||||||
|     MergeBaseUpdateLSDouble(*MI); |  | ||||||
|   MergeBaseCandidates.clear(); |  | ||||||
|  |  | ||||||
|   return Changed; |   return Changed; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -112,10 +112,10 @@ entry: | |||||||
| } | } | ||||||
|  |  | ||||||
| ; CHECK-LABEL: strd_spill_ldrd_reload: | ; CHECK-LABEL: strd_spill_ldrd_reload: | ||||||
| ; A8: strd r1, r0, [sp, #-8]! | ; A8: strd r1, r0, [sp] | ||||||
| ; M3: strd r1, r0, [sp, #-8]! | ; M3: strd r1, r0, [sp] | ||||||
| ; BASIC: strd r1, r0, [sp, #-8]! | ; BASIC: strd r1, r0, [sp] | ||||||
| ; GREEDY: strd r0, r1, [sp, #-8]! | ; GREEDY: strd r0, r1, [sp] | ||||||
| ; CHECK: @ InlineAsm Start | ; CHECK: @ InlineAsm Start | ||||||
| ; CHECK: @ InlineAsm End | ; CHECK: @ InlineAsm End | ||||||
| ; A8: ldrd r2, r1, [sp] | ; A8: ldrd r2, r1, [sp] | ||||||
| @@ -131,53 +131,5 @@ define void @strd_spill_ldrd_reload(i32 %v0, i32 %v1) { | |||||||
|   ret void |   ret void | ||||||
| } | } | ||||||
|  |  | ||||||
| declare void @extfunc2(i32*, i32, i32) |  | ||||||
|  |  | ||||||
| ; CHECK-LABEL: ldrd_postupdate_dec: |  | ||||||
| ; CHECK: ldrd r1, r2, [r0], #-8 |  | ||||||
| ; CHECK-NEXT: bl{{x?}} _extfunc |  | ||||||
| define void @ldrd_postupdate_dec(i32* %p0) { |  | ||||||
|   %p0.1 = getelementptr i32, i32* %p0, i32 1 |  | ||||||
|   %v0 = load i32, i32* %p0 |  | ||||||
|   %v1 = load i32, i32* %p0.1 |  | ||||||
|   %p1 = getelementptr i32, i32* %p0, i32 -2 |  | ||||||
|   call void @extfunc2(i32* %p1, i32 %v0, i32 %v1) |  | ||||||
|   ret void |  | ||||||
| } |  | ||||||
|  |  | ||||||
| ; CHECK-LABEL: ldrd_postupdate_inc: |  | ||||||
| ; CHECK: ldrd r1, r2, [r0], #8 |  | ||||||
| ; CHECK-NEXT: bl{{x?}} _extfunc |  | ||||||
| define void @ldrd_postupdate_inc(i32* %p0) { |  | ||||||
|   %p0.1 = getelementptr i32, i32* %p0, i32 1 |  | ||||||
|   %v0 = load i32, i32* %p0 |  | ||||||
|   %v1 = load i32, i32* %p0.1 |  | ||||||
|   %p1 = getelementptr i32, i32* %p0, i32 2 |  | ||||||
|   call void @extfunc2(i32* %p1, i32 %v0, i32 %v1) |  | ||||||
|   ret void |  | ||||||
| } |  | ||||||
|  |  | ||||||
| ; CHECK-LABEL: strd_postupdate_dec: |  | ||||||
| ; CHECK: strd r1, r2, [r0], #-8 |  | ||||||
| ; CHECK-NEXT: bx lr |  | ||||||
| define i32* @strd_postupdate_dec(i32* %p0, i32 %v0, i32 %v1) { |  | ||||||
|   %p0.1 = getelementptr i32, i32* %p0, i32 1 |  | ||||||
|   store i32 %v0, i32* %p0 |  | ||||||
|   store i32 %v1, i32* %p0.1 |  | ||||||
|   %p1 = getelementptr i32, i32* %p0, i32 -2 |  | ||||||
|   ret i32* %p1 |  | ||||||
| } |  | ||||||
|  |  | ||||||
| ; CHECK-LABEL: strd_postupdate_inc: |  | ||||||
| ; CHECK: strd r1, r2, [r0], #8 |  | ||||||
| ; CHECK-NEXT: bx lr |  | ||||||
| define i32* @strd_postupdate_inc(i32* %p0, i32 %v0, i32 %v1) { |  | ||||||
|   %p0.1 = getelementptr i32, i32* %p0, i32 1 |  | ||||||
|   store i32 %v0, i32* %p0 |  | ||||||
|   store i32 %v1, i32* %p0.1 |  | ||||||
|   %p1 = getelementptr i32, i32* %p0, i32 2 |  | ||||||
|   ret i32* %p1 |  | ||||||
| } |  | ||||||
|  |  | ||||||
| declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind | declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind | ||||||
| declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind | declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user