1 //===- AArch64MachineScheduler.cpp - MI Scheduler for AArch64 -------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "AArch64MachineScheduler.h"
10 #include "AArch64InstrInfo.h"
11 #include "AArch64Subtarget.h"
12 #include "MCTargetDesc/AArch64MCTargetDesc.h"
16 static bool needReorderStoreMI(const MachineInstr
*MI
) {
20 switch (MI
->getOpcode()) {
25 if (!MI
->getMF()->getSubtarget
<AArch64Subtarget
>().isStoreAddressAscend())
29 return AArch64InstrInfo::getLdStOffsetOp(*MI
).isImm();
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
);
41 // May overlapping writes if two store instructions without same base
42 if (!Base0
.isIdenticalTo(Base1
))
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
;
54 const MachineInstr
&MI
= (Off0
< Off1
) ? MI0
: MI1
;
55 int Multiples
= AArch64InstrInfo::isPairedLdSt(MI
) ? 2 : 1;
56 int StoreSize
= AArch64InstrInfo::getMemScale(MI
) * Multiples
;
58 return llabs(Off0
- Off1
) < StoreSize
;
61 bool AArch64PostRASchedStrategy::tryCandidate(SchedCandidate
&Cand
,
62 SchedCandidate
&TryCand
) {
63 bool OriginalResult
= PostGenericScheduler::tryCandidate(Cand
, TryCand
);
66 MachineInstr
*Instr0
= TryCand
.SU
->getInstr();
67 MachineInstr
*Instr1
= Cand
.SU
->getInstr();
69 if (!needReorderStoreMI(Instr0
) || !needReorderStoreMI(Instr1
))
70 return OriginalResult
;
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.
81 return OriginalResult
;