30#define DEBUG_TYPE "aarch64-pbqp"
36bool isOdd(
unsigned reg) {
142bool haveSameParity(
unsigned reg1,
unsigned reg2) {
144 "Expecting an FP register for reg1");
146 "Expecting an FP register for reg2");
148 return isOdd(reg1) == isOdd(reg2);
153bool A57ChainingConstraint::addIntraChainConstraint(
PBQPRAGraph &
G,
unsigned Rd,
171 const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRdAllowed =
172 &
G.getNodeMetadata(node1).getAllowedRegs();
173 const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRaAllowed =
174 &
G.getNodeMetadata(node2).getAllowedRegs();
180 if (edge ==
G.invalidEdgeId()) {
183 bool livesOverlap = ld.
overlaps(la);
186 vRaAllowed->size() + 1, 0);
187 for (
unsigned i = 0, ie = vRdAllowed->size(); i != ie; ++i) {
188 unsigned pRd = (*vRdAllowed)[i];
189 for (
unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) {
190 unsigned pRa = (*vRaAllowed)[
j];
192 costs[i + 1][
j + 1] = std::numeric_limits<PBQP::PBQPNum>::infinity();
194 costs[i + 1][
j + 1] = haveSameParity(pRd, pRa) ? 0.0 : 1.0;
197 G.addEdge(node1, node2, std::move(costs));
201 if (
G.getEdgeNode1Id(edge) == node2) {
208 for (
unsigned i = 0, ie = vRdAllowed->size(); i != ie; ++i) {
209 unsigned pRd = (*vRdAllowed)[i];
213 PBQP::PBQPNum sameParityMax = std::numeric_limits<PBQP::PBQPNum>::min();
214 for (
unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) {
215 unsigned pRa = (*vRaAllowed)[
j];
216 if (haveSameParity(pRd, pRa))
217 if (costs[i + 1][j + 1] !=
218 std::numeric_limits<PBQP::PBQPNum>::infinity() &&
219 costs[i + 1][j + 1] > sameParityMax)
220 sameParityMax = costs[i + 1][
j + 1];
225 for (
unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) {
226 unsigned pRa = (*vRaAllowed)[
j];
227 if (!haveSameParity(pRd, pRa))
228 if (sameParityMax > costs[i + 1][j + 1])
229 costs[i + 1][
j + 1] = sameParityMax + 1.0;
232 G.updateEdgeCosts(edge, std::move(costs));
237void A57ChainingConstraint::addInterChainConstraint(
PBQPRAGraph &
G,
unsigned Rd,
242 if (Chains.
count(Ra)) {
245 <<
" to " <<
printReg(Rd, TRI) <<
'\n';);
258 for (
auto r : Chains) {
265 const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRdAllowed =
266 &
G.getNodeMetadata(node1).getAllowedRegs();
269 const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRrAllowed =
270 &
G.getNodeMetadata(node2).getAllowedRegs();
273 assert(edge !=
G.invalidEdgeId() &&
274 "PBQP error ! The edge should exist !");
278 if (
G.getEdgeNode1Id(edge) == node2) {
285 for (
unsigned i = 0, ie = vRdAllowed->size(); i != ie; ++i) {
286 unsigned pRd = (*vRdAllowed)[i];
290 PBQP::PBQPNum sameParityMax = std::numeric_limits<PBQP::PBQPNum>::min();
291 for (
unsigned j = 0, je = vRrAllowed->size(); j != je; ++j) {
292 unsigned pRa = (*vRrAllowed)[
j];
293 if (!haveSameParity(pRd, pRa))
294 if (costs[i + 1][j + 1] !=
295 std::numeric_limits<PBQP::PBQPNum>::infinity() &&
296 costs[i + 1][j + 1] > sameParityMax)
297 sameParityMax = costs[i + 1][
j + 1];
302 for (
unsigned j = 0, je = vRrAllowed->size(); j != je; ++j) {
303 unsigned pRa = (*vRrAllowed)[
j];
304 if (haveSameParity(pRd, pRa))
305 if (sameParityMax > costs[i + 1][j + 1])
306 costs[i + 1][
j + 1] = sameParityMax + 1.0;
309 G.updateEdgeCosts(edge, std::move(costs));
328 for (
const auto &
MBB: MF) {
331 for (
const auto &
MI:
MBB) {
334 for (
auto r : Chains) {
342 while (!toDel.
empty()) {
343 Chains.remove(toDel.
back());
348 switch (
MI.getOpcode()) {
349 case AArch64::FMSUBSrrr:
350 case AArch64::FMADDSrrr:
351 case AArch64::FNMSUBSrrr:
352 case AArch64::FNMADDSrrr:
353 case AArch64::FMSUBDrrr:
354 case AArch64::FMADDDrrr:
355 case AArch64::FNMSUBDrrr:
356 case AArch64::FNMADDDrrr: {
360 if (addIntraChainConstraint(
G, Rd, Ra))
361 addInterChainConstraint(
G, Rd, Ra);
365 case AArch64::FMLAv2f32:
366 case AArch64::FMLSv2f32: {
368 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
static bool isFpOrNEON(Register Reg)
Returns whether the physical register is FP or NEON.
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 constexpr bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
bool remove(const value_type &X)
Remove an item from the set vector.
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
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.