29#define DEBUG_TYPE "aarch64-pbqp"
36bool isFPReg(
unsigned reg) {
37 return AArch64::FPR32RegClass.contains(reg) ||
38 AArch64::FPR64RegClass.contains(reg) ||
39 AArch64::FPR128RegClass.contains(reg);
43bool isOdd(
unsigned reg) {
149bool haveSameParity(
unsigned reg1,
unsigned reg2) {
150 assert(isFPReg(reg1) &&
"Expecting an FP register for reg1");
151 assert(isFPReg(reg2) &&
"Expecting an FP register for reg2");
153 return isOdd(reg1) == isOdd(reg2);
158bool A57ChainingConstraint::addIntraChainConstraint(
PBQPRAGraph &
G,
unsigned Rd,
176 const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRdAllowed =
177 &
G.getNodeMetadata(node1).getAllowedRegs();
178 const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRaAllowed =
179 &
G.getNodeMetadata(node2).getAllowedRegs();
185 if (edge ==
G.invalidEdgeId()) {
188 bool livesOverlap = ld.
overlaps(la);
191 vRaAllowed->size() + 1, 0);
192 for (
unsigned i = 0, ie = vRdAllowed->size(); i != ie; ++i) {
193 unsigned pRd = (*vRdAllowed)[i];
194 for (
unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) {
195 unsigned pRa = (*vRaAllowed)[
j];
197 costs[i + 1][
j + 1] = std::numeric_limits<PBQP::PBQPNum>::infinity();
199 costs[i + 1][
j + 1] = haveSameParity(pRd, pRa) ? 0.0 : 1.0;
202 G.addEdge(node1, node2, std::move(costs));
206 if (
G.getEdgeNode1Id(edge) == node2) {
213 for (
unsigned i = 0, ie = vRdAllowed->size(); i != ie; ++i) {
214 unsigned pRd = (*vRdAllowed)[i];
218 PBQP::PBQPNum sameParityMax = std::numeric_limits<PBQP::PBQPNum>::min();
219 for (
unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) {
220 unsigned pRa = (*vRaAllowed)[
j];
221 if (haveSameParity(pRd, pRa))
222 if (costs[i + 1][j + 1] !=
223 std::numeric_limits<PBQP::PBQPNum>::infinity() &&
224 costs[i + 1][j + 1] > sameParityMax)
225 sameParityMax = costs[i + 1][
j + 1];
230 for (
unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) {
231 unsigned pRa = (*vRaAllowed)[
j];
232 if (!haveSameParity(pRd, pRa))
233 if (sameParityMax > costs[i + 1][j + 1])
234 costs[i + 1][
j + 1] = sameParityMax + 1.0;
237 G.updateEdgeCosts(edge, std::move(costs));
242void A57ChainingConstraint::addInterChainConstraint(
PBQPRAGraph &
G,
unsigned Rd,
247 if (Chains.
count(Ra)) {
250 <<
" to " <<
printReg(Rd, TRI) <<
'\n';);
263 for (
auto r : Chains) {
270 const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRdAllowed =
271 &
G.getNodeMetadata(node1).getAllowedRegs();
274 const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRrAllowed =
275 &
G.getNodeMetadata(node2).getAllowedRegs();
278 assert(edge !=
G.invalidEdgeId() &&
279 "PBQP error ! The edge should exist !");
283 if (
G.getEdgeNode1Id(edge) == node2) {
290 for (
unsigned i = 0, ie = vRdAllowed->size(); i != ie; ++i) {
291 unsigned pRd = (*vRdAllowed)[i];
295 PBQP::PBQPNum sameParityMax = std::numeric_limits<PBQP::PBQPNum>::min();
296 for (
unsigned j = 0, je = vRrAllowed->size(); j != je; ++j) {
297 unsigned pRa = (*vRrAllowed)[
j];
298 if (!haveSameParity(pRd, pRa))
299 if (costs[i + 1][j + 1] !=
300 std::numeric_limits<PBQP::PBQPNum>::infinity() &&
301 costs[i + 1][j + 1] > sameParityMax)
302 sameParityMax = costs[i + 1][
j + 1];
307 for (
unsigned j = 0, je = vRrAllowed->size(); j != je; ++j) {
308 unsigned pRa = (*vRrAllowed)[
j];
309 if (haveSameParity(pRd, pRa))
310 if (sameParityMax > costs[i + 1][j + 1])
311 costs[i + 1][
j + 1] = sameParityMax + 1.0;
314 G.updateEdgeCosts(edge, std::move(costs));
333 for (
const auto &
MBB: MF) {
336 for (
const auto &
MI:
MBB) {
339 for (
auto r : Chains) {
347 while (!toDel.
empty()) {
348 Chains.remove(toDel.
back());
353 switch (
MI.getOpcode()) {
354 case AArch64::FMSUBSrrr:
355 case AArch64::FMADDSrrr:
356 case AArch64::FNMSUBSrrr:
357 case AArch64::FNMADDSrrr:
358 case AArch64::FMSUBDrrr:
359 case AArch64::FMADDDrrr:
360 case AArch64::FNMSUBDrrr:
361 case AArch64::FNMADDDrrr: {
365 if (addIntraChainConstraint(
G, Rd, Ra))
366 addInterChainConstraint(
G, Rd, Ra);
370 case AArch64::FMLAv2f32:
371 case AArch64::FMLSv2f32: {
373 addInterChainConstraint(
G, Rd, Rd);
static bool regJustKilledBefore(const LiveIntervals &LIs, unsigned reg, const MachineInstr &MI)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void apply(PBQPRAGraph &G) override
LiveInterval - This class represents the liveness of a register, or stack slot.
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
bool overlaps(const LiveRange &other) const
overlaps - Return true if the intersection of the two live ranges is not empty.
bool expiredAt(SlotIndex index) const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void dump() const
dump - Print the current MachineFunction to cerr, useful for debugger use.
Representation of each machine instruction.
typename SolverT::RawMatrix RawMatrix
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
Wrapper class representing virtual and physical registers.
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
bool remove(const value_type &X)
Remove an item from the set vector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
SlotIndex - An opaque wrapper around machine indexes.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool regsOverlap(Register RegA, Register RegB) const
Returns true if the two registers are equal or alias each other.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.