xref: /llvm-project/llvm/lib/Target/AArch64/AArch64MachineScheduler.cpp (revision de9d80c1c579e39cc658a508f1d4ba1cd792e4d5)
1572fc7d2SAndre Vieira //===- AArch64MachineScheduler.cpp - MI Scheduler for AArch64 -------------===//
2572fc7d2SAndre Vieira //
3572fc7d2SAndre Vieira // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4572fc7d2SAndre Vieira // See https://llvm.org/LICENSE.txt for license information.
5572fc7d2SAndre Vieira // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6572fc7d2SAndre Vieira //
7572fc7d2SAndre Vieira //===----------------------------------------------------------------------===//
8572fc7d2SAndre Vieira 
9572fc7d2SAndre Vieira #include "AArch64MachineScheduler.h"
10c42a2255Szhongyunde #include "AArch64InstrInfo.h"
11c42a2255Szhongyunde #include "AArch64Subtarget.h"
12572fc7d2SAndre Vieira #include "MCTargetDesc/AArch64MCTargetDesc.h"
13572fc7d2SAndre Vieira 
14572fc7d2SAndre Vieira using namespace llvm;
15572fc7d2SAndre Vieira 
needReorderStoreMI(const MachineInstr * MI)16c42a2255Szhongyunde static bool needReorderStoreMI(const MachineInstr *MI) {
17c42a2255Szhongyunde   if (!MI)
18c42a2255Szhongyunde     return false;
19c42a2255Szhongyunde 
20c42a2255Szhongyunde   switch (MI->getOpcode()) {
21c42a2255Szhongyunde   default:
22c42a2255Szhongyunde     return false;
23c42a2255Szhongyunde   case AArch64::STURQi:
24c42a2255Szhongyunde   case AArch64::STRQui:
25bddf2073Szhongyunde     if (!MI->getMF()->getSubtarget<AArch64Subtarget>().isStoreAddressAscend())
26c42a2255Szhongyunde       return false;
27*de9d80c1SFangrui Song     [[fallthrough]];
28c42a2255Szhongyunde   case AArch64::STPQi:
290cb33551Szhongyunde     return AArch64InstrInfo::getLdStOffsetOp(*MI).isImm();
30c42a2255Szhongyunde   }
31c42a2255Szhongyunde 
32c42a2255Szhongyunde   return false;
33c42a2255Szhongyunde }
34c42a2255Szhongyunde 
35c42a2255Szhongyunde // 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)36c42a2255Szhongyunde static bool mayOverlapWrite(const MachineInstr &MI0, const MachineInstr &MI1,
37c42a2255Szhongyunde                             int64_t &Off0, int64_t &Off1) {
38c42a2255Szhongyunde   const MachineOperand &Base0 = AArch64InstrInfo::getLdStBaseOp(MI0);
39c42a2255Szhongyunde   const MachineOperand &Base1 = AArch64InstrInfo::getLdStBaseOp(MI1);
40c42a2255Szhongyunde 
41c42a2255Szhongyunde   // May overlapping writes if two store instructions without same base
42c42a2255Szhongyunde   if (!Base0.isIdenticalTo(Base1))
43c42a2255Szhongyunde     return true;
44c42a2255Szhongyunde 
45c42a2255Szhongyunde   int StoreSize0 = AArch64InstrInfo::getMemScale(MI0);
46c42a2255Szhongyunde   int StoreSize1 = AArch64InstrInfo::getMemScale(MI1);
47c42a2255Szhongyunde   Off0 = AArch64InstrInfo::hasUnscaledLdStOffset(MI0.getOpcode())
48c42a2255Szhongyunde              ? AArch64InstrInfo::getLdStOffsetOp(MI0).getImm()
49c42a2255Szhongyunde              : AArch64InstrInfo::getLdStOffsetOp(MI0).getImm() * StoreSize0;
50c42a2255Szhongyunde   Off1 = AArch64InstrInfo::hasUnscaledLdStOffset(MI1.getOpcode())
51c42a2255Szhongyunde              ? AArch64InstrInfo::getLdStOffsetOp(MI1).getImm()
52c42a2255Szhongyunde              : AArch64InstrInfo::getLdStOffsetOp(MI1).getImm() * StoreSize1;
53c42a2255Szhongyunde 
54c42a2255Szhongyunde   const MachineInstr &MI = (Off0 < Off1) ? MI0 : MI1;
55c42a2255Szhongyunde   int Multiples = AArch64InstrInfo::isPairedLdSt(MI) ? 2 : 1;
56c42a2255Szhongyunde   int StoreSize = AArch64InstrInfo::getMemScale(MI) * Multiples;
57c42a2255Szhongyunde 
58c42a2255Szhongyunde   return llabs(Off0 - Off1) < StoreSize;
59c42a2255Szhongyunde }
60c42a2255Szhongyunde 
tryCandidate(SchedCandidate & Cand,SchedCandidate & TryCand)61572fc7d2SAndre Vieira bool AArch64PostRASchedStrategy::tryCandidate(SchedCandidate &Cand,
62572fc7d2SAndre Vieira                                               SchedCandidate &TryCand) {
63572fc7d2SAndre Vieira   bool OriginalResult = PostGenericScheduler::tryCandidate(Cand, TryCand);
64572fc7d2SAndre Vieira 
65572fc7d2SAndre Vieira   if (Cand.isValid()) {
66572fc7d2SAndre Vieira     MachineInstr *Instr0 = TryCand.SU->getInstr();
67572fc7d2SAndre Vieira     MachineInstr *Instr1 = Cand.SU->getInstr();
68c42a2255Szhongyunde 
69c42a2255Szhongyunde     if (!needReorderStoreMI(Instr0) || !needReorderStoreMI(Instr1))
70c42a2255Szhongyunde       return OriginalResult;
71c42a2255Szhongyunde 
72c42a2255Szhongyunde     int64_t Off0, Off1;
73572fc7d2SAndre Vieira     // With the same base address and non-overlapping writes.
74c42a2255Szhongyunde     if (!mayOverlapWrite(*Instr0, *Instr1, Off0, Off1)) {
75572fc7d2SAndre Vieira       TryCand.Reason = NodeOrder;
76572fc7d2SAndre Vieira       // Order them by ascending offsets.
77572fc7d2SAndre Vieira       return Off0 < Off1;
78572fc7d2SAndre Vieira     }
79572fc7d2SAndre Vieira   }
80572fc7d2SAndre Vieira 
81572fc7d2SAndre Vieira   return OriginalResult;
82572fc7d2SAndre Vieira }
83