10b57cec5SDimitry Andric //===-- AArch64PBQPRegAlloc.cpp - AArch64 specific PBQP constraints -------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // This file contains the AArch64 / Cortex-A57 specific register allocation 90b57cec5SDimitry Andric // constraints for use by the PBQP register allocator. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric // It is essentially a transcription of what is contained in 120b57cec5SDimitry Andric // AArch64A57FPLoadBalancing, which tries to use a balanced 130b57cec5SDimitry Andric // mix of odd and even D-registers when performing a critical sequence of 140b57cec5SDimitry Andric // independent, non-quadword FP/ASIMD floating-point multiply-accumulates. 150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "AArch64PBQPRegAlloc.h" 180b57cec5SDimitry Andric #include "AArch64.h" 19*0fca6ea1SDimitry Andric #include "AArch64InstrInfo.h" 200b57cec5SDimitry Andric #include "AArch64RegisterInfo.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 250b57cec5SDimitry Andric #include "llvm/CodeGen/RegAllocPBQP.h" 260b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 270b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 290b57cec5SDimitry Andric 30fe6060f1SDimitry Andric #define DEBUG_TYPE "aarch64-pbqp" 31fe6060f1SDimitry Andric 320b57cec5SDimitry Andric using namespace llvm; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric namespace { 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric bool isOdd(unsigned reg) { 370b57cec5SDimitry Andric switch (reg) { 380b57cec5SDimitry Andric default: 390b57cec5SDimitry Andric llvm_unreachable("Register is not from the expected class !"); 400b57cec5SDimitry Andric case AArch64::S1: 410b57cec5SDimitry Andric case AArch64::S3: 420b57cec5SDimitry Andric case AArch64::S5: 430b57cec5SDimitry Andric case AArch64::S7: 440b57cec5SDimitry Andric case AArch64::S9: 450b57cec5SDimitry Andric case AArch64::S11: 460b57cec5SDimitry Andric case AArch64::S13: 470b57cec5SDimitry Andric case AArch64::S15: 480b57cec5SDimitry Andric case AArch64::S17: 490b57cec5SDimitry Andric case AArch64::S19: 500b57cec5SDimitry Andric case AArch64::S21: 510b57cec5SDimitry Andric case AArch64::S23: 520b57cec5SDimitry Andric case AArch64::S25: 530b57cec5SDimitry Andric case AArch64::S27: 540b57cec5SDimitry Andric case AArch64::S29: 550b57cec5SDimitry Andric case AArch64::S31: 560b57cec5SDimitry Andric case AArch64::D1: 570b57cec5SDimitry Andric case AArch64::D3: 580b57cec5SDimitry Andric case AArch64::D5: 590b57cec5SDimitry Andric case AArch64::D7: 600b57cec5SDimitry Andric case AArch64::D9: 610b57cec5SDimitry Andric case AArch64::D11: 620b57cec5SDimitry Andric case AArch64::D13: 630b57cec5SDimitry Andric case AArch64::D15: 640b57cec5SDimitry Andric case AArch64::D17: 650b57cec5SDimitry Andric case AArch64::D19: 660b57cec5SDimitry Andric case AArch64::D21: 670b57cec5SDimitry Andric case AArch64::D23: 680b57cec5SDimitry Andric case AArch64::D25: 690b57cec5SDimitry Andric case AArch64::D27: 700b57cec5SDimitry Andric case AArch64::D29: 710b57cec5SDimitry Andric case AArch64::D31: 720b57cec5SDimitry Andric case AArch64::Q1: 730b57cec5SDimitry Andric case AArch64::Q3: 740b57cec5SDimitry Andric case AArch64::Q5: 750b57cec5SDimitry Andric case AArch64::Q7: 760b57cec5SDimitry Andric case AArch64::Q9: 770b57cec5SDimitry Andric case AArch64::Q11: 780b57cec5SDimitry Andric case AArch64::Q13: 790b57cec5SDimitry Andric case AArch64::Q15: 800b57cec5SDimitry Andric case AArch64::Q17: 810b57cec5SDimitry Andric case AArch64::Q19: 820b57cec5SDimitry Andric case AArch64::Q21: 830b57cec5SDimitry Andric case AArch64::Q23: 840b57cec5SDimitry Andric case AArch64::Q25: 850b57cec5SDimitry Andric case AArch64::Q27: 860b57cec5SDimitry Andric case AArch64::Q29: 870b57cec5SDimitry Andric case AArch64::Q31: 880b57cec5SDimitry Andric return true; 890b57cec5SDimitry Andric case AArch64::S0: 900b57cec5SDimitry Andric case AArch64::S2: 910b57cec5SDimitry Andric case AArch64::S4: 920b57cec5SDimitry Andric case AArch64::S6: 930b57cec5SDimitry Andric case AArch64::S8: 940b57cec5SDimitry Andric case AArch64::S10: 950b57cec5SDimitry Andric case AArch64::S12: 960b57cec5SDimitry Andric case AArch64::S14: 970b57cec5SDimitry Andric case AArch64::S16: 980b57cec5SDimitry Andric case AArch64::S18: 990b57cec5SDimitry Andric case AArch64::S20: 1000b57cec5SDimitry Andric case AArch64::S22: 1010b57cec5SDimitry Andric case AArch64::S24: 1020b57cec5SDimitry Andric case AArch64::S26: 1030b57cec5SDimitry Andric case AArch64::S28: 1040b57cec5SDimitry Andric case AArch64::S30: 1050b57cec5SDimitry Andric case AArch64::D0: 1060b57cec5SDimitry Andric case AArch64::D2: 1070b57cec5SDimitry Andric case AArch64::D4: 1080b57cec5SDimitry Andric case AArch64::D6: 1090b57cec5SDimitry Andric case AArch64::D8: 1100b57cec5SDimitry Andric case AArch64::D10: 1110b57cec5SDimitry Andric case AArch64::D12: 1120b57cec5SDimitry Andric case AArch64::D14: 1130b57cec5SDimitry Andric case AArch64::D16: 1140b57cec5SDimitry Andric case AArch64::D18: 1150b57cec5SDimitry Andric case AArch64::D20: 1160b57cec5SDimitry Andric case AArch64::D22: 1170b57cec5SDimitry Andric case AArch64::D24: 1180b57cec5SDimitry Andric case AArch64::D26: 1190b57cec5SDimitry Andric case AArch64::D28: 1200b57cec5SDimitry Andric case AArch64::D30: 1210b57cec5SDimitry Andric case AArch64::Q0: 1220b57cec5SDimitry Andric case AArch64::Q2: 1230b57cec5SDimitry Andric case AArch64::Q4: 1240b57cec5SDimitry Andric case AArch64::Q6: 1250b57cec5SDimitry Andric case AArch64::Q8: 1260b57cec5SDimitry Andric case AArch64::Q10: 1270b57cec5SDimitry Andric case AArch64::Q12: 1280b57cec5SDimitry Andric case AArch64::Q14: 1290b57cec5SDimitry Andric case AArch64::Q16: 1300b57cec5SDimitry Andric case AArch64::Q18: 1310b57cec5SDimitry Andric case AArch64::Q20: 1320b57cec5SDimitry Andric case AArch64::Q22: 1330b57cec5SDimitry Andric case AArch64::Q24: 1340b57cec5SDimitry Andric case AArch64::Q26: 1350b57cec5SDimitry Andric case AArch64::Q28: 1360b57cec5SDimitry Andric case AArch64::Q30: 1370b57cec5SDimitry Andric return false; 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric bool haveSameParity(unsigned reg1, unsigned reg2) { 143*0fca6ea1SDimitry Andric assert(AArch64InstrInfo::isFpOrNEON(reg1) && 144*0fca6ea1SDimitry Andric "Expecting an FP register for reg1"); 145*0fca6ea1SDimitry Andric assert(AArch64InstrInfo::isFpOrNEON(reg2) && 146*0fca6ea1SDimitry Andric "Expecting an FP register for reg2"); 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric return isOdd(reg1) == isOdd(reg2); 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric bool A57ChainingConstraint::addIntraChainConstraint(PBQPRAGraph &G, unsigned Rd, 1540b57cec5SDimitry Andric unsigned Ra) { 1550b57cec5SDimitry Andric if (Rd == Ra) 1560b57cec5SDimitry Andric return false; 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric LiveIntervals &LIs = G.getMetadata().LIS; 1590b57cec5SDimitry Andric 1608bcb0991SDimitry Andric if (Register::isPhysicalRegister(Rd) || Register::isPhysicalRegister(Ra)) { 1618bcb0991SDimitry Andric LLVM_DEBUG(dbgs() << "Rd is a physical reg:" 1628bcb0991SDimitry Andric << Register::isPhysicalRegister(Rd) << '\n'); 1638bcb0991SDimitry Andric LLVM_DEBUG(dbgs() << "Ra is a physical reg:" 1648bcb0991SDimitry Andric << Register::isPhysicalRegister(Ra) << '\n'); 1650b57cec5SDimitry Andric return false; 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric PBQPRAGraph::NodeId node1 = G.getMetadata().getNodeIdForVReg(Rd); 1690b57cec5SDimitry Andric PBQPRAGraph::NodeId node2 = G.getMetadata().getNodeIdForVReg(Ra); 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRdAllowed = 1720b57cec5SDimitry Andric &G.getNodeMetadata(node1).getAllowedRegs(); 1730b57cec5SDimitry Andric const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRaAllowed = 1740b57cec5SDimitry Andric &G.getNodeMetadata(node2).getAllowedRegs(); 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric PBQPRAGraph::EdgeId edge = G.findEdge(node1, node2); 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric // The edge does not exist. Create one with the appropriate interference 1790b57cec5SDimitry Andric // costs. 1800b57cec5SDimitry Andric if (edge == G.invalidEdgeId()) { 1810b57cec5SDimitry Andric const LiveInterval &ld = LIs.getInterval(Rd); 1820b57cec5SDimitry Andric const LiveInterval &la = LIs.getInterval(Ra); 1830b57cec5SDimitry Andric bool livesOverlap = ld.overlaps(la); 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric PBQPRAGraph::RawMatrix costs(vRdAllowed->size() + 1, 1860b57cec5SDimitry Andric vRaAllowed->size() + 1, 0); 1870b57cec5SDimitry Andric for (unsigned i = 0, ie = vRdAllowed->size(); i != ie; ++i) { 1880b57cec5SDimitry Andric unsigned pRd = (*vRdAllowed)[i]; 1890b57cec5SDimitry Andric for (unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) { 1900b57cec5SDimitry Andric unsigned pRa = (*vRaAllowed)[j]; 1910b57cec5SDimitry Andric if (livesOverlap && TRI->regsOverlap(pRd, pRa)) 1920b57cec5SDimitry Andric costs[i + 1][j + 1] = std::numeric_limits<PBQP::PBQPNum>::infinity(); 1930b57cec5SDimitry Andric else 1940b57cec5SDimitry Andric costs[i + 1][j + 1] = haveSameParity(pRd, pRa) ? 0.0 : 1.0; 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric G.addEdge(node1, node2, std::move(costs)); 1980b57cec5SDimitry Andric return true; 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric if (G.getEdgeNode1Id(edge) == node2) { 2020b57cec5SDimitry Andric std::swap(node1, node2); 2030b57cec5SDimitry Andric std::swap(vRdAllowed, vRaAllowed); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric // Enforce minCost(sameParity(RaClass)) > maxCost(otherParity(RdClass)) 2070b57cec5SDimitry Andric PBQPRAGraph::RawMatrix costs(G.getEdgeCosts(edge)); 2080b57cec5SDimitry Andric for (unsigned i = 0, ie = vRdAllowed->size(); i != ie; ++i) { 2090b57cec5SDimitry Andric unsigned pRd = (*vRdAllowed)[i]; 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric // Get the maximum cost (excluding unallocatable reg) for same parity 2120b57cec5SDimitry Andric // registers 2130b57cec5SDimitry Andric PBQP::PBQPNum sameParityMax = std::numeric_limits<PBQP::PBQPNum>::min(); 2140b57cec5SDimitry Andric for (unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) { 2150b57cec5SDimitry Andric unsigned pRa = (*vRaAllowed)[j]; 2160b57cec5SDimitry Andric if (haveSameParity(pRd, pRa)) 2170b57cec5SDimitry Andric if (costs[i + 1][j + 1] != 2180b57cec5SDimitry Andric std::numeric_limits<PBQP::PBQPNum>::infinity() && 2190b57cec5SDimitry Andric costs[i + 1][j + 1] > sameParityMax) 2200b57cec5SDimitry Andric sameParityMax = costs[i + 1][j + 1]; 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric // Ensure all registers with a different parity have a higher cost 2240b57cec5SDimitry Andric // than sameParityMax 2250b57cec5SDimitry Andric for (unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) { 2260b57cec5SDimitry Andric unsigned pRa = (*vRaAllowed)[j]; 2270b57cec5SDimitry Andric if (!haveSameParity(pRd, pRa)) 2280b57cec5SDimitry Andric if (sameParityMax > costs[i + 1][j + 1]) 2290b57cec5SDimitry Andric costs[i + 1][j + 1] = sameParityMax + 1.0; 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric G.updateEdgeCosts(edge, std::move(costs)); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric return true; 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric void A57ChainingConstraint::addInterChainConstraint(PBQPRAGraph &G, unsigned Rd, 2380b57cec5SDimitry Andric unsigned Ra) { 2390b57cec5SDimitry Andric LiveIntervals &LIs = G.getMetadata().LIS; 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric // Do some Chain management 2420b57cec5SDimitry Andric if (Chains.count(Ra)) { 2430b57cec5SDimitry Andric if (Rd != Ra) { 2440b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Moving acc chain from " << printReg(Ra, TRI) 2450b57cec5SDimitry Andric << " to " << printReg(Rd, TRI) << '\n';); 2460b57cec5SDimitry Andric Chains.remove(Ra); 2470b57cec5SDimitry Andric Chains.insert(Rd); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric } else { 2500b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Creating new acc chain for " << printReg(Rd, TRI) 2510b57cec5SDimitry Andric << '\n';); 2520b57cec5SDimitry Andric Chains.insert(Rd); 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric PBQPRAGraph::NodeId node1 = G.getMetadata().getNodeIdForVReg(Rd); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric const LiveInterval &ld = LIs.getInterval(Rd); 2580b57cec5SDimitry Andric for (auto r : Chains) { 2590b57cec5SDimitry Andric // Skip self 2600b57cec5SDimitry Andric if (r == Rd) 2610b57cec5SDimitry Andric continue; 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric const LiveInterval &lr = LIs.getInterval(r); 2640b57cec5SDimitry Andric if (ld.overlaps(lr)) { 2650b57cec5SDimitry Andric const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRdAllowed = 2660b57cec5SDimitry Andric &G.getNodeMetadata(node1).getAllowedRegs(); 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric PBQPRAGraph::NodeId node2 = G.getMetadata().getNodeIdForVReg(r); 2690b57cec5SDimitry Andric const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRrAllowed = 2700b57cec5SDimitry Andric &G.getNodeMetadata(node2).getAllowedRegs(); 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric PBQPRAGraph::EdgeId edge = G.findEdge(node1, node2); 2730b57cec5SDimitry Andric assert(edge != G.invalidEdgeId() && 2740b57cec5SDimitry Andric "PBQP error ! The edge should exist !"); 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Refining constraint !\n";); 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric if (G.getEdgeNode1Id(edge) == node2) { 2790b57cec5SDimitry Andric std::swap(node1, node2); 2800b57cec5SDimitry Andric std::swap(vRdAllowed, vRrAllowed); 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric // Enforce that cost is higher with all other Chains of the same parity 2840b57cec5SDimitry Andric PBQP::Matrix costs(G.getEdgeCosts(edge)); 2850b57cec5SDimitry Andric for (unsigned i = 0, ie = vRdAllowed->size(); i != ie; ++i) { 2860b57cec5SDimitry Andric unsigned pRd = (*vRdAllowed)[i]; 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric // Get the maximum cost (excluding unallocatable reg) for all other 2890b57cec5SDimitry Andric // parity registers 2900b57cec5SDimitry Andric PBQP::PBQPNum sameParityMax = std::numeric_limits<PBQP::PBQPNum>::min(); 2910b57cec5SDimitry Andric for (unsigned j = 0, je = vRrAllowed->size(); j != je; ++j) { 2920b57cec5SDimitry Andric unsigned pRa = (*vRrAllowed)[j]; 2930b57cec5SDimitry Andric if (!haveSameParity(pRd, pRa)) 2940b57cec5SDimitry Andric if (costs[i + 1][j + 1] != 2950b57cec5SDimitry Andric std::numeric_limits<PBQP::PBQPNum>::infinity() && 2960b57cec5SDimitry Andric costs[i + 1][j + 1] > sameParityMax) 2970b57cec5SDimitry Andric sameParityMax = costs[i + 1][j + 1]; 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric // Ensure all registers with same parity have a higher cost 3010b57cec5SDimitry Andric // than sameParityMax 3020b57cec5SDimitry Andric for (unsigned j = 0, je = vRrAllowed->size(); j != je; ++j) { 3030b57cec5SDimitry Andric unsigned pRa = (*vRrAllowed)[j]; 3040b57cec5SDimitry Andric if (haveSameParity(pRd, pRa)) 3050b57cec5SDimitry Andric if (sameParityMax > costs[i + 1][j + 1]) 3060b57cec5SDimitry Andric costs[i + 1][j + 1] = sameParityMax + 1.0; 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric } 3090b57cec5SDimitry Andric G.updateEdgeCosts(edge, std::move(costs)); 3100b57cec5SDimitry Andric } 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric static bool regJustKilledBefore(const LiveIntervals &LIs, unsigned reg, 3150b57cec5SDimitry Andric const MachineInstr &MI) { 3160b57cec5SDimitry Andric const LiveInterval &LI = LIs.getInterval(reg); 3170b57cec5SDimitry Andric SlotIndex SI = LIs.getInstructionIndex(MI); 3180b57cec5SDimitry Andric return LI.expiredAt(SI); 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric void A57ChainingConstraint::apply(PBQPRAGraph &G) { 3220b57cec5SDimitry Andric const MachineFunction &MF = G.getMetadata().MF; 3230b57cec5SDimitry Andric LiveIntervals &LIs = G.getMetadata().LIS; 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric TRI = MF.getSubtarget().getRegisterInfo(); 3260b57cec5SDimitry Andric LLVM_DEBUG(MF.dump()); 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric for (const auto &MBB: MF) { 3290b57cec5SDimitry Andric Chains.clear(); // FIXME: really needed ? Could not work at MF level ? 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric for (const auto &MI: MBB) { 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric // Forget Chains which have expired 3340b57cec5SDimitry Andric for (auto r : Chains) { 3350b57cec5SDimitry Andric SmallVector<unsigned, 8> toDel; 3360b57cec5SDimitry Andric if(regJustKilledBefore(LIs, r, MI)) { 3370b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Killing chain " << printReg(r, TRI) << " at "; 3380b57cec5SDimitry Andric MI.print(dbgs());); 3390b57cec5SDimitry Andric toDel.push_back(r); 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric while (!toDel.empty()) { 3430b57cec5SDimitry Andric Chains.remove(toDel.back()); 3440b57cec5SDimitry Andric toDel.pop_back(); 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric switch (MI.getOpcode()) { 3490b57cec5SDimitry Andric case AArch64::FMSUBSrrr: 3500b57cec5SDimitry Andric case AArch64::FMADDSrrr: 3510b57cec5SDimitry Andric case AArch64::FNMSUBSrrr: 3520b57cec5SDimitry Andric case AArch64::FNMADDSrrr: 3530b57cec5SDimitry Andric case AArch64::FMSUBDrrr: 3540b57cec5SDimitry Andric case AArch64::FMADDDrrr: 3550b57cec5SDimitry Andric case AArch64::FNMSUBDrrr: 3560b57cec5SDimitry Andric case AArch64::FNMADDDrrr: { 3578bcb0991SDimitry Andric Register Rd = MI.getOperand(0).getReg(); 3588bcb0991SDimitry Andric Register Ra = MI.getOperand(3).getReg(); 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric if (addIntraChainConstraint(G, Rd, Ra)) 3610b57cec5SDimitry Andric addInterChainConstraint(G, Rd, Ra); 3620b57cec5SDimitry Andric break; 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric case AArch64::FMLAv2f32: 3660b57cec5SDimitry Andric case AArch64::FMLSv2f32: { 3678bcb0991SDimitry Andric Register Rd = MI.getOperand(0).getReg(); 3680b57cec5SDimitry Andric addInterChainConstraint(G, Rd, Rd); 3690b57cec5SDimitry Andric break; 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric default: 3730b57cec5SDimitry Andric break; 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric } 378