1 //===- AArch64MachineScheduler.cpp - MI Scheduler for AArch64 -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "AArch64MachineScheduler.h" 10 #include "AArch64InstrInfo.h" 11 #include "AArch64Subtarget.h" 12 #include "MCTargetDesc/AArch64MCTargetDesc.h" 13 14 using namespace llvm; 15 16 static bool needReorderStoreMI(const MachineInstr *MI) { 17 if (!MI) 18 return false; 19 20 switch (MI->getOpcode()) { 21 default: 22 return false; 23 case AArch64::STURQi: 24 case AArch64::STRQui: 25 if (!MI->getMF()->getSubtarget<AArch64Subtarget>().isStoreAddressAscend()) 26 return false; 27 [[fallthrough]]; 28 case AArch64::STPQi: 29 return AArch64InstrInfo::getLdStOffsetOp(*MI).isImm(); 30 } 31 32 return false; 33 } 34 35 // Return true if two stores with same base address may overlap writes 36 static bool mayOverlapWrite(const MachineInstr &MI0, const MachineInstr &MI1, 37 int64_t &Off0, int64_t &Off1) { 38 const MachineOperand &Base0 = AArch64InstrInfo::getLdStBaseOp(MI0); 39 const MachineOperand &Base1 = AArch64InstrInfo::getLdStBaseOp(MI1); 40 41 // May overlapping writes if two store instructions without same base 42 if (!Base0.isIdenticalTo(Base1)) 43 return true; 44 45 int StoreSize0 = AArch64InstrInfo::getMemScale(MI0); 46 int StoreSize1 = AArch64InstrInfo::getMemScale(MI1); 47 Off0 = AArch64InstrInfo::hasUnscaledLdStOffset(MI0.getOpcode()) 48 ? AArch64InstrInfo::getLdStOffsetOp(MI0).getImm() 49 : AArch64InstrInfo::getLdStOffsetOp(MI0).getImm() * StoreSize0; 50 Off1 = AArch64InstrInfo::hasUnscaledLdStOffset(MI1.getOpcode()) 51 ? AArch64InstrInfo::getLdStOffsetOp(MI1).getImm() 52 : AArch64InstrInfo::getLdStOffsetOp(MI1).getImm() * StoreSize1; 53 54 const MachineInstr &MI = (Off0 < Off1) ? MI0 : MI1; 55 int Multiples = AArch64InstrInfo::isPairedLdSt(MI) ? 2 : 1; 56 int StoreSize = AArch64InstrInfo::getMemScale(MI) * Multiples; 57 58 return llabs(Off0 - Off1) < StoreSize; 59 } 60 61 bool AArch64PostRASchedStrategy::tryCandidate(SchedCandidate &Cand, 62 SchedCandidate &TryCand) { 63 bool OriginalResult = PostGenericScheduler::tryCandidate(Cand, TryCand); 64 65 if (Cand.isValid()) { 66 MachineInstr *Instr0 = TryCand.SU->getInstr(); 67 MachineInstr *Instr1 = Cand.SU->getInstr(); 68 69 if (!needReorderStoreMI(Instr0) || !needReorderStoreMI(Instr1)) 70 return OriginalResult; 71 72 int64_t Off0, Off1; 73 // With the same base address and non-overlapping writes. 74 if (!mayOverlapWrite(*Instr0, *Instr1, Off0, Off1)) { 75 TryCand.Reason = NodeOrder; 76 // Order them by ascending offsets. 77 return Off0 < Off1; 78 } 79 } 80 81 return OriginalResult; 82 } 83