xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64MachineScheduler.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
181ad6265SDimitry Andric //===- AArch64MachineScheduler.cpp - MI Scheduler for AArch64 -------------===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #include "AArch64MachineScheduler.h"
1081ad6265SDimitry Andric #include "AArch64InstrInfo.h"
1181ad6265SDimitry Andric #include "AArch64Subtarget.h"
1281ad6265SDimitry Andric #include "MCTargetDesc/AArch64MCTargetDesc.h"
1381ad6265SDimitry Andric 
1481ad6265SDimitry Andric using namespace llvm;
1581ad6265SDimitry Andric 
needReorderStoreMI(const MachineInstr * MI)1681ad6265SDimitry Andric static bool needReorderStoreMI(const MachineInstr *MI) {
1781ad6265SDimitry Andric   if (!MI)
1881ad6265SDimitry Andric     return false;
1981ad6265SDimitry Andric 
2081ad6265SDimitry Andric   switch (MI->getOpcode()) {
2181ad6265SDimitry Andric   default:
2281ad6265SDimitry Andric     return false;
2381ad6265SDimitry Andric   case AArch64::STURQi:
2481ad6265SDimitry Andric   case AArch64::STRQui:
25fcaf7f86SDimitry Andric     if (!MI->getMF()->getSubtarget<AArch64Subtarget>().isStoreAddressAscend())
2681ad6265SDimitry Andric       return false;
27*bdd1243dSDimitry Andric     [[fallthrough]];
2881ad6265SDimitry Andric   case AArch64::STPQi:
2981ad6265SDimitry Andric     return AArch64InstrInfo::getLdStOffsetOp(*MI).isImm();
3081ad6265SDimitry Andric   }
3181ad6265SDimitry Andric 
3281ad6265SDimitry Andric   return false;
3381ad6265SDimitry Andric }
3481ad6265SDimitry Andric 
3581ad6265SDimitry Andric // Return true if two stores with same base address may overlap writes
mayOverlapWrite(const MachineInstr & MI0,const MachineInstr & MI1,int64_t & Off0,int64_t & Off1)3681ad6265SDimitry Andric static bool mayOverlapWrite(const MachineInstr &MI0, const MachineInstr &MI1,
3781ad6265SDimitry Andric                             int64_t &Off0, int64_t &Off1) {
3881ad6265SDimitry Andric   const MachineOperand &Base0 = AArch64InstrInfo::getLdStBaseOp(MI0);
3981ad6265SDimitry Andric   const MachineOperand &Base1 = AArch64InstrInfo::getLdStBaseOp(MI1);
4081ad6265SDimitry Andric 
4181ad6265SDimitry Andric   // May overlapping writes if two store instructions without same base
4281ad6265SDimitry Andric   if (!Base0.isIdenticalTo(Base1))
4381ad6265SDimitry Andric     return true;
4481ad6265SDimitry Andric 
4581ad6265SDimitry Andric   int StoreSize0 = AArch64InstrInfo::getMemScale(MI0);
4681ad6265SDimitry Andric   int StoreSize1 = AArch64InstrInfo::getMemScale(MI1);
4781ad6265SDimitry Andric   Off0 = AArch64InstrInfo::hasUnscaledLdStOffset(MI0.getOpcode())
4881ad6265SDimitry Andric              ? AArch64InstrInfo::getLdStOffsetOp(MI0).getImm()
4981ad6265SDimitry Andric              : AArch64InstrInfo::getLdStOffsetOp(MI0).getImm() * StoreSize0;
5081ad6265SDimitry Andric   Off1 = AArch64InstrInfo::hasUnscaledLdStOffset(MI1.getOpcode())
5181ad6265SDimitry Andric              ? AArch64InstrInfo::getLdStOffsetOp(MI1).getImm()
5281ad6265SDimitry Andric              : AArch64InstrInfo::getLdStOffsetOp(MI1).getImm() * StoreSize1;
5381ad6265SDimitry Andric 
5481ad6265SDimitry Andric   const MachineInstr &MI = (Off0 < Off1) ? MI0 : MI1;
5581ad6265SDimitry Andric   int Multiples = AArch64InstrInfo::isPairedLdSt(MI) ? 2 : 1;
5681ad6265SDimitry Andric   int StoreSize = AArch64InstrInfo::getMemScale(MI) * Multiples;
5781ad6265SDimitry Andric 
5881ad6265SDimitry Andric   return llabs(Off0 - Off1) < StoreSize;
5981ad6265SDimitry Andric }
6081ad6265SDimitry Andric 
tryCandidate(SchedCandidate & Cand,SchedCandidate & TryCand)6181ad6265SDimitry Andric bool AArch64PostRASchedStrategy::tryCandidate(SchedCandidate &Cand,
6281ad6265SDimitry Andric                                               SchedCandidate &TryCand) {
6381ad6265SDimitry Andric   bool OriginalResult = PostGenericScheduler::tryCandidate(Cand, TryCand);
6481ad6265SDimitry Andric 
6581ad6265SDimitry Andric   if (Cand.isValid()) {
6681ad6265SDimitry Andric     MachineInstr *Instr0 = TryCand.SU->getInstr();
6781ad6265SDimitry Andric     MachineInstr *Instr1 = Cand.SU->getInstr();
6881ad6265SDimitry Andric 
6981ad6265SDimitry Andric     if (!needReorderStoreMI(Instr0) || !needReorderStoreMI(Instr1))
7081ad6265SDimitry Andric       return OriginalResult;
7181ad6265SDimitry Andric 
7281ad6265SDimitry Andric     int64_t Off0, Off1;
7381ad6265SDimitry Andric     // With the same base address and non-overlapping writes.
7481ad6265SDimitry Andric     if (!mayOverlapWrite(*Instr0, *Instr1, Off0, Off1)) {
7581ad6265SDimitry Andric       TryCand.Reason = NodeOrder;
7681ad6265SDimitry Andric       // Order them by ascending offsets.
7781ad6265SDimitry Andric       return Off0 < Off1;
7881ad6265SDimitry Andric     }
7981ad6265SDimitry Andric   }
8081ad6265SDimitry Andric 
8181ad6265SDimitry Andric   return OriginalResult;
8281ad6265SDimitry Andric }
83