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,
156 LiveIntervals &LIs =
G.getMetadata().LIS;
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];
189 if (livesOverlap && TRI->regsOverlap(pRd, pRa))
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,
237 LiveIntervals &LIs =
G.getMetadata().LIS;
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) {
282 PBQP::Matrix costs(
G.getEdgeCosts(edge));
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);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool regJustKilledBefore(const LiveIntervals &LIs, unsigned reg, const MachineInstr &MI)
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 RegAllocSolverImpl::RawMatrix RawMatrix
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.
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.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
#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.
PBQP::RegAlloc::PBQPRAGraph PBQPRAGraph
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI 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.