28#define DEBUG_TYPE "aarch64-pbqp"
34bool isOdd(
unsigned reg) {
140bool haveSameParity(
unsigned reg1,
unsigned reg2) {
142 "Expecting an FP register for reg1");
144 "Expecting an FP register for reg2");
146 return isOdd(reg1) == isOdd(reg2);
151bool A57ChainingConstraint::addIntraChainConstraint(
PBQPRAGraph &
G,
unsigned Rd,
169 const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRdAllowed =
170 &
G.getNodeMetadata(node1).getAllowedRegs();
171 const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRaAllowed =
172 &
G.getNodeMetadata(node2).getAllowedRegs();
178 if (edge ==
G.invalidEdgeId()) {
181 bool livesOverlap = ld.
overlaps(la);
184 vRaAllowed->size() + 1, 0);
185 for (
unsigned i = 0, ie = vRdAllowed->size(); i != ie; ++i) {
186 unsigned pRd = (*vRdAllowed)[i];
187 for (
unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) {
188 unsigned pRa = (*vRaAllowed)[
j];
190 costs[i + 1][
j + 1] = std::numeric_limits<PBQP::PBQPNum>::infinity();
192 costs[i + 1][
j + 1] = haveSameParity(pRd, pRa) ? 0.0 : 1.0;
195 G.addEdge(node1, node2, std::move(costs));
199 if (
G.getEdgeNode1Id(edge) == node2) {
206 for (
unsigned i = 0, ie = vRdAllowed->size(); i != ie; ++i) {
207 unsigned pRd = (*vRdAllowed)[i];
211 PBQP::PBQPNum sameParityMax = std::numeric_limits<PBQP::PBQPNum>::min();
212 for (
unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) {
213 unsigned pRa = (*vRaAllowed)[
j];
214 if (haveSameParity(pRd, pRa))
215 if (costs[i + 1][j + 1] !=
216 std::numeric_limits<PBQP::PBQPNum>::infinity() &&
217 costs[i + 1][j + 1] > sameParityMax)
218 sameParityMax = costs[i + 1][
j + 1];
223 for (
unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) {
224 unsigned pRa = (*vRaAllowed)[
j];
225 if (!haveSameParity(pRd, pRa))
226 if (sameParityMax > costs[i + 1][j + 1])
227 costs[i + 1][
j + 1] = sameParityMax + 1.0;
230 G.updateEdgeCosts(edge, std::move(costs));
235void A57ChainingConstraint::addInterChainConstraint(
PBQPRAGraph &
G,
unsigned Rd,
240 if (Chains.
count(Ra)) {
243 <<
" to " <<
printReg(Rd, TRI) <<
'\n');
256 for (
auto r : Chains) {
263 const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRdAllowed =
264 &
G.getNodeMetadata(node1).getAllowedRegs();
267 const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRrAllowed =
268 &
G.getNodeMetadata(node2).getAllowedRegs();
271 assert(edge !=
G.invalidEdgeId() &&
272 "PBQP error ! The edge should exist !");
276 if (
G.getEdgeNode1Id(edge) == node2) {
283 for (
unsigned i = 0, ie = vRdAllowed->size(); i != ie; ++i) {
284 unsigned pRd = (*vRdAllowed)[i];
288 PBQP::PBQPNum sameParityMax = std::numeric_limits<PBQP::PBQPNum>::min();
289 for (
unsigned j = 0, je = vRrAllowed->size(); j != je; ++j) {
290 unsigned pRa = (*vRrAllowed)[
j];
291 if (!haveSameParity(pRd, pRa))
292 if (costs[i + 1][j + 1] !=
293 std::numeric_limits<PBQP::PBQPNum>::infinity() &&
294 costs[i + 1][j + 1] > sameParityMax)
295 sameParityMax = costs[i + 1][
j + 1];
300 for (
unsigned j = 0, je = vRrAllowed->size(); j != je; ++j) {
301 unsigned pRa = (*vRrAllowed)[
j];
302 if (haveSameParity(pRd, pRa))
303 if (sameParityMax > costs[i + 1][j + 1])
304 costs[i + 1][
j + 1] = sameParityMax + 1.0;
307 G.updateEdgeCosts(edge, std::move(costs));
326 for (
const auto &
MBB: MF) {
329 for (
const auto &
MI:
MBB) {
332 for (
auto r : Chains) {
340 while (!toDel.
empty()) {
341 Chains.remove(toDel.
back());
346 switch (
MI.getOpcode()) {
347 case AArch64::FMSUBSrrr:
348 case AArch64::FMADDSrrr:
349 case AArch64::FNMSUBSrrr:
350 case AArch64::FNMADDSrrr:
351 case AArch64::FMSUBDrrr:
352 case AArch64::FMADDDrrr:
353 case AArch64::FNMSUBDrrr:
354 case AArch64::FNMADDDrrr: {
358 if (addIntraChainConstraint(
G, Rd, Ra))
359 addInterChainConstraint(
G, Rd, Ra);
363 case AArch64::FMLAv2f32:
364 case AArch64::FMLSv2f32: {
366 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.