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