forked from OSchip/llvm-project
83 lines
2.8 KiB
C++
83 lines
2.8 KiB
C++
//===- AArch64MachineScheduler.cpp - MI Scheduler for AArch64 -------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "AArch64MachineScheduler.h"
|
|
#include "AArch64InstrInfo.h"
|
|
#include "AArch64Subtarget.h"
|
|
#include "MCTargetDesc/AArch64MCTargetDesc.h"
|
|
|
|
using namespace llvm;
|
|
|
|
static bool needReorderStoreMI(const MachineInstr *MI) {
|
|
if (!MI)
|
|
return false;
|
|
|
|
switch (MI->getOpcode()) {
|
|
default:
|
|
return false;
|
|
case AArch64::STURQi:
|
|
case AArch64::STRQui:
|
|
if (!MI->getMF()->getSubtarget<AArch64Subtarget>().isStoreAddressAscend())
|
|
return false;
|
|
[[fallthrough]];
|
|
case AArch64::STPQi:
|
|
return AArch64InstrInfo::getLdStOffsetOp(*MI).isImm();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Return true if two stores with same base address may overlap writes
|
|
static bool mayOverlapWrite(const MachineInstr &MI0, const MachineInstr &MI1,
|
|
int64_t &Off0, int64_t &Off1) {
|
|
const MachineOperand &Base0 = AArch64InstrInfo::getLdStBaseOp(MI0);
|
|
const MachineOperand &Base1 = AArch64InstrInfo::getLdStBaseOp(MI1);
|
|
|
|
// May overlapping writes if two store instructions without same base
|
|
if (!Base0.isIdenticalTo(Base1))
|
|
return true;
|
|
|
|
int StoreSize0 = AArch64InstrInfo::getMemScale(MI0);
|
|
int StoreSize1 = AArch64InstrInfo::getMemScale(MI1);
|
|
Off0 = AArch64InstrInfo::hasUnscaledLdStOffset(MI0.getOpcode())
|
|
? AArch64InstrInfo::getLdStOffsetOp(MI0).getImm()
|
|
: AArch64InstrInfo::getLdStOffsetOp(MI0).getImm() * StoreSize0;
|
|
Off1 = AArch64InstrInfo::hasUnscaledLdStOffset(MI1.getOpcode())
|
|
? AArch64InstrInfo::getLdStOffsetOp(MI1).getImm()
|
|
: AArch64InstrInfo::getLdStOffsetOp(MI1).getImm() * StoreSize1;
|
|
|
|
const MachineInstr &MI = (Off0 < Off1) ? MI0 : MI1;
|
|
int Multiples = AArch64InstrInfo::isPairedLdSt(MI) ? 2 : 1;
|
|
int StoreSize = AArch64InstrInfo::getMemScale(MI) * Multiples;
|
|
|
|
return llabs(Off0 - Off1) < StoreSize;
|
|
}
|
|
|
|
bool AArch64PostRASchedStrategy::tryCandidate(SchedCandidate &Cand,
|
|
SchedCandidate &TryCand) {
|
|
bool OriginalResult = PostGenericScheduler::tryCandidate(Cand, TryCand);
|
|
|
|
if (Cand.isValid()) {
|
|
MachineInstr *Instr0 = TryCand.SU->getInstr();
|
|
MachineInstr *Instr1 = Cand.SU->getInstr();
|
|
|
|
if (!needReorderStoreMI(Instr0) || !needReorderStoreMI(Instr1))
|
|
return OriginalResult;
|
|
|
|
int64_t Off0, Off1;
|
|
// With the same base address and non-overlapping writes.
|
|
if (!mayOverlapWrite(*Instr0, *Instr1, Off0, Off1)) {
|
|
TryCand.Reason = NodeOrder;
|
|
// Order them by ascending offsets.
|
|
return Off0 < Off1;
|
|
}
|
|
}
|
|
|
|
return OriginalResult;
|
|
}
|