1*9880d681SAndroid Build Coastguard Worker //===- AArch64InstrInfo.cpp - AArch64 Instruction Information -------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file contains the AArch64 implementation of the TargetInstrInfo class.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Worker #include "AArch64InstrInfo.h"
15*9880d681SAndroid Build Coastguard Worker #include "AArch64Subtarget.h"
16*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/AArch64AddressingModes.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineMemOperand.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/PseudoSourceValue.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetRegistry.h"
25*9880d681SAndroid Build Coastguard Worker #include <algorithm>
26*9880d681SAndroid Build Coastguard Worker
27*9880d681SAndroid Build Coastguard Worker using namespace llvm;
28*9880d681SAndroid Build Coastguard Worker
29*9880d681SAndroid Build Coastguard Worker #define GET_INSTRINFO_CTOR_DTOR
30*9880d681SAndroid Build Coastguard Worker #include "AArch64GenInstrInfo.inc"
31*9880d681SAndroid Build Coastguard Worker
32*9880d681SAndroid Build Coastguard Worker static LLVM_CONSTEXPR MachineMemOperand::Flags MOSuppressPair =
33*9880d681SAndroid Build Coastguard Worker MachineMemOperand::MOTargetFlag1;
34*9880d681SAndroid Build Coastguard Worker
AArch64InstrInfo(const AArch64Subtarget & STI)35*9880d681SAndroid Build Coastguard Worker AArch64InstrInfo::AArch64InstrInfo(const AArch64Subtarget &STI)
36*9880d681SAndroid Build Coastguard Worker : AArch64GenInstrInfo(AArch64::ADJCALLSTACKDOWN, AArch64::ADJCALLSTACKUP),
37*9880d681SAndroid Build Coastguard Worker RI(STI.getTargetTriple()), Subtarget(STI) {}
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker /// GetInstSize - Return the number of bytes of code the specified
40*9880d681SAndroid Build Coastguard Worker /// instruction may be. This returns the maximum number of bytes.
GetInstSizeInBytes(const MachineInstr & MI) const41*9880d681SAndroid Build Coastguard Worker unsigned AArch64InstrInfo::GetInstSizeInBytes(const MachineInstr &MI) const {
42*9880d681SAndroid Build Coastguard Worker const MachineBasicBlock &MBB = *MI.getParent();
43*9880d681SAndroid Build Coastguard Worker const MachineFunction *MF = MBB.getParent();
44*9880d681SAndroid Build Coastguard Worker const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo();
45*9880d681SAndroid Build Coastguard Worker
46*9880d681SAndroid Build Coastguard Worker if (MI.getOpcode() == AArch64::INLINEASM)
47*9880d681SAndroid Build Coastguard Worker return getInlineAsmLength(MI.getOperand(0).getSymbolName(), *MAI);
48*9880d681SAndroid Build Coastguard Worker
49*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &Desc = MI.getDesc();
50*9880d681SAndroid Build Coastguard Worker switch (Desc.getOpcode()) {
51*9880d681SAndroid Build Coastguard Worker default:
52*9880d681SAndroid Build Coastguard Worker // Anything not explicitly designated otherwise is a nomal 4-byte insn.
53*9880d681SAndroid Build Coastguard Worker return 4;
54*9880d681SAndroid Build Coastguard Worker case TargetOpcode::DBG_VALUE:
55*9880d681SAndroid Build Coastguard Worker case TargetOpcode::EH_LABEL:
56*9880d681SAndroid Build Coastguard Worker case TargetOpcode::IMPLICIT_DEF:
57*9880d681SAndroid Build Coastguard Worker case TargetOpcode::KILL:
58*9880d681SAndroid Build Coastguard Worker return 0;
59*9880d681SAndroid Build Coastguard Worker }
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker llvm_unreachable("GetInstSizeInBytes()- Unable to determin insn size");
62*9880d681SAndroid Build Coastguard Worker }
63*9880d681SAndroid Build Coastguard Worker
parseCondBranch(MachineInstr * LastInst,MachineBasicBlock * & Target,SmallVectorImpl<MachineOperand> & Cond)64*9880d681SAndroid Build Coastguard Worker static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target,
65*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MachineOperand> &Cond) {
66*9880d681SAndroid Build Coastguard Worker // Block ends with fall-through condbranch.
67*9880d681SAndroid Build Coastguard Worker switch (LastInst->getOpcode()) {
68*9880d681SAndroid Build Coastguard Worker default:
69*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown branch instruction?");
70*9880d681SAndroid Build Coastguard Worker case AArch64::Bcc:
71*9880d681SAndroid Build Coastguard Worker Target = LastInst->getOperand(1).getMBB();
72*9880d681SAndroid Build Coastguard Worker Cond.push_back(LastInst->getOperand(0));
73*9880d681SAndroid Build Coastguard Worker break;
74*9880d681SAndroid Build Coastguard Worker case AArch64::CBZW:
75*9880d681SAndroid Build Coastguard Worker case AArch64::CBZX:
76*9880d681SAndroid Build Coastguard Worker case AArch64::CBNZW:
77*9880d681SAndroid Build Coastguard Worker case AArch64::CBNZX:
78*9880d681SAndroid Build Coastguard Worker Target = LastInst->getOperand(1).getMBB();
79*9880d681SAndroid Build Coastguard Worker Cond.push_back(MachineOperand::CreateImm(-1));
80*9880d681SAndroid Build Coastguard Worker Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
81*9880d681SAndroid Build Coastguard Worker Cond.push_back(LastInst->getOperand(0));
82*9880d681SAndroid Build Coastguard Worker break;
83*9880d681SAndroid Build Coastguard Worker case AArch64::TBZW:
84*9880d681SAndroid Build Coastguard Worker case AArch64::TBZX:
85*9880d681SAndroid Build Coastguard Worker case AArch64::TBNZW:
86*9880d681SAndroid Build Coastguard Worker case AArch64::TBNZX:
87*9880d681SAndroid Build Coastguard Worker Target = LastInst->getOperand(2).getMBB();
88*9880d681SAndroid Build Coastguard Worker Cond.push_back(MachineOperand::CreateImm(-1));
89*9880d681SAndroid Build Coastguard Worker Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
90*9880d681SAndroid Build Coastguard Worker Cond.push_back(LastInst->getOperand(0));
91*9880d681SAndroid Build Coastguard Worker Cond.push_back(LastInst->getOperand(1));
92*9880d681SAndroid Build Coastguard Worker }
93*9880d681SAndroid Build Coastguard Worker }
94*9880d681SAndroid Build Coastguard Worker
95*9880d681SAndroid Build Coastguard Worker // Branch analysis.
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const96*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::analyzeBranch(MachineBasicBlock &MBB,
97*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *&TBB,
98*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *&FBB,
99*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MachineOperand> &Cond,
100*9880d681SAndroid Build Coastguard Worker bool AllowModify) const {
101*9880d681SAndroid Build Coastguard Worker // If the block has no terminators, it just falls into the block after it.
102*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
103*9880d681SAndroid Build Coastguard Worker if (I == MBB.end())
104*9880d681SAndroid Build Coastguard Worker return false;
105*9880d681SAndroid Build Coastguard Worker
106*9880d681SAndroid Build Coastguard Worker if (!isUnpredicatedTerminator(*I))
107*9880d681SAndroid Build Coastguard Worker return false;
108*9880d681SAndroid Build Coastguard Worker
109*9880d681SAndroid Build Coastguard Worker // Get the last instruction in the block.
110*9880d681SAndroid Build Coastguard Worker MachineInstr *LastInst = &*I;
111*9880d681SAndroid Build Coastguard Worker
112*9880d681SAndroid Build Coastguard Worker // If there is only one terminator instruction, process it.
113*9880d681SAndroid Build Coastguard Worker unsigned LastOpc = LastInst->getOpcode();
114*9880d681SAndroid Build Coastguard Worker if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
115*9880d681SAndroid Build Coastguard Worker if (isUncondBranchOpcode(LastOpc)) {
116*9880d681SAndroid Build Coastguard Worker TBB = LastInst->getOperand(0).getMBB();
117*9880d681SAndroid Build Coastguard Worker return false;
118*9880d681SAndroid Build Coastguard Worker }
119*9880d681SAndroid Build Coastguard Worker if (isCondBranchOpcode(LastOpc)) {
120*9880d681SAndroid Build Coastguard Worker // Block ends with fall-through condbranch.
121*9880d681SAndroid Build Coastguard Worker parseCondBranch(LastInst, TBB, Cond);
122*9880d681SAndroid Build Coastguard Worker return false;
123*9880d681SAndroid Build Coastguard Worker }
124*9880d681SAndroid Build Coastguard Worker return true; // Can't handle indirect branch.
125*9880d681SAndroid Build Coastguard Worker }
126*9880d681SAndroid Build Coastguard Worker
127*9880d681SAndroid Build Coastguard Worker // Get the instruction before it if it is a terminator.
128*9880d681SAndroid Build Coastguard Worker MachineInstr *SecondLastInst = &*I;
129*9880d681SAndroid Build Coastguard Worker unsigned SecondLastOpc = SecondLastInst->getOpcode();
130*9880d681SAndroid Build Coastguard Worker
131*9880d681SAndroid Build Coastguard Worker // If AllowModify is true and the block ends with two or more unconditional
132*9880d681SAndroid Build Coastguard Worker // branches, delete all but the first unconditional branch.
133*9880d681SAndroid Build Coastguard Worker if (AllowModify && isUncondBranchOpcode(LastOpc)) {
134*9880d681SAndroid Build Coastguard Worker while (isUncondBranchOpcode(SecondLastOpc)) {
135*9880d681SAndroid Build Coastguard Worker LastInst->eraseFromParent();
136*9880d681SAndroid Build Coastguard Worker LastInst = SecondLastInst;
137*9880d681SAndroid Build Coastguard Worker LastOpc = LastInst->getOpcode();
138*9880d681SAndroid Build Coastguard Worker if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
139*9880d681SAndroid Build Coastguard Worker // Return now the only terminator is an unconditional branch.
140*9880d681SAndroid Build Coastguard Worker TBB = LastInst->getOperand(0).getMBB();
141*9880d681SAndroid Build Coastguard Worker return false;
142*9880d681SAndroid Build Coastguard Worker } else {
143*9880d681SAndroid Build Coastguard Worker SecondLastInst = &*I;
144*9880d681SAndroid Build Coastguard Worker SecondLastOpc = SecondLastInst->getOpcode();
145*9880d681SAndroid Build Coastguard Worker }
146*9880d681SAndroid Build Coastguard Worker }
147*9880d681SAndroid Build Coastguard Worker }
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker // If there are three terminators, we don't know what sort of block this is.
150*9880d681SAndroid Build Coastguard Worker if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))
151*9880d681SAndroid Build Coastguard Worker return true;
152*9880d681SAndroid Build Coastguard Worker
153*9880d681SAndroid Build Coastguard Worker // If the block ends with a B and a Bcc, handle it.
154*9880d681SAndroid Build Coastguard Worker if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
155*9880d681SAndroid Build Coastguard Worker parseCondBranch(SecondLastInst, TBB, Cond);
156*9880d681SAndroid Build Coastguard Worker FBB = LastInst->getOperand(0).getMBB();
157*9880d681SAndroid Build Coastguard Worker return false;
158*9880d681SAndroid Build Coastguard Worker }
159*9880d681SAndroid Build Coastguard Worker
160*9880d681SAndroid Build Coastguard Worker // If the block ends with two unconditional branches, handle it. The second
161*9880d681SAndroid Build Coastguard Worker // one is not executed, so remove it.
162*9880d681SAndroid Build Coastguard Worker if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
163*9880d681SAndroid Build Coastguard Worker TBB = SecondLastInst->getOperand(0).getMBB();
164*9880d681SAndroid Build Coastguard Worker I = LastInst;
165*9880d681SAndroid Build Coastguard Worker if (AllowModify)
166*9880d681SAndroid Build Coastguard Worker I->eraseFromParent();
167*9880d681SAndroid Build Coastguard Worker return false;
168*9880d681SAndroid Build Coastguard Worker }
169*9880d681SAndroid Build Coastguard Worker
170*9880d681SAndroid Build Coastguard Worker // ...likewise if it ends with an indirect branch followed by an unconditional
171*9880d681SAndroid Build Coastguard Worker // branch.
172*9880d681SAndroid Build Coastguard Worker if (isIndirectBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
173*9880d681SAndroid Build Coastguard Worker I = LastInst;
174*9880d681SAndroid Build Coastguard Worker if (AllowModify)
175*9880d681SAndroid Build Coastguard Worker I->eraseFromParent();
176*9880d681SAndroid Build Coastguard Worker return true;
177*9880d681SAndroid Build Coastguard Worker }
178*9880d681SAndroid Build Coastguard Worker
179*9880d681SAndroid Build Coastguard Worker // Otherwise, can't handle this.
180*9880d681SAndroid Build Coastguard Worker return true;
181*9880d681SAndroid Build Coastguard Worker }
182*9880d681SAndroid Build Coastguard Worker
ReverseBranchCondition(SmallVectorImpl<MachineOperand> & Cond) const183*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::ReverseBranchCondition(
184*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MachineOperand> &Cond) const {
185*9880d681SAndroid Build Coastguard Worker if (Cond[0].getImm() != -1) {
186*9880d681SAndroid Build Coastguard Worker // Regular Bcc
187*9880d681SAndroid Build Coastguard Worker AArch64CC::CondCode CC = (AArch64CC::CondCode)(int)Cond[0].getImm();
188*9880d681SAndroid Build Coastguard Worker Cond[0].setImm(AArch64CC::getInvertedCondCode(CC));
189*9880d681SAndroid Build Coastguard Worker } else {
190*9880d681SAndroid Build Coastguard Worker // Folded compare-and-branch
191*9880d681SAndroid Build Coastguard Worker switch (Cond[1].getImm()) {
192*9880d681SAndroid Build Coastguard Worker default:
193*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown conditional branch!");
194*9880d681SAndroid Build Coastguard Worker case AArch64::CBZW:
195*9880d681SAndroid Build Coastguard Worker Cond[1].setImm(AArch64::CBNZW);
196*9880d681SAndroid Build Coastguard Worker break;
197*9880d681SAndroid Build Coastguard Worker case AArch64::CBNZW:
198*9880d681SAndroid Build Coastguard Worker Cond[1].setImm(AArch64::CBZW);
199*9880d681SAndroid Build Coastguard Worker break;
200*9880d681SAndroid Build Coastguard Worker case AArch64::CBZX:
201*9880d681SAndroid Build Coastguard Worker Cond[1].setImm(AArch64::CBNZX);
202*9880d681SAndroid Build Coastguard Worker break;
203*9880d681SAndroid Build Coastguard Worker case AArch64::CBNZX:
204*9880d681SAndroid Build Coastguard Worker Cond[1].setImm(AArch64::CBZX);
205*9880d681SAndroid Build Coastguard Worker break;
206*9880d681SAndroid Build Coastguard Worker case AArch64::TBZW:
207*9880d681SAndroid Build Coastguard Worker Cond[1].setImm(AArch64::TBNZW);
208*9880d681SAndroid Build Coastguard Worker break;
209*9880d681SAndroid Build Coastguard Worker case AArch64::TBNZW:
210*9880d681SAndroid Build Coastguard Worker Cond[1].setImm(AArch64::TBZW);
211*9880d681SAndroid Build Coastguard Worker break;
212*9880d681SAndroid Build Coastguard Worker case AArch64::TBZX:
213*9880d681SAndroid Build Coastguard Worker Cond[1].setImm(AArch64::TBNZX);
214*9880d681SAndroid Build Coastguard Worker break;
215*9880d681SAndroid Build Coastguard Worker case AArch64::TBNZX:
216*9880d681SAndroid Build Coastguard Worker Cond[1].setImm(AArch64::TBZX);
217*9880d681SAndroid Build Coastguard Worker break;
218*9880d681SAndroid Build Coastguard Worker }
219*9880d681SAndroid Build Coastguard Worker }
220*9880d681SAndroid Build Coastguard Worker
221*9880d681SAndroid Build Coastguard Worker return false;
222*9880d681SAndroid Build Coastguard Worker }
223*9880d681SAndroid Build Coastguard Worker
RemoveBranch(MachineBasicBlock & MBB) const224*9880d681SAndroid Build Coastguard Worker unsigned AArch64InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
225*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
226*9880d681SAndroid Build Coastguard Worker if (I == MBB.end())
227*9880d681SAndroid Build Coastguard Worker return 0;
228*9880d681SAndroid Build Coastguard Worker
229*9880d681SAndroid Build Coastguard Worker if (!isUncondBranchOpcode(I->getOpcode()) &&
230*9880d681SAndroid Build Coastguard Worker !isCondBranchOpcode(I->getOpcode()))
231*9880d681SAndroid Build Coastguard Worker return 0;
232*9880d681SAndroid Build Coastguard Worker
233*9880d681SAndroid Build Coastguard Worker // Remove the branch.
234*9880d681SAndroid Build Coastguard Worker I->eraseFromParent();
235*9880d681SAndroid Build Coastguard Worker
236*9880d681SAndroid Build Coastguard Worker I = MBB.end();
237*9880d681SAndroid Build Coastguard Worker
238*9880d681SAndroid Build Coastguard Worker if (I == MBB.begin())
239*9880d681SAndroid Build Coastguard Worker return 1;
240*9880d681SAndroid Build Coastguard Worker --I;
241*9880d681SAndroid Build Coastguard Worker if (!isCondBranchOpcode(I->getOpcode()))
242*9880d681SAndroid Build Coastguard Worker return 1;
243*9880d681SAndroid Build Coastguard Worker
244*9880d681SAndroid Build Coastguard Worker // Remove the branch.
245*9880d681SAndroid Build Coastguard Worker I->eraseFromParent();
246*9880d681SAndroid Build Coastguard Worker return 2;
247*9880d681SAndroid Build Coastguard Worker }
248*9880d681SAndroid Build Coastguard Worker
instantiateCondBranch(MachineBasicBlock & MBB,const DebugLoc & DL,MachineBasicBlock * TBB,ArrayRef<MachineOperand> Cond) const249*9880d681SAndroid Build Coastguard Worker void AArch64InstrInfo::instantiateCondBranch(
250*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB, const DebugLoc &DL, MachineBasicBlock *TBB,
251*9880d681SAndroid Build Coastguard Worker ArrayRef<MachineOperand> Cond) const {
252*9880d681SAndroid Build Coastguard Worker if (Cond[0].getImm() != -1) {
253*9880d681SAndroid Build Coastguard Worker // Regular Bcc
254*9880d681SAndroid Build Coastguard Worker BuildMI(&MBB, DL, get(AArch64::Bcc)).addImm(Cond[0].getImm()).addMBB(TBB);
255*9880d681SAndroid Build Coastguard Worker } else {
256*9880d681SAndroid Build Coastguard Worker // Folded compare-and-branch
257*9880d681SAndroid Build Coastguard Worker // Note that we use addOperand instead of addReg to keep the flags.
258*9880d681SAndroid Build Coastguard Worker const MachineInstrBuilder MIB =
259*9880d681SAndroid Build Coastguard Worker BuildMI(&MBB, DL, get(Cond[1].getImm())).addOperand(Cond[2]);
260*9880d681SAndroid Build Coastguard Worker if (Cond.size() > 3)
261*9880d681SAndroid Build Coastguard Worker MIB.addImm(Cond[3].getImm());
262*9880d681SAndroid Build Coastguard Worker MIB.addMBB(TBB);
263*9880d681SAndroid Build Coastguard Worker }
264*9880d681SAndroid Build Coastguard Worker }
265*9880d681SAndroid Build Coastguard Worker
InsertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL) const266*9880d681SAndroid Build Coastguard Worker unsigned AArch64InstrInfo::InsertBranch(MachineBasicBlock &MBB,
267*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *TBB,
268*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *FBB,
269*9880d681SAndroid Build Coastguard Worker ArrayRef<MachineOperand> Cond,
270*9880d681SAndroid Build Coastguard Worker const DebugLoc &DL) const {
271*9880d681SAndroid Build Coastguard Worker // Shouldn't be a fall through.
272*9880d681SAndroid Build Coastguard Worker assert(TBB && "InsertBranch must not be told to insert a fallthrough");
273*9880d681SAndroid Build Coastguard Worker
274*9880d681SAndroid Build Coastguard Worker if (!FBB) {
275*9880d681SAndroid Build Coastguard Worker if (Cond.empty()) // Unconditional branch?
276*9880d681SAndroid Build Coastguard Worker BuildMI(&MBB, DL, get(AArch64::B)).addMBB(TBB);
277*9880d681SAndroid Build Coastguard Worker else
278*9880d681SAndroid Build Coastguard Worker instantiateCondBranch(MBB, DL, TBB, Cond);
279*9880d681SAndroid Build Coastguard Worker return 1;
280*9880d681SAndroid Build Coastguard Worker }
281*9880d681SAndroid Build Coastguard Worker
282*9880d681SAndroid Build Coastguard Worker // Two-way conditional branch.
283*9880d681SAndroid Build Coastguard Worker instantiateCondBranch(MBB, DL, TBB, Cond);
284*9880d681SAndroid Build Coastguard Worker BuildMI(&MBB, DL, get(AArch64::B)).addMBB(FBB);
285*9880d681SAndroid Build Coastguard Worker return 2;
286*9880d681SAndroid Build Coastguard Worker }
287*9880d681SAndroid Build Coastguard Worker
288*9880d681SAndroid Build Coastguard Worker // Find the original register that VReg is copied from.
removeCopies(const MachineRegisterInfo & MRI,unsigned VReg)289*9880d681SAndroid Build Coastguard Worker static unsigned removeCopies(const MachineRegisterInfo &MRI, unsigned VReg) {
290*9880d681SAndroid Build Coastguard Worker while (TargetRegisterInfo::isVirtualRegister(VReg)) {
291*9880d681SAndroid Build Coastguard Worker const MachineInstr *DefMI = MRI.getVRegDef(VReg);
292*9880d681SAndroid Build Coastguard Worker if (!DefMI->isFullCopy())
293*9880d681SAndroid Build Coastguard Worker return VReg;
294*9880d681SAndroid Build Coastguard Worker VReg = DefMI->getOperand(1).getReg();
295*9880d681SAndroid Build Coastguard Worker }
296*9880d681SAndroid Build Coastguard Worker return VReg;
297*9880d681SAndroid Build Coastguard Worker }
298*9880d681SAndroid Build Coastguard Worker
299*9880d681SAndroid Build Coastguard Worker // Determine if VReg is defined by an instruction that can be folded into a
300*9880d681SAndroid Build Coastguard Worker // csel instruction. If so, return the folded opcode, and the replacement
301*9880d681SAndroid Build Coastguard Worker // register.
canFoldIntoCSel(const MachineRegisterInfo & MRI,unsigned VReg,unsigned * NewVReg=nullptr)302*9880d681SAndroid Build Coastguard Worker static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg,
303*9880d681SAndroid Build Coastguard Worker unsigned *NewVReg = nullptr) {
304*9880d681SAndroid Build Coastguard Worker VReg = removeCopies(MRI, VReg);
305*9880d681SAndroid Build Coastguard Worker if (!TargetRegisterInfo::isVirtualRegister(VReg))
306*9880d681SAndroid Build Coastguard Worker return 0;
307*9880d681SAndroid Build Coastguard Worker
308*9880d681SAndroid Build Coastguard Worker bool Is64Bit = AArch64::GPR64allRegClass.hasSubClassEq(MRI.getRegClass(VReg));
309*9880d681SAndroid Build Coastguard Worker const MachineInstr *DefMI = MRI.getVRegDef(VReg);
310*9880d681SAndroid Build Coastguard Worker unsigned Opc = 0;
311*9880d681SAndroid Build Coastguard Worker unsigned SrcOpNum = 0;
312*9880d681SAndroid Build Coastguard Worker switch (DefMI->getOpcode()) {
313*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXri:
314*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWri:
315*9880d681SAndroid Build Coastguard Worker // if NZCV is used, do not fold.
316*9880d681SAndroid Build Coastguard Worker if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, true) == -1)
317*9880d681SAndroid Build Coastguard Worker return 0;
318*9880d681SAndroid Build Coastguard Worker // fall-through to ADDXri and ADDWri.
319*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXri:
320*9880d681SAndroid Build Coastguard Worker case AArch64::ADDWri:
321*9880d681SAndroid Build Coastguard Worker // add x, 1 -> csinc.
322*9880d681SAndroid Build Coastguard Worker if (!DefMI->getOperand(2).isImm() || DefMI->getOperand(2).getImm() != 1 ||
323*9880d681SAndroid Build Coastguard Worker DefMI->getOperand(3).getImm() != 0)
324*9880d681SAndroid Build Coastguard Worker return 0;
325*9880d681SAndroid Build Coastguard Worker SrcOpNum = 1;
326*9880d681SAndroid Build Coastguard Worker Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
327*9880d681SAndroid Build Coastguard Worker break;
328*9880d681SAndroid Build Coastguard Worker
329*9880d681SAndroid Build Coastguard Worker case AArch64::ORNXrr:
330*9880d681SAndroid Build Coastguard Worker case AArch64::ORNWrr: {
331*9880d681SAndroid Build Coastguard Worker // not x -> csinv, represented as orn dst, xzr, src.
332*9880d681SAndroid Build Coastguard Worker unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
333*9880d681SAndroid Build Coastguard Worker if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
334*9880d681SAndroid Build Coastguard Worker return 0;
335*9880d681SAndroid Build Coastguard Worker SrcOpNum = 2;
336*9880d681SAndroid Build Coastguard Worker Opc = Is64Bit ? AArch64::CSINVXr : AArch64::CSINVWr;
337*9880d681SAndroid Build Coastguard Worker break;
338*9880d681SAndroid Build Coastguard Worker }
339*9880d681SAndroid Build Coastguard Worker
340*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXrr:
341*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWrr:
342*9880d681SAndroid Build Coastguard Worker // if NZCV is used, do not fold.
343*9880d681SAndroid Build Coastguard Worker if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, true) == -1)
344*9880d681SAndroid Build Coastguard Worker return 0;
345*9880d681SAndroid Build Coastguard Worker // fall-through to SUBXrr and SUBWrr.
346*9880d681SAndroid Build Coastguard Worker case AArch64::SUBXrr:
347*9880d681SAndroid Build Coastguard Worker case AArch64::SUBWrr: {
348*9880d681SAndroid Build Coastguard Worker // neg x -> csneg, represented as sub dst, xzr, src.
349*9880d681SAndroid Build Coastguard Worker unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
350*9880d681SAndroid Build Coastguard Worker if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
351*9880d681SAndroid Build Coastguard Worker return 0;
352*9880d681SAndroid Build Coastguard Worker SrcOpNum = 2;
353*9880d681SAndroid Build Coastguard Worker Opc = Is64Bit ? AArch64::CSNEGXr : AArch64::CSNEGWr;
354*9880d681SAndroid Build Coastguard Worker break;
355*9880d681SAndroid Build Coastguard Worker }
356*9880d681SAndroid Build Coastguard Worker default:
357*9880d681SAndroid Build Coastguard Worker return 0;
358*9880d681SAndroid Build Coastguard Worker }
359*9880d681SAndroid Build Coastguard Worker assert(Opc && SrcOpNum && "Missing parameters");
360*9880d681SAndroid Build Coastguard Worker
361*9880d681SAndroid Build Coastguard Worker if (NewVReg)
362*9880d681SAndroid Build Coastguard Worker *NewVReg = DefMI->getOperand(SrcOpNum).getReg();
363*9880d681SAndroid Build Coastguard Worker return Opc;
364*9880d681SAndroid Build Coastguard Worker }
365*9880d681SAndroid Build Coastguard Worker
canInsertSelect(const MachineBasicBlock & MBB,ArrayRef<MachineOperand> Cond,unsigned TrueReg,unsigned FalseReg,int & CondCycles,int & TrueCycles,int & FalseCycles) const366*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::canInsertSelect(
367*9880d681SAndroid Build Coastguard Worker const MachineBasicBlock &MBB, ArrayRef<MachineOperand> Cond,
368*9880d681SAndroid Build Coastguard Worker unsigned TrueReg, unsigned FalseReg, int &CondCycles, int &TrueCycles,
369*9880d681SAndroid Build Coastguard Worker int &FalseCycles) const {
370*9880d681SAndroid Build Coastguard Worker // Check register classes.
371*9880d681SAndroid Build Coastguard Worker const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
372*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC =
373*9880d681SAndroid Build Coastguard Worker RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));
374*9880d681SAndroid Build Coastguard Worker if (!RC)
375*9880d681SAndroid Build Coastguard Worker return false;
376*9880d681SAndroid Build Coastguard Worker
377*9880d681SAndroid Build Coastguard Worker // Expanding cbz/tbz requires an extra cycle of latency on the condition.
378*9880d681SAndroid Build Coastguard Worker unsigned ExtraCondLat = Cond.size() != 1;
379*9880d681SAndroid Build Coastguard Worker
380*9880d681SAndroid Build Coastguard Worker // GPRs are handled by csel.
381*9880d681SAndroid Build Coastguard Worker // FIXME: Fold in x+1, -x, and ~x when applicable.
382*9880d681SAndroid Build Coastguard Worker if (AArch64::GPR64allRegClass.hasSubClassEq(RC) ||
383*9880d681SAndroid Build Coastguard Worker AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
384*9880d681SAndroid Build Coastguard Worker // Single-cycle csel, csinc, csinv, and csneg.
385*9880d681SAndroid Build Coastguard Worker CondCycles = 1 + ExtraCondLat;
386*9880d681SAndroid Build Coastguard Worker TrueCycles = FalseCycles = 1;
387*9880d681SAndroid Build Coastguard Worker if (canFoldIntoCSel(MRI, TrueReg))
388*9880d681SAndroid Build Coastguard Worker TrueCycles = 0;
389*9880d681SAndroid Build Coastguard Worker else if (canFoldIntoCSel(MRI, FalseReg))
390*9880d681SAndroid Build Coastguard Worker FalseCycles = 0;
391*9880d681SAndroid Build Coastguard Worker return true;
392*9880d681SAndroid Build Coastguard Worker }
393*9880d681SAndroid Build Coastguard Worker
394*9880d681SAndroid Build Coastguard Worker // Scalar floating point is handled by fcsel.
395*9880d681SAndroid Build Coastguard Worker // FIXME: Form fabs, fmin, and fmax when applicable.
396*9880d681SAndroid Build Coastguard Worker if (AArch64::FPR64RegClass.hasSubClassEq(RC) ||
397*9880d681SAndroid Build Coastguard Worker AArch64::FPR32RegClass.hasSubClassEq(RC)) {
398*9880d681SAndroid Build Coastguard Worker CondCycles = 5 + ExtraCondLat;
399*9880d681SAndroid Build Coastguard Worker TrueCycles = FalseCycles = 2;
400*9880d681SAndroid Build Coastguard Worker return true;
401*9880d681SAndroid Build Coastguard Worker }
402*9880d681SAndroid Build Coastguard Worker
403*9880d681SAndroid Build Coastguard Worker // Can't do vectors.
404*9880d681SAndroid Build Coastguard Worker return false;
405*9880d681SAndroid Build Coastguard Worker }
406*9880d681SAndroid Build Coastguard Worker
insertSelect(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,const DebugLoc & DL,unsigned DstReg,ArrayRef<MachineOperand> Cond,unsigned TrueReg,unsigned FalseReg) const407*9880d681SAndroid Build Coastguard Worker void AArch64InstrInfo::insertSelect(MachineBasicBlock &MBB,
408*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator I,
409*9880d681SAndroid Build Coastguard Worker const DebugLoc &DL, unsigned DstReg,
410*9880d681SAndroid Build Coastguard Worker ArrayRef<MachineOperand> Cond,
411*9880d681SAndroid Build Coastguard Worker unsigned TrueReg, unsigned FalseReg) const {
412*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
413*9880d681SAndroid Build Coastguard Worker
414*9880d681SAndroid Build Coastguard Worker // Parse the condition code, see parseCondBranch() above.
415*9880d681SAndroid Build Coastguard Worker AArch64CC::CondCode CC;
416*9880d681SAndroid Build Coastguard Worker switch (Cond.size()) {
417*9880d681SAndroid Build Coastguard Worker default:
418*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown condition opcode in Cond");
419*9880d681SAndroid Build Coastguard Worker case 1: // b.cc
420*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::CondCode(Cond[0].getImm());
421*9880d681SAndroid Build Coastguard Worker break;
422*9880d681SAndroid Build Coastguard Worker case 3: { // cbz/cbnz
423*9880d681SAndroid Build Coastguard Worker // We must insert a compare against 0.
424*9880d681SAndroid Build Coastguard Worker bool Is64Bit;
425*9880d681SAndroid Build Coastguard Worker switch (Cond[1].getImm()) {
426*9880d681SAndroid Build Coastguard Worker default:
427*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown branch opcode in Cond");
428*9880d681SAndroid Build Coastguard Worker case AArch64::CBZW:
429*9880d681SAndroid Build Coastguard Worker Is64Bit = 0;
430*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::EQ;
431*9880d681SAndroid Build Coastguard Worker break;
432*9880d681SAndroid Build Coastguard Worker case AArch64::CBZX:
433*9880d681SAndroid Build Coastguard Worker Is64Bit = 1;
434*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::EQ;
435*9880d681SAndroid Build Coastguard Worker break;
436*9880d681SAndroid Build Coastguard Worker case AArch64::CBNZW:
437*9880d681SAndroid Build Coastguard Worker Is64Bit = 0;
438*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::NE;
439*9880d681SAndroid Build Coastguard Worker break;
440*9880d681SAndroid Build Coastguard Worker case AArch64::CBNZX:
441*9880d681SAndroid Build Coastguard Worker Is64Bit = 1;
442*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::NE;
443*9880d681SAndroid Build Coastguard Worker break;
444*9880d681SAndroid Build Coastguard Worker }
445*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = Cond[2].getReg();
446*9880d681SAndroid Build Coastguard Worker if (Is64Bit) {
447*9880d681SAndroid Build Coastguard Worker // cmp reg, #0 is actually subs xzr, reg, #0.
448*9880d681SAndroid Build Coastguard Worker MRI.constrainRegClass(SrcReg, &AArch64::GPR64spRegClass);
449*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::SUBSXri), AArch64::XZR)
450*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg)
451*9880d681SAndroid Build Coastguard Worker .addImm(0)
452*9880d681SAndroid Build Coastguard Worker .addImm(0);
453*9880d681SAndroid Build Coastguard Worker } else {
454*9880d681SAndroid Build Coastguard Worker MRI.constrainRegClass(SrcReg, &AArch64::GPR32spRegClass);
455*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::SUBSWri), AArch64::WZR)
456*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg)
457*9880d681SAndroid Build Coastguard Worker .addImm(0)
458*9880d681SAndroid Build Coastguard Worker .addImm(0);
459*9880d681SAndroid Build Coastguard Worker }
460*9880d681SAndroid Build Coastguard Worker break;
461*9880d681SAndroid Build Coastguard Worker }
462*9880d681SAndroid Build Coastguard Worker case 4: { // tbz/tbnz
463*9880d681SAndroid Build Coastguard Worker // We must insert a tst instruction.
464*9880d681SAndroid Build Coastguard Worker switch (Cond[1].getImm()) {
465*9880d681SAndroid Build Coastguard Worker default:
466*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown branch opcode in Cond");
467*9880d681SAndroid Build Coastguard Worker case AArch64::TBZW:
468*9880d681SAndroid Build Coastguard Worker case AArch64::TBZX:
469*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::EQ;
470*9880d681SAndroid Build Coastguard Worker break;
471*9880d681SAndroid Build Coastguard Worker case AArch64::TBNZW:
472*9880d681SAndroid Build Coastguard Worker case AArch64::TBNZX:
473*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::NE;
474*9880d681SAndroid Build Coastguard Worker break;
475*9880d681SAndroid Build Coastguard Worker }
476*9880d681SAndroid Build Coastguard Worker // cmp reg, #foo is actually ands xzr, reg, #1<<foo.
477*9880d681SAndroid Build Coastguard Worker if (Cond[1].getImm() == AArch64::TBZW || Cond[1].getImm() == AArch64::TBNZW)
478*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::ANDSWri), AArch64::WZR)
479*9880d681SAndroid Build Coastguard Worker .addReg(Cond[2].getReg())
480*9880d681SAndroid Build Coastguard Worker .addImm(
481*9880d681SAndroid Build Coastguard Worker AArch64_AM::encodeLogicalImmediate(1ull << Cond[3].getImm(), 32));
482*9880d681SAndroid Build Coastguard Worker else
483*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::ANDSXri), AArch64::XZR)
484*9880d681SAndroid Build Coastguard Worker .addReg(Cond[2].getReg())
485*9880d681SAndroid Build Coastguard Worker .addImm(
486*9880d681SAndroid Build Coastguard Worker AArch64_AM::encodeLogicalImmediate(1ull << Cond[3].getImm(), 64));
487*9880d681SAndroid Build Coastguard Worker break;
488*9880d681SAndroid Build Coastguard Worker }
489*9880d681SAndroid Build Coastguard Worker }
490*9880d681SAndroid Build Coastguard Worker
491*9880d681SAndroid Build Coastguard Worker unsigned Opc = 0;
492*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = nullptr;
493*9880d681SAndroid Build Coastguard Worker bool TryFold = false;
494*9880d681SAndroid Build Coastguard Worker if (MRI.constrainRegClass(DstReg, &AArch64::GPR64RegClass)) {
495*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR64RegClass;
496*9880d681SAndroid Build Coastguard Worker Opc = AArch64::CSELXr;
497*9880d681SAndroid Build Coastguard Worker TryFold = true;
498*9880d681SAndroid Build Coastguard Worker } else if (MRI.constrainRegClass(DstReg, &AArch64::GPR32RegClass)) {
499*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR32RegClass;
500*9880d681SAndroid Build Coastguard Worker Opc = AArch64::CSELWr;
501*9880d681SAndroid Build Coastguard Worker TryFold = true;
502*9880d681SAndroid Build Coastguard Worker } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR64RegClass)) {
503*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR64RegClass;
504*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FCSELDrrr;
505*9880d681SAndroid Build Coastguard Worker } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR32RegClass)) {
506*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR32RegClass;
507*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FCSELSrrr;
508*9880d681SAndroid Build Coastguard Worker }
509*9880d681SAndroid Build Coastguard Worker assert(RC && "Unsupported regclass");
510*9880d681SAndroid Build Coastguard Worker
511*9880d681SAndroid Build Coastguard Worker // Try folding simple instructions into the csel.
512*9880d681SAndroid Build Coastguard Worker if (TryFold) {
513*9880d681SAndroid Build Coastguard Worker unsigned NewVReg = 0;
514*9880d681SAndroid Build Coastguard Worker unsigned FoldedOpc = canFoldIntoCSel(MRI, TrueReg, &NewVReg);
515*9880d681SAndroid Build Coastguard Worker if (FoldedOpc) {
516*9880d681SAndroid Build Coastguard Worker // The folded opcodes csinc, csinc and csneg apply the operation to
517*9880d681SAndroid Build Coastguard Worker // FalseReg, so we need to invert the condition.
518*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::getInvertedCondCode(CC);
519*9880d681SAndroid Build Coastguard Worker TrueReg = FalseReg;
520*9880d681SAndroid Build Coastguard Worker } else
521*9880d681SAndroid Build Coastguard Worker FoldedOpc = canFoldIntoCSel(MRI, FalseReg, &NewVReg);
522*9880d681SAndroid Build Coastguard Worker
523*9880d681SAndroid Build Coastguard Worker // Fold the operation. Leave any dead instructions for DCE to clean up.
524*9880d681SAndroid Build Coastguard Worker if (FoldedOpc) {
525*9880d681SAndroid Build Coastguard Worker FalseReg = NewVReg;
526*9880d681SAndroid Build Coastguard Worker Opc = FoldedOpc;
527*9880d681SAndroid Build Coastguard Worker // The extends the live range of NewVReg.
528*9880d681SAndroid Build Coastguard Worker MRI.clearKillFlags(NewVReg);
529*9880d681SAndroid Build Coastguard Worker }
530*9880d681SAndroid Build Coastguard Worker }
531*9880d681SAndroid Build Coastguard Worker
532*9880d681SAndroid Build Coastguard Worker // Pull all virtual register into the appropriate class.
533*9880d681SAndroid Build Coastguard Worker MRI.constrainRegClass(TrueReg, RC);
534*9880d681SAndroid Build Coastguard Worker MRI.constrainRegClass(FalseReg, RC);
535*9880d681SAndroid Build Coastguard Worker
536*9880d681SAndroid Build Coastguard Worker // Insert the csel.
537*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(Opc), DstReg).addReg(TrueReg).addReg(FalseReg).addImm(
538*9880d681SAndroid Build Coastguard Worker CC);
539*9880d681SAndroid Build Coastguard Worker }
540*9880d681SAndroid Build Coastguard Worker
541*9880d681SAndroid Build Coastguard Worker /// Returns true if a MOVi32imm or MOVi64imm can be expanded to an ORRxx.
canBeExpandedToORR(const MachineInstr & MI,unsigned BitSize)542*9880d681SAndroid Build Coastguard Worker static bool canBeExpandedToORR(const MachineInstr &MI, unsigned BitSize) {
543*9880d681SAndroid Build Coastguard Worker uint64_t Imm = MI.getOperand(1).getImm();
544*9880d681SAndroid Build Coastguard Worker uint64_t UImm = Imm << (64 - BitSize) >> (64 - BitSize);
545*9880d681SAndroid Build Coastguard Worker uint64_t Encoding;
546*9880d681SAndroid Build Coastguard Worker return AArch64_AM::processLogicalImmediate(UImm, BitSize, Encoding);
547*9880d681SAndroid Build Coastguard Worker }
548*9880d681SAndroid Build Coastguard Worker
549*9880d681SAndroid Build Coastguard Worker // FIXME: this implementation should be micro-architecture dependent, so a
550*9880d681SAndroid Build Coastguard Worker // micro-architecture target hook should be introduced here in future.
isAsCheapAsAMove(const MachineInstr & MI) const551*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::isAsCheapAsAMove(const MachineInstr &MI) const {
552*9880d681SAndroid Build Coastguard Worker if (!Subtarget.hasCustomCheapAsMoveHandling())
553*9880d681SAndroid Build Coastguard Worker return MI.isAsCheapAsAMove();
554*9880d681SAndroid Build Coastguard Worker
555*9880d681SAndroid Build Coastguard Worker unsigned Imm;
556*9880d681SAndroid Build Coastguard Worker
557*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
558*9880d681SAndroid Build Coastguard Worker default:
559*9880d681SAndroid Build Coastguard Worker return false;
560*9880d681SAndroid Build Coastguard Worker
561*9880d681SAndroid Build Coastguard Worker // add/sub on register without shift
562*9880d681SAndroid Build Coastguard Worker case AArch64::ADDWri:
563*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXri:
564*9880d681SAndroid Build Coastguard Worker case AArch64::SUBWri:
565*9880d681SAndroid Build Coastguard Worker case AArch64::SUBXri:
566*9880d681SAndroid Build Coastguard Worker return (Subtarget.getProcFamily() == AArch64Subtarget::ExynosM1 ||
567*9880d681SAndroid Build Coastguard Worker MI.getOperand(3).getImm() == 0);
568*9880d681SAndroid Build Coastguard Worker
569*9880d681SAndroid Build Coastguard Worker // add/sub on register with shift
570*9880d681SAndroid Build Coastguard Worker case AArch64::ADDWrs:
571*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXrs:
572*9880d681SAndroid Build Coastguard Worker case AArch64::SUBWrs:
573*9880d681SAndroid Build Coastguard Worker case AArch64::SUBXrs:
574*9880d681SAndroid Build Coastguard Worker Imm = MI.getOperand(3).getImm();
575*9880d681SAndroid Build Coastguard Worker return (Subtarget.getProcFamily() == AArch64Subtarget::ExynosM1 &&
576*9880d681SAndroid Build Coastguard Worker AArch64_AM::getArithShiftValue(Imm) < 4);
577*9880d681SAndroid Build Coastguard Worker
578*9880d681SAndroid Build Coastguard Worker // logical ops on immediate
579*9880d681SAndroid Build Coastguard Worker case AArch64::ANDWri:
580*9880d681SAndroid Build Coastguard Worker case AArch64::ANDXri:
581*9880d681SAndroid Build Coastguard Worker case AArch64::EORWri:
582*9880d681SAndroid Build Coastguard Worker case AArch64::EORXri:
583*9880d681SAndroid Build Coastguard Worker case AArch64::ORRWri:
584*9880d681SAndroid Build Coastguard Worker case AArch64::ORRXri:
585*9880d681SAndroid Build Coastguard Worker return true;
586*9880d681SAndroid Build Coastguard Worker
587*9880d681SAndroid Build Coastguard Worker // logical ops on register without shift
588*9880d681SAndroid Build Coastguard Worker case AArch64::ANDWrr:
589*9880d681SAndroid Build Coastguard Worker case AArch64::ANDXrr:
590*9880d681SAndroid Build Coastguard Worker case AArch64::BICWrr:
591*9880d681SAndroid Build Coastguard Worker case AArch64::BICXrr:
592*9880d681SAndroid Build Coastguard Worker case AArch64::EONWrr:
593*9880d681SAndroid Build Coastguard Worker case AArch64::EONXrr:
594*9880d681SAndroid Build Coastguard Worker case AArch64::EORWrr:
595*9880d681SAndroid Build Coastguard Worker case AArch64::EORXrr:
596*9880d681SAndroid Build Coastguard Worker case AArch64::ORNWrr:
597*9880d681SAndroid Build Coastguard Worker case AArch64::ORNXrr:
598*9880d681SAndroid Build Coastguard Worker case AArch64::ORRWrr:
599*9880d681SAndroid Build Coastguard Worker case AArch64::ORRXrr:
600*9880d681SAndroid Build Coastguard Worker return true;
601*9880d681SAndroid Build Coastguard Worker
602*9880d681SAndroid Build Coastguard Worker // logical ops on register with shift
603*9880d681SAndroid Build Coastguard Worker case AArch64::ANDWrs:
604*9880d681SAndroid Build Coastguard Worker case AArch64::ANDXrs:
605*9880d681SAndroid Build Coastguard Worker case AArch64::BICWrs:
606*9880d681SAndroid Build Coastguard Worker case AArch64::BICXrs:
607*9880d681SAndroid Build Coastguard Worker case AArch64::EONWrs:
608*9880d681SAndroid Build Coastguard Worker case AArch64::EONXrs:
609*9880d681SAndroid Build Coastguard Worker case AArch64::EORWrs:
610*9880d681SAndroid Build Coastguard Worker case AArch64::EORXrs:
611*9880d681SAndroid Build Coastguard Worker case AArch64::ORNWrs:
612*9880d681SAndroid Build Coastguard Worker case AArch64::ORNXrs:
613*9880d681SAndroid Build Coastguard Worker case AArch64::ORRWrs:
614*9880d681SAndroid Build Coastguard Worker case AArch64::ORRXrs:
615*9880d681SAndroid Build Coastguard Worker Imm = MI.getOperand(3).getImm();
616*9880d681SAndroid Build Coastguard Worker return (Subtarget.getProcFamily() == AArch64Subtarget::ExynosM1 &&
617*9880d681SAndroid Build Coastguard Worker AArch64_AM::getShiftValue(Imm) < 4 &&
618*9880d681SAndroid Build Coastguard Worker AArch64_AM::getShiftType(Imm) == AArch64_AM::LSL);
619*9880d681SAndroid Build Coastguard Worker
620*9880d681SAndroid Build Coastguard Worker // If MOVi32imm or MOVi64imm can be expanded into ORRWri or
621*9880d681SAndroid Build Coastguard Worker // ORRXri, it is as cheap as MOV
622*9880d681SAndroid Build Coastguard Worker case AArch64::MOVi32imm:
623*9880d681SAndroid Build Coastguard Worker return canBeExpandedToORR(MI, 32);
624*9880d681SAndroid Build Coastguard Worker case AArch64::MOVi64imm:
625*9880d681SAndroid Build Coastguard Worker return canBeExpandedToORR(MI, 64);
626*9880d681SAndroid Build Coastguard Worker
627*9880d681SAndroid Build Coastguard Worker // It is cheap to move #0 to float registers if the subtarget has
628*9880d681SAndroid Build Coastguard Worker // ZeroCycleZeroing feature.
629*9880d681SAndroid Build Coastguard Worker case AArch64::FMOVS0:
630*9880d681SAndroid Build Coastguard Worker case AArch64::FMOVD0:
631*9880d681SAndroid Build Coastguard Worker return Subtarget.hasZeroCycleZeroing();
632*9880d681SAndroid Build Coastguard Worker }
633*9880d681SAndroid Build Coastguard Worker
634*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown opcode to check as cheap as a move!");
635*9880d681SAndroid Build Coastguard Worker }
636*9880d681SAndroid Build Coastguard Worker
isCoalescableExtInstr(const MachineInstr & MI,unsigned & SrcReg,unsigned & DstReg,unsigned & SubIdx) const637*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::isCoalescableExtInstr(const MachineInstr &MI,
638*9880d681SAndroid Build Coastguard Worker unsigned &SrcReg, unsigned &DstReg,
639*9880d681SAndroid Build Coastguard Worker unsigned &SubIdx) const {
640*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
641*9880d681SAndroid Build Coastguard Worker default:
642*9880d681SAndroid Build Coastguard Worker return false;
643*9880d681SAndroid Build Coastguard Worker case AArch64::SBFMXri: // aka sxtw
644*9880d681SAndroid Build Coastguard Worker case AArch64::UBFMXri: // aka uxtw
645*9880d681SAndroid Build Coastguard Worker // Check for the 32 -> 64 bit extension case, these instructions can do
646*9880d681SAndroid Build Coastguard Worker // much more.
647*9880d681SAndroid Build Coastguard Worker if (MI.getOperand(2).getImm() != 0 || MI.getOperand(3).getImm() != 31)
648*9880d681SAndroid Build Coastguard Worker return false;
649*9880d681SAndroid Build Coastguard Worker // This is a signed or unsigned 32 -> 64 bit extension.
650*9880d681SAndroid Build Coastguard Worker SrcReg = MI.getOperand(1).getReg();
651*9880d681SAndroid Build Coastguard Worker DstReg = MI.getOperand(0).getReg();
652*9880d681SAndroid Build Coastguard Worker SubIdx = AArch64::sub_32;
653*9880d681SAndroid Build Coastguard Worker return true;
654*9880d681SAndroid Build Coastguard Worker }
655*9880d681SAndroid Build Coastguard Worker }
656*9880d681SAndroid Build Coastguard Worker
areMemAccessesTriviallyDisjoint(MachineInstr & MIa,MachineInstr & MIb,AliasAnalysis * AA) const657*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::areMemAccessesTriviallyDisjoint(
658*9880d681SAndroid Build Coastguard Worker MachineInstr &MIa, MachineInstr &MIb, AliasAnalysis *AA) const {
659*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = &getRegisterInfo();
660*9880d681SAndroid Build Coastguard Worker unsigned BaseRegA = 0, BaseRegB = 0;
661*9880d681SAndroid Build Coastguard Worker int64_t OffsetA = 0, OffsetB = 0;
662*9880d681SAndroid Build Coastguard Worker unsigned WidthA = 0, WidthB = 0;
663*9880d681SAndroid Build Coastguard Worker
664*9880d681SAndroid Build Coastguard Worker assert(MIa.mayLoadOrStore() && "MIa must be a load or store.");
665*9880d681SAndroid Build Coastguard Worker assert(MIb.mayLoadOrStore() && "MIb must be a load or store.");
666*9880d681SAndroid Build Coastguard Worker
667*9880d681SAndroid Build Coastguard Worker if (MIa.hasUnmodeledSideEffects() || MIb.hasUnmodeledSideEffects() ||
668*9880d681SAndroid Build Coastguard Worker MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
669*9880d681SAndroid Build Coastguard Worker return false;
670*9880d681SAndroid Build Coastguard Worker
671*9880d681SAndroid Build Coastguard Worker // Retrieve the base register, offset from the base register and width. Width
672*9880d681SAndroid Build Coastguard Worker // is the size of memory that is being loaded/stored (e.g. 1, 2, 4, 8). If
673*9880d681SAndroid Build Coastguard Worker // base registers are identical, and the offset of a lower memory access +
674*9880d681SAndroid Build Coastguard Worker // the width doesn't overlap the offset of a higher memory access,
675*9880d681SAndroid Build Coastguard Worker // then the memory accesses are different.
676*9880d681SAndroid Build Coastguard Worker if (getMemOpBaseRegImmOfsWidth(MIa, BaseRegA, OffsetA, WidthA, TRI) &&
677*9880d681SAndroid Build Coastguard Worker getMemOpBaseRegImmOfsWidth(MIb, BaseRegB, OffsetB, WidthB, TRI)) {
678*9880d681SAndroid Build Coastguard Worker if (BaseRegA == BaseRegB) {
679*9880d681SAndroid Build Coastguard Worker int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
680*9880d681SAndroid Build Coastguard Worker int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
681*9880d681SAndroid Build Coastguard Worker int LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
682*9880d681SAndroid Build Coastguard Worker if (LowOffset + LowWidth <= HighOffset)
683*9880d681SAndroid Build Coastguard Worker return true;
684*9880d681SAndroid Build Coastguard Worker }
685*9880d681SAndroid Build Coastguard Worker }
686*9880d681SAndroid Build Coastguard Worker return false;
687*9880d681SAndroid Build Coastguard Worker }
688*9880d681SAndroid Build Coastguard Worker
689*9880d681SAndroid Build Coastguard Worker /// analyzeCompare - For a comparison instruction, return the source registers
690*9880d681SAndroid Build Coastguard Worker /// in SrcReg and SrcReg2, and the value it compares against in CmpValue.
691*9880d681SAndroid Build Coastguard Worker /// Return true if the comparison instruction can be analyzed.
analyzeCompare(const MachineInstr & MI,unsigned & SrcReg,unsigned & SrcReg2,int & CmpMask,int & CmpValue) const692*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
693*9880d681SAndroid Build Coastguard Worker unsigned &SrcReg2, int &CmpMask,
694*9880d681SAndroid Build Coastguard Worker int &CmpValue) const {
695*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
696*9880d681SAndroid Build Coastguard Worker default:
697*9880d681SAndroid Build Coastguard Worker break;
698*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWrr:
699*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWrs:
700*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWrx:
701*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXrr:
702*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXrs:
703*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXrx:
704*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWrr:
705*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWrs:
706*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWrx:
707*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXrr:
708*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXrs:
709*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXrx:
710*9880d681SAndroid Build Coastguard Worker // Replace SUBSWrr with SUBWrr if NZCV is not used.
711*9880d681SAndroid Build Coastguard Worker SrcReg = MI.getOperand(1).getReg();
712*9880d681SAndroid Build Coastguard Worker SrcReg2 = MI.getOperand(2).getReg();
713*9880d681SAndroid Build Coastguard Worker CmpMask = ~0;
714*9880d681SAndroid Build Coastguard Worker CmpValue = 0;
715*9880d681SAndroid Build Coastguard Worker return true;
716*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWri:
717*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWri:
718*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXri:
719*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXri:
720*9880d681SAndroid Build Coastguard Worker SrcReg = MI.getOperand(1).getReg();
721*9880d681SAndroid Build Coastguard Worker SrcReg2 = 0;
722*9880d681SAndroid Build Coastguard Worker CmpMask = ~0;
723*9880d681SAndroid Build Coastguard Worker // FIXME: In order to convert CmpValue to 0 or 1
724*9880d681SAndroid Build Coastguard Worker CmpValue = MI.getOperand(2).getImm() != 0;
725*9880d681SAndroid Build Coastguard Worker return true;
726*9880d681SAndroid Build Coastguard Worker case AArch64::ANDSWri:
727*9880d681SAndroid Build Coastguard Worker case AArch64::ANDSXri:
728*9880d681SAndroid Build Coastguard Worker // ANDS does not use the same encoding scheme as the others xxxS
729*9880d681SAndroid Build Coastguard Worker // instructions.
730*9880d681SAndroid Build Coastguard Worker SrcReg = MI.getOperand(1).getReg();
731*9880d681SAndroid Build Coastguard Worker SrcReg2 = 0;
732*9880d681SAndroid Build Coastguard Worker CmpMask = ~0;
733*9880d681SAndroid Build Coastguard Worker // FIXME:The return val type of decodeLogicalImmediate is uint64_t,
734*9880d681SAndroid Build Coastguard Worker // while the type of CmpValue is int. When converting uint64_t to int,
735*9880d681SAndroid Build Coastguard Worker // the high 32 bits of uint64_t will be lost.
736*9880d681SAndroid Build Coastguard Worker // In fact it causes a bug in spec2006-483.xalancbmk
737*9880d681SAndroid Build Coastguard Worker // CmpValue is only used to compare with zero in OptimizeCompareInstr
738*9880d681SAndroid Build Coastguard Worker CmpValue = AArch64_AM::decodeLogicalImmediate(
739*9880d681SAndroid Build Coastguard Worker MI.getOperand(2).getImm(),
740*9880d681SAndroid Build Coastguard Worker MI.getOpcode() == AArch64::ANDSWri ? 32 : 64) != 0;
741*9880d681SAndroid Build Coastguard Worker return true;
742*9880d681SAndroid Build Coastguard Worker }
743*9880d681SAndroid Build Coastguard Worker
744*9880d681SAndroid Build Coastguard Worker return false;
745*9880d681SAndroid Build Coastguard Worker }
746*9880d681SAndroid Build Coastguard Worker
UpdateOperandRegClass(MachineInstr & Instr)747*9880d681SAndroid Build Coastguard Worker static bool UpdateOperandRegClass(MachineInstr &Instr) {
748*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MBB = Instr.getParent();
749*9880d681SAndroid Build Coastguard Worker assert(MBB && "Can't get MachineBasicBlock here");
750*9880d681SAndroid Build Coastguard Worker MachineFunction *MF = MBB->getParent();
751*9880d681SAndroid Build Coastguard Worker assert(MF && "Can't get MachineFunction here");
752*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
753*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
754*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo *MRI = &MF->getRegInfo();
755*9880d681SAndroid Build Coastguard Worker
756*9880d681SAndroid Build Coastguard Worker for (unsigned OpIdx = 0, EndIdx = Instr.getNumOperands(); OpIdx < EndIdx;
757*9880d681SAndroid Build Coastguard Worker ++OpIdx) {
758*9880d681SAndroid Build Coastguard Worker MachineOperand &MO = Instr.getOperand(OpIdx);
759*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *OpRegCstraints =
760*9880d681SAndroid Build Coastguard Worker Instr.getRegClassConstraint(OpIdx, TII, TRI);
761*9880d681SAndroid Build Coastguard Worker
762*9880d681SAndroid Build Coastguard Worker // If there's no constraint, there's nothing to do.
763*9880d681SAndroid Build Coastguard Worker if (!OpRegCstraints)
764*9880d681SAndroid Build Coastguard Worker continue;
765*9880d681SAndroid Build Coastguard Worker // If the operand is a frame index, there's nothing to do here.
766*9880d681SAndroid Build Coastguard Worker // A frame index operand will resolve correctly during PEI.
767*9880d681SAndroid Build Coastguard Worker if (MO.isFI())
768*9880d681SAndroid Build Coastguard Worker continue;
769*9880d681SAndroid Build Coastguard Worker
770*9880d681SAndroid Build Coastguard Worker assert(MO.isReg() &&
771*9880d681SAndroid Build Coastguard Worker "Operand has register constraints without being a register!");
772*9880d681SAndroid Build Coastguard Worker
773*9880d681SAndroid Build Coastguard Worker unsigned Reg = MO.getReg();
774*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
775*9880d681SAndroid Build Coastguard Worker if (!OpRegCstraints->contains(Reg))
776*9880d681SAndroid Build Coastguard Worker return false;
777*9880d681SAndroid Build Coastguard Worker } else if (!OpRegCstraints->hasSubClassEq(MRI->getRegClass(Reg)) &&
778*9880d681SAndroid Build Coastguard Worker !MRI->constrainRegClass(Reg, OpRegCstraints))
779*9880d681SAndroid Build Coastguard Worker return false;
780*9880d681SAndroid Build Coastguard Worker }
781*9880d681SAndroid Build Coastguard Worker
782*9880d681SAndroid Build Coastguard Worker return true;
783*9880d681SAndroid Build Coastguard Worker }
784*9880d681SAndroid Build Coastguard Worker
785*9880d681SAndroid Build Coastguard Worker /// \brief Return the opcode that does not set flags when possible - otherwise
786*9880d681SAndroid Build Coastguard Worker /// return the original opcode. The caller is responsible to do the actual
787*9880d681SAndroid Build Coastguard Worker /// substitution and legality checking.
convertFlagSettingOpcode(const MachineInstr & MI)788*9880d681SAndroid Build Coastguard Worker static unsigned convertFlagSettingOpcode(const MachineInstr &MI) {
789*9880d681SAndroid Build Coastguard Worker // Don't convert all compare instructions, because for some the zero register
790*9880d681SAndroid Build Coastguard Worker // encoding becomes the sp register.
791*9880d681SAndroid Build Coastguard Worker bool MIDefinesZeroReg = false;
792*9880d681SAndroid Build Coastguard Worker if (MI.definesRegister(AArch64::WZR) || MI.definesRegister(AArch64::XZR))
793*9880d681SAndroid Build Coastguard Worker MIDefinesZeroReg = true;
794*9880d681SAndroid Build Coastguard Worker
795*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
796*9880d681SAndroid Build Coastguard Worker default:
797*9880d681SAndroid Build Coastguard Worker return MI.getOpcode();
798*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWrr:
799*9880d681SAndroid Build Coastguard Worker return AArch64::ADDWrr;
800*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWri:
801*9880d681SAndroid Build Coastguard Worker return MIDefinesZeroReg ? AArch64::ADDSWri : AArch64::ADDWri;
802*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWrs:
803*9880d681SAndroid Build Coastguard Worker return MIDefinesZeroReg ? AArch64::ADDSWrs : AArch64::ADDWrs;
804*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWrx:
805*9880d681SAndroid Build Coastguard Worker return AArch64::ADDWrx;
806*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXrr:
807*9880d681SAndroid Build Coastguard Worker return AArch64::ADDXrr;
808*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXri:
809*9880d681SAndroid Build Coastguard Worker return MIDefinesZeroReg ? AArch64::ADDSXri : AArch64::ADDXri;
810*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXrs:
811*9880d681SAndroid Build Coastguard Worker return MIDefinesZeroReg ? AArch64::ADDSXrs : AArch64::ADDXrs;
812*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXrx:
813*9880d681SAndroid Build Coastguard Worker return AArch64::ADDXrx;
814*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWrr:
815*9880d681SAndroid Build Coastguard Worker return AArch64::SUBWrr;
816*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWri:
817*9880d681SAndroid Build Coastguard Worker return MIDefinesZeroReg ? AArch64::SUBSWri : AArch64::SUBWri;
818*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWrs:
819*9880d681SAndroid Build Coastguard Worker return MIDefinesZeroReg ? AArch64::SUBSWrs : AArch64::SUBWrs;
820*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWrx:
821*9880d681SAndroid Build Coastguard Worker return AArch64::SUBWrx;
822*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXrr:
823*9880d681SAndroid Build Coastguard Worker return AArch64::SUBXrr;
824*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXri:
825*9880d681SAndroid Build Coastguard Worker return MIDefinesZeroReg ? AArch64::SUBSXri : AArch64::SUBXri;
826*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXrs:
827*9880d681SAndroid Build Coastguard Worker return MIDefinesZeroReg ? AArch64::SUBSXrs : AArch64::SUBXrs;
828*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXrx:
829*9880d681SAndroid Build Coastguard Worker return AArch64::SUBXrx;
830*9880d681SAndroid Build Coastguard Worker }
831*9880d681SAndroid Build Coastguard Worker }
832*9880d681SAndroid Build Coastguard Worker
833*9880d681SAndroid Build Coastguard Worker enum AccessKind {
834*9880d681SAndroid Build Coastguard Worker AK_Write = 0x01,
835*9880d681SAndroid Build Coastguard Worker AK_Read = 0x10,
836*9880d681SAndroid Build Coastguard Worker AK_All = 0x11
837*9880d681SAndroid Build Coastguard Worker };
838*9880d681SAndroid Build Coastguard Worker
839*9880d681SAndroid Build Coastguard Worker /// True when condition flags are accessed (either by writing or reading)
840*9880d681SAndroid Build Coastguard Worker /// on the instruction trace starting at From and ending at To.
841*9880d681SAndroid Build Coastguard Worker ///
842*9880d681SAndroid Build Coastguard Worker /// Note: If From and To are from different blocks it's assumed CC are accessed
843*9880d681SAndroid Build Coastguard Worker /// on the path.
areCFlagsAccessedBetweenInstrs(MachineBasicBlock::iterator From,MachineBasicBlock::iterator To,const TargetRegisterInfo * TRI,const AccessKind AccessToCheck=AK_All)844*9880d681SAndroid Build Coastguard Worker static bool areCFlagsAccessedBetweenInstrs(
845*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator From, MachineBasicBlock::iterator To,
846*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI, const AccessKind AccessToCheck = AK_All) {
847*9880d681SAndroid Build Coastguard Worker // Early exit if To is at the beginning of the BB.
848*9880d681SAndroid Build Coastguard Worker if (To == To->getParent()->begin())
849*9880d681SAndroid Build Coastguard Worker return true;
850*9880d681SAndroid Build Coastguard Worker
851*9880d681SAndroid Build Coastguard Worker // Check whether the instructions are in the same basic block
852*9880d681SAndroid Build Coastguard Worker // If not, assume the condition flags might get modified somewhere.
853*9880d681SAndroid Build Coastguard Worker if (To->getParent() != From->getParent())
854*9880d681SAndroid Build Coastguard Worker return true;
855*9880d681SAndroid Build Coastguard Worker
856*9880d681SAndroid Build Coastguard Worker // From must be above To.
857*9880d681SAndroid Build Coastguard Worker assert(std::find_if(MachineBasicBlock::reverse_iterator(To),
858*9880d681SAndroid Build Coastguard Worker To->getParent()->rend(), [From](MachineInstr &MI) {
859*9880d681SAndroid Build Coastguard Worker return MachineBasicBlock::iterator(MI) == From;
860*9880d681SAndroid Build Coastguard Worker }) != To->getParent()->rend());
861*9880d681SAndroid Build Coastguard Worker
862*9880d681SAndroid Build Coastguard Worker // We iterate backward starting \p To until we hit \p From.
863*9880d681SAndroid Build Coastguard Worker for (--To; To != From; --To) {
864*9880d681SAndroid Build Coastguard Worker const MachineInstr &Instr = *To;
865*9880d681SAndroid Build Coastguard Worker
866*9880d681SAndroid Build Coastguard Worker if ( ((AccessToCheck & AK_Write) && Instr.modifiesRegister(AArch64::NZCV, TRI)) ||
867*9880d681SAndroid Build Coastguard Worker ((AccessToCheck & AK_Read) && Instr.readsRegister(AArch64::NZCV, TRI)))
868*9880d681SAndroid Build Coastguard Worker return true;
869*9880d681SAndroid Build Coastguard Worker }
870*9880d681SAndroid Build Coastguard Worker return false;
871*9880d681SAndroid Build Coastguard Worker }
872*9880d681SAndroid Build Coastguard Worker
873*9880d681SAndroid Build Coastguard Worker /// Try to optimize a compare instruction. A compare instruction is an
874*9880d681SAndroid Build Coastguard Worker /// instruction which produces AArch64::NZCV. It can be truly compare instruction
875*9880d681SAndroid Build Coastguard Worker /// when there are no uses of its destination register.
876*9880d681SAndroid Build Coastguard Worker ///
877*9880d681SAndroid Build Coastguard Worker /// The following steps are tried in order:
878*9880d681SAndroid Build Coastguard Worker /// 1. Convert CmpInstr into an unconditional version.
879*9880d681SAndroid Build Coastguard Worker /// 2. Remove CmpInstr if above there is an instruction producing a needed
880*9880d681SAndroid Build Coastguard Worker /// condition code or an instruction which can be converted into such an instruction.
881*9880d681SAndroid Build Coastguard Worker /// Only comparison with zero is supported.
optimizeCompareInstr(MachineInstr & CmpInstr,unsigned SrcReg,unsigned SrcReg2,int CmpMask,int CmpValue,const MachineRegisterInfo * MRI) const882*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::optimizeCompareInstr(
883*9880d681SAndroid Build Coastguard Worker MachineInstr &CmpInstr, unsigned SrcReg, unsigned SrcReg2, int CmpMask,
884*9880d681SAndroid Build Coastguard Worker int CmpValue, const MachineRegisterInfo *MRI) const {
885*9880d681SAndroid Build Coastguard Worker assert(CmpInstr.getParent());
886*9880d681SAndroid Build Coastguard Worker assert(MRI);
887*9880d681SAndroid Build Coastguard Worker
888*9880d681SAndroid Build Coastguard Worker // Replace SUBSWrr with SUBWrr if NZCV is not used.
889*9880d681SAndroid Build Coastguard Worker int DeadNZCVIdx = CmpInstr.findRegisterDefOperandIdx(AArch64::NZCV, true);
890*9880d681SAndroid Build Coastguard Worker if (DeadNZCVIdx != -1) {
891*9880d681SAndroid Build Coastguard Worker if (CmpInstr.definesRegister(AArch64::WZR) ||
892*9880d681SAndroid Build Coastguard Worker CmpInstr.definesRegister(AArch64::XZR)) {
893*9880d681SAndroid Build Coastguard Worker CmpInstr.eraseFromParent();
894*9880d681SAndroid Build Coastguard Worker return true;
895*9880d681SAndroid Build Coastguard Worker }
896*9880d681SAndroid Build Coastguard Worker unsigned Opc = CmpInstr.getOpcode();
897*9880d681SAndroid Build Coastguard Worker unsigned NewOpc = convertFlagSettingOpcode(CmpInstr);
898*9880d681SAndroid Build Coastguard Worker if (NewOpc == Opc)
899*9880d681SAndroid Build Coastguard Worker return false;
900*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &MCID = get(NewOpc);
901*9880d681SAndroid Build Coastguard Worker CmpInstr.setDesc(MCID);
902*9880d681SAndroid Build Coastguard Worker CmpInstr.RemoveOperand(DeadNZCVIdx);
903*9880d681SAndroid Build Coastguard Worker bool succeeded = UpdateOperandRegClass(CmpInstr);
904*9880d681SAndroid Build Coastguard Worker (void)succeeded;
905*9880d681SAndroid Build Coastguard Worker assert(succeeded && "Some operands reg class are incompatible!");
906*9880d681SAndroid Build Coastguard Worker return true;
907*9880d681SAndroid Build Coastguard Worker }
908*9880d681SAndroid Build Coastguard Worker
909*9880d681SAndroid Build Coastguard Worker // Continue only if we have a "ri" where immediate is zero.
910*9880d681SAndroid Build Coastguard Worker // FIXME:CmpValue has already been converted to 0 or 1 in analyzeCompare
911*9880d681SAndroid Build Coastguard Worker // function.
912*9880d681SAndroid Build Coastguard Worker assert((CmpValue == 0 || CmpValue == 1) && "CmpValue must be 0 or 1!");
913*9880d681SAndroid Build Coastguard Worker if (CmpValue != 0 || SrcReg2 != 0)
914*9880d681SAndroid Build Coastguard Worker return false;
915*9880d681SAndroid Build Coastguard Worker
916*9880d681SAndroid Build Coastguard Worker // CmpInstr is a Compare instruction if destination register is not used.
917*9880d681SAndroid Build Coastguard Worker if (!MRI->use_nodbg_empty(CmpInstr.getOperand(0).getReg()))
918*9880d681SAndroid Build Coastguard Worker return false;
919*9880d681SAndroid Build Coastguard Worker
920*9880d681SAndroid Build Coastguard Worker return substituteCmpToZero(CmpInstr, SrcReg, MRI);
921*9880d681SAndroid Build Coastguard Worker }
922*9880d681SAndroid Build Coastguard Worker
923*9880d681SAndroid Build Coastguard Worker /// Get opcode of S version of Instr.
924*9880d681SAndroid Build Coastguard Worker /// If Instr is S version its opcode is returned.
925*9880d681SAndroid Build Coastguard Worker /// AArch64::INSTRUCTION_LIST_END is returned if Instr does not have S version
926*9880d681SAndroid Build Coastguard Worker /// or we are not interested in it.
sForm(MachineInstr & Instr)927*9880d681SAndroid Build Coastguard Worker static unsigned sForm(MachineInstr &Instr) {
928*9880d681SAndroid Build Coastguard Worker switch (Instr.getOpcode()) {
929*9880d681SAndroid Build Coastguard Worker default:
930*9880d681SAndroid Build Coastguard Worker return AArch64::INSTRUCTION_LIST_END;
931*9880d681SAndroid Build Coastguard Worker
932*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWrr:
933*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWri:
934*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXrr:
935*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXri:
936*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWrr:
937*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWri:
938*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXrr:
939*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXri:
940*9880d681SAndroid Build Coastguard Worker return Instr.getOpcode();;
941*9880d681SAndroid Build Coastguard Worker
942*9880d681SAndroid Build Coastguard Worker case AArch64::ADDWrr: return AArch64::ADDSWrr;
943*9880d681SAndroid Build Coastguard Worker case AArch64::ADDWri: return AArch64::ADDSWri;
944*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXrr: return AArch64::ADDSXrr;
945*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXri: return AArch64::ADDSXri;
946*9880d681SAndroid Build Coastguard Worker case AArch64::ADCWr: return AArch64::ADCSWr;
947*9880d681SAndroid Build Coastguard Worker case AArch64::ADCXr: return AArch64::ADCSXr;
948*9880d681SAndroid Build Coastguard Worker case AArch64::SUBWrr: return AArch64::SUBSWrr;
949*9880d681SAndroid Build Coastguard Worker case AArch64::SUBWri: return AArch64::SUBSWri;
950*9880d681SAndroid Build Coastguard Worker case AArch64::SUBXrr: return AArch64::SUBSXrr;
951*9880d681SAndroid Build Coastguard Worker case AArch64::SUBXri: return AArch64::SUBSXri;
952*9880d681SAndroid Build Coastguard Worker case AArch64::SBCWr: return AArch64::SBCSWr;
953*9880d681SAndroid Build Coastguard Worker case AArch64::SBCXr: return AArch64::SBCSXr;
954*9880d681SAndroid Build Coastguard Worker case AArch64::ANDWri: return AArch64::ANDSWri;
955*9880d681SAndroid Build Coastguard Worker case AArch64::ANDXri: return AArch64::ANDSXri;
956*9880d681SAndroid Build Coastguard Worker }
957*9880d681SAndroid Build Coastguard Worker }
958*9880d681SAndroid Build Coastguard Worker
959*9880d681SAndroid Build Coastguard Worker /// Check if AArch64::NZCV should be alive in successors of MBB.
areCFlagsAliveInSuccessors(MachineBasicBlock * MBB)960*9880d681SAndroid Build Coastguard Worker static bool areCFlagsAliveInSuccessors(MachineBasicBlock *MBB) {
961*9880d681SAndroid Build Coastguard Worker for (auto *BB : MBB->successors())
962*9880d681SAndroid Build Coastguard Worker if (BB->isLiveIn(AArch64::NZCV))
963*9880d681SAndroid Build Coastguard Worker return true;
964*9880d681SAndroid Build Coastguard Worker return false;
965*9880d681SAndroid Build Coastguard Worker }
966*9880d681SAndroid Build Coastguard Worker
967*9880d681SAndroid Build Coastguard Worker struct UsedNZCV {
968*9880d681SAndroid Build Coastguard Worker bool N;
969*9880d681SAndroid Build Coastguard Worker bool Z;
970*9880d681SAndroid Build Coastguard Worker bool C;
971*9880d681SAndroid Build Coastguard Worker bool V;
UsedNZCVUsedNZCV972*9880d681SAndroid Build Coastguard Worker UsedNZCV(): N(false), Z(false), C(false), V(false) {}
operator |=UsedNZCV973*9880d681SAndroid Build Coastguard Worker UsedNZCV& operator |=(const UsedNZCV& UsedFlags) {
974*9880d681SAndroid Build Coastguard Worker this->N |= UsedFlags.N;
975*9880d681SAndroid Build Coastguard Worker this->Z |= UsedFlags.Z;
976*9880d681SAndroid Build Coastguard Worker this->C |= UsedFlags.C;
977*9880d681SAndroid Build Coastguard Worker this->V |= UsedFlags.V;
978*9880d681SAndroid Build Coastguard Worker return *this;
979*9880d681SAndroid Build Coastguard Worker }
980*9880d681SAndroid Build Coastguard Worker };
981*9880d681SAndroid Build Coastguard Worker
982*9880d681SAndroid Build Coastguard Worker /// Find a condition code used by the instruction.
983*9880d681SAndroid Build Coastguard Worker /// Returns AArch64CC::Invalid if either the instruction does not use condition
984*9880d681SAndroid Build Coastguard Worker /// codes or we don't optimize CmpInstr in the presence of such instructions.
findCondCodeUsedByInstr(const MachineInstr & Instr)985*9880d681SAndroid Build Coastguard Worker static AArch64CC::CondCode findCondCodeUsedByInstr(const MachineInstr &Instr) {
986*9880d681SAndroid Build Coastguard Worker switch (Instr.getOpcode()) {
987*9880d681SAndroid Build Coastguard Worker default:
988*9880d681SAndroid Build Coastguard Worker return AArch64CC::Invalid;
989*9880d681SAndroid Build Coastguard Worker
990*9880d681SAndroid Build Coastguard Worker case AArch64::Bcc: {
991*9880d681SAndroid Build Coastguard Worker int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV);
992*9880d681SAndroid Build Coastguard Worker assert(Idx >= 2);
993*9880d681SAndroid Build Coastguard Worker return static_cast<AArch64CC::CondCode>(Instr.getOperand(Idx - 2).getImm());
994*9880d681SAndroid Build Coastguard Worker }
995*9880d681SAndroid Build Coastguard Worker
996*9880d681SAndroid Build Coastguard Worker case AArch64::CSINVWr:
997*9880d681SAndroid Build Coastguard Worker case AArch64::CSINVXr:
998*9880d681SAndroid Build Coastguard Worker case AArch64::CSINCWr:
999*9880d681SAndroid Build Coastguard Worker case AArch64::CSINCXr:
1000*9880d681SAndroid Build Coastguard Worker case AArch64::CSELWr:
1001*9880d681SAndroid Build Coastguard Worker case AArch64::CSELXr:
1002*9880d681SAndroid Build Coastguard Worker case AArch64::CSNEGWr:
1003*9880d681SAndroid Build Coastguard Worker case AArch64::CSNEGXr:
1004*9880d681SAndroid Build Coastguard Worker case AArch64::FCSELSrrr:
1005*9880d681SAndroid Build Coastguard Worker case AArch64::FCSELDrrr: {
1006*9880d681SAndroid Build Coastguard Worker int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV);
1007*9880d681SAndroid Build Coastguard Worker assert(Idx >= 1);
1008*9880d681SAndroid Build Coastguard Worker return static_cast<AArch64CC::CondCode>(Instr.getOperand(Idx - 1).getImm());
1009*9880d681SAndroid Build Coastguard Worker }
1010*9880d681SAndroid Build Coastguard Worker }
1011*9880d681SAndroid Build Coastguard Worker }
1012*9880d681SAndroid Build Coastguard Worker
getUsedNZCV(AArch64CC::CondCode CC)1013*9880d681SAndroid Build Coastguard Worker static UsedNZCV getUsedNZCV(AArch64CC::CondCode CC) {
1014*9880d681SAndroid Build Coastguard Worker assert(CC != AArch64CC::Invalid);
1015*9880d681SAndroid Build Coastguard Worker UsedNZCV UsedFlags;
1016*9880d681SAndroid Build Coastguard Worker switch (CC) {
1017*9880d681SAndroid Build Coastguard Worker default:
1018*9880d681SAndroid Build Coastguard Worker break;
1019*9880d681SAndroid Build Coastguard Worker
1020*9880d681SAndroid Build Coastguard Worker case AArch64CC::EQ: // Z set
1021*9880d681SAndroid Build Coastguard Worker case AArch64CC::NE: // Z clear
1022*9880d681SAndroid Build Coastguard Worker UsedFlags.Z = true;
1023*9880d681SAndroid Build Coastguard Worker break;
1024*9880d681SAndroid Build Coastguard Worker
1025*9880d681SAndroid Build Coastguard Worker case AArch64CC::HI: // Z clear and C set
1026*9880d681SAndroid Build Coastguard Worker case AArch64CC::LS: // Z set or C clear
1027*9880d681SAndroid Build Coastguard Worker UsedFlags.Z = true;
1028*9880d681SAndroid Build Coastguard Worker case AArch64CC::HS: // C set
1029*9880d681SAndroid Build Coastguard Worker case AArch64CC::LO: // C clear
1030*9880d681SAndroid Build Coastguard Worker UsedFlags.C = true;
1031*9880d681SAndroid Build Coastguard Worker break;
1032*9880d681SAndroid Build Coastguard Worker
1033*9880d681SAndroid Build Coastguard Worker case AArch64CC::MI: // N set
1034*9880d681SAndroid Build Coastguard Worker case AArch64CC::PL: // N clear
1035*9880d681SAndroid Build Coastguard Worker UsedFlags.N = true;
1036*9880d681SAndroid Build Coastguard Worker break;
1037*9880d681SAndroid Build Coastguard Worker
1038*9880d681SAndroid Build Coastguard Worker case AArch64CC::VS: // V set
1039*9880d681SAndroid Build Coastguard Worker case AArch64CC::VC: // V clear
1040*9880d681SAndroid Build Coastguard Worker UsedFlags.V = true;
1041*9880d681SAndroid Build Coastguard Worker break;
1042*9880d681SAndroid Build Coastguard Worker
1043*9880d681SAndroid Build Coastguard Worker case AArch64CC::GT: // Z clear, N and V the same
1044*9880d681SAndroid Build Coastguard Worker case AArch64CC::LE: // Z set, N and V differ
1045*9880d681SAndroid Build Coastguard Worker UsedFlags.Z = true;
1046*9880d681SAndroid Build Coastguard Worker case AArch64CC::GE: // N and V the same
1047*9880d681SAndroid Build Coastguard Worker case AArch64CC::LT: // N and V differ
1048*9880d681SAndroid Build Coastguard Worker UsedFlags.N = true;
1049*9880d681SAndroid Build Coastguard Worker UsedFlags.V = true;
1050*9880d681SAndroid Build Coastguard Worker break;
1051*9880d681SAndroid Build Coastguard Worker }
1052*9880d681SAndroid Build Coastguard Worker return UsedFlags;
1053*9880d681SAndroid Build Coastguard Worker }
1054*9880d681SAndroid Build Coastguard Worker
isADDSRegImm(unsigned Opcode)1055*9880d681SAndroid Build Coastguard Worker static bool isADDSRegImm(unsigned Opcode) {
1056*9880d681SAndroid Build Coastguard Worker return Opcode == AArch64::ADDSWri || Opcode == AArch64::ADDSXri;
1057*9880d681SAndroid Build Coastguard Worker }
1058*9880d681SAndroid Build Coastguard Worker
isSUBSRegImm(unsigned Opcode)1059*9880d681SAndroid Build Coastguard Worker static bool isSUBSRegImm(unsigned Opcode) {
1060*9880d681SAndroid Build Coastguard Worker return Opcode == AArch64::SUBSWri || Opcode == AArch64::SUBSXri;
1061*9880d681SAndroid Build Coastguard Worker }
1062*9880d681SAndroid Build Coastguard Worker
1063*9880d681SAndroid Build Coastguard Worker /// Check if CmpInstr can be substituted by MI.
1064*9880d681SAndroid Build Coastguard Worker ///
1065*9880d681SAndroid Build Coastguard Worker /// CmpInstr can be substituted:
1066*9880d681SAndroid Build Coastguard Worker /// - CmpInstr is either 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
1067*9880d681SAndroid Build Coastguard Worker /// - and, MI and CmpInstr are from the same MachineBB
1068*9880d681SAndroid Build Coastguard Worker /// - and, condition flags are not alive in successors of the CmpInstr parent
1069*9880d681SAndroid Build Coastguard Worker /// - and, if MI opcode is the S form there must be no defs of flags between
1070*9880d681SAndroid Build Coastguard Worker /// MI and CmpInstr
1071*9880d681SAndroid Build Coastguard Worker /// or if MI opcode is not the S form there must be neither defs of flags
1072*9880d681SAndroid Build Coastguard Worker /// nor uses of flags between MI and CmpInstr.
1073*9880d681SAndroid Build Coastguard Worker /// - and C/V flags are not used after CmpInstr
canInstrSubstituteCmpInstr(MachineInstr * MI,MachineInstr * CmpInstr,const TargetRegisterInfo * TRI)1074*9880d681SAndroid Build Coastguard Worker static bool canInstrSubstituteCmpInstr(MachineInstr *MI, MachineInstr *CmpInstr,
1075*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI) {
1076*9880d681SAndroid Build Coastguard Worker assert(MI);
1077*9880d681SAndroid Build Coastguard Worker assert(sForm(*MI) != AArch64::INSTRUCTION_LIST_END);
1078*9880d681SAndroid Build Coastguard Worker assert(CmpInstr);
1079*9880d681SAndroid Build Coastguard Worker
1080*9880d681SAndroid Build Coastguard Worker const unsigned CmpOpcode = CmpInstr->getOpcode();
1081*9880d681SAndroid Build Coastguard Worker if (!isADDSRegImm(CmpOpcode) && !isSUBSRegImm(CmpOpcode))
1082*9880d681SAndroid Build Coastguard Worker return false;
1083*9880d681SAndroid Build Coastguard Worker
1084*9880d681SAndroid Build Coastguard Worker if (MI->getParent() != CmpInstr->getParent())
1085*9880d681SAndroid Build Coastguard Worker return false;
1086*9880d681SAndroid Build Coastguard Worker
1087*9880d681SAndroid Build Coastguard Worker if (areCFlagsAliveInSuccessors(CmpInstr->getParent()))
1088*9880d681SAndroid Build Coastguard Worker return false;
1089*9880d681SAndroid Build Coastguard Worker
1090*9880d681SAndroid Build Coastguard Worker AccessKind AccessToCheck = AK_Write;
1091*9880d681SAndroid Build Coastguard Worker if (sForm(*MI) != MI->getOpcode())
1092*9880d681SAndroid Build Coastguard Worker AccessToCheck = AK_All;
1093*9880d681SAndroid Build Coastguard Worker if (areCFlagsAccessedBetweenInstrs(MI, CmpInstr, TRI, AccessToCheck))
1094*9880d681SAndroid Build Coastguard Worker return false;
1095*9880d681SAndroid Build Coastguard Worker
1096*9880d681SAndroid Build Coastguard Worker UsedNZCV NZCVUsedAfterCmp;
1097*9880d681SAndroid Build Coastguard Worker for (auto I = std::next(CmpInstr->getIterator()), E = CmpInstr->getParent()->instr_end();
1098*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
1099*9880d681SAndroid Build Coastguard Worker const MachineInstr &Instr = *I;
1100*9880d681SAndroid Build Coastguard Worker if (Instr.readsRegister(AArch64::NZCV, TRI)) {
1101*9880d681SAndroid Build Coastguard Worker AArch64CC::CondCode CC = findCondCodeUsedByInstr(Instr);
1102*9880d681SAndroid Build Coastguard Worker if (CC == AArch64CC::Invalid) // Unsupported conditional instruction
1103*9880d681SAndroid Build Coastguard Worker return false;
1104*9880d681SAndroid Build Coastguard Worker NZCVUsedAfterCmp |= getUsedNZCV(CC);
1105*9880d681SAndroid Build Coastguard Worker }
1106*9880d681SAndroid Build Coastguard Worker
1107*9880d681SAndroid Build Coastguard Worker if (Instr.modifiesRegister(AArch64::NZCV, TRI))
1108*9880d681SAndroid Build Coastguard Worker break;
1109*9880d681SAndroid Build Coastguard Worker }
1110*9880d681SAndroid Build Coastguard Worker
1111*9880d681SAndroid Build Coastguard Worker return !NZCVUsedAfterCmp.C && !NZCVUsedAfterCmp.V;
1112*9880d681SAndroid Build Coastguard Worker }
1113*9880d681SAndroid Build Coastguard Worker
1114*9880d681SAndroid Build Coastguard Worker /// Substitute an instruction comparing to zero with another instruction
1115*9880d681SAndroid Build Coastguard Worker /// which produces needed condition flags.
1116*9880d681SAndroid Build Coastguard Worker ///
1117*9880d681SAndroid Build Coastguard Worker /// Return true on success.
substituteCmpToZero(MachineInstr & CmpInstr,unsigned SrcReg,const MachineRegisterInfo * MRI) const1118*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::substituteCmpToZero(
1119*9880d681SAndroid Build Coastguard Worker MachineInstr &CmpInstr, unsigned SrcReg,
1120*9880d681SAndroid Build Coastguard Worker const MachineRegisterInfo *MRI) const {
1121*9880d681SAndroid Build Coastguard Worker assert(MRI);
1122*9880d681SAndroid Build Coastguard Worker // Get the unique definition of SrcReg.
1123*9880d681SAndroid Build Coastguard Worker MachineInstr *MI = MRI->getUniqueVRegDef(SrcReg);
1124*9880d681SAndroid Build Coastguard Worker if (!MI)
1125*9880d681SAndroid Build Coastguard Worker return false;
1126*9880d681SAndroid Build Coastguard Worker
1127*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = &getRegisterInfo();
1128*9880d681SAndroid Build Coastguard Worker
1129*9880d681SAndroid Build Coastguard Worker unsigned NewOpc = sForm(*MI);
1130*9880d681SAndroid Build Coastguard Worker if (NewOpc == AArch64::INSTRUCTION_LIST_END)
1131*9880d681SAndroid Build Coastguard Worker return false;
1132*9880d681SAndroid Build Coastguard Worker
1133*9880d681SAndroid Build Coastguard Worker if (!canInstrSubstituteCmpInstr(MI, &CmpInstr, TRI))
1134*9880d681SAndroid Build Coastguard Worker return false;
1135*9880d681SAndroid Build Coastguard Worker
1136*9880d681SAndroid Build Coastguard Worker // Update the instruction to set NZCV.
1137*9880d681SAndroid Build Coastguard Worker MI->setDesc(get(NewOpc));
1138*9880d681SAndroid Build Coastguard Worker CmpInstr.eraseFromParent();
1139*9880d681SAndroid Build Coastguard Worker bool succeeded = UpdateOperandRegClass(*MI);
1140*9880d681SAndroid Build Coastguard Worker (void)succeeded;
1141*9880d681SAndroid Build Coastguard Worker assert(succeeded && "Some operands reg class are incompatible!");
1142*9880d681SAndroid Build Coastguard Worker MI->addRegisterDefined(AArch64::NZCV, TRI);
1143*9880d681SAndroid Build Coastguard Worker return true;
1144*9880d681SAndroid Build Coastguard Worker }
1145*9880d681SAndroid Build Coastguard Worker
expandPostRAPseudo(MachineInstr & MI) const1146*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
1147*9880d681SAndroid Build Coastguard Worker if (MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD)
1148*9880d681SAndroid Build Coastguard Worker return false;
1149*9880d681SAndroid Build Coastguard Worker
1150*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *MI.getParent();
1151*9880d681SAndroid Build Coastguard Worker DebugLoc DL = MI.getDebugLoc();
1152*9880d681SAndroid Build Coastguard Worker unsigned Reg = MI.getOperand(0).getReg();
1153*9880d681SAndroid Build Coastguard Worker const GlobalValue *GV =
1154*9880d681SAndroid Build Coastguard Worker cast<GlobalValue>((*MI.memoperands_begin())->getValue());
1155*9880d681SAndroid Build Coastguard Worker const TargetMachine &TM = MBB.getParent()->getTarget();
1156*9880d681SAndroid Build Coastguard Worker unsigned char OpFlags = Subtarget.ClassifyGlobalReference(GV, TM);
1157*9880d681SAndroid Build Coastguard Worker const unsigned char MO_NC = AArch64II::MO_NC;
1158*9880d681SAndroid Build Coastguard Worker
1159*9880d681SAndroid Build Coastguard Worker if ((OpFlags & AArch64II::MO_GOT) != 0) {
1160*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MI, DL, get(AArch64::LOADgot), Reg)
1161*9880d681SAndroid Build Coastguard Worker .addGlobalAddress(GV, 0, AArch64II::MO_GOT);
1162*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
1163*9880d681SAndroid Build Coastguard Worker .addReg(Reg, RegState::Kill)
1164*9880d681SAndroid Build Coastguard Worker .addImm(0)
1165*9880d681SAndroid Build Coastguard Worker .addMemOperand(*MI.memoperands_begin());
1166*9880d681SAndroid Build Coastguard Worker } else if (TM.getCodeModel() == CodeModel::Large) {
1167*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MI, DL, get(AArch64::MOVZXi), Reg)
1168*9880d681SAndroid Build Coastguard Worker .addGlobalAddress(GV, 0, AArch64II::MO_G3).addImm(48);
1169*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
1170*9880d681SAndroid Build Coastguard Worker .addReg(Reg, RegState::Kill)
1171*9880d681SAndroid Build Coastguard Worker .addGlobalAddress(GV, 0, AArch64II::MO_G2 | MO_NC).addImm(32);
1172*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
1173*9880d681SAndroid Build Coastguard Worker .addReg(Reg, RegState::Kill)
1174*9880d681SAndroid Build Coastguard Worker .addGlobalAddress(GV, 0, AArch64II::MO_G1 | MO_NC).addImm(16);
1175*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
1176*9880d681SAndroid Build Coastguard Worker .addReg(Reg, RegState::Kill)
1177*9880d681SAndroid Build Coastguard Worker .addGlobalAddress(GV, 0, AArch64II::MO_G0 | MO_NC).addImm(0);
1178*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
1179*9880d681SAndroid Build Coastguard Worker .addReg(Reg, RegState::Kill)
1180*9880d681SAndroid Build Coastguard Worker .addImm(0)
1181*9880d681SAndroid Build Coastguard Worker .addMemOperand(*MI.memoperands_begin());
1182*9880d681SAndroid Build Coastguard Worker } else {
1183*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MI, DL, get(AArch64::ADRP), Reg)
1184*9880d681SAndroid Build Coastguard Worker .addGlobalAddress(GV, 0, OpFlags | AArch64II::MO_PAGE);
1185*9880d681SAndroid Build Coastguard Worker unsigned char LoFlags = OpFlags | AArch64II::MO_PAGEOFF | MO_NC;
1186*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
1187*9880d681SAndroid Build Coastguard Worker .addReg(Reg, RegState::Kill)
1188*9880d681SAndroid Build Coastguard Worker .addGlobalAddress(GV, 0, LoFlags)
1189*9880d681SAndroid Build Coastguard Worker .addMemOperand(*MI.memoperands_begin());
1190*9880d681SAndroid Build Coastguard Worker }
1191*9880d681SAndroid Build Coastguard Worker
1192*9880d681SAndroid Build Coastguard Worker MBB.erase(MI);
1193*9880d681SAndroid Build Coastguard Worker
1194*9880d681SAndroid Build Coastguard Worker return true;
1195*9880d681SAndroid Build Coastguard Worker }
1196*9880d681SAndroid Build Coastguard Worker
1197*9880d681SAndroid Build Coastguard Worker /// Return true if this is this instruction has a non-zero immediate
hasShiftedReg(const MachineInstr & MI) const1198*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::hasShiftedReg(const MachineInstr &MI) const {
1199*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
1200*9880d681SAndroid Build Coastguard Worker default:
1201*9880d681SAndroid Build Coastguard Worker break;
1202*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWrs:
1203*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXrs:
1204*9880d681SAndroid Build Coastguard Worker case AArch64::ADDWrs:
1205*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXrs:
1206*9880d681SAndroid Build Coastguard Worker case AArch64::ANDSWrs:
1207*9880d681SAndroid Build Coastguard Worker case AArch64::ANDSXrs:
1208*9880d681SAndroid Build Coastguard Worker case AArch64::ANDWrs:
1209*9880d681SAndroid Build Coastguard Worker case AArch64::ANDXrs:
1210*9880d681SAndroid Build Coastguard Worker case AArch64::BICSWrs:
1211*9880d681SAndroid Build Coastguard Worker case AArch64::BICSXrs:
1212*9880d681SAndroid Build Coastguard Worker case AArch64::BICWrs:
1213*9880d681SAndroid Build Coastguard Worker case AArch64::BICXrs:
1214*9880d681SAndroid Build Coastguard Worker case AArch64::CRC32Brr:
1215*9880d681SAndroid Build Coastguard Worker case AArch64::CRC32CBrr:
1216*9880d681SAndroid Build Coastguard Worker case AArch64::CRC32CHrr:
1217*9880d681SAndroid Build Coastguard Worker case AArch64::CRC32CWrr:
1218*9880d681SAndroid Build Coastguard Worker case AArch64::CRC32CXrr:
1219*9880d681SAndroid Build Coastguard Worker case AArch64::CRC32Hrr:
1220*9880d681SAndroid Build Coastguard Worker case AArch64::CRC32Wrr:
1221*9880d681SAndroid Build Coastguard Worker case AArch64::CRC32Xrr:
1222*9880d681SAndroid Build Coastguard Worker case AArch64::EONWrs:
1223*9880d681SAndroid Build Coastguard Worker case AArch64::EONXrs:
1224*9880d681SAndroid Build Coastguard Worker case AArch64::EORWrs:
1225*9880d681SAndroid Build Coastguard Worker case AArch64::EORXrs:
1226*9880d681SAndroid Build Coastguard Worker case AArch64::ORNWrs:
1227*9880d681SAndroid Build Coastguard Worker case AArch64::ORNXrs:
1228*9880d681SAndroid Build Coastguard Worker case AArch64::ORRWrs:
1229*9880d681SAndroid Build Coastguard Worker case AArch64::ORRXrs:
1230*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWrs:
1231*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXrs:
1232*9880d681SAndroid Build Coastguard Worker case AArch64::SUBWrs:
1233*9880d681SAndroid Build Coastguard Worker case AArch64::SUBXrs:
1234*9880d681SAndroid Build Coastguard Worker if (MI.getOperand(3).isImm()) {
1235*9880d681SAndroid Build Coastguard Worker unsigned val = MI.getOperand(3).getImm();
1236*9880d681SAndroid Build Coastguard Worker return (val != 0);
1237*9880d681SAndroid Build Coastguard Worker }
1238*9880d681SAndroid Build Coastguard Worker break;
1239*9880d681SAndroid Build Coastguard Worker }
1240*9880d681SAndroid Build Coastguard Worker return false;
1241*9880d681SAndroid Build Coastguard Worker }
1242*9880d681SAndroid Build Coastguard Worker
1243*9880d681SAndroid Build Coastguard Worker /// Return true if this is this instruction has a non-zero immediate
hasExtendedReg(const MachineInstr & MI) const1244*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::hasExtendedReg(const MachineInstr &MI) const {
1245*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
1246*9880d681SAndroid Build Coastguard Worker default:
1247*9880d681SAndroid Build Coastguard Worker break;
1248*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWrx:
1249*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXrx:
1250*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXrx64:
1251*9880d681SAndroid Build Coastguard Worker case AArch64::ADDWrx:
1252*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXrx:
1253*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXrx64:
1254*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWrx:
1255*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXrx:
1256*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXrx64:
1257*9880d681SAndroid Build Coastguard Worker case AArch64::SUBWrx:
1258*9880d681SAndroid Build Coastguard Worker case AArch64::SUBXrx:
1259*9880d681SAndroid Build Coastguard Worker case AArch64::SUBXrx64:
1260*9880d681SAndroid Build Coastguard Worker if (MI.getOperand(3).isImm()) {
1261*9880d681SAndroid Build Coastguard Worker unsigned val = MI.getOperand(3).getImm();
1262*9880d681SAndroid Build Coastguard Worker return (val != 0);
1263*9880d681SAndroid Build Coastguard Worker }
1264*9880d681SAndroid Build Coastguard Worker break;
1265*9880d681SAndroid Build Coastguard Worker }
1266*9880d681SAndroid Build Coastguard Worker
1267*9880d681SAndroid Build Coastguard Worker return false;
1268*9880d681SAndroid Build Coastguard Worker }
1269*9880d681SAndroid Build Coastguard Worker
1270*9880d681SAndroid Build Coastguard Worker // Return true if this instruction simply sets its single destination register
1271*9880d681SAndroid Build Coastguard Worker // to zero. This is equivalent to a register rename of the zero-register.
isGPRZero(const MachineInstr & MI) const1272*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::isGPRZero(const MachineInstr &MI) const {
1273*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
1274*9880d681SAndroid Build Coastguard Worker default:
1275*9880d681SAndroid Build Coastguard Worker break;
1276*9880d681SAndroid Build Coastguard Worker case AArch64::MOVZWi:
1277*9880d681SAndroid Build Coastguard Worker case AArch64::MOVZXi: // movz Rd, #0 (LSL #0)
1278*9880d681SAndroid Build Coastguard Worker if (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) {
1279*9880d681SAndroid Build Coastguard Worker assert(MI.getDesc().getNumOperands() == 3 &&
1280*9880d681SAndroid Build Coastguard Worker MI.getOperand(2).getImm() == 0 && "invalid MOVZi operands");
1281*9880d681SAndroid Build Coastguard Worker return true;
1282*9880d681SAndroid Build Coastguard Worker }
1283*9880d681SAndroid Build Coastguard Worker break;
1284*9880d681SAndroid Build Coastguard Worker case AArch64::ANDWri: // and Rd, Rzr, #imm
1285*9880d681SAndroid Build Coastguard Worker return MI.getOperand(1).getReg() == AArch64::WZR;
1286*9880d681SAndroid Build Coastguard Worker case AArch64::ANDXri:
1287*9880d681SAndroid Build Coastguard Worker return MI.getOperand(1).getReg() == AArch64::XZR;
1288*9880d681SAndroid Build Coastguard Worker case TargetOpcode::COPY:
1289*9880d681SAndroid Build Coastguard Worker return MI.getOperand(1).getReg() == AArch64::WZR;
1290*9880d681SAndroid Build Coastguard Worker }
1291*9880d681SAndroid Build Coastguard Worker return false;
1292*9880d681SAndroid Build Coastguard Worker }
1293*9880d681SAndroid Build Coastguard Worker
1294*9880d681SAndroid Build Coastguard Worker // Return true if this instruction simply renames a general register without
1295*9880d681SAndroid Build Coastguard Worker // modifying bits.
isGPRCopy(const MachineInstr & MI) const1296*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::isGPRCopy(const MachineInstr &MI) const {
1297*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
1298*9880d681SAndroid Build Coastguard Worker default:
1299*9880d681SAndroid Build Coastguard Worker break;
1300*9880d681SAndroid Build Coastguard Worker case TargetOpcode::COPY: {
1301*9880d681SAndroid Build Coastguard Worker // GPR32 copies will by lowered to ORRXrs
1302*9880d681SAndroid Build Coastguard Worker unsigned DstReg = MI.getOperand(0).getReg();
1303*9880d681SAndroid Build Coastguard Worker return (AArch64::GPR32RegClass.contains(DstReg) ||
1304*9880d681SAndroid Build Coastguard Worker AArch64::GPR64RegClass.contains(DstReg));
1305*9880d681SAndroid Build Coastguard Worker }
1306*9880d681SAndroid Build Coastguard Worker case AArch64::ORRXrs: // orr Xd, Xzr, Xm (LSL #0)
1307*9880d681SAndroid Build Coastguard Worker if (MI.getOperand(1).getReg() == AArch64::XZR) {
1308*9880d681SAndroid Build Coastguard Worker assert(MI.getDesc().getNumOperands() == 4 &&
1309*9880d681SAndroid Build Coastguard Worker MI.getOperand(3).getImm() == 0 && "invalid ORRrs operands");
1310*9880d681SAndroid Build Coastguard Worker return true;
1311*9880d681SAndroid Build Coastguard Worker }
1312*9880d681SAndroid Build Coastguard Worker break;
1313*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXri: // add Xd, Xn, #0 (LSL #0)
1314*9880d681SAndroid Build Coastguard Worker if (MI.getOperand(2).getImm() == 0) {
1315*9880d681SAndroid Build Coastguard Worker assert(MI.getDesc().getNumOperands() == 4 &&
1316*9880d681SAndroid Build Coastguard Worker MI.getOperand(3).getImm() == 0 && "invalid ADDXri operands");
1317*9880d681SAndroid Build Coastguard Worker return true;
1318*9880d681SAndroid Build Coastguard Worker }
1319*9880d681SAndroid Build Coastguard Worker break;
1320*9880d681SAndroid Build Coastguard Worker }
1321*9880d681SAndroid Build Coastguard Worker return false;
1322*9880d681SAndroid Build Coastguard Worker }
1323*9880d681SAndroid Build Coastguard Worker
1324*9880d681SAndroid Build Coastguard Worker // Return true if this instruction simply renames a general register without
1325*9880d681SAndroid Build Coastguard Worker // modifying bits.
isFPRCopy(const MachineInstr & MI) const1326*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::isFPRCopy(const MachineInstr &MI) const {
1327*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
1328*9880d681SAndroid Build Coastguard Worker default:
1329*9880d681SAndroid Build Coastguard Worker break;
1330*9880d681SAndroid Build Coastguard Worker case TargetOpcode::COPY: {
1331*9880d681SAndroid Build Coastguard Worker // FPR64 copies will by lowered to ORR.16b
1332*9880d681SAndroid Build Coastguard Worker unsigned DstReg = MI.getOperand(0).getReg();
1333*9880d681SAndroid Build Coastguard Worker return (AArch64::FPR64RegClass.contains(DstReg) ||
1334*9880d681SAndroid Build Coastguard Worker AArch64::FPR128RegClass.contains(DstReg));
1335*9880d681SAndroid Build Coastguard Worker }
1336*9880d681SAndroid Build Coastguard Worker case AArch64::ORRv16i8:
1337*9880d681SAndroid Build Coastguard Worker if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
1338*9880d681SAndroid Build Coastguard Worker assert(MI.getDesc().getNumOperands() == 3 && MI.getOperand(0).isReg() &&
1339*9880d681SAndroid Build Coastguard Worker "invalid ORRv16i8 operands");
1340*9880d681SAndroid Build Coastguard Worker return true;
1341*9880d681SAndroid Build Coastguard Worker }
1342*9880d681SAndroid Build Coastguard Worker break;
1343*9880d681SAndroid Build Coastguard Worker }
1344*9880d681SAndroid Build Coastguard Worker return false;
1345*9880d681SAndroid Build Coastguard Worker }
1346*9880d681SAndroid Build Coastguard Worker
isLoadFromStackSlot(const MachineInstr & MI,int & FrameIndex) const1347*9880d681SAndroid Build Coastguard Worker unsigned AArch64InstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
1348*9880d681SAndroid Build Coastguard Worker int &FrameIndex) const {
1349*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
1350*9880d681SAndroid Build Coastguard Worker default:
1351*9880d681SAndroid Build Coastguard Worker break;
1352*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
1353*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXui:
1354*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBui:
1355*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHui:
1356*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSui:
1357*9880d681SAndroid Build Coastguard Worker case AArch64::LDRDui:
1358*9880d681SAndroid Build Coastguard Worker case AArch64::LDRQui:
1359*9880d681SAndroid Build Coastguard Worker if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
1360*9880d681SAndroid Build Coastguard Worker MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
1361*9880d681SAndroid Build Coastguard Worker FrameIndex = MI.getOperand(1).getIndex();
1362*9880d681SAndroid Build Coastguard Worker return MI.getOperand(0).getReg();
1363*9880d681SAndroid Build Coastguard Worker }
1364*9880d681SAndroid Build Coastguard Worker break;
1365*9880d681SAndroid Build Coastguard Worker }
1366*9880d681SAndroid Build Coastguard Worker
1367*9880d681SAndroid Build Coastguard Worker return 0;
1368*9880d681SAndroid Build Coastguard Worker }
1369*9880d681SAndroid Build Coastguard Worker
isStoreToStackSlot(const MachineInstr & MI,int & FrameIndex) const1370*9880d681SAndroid Build Coastguard Worker unsigned AArch64InstrInfo::isStoreToStackSlot(const MachineInstr &MI,
1371*9880d681SAndroid Build Coastguard Worker int &FrameIndex) const {
1372*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
1373*9880d681SAndroid Build Coastguard Worker default:
1374*9880d681SAndroid Build Coastguard Worker break;
1375*9880d681SAndroid Build Coastguard Worker case AArch64::STRWui:
1376*9880d681SAndroid Build Coastguard Worker case AArch64::STRXui:
1377*9880d681SAndroid Build Coastguard Worker case AArch64::STRBui:
1378*9880d681SAndroid Build Coastguard Worker case AArch64::STRHui:
1379*9880d681SAndroid Build Coastguard Worker case AArch64::STRSui:
1380*9880d681SAndroid Build Coastguard Worker case AArch64::STRDui:
1381*9880d681SAndroid Build Coastguard Worker case AArch64::STRQui:
1382*9880d681SAndroid Build Coastguard Worker if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
1383*9880d681SAndroid Build Coastguard Worker MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
1384*9880d681SAndroid Build Coastguard Worker FrameIndex = MI.getOperand(1).getIndex();
1385*9880d681SAndroid Build Coastguard Worker return MI.getOperand(0).getReg();
1386*9880d681SAndroid Build Coastguard Worker }
1387*9880d681SAndroid Build Coastguard Worker break;
1388*9880d681SAndroid Build Coastguard Worker }
1389*9880d681SAndroid Build Coastguard Worker return 0;
1390*9880d681SAndroid Build Coastguard Worker }
1391*9880d681SAndroid Build Coastguard Worker
1392*9880d681SAndroid Build Coastguard Worker /// Return true if this is load/store scales or extends its register offset.
1393*9880d681SAndroid Build Coastguard Worker /// This refers to scaling a dynamic index as opposed to scaled immediates.
1394*9880d681SAndroid Build Coastguard Worker /// MI should be a memory op that allows scaled addressing.
isScaledAddr(const MachineInstr & MI) const1395*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::isScaledAddr(const MachineInstr &MI) const {
1396*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
1397*9880d681SAndroid Build Coastguard Worker default:
1398*9880d681SAndroid Build Coastguard Worker break;
1399*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBroW:
1400*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBroW:
1401*9880d681SAndroid Build Coastguard Worker case AArch64::LDRDroW:
1402*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHroW:
1403*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHroW:
1404*9880d681SAndroid Build Coastguard Worker case AArch64::LDRQroW:
1405*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBWroW:
1406*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBXroW:
1407*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHWroW:
1408*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHXroW:
1409*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWroW:
1410*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSroW:
1411*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWroW:
1412*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXroW:
1413*9880d681SAndroid Build Coastguard Worker case AArch64::STRBBroW:
1414*9880d681SAndroid Build Coastguard Worker case AArch64::STRBroW:
1415*9880d681SAndroid Build Coastguard Worker case AArch64::STRDroW:
1416*9880d681SAndroid Build Coastguard Worker case AArch64::STRHHroW:
1417*9880d681SAndroid Build Coastguard Worker case AArch64::STRHroW:
1418*9880d681SAndroid Build Coastguard Worker case AArch64::STRQroW:
1419*9880d681SAndroid Build Coastguard Worker case AArch64::STRSroW:
1420*9880d681SAndroid Build Coastguard Worker case AArch64::STRWroW:
1421*9880d681SAndroid Build Coastguard Worker case AArch64::STRXroW:
1422*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBroX:
1423*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBroX:
1424*9880d681SAndroid Build Coastguard Worker case AArch64::LDRDroX:
1425*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHroX:
1426*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHroX:
1427*9880d681SAndroid Build Coastguard Worker case AArch64::LDRQroX:
1428*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBWroX:
1429*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBXroX:
1430*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHWroX:
1431*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHXroX:
1432*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWroX:
1433*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSroX:
1434*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWroX:
1435*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXroX:
1436*9880d681SAndroid Build Coastguard Worker case AArch64::STRBBroX:
1437*9880d681SAndroid Build Coastguard Worker case AArch64::STRBroX:
1438*9880d681SAndroid Build Coastguard Worker case AArch64::STRDroX:
1439*9880d681SAndroid Build Coastguard Worker case AArch64::STRHHroX:
1440*9880d681SAndroid Build Coastguard Worker case AArch64::STRHroX:
1441*9880d681SAndroid Build Coastguard Worker case AArch64::STRQroX:
1442*9880d681SAndroid Build Coastguard Worker case AArch64::STRSroX:
1443*9880d681SAndroid Build Coastguard Worker case AArch64::STRWroX:
1444*9880d681SAndroid Build Coastguard Worker case AArch64::STRXroX:
1445*9880d681SAndroid Build Coastguard Worker
1446*9880d681SAndroid Build Coastguard Worker unsigned Val = MI.getOperand(3).getImm();
1447*9880d681SAndroid Build Coastguard Worker AArch64_AM::ShiftExtendType ExtType = AArch64_AM::getMemExtendType(Val);
1448*9880d681SAndroid Build Coastguard Worker return (ExtType != AArch64_AM::UXTX) || AArch64_AM::getMemDoShift(Val);
1449*9880d681SAndroid Build Coastguard Worker }
1450*9880d681SAndroid Build Coastguard Worker return false;
1451*9880d681SAndroid Build Coastguard Worker }
1452*9880d681SAndroid Build Coastguard Worker
1453*9880d681SAndroid Build Coastguard Worker /// Check all MachineMemOperands for a hint to suppress pairing.
isLdStPairSuppressed(const MachineInstr & MI) const1454*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::isLdStPairSuppressed(const MachineInstr &MI) const {
1455*9880d681SAndroid Build Coastguard Worker return any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
1456*9880d681SAndroid Build Coastguard Worker return MMO->getFlags() & MOSuppressPair;
1457*9880d681SAndroid Build Coastguard Worker });
1458*9880d681SAndroid Build Coastguard Worker }
1459*9880d681SAndroid Build Coastguard Worker
1460*9880d681SAndroid Build Coastguard Worker /// Set a flag on the first MachineMemOperand to suppress pairing.
suppressLdStPair(MachineInstr & MI) const1461*9880d681SAndroid Build Coastguard Worker void AArch64InstrInfo::suppressLdStPair(MachineInstr &MI) const {
1462*9880d681SAndroid Build Coastguard Worker if (MI.memoperands_empty())
1463*9880d681SAndroid Build Coastguard Worker return;
1464*9880d681SAndroid Build Coastguard Worker (*MI.memoperands_begin())->setFlags(MOSuppressPair);
1465*9880d681SAndroid Build Coastguard Worker }
1466*9880d681SAndroid Build Coastguard Worker
isUnscaledLdSt(unsigned Opc) const1467*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::isUnscaledLdSt(unsigned Opc) const {
1468*9880d681SAndroid Build Coastguard Worker switch (Opc) {
1469*9880d681SAndroid Build Coastguard Worker default:
1470*9880d681SAndroid Build Coastguard Worker return false;
1471*9880d681SAndroid Build Coastguard Worker case AArch64::STURSi:
1472*9880d681SAndroid Build Coastguard Worker case AArch64::STURDi:
1473*9880d681SAndroid Build Coastguard Worker case AArch64::STURQi:
1474*9880d681SAndroid Build Coastguard Worker case AArch64::STURBBi:
1475*9880d681SAndroid Build Coastguard Worker case AArch64::STURHHi:
1476*9880d681SAndroid Build Coastguard Worker case AArch64::STURWi:
1477*9880d681SAndroid Build Coastguard Worker case AArch64::STURXi:
1478*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSi:
1479*9880d681SAndroid Build Coastguard Worker case AArch64::LDURDi:
1480*9880d681SAndroid Build Coastguard Worker case AArch64::LDURQi:
1481*9880d681SAndroid Build Coastguard Worker case AArch64::LDURWi:
1482*9880d681SAndroid Build Coastguard Worker case AArch64::LDURXi:
1483*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSWi:
1484*9880d681SAndroid Build Coastguard Worker case AArch64::LDURHHi:
1485*9880d681SAndroid Build Coastguard Worker case AArch64::LDURBBi:
1486*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSBWi:
1487*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSHWi:
1488*9880d681SAndroid Build Coastguard Worker return true;
1489*9880d681SAndroid Build Coastguard Worker }
1490*9880d681SAndroid Build Coastguard Worker }
1491*9880d681SAndroid Build Coastguard Worker
isUnscaledLdSt(MachineInstr & MI) const1492*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::isUnscaledLdSt(MachineInstr &MI) const {
1493*9880d681SAndroid Build Coastguard Worker return isUnscaledLdSt(MI.getOpcode());
1494*9880d681SAndroid Build Coastguard Worker }
1495*9880d681SAndroid Build Coastguard Worker
1496*9880d681SAndroid Build Coastguard Worker // Is this a candidate for ld/st merging or pairing? For example, we don't
1497*9880d681SAndroid Build Coastguard Worker // touch volatiles or load/stores that have a hint to avoid pair formation.
isCandidateToMergeOrPair(MachineInstr & MI) const1498*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::isCandidateToMergeOrPair(MachineInstr &MI) const {
1499*9880d681SAndroid Build Coastguard Worker // If this is a volatile load/store, don't mess with it.
1500*9880d681SAndroid Build Coastguard Worker if (MI.hasOrderedMemoryRef())
1501*9880d681SAndroid Build Coastguard Worker return false;
1502*9880d681SAndroid Build Coastguard Worker
1503*9880d681SAndroid Build Coastguard Worker // Make sure this is a reg+imm (as opposed to an address reloc).
1504*9880d681SAndroid Build Coastguard Worker assert(MI.getOperand(1).isReg() && "Expected a reg operand.");
1505*9880d681SAndroid Build Coastguard Worker if (!MI.getOperand(2).isImm())
1506*9880d681SAndroid Build Coastguard Worker return false;
1507*9880d681SAndroid Build Coastguard Worker
1508*9880d681SAndroid Build Coastguard Worker // Can't merge/pair if the instruction modifies the base register.
1509*9880d681SAndroid Build Coastguard Worker // e.g., ldr x0, [x0]
1510*9880d681SAndroid Build Coastguard Worker unsigned BaseReg = MI.getOperand(1).getReg();
1511*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = &getRegisterInfo();
1512*9880d681SAndroid Build Coastguard Worker if (MI.modifiesRegister(BaseReg, TRI))
1513*9880d681SAndroid Build Coastguard Worker return false;
1514*9880d681SAndroid Build Coastguard Worker
1515*9880d681SAndroid Build Coastguard Worker // Check if this load/store has a hint to avoid pair formation.
1516*9880d681SAndroid Build Coastguard Worker // MachineMemOperands hints are set by the AArch64StorePairSuppress pass.
1517*9880d681SAndroid Build Coastguard Worker if (isLdStPairSuppressed(MI))
1518*9880d681SAndroid Build Coastguard Worker return false;
1519*9880d681SAndroid Build Coastguard Worker
1520*9880d681SAndroid Build Coastguard Worker // On some CPUs quad load/store pairs are slower than two single load/stores.
1521*9880d681SAndroid Build Coastguard Worker if (Subtarget.avoidQuadLdStPairs()) {
1522*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
1523*9880d681SAndroid Build Coastguard Worker default:
1524*9880d681SAndroid Build Coastguard Worker break;
1525*9880d681SAndroid Build Coastguard Worker
1526*9880d681SAndroid Build Coastguard Worker case AArch64::LDURQi:
1527*9880d681SAndroid Build Coastguard Worker case AArch64::STURQi:
1528*9880d681SAndroid Build Coastguard Worker case AArch64::LDRQui:
1529*9880d681SAndroid Build Coastguard Worker case AArch64::STRQui:
1530*9880d681SAndroid Build Coastguard Worker return false;
1531*9880d681SAndroid Build Coastguard Worker }
1532*9880d681SAndroid Build Coastguard Worker }
1533*9880d681SAndroid Build Coastguard Worker
1534*9880d681SAndroid Build Coastguard Worker return true;
1535*9880d681SAndroid Build Coastguard Worker }
1536*9880d681SAndroid Build Coastguard Worker
getMemOpBaseRegImmOfs(MachineInstr & LdSt,unsigned & BaseReg,int64_t & Offset,const TargetRegisterInfo * TRI) const1537*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::getMemOpBaseRegImmOfs(
1538*9880d681SAndroid Build Coastguard Worker MachineInstr &LdSt, unsigned &BaseReg, int64_t &Offset,
1539*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI) const {
1540*9880d681SAndroid Build Coastguard Worker switch (LdSt.getOpcode()) {
1541*9880d681SAndroid Build Coastguard Worker default:
1542*9880d681SAndroid Build Coastguard Worker return false;
1543*9880d681SAndroid Build Coastguard Worker // Scaled instructions.
1544*9880d681SAndroid Build Coastguard Worker case AArch64::STRSui:
1545*9880d681SAndroid Build Coastguard Worker case AArch64::STRDui:
1546*9880d681SAndroid Build Coastguard Worker case AArch64::STRQui:
1547*9880d681SAndroid Build Coastguard Worker case AArch64::STRXui:
1548*9880d681SAndroid Build Coastguard Worker case AArch64::STRWui:
1549*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSui:
1550*9880d681SAndroid Build Coastguard Worker case AArch64::LDRDui:
1551*9880d681SAndroid Build Coastguard Worker case AArch64::LDRQui:
1552*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXui:
1553*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
1554*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWui:
1555*9880d681SAndroid Build Coastguard Worker // Unscaled instructions.
1556*9880d681SAndroid Build Coastguard Worker case AArch64::STURSi:
1557*9880d681SAndroid Build Coastguard Worker case AArch64::STURDi:
1558*9880d681SAndroid Build Coastguard Worker case AArch64::STURQi:
1559*9880d681SAndroid Build Coastguard Worker case AArch64::STURXi:
1560*9880d681SAndroid Build Coastguard Worker case AArch64::STURWi:
1561*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSi:
1562*9880d681SAndroid Build Coastguard Worker case AArch64::LDURDi:
1563*9880d681SAndroid Build Coastguard Worker case AArch64::LDURQi:
1564*9880d681SAndroid Build Coastguard Worker case AArch64::LDURWi:
1565*9880d681SAndroid Build Coastguard Worker case AArch64::LDURXi:
1566*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSWi:
1567*9880d681SAndroid Build Coastguard Worker unsigned Width;
1568*9880d681SAndroid Build Coastguard Worker return getMemOpBaseRegImmOfsWidth(LdSt, BaseReg, Offset, Width, TRI);
1569*9880d681SAndroid Build Coastguard Worker };
1570*9880d681SAndroid Build Coastguard Worker }
1571*9880d681SAndroid Build Coastguard Worker
getMemOpBaseRegImmOfsWidth(MachineInstr & LdSt,unsigned & BaseReg,int64_t & Offset,unsigned & Width,const TargetRegisterInfo * TRI) const1572*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::getMemOpBaseRegImmOfsWidth(
1573*9880d681SAndroid Build Coastguard Worker MachineInstr &LdSt, unsigned &BaseReg, int64_t &Offset, unsigned &Width,
1574*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI) const {
1575*9880d681SAndroid Build Coastguard Worker assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
1576*9880d681SAndroid Build Coastguard Worker // Handle only loads/stores with base register followed by immediate offset.
1577*9880d681SAndroid Build Coastguard Worker if (LdSt.getNumExplicitOperands() == 3) {
1578*9880d681SAndroid Build Coastguard Worker // Non-paired instruction (e.g., ldr x1, [x0, #8]).
1579*9880d681SAndroid Build Coastguard Worker if (!LdSt.getOperand(1).isReg() || !LdSt.getOperand(2).isImm())
1580*9880d681SAndroid Build Coastguard Worker return false;
1581*9880d681SAndroid Build Coastguard Worker } else if (LdSt.getNumExplicitOperands() == 4) {
1582*9880d681SAndroid Build Coastguard Worker // Paired instruction (e.g., ldp x1, x2, [x0, #8]).
1583*9880d681SAndroid Build Coastguard Worker if (!LdSt.getOperand(1).isReg() || !LdSt.getOperand(2).isReg() ||
1584*9880d681SAndroid Build Coastguard Worker !LdSt.getOperand(3).isImm())
1585*9880d681SAndroid Build Coastguard Worker return false;
1586*9880d681SAndroid Build Coastguard Worker } else
1587*9880d681SAndroid Build Coastguard Worker return false;
1588*9880d681SAndroid Build Coastguard Worker
1589*9880d681SAndroid Build Coastguard Worker // Offset is calculated as the immediate operand multiplied by the scaling factor.
1590*9880d681SAndroid Build Coastguard Worker // Unscaled instructions have scaling factor set to 1.
1591*9880d681SAndroid Build Coastguard Worker unsigned Scale = 0;
1592*9880d681SAndroid Build Coastguard Worker switch (LdSt.getOpcode()) {
1593*9880d681SAndroid Build Coastguard Worker default:
1594*9880d681SAndroid Build Coastguard Worker return false;
1595*9880d681SAndroid Build Coastguard Worker case AArch64::LDURQi:
1596*9880d681SAndroid Build Coastguard Worker case AArch64::STURQi:
1597*9880d681SAndroid Build Coastguard Worker Width = 16;
1598*9880d681SAndroid Build Coastguard Worker Scale = 1;
1599*9880d681SAndroid Build Coastguard Worker break;
1600*9880d681SAndroid Build Coastguard Worker case AArch64::LDURXi:
1601*9880d681SAndroid Build Coastguard Worker case AArch64::LDURDi:
1602*9880d681SAndroid Build Coastguard Worker case AArch64::STURXi:
1603*9880d681SAndroid Build Coastguard Worker case AArch64::STURDi:
1604*9880d681SAndroid Build Coastguard Worker Width = 8;
1605*9880d681SAndroid Build Coastguard Worker Scale = 1;
1606*9880d681SAndroid Build Coastguard Worker break;
1607*9880d681SAndroid Build Coastguard Worker case AArch64::LDURWi:
1608*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSi:
1609*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSWi:
1610*9880d681SAndroid Build Coastguard Worker case AArch64::STURWi:
1611*9880d681SAndroid Build Coastguard Worker case AArch64::STURSi:
1612*9880d681SAndroid Build Coastguard Worker Width = 4;
1613*9880d681SAndroid Build Coastguard Worker Scale = 1;
1614*9880d681SAndroid Build Coastguard Worker break;
1615*9880d681SAndroid Build Coastguard Worker case AArch64::LDURHi:
1616*9880d681SAndroid Build Coastguard Worker case AArch64::LDURHHi:
1617*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSHXi:
1618*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSHWi:
1619*9880d681SAndroid Build Coastguard Worker case AArch64::STURHi:
1620*9880d681SAndroid Build Coastguard Worker case AArch64::STURHHi:
1621*9880d681SAndroid Build Coastguard Worker Width = 2;
1622*9880d681SAndroid Build Coastguard Worker Scale = 1;
1623*9880d681SAndroid Build Coastguard Worker break;
1624*9880d681SAndroid Build Coastguard Worker case AArch64::LDURBi:
1625*9880d681SAndroid Build Coastguard Worker case AArch64::LDURBBi:
1626*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSBXi:
1627*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSBWi:
1628*9880d681SAndroid Build Coastguard Worker case AArch64::STURBi:
1629*9880d681SAndroid Build Coastguard Worker case AArch64::STURBBi:
1630*9880d681SAndroid Build Coastguard Worker Width = 1;
1631*9880d681SAndroid Build Coastguard Worker Scale = 1;
1632*9880d681SAndroid Build Coastguard Worker break;
1633*9880d681SAndroid Build Coastguard Worker case AArch64::LDPQi:
1634*9880d681SAndroid Build Coastguard Worker case AArch64::LDNPQi:
1635*9880d681SAndroid Build Coastguard Worker case AArch64::STPQi:
1636*9880d681SAndroid Build Coastguard Worker case AArch64::STNPQi:
1637*9880d681SAndroid Build Coastguard Worker Scale = 16;
1638*9880d681SAndroid Build Coastguard Worker Width = 32;
1639*9880d681SAndroid Build Coastguard Worker break;
1640*9880d681SAndroid Build Coastguard Worker case AArch64::LDRQui:
1641*9880d681SAndroid Build Coastguard Worker case AArch64::STRQui:
1642*9880d681SAndroid Build Coastguard Worker Scale = Width = 16;
1643*9880d681SAndroid Build Coastguard Worker break;
1644*9880d681SAndroid Build Coastguard Worker case AArch64::LDPXi:
1645*9880d681SAndroid Build Coastguard Worker case AArch64::LDPDi:
1646*9880d681SAndroid Build Coastguard Worker case AArch64::LDNPXi:
1647*9880d681SAndroid Build Coastguard Worker case AArch64::LDNPDi:
1648*9880d681SAndroid Build Coastguard Worker case AArch64::STPXi:
1649*9880d681SAndroid Build Coastguard Worker case AArch64::STPDi:
1650*9880d681SAndroid Build Coastguard Worker case AArch64::STNPXi:
1651*9880d681SAndroid Build Coastguard Worker case AArch64::STNPDi:
1652*9880d681SAndroid Build Coastguard Worker Scale = 8;
1653*9880d681SAndroid Build Coastguard Worker Width = 16;
1654*9880d681SAndroid Build Coastguard Worker break;
1655*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXui:
1656*9880d681SAndroid Build Coastguard Worker case AArch64::LDRDui:
1657*9880d681SAndroid Build Coastguard Worker case AArch64::STRXui:
1658*9880d681SAndroid Build Coastguard Worker case AArch64::STRDui:
1659*9880d681SAndroid Build Coastguard Worker Scale = Width = 8;
1660*9880d681SAndroid Build Coastguard Worker break;
1661*9880d681SAndroid Build Coastguard Worker case AArch64::LDPWi:
1662*9880d681SAndroid Build Coastguard Worker case AArch64::LDPSi:
1663*9880d681SAndroid Build Coastguard Worker case AArch64::LDNPWi:
1664*9880d681SAndroid Build Coastguard Worker case AArch64::LDNPSi:
1665*9880d681SAndroid Build Coastguard Worker case AArch64::STPWi:
1666*9880d681SAndroid Build Coastguard Worker case AArch64::STPSi:
1667*9880d681SAndroid Build Coastguard Worker case AArch64::STNPWi:
1668*9880d681SAndroid Build Coastguard Worker case AArch64::STNPSi:
1669*9880d681SAndroid Build Coastguard Worker Scale = 4;
1670*9880d681SAndroid Build Coastguard Worker Width = 8;
1671*9880d681SAndroid Build Coastguard Worker break;
1672*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
1673*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSui:
1674*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWui:
1675*9880d681SAndroid Build Coastguard Worker case AArch64::STRWui:
1676*9880d681SAndroid Build Coastguard Worker case AArch64::STRSui:
1677*9880d681SAndroid Build Coastguard Worker Scale = Width = 4;
1678*9880d681SAndroid Build Coastguard Worker break;
1679*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHui:
1680*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHui:
1681*9880d681SAndroid Build Coastguard Worker case AArch64::STRHui:
1682*9880d681SAndroid Build Coastguard Worker case AArch64::STRHHui:
1683*9880d681SAndroid Build Coastguard Worker Scale = Width = 2;
1684*9880d681SAndroid Build Coastguard Worker break;
1685*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBui:
1686*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBui:
1687*9880d681SAndroid Build Coastguard Worker case AArch64::STRBui:
1688*9880d681SAndroid Build Coastguard Worker case AArch64::STRBBui:
1689*9880d681SAndroid Build Coastguard Worker Scale = Width = 1;
1690*9880d681SAndroid Build Coastguard Worker break;
1691*9880d681SAndroid Build Coastguard Worker }
1692*9880d681SAndroid Build Coastguard Worker
1693*9880d681SAndroid Build Coastguard Worker if (LdSt.getNumExplicitOperands() == 3) {
1694*9880d681SAndroid Build Coastguard Worker BaseReg = LdSt.getOperand(1).getReg();
1695*9880d681SAndroid Build Coastguard Worker Offset = LdSt.getOperand(2).getImm() * Scale;
1696*9880d681SAndroid Build Coastguard Worker } else {
1697*9880d681SAndroid Build Coastguard Worker assert(LdSt.getNumExplicitOperands() == 4 && "invalid number of operands");
1698*9880d681SAndroid Build Coastguard Worker BaseReg = LdSt.getOperand(2).getReg();
1699*9880d681SAndroid Build Coastguard Worker Offset = LdSt.getOperand(3).getImm() * Scale;
1700*9880d681SAndroid Build Coastguard Worker }
1701*9880d681SAndroid Build Coastguard Worker return true;
1702*9880d681SAndroid Build Coastguard Worker }
1703*9880d681SAndroid Build Coastguard Worker
1704*9880d681SAndroid Build Coastguard Worker // Scale the unscaled offsets. Returns false if the unscaled offset can't be
1705*9880d681SAndroid Build Coastguard Worker // scaled.
scaleOffset(unsigned Opc,int64_t & Offset)1706*9880d681SAndroid Build Coastguard Worker static bool scaleOffset(unsigned Opc, int64_t &Offset) {
1707*9880d681SAndroid Build Coastguard Worker unsigned OffsetStride = 1;
1708*9880d681SAndroid Build Coastguard Worker switch (Opc) {
1709*9880d681SAndroid Build Coastguard Worker default:
1710*9880d681SAndroid Build Coastguard Worker return false;
1711*9880d681SAndroid Build Coastguard Worker case AArch64::LDURQi:
1712*9880d681SAndroid Build Coastguard Worker case AArch64::STURQi:
1713*9880d681SAndroid Build Coastguard Worker OffsetStride = 16;
1714*9880d681SAndroid Build Coastguard Worker break;
1715*9880d681SAndroid Build Coastguard Worker case AArch64::LDURXi:
1716*9880d681SAndroid Build Coastguard Worker case AArch64::LDURDi:
1717*9880d681SAndroid Build Coastguard Worker case AArch64::STURXi:
1718*9880d681SAndroid Build Coastguard Worker case AArch64::STURDi:
1719*9880d681SAndroid Build Coastguard Worker OffsetStride = 8;
1720*9880d681SAndroid Build Coastguard Worker break;
1721*9880d681SAndroid Build Coastguard Worker case AArch64::LDURWi:
1722*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSi:
1723*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSWi:
1724*9880d681SAndroid Build Coastguard Worker case AArch64::STURWi:
1725*9880d681SAndroid Build Coastguard Worker case AArch64::STURSi:
1726*9880d681SAndroid Build Coastguard Worker OffsetStride = 4;
1727*9880d681SAndroid Build Coastguard Worker break;
1728*9880d681SAndroid Build Coastguard Worker }
1729*9880d681SAndroid Build Coastguard Worker // If the byte-offset isn't a multiple of the stride, we can't scale this
1730*9880d681SAndroid Build Coastguard Worker // offset.
1731*9880d681SAndroid Build Coastguard Worker if (Offset % OffsetStride != 0)
1732*9880d681SAndroid Build Coastguard Worker return false;
1733*9880d681SAndroid Build Coastguard Worker
1734*9880d681SAndroid Build Coastguard Worker // Convert the byte-offset used by unscaled into an "element" offset used
1735*9880d681SAndroid Build Coastguard Worker // by the scaled pair load/store instructions.
1736*9880d681SAndroid Build Coastguard Worker Offset /= OffsetStride;
1737*9880d681SAndroid Build Coastguard Worker return true;
1738*9880d681SAndroid Build Coastguard Worker }
1739*9880d681SAndroid Build Coastguard Worker
canPairLdStOpc(unsigned FirstOpc,unsigned SecondOpc)1740*9880d681SAndroid Build Coastguard Worker static bool canPairLdStOpc(unsigned FirstOpc, unsigned SecondOpc) {
1741*9880d681SAndroid Build Coastguard Worker if (FirstOpc == SecondOpc)
1742*9880d681SAndroid Build Coastguard Worker return true;
1743*9880d681SAndroid Build Coastguard Worker // We can also pair sign-ext and zero-ext instructions.
1744*9880d681SAndroid Build Coastguard Worker switch (FirstOpc) {
1745*9880d681SAndroid Build Coastguard Worker default:
1746*9880d681SAndroid Build Coastguard Worker return false;
1747*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
1748*9880d681SAndroid Build Coastguard Worker case AArch64::LDURWi:
1749*9880d681SAndroid Build Coastguard Worker return SecondOpc == AArch64::LDRSWui || SecondOpc == AArch64::LDURSWi;
1750*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWui:
1751*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSWi:
1752*9880d681SAndroid Build Coastguard Worker return SecondOpc == AArch64::LDRWui || SecondOpc == AArch64::LDURWi;
1753*9880d681SAndroid Build Coastguard Worker }
1754*9880d681SAndroid Build Coastguard Worker // These instructions can't be paired based on their opcodes.
1755*9880d681SAndroid Build Coastguard Worker return false;
1756*9880d681SAndroid Build Coastguard Worker }
1757*9880d681SAndroid Build Coastguard Worker
1758*9880d681SAndroid Build Coastguard Worker /// Detect opportunities for ldp/stp formation.
1759*9880d681SAndroid Build Coastguard Worker ///
1760*9880d681SAndroid Build Coastguard Worker /// Only called for LdSt for which getMemOpBaseRegImmOfs returns true.
shouldClusterMemOps(MachineInstr & FirstLdSt,MachineInstr & SecondLdSt,unsigned NumLoads) const1761*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::shouldClusterMemOps(MachineInstr &FirstLdSt,
1762*9880d681SAndroid Build Coastguard Worker MachineInstr &SecondLdSt,
1763*9880d681SAndroid Build Coastguard Worker unsigned NumLoads) const {
1764*9880d681SAndroid Build Coastguard Worker // Only cluster up to a single pair.
1765*9880d681SAndroid Build Coastguard Worker if (NumLoads > 1)
1766*9880d681SAndroid Build Coastguard Worker return false;
1767*9880d681SAndroid Build Coastguard Worker
1768*9880d681SAndroid Build Coastguard Worker // Can we pair these instructions based on their opcodes?
1769*9880d681SAndroid Build Coastguard Worker unsigned FirstOpc = FirstLdSt.getOpcode();
1770*9880d681SAndroid Build Coastguard Worker unsigned SecondOpc = SecondLdSt.getOpcode();
1771*9880d681SAndroid Build Coastguard Worker if (!canPairLdStOpc(FirstOpc, SecondOpc))
1772*9880d681SAndroid Build Coastguard Worker return false;
1773*9880d681SAndroid Build Coastguard Worker
1774*9880d681SAndroid Build Coastguard Worker // Can't merge volatiles or load/stores that have a hint to avoid pair
1775*9880d681SAndroid Build Coastguard Worker // formation, for example.
1776*9880d681SAndroid Build Coastguard Worker if (!isCandidateToMergeOrPair(FirstLdSt) ||
1777*9880d681SAndroid Build Coastguard Worker !isCandidateToMergeOrPair(SecondLdSt))
1778*9880d681SAndroid Build Coastguard Worker return false;
1779*9880d681SAndroid Build Coastguard Worker
1780*9880d681SAndroid Build Coastguard Worker // isCandidateToMergeOrPair guarantees that operand 2 is an immediate.
1781*9880d681SAndroid Build Coastguard Worker int64_t Offset1 = FirstLdSt.getOperand(2).getImm();
1782*9880d681SAndroid Build Coastguard Worker if (isUnscaledLdSt(FirstOpc) && !scaleOffset(FirstOpc, Offset1))
1783*9880d681SAndroid Build Coastguard Worker return false;
1784*9880d681SAndroid Build Coastguard Worker
1785*9880d681SAndroid Build Coastguard Worker int64_t Offset2 = SecondLdSt.getOperand(2).getImm();
1786*9880d681SAndroid Build Coastguard Worker if (isUnscaledLdSt(SecondOpc) && !scaleOffset(SecondOpc, Offset2))
1787*9880d681SAndroid Build Coastguard Worker return false;
1788*9880d681SAndroid Build Coastguard Worker
1789*9880d681SAndroid Build Coastguard Worker // Pairwise instructions have a 7-bit signed offset field.
1790*9880d681SAndroid Build Coastguard Worker if (Offset1 > 63 || Offset1 < -64)
1791*9880d681SAndroid Build Coastguard Worker return false;
1792*9880d681SAndroid Build Coastguard Worker
1793*9880d681SAndroid Build Coastguard Worker // The caller should already have ordered First/SecondLdSt by offset.
1794*9880d681SAndroid Build Coastguard Worker assert(Offset1 <= Offset2 && "Caller should have ordered offsets.");
1795*9880d681SAndroid Build Coastguard Worker return Offset1 + 1 == Offset2;
1796*9880d681SAndroid Build Coastguard Worker }
1797*9880d681SAndroid Build Coastguard Worker
shouldScheduleAdjacent(MachineInstr & First,MachineInstr & Second) const1798*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::shouldScheduleAdjacent(MachineInstr &First,
1799*9880d681SAndroid Build Coastguard Worker MachineInstr &Second) const {
1800*9880d681SAndroid Build Coastguard Worker if (Subtarget.hasMacroOpFusion()) {
1801*9880d681SAndroid Build Coastguard Worker // Fuse CMN, CMP, TST followed by Bcc.
1802*9880d681SAndroid Build Coastguard Worker unsigned SecondOpcode = Second.getOpcode();
1803*9880d681SAndroid Build Coastguard Worker if (SecondOpcode == AArch64::Bcc) {
1804*9880d681SAndroid Build Coastguard Worker switch (First.getOpcode()) {
1805*9880d681SAndroid Build Coastguard Worker default:
1806*9880d681SAndroid Build Coastguard Worker return false;
1807*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWri:
1808*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWri:
1809*9880d681SAndroid Build Coastguard Worker case AArch64::ANDSWri:
1810*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXri:
1811*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXri:
1812*9880d681SAndroid Build Coastguard Worker case AArch64::ANDSXri:
1813*9880d681SAndroid Build Coastguard Worker return true;
1814*9880d681SAndroid Build Coastguard Worker }
1815*9880d681SAndroid Build Coastguard Worker }
1816*9880d681SAndroid Build Coastguard Worker // Fuse ALU operations followed by CBZ/CBNZ.
1817*9880d681SAndroid Build Coastguard Worker if (SecondOpcode == AArch64::CBNZW || SecondOpcode == AArch64::CBNZX ||
1818*9880d681SAndroid Build Coastguard Worker SecondOpcode == AArch64::CBZW || SecondOpcode == AArch64::CBZX) {
1819*9880d681SAndroid Build Coastguard Worker switch (First.getOpcode()) {
1820*9880d681SAndroid Build Coastguard Worker default:
1821*9880d681SAndroid Build Coastguard Worker return false;
1822*9880d681SAndroid Build Coastguard Worker case AArch64::ADDWri:
1823*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXri:
1824*9880d681SAndroid Build Coastguard Worker case AArch64::ANDWri:
1825*9880d681SAndroid Build Coastguard Worker case AArch64::ANDXri:
1826*9880d681SAndroid Build Coastguard Worker case AArch64::EORWri:
1827*9880d681SAndroid Build Coastguard Worker case AArch64::EORXri:
1828*9880d681SAndroid Build Coastguard Worker case AArch64::ORRWri:
1829*9880d681SAndroid Build Coastguard Worker case AArch64::ORRXri:
1830*9880d681SAndroid Build Coastguard Worker case AArch64::SUBWri:
1831*9880d681SAndroid Build Coastguard Worker case AArch64::SUBXri:
1832*9880d681SAndroid Build Coastguard Worker return true;
1833*9880d681SAndroid Build Coastguard Worker }
1834*9880d681SAndroid Build Coastguard Worker }
1835*9880d681SAndroid Build Coastguard Worker }
1836*9880d681SAndroid Build Coastguard Worker return false;
1837*9880d681SAndroid Build Coastguard Worker }
1838*9880d681SAndroid Build Coastguard Worker
emitFrameIndexDebugValue(MachineFunction & MF,int FrameIx,uint64_t Offset,const MDNode * Var,const MDNode * Expr,const DebugLoc & DL) const1839*9880d681SAndroid Build Coastguard Worker MachineInstr *AArch64InstrInfo::emitFrameIndexDebugValue(
1840*9880d681SAndroid Build Coastguard Worker MachineFunction &MF, int FrameIx, uint64_t Offset, const MDNode *Var,
1841*9880d681SAndroid Build Coastguard Worker const MDNode *Expr, const DebugLoc &DL) const {
1842*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB = BuildMI(MF, DL, get(AArch64::DBG_VALUE))
1843*9880d681SAndroid Build Coastguard Worker .addFrameIndex(FrameIx)
1844*9880d681SAndroid Build Coastguard Worker .addImm(0)
1845*9880d681SAndroid Build Coastguard Worker .addImm(Offset)
1846*9880d681SAndroid Build Coastguard Worker .addMetadata(Var)
1847*9880d681SAndroid Build Coastguard Worker .addMetadata(Expr);
1848*9880d681SAndroid Build Coastguard Worker return &*MIB;
1849*9880d681SAndroid Build Coastguard Worker }
1850*9880d681SAndroid Build Coastguard Worker
AddSubReg(const MachineInstrBuilder & MIB,unsigned Reg,unsigned SubIdx,unsigned State,const TargetRegisterInfo * TRI)1851*9880d681SAndroid Build Coastguard Worker static const MachineInstrBuilder &AddSubReg(const MachineInstrBuilder &MIB,
1852*9880d681SAndroid Build Coastguard Worker unsigned Reg, unsigned SubIdx,
1853*9880d681SAndroid Build Coastguard Worker unsigned State,
1854*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI) {
1855*9880d681SAndroid Build Coastguard Worker if (!SubIdx)
1856*9880d681SAndroid Build Coastguard Worker return MIB.addReg(Reg, State);
1857*9880d681SAndroid Build Coastguard Worker
1858*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isPhysicalRegister(Reg))
1859*9880d681SAndroid Build Coastguard Worker return MIB.addReg(TRI->getSubReg(Reg, SubIdx), State);
1860*9880d681SAndroid Build Coastguard Worker return MIB.addReg(Reg, State, SubIdx);
1861*9880d681SAndroid Build Coastguard Worker }
1862*9880d681SAndroid Build Coastguard Worker
forwardCopyWillClobberTuple(unsigned DestReg,unsigned SrcReg,unsigned NumRegs)1863*9880d681SAndroid Build Coastguard Worker static bool forwardCopyWillClobberTuple(unsigned DestReg, unsigned SrcReg,
1864*9880d681SAndroid Build Coastguard Worker unsigned NumRegs) {
1865*9880d681SAndroid Build Coastguard Worker // We really want the positive remainder mod 32 here, that happens to be
1866*9880d681SAndroid Build Coastguard Worker // easily obtainable with a mask.
1867*9880d681SAndroid Build Coastguard Worker return ((DestReg - SrcReg) & 0x1f) < NumRegs;
1868*9880d681SAndroid Build Coastguard Worker }
1869*9880d681SAndroid Build Coastguard Worker
copyPhysRegTuple(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,const DebugLoc & DL,unsigned DestReg,unsigned SrcReg,bool KillSrc,unsigned Opcode,llvm::ArrayRef<unsigned> Indices) const1870*9880d681SAndroid Build Coastguard Worker void AArch64InstrInfo::copyPhysRegTuple(
1871*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL,
1872*9880d681SAndroid Build Coastguard Worker unsigned DestReg, unsigned SrcReg, bool KillSrc, unsigned Opcode,
1873*9880d681SAndroid Build Coastguard Worker llvm::ArrayRef<unsigned> Indices) const {
1874*9880d681SAndroid Build Coastguard Worker assert(Subtarget.hasNEON() &&
1875*9880d681SAndroid Build Coastguard Worker "Unexpected register copy without NEON");
1876*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = &getRegisterInfo();
1877*9880d681SAndroid Build Coastguard Worker uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
1878*9880d681SAndroid Build Coastguard Worker uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
1879*9880d681SAndroid Build Coastguard Worker unsigned NumRegs = Indices.size();
1880*9880d681SAndroid Build Coastguard Worker
1881*9880d681SAndroid Build Coastguard Worker int SubReg = 0, End = NumRegs, Incr = 1;
1882*9880d681SAndroid Build Coastguard Worker if (forwardCopyWillClobberTuple(DestEncoding, SrcEncoding, NumRegs)) {
1883*9880d681SAndroid Build Coastguard Worker SubReg = NumRegs - 1;
1884*9880d681SAndroid Build Coastguard Worker End = -1;
1885*9880d681SAndroid Build Coastguard Worker Incr = -1;
1886*9880d681SAndroid Build Coastguard Worker }
1887*9880d681SAndroid Build Coastguard Worker
1888*9880d681SAndroid Build Coastguard Worker for (; SubReg != End; SubReg += Incr) {
1889*9880d681SAndroid Build Coastguard Worker const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
1890*9880d681SAndroid Build Coastguard Worker AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
1891*9880d681SAndroid Build Coastguard Worker AddSubReg(MIB, SrcReg, Indices[SubReg], 0, TRI);
1892*9880d681SAndroid Build Coastguard Worker AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
1893*9880d681SAndroid Build Coastguard Worker }
1894*9880d681SAndroid Build Coastguard Worker }
1895*9880d681SAndroid Build Coastguard Worker
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,const DebugLoc & DL,unsigned DestReg,unsigned SrcReg,bool KillSrc) const1896*9880d681SAndroid Build Coastguard Worker void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
1897*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator I,
1898*9880d681SAndroid Build Coastguard Worker const DebugLoc &DL, unsigned DestReg,
1899*9880d681SAndroid Build Coastguard Worker unsigned SrcReg, bool KillSrc) const {
1900*9880d681SAndroid Build Coastguard Worker if (AArch64::GPR32spRegClass.contains(DestReg) &&
1901*9880d681SAndroid Build Coastguard Worker (AArch64::GPR32spRegClass.contains(SrcReg) || SrcReg == AArch64::WZR)) {
1902*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = &getRegisterInfo();
1903*9880d681SAndroid Build Coastguard Worker
1904*9880d681SAndroid Build Coastguard Worker if (DestReg == AArch64::WSP || SrcReg == AArch64::WSP) {
1905*9880d681SAndroid Build Coastguard Worker // If either operand is WSP, expand to ADD #0.
1906*9880d681SAndroid Build Coastguard Worker if (Subtarget.hasZeroCycleRegMove()) {
1907*9880d681SAndroid Build Coastguard Worker // Cyclone recognizes "ADD Xd, Xn, #0" as a zero-cycle register move.
1908*9880d681SAndroid Build Coastguard Worker unsigned DestRegX = TRI->getMatchingSuperReg(DestReg, AArch64::sub_32,
1909*9880d681SAndroid Build Coastguard Worker &AArch64::GPR64spRegClass);
1910*9880d681SAndroid Build Coastguard Worker unsigned SrcRegX = TRI->getMatchingSuperReg(SrcReg, AArch64::sub_32,
1911*9880d681SAndroid Build Coastguard Worker &AArch64::GPR64spRegClass);
1912*9880d681SAndroid Build Coastguard Worker // This instruction is reading and writing X registers. This may upset
1913*9880d681SAndroid Build Coastguard Worker // the register scavenger and machine verifier, so we need to indicate
1914*9880d681SAndroid Build Coastguard Worker // that we are reading an undefined value from SrcRegX, but a proper
1915*9880d681SAndroid Build Coastguard Worker // value from SrcReg.
1916*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestRegX)
1917*9880d681SAndroid Build Coastguard Worker .addReg(SrcRegX, RegState::Undef)
1918*9880d681SAndroid Build Coastguard Worker .addImm(0)
1919*9880d681SAndroid Build Coastguard Worker .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, 0))
1920*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
1921*9880d681SAndroid Build Coastguard Worker } else {
1922*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::ADDWri), DestReg)
1923*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc))
1924*9880d681SAndroid Build Coastguard Worker .addImm(0)
1925*9880d681SAndroid Build Coastguard Worker .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, 0));
1926*9880d681SAndroid Build Coastguard Worker }
1927*9880d681SAndroid Build Coastguard Worker } else if (SrcReg == AArch64::WZR && Subtarget.hasZeroCycleZeroing()) {
1928*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::MOVZWi), DestReg).addImm(0).addImm(
1929*9880d681SAndroid Build Coastguard Worker AArch64_AM::getShifterImm(AArch64_AM::LSL, 0));
1930*9880d681SAndroid Build Coastguard Worker } else {
1931*9880d681SAndroid Build Coastguard Worker if (Subtarget.hasZeroCycleRegMove()) {
1932*9880d681SAndroid Build Coastguard Worker // Cyclone recognizes "ORR Xd, XZR, Xm" as a zero-cycle register move.
1933*9880d681SAndroid Build Coastguard Worker unsigned DestRegX = TRI->getMatchingSuperReg(DestReg, AArch64::sub_32,
1934*9880d681SAndroid Build Coastguard Worker &AArch64::GPR64spRegClass);
1935*9880d681SAndroid Build Coastguard Worker unsigned SrcRegX = TRI->getMatchingSuperReg(SrcReg, AArch64::sub_32,
1936*9880d681SAndroid Build Coastguard Worker &AArch64::GPR64spRegClass);
1937*9880d681SAndroid Build Coastguard Worker // This instruction is reading and writing X registers. This may upset
1938*9880d681SAndroid Build Coastguard Worker // the register scavenger and machine verifier, so we need to indicate
1939*9880d681SAndroid Build Coastguard Worker // that we are reading an undefined value from SrcRegX, but a proper
1940*9880d681SAndroid Build Coastguard Worker // value from SrcReg.
1941*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestRegX)
1942*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::XZR)
1943*9880d681SAndroid Build Coastguard Worker .addReg(SrcRegX, RegState::Undef)
1944*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
1945*9880d681SAndroid Build Coastguard Worker } else {
1946*9880d681SAndroid Build Coastguard Worker // Otherwise, expand to ORR WZR.
1947*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::ORRWrr), DestReg)
1948*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::WZR)
1949*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
1950*9880d681SAndroid Build Coastguard Worker }
1951*9880d681SAndroid Build Coastguard Worker }
1952*9880d681SAndroid Build Coastguard Worker return;
1953*9880d681SAndroid Build Coastguard Worker }
1954*9880d681SAndroid Build Coastguard Worker
1955*9880d681SAndroid Build Coastguard Worker if (AArch64::GPR64spRegClass.contains(DestReg) &&
1956*9880d681SAndroid Build Coastguard Worker (AArch64::GPR64spRegClass.contains(SrcReg) || SrcReg == AArch64::XZR)) {
1957*9880d681SAndroid Build Coastguard Worker if (DestReg == AArch64::SP || SrcReg == AArch64::SP) {
1958*9880d681SAndroid Build Coastguard Worker // If either operand is SP, expand to ADD #0.
1959*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestReg)
1960*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc))
1961*9880d681SAndroid Build Coastguard Worker .addImm(0)
1962*9880d681SAndroid Build Coastguard Worker .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, 0));
1963*9880d681SAndroid Build Coastguard Worker } else if (SrcReg == AArch64::XZR && Subtarget.hasZeroCycleZeroing()) {
1964*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::MOVZXi), DestReg).addImm(0).addImm(
1965*9880d681SAndroid Build Coastguard Worker AArch64_AM::getShifterImm(AArch64_AM::LSL, 0));
1966*9880d681SAndroid Build Coastguard Worker } else {
1967*9880d681SAndroid Build Coastguard Worker // Otherwise, expand to ORR XZR.
1968*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestReg)
1969*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::XZR)
1970*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
1971*9880d681SAndroid Build Coastguard Worker }
1972*9880d681SAndroid Build Coastguard Worker return;
1973*9880d681SAndroid Build Coastguard Worker }
1974*9880d681SAndroid Build Coastguard Worker
1975*9880d681SAndroid Build Coastguard Worker // Copy a DDDD register quad by copying the individual sub-registers.
1976*9880d681SAndroid Build Coastguard Worker if (AArch64::DDDDRegClass.contains(DestReg) &&
1977*9880d681SAndroid Build Coastguard Worker AArch64::DDDDRegClass.contains(SrcReg)) {
1978*9880d681SAndroid Build Coastguard Worker static const unsigned Indices[] = { AArch64::dsub0, AArch64::dsub1,
1979*9880d681SAndroid Build Coastguard Worker AArch64::dsub2, AArch64::dsub3 };
1980*9880d681SAndroid Build Coastguard Worker copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
1981*9880d681SAndroid Build Coastguard Worker Indices);
1982*9880d681SAndroid Build Coastguard Worker return;
1983*9880d681SAndroid Build Coastguard Worker }
1984*9880d681SAndroid Build Coastguard Worker
1985*9880d681SAndroid Build Coastguard Worker // Copy a DDD register triple by copying the individual sub-registers.
1986*9880d681SAndroid Build Coastguard Worker if (AArch64::DDDRegClass.contains(DestReg) &&
1987*9880d681SAndroid Build Coastguard Worker AArch64::DDDRegClass.contains(SrcReg)) {
1988*9880d681SAndroid Build Coastguard Worker static const unsigned Indices[] = { AArch64::dsub0, AArch64::dsub1,
1989*9880d681SAndroid Build Coastguard Worker AArch64::dsub2 };
1990*9880d681SAndroid Build Coastguard Worker copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
1991*9880d681SAndroid Build Coastguard Worker Indices);
1992*9880d681SAndroid Build Coastguard Worker return;
1993*9880d681SAndroid Build Coastguard Worker }
1994*9880d681SAndroid Build Coastguard Worker
1995*9880d681SAndroid Build Coastguard Worker // Copy a DD register pair by copying the individual sub-registers.
1996*9880d681SAndroid Build Coastguard Worker if (AArch64::DDRegClass.contains(DestReg) &&
1997*9880d681SAndroid Build Coastguard Worker AArch64::DDRegClass.contains(SrcReg)) {
1998*9880d681SAndroid Build Coastguard Worker static const unsigned Indices[] = { AArch64::dsub0, AArch64::dsub1 };
1999*9880d681SAndroid Build Coastguard Worker copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
2000*9880d681SAndroid Build Coastguard Worker Indices);
2001*9880d681SAndroid Build Coastguard Worker return;
2002*9880d681SAndroid Build Coastguard Worker }
2003*9880d681SAndroid Build Coastguard Worker
2004*9880d681SAndroid Build Coastguard Worker // Copy a QQQQ register quad by copying the individual sub-registers.
2005*9880d681SAndroid Build Coastguard Worker if (AArch64::QQQQRegClass.contains(DestReg) &&
2006*9880d681SAndroid Build Coastguard Worker AArch64::QQQQRegClass.contains(SrcReg)) {
2007*9880d681SAndroid Build Coastguard Worker static const unsigned Indices[] = { AArch64::qsub0, AArch64::qsub1,
2008*9880d681SAndroid Build Coastguard Worker AArch64::qsub2, AArch64::qsub3 };
2009*9880d681SAndroid Build Coastguard Worker copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
2010*9880d681SAndroid Build Coastguard Worker Indices);
2011*9880d681SAndroid Build Coastguard Worker return;
2012*9880d681SAndroid Build Coastguard Worker }
2013*9880d681SAndroid Build Coastguard Worker
2014*9880d681SAndroid Build Coastguard Worker // Copy a QQQ register triple by copying the individual sub-registers.
2015*9880d681SAndroid Build Coastguard Worker if (AArch64::QQQRegClass.contains(DestReg) &&
2016*9880d681SAndroid Build Coastguard Worker AArch64::QQQRegClass.contains(SrcReg)) {
2017*9880d681SAndroid Build Coastguard Worker static const unsigned Indices[] = { AArch64::qsub0, AArch64::qsub1,
2018*9880d681SAndroid Build Coastguard Worker AArch64::qsub2 };
2019*9880d681SAndroid Build Coastguard Worker copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
2020*9880d681SAndroid Build Coastguard Worker Indices);
2021*9880d681SAndroid Build Coastguard Worker return;
2022*9880d681SAndroid Build Coastguard Worker }
2023*9880d681SAndroid Build Coastguard Worker
2024*9880d681SAndroid Build Coastguard Worker // Copy a QQ register pair by copying the individual sub-registers.
2025*9880d681SAndroid Build Coastguard Worker if (AArch64::QQRegClass.contains(DestReg) &&
2026*9880d681SAndroid Build Coastguard Worker AArch64::QQRegClass.contains(SrcReg)) {
2027*9880d681SAndroid Build Coastguard Worker static const unsigned Indices[] = { AArch64::qsub0, AArch64::qsub1 };
2028*9880d681SAndroid Build Coastguard Worker copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
2029*9880d681SAndroid Build Coastguard Worker Indices);
2030*9880d681SAndroid Build Coastguard Worker return;
2031*9880d681SAndroid Build Coastguard Worker }
2032*9880d681SAndroid Build Coastguard Worker
2033*9880d681SAndroid Build Coastguard Worker if (AArch64::FPR128RegClass.contains(DestReg) &&
2034*9880d681SAndroid Build Coastguard Worker AArch64::FPR128RegClass.contains(SrcReg)) {
2035*9880d681SAndroid Build Coastguard Worker if(Subtarget.hasNEON()) {
2036*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
2037*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg)
2038*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
2039*9880d681SAndroid Build Coastguard Worker } else {
2040*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::STRQpre))
2041*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::SP, RegState::Define)
2042*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc))
2043*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::SP)
2044*9880d681SAndroid Build Coastguard Worker .addImm(-16);
2045*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::LDRQpre))
2046*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::SP, RegState::Define)
2047*9880d681SAndroid Build Coastguard Worker .addReg(DestReg, RegState::Define)
2048*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::SP)
2049*9880d681SAndroid Build Coastguard Worker .addImm(16);
2050*9880d681SAndroid Build Coastguard Worker }
2051*9880d681SAndroid Build Coastguard Worker return;
2052*9880d681SAndroid Build Coastguard Worker }
2053*9880d681SAndroid Build Coastguard Worker
2054*9880d681SAndroid Build Coastguard Worker if (AArch64::FPR64RegClass.contains(DestReg) &&
2055*9880d681SAndroid Build Coastguard Worker AArch64::FPR64RegClass.contains(SrcReg)) {
2056*9880d681SAndroid Build Coastguard Worker if(Subtarget.hasNEON()) {
2057*9880d681SAndroid Build Coastguard Worker DestReg = RI.getMatchingSuperReg(DestReg, AArch64::dsub,
2058*9880d681SAndroid Build Coastguard Worker &AArch64::FPR128RegClass);
2059*9880d681SAndroid Build Coastguard Worker SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::dsub,
2060*9880d681SAndroid Build Coastguard Worker &AArch64::FPR128RegClass);
2061*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
2062*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg)
2063*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
2064*9880d681SAndroid Build Coastguard Worker } else {
2065*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestReg)
2066*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
2067*9880d681SAndroid Build Coastguard Worker }
2068*9880d681SAndroid Build Coastguard Worker return;
2069*9880d681SAndroid Build Coastguard Worker }
2070*9880d681SAndroid Build Coastguard Worker
2071*9880d681SAndroid Build Coastguard Worker if (AArch64::FPR32RegClass.contains(DestReg) &&
2072*9880d681SAndroid Build Coastguard Worker AArch64::FPR32RegClass.contains(SrcReg)) {
2073*9880d681SAndroid Build Coastguard Worker if(Subtarget.hasNEON()) {
2074*9880d681SAndroid Build Coastguard Worker DestReg = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
2075*9880d681SAndroid Build Coastguard Worker &AArch64::FPR128RegClass);
2076*9880d681SAndroid Build Coastguard Worker SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
2077*9880d681SAndroid Build Coastguard Worker &AArch64::FPR128RegClass);
2078*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
2079*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg)
2080*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
2081*9880d681SAndroid Build Coastguard Worker } else {
2082*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
2083*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
2084*9880d681SAndroid Build Coastguard Worker }
2085*9880d681SAndroid Build Coastguard Worker return;
2086*9880d681SAndroid Build Coastguard Worker }
2087*9880d681SAndroid Build Coastguard Worker
2088*9880d681SAndroid Build Coastguard Worker if (AArch64::FPR16RegClass.contains(DestReg) &&
2089*9880d681SAndroid Build Coastguard Worker AArch64::FPR16RegClass.contains(SrcReg)) {
2090*9880d681SAndroid Build Coastguard Worker if(Subtarget.hasNEON()) {
2091*9880d681SAndroid Build Coastguard Worker DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
2092*9880d681SAndroid Build Coastguard Worker &AArch64::FPR128RegClass);
2093*9880d681SAndroid Build Coastguard Worker SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
2094*9880d681SAndroid Build Coastguard Worker &AArch64::FPR128RegClass);
2095*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
2096*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg)
2097*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
2098*9880d681SAndroid Build Coastguard Worker } else {
2099*9880d681SAndroid Build Coastguard Worker DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
2100*9880d681SAndroid Build Coastguard Worker &AArch64::FPR32RegClass);
2101*9880d681SAndroid Build Coastguard Worker SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
2102*9880d681SAndroid Build Coastguard Worker &AArch64::FPR32RegClass);
2103*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
2104*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
2105*9880d681SAndroid Build Coastguard Worker }
2106*9880d681SAndroid Build Coastguard Worker return;
2107*9880d681SAndroid Build Coastguard Worker }
2108*9880d681SAndroid Build Coastguard Worker
2109*9880d681SAndroid Build Coastguard Worker if (AArch64::FPR8RegClass.contains(DestReg) &&
2110*9880d681SAndroid Build Coastguard Worker AArch64::FPR8RegClass.contains(SrcReg)) {
2111*9880d681SAndroid Build Coastguard Worker if(Subtarget.hasNEON()) {
2112*9880d681SAndroid Build Coastguard Worker DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
2113*9880d681SAndroid Build Coastguard Worker &AArch64::FPR128RegClass);
2114*9880d681SAndroid Build Coastguard Worker SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
2115*9880d681SAndroid Build Coastguard Worker &AArch64::FPR128RegClass);
2116*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
2117*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg)
2118*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
2119*9880d681SAndroid Build Coastguard Worker } else {
2120*9880d681SAndroid Build Coastguard Worker DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
2121*9880d681SAndroid Build Coastguard Worker &AArch64::FPR32RegClass);
2122*9880d681SAndroid Build Coastguard Worker SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
2123*9880d681SAndroid Build Coastguard Worker &AArch64::FPR32RegClass);
2124*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
2125*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
2126*9880d681SAndroid Build Coastguard Worker }
2127*9880d681SAndroid Build Coastguard Worker return;
2128*9880d681SAndroid Build Coastguard Worker }
2129*9880d681SAndroid Build Coastguard Worker
2130*9880d681SAndroid Build Coastguard Worker // Copies between GPR64 and FPR64.
2131*9880d681SAndroid Build Coastguard Worker if (AArch64::FPR64RegClass.contains(DestReg) &&
2132*9880d681SAndroid Build Coastguard Worker AArch64::GPR64RegClass.contains(SrcReg)) {
2133*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::FMOVXDr), DestReg)
2134*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
2135*9880d681SAndroid Build Coastguard Worker return;
2136*9880d681SAndroid Build Coastguard Worker }
2137*9880d681SAndroid Build Coastguard Worker if (AArch64::GPR64RegClass.contains(DestReg) &&
2138*9880d681SAndroid Build Coastguard Worker AArch64::FPR64RegClass.contains(SrcReg)) {
2139*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::FMOVDXr), DestReg)
2140*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
2141*9880d681SAndroid Build Coastguard Worker return;
2142*9880d681SAndroid Build Coastguard Worker }
2143*9880d681SAndroid Build Coastguard Worker // Copies between GPR32 and FPR32.
2144*9880d681SAndroid Build Coastguard Worker if (AArch64::FPR32RegClass.contains(DestReg) &&
2145*9880d681SAndroid Build Coastguard Worker AArch64::GPR32RegClass.contains(SrcReg)) {
2146*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::FMOVWSr), DestReg)
2147*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
2148*9880d681SAndroid Build Coastguard Worker return;
2149*9880d681SAndroid Build Coastguard Worker }
2150*9880d681SAndroid Build Coastguard Worker if (AArch64::GPR32RegClass.contains(DestReg) &&
2151*9880d681SAndroid Build Coastguard Worker AArch64::FPR32RegClass.contains(SrcReg)) {
2152*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::FMOVSWr), DestReg)
2153*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
2154*9880d681SAndroid Build Coastguard Worker return;
2155*9880d681SAndroid Build Coastguard Worker }
2156*9880d681SAndroid Build Coastguard Worker
2157*9880d681SAndroid Build Coastguard Worker if (DestReg == AArch64::NZCV) {
2158*9880d681SAndroid Build Coastguard Worker assert(AArch64::GPR64RegClass.contains(SrcReg) && "Invalid NZCV copy");
2159*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::MSR))
2160*9880d681SAndroid Build Coastguard Worker .addImm(AArch64SysReg::NZCV)
2161*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc))
2162*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::NZCV, RegState::Implicit | RegState::Define);
2163*9880d681SAndroid Build Coastguard Worker return;
2164*9880d681SAndroid Build Coastguard Worker }
2165*9880d681SAndroid Build Coastguard Worker
2166*9880d681SAndroid Build Coastguard Worker if (SrcReg == AArch64::NZCV) {
2167*9880d681SAndroid Build Coastguard Worker assert(AArch64::GPR64RegClass.contains(DestReg) && "Invalid NZCV copy");
2168*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, I, DL, get(AArch64::MRS), DestReg)
2169*9880d681SAndroid Build Coastguard Worker .addImm(AArch64SysReg::NZCV)
2170*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::NZCV, RegState::Implicit | getKillRegState(KillSrc));
2171*9880d681SAndroid Build Coastguard Worker return;
2172*9880d681SAndroid Build Coastguard Worker }
2173*9880d681SAndroid Build Coastguard Worker
2174*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unimplemented reg-to-reg copy");
2175*9880d681SAndroid Build Coastguard Worker }
2176*9880d681SAndroid Build Coastguard Worker
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,unsigned SrcReg,bool isKill,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const2177*9880d681SAndroid Build Coastguard Worker void AArch64InstrInfo::storeRegToStackSlot(
2178*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned SrcReg,
2179*9880d681SAndroid Build Coastguard Worker bool isKill, int FI, const TargetRegisterClass *RC,
2180*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI) const {
2181*9880d681SAndroid Build Coastguard Worker DebugLoc DL;
2182*9880d681SAndroid Build Coastguard Worker if (MBBI != MBB.end())
2183*9880d681SAndroid Build Coastguard Worker DL = MBBI->getDebugLoc();
2184*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = *MBB.getParent();
2185*9880d681SAndroid Build Coastguard Worker MachineFrameInfo &MFI = *MF.getFrameInfo();
2186*9880d681SAndroid Build Coastguard Worker unsigned Align = MFI.getObjectAlignment(FI);
2187*9880d681SAndroid Build Coastguard Worker
2188*9880d681SAndroid Build Coastguard Worker MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(MF, FI);
2189*9880d681SAndroid Build Coastguard Worker MachineMemOperand *MMO = MF.getMachineMemOperand(
2190*9880d681SAndroid Build Coastguard Worker PtrInfo, MachineMemOperand::MOStore, MFI.getObjectSize(FI), Align);
2191*9880d681SAndroid Build Coastguard Worker unsigned Opc = 0;
2192*9880d681SAndroid Build Coastguard Worker bool Offset = true;
2193*9880d681SAndroid Build Coastguard Worker switch (RC->getSize()) {
2194*9880d681SAndroid Build Coastguard Worker case 1:
2195*9880d681SAndroid Build Coastguard Worker if (AArch64::FPR8RegClass.hasSubClassEq(RC))
2196*9880d681SAndroid Build Coastguard Worker Opc = AArch64::STRBui;
2197*9880d681SAndroid Build Coastguard Worker break;
2198*9880d681SAndroid Build Coastguard Worker case 2:
2199*9880d681SAndroid Build Coastguard Worker if (AArch64::FPR16RegClass.hasSubClassEq(RC))
2200*9880d681SAndroid Build Coastguard Worker Opc = AArch64::STRHui;
2201*9880d681SAndroid Build Coastguard Worker break;
2202*9880d681SAndroid Build Coastguard Worker case 4:
2203*9880d681SAndroid Build Coastguard Worker if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
2204*9880d681SAndroid Build Coastguard Worker Opc = AArch64::STRWui;
2205*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(SrcReg))
2206*9880d681SAndroid Build Coastguard Worker MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR32RegClass);
2207*9880d681SAndroid Build Coastguard Worker else
2208*9880d681SAndroid Build Coastguard Worker assert(SrcReg != AArch64::WSP);
2209*9880d681SAndroid Build Coastguard Worker } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
2210*9880d681SAndroid Build Coastguard Worker Opc = AArch64::STRSui;
2211*9880d681SAndroid Build Coastguard Worker break;
2212*9880d681SAndroid Build Coastguard Worker case 8:
2213*9880d681SAndroid Build Coastguard Worker if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
2214*9880d681SAndroid Build Coastguard Worker Opc = AArch64::STRXui;
2215*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(SrcReg))
2216*9880d681SAndroid Build Coastguard Worker MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
2217*9880d681SAndroid Build Coastguard Worker else
2218*9880d681SAndroid Build Coastguard Worker assert(SrcReg != AArch64::SP);
2219*9880d681SAndroid Build Coastguard Worker } else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
2220*9880d681SAndroid Build Coastguard Worker Opc = AArch64::STRDui;
2221*9880d681SAndroid Build Coastguard Worker break;
2222*9880d681SAndroid Build Coastguard Worker case 16:
2223*9880d681SAndroid Build Coastguard Worker if (AArch64::FPR128RegClass.hasSubClassEq(RC))
2224*9880d681SAndroid Build Coastguard Worker Opc = AArch64::STRQui;
2225*9880d681SAndroid Build Coastguard Worker else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
2226*9880d681SAndroid Build Coastguard Worker assert(Subtarget.hasNEON() &&
2227*9880d681SAndroid Build Coastguard Worker "Unexpected register store without NEON");
2228*9880d681SAndroid Build Coastguard Worker Opc = AArch64::ST1Twov1d;
2229*9880d681SAndroid Build Coastguard Worker Offset = false;
2230*9880d681SAndroid Build Coastguard Worker }
2231*9880d681SAndroid Build Coastguard Worker break;
2232*9880d681SAndroid Build Coastguard Worker case 24:
2233*9880d681SAndroid Build Coastguard Worker if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
2234*9880d681SAndroid Build Coastguard Worker assert(Subtarget.hasNEON() &&
2235*9880d681SAndroid Build Coastguard Worker "Unexpected register store without NEON");
2236*9880d681SAndroid Build Coastguard Worker Opc = AArch64::ST1Threev1d;
2237*9880d681SAndroid Build Coastguard Worker Offset = false;
2238*9880d681SAndroid Build Coastguard Worker }
2239*9880d681SAndroid Build Coastguard Worker break;
2240*9880d681SAndroid Build Coastguard Worker case 32:
2241*9880d681SAndroid Build Coastguard Worker if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
2242*9880d681SAndroid Build Coastguard Worker assert(Subtarget.hasNEON() &&
2243*9880d681SAndroid Build Coastguard Worker "Unexpected register store without NEON");
2244*9880d681SAndroid Build Coastguard Worker Opc = AArch64::ST1Fourv1d;
2245*9880d681SAndroid Build Coastguard Worker Offset = false;
2246*9880d681SAndroid Build Coastguard Worker } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
2247*9880d681SAndroid Build Coastguard Worker assert(Subtarget.hasNEON() &&
2248*9880d681SAndroid Build Coastguard Worker "Unexpected register store without NEON");
2249*9880d681SAndroid Build Coastguard Worker Opc = AArch64::ST1Twov2d;
2250*9880d681SAndroid Build Coastguard Worker Offset = false;
2251*9880d681SAndroid Build Coastguard Worker }
2252*9880d681SAndroid Build Coastguard Worker break;
2253*9880d681SAndroid Build Coastguard Worker case 48:
2254*9880d681SAndroid Build Coastguard Worker if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
2255*9880d681SAndroid Build Coastguard Worker assert(Subtarget.hasNEON() &&
2256*9880d681SAndroid Build Coastguard Worker "Unexpected register store without NEON");
2257*9880d681SAndroid Build Coastguard Worker Opc = AArch64::ST1Threev2d;
2258*9880d681SAndroid Build Coastguard Worker Offset = false;
2259*9880d681SAndroid Build Coastguard Worker }
2260*9880d681SAndroid Build Coastguard Worker break;
2261*9880d681SAndroid Build Coastguard Worker case 64:
2262*9880d681SAndroid Build Coastguard Worker if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
2263*9880d681SAndroid Build Coastguard Worker assert(Subtarget.hasNEON() &&
2264*9880d681SAndroid Build Coastguard Worker "Unexpected register store without NEON");
2265*9880d681SAndroid Build Coastguard Worker Opc = AArch64::ST1Fourv2d;
2266*9880d681SAndroid Build Coastguard Worker Offset = false;
2267*9880d681SAndroid Build Coastguard Worker }
2268*9880d681SAndroid Build Coastguard Worker break;
2269*9880d681SAndroid Build Coastguard Worker }
2270*9880d681SAndroid Build Coastguard Worker assert(Opc && "Unknown register class");
2271*9880d681SAndroid Build Coastguard Worker
2272*9880d681SAndroid Build Coastguard Worker const MachineInstrBuilder MI = BuildMI(MBB, MBBI, DL, get(Opc))
2273*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(isKill))
2274*9880d681SAndroid Build Coastguard Worker .addFrameIndex(FI);
2275*9880d681SAndroid Build Coastguard Worker
2276*9880d681SAndroid Build Coastguard Worker if (Offset)
2277*9880d681SAndroid Build Coastguard Worker MI.addImm(0);
2278*9880d681SAndroid Build Coastguard Worker MI.addMemOperand(MMO);
2279*9880d681SAndroid Build Coastguard Worker }
2280*9880d681SAndroid Build Coastguard Worker
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,unsigned DestReg,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const2281*9880d681SAndroid Build Coastguard Worker void AArch64InstrInfo::loadRegFromStackSlot(
2282*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg,
2283*9880d681SAndroid Build Coastguard Worker int FI, const TargetRegisterClass *RC,
2284*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI) const {
2285*9880d681SAndroid Build Coastguard Worker DebugLoc DL;
2286*9880d681SAndroid Build Coastguard Worker if (MBBI != MBB.end())
2287*9880d681SAndroid Build Coastguard Worker DL = MBBI->getDebugLoc();
2288*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = *MBB.getParent();
2289*9880d681SAndroid Build Coastguard Worker MachineFrameInfo &MFI = *MF.getFrameInfo();
2290*9880d681SAndroid Build Coastguard Worker unsigned Align = MFI.getObjectAlignment(FI);
2291*9880d681SAndroid Build Coastguard Worker MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(MF, FI);
2292*9880d681SAndroid Build Coastguard Worker MachineMemOperand *MMO = MF.getMachineMemOperand(
2293*9880d681SAndroid Build Coastguard Worker PtrInfo, MachineMemOperand::MOLoad, MFI.getObjectSize(FI), Align);
2294*9880d681SAndroid Build Coastguard Worker
2295*9880d681SAndroid Build Coastguard Worker unsigned Opc = 0;
2296*9880d681SAndroid Build Coastguard Worker bool Offset = true;
2297*9880d681SAndroid Build Coastguard Worker switch (RC->getSize()) {
2298*9880d681SAndroid Build Coastguard Worker case 1:
2299*9880d681SAndroid Build Coastguard Worker if (AArch64::FPR8RegClass.hasSubClassEq(RC))
2300*9880d681SAndroid Build Coastguard Worker Opc = AArch64::LDRBui;
2301*9880d681SAndroid Build Coastguard Worker break;
2302*9880d681SAndroid Build Coastguard Worker case 2:
2303*9880d681SAndroid Build Coastguard Worker if (AArch64::FPR16RegClass.hasSubClassEq(RC))
2304*9880d681SAndroid Build Coastguard Worker Opc = AArch64::LDRHui;
2305*9880d681SAndroid Build Coastguard Worker break;
2306*9880d681SAndroid Build Coastguard Worker case 4:
2307*9880d681SAndroid Build Coastguard Worker if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
2308*9880d681SAndroid Build Coastguard Worker Opc = AArch64::LDRWui;
2309*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(DestReg))
2310*9880d681SAndroid Build Coastguard Worker MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR32RegClass);
2311*9880d681SAndroid Build Coastguard Worker else
2312*9880d681SAndroid Build Coastguard Worker assert(DestReg != AArch64::WSP);
2313*9880d681SAndroid Build Coastguard Worker } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
2314*9880d681SAndroid Build Coastguard Worker Opc = AArch64::LDRSui;
2315*9880d681SAndroid Build Coastguard Worker break;
2316*9880d681SAndroid Build Coastguard Worker case 8:
2317*9880d681SAndroid Build Coastguard Worker if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
2318*9880d681SAndroid Build Coastguard Worker Opc = AArch64::LDRXui;
2319*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(DestReg))
2320*9880d681SAndroid Build Coastguard Worker MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR64RegClass);
2321*9880d681SAndroid Build Coastguard Worker else
2322*9880d681SAndroid Build Coastguard Worker assert(DestReg != AArch64::SP);
2323*9880d681SAndroid Build Coastguard Worker } else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
2324*9880d681SAndroid Build Coastguard Worker Opc = AArch64::LDRDui;
2325*9880d681SAndroid Build Coastguard Worker break;
2326*9880d681SAndroid Build Coastguard Worker case 16:
2327*9880d681SAndroid Build Coastguard Worker if (AArch64::FPR128RegClass.hasSubClassEq(RC))
2328*9880d681SAndroid Build Coastguard Worker Opc = AArch64::LDRQui;
2329*9880d681SAndroid Build Coastguard Worker else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
2330*9880d681SAndroid Build Coastguard Worker assert(Subtarget.hasNEON() &&
2331*9880d681SAndroid Build Coastguard Worker "Unexpected register load without NEON");
2332*9880d681SAndroid Build Coastguard Worker Opc = AArch64::LD1Twov1d;
2333*9880d681SAndroid Build Coastguard Worker Offset = false;
2334*9880d681SAndroid Build Coastguard Worker }
2335*9880d681SAndroid Build Coastguard Worker break;
2336*9880d681SAndroid Build Coastguard Worker case 24:
2337*9880d681SAndroid Build Coastguard Worker if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
2338*9880d681SAndroid Build Coastguard Worker assert(Subtarget.hasNEON() &&
2339*9880d681SAndroid Build Coastguard Worker "Unexpected register load without NEON");
2340*9880d681SAndroid Build Coastguard Worker Opc = AArch64::LD1Threev1d;
2341*9880d681SAndroid Build Coastguard Worker Offset = false;
2342*9880d681SAndroid Build Coastguard Worker }
2343*9880d681SAndroid Build Coastguard Worker break;
2344*9880d681SAndroid Build Coastguard Worker case 32:
2345*9880d681SAndroid Build Coastguard Worker if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
2346*9880d681SAndroid Build Coastguard Worker assert(Subtarget.hasNEON() &&
2347*9880d681SAndroid Build Coastguard Worker "Unexpected register load without NEON");
2348*9880d681SAndroid Build Coastguard Worker Opc = AArch64::LD1Fourv1d;
2349*9880d681SAndroid Build Coastguard Worker Offset = false;
2350*9880d681SAndroid Build Coastguard Worker } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
2351*9880d681SAndroid Build Coastguard Worker assert(Subtarget.hasNEON() &&
2352*9880d681SAndroid Build Coastguard Worker "Unexpected register load without NEON");
2353*9880d681SAndroid Build Coastguard Worker Opc = AArch64::LD1Twov2d;
2354*9880d681SAndroid Build Coastguard Worker Offset = false;
2355*9880d681SAndroid Build Coastguard Worker }
2356*9880d681SAndroid Build Coastguard Worker break;
2357*9880d681SAndroid Build Coastguard Worker case 48:
2358*9880d681SAndroid Build Coastguard Worker if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
2359*9880d681SAndroid Build Coastguard Worker assert(Subtarget.hasNEON() &&
2360*9880d681SAndroid Build Coastguard Worker "Unexpected register load without NEON");
2361*9880d681SAndroid Build Coastguard Worker Opc = AArch64::LD1Threev2d;
2362*9880d681SAndroid Build Coastguard Worker Offset = false;
2363*9880d681SAndroid Build Coastguard Worker }
2364*9880d681SAndroid Build Coastguard Worker break;
2365*9880d681SAndroid Build Coastguard Worker case 64:
2366*9880d681SAndroid Build Coastguard Worker if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
2367*9880d681SAndroid Build Coastguard Worker assert(Subtarget.hasNEON() &&
2368*9880d681SAndroid Build Coastguard Worker "Unexpected register load without NEON");
2369*9880d681SAndroid Build Coastguard Worker Opc = AArch64::LD1Fourv2d;
2370*9880d681SAndroid Build Coastguard Worker Offset = false;
2371*9880d681SAndroid Build Coastguard Worker }
2372*9880d681SAndroid Build Coastguard Worker break;
2373*9880d681SAndroid Build Coastguard Worker }
2374*9880d681SAndroid Build Coastguard Worker assert(Opc && "Unknown register class");
2375*9880d681SAndroid Build Coastguard Worker
2376*9880d681SAndroid Build Coastguard Worker const MachineInstrBuilder MI = BuildMI(MBB, MBBI, DL, get(Opc))
2377*9880d681SAndroid Build Coastguard Worker .addReg(DestReg, getDefRegState(true))
2378*9880d681SAndroid Build Coastguard Worker .addFrameIndex(FI);
2379*9880d681SAndroid Build Coastguard Worker if (Offset)
2380*9880d681SAndroid Build Coastguard Worker MI.addImm(0);
2381*9880d681SAndroid Build Coastguard Worker MI.addMemOperand(MMO);
2382*9880d681SAndroid Build Coastguard Worker }
2383*9880d681SAndroid Build Coastguard Worker
emitFrameOffset(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,unsigned DestReg,unsigned SrcReg,int Offset,const TargetInstrInfo * TII,MachineInstr::MIFlag Flag,bool SetNZCV)2384*9880d681SAndroid Build Coastguard Worker void llvm::emitFrameOffset(MachineBasicBlock &MBB,
2385*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
2386*9880d681SAndroid Build Coastguard Worker unsigned DestReg, unsigned SrcReg, int Offset,
2387*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII,
2388*9880d681SAndroid Build Coastguard Worker MachineInstr::MIFlag Flag, bool SetNZCV) {
2389*9880d681SAndroid Build Coastguard Worker if (DestReg == SrcReg && Offset == 0)
2390*9880d681SAndroid Build Coastguard Worker return;
2391*9880d681SAndroid Build Coastguard Worker
2392*9880d681SAndroid Build Coastguard Worker assert((DestReg != AArch64::SP || Offset % 16 == 0) &&
2393*9880d681SAndroid Build Coastguard Worker "SP increment/decrement not 16-byte aligned");
2394*9880d681SAndroid Build Coastguard Worker
2395*9880d681SAndroid Build Coastguard Worker bool isSub = Offset < 0;
2396*9880d681SAndroid Build Coastguard Worker if (isSub)
2397*9880d681SAndroid Build Coastguard Worker Offset = -Offset;
2398*9880d681SAndroid Build Coastguard Worker
2399*9880d681SAndroid Build Coastguard Worker // FIXME: If the offset won't fit in 24-bits, compute the offset into a
2400*9880d681SAndroid Build Coastguard Worker // scratch register. If DestReg is a virtual register, use it as the
2401*9880d681SAndroid Build Coastguard Worker // scratch register; otherwise, create a new virtual register (to be
2402*9880d681SAndroid Build Coastguard Worker // replaced by the scavenger at the end of PEI). That case can be optimized
2403*9880d681SAndroid Build Coastguard Worker // slightly if DestReg is SP which is always 16-byte aligned, so the scratch
2404*9880d681SAndroid Build Coastguard Worker // register can be loaded with offset%8 and the add/sub can use an extending
2405*9880d681SAndroid Build Coastguard Worker // instruction with LSL#3.
2406*9880d681SAndroid Build Coastguard Worker // Currently the function handles any offsets but generates a poor sequence
2407*9880d681SAndroid Build Coastguard Worker // of code.
2408*9880d681SAndroid Build Coastguard Worker // assert(Offset < (1 << 24) && "unimplemented reg plus immediate");
2409*9880d681SAndroid Build Coastguard Worker
2410*9880d681SAndroid Build Coastguard Worker unsigned Opc;
2411*9880d681SAndroid Build Coastguard Worker if (SetNZCV)
2412*9880d681SAndroid Build Coastguard Worker Opc = isSub ? AArch64::SUBSXri : AArch64::ADDSXri;
2413*9880d681SAndroid Build Coastguard Worker else
2414*9880d681SAndroid Build Coastguard Worker Opc = isSub ? AArch64::SUBXri : AArch64::ADDXri;
2415*9880d681SAndroid Build Coastguard Worker const unsigned MaxEncoding = 0xfff;
2416*9880d681SAndroid Build Coastguard Worker const unsigned ShiftSize = 12;
2417*9880d681SAndroid Build Coastguard Worker const unsigned MaxEncodableValue = MaxEncoding << ShiftSize;
2418*9880d681SAndroid Build Coastguard Worker while (((unsigned)Offset) >= (1 << ShiftSize)) {
2419*9880d681SAndroid Build Coastguard Worker unsigned ThisVal;
2420*9880d681SAndroid Build Coastguard Worker if (((unsigned)Offset) > MaxEncodableValue) {
2421*9880d681SAndroid Build Coastguard Worker ThisVal = MaxEncodableValue;
2422*9880d681SAndroid Build Coastguard Worker } else {
2423*9880d681SAndroid Build Coastguard Worker ThisVal = Offset & MaxEncodableValue;
2424*9880d681SAndroid Build Coastguard Worker }
2425*9880d681SAndroid Build Coastguard Worker assert((ThisVal >> ShiftSize) <= MaxEncoding &&
2426*9880d681SAndroid Build Coastguard Worker "Encoding cannot handle value that big");
2427*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg)
2428*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg)
2429*9880d681SAndroid Build Coastguard Worker .addImm(ThisVal >> ShiftSize)
2430*9880d681SAndroid Build Coastguard Worker .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftSize))
2431*9880d681SAndroid Build Coastguard Worker .setMIFlag(Flag);
2432*9880d681SAndroid Build Coastguard Worker
2433*9880d681SAndroid Build Coastguard Worker SrcReg = DestReg;
2434*9880d681SAndroid Build Coastguard Worker Offset -= ThisVal;
2435*9880d681SAndroid Build Coastguard Worker if (Offset == 0)
2436*9880d681SAndroid Build Coastguard Worker return;
2437*9880d681SAndroid Build Coastguard Worker }
2438*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg)
2439*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg)
2440*9880d681SAndroid Build Coastguard Worker .addImm(Offset)
2441*9880d681SAndroid Build Coastguard Worker .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, 0))
2442*9880d681SAndroid Build Coastguard Worker .setMIFlag(Flag);
2443*9880d681SAndroid Build Coastguard Worker }
2444*9880d681SAndroid Build Coastguard Worker
foldMemoryOperandImpl(MachineFunction & MF,MachineInstr & MI,ArrayRef<unsigned> Ops,MachineBasicBlock::iterator InsertPt,int FrameIndex,LiveIntervals * LIS) const2445*9880d681SAndroid Build Coastguard Worker MachineInstr *AArch64InstrInfo::foldMemoryOperandImpl(
2446*9880d681SAndroid Build Coastguard Worker MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,
2447*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator InsertPt, int FrameIndex,
2448*9880d681SAndroid Build Coastguard Worker LiveIntervals *LIS) const {
2449*9880d681SAndroid Build Coastguard Worker // This is a bit of a hack. Consider this instruction:
2450*9880d681SAndroid Build Coastguard Worker //
2451*9880d681SAndroid Build Coastguard Worker // %vreg0<def> = COPY %SP; GPR64all:%vreg0
2452*9880d681SAndroid Build Coastguard Worker //
2453*9880d681SAndroid Build Coastguard Worker // We explicitly chose GPR64all for the virtual register so such a copy might
2454*9880d681SAndroid Build Coastguard Worker // be eliminated by RegisterCoalescer. However, that may not be possible, and
2455*9880d681SAndroid Build Coastguard Worker // %vreg0 may even spill. We can't spill %SP, and since it is in the GPR64all
2456*9880d681SAndroid Build Coastguard Worker // register class, TargetInstrInfo::foldMemoryOperand() is going to try.
2457*9880d681SAndroid Build Coastguard Worker //
2458*9880d681SAndroid Build Coastguard Worker // To prevent that, we are going to constrain the %vreg0 register class here.
2459*9880d681SAndroid Build Coastguard Worker //
2460*9880d681SAndroid Build Coastguard Worker // <rdar://problem/11522048>
2461*9880d681SAndroid Build Coastguard Worker //
2462*9880d681SAndroid Build Coastguard Worker if (MI.isCopy()) {
2463*9880d681SAndroid Build Coastguard Worker unsigned DstReg = MI.getOperand(0).getReg();
2464*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = MI.getOperand(1).getReg();
2465*9880d681SAndroid Build Coastguard Worker if (SrcReg == AArch64::SP &&
2466*9880d681SAndroid Build Coastguard Worker TargetRegisterInfo::isVirtualRegister(DstReg)) {
2467*9880d681SAndroid Build Coastguard Worker MF.getRegInfo().constrainRegClass(DstReg, &AArch64::GPR64RegClass);
2468*9880d681SAndroid Build Coastguard Worker return nullptr;
2469*9880d681SAndroid Build Coastguard Worker }
2470*9880d681SAndroid Build Coastguard Worker if (DstReg == AArch64::SP &&
2471*9880d681SAndroid Build Coastguard Worker TargetRegisterInfo::isVirtualRegister(SrcReg)) {
2472*9880d681SAndroid Build Coastguard Worker MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
2473*9880d681SAndroid Build Coastguard Worker return nullptr;
2474*9880d681SAndroid Build Coastguard Worker }
2475*9880d681SAndroid Build Coastguard Worker }
2476*9880d681SAndroid Build Coastguard Worker
2477*9880d681SAndroid Build Coastguard Worker // Cannot fold.
2478*9880d681SAndroid Build Coastguard Worker return nullptr;
2479*9880d681SAndroid Build Coastguard Worker }
2480*9880d681SAndroid Build Coastguard Worker
isAArch64FrameOffsetLegal(const MachineInstr & MI,int & Offset,bool * OutUseUnscaledOp,unsigned * OutUnscaledOp,int * EmittableOffset)2481*9880d681SAndroid Build Coastguard Worker int llvm::isAArch64FrameOffsetLegal(const MachineInstr &MI, int &Offset,
2482*9880d681SAndroid Build Coastguard Worker bool *OutUseUnscaledOp,
2483*9880d681SAndroid Build Coastguard Worker unsigned *OutUnscaledOp,
2484*9880d681SAndroid Build Coastguard Worker int *EmittableOffset) {
2485*9880d681SAndroid Build Coastguard Worker int Scale = 1;
2486*9880d681SAndroid Build Coastguard Worker bool IsSigned = false;
2487*9880d681SAndroid Build Coastguard Worker // The ImmIdx should be changed case by case if it is not 2.
2488*9880d681SAndroid Build Coastguard Worker unsigned ImmIdx = 2;
2489*9880d681SAndroid Build Coastguard Worker unsigned UnscaledOp = 0;
2490*9880d681SAndroid Build Coastguard Worker // Set output values in case of early exit.
2491*9880d681SAndroid Build Coastguard Worker if (EmittableOffset)
2492*9880d681SAndroid Build Coastguard Worker *EmittableOffset = 0;
2493*9880d681SAndroid Build Coastguard Worker if (OutUseUnscaledOp)
2494*9880d681SAndroid Build Coastguard Worker *OutUseUnscaledOp = false;
2495*9880d681SAndroid Build Coastguard Worker if (OutUnscaledOp)
2496*9880d681SAndroid Build Coastguard Worker *OutUnscaledOp = 0;
2497*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
2498*9880d681SAndroid Build Coastguard Worker default:
2499*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unhandled opcode in rewriteAArch64FrameIndex");
2500*9880d681SAndroid Build Coastguard Worker // Vector spills/fills can't take an immediate offset.
2501*9880d681SAndroid Build Coastguard Worker case AArch64::LD1Twov2d:
2502*9880d681SAndroid Build Coastguard Worker case AArch64::LD1Threev2d:
2503*9880d681SAndroid Build Coastguard Worker case AArch64::LD1Fourv2d:
2504*9880d681SAndroid Build Coastguard Worker case AArch64::LD1Twov1d:
2505*9880d681SAndroid Build Coastguard Worker case AArch64::LD1Threev1d:
2506*9880d681SAndroid Build Coastguard Worker case AArch64::LD1Fourv1d:
2507*9880d681SAndroid Build Coastguard Worker case AArch64::ST1Twov2d:
2508*9880d681SAndroid Build Coastguard Worker case AArch64::ST1Threev2d:
2509*9880d681SAndroid Build Coastguard Worker case AArch64::ST1Fourv2d:
2510*9880d681SAndroid Build Coastguard Worker case AArch64::ST1Twov1d:
2511*9880d681SAndroid Build Coastguard Worker case AArch64::ST1Threev1d:
2512*9880d681SAndroid Build Coastguard Worker case AArch64::ST1Fourv1d:
2513*9880d681SAndroid Build Coastguard Worker return AArch64FrameOffsetCannotUpdate;
2514*9880d681SAndroid Build Coastguard Worker case AArch64::PRFMui:
2515*9880d681SAndroid Build Coastguard Worker Scale = 8;
2516*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::PRFUMi;
2517*9880d681SAndroid Build Coastguard Worker break;
2518*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXui:
2519*9880d681SAndroid Build Coastguard Worker Scale = 8;
2520*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::LDURXi;
2521*9880d681SAndroid Build Coastguard Worker break;
2522*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
2523*9880d681SAndroid Build Coastguard Worker Scale = 4;
2524*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::LDURWi;
2525*9880d681SAndroid Build Coastguard Worker break;
2526*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBui:
2527*9880d681SAndroid Build Coastguard Worker Scale = 1;
2528*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::LDURBi;
2529*9880d681SAndroid Build Coastguard Worker break;
2530*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHui:
2531*9880d681SAndroid Build Coastguard Worker Scale = 2;
2532*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::LDURHi;
2533*9880d681SAndroid Build Coastguard Worker break;
2534*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSui:
2535*9880d681SAndroid Build Coastguard Worker Scale = 4;
2536*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::LDURSi;
2537*9880d681SAndroid Build Coastguard Worker break;
2538*9880d681SAndroid Build Coastguard Worker case AArch64::LDRDui:
2539*9880d681SAndroid Build Coastguard Worker Scale = 8;
2540*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::LDURDi;
2541*9880d681SAndroid Build Coastguard Worker break;
2542*9880d681SAndroid Build Coastguard Worker case AArch64::LDRQui:
2543*9880d681SAndroid Build Coastguard Worker Scale = 16;
2544*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::LDURQi;
2545*9880d681SAndroid Build Coastguard Worker break;
2546*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBui:
2547*9880d681SAndroid Build Coastguard Worker Scale = 1;
2548*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::LDURBBi;
2549*9880d681SAndroid Build Coastguard Worker break;
2550*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHui:
2551*9880d681SAndroid Build Coastguard Worker Scale = 2;
2552*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::LDURHHi;
2553*9880d681SAndroid Build Coastguard Worker break;
2554*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBXui:
2555*9880d681SAndroid Build Coastguard Worker Scale = 1;
2556*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::LDURSBXi;
2557*9880d681SAndroid Build Coastguard Worker break;
2558*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBWui:
2559*9880d681SAndroid Build Coastguard Worker Scale = 1;
2560*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::LDURSBWi;
2561*9880d681SAndroid Build Coastguard Worker break;
2562*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHXui:
2563*9880d681SAndroid Build Coastguard Worker Scale = 2;
2564*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::LDURSHXi;
2565*9880d681SAndroid Build Coastguard Worker break;
2566*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHWui:
2567*9880d681SAndroid Build Coastguard Worker Scale = 2;
2568*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::LDURSHWi;
2569*9880d681SAndroid Build Coastguard Worker break;
2570*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWui:
2571*9880d681SAndroid Build Coastguard Worker Scale = 4;
2572*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::LDURSWi;
2573*9880d681SAndroid Build Coastguard Worker break;
2574*9880d681SAndroid Build Coastguard Worker
2575*9880d681SAndroid Build Coastguard Worker case AArch64::STRXui:
2576*9880d681SAndroid Build Coastguard Worker Scale = 8;
2577*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::STURXi;
2578*9880d681SAndroid Build Coastguard Worker break;
2579*9880d681SAndroid Build Coastguard Worker case AArch64::STRWui:
2580*9880d681SAndroid Build Coastguard Worker Scale = 4;
2581*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::STURWi;
2582*9880d681SAndroid Build Coastguard Worker break;
2583*9880d681SAndroid Build Coastguard Worker case AArch64::STRBui:
2584*9880d681SAndroid Build Coastguard Worker Scale = 1;
2585*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::STURBi;
2586*9880d681SAndroid Build Coastguard Worker break;
2587*9880d681SAndroid Build Coastguard Worker case AArch64::STRHui:
2588*9880d681SAndroid Build Coastguard Worker Scale = 2;
2589*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::STURHi;
2590*9880d681SAndroid Build Coastguard Worker break;
2591*9880d681SAndroid Build Coastguard Worker case AArch64::STRSui:
2592*9880d681SAndroid Build Coastguard Worker Scale = 4;
2593*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::STURSi;
2594*9880d681SAndroid Build Coastguard Worker break;
2595*9880d681SAndroid Build Coastguard Worker case AArch64::STRDui:
2596*9880d681SAndroid Build Coastguard Worker Scale = 8;
2597*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::STURDi;
2598*9880d681SAndroid Build Coastguard Worker break;
2599*9880d681SAndroid Build Coastguard Worker case AArch64::STRQui:
2600*9880d681SAndroid Build Coastguard Worker Scale = 16;
2601*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::STURQi;
2602*9880d681SAndroid Build Coastguard Worker break;
2603*9880d681SAndroid Build Coastguard Worker case AArch64::STRBBui:
2604*9880d681SAndroid Build Coastguard Worker Scale = 1;
2605*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::STURBBi;
2606*9880d681SAndroid Build Coastguard Worker break;
2607*9880d681SAndroid Build Coastguard Worker case AArch64::STRHHui:
2608*9880d681SAndroid Build Coastguard Worker Scale = 2;
2609*9880d681SAndroid Build Coastguard Worker UnscaledOp = AArch64::STURHHi;
2610*9880d681SAndroid Build Coastguard Worker break;
2611*9880d681SAndroid Build Coastguard Worker
2612*9880d681SAndroid Build Coastguard Worker case AArch64::LDPXi:
2613*9880d681SAndroid Build Coastguard Worker case AArch64::LDPDi:
2614*9880d681SAndroid Build Coastguard Worker case AArch64::STPXi:
2615*9880d681SAndroid Build Coastguard Worker case AArch64::STPDi:
2616*9880d681SAndroid Build Coastguard Worker case AArch64::LDNPXi:
2617*9880d681SAndroid Build Coastguard Worker case AArch64::LDNPDi:
2618*9880d681SAndroid Build Coastguard Worker case AArch64::STNPXi:
2619*9880d681SAndroid Build Coastguard Worker case AArch64::STNPDi:
2620*9880d681SAndroid Build Coastguard Worker ImmIdx = 3;
2621*9880d681SAndroid Build Coastguard Worker IsSigned = true;
2622*9880d681SAndroid Build Coastguard Worker Scale = 8;
2623*9880d681SAndroid Build Coastguard Worker break;
2624*9880d681SAndroid Build Coastguard Worker case AArch64::LDPQi:
2625*9880d681SAndroid Build Coastguard Worker case AArch64::STPQi:
2626*9880d681SAndroid Build Coastguard Worker case AArch64::LDNPQi:
2627*9880d681SAndroid Build Coastguard Worker case AArch64::STNPQi:
2628*9880d681SAndroid Build Coastguard Worker ImmIdx = 3;
2629*9880d681SAndroid Build Coastguard Worker IsSigned = true;
2630*9880d681SAndroid Build Coastguard Worker Scale = 16;
2631*9880d681SAndroid Build Coastguard Worker break;
2632*9880d681SAndroid Build Coastguard Worker case AArch64::LDPWi:
2633*9880d681SAndroid Build Coastguard Worker case AArch64::LDPSi:
2634*9880d681SAndroid Build Coastguard Worker case AArch64::STPWi:
2635*9880d681SAndroid Build Coastguard Worker case AArch64::STPSi:
2636*9880d681SAndroid Build Coastguard Worker case AArch64::LDNPWi:
2637*9880d681SAndroid Build Coastguard Worker case AArch64::LDNPSi:
2638*9880d681SAndroid Build Coastguard Worker case AArch64::STNPWi:
2639*9880d681SAndroid Build Coastguard Worker case AArch64::STNPSi:
2640*9880d681SAndroid Build Coastguard Worker ImmIdx = 3;
2641*9880d681SAndroid Build Coastguard Worker IsSigned = true;
2642*9880d681SAndroid Build Coastguard Worker Scale = 4;
2643*9880d681SAndroid Build Coastguard Worker break;
2644*9880d681SAndroid Build Coastguard Worker
2645*9880d681SAndroid Build Coastguard Worker case AArch64::LDURXi:
2646*9880d681SAndroid Build Coastguard Worker case AArch64::LDURWi:
2647*9880d681SAndroid Build Coastguard Worker case AArch64::LDURBi:
2648*9880d681SAndroid Build Coastguard Worker case AArch64::LDURHi:
2649*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSi:
2650*9880d681SAndroid Build Coastguard Worker case AArch64::LDURDi:
2651*9880d681SAndroid Build Coastguard Worker case AArch64::LDURQi:
2652*9880d681SAndroid Build Coastguard Worker case AArch64::LDURHHi:
2653*9880d681SAndroid Build Coastguard Worker case AArch64::LDURBBi:
2654*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSBXi:
2655*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSBWi:
2656*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSHXi:
2657*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSHWi:
2658*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSWi:
2659*9880d681SAndroid Build Coastguard Worker case AArch64::STURXi:
2660*9880d681SAndroid Build Coastguard Worker case AArch64::STURWi:
2661*9880d681SAndroid Build Coastguard Worker case AArch64::STURBi:
2662*9880d681SAndroid Build Coastguard Worker case AArch64::STURHi:
2663*9880d681SAndroid Build Coastguard Worker case AArch64::STURSi:
2664*9880d681SAndroid Build Coastguard Worker case AArch64::STURDi:
2665*9880d681SAndroid Build Coastguard Worker case AArch64::STURQi:
2666*9880d681SAndroid Build Coastguard Worker case AArch64::STURBBi:
2667*9880d681SAndroid Build Coastguard Worker case AArch64::STURHHi:
2668*9880d681SAndroid Build Coastguard Worker Scale = 1;
2669*9880d681SAndroid Build Coastguard Worker break;
2670*9880d681SAndroid Build Coastguard Worker }
2671*9880d681SAndroid Build Coastguard Worker
2672*9880d681SAndroid Build Coastguard Worker Offset += MI.getOperand(ImmIdx).getImm() * Scale;
2673*9880d681SAndroid Build Coastguard Worker
2674*9880d681SAndroid Build Coastguard Worker bool useUnscaledOp = false;
2675*9880d681SAndroid Build Coastguard Worker // If the offset doesn't match the scale, we rewrite the instruction to
2676*9880d681SAndroid Build Coastguard Worker // use the unscaled instruction instead. Likewise, if we have a negative
2677*9880d681SAndroid Build Coastguard Worker // offset (and have an unscaled op to use).
2678*9880d681SAndroid Build Coastguard Worker if ((Offset & (Scale - 1)) != 0 || (Offset < 0 && UnscaledOp != 0))
2679*9880d681SAndroid Build Coastguard Worker useUnscaledOp = true;
2680*9880d681SAndroid Build Coastguard Worker
2681*9880d681SAndroid Build Coastguard Worker // Use an unscaled addressing mode if the instruction has a negative offset
2682*9880d681SAndroid Build Coastguard Worker // (or if the instruction is already using an unscaled addressing mode).
2683*9880d681SAndroid Build Coastguard Worker unsigned MaskBits;
2684*9880d681SAndroid Build Coastguard Worker if (IsSigned) {
2685*9880d681SAndroid Build Coastguard Worker // ldp/stp instructions.
2686*9880d681SAndroid Build Coastguard Worker MaskBits = 7;
2687*9880d681SAndroid Build Coastguard Worker Offset /= Scale;
2688*9880d681SAndroid Build Coastguard Worker } else if (UnscaledOp == 0 || useUnscaledOp) {
2689*9880d681SAndroid Build Coastguard Worker MaskBits = 9;
2690*9880d681SAndroid Build Coastguard Worker IsSigned = true;
2691*9880d681SAndroid Build Coastguard Worker Scale = 1;
2692*9880d681SAndroid Build Coastguard Worker } else {
2693*9880d681SAndroid Build Coastguard Worker MaskBits = 12;
2694*9880d681SAndroid Build Coastguard Worker IsSigned = false;
2695*9880d681SAndroid Build Coastguard Worker Offset /= Scale;
2696*9880d681SAndroid Build Coastguard Worker }
2697*9880d681SAndroid Build Coastguard Worker
2698*9880d681SAndroid Build Coastguard Worker // Attempt to fold address computation.
2699*9880d681SAndroid Build Coastguard Worker int MaxOff = (1 << (MaskBits - IsSigned)) - 1;
2700*9880d681SAndroid Build Coastguard Worker int MinOff = (IsSigned ? (-MaxOff - 1) : 0);
2701*9880d681SAndroid Build Coastguard Worker if (Offset >= MinOff && Offset <= MaxOff) {
2702*9880d681SAndroid Build Coastguard Worker if (EmittableOffset)
2703*9880d681SAndroid Build Coastguard Worker *EmittableOffset = Offset;
2704*9880d681SAndroid Build Coastguard Worker Offset = 0;
2705*9880d681SAndroid Build Coastguard Worker } else {
2706*9880d681SAndroid Build Coastguard Worker int NewOff = Offset < 0 ? MinOff : MaxOff;
2707*9880d681SAndroid Build Coastguard Worker if (EmittableOffset)
2708*9880d681SAndroid Build Coastguard Worker *EmittableOffset = NewOff;
2709*9880d681SAndroid Build Coastguard Worker Offset = (Offset - NewOff) * Scale;
2710*9880d681SAndroid Build Coastguard Worker }
2711*9880d681SAndroid Build Coastguard Worker if (OutUseUnscaledOp)
2712*9880d681SAndroid Build Coastguard Worker *OutUseUnscaledOp = useUnscaledOp;
2713*9880d681SAndroid Build Coastguard Worker if (OutUnscaledOp)
2714*9880d681SAndroid Build Coastguard Worker *OutUnscaledOp = UnscaledOp;
2715*9880d681SAndroid Build Coastguard Worker return AArch64FrameOffsetCanUpdate |
2716*9880d681SAndroid Build Coastguard Worker (Offset == 0 ? AArch64FrameOffsetIsLegal : 0);
2717*9880d681SAndroid Build Coastguard Worker }
2718*9880d681SAndroid Build Coastguard Worker
rewriteAArch64FrameIndex(MachineInstr & MI,unsigned FrameRegIdx,unsigned FrameReg,int & Offset,const AArch64InstrInfo * TII)2719*9880d681SAndroid Build Coastguard Worker bool llvm::rewriteAArch64FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
2720*9880d681SAndroid Build Coastguard Worker unsigned FrameReg, int &Offset,
2721*9880d681SAndroid Build Coastguard Worker const AArch64InstrInfo *TII) {
2722*9880d681SAndroid Build Coastguard Worker unsigned Opcode = MI.getOpcode();
2723*9880d681SAndroid Build Coastguard Worker unsigned ImmIdx = FrameRegIdx + 1;
2724*9880d681SAndroid Build Coastguard Worker
2725*9880d681SAndroid Build Coastguard Worker if (Opcode == AArch64::ADDSXri || Opcode == AArch64::ADDXri) {
2726*9880d681SAndroid Build Coastguard Worker Offset += MI.getOperand(ImmIdx).getImm();
2727*9880d681SAndroid Build Coastguard Worker emitFrameOffset(*MI.getParent(), MI, MI.getDebugLoc(),
2728*9880d681SAndroid Build Coastguard Worker MI.getOperand(0).getReg(), FrameReg, Offset, TII,
2729*9880d681SAndroid Build Coastguard Worker MachineInstr::NoFlags, (Opcode == AArch64::ADDSXri));
2730*9880d681SAndroid Build Coastguard Worker MI.eraseFromParent();
2731*9880d681SAndroid Build Coastguard Worker Offset = 0;
2732*9880d681SAndroid Build Coastguard Worker return true;
2733*9880d681SAndroid Build Coastguard Worker }
2734*9880d681SAndroid Build Coastguard Worker
2735*9880d681SAndroid Build Coastguard Worker int NewOffset;
2736*9880d681SAndroid Build Coastguard Worker unsigned UnscaledOp;
2737*9880d681SAndroid Build Coastguard Worker bool UseUnscaledOp;
2738*9880d681SAndroid Build Coastguard Worker int Status = isAArch64FrameOffsetLegal(MI, Offset, &UseUnscaledOp,
2739*9880d681SAndroid Build Coastguard Worker &UnscaledOp, &NewOffset);
2740*9880d681SAndroid Build Coastguard Worker if (Status & AArch64FrameOffsetCanUpdate) {
2741*9880d681SAndroid Build Coastguard Worker if (Status & AArch64FrameOffsetIsLegal)
2742*9880d681SAndroid Build Coastguard Worker // Replace the FrameIndex with FrameReg.
2743*9880d681SAndroid Build Coastguard Worker MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
2744*9880d681SAndroid Build Coastguard Worker if (UseUnscaledOp)
2745*9880d681SAndroid Build Coastguard Worker MI.setDesc(TII->get(UnscaledOp));
2746*9880d681SAndroid Build Coastguard Worker
2747*9880d681SAndroid Build Coastguard Worker MI.getOperand(ImmIdx).ChangeToImmediate(NewOffset);
2748*9880d681SAndroid Build Coastguard Worker return Offset == 0;
2749*9880d681SAndroid Build Coastguard Worker }
2750*9880d681SAndroid Build Coastguard Worker
2751*9880d681SAndroid Build Coastguard Worker return false;
2752*9880d681SAndroid Build Coastguard Worker }
2753*9880d681SAndroid Build Coastguard Worker
getNoopForMachoTarget(MCInst & NopInst) const2754*9880d681SAndroid Build Coastguard Worker void AArch64InstrInfo::getNoopForMachoTarget(MCInst &NopInst) const {
2755*9880d681SAndroid Build Coastguard Worker NopInst.setOpcode(AArch64::HINT);
2756*9880d681SAndroid Build Coastguard Worker NopInst.addOperand(MCOperand::createImm(0));
2757*9880d681SAndroid Build Coastguard Worker }
2758*9880d681SAndroid Build Coastguard Worker
2759*9880d681SAndroid Build Coastguard Worker // AArch64 supports MachineCombiner.
useMachineCombiner() const2760*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::useMachineCombiner() const {
2761*9880d681SAndroid Build Coastguard Worker
2762*9880d681SAndroid Build Coastguard Worker return true;
2763*9880d681SAndroid Build Coastguard Worker }
2764*9880d681SAndroid Build Coastguard Worker //
2765*9880d681SAndroid Build Coastguard Worker // True when Opc sets flag
isCombineInstrSettingFlag(unsigned Opc)2766*9880d681SAndroid Build Coastguard Worker static bool isCombineInstrSettingFlag(unsigned Opc) {
2767*9880d681SAndroid Build Coastguard Worker switch (Opc) {
2768*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWrr:
2769*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWri:
2770*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXrr:
2771*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXri:
2772*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWrr:
2773*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXrr:
2774*9880d681SAndroid Build Coastguard Worker // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
2775*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWri:
2776*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXri:
2777*9880d681SAndroid Build Coastguard Worker return true;
2778*9880d681SAndroid Build Coastguard Worker default:
2779*9880d681SAndroid Build Coastguard Worker break;
2780*9880d681SAndroid Build Coastguard Worker }
2781*9880d681SAndroid Build Coastguard Worker return false;
2782*9880d681SAndroid Build Coastguard Worker }
2783*9880d681SAndroid Build Coastguard Worker //
2784*9880d681SAndroid Build Coastguard Worker // 32b Opcodes that can be combined with a MUL
isCombineInstrCandidate32(unsigned Opc)2785*9880d681SAndroid Build Coastguard Worker static bool isCombineInstrCandidate32(unsigned Opc) {
2786*9880d681SAndroid Build Coastguard Worker switch (Opc) {
2787*9880d681SAndroid Build Coastguard Worker case AArch64::ADDWrr:
2788*9880d681SAndroid Build Coastguard Worker case AArch64::ADDWri:
2789*9880d681SAndroid Build Coastguard Worker case AArch64::SUBWrr:
2790*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWrr:
2791*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSWri:
2792*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWrr:
2793*9880d681SAndroid Build Coastguard Worker // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
2794*9880d681SAndroid Build Coastguard Worker case AArch64::SUBWri:
2795*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSWri:
2796*9880d681SAndroid Build Coastguard Worker return true;
2797*9880d681SAndroid Build Coastguard Worker default:
2798*9880d681SAndroid Build Coastguard Worker break;
2799*9880d681SAndroid Build Coastguard Worker }
2800*9880d681SAndroid Build Coastguard Worker return false;
2801*9880d681SAndroid Build Coastguard Worker }
2802*9880d681SAndroid Build Coastguard Worker //
2803*9880d681SAndroid Build Coastguard Worker // 64b Opcodes that can be combined with a MUL
isCombineInstrCandidate64(unsigned Opc)2804*9880d681SAndroid Build Coastguard Worker static bool isCombineInstrCandidate64(unsigned Opc) {
2805*9880d681SAndroid Build Coastguard Worker switch (Opc) {
2806*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXrr:
2807*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXri:
2808*9880d681SAndroid Build Coastguard Worker case AArch64::SUBXrr:
2809*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXrr:
2810*9880d681SAndroid Build Coastguard Worker case AArch64::ADDSXri:
2811*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXrr:
2812*9880d681SAndroid Build Coastguard Worker // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
2813*9880d681SAndroid Build Coastguard Worker case AArch64::SUBXri:
2814*9880d681SAndroid Build Coastguard Worker case AArch64::SUBSXri:
2815*9880d681SAndroid Build Coastguard Worker return true;
2816*9880d681SAndroid Build Coastguard Worker default:
2817*9880d681SAndroid Build Coastguard Worker break;
2818*9880d681SAndroid Build Coastguard Worker }
2819*9880d681SAndroid Build Coastguard Worker return false;
2820*9880d681SAndroid Build Coastguard Worker }
2821*9880d681SAndroid Build Coastguard Worker //
2822*9880d681SAndroid Build Coastguard Worker // FP Opcodes that can be combined with a FMUL
isCombineInstrCandidateFP(const MachineInstr & Inst)2823*9880d681SAndroid Build Coastguard Worker static bool isCombineInstrCandidateFP(const MachineInstr &Inst) {
2824*9880d681SAndroid Build Coastguard Worker switch (Inst.getOpcode()) {
2825*9880d681SAndroid Build Coastguard Worker case AArch64::FADDSrr:
2826*9880d681SAndroid Build Coastguard Worker case AArch64::FADDDrr:
2827*9880d681SAndroid Build Coastguard Worker case AArch64::FADDv2f32:
2828*9880d681SAndroid Build Coastguard Worker case AArch64::FADDv2f64:
2829*9880d681SAndroid Build Coastguard Worker case AArch64::FADDv4f32:
2830*9880d681SAndroid Build Coastguard Worker case AArch64::FSUBSrr:
2831*9880d681SAndroid Build Coastguard Worker case AArch64::FSUBDrr:
2832*9880d681SAndroid Build Coastguard Worker case AArch64::FSUBv2f32:
2833*9880d681SAndroid Build Coastguard Worker case AArch64::FSUBv2f64:
2834*9880d681SAndroid Build Coastguard Worker case AArch64::FSUBv4f32:
2835*9880d681SAndroid Build Coastguard Worker return Inst.getParent()->getParent()->getTarget().Options.UnsafeFPMath;
2836*9880d681SAndroid Build Coastguard Worker default:
2837*9880d681SAndroid Build Coastguard Worker break;
2838*9880d681SAndroid Build Coastguard Worker }
2839*9880d681SAndroid Build Coastguard Worker return false;
2840*9880d681SAndroid Build Coastguard Worker }
2841*9880d681SAndroid Build Coastguard Worker //
2842*9880d681SAndroid Build Coastguard Worker // Opcodes that can be combined with a MUL
isCombineInstrCandidate(unsigned Opc)2843*9880d681SAndroid Build Coastguard Worker static bool isCombineInstrCandidate(unsigned Opc) {
2844*9880d681SAndroid Build Coastguard Worker return (isCombineInstrCandidate32(Opc) || isCombineInstrCandidate64(Opc));
2845*9880d681SAndroid Build Coastguard Worker }
2846*9880d681SAndroid Build Coastguard Worker
2847*9880d681SAndroid Build Coastguard Worker //
2848*9880d681SAndroid Build Coastguard Worker // Utility routine that checks if \param MO is defined by an
2849*9880d681SAndroid Build Coastguard Worker // \param CombineOpc instruction in the basic block \param MBB
canCombine(MachineBasicBlock & MBB,MachineOperand & MO,unsigned CombineOpc,unsigned ZeroReg=0,bool CheckZeroReg=false)2850*9880d681SAndroid Build Coastguard Worker static bool canCombine(MachineBasicBlock &MBB, MachineOperand &MO,
2851*9880d681SAndroid Build Coastguard Worker unsigned CombineOpc, unsigned ZeroReg = 0,
2852*9880d681SAndroid Build Coastguard Worker bool CheckZeroReg = false) {
2853*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
2854*9880d681SAndroid Build Coastguard Worker MachineInstr *MI = nullptr;
2855*9880d681SAndroid Build Coastguard Worker
2856*9880d681SAndroid Build Coastguard Worker if (MO.isReg() && TargetRegisterInfo::isVirtualRegister(MO.getReg()))
2857*9880d681SAndroid Build Coastguard Worker MI = MRI.getUniqueVRegDef(MO.getReg());
2858*9880d681SAndroid Build Coastguard Worker // And it needs to be in the trace (otherwise, it won't have a depth).
2859*9880d681SAndroid Build Coastguard Worker if (!MI || MI->getParent() != &MBB || (unsigned)MI->getOpcode() != CombineOpc)
2860*9880d681SAndroid Build Coastguard Worker return false;
2861*9880d681SAndroid Build Coastguard Worker // Must only used by the user we combine with.
2862*9880d681SAndroid Build Coastguard Worker if (!MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))
2863*9880d681SAndroid Build Coastguard Worker return false;
2864*9880d681SAndroid Build Coastguard Worker
2865*9880d681SAndroid Build Coastguard Worker if (CheckZeroReg) {
2866*9880d681SAndroid Build Coastguard Worker assert(MI->getNumOperands() >= 4 && MI->getOperand(0).isReg() &&
2867*9880d681SAndroid Build Coastguard Worker MI->getOperand(1).isReg() && MI->getOperand(2).isReg() &&
2868*9880d681SAndroid Build Coastguard Worker MI->getOperand(3).isReg() && "MAdd/MSub must have a least 4 regs");
2869*9880d681SAndroid Build Coastguard Worker // The third input reg must be zero.
2870*9880d681SAndroid Build Coastguard Worker if (MI->getOperand(3).getReg() != ZeroReg)
2871*9880d681SAndroid Build Coastguard Worker return false;
2872*9880d681SAndroid Build Coastguard Worker }
2873*9880d681SAndroid Build Coastguard Worker
2874*9880d681SAndroid Build Coastguard Worker return true;
2875*9880d681SAndroid Build Coastguard Worker }
2876*9880d681SAndroid Build Coastguard Worker
2877*9880d681SAndroid Build Coastguard Worker //
2878*9880d681SAndroid Build Coastguard Worker // Is \param MO defined by an integer multiply and can be combined?
canCombineWithMUL(MachineBasicBlock & MBB,MachineOperand & MO,unsigned MulOpc,unsigned ZeroReg)2879*9880d681SAndroid Build Coastguard Worker static bool canCombineWithMUL(MachineBasicBlock &MBB, MachineOperand &MO,
2880*9880d681SAndroid Build Coastguard Worker unsigned MulOpc, unsigned ZeroReg) {
2881*9880d681SAndroid Build Coastguard Worker return canCombine(MBB, MO, MulOpc, ZeroReg, true);
2882*9880d681SAndroid Build Coastguard Worker }
2883*9880d681SAndroid Build Coastguard Worker
2884*9880d681SAndroid Build Coastguard Worker //
2885*9880d681SAndroid Build Coastguard Worker // Is \param MO defined by a floating-point multiply and can be combined?
canCombineWithFMUL(MachineBasicBlock & MBB,MachineOperand & MO,unsigned MulOpc)2886*9880d681SAndroid Build Coastguard Worker static bool canCombineWithFMUL(MachineBasicBlock &MBB, MachineOperand &MO,
2887*9880d681SAndroid Build Coastguard Worker unsigned MulOpc) {
2888*9880d681SAndroid Build Coastguard Worker return canCombine(MBB, MO, MulOpc);
2889*9880d681SAndroid Build Coastguard Worker }
2890*9880d681SAndroid Build Coastguard Worker
2891*9880d681SAndroid Build Coastguard Worker // TODO: There are many more machine instruction opcodes to match:
2892*9880d681SAndroid Build Coastguard Worker // 1. Other data types (integer, vectors)
2893*9880d681SAndroid Build Coastguard Worker // 2. Other math / logic operations (xor, or)
2894*9880d681SAndroid Build Coastguard Worker // 3. Other forms of the same operation (intrinsics and other variants)
isAssociativeAndCommutative(const MachineInstr & Inst) const2895*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst) const {
2896*9880d681SAndroid Build Coastguard Worker switch (Inst.getOpcode()) {
2897*9880d681SAndroid Build Coastguard Worker case AArch64::FADDDrr:
2898*9880d681SAndroid Build Coastguard Worker case AArch64::FADDSrr:
2899*9880d681SAndroid Build Coastguard Worker case AArch64::FADDv2f32:
2900*9880d681SAndroid Build Coastguard Worker case AArch64::FADDv2f64:
2901*9880d681SAndroid Build Coastguard Worker case AArch64::FADDv4f32:
2902*9880d681SAndroid Build Coastguard Worker case AArch64::FMULDrr:
2903*9880d681SAndroid Build Coastguard Worker case AArch64::FMULSrr:
2904*9880d681SAndroid Build Coastguard Worker case AArch64::FMULX32:
2905*9880d681SAndroid Build Coastguard Worker case AArch64::FMULX64:
2906*9880d681SAndroid Build Coastguard Worker case AArch64::FMULXv2f32:
2907*9880d681SAndroid Build Coastguard Worker case AArch64::FMULXv2f64:
2908*9880d681SAndroid Build Coastguard Worker case AArch64::FMULXv4f32:
2909*9880d681SAndroid Build Coastguard Worker case AArch64::FMULv2f32:
2910*9880d681SAndroid Build Coastguard Worker case AArch64::FMULv2f64:
2911*9880d681SAndroid Build Coastguard Worker case AArch64::FMULv4f32:
2912*9880d681SAndroid Build Coastguard Worker return Inst.getParent()->getParent()->getTarget().Options.UnsafeFPMath;
2913*9880d681SAndroid Build Coastguard Worker default:
2914*9880d681SAndroid Build Coastguard Worker return false;
2915*9880d681SAndroid Build Coastguard Worker }
2916*9880d681SAndroid Build Coastguard Worker }
2917*9880d681SAndroid Build Coastguard Worker
2918*9880d681SAndroid Build Coastguard Worker /// Find instructions that can be turned into madd.
getMaddPatterns(MachineInstr & Root,SmallVectorImpl<MachineCombinerPattern> & Patterns)2919*9880d681SAndroid Build Coastguard Worker static bool getMaddPatterns(MachineInstr &Root,
2920*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MachineCombinerPattern> &Patterns) {
2921*9880d681SAndroid Build Coastguard Worker unsigned Opc = Root.getOpcode();
2922*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *Root.getParent();
2923*9880d681SAndroid Build Coastguard Worker bool Found = false;
2924*9880d681SAndroid Build Coastguard Worker
2925*9880d681SAndroid Build Coastguard Worker if (!isCombineInstrCandidate(Opc))
2926*9880d681SAndroid Build Coastguard Worker return false;
2927*9880d681SAndroid Build Coastguard Worker if (isCombineInstrSettingFlag(Opc)) {
2928*9880d681SAndroid Build Coastguard Worker int Cmp_NZCV = Root.findRegisterDefOperandIdx(AArch64::NZCV, true);
2929*9880d681SAndroid Build Coastguard Worker // When NZCV is live bail out.
2930*9880d681SAndroid Build Coastguard Worker if (Cmp_NZCV == -1)
2931*9880d681SAndroid Build Coastguard Worker return false;
2932*9880d681SAndroid Build Coastguard Worker unsigned NewOpc = convertFlagSettingOpcode(Root);
2933*9880d681SAndroid Build Coastguard Worker // When opcode can't change bail out.
2934*9880d681SAndroid Build Coastguard Worker // CHECKME: do we miss any cases for opcode conversion?
2935*9880d681SAndroid Build Coastguard Worker if (NewOpc == Opc)
2936*9880d681SAndroid Build Coastguard Worker return false;
2937*9880d681SAndroid Build Coastguard Worker Opc = NewOpc;
2938*9880d681SAndroid Build Coastguard Worker }
2939*9880d681SAndroid Build Coastguard Worker
2940*9880d681SAndroid Build Coastguard Worker switch (Opc) {
2941*9880d681SAndroid Build Coastguard Worker default:
2942*9880d681SAndroid Build Coastguard Worker break;
2943*9880d681SAndroid Build Coastguard Worker case AArch64::ADDWrr:
2944*9880d681SAndroid Build Coastguard Worker assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
2945*9880d681SAndroid Build Coastguard Worker "ADDWrr does not have register operands");
2946*9880d681SAndroid Build Coastguard Worker if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDWrrr,
2947*9880d681SAndroid Build Coastguard Worker AArch64::WZR)) {
2948*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::MULADDW_OP1);
2949*9880d681SAndroid Build Coastguard Worker Found = true;
2950*9880d681SAndroid Build Coastguard Worker }
2951*9880d681SAndroid Build Coastguard Worker if (canCombineWithMUL(MBB, Root.getOperand(2), AArch64::MADDWrrr,
2952*9880d681SAndroid Build Coastguard Worker AArch64::WZR)) {
2953*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::MULADDW_OP2);
2954*9880d681SAndroid Build Coastguard Worker Found = true;
2955*9880d681SAndroid Build Coastguard Worker }
2956*9880d681SAndroid Build Coastguard Worker break;
2957*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXrr:
2958*9880d681SAndroid Build Coastguard Worker if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDXrrr,
2959*9880d681SAndroid Build Coastguard Worker AArch64::XZR)) {
2960*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::MULADDX_OP1);
2961*9880d681SAndroid Build Coastguard Worker Found = true;
2962*9880d681SAndroid Build Coastguard Worker }
2963*9880d681SAndroid Build Coastguard Worker if (canCombineWithMUL(MBB, Root.getOperand(2), AArch64::MADDXrrr,
2964*9880d681SAndroid Build Coastguard Worker AArch64::XZR)) {
2965*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::MULADDX_OP2);
2966*9880d681SAndroid Build Coastguard Worker Found = true;
2967*9880d681SAndroid Build Coastguard Worker }
2968*9880d681SAndroid Build Coastguard Worker break;
2969*9880d681SAndroid Build Coastguard Worker case AArch64::SUBWrr:
2970*9880d681SAndroid Build Coastguard Worker if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDWrrr,
2971*9880d681SAndroid Build Coastguard Worker AArch64::WZR)) {
2972*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::MULSUBW_OP1);
2973*9880d681SAndroid Build Coastguard Worker Found = true;
2974*9880d681SAndroid Build Coastguard Worker }
2975*9880d681SAndroid Build Coastguard Worker if (canCombineWithMUL(MBB, Root.getOperand(2), AArch64::MADDWrrr,
2976*9880d681SAndroid Build Coastguard Worker AArch64::WZR)) {
2977*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::MULSUBW_OP2);
2978*9880d681SAndroid Build Coastguard Worker Found = true;
2979*9880d681SAndroid Build Coastguard Worker }
2980*9880d681SAndroid Build Coastguard Worker break;
2981*9880d681SAndroid Build Coastguard Worker case AArch64::SUBXrr:
2982*9880d681SAndroid Build Coastguard Worker if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDXrrr,
2983*9880d681SAndroid Build Coastguard Worker AArch64::XZR)) {
2984*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::MULSUBX_OP1);
2985*9880d681SAndroid Build Coastguard Worker Found = true;
2986*9880d681SAndroid Build Coastguard Worker }
2987*9880d681SAndroid Build Coastguard Worker if (canCombineWithMUL(MBB, Root.getOperand(2), AArch64::MADDXrrr,
2988*9880d681SAndroid Build Coastguard Worker AArch64::XZR)) {
2989*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::MULSUBX_OP2);
2990*9880d681SAndroid Build Coastguard Worker Found = true;
2991*9880d681SAndroid Build Coastguard Worker }
2992*9880d681SAndroid Build Coastguard Worker break;
2993*9880d681SAndroid Build Coastguard Worker case AArch64::ADDWri:
2994*9880d681SAndroid Build Coastguard Worker if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDWrrr,
2995*9880d681SAndroid Build Coastguard Worker AArch64::WZR)) {
2996*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::MULADDWI_OP1);
2997*9880d681SAndroid Build Coastguard Worker Found = true;
2998*9880d681SAndroid Build Coastguard Worker }
2999*9880d681SAndroid Build Coastguard Worker break;
3000*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXri:
3001*9880d681SAndroid Build Coastguard Worker if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDXrrr,
3002*9880d681SAndroid Build Coastguard Worker AArch64::XZR)) {
3003*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::MULADDXI_OP1);
3004*9880d681SAndroid Build Coastguard Worker Found = true;
3005*9880d681SAndroid Build Coastguard Worker }
3006*9880d681SAndroid Build Coastguard Worker break;
3007*9880d681SAndroid Build Coastguard Worker case AArch64::SUBWri:
3008*9880d681SAndroid Build Coastguard Worker if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDWrrr,
3009*9880d681SAndroid Build Coastguard Worker AArch64::WZR)) {
3010*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::MULSUBWI_OP1);
3011*9880d681SAndroid Build Coastguard Worker Found = true;
3012*9880d681SAndroid Build Coastguard Worker }
3013*9880d681SAndroid Build Coastguard Worker break;
3014*9880d681SAndroid Build Coastguard Worker case AArch64::SUBXri:
3015*9880d681SAndroid Build Coastguard Worker if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDXrrr,
3016*9880d681SAndroid Build Coastguard Worker AArch64::XZR)) {
3017*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::MULSUBXI_OP1);
3018*9880d681SAndroid Build Coastguard Worker Found = true;
3019*9880d681SAndroid Build Coastguard Worker }
3020*9880d681SAndroid Build Coastguard Worker break;
3021*9880d681SAndroid Build Coastguard Worker }
3022*9880d681SAndroid Build Coastguard Worker return Found;
3023*9880d681SAndroid Build Coastguard Worker }
3024*9880d681SAndroid Build Coastguard Worker /// Floating-Point Support
3025*9880d681SAndroid Build Coastguard Worker
3026*9880d681SAndroid Build Coastguard Worker /// Find instructions that can be turned into madd.
getFMAPatterns(MachineInstr & Root,SmallVectorImpl<MachineCombinerPattern> & Patterns)3027*9880d681SAndroid Build Coastguard Worker static bool getFMAPatterns(MachineInstr &Root,
3028*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MachineCombinerPattern> &Patterns) {
3029*9880d681SAndroid Build Coastguard Worker
3030*9880d681SAndroid Build Coastguard Worker if (!isCombineInstrCandidateFP(Root))
3031*9880d681SAndroid Build Coastguard Worker return 0;
3032*9880d681SAndroid Build Coastguard Worker
3033*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *Root.getParent();
3034*9880d681SAndroid Build Coastguard Worker bool Found = false;
3035*9880d681SAndroid Build Coastguard Worker
3036*9880d681SAndroid Build Coastguard Worker switch (Root.getOpcode()) {
3037*9880d681SAndroid Build Coastguard Worker default:
3038*9880d681SAndroid Build Coastguard Worker assert(false && "Unsupported FP instruction in combiner\n");
3039*9880d681SAndroid Build Coastguard Worker break;
3040*9880d681SAndroid Build Coastguard Worker case AArch64::FADDSrr:
3041*9880d681SAndroid Build Coastguard Worker assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
3042*9880d681SAndroid Build Coastguard Worker "FADDWrr does not have register operands");
3043*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(1), AArch64::FMULSrr)) {
3044*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMULADDS_OP1);
3045*9880d681SAndroid Build Coastguard Worker Found = true;
3046*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(1),
3047*9880d681SAndroid Build Coastguard Worker AArch64::FMULv1i32_indexed)) {
3048*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv1i32_indexed_OP1);
3049*9880d681SAndroid Build Coastguard Worker Found = true;
3050*9880d681SAndroid Build Coastguard Worker }
3051*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(2), AArch64::FMULSrr)) {
3052*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMULADDS_OP2);
3053*9880d681SAndroid Build Coastguard Worker Found = true;
3054*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3055*9880d681SAndroid Build Coastguard Worker AArch64::FMULv1i32_indexed)) {
3056*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv1i32_indexed_OP2);
3057*9880d681SAndroid Build Coastguard Worker Found = true;
3058*9880d681SAndroid Build Coastguard Worker }
3059*9880d681SAndroid Build Coastguard Worker break;
3060*9880d681SAndroid Build Coastguard Worker case AArch64::FADDDrr:
3061*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(1), AArch64::FMULDrr)) {
3062*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMULADDD_OP1);
3063*9880d681SAndroid Build Coastguard Worker Found = true;
3064*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(1),
3065*9880d681SAndroid Build Coastguard Worker AArch64::FMULv1i64_indexed)) {
3066*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv1i64_indexed_OP1);
3067*9880d681SAndroid Build Coastguard Worker Found = true;
3068*9880d681SAndroid Build Coastguard Worker }
3069*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(2), AArch64::FMULDrr)) {
3070*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMULADDD_OP2);
3071*9880d681SAndroid Build Coastguard Worker Found = true;
3072*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3073*9880d681SAndroid Build Coastguard Worker AArch64::FMULv1i64_indexed)) {
3074*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv1i64_indexed_OP2);
3075*9880d681SAndroid Build Coastguard Worker Found = true;
3076*9880d681SAndroid Build Coastguard Worker }
3077*9880d681SAndroid Build Coastguard Worker break;
3078*9880d681SAndroid Build Coastguard Worker case AArch64::FADDv2f32:
3079*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(1),
3080*9880d681SAndroid Build Coastguard Worker AArch64::FMULv2i32_indexed)) {
3081*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv2i32_indexed_OP1);
3082*9880d681SAndroid Build Coastguard Worker Found = true;
3083*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(1),
3084*9880d681SAndroid Build Coastguard Worker AArch64::FMULv2f32)) {
3085*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv2f32_OP1);
3086*9880d681SAndroid Build Coastguard Worker Found = true;
3087*9880d681SAndroid Build Coastguard Worker }
3088*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(2),
3089*9880d681SAndroid Build Coastguard Worker AArch64::FMULv2i32_indexed)) {
3090*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv2i32_indexed_OP2);
3091*9880d681SAndroid Build Coastguard Worker Found = true;
3092*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3093*9880d681SAndroid Build Coastguard Worker AArch64::FMULv2f32)) {
3094*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv2f32_OP2);
3095*9880d681SAndroid Build Coastguard Worker Found = true;
3096*9880d681SAndroid Build Coastguard Worker }
3097*9880d681SAndroid Build Coastguard Worker break;
3098*9880d681SAndroid Build Coastguard Worker case AArch64::FADDv2f64:
3099*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(1),
3100*9880d681SAndroid Build Coastguard Worker AArch64::FMULv2i64_indexed)) {
3101*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv2i64_indexed_OP1);
3102*9880d681SAndroid Build Coastguard Worker Found = true;
3103*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(1),
3104*9880d681SAndroid Build Coastguard Worker AArch64::FMULv2f64)) {
3105*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv2f64_OP1);
3106*9880d681SAndroid Build Coastguard Worker Found = true;
3107*9880d681SAndroid Build Coastguard Worker }
3108*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(2),
3109*9880d681SAndroid Build Coastguard Worker AArch64::FMULv2i64_indexed)) {
3110*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv2i64_indexed_OP2);
3111*9880d681SAndroid Build Coastguard Worker Found = true;
3112*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3113*9880d681SAndroid Build Coastguard Worker AArch64::FMULv2f64)) {
3114*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv2f64_OP2);
3115*9880d681SAndroid Build Coastguard Worker Found = true;
3116*9880d681SAndroid Build Coastguard Worker }
3117*9880d681SAndroid Build Coastguard Worker break;
3118*9880d681SAndroid Build Coastguard Worker case AArch64::FADDv4f32:
3119*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(1),
3120*9880d681SAndroid Build Coastguard Worker AArch64::FMULv4i32_indexed)) {
3121*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv4i32_indexed_OP1);
3122*9880d681SAndroid Build Coastguard Worker Found = true;
3123*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(1),
3124*9880d681SAndroid Build Coastguard Worker AArch64::FMULv4f32)) {
3125*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv4f32_OP1);
3126*9880d681SAndroid Build Coastguard Worker Found = true;
3127*9880d681SAndroid Build Coastguard Worker }
3128*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(2),
3129*9880d681SAndroid Build Coastguard Worker AArch64::FMULv4i32_indexed)) {
3130*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv4i32_indexed_OP2);
3131*9880d681SAndroid Build Coastguard Worker Found = true;
3132*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3133*9880d681SAndroid Build Coastguard Worker AArch64::FMULv4f32)) {
3134*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLAv4f32_OP2);
3135*9880d681SAndroid Build Coastguard Worker Found = true;
3136*9880d681SAndroid Build Coastguard Worker }
3137*9880d681SAndroid Build Coastguard Worker break;
3138*9880d681SAndroid Build Coastguard Worker
3139*9880d681SAndroid Build Coastguard Worker case AArch64::FSUBSrr:
3140*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(1), AArch64::FMULSrr)) {
3141*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMULSUBS_OP1);
3142*9880d681SAndroid Build Coastguard Worker Found = true;
3143*9880d681SAndroid Build Coastguard Worker }
3144*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(2), AArch64::FMULSrr)) {
3145*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMULSUBS_OP2);
3146*9880d681SAndroid Build Coastguard Worker Found = true;
3147*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3148*9880d681SAndroid Build Coastguard Worker AArch64::FMULv1i32_indexed)) {
3149*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLSv1i32_indexed_OP2);
3150*9880d681SAndroid Build Coastguard Worker Found = true;
3151*9880d681SAndroid Build Coastguard Worker }
3152*9880d681SAndroid Build Coastguard Worker break;
3153*9880d681SAndroid Build Coastguard Worker case AArch64::FSUBDrr:
3154*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(1), AArch64::FMULDrr)) {
3155*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMULSUBD_OP1);
3156*9880d681SAndroid Build Coastguard Worker Found = true;
3157*9880d681SAndroid Build Coastguard Worker }
3158*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(2), AArch64::FMULDrr)) {
3159*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMULSUBD_OP2);
3160*9880d681SAndroid Build Coastguard Worker Found = true;
3161*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3162*9880d681SAndroid Build Coastguard Worker AArch64::FMULv1i64_indexed)) {
3163*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLSv1i64_indexed_OP2);
3164*9880d681SAndroid Build Coastguard Worker Found = true;
3165*9880d681SAndroid Build Coastguard Worker }
3166*9880d681SAndroid Build Coastguard Worker break;
3167*9880d681SAndroid Build Coastguard Worker case AArch64::FSUBv2f32:
3168*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(2),
3169*9880d681SAndroid Build Coastguard Worker AArch64::FMULv2i32_indexed)) {
3170*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLSv2i32_indexed_OP2);
3171*9880d681SAndroid Build Coastguard Worker Found = true;
3172*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3173*9880d681SAndroid Build Coastguard Worker AArch64::FMULv2f32)) {
3174*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLSv2f32_OP2);
3175*9880d681SAndroid Build Coastguard Worker Found = true;
3176*9880d681SAndroid Build Coastguard Worker }
3177*9880d681SAndroid Build Coastguard Worker break;
3178*9880d681SAndroid Build Coastguard Worker case AArch64::FSUBv2f64:
3179*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(2),
3180*9880d681SAndroid Build Coastguard Worker AArch64::FMULv2i64_indexed)) {
3181*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLSv2i64_indexed_OP2);
3182*9880d681SAndroid Build Coastguard Worker Found = true;
3183*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3184*9880d681SAndroid Build Coastguard Worker AArch64::FMULv2f64)) {
3185*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLSv2f64_OP2);
3186*9880d681SAndroid Build Coastguard Worker Found = true;
3187*9880d681SAndroid Build Coastguard Worker }
3188*9880d681SAndroid Build Coastguard Worker break;
3189*9880d681SAndroid Build Coastguard Worker case AArch64::FSUBv4f32:
3190*9880d681SAndroid Build Coastguard Worker if (canCombineWithFMUL(MBB, Root.getOperand(2),
3191*9880d681SAndroid Build Coastguard Worker AArch64::FMULv4i32_indexed)) {
3192*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLSv4i32_indexed_OP2);
3193*9880d681SAndroid Build Coastguard Worker Found = true;
3194*9880d681SAndroid Build Coastguard Worker } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3195*9880d681SAndroid Build Coastguard Worker AArch64::FMULv4f32)) {
3196*9880d681SAndroid Build Coastguard Worker Patterns.push_back(MachineCombinerPattern::FMLSv4f32_OP2);
3197*9880d681SAndroid Build Coastguard Worker Found = true;
3198*9880d681SAndroid Build Coastguard Worker }
3199*9880d681SAndroid Build Coastguard Worker break;
3200*9880d681SAndroid Build Coastguard Worker }
3201*9880d681SAndroid Build Coastguard Worker return Found;
3202*9880d681SAndroid Build Coastguard Worker }
3203*9880d681SAndroid Build Coastguard Worker
3204*9880d681SAndroid Build Coastguard Worker /// Return true when a code sequence can improve throughput. It
3205*9880d681SAndroid Build Coastguard Worker /// should be called only for instructions in loops.
3206*9880d681SAndroid Build Coastguard Worker /// \param Pattern - combiner pattern
3207*9880d681SAndroid Build Coastguard Worker bool
isThroughputPattern(MachineCombinerPattern Pattern) const3208*9880d681SAndroid Build Coastguard Worker AArch64InstrInfo::isThroughputPattern(MachineCombinerPattern Pattern) const {
3209*9880d681SAndroid Build Coastguard Worker switch (Pattern) {
3210*9880d681SAndroid Build Coastguard Worker default:
3211*9880d681SAndroid Build Coastguard Worker break;
3212*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULADDS_OP1:
3213*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULADDS_OP2:
3214*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULSUBS_OP1:
3215*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULSUBS_OP2:
3216*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULADDD_OP1:
3217*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULADDD_OP2:
3218*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULSUBD_OP1:
3219*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULSUBD_OP2:
3220*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv1i32_indexed_OP1:
3221*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv1i32_indexed_OP2:
3222*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv1i64_indexed_OP1:
3223*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv1i64_indexed_OP2:
3224*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2f32_OP2:
3225*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2f32_OP1:
3226*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2f64_OP1:
3227*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2f64_OP2:
3228*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2i32_indexed_OP1:
3229*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2i32_indexed_OP2:
3230*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2i64_indexed_OP1:
3231*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2i64_indexed_OP2:
3232*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv4f32_OP1:
3233*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv4f32_OP2:
3234*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv4i32_indexed_OP1:
3235*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv4i32_indexed_OP2:
3236*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv1i32_indexed_OP2:
3237*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv1i64_indexed_OP2:
3238*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv2i32_indexed_OP2:
3239*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv2i64_indexed_OP2:
3240*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv2f32_OP2:
3241*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv2f64_OP2:
3242*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv4i32_indexed_OP2:
3243*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv4f32_OP2:
3244*9880d681SAndroid Build Coastguard Worker return true;
3245*9880d681SAndroid Build Coastguard Worker } // end switch (Pattern)
3246*9880d681SAndroid Build Coastguard Worker return false;
3247*9880d681SAndroid Build Coastguard Worker }
3248*9880d681SAndroid Build Coastguard Worker /// Return true when there is potentially a faster code sequence for an
3249*9880d681SAndroid Build Coastguard Worker /// instruction chain ending in \p Root. All potential patterns are listed in
3250*9880d681SAndroid Build Coastguard Worker /// the \p Pattern vector. Pattern should be sorted in priority order since the
3251*9880d681SAndroid Build Coastguard Worker /// pattern evaluator stops checking as soon as it finds a faster sequence.
3252*9880d681SAndroid Build Coastguard Worker
getMachineCombinerPatterns(MachineInstr & Root,SmallVectorImpl<MachineCombinerPattern> & Patterns) const3253*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::getMachineCombinerPatterns(
3254*9880d681SAndroid Build Coastguard Worker MachineInstr &Root,
3255*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MachineCombinerPattern> &Patterns) const {
3256*9880d681SAndroid Build Coastguard Worker // Integer patterns
3257*9880d681SAndroid Build Coastguard Worker if (getMaddPatterns(Root, Patterns))
3258*9880d681SAndroid Build Coastguard Worker return true;
3259*9880d681SAndroid Build Coastguard Worker // Floating point patterns
3260*9880d681SAndroid Build Coastguard Worker if (getFMAPatterns(Root, Patterns))
3261*9880d681SAndroid Build Coastguard Worker return true;
3262*9880d681SAndroid Build Coastguard Worker
3263*9880d681SAndroid Build Coastguard Worker return TargetInstrInfo::getMachineCombinerPatterns(Root, Patterns);
3264*9880d681SAndroid Build Coastguard Worker }
3265*9880d681SAndroid Build Coastguard Worker
3266*9880d681SAndroid Build Coastguard Worker enum class FMAInstKind { Default, Indexed, Accumulator };
3267*9880d681SAndroid Build Coastguard Worker /// genFusedMultiply - Generate fused multiply instructions.
3268*9880d681SAndroid Build Coastguard Worker /// This function supports both integer and floating point instructions.
3269*9880d681SAndroid Build Coastguard Worker /// A typical example:
3270*9880d681SAndroid Build Coastguard Worker /// F|MUL I=A,B,0
3271*9880d681SAndroid Build Coastguard Worker /// F|ADD R,I,C
3272*9880d681SAndroid Build Coastguard Worker /// ==> F|MADD R,A,B,C
3273*9880d681SAndroid Build Coastguard Worker /// \param Root is the F|ADD instruction
3274*9880d681SAndroid Build Coastguard Worker /// \param [out] InsInstrs is a vector of machine instructions and will
3275*9880d681SAndroid Build Coastguard Worker /// contain the generated madd instruction
3276*9880d681SAndroid Build Coastguard Worker /// \param IdxMulOpd is index of operand in Root that is the result of
3277*9880d681SAndroid Build Coastguard Worker /// the F|MUL. In the example above IdxMulOpd is 1.
3278*9880d681SAndroid Build Coastguard Worker /// \param MaddOpc the opcode fo the f|madd instruction
3279*9880d681SAndroid Build Coastguard Worker static MachineInstr *
genFusedMultiply(MachineFunction & MF,MachineRegisterInfo & MRI,const TargetInstrInfo * TII,MachineInstr & Root,SmallVectorImpl<MachineInstr * > & InsInstrs,unsigned IdxMulOpd,unsigned MaddOpc,const TargetRegisterClass * RC,FMAInstKind kind=FMAInstKind::Default)3280*9880d681SAndroid Build Coastguard Worker genFusedMultiply(MachineFunction &MF, MachineRegisterInfo &MRI,
3281*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII, MachineInstr &Root,
3282*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MachineInstr *> &InsInstrs, unsigned IdxMulOpd,
3283*9880d681SAndroid Build Coastguard Worker unsigned MaddOpc, const TargetRegisterClass *RC,
3284*9880d681SAndroid Build Coastguard Worker FMAInstKind kind = FMAInstKind::Default) {
3285*9880d681SAndroid Build Coastguard Worker assert(IdxMulOpd == 1 || IdxMulOpd == 2);
3286*9880d681SAndroid Build Coastguard Worker
3287*9880d681SAndroid Build Coastguard Worker unsigned IdxOtherOpd = IdxMulOpd == 1 ? 2 : 1;
3288*9880d681SAndroid Build Coastguard Worker MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
3289*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = Root.getOperand(0).getReg();
3290*9880d681SAndroid Build Coastguard Worker unsigned SrcReg0 = MUL->getOperand(1).getReg();
3291*9880d681SAndroid Build Coastguard Worker bool Src0IsKill = MUL->getOperand(1).isKill();
3292*9880d681SAndroid Build Coastguard Worker unsigned SrcReg1 = MUL->getOperand(2).getReg();
3293*9880d681SAndroid Build Coastguard Worker bool Src1IsKill = MUL->getOperand(2).isKill();
3294*9880d681SAndroid Build Coastguard Worker unsigned SrcReg2 = Root.getOperand(IdxOtherOpd).getReg();
3295*9880d681SAndroid Build Coastguard Worker bool Src2IsKill = Root.getOperand(IdxOtherOpd).isKill();
3296*9880d681SAndroid Build Coastguard Worker
3297*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(ResultReg))
3298*9880d681SAndroid Build Coastguard Worker MRI.constrainRegClass(ResultReg, RC);
3299*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(SrcReg0))
3300*9880d681SAndroid Build Coastguard Worker MRI.constrainRegClass(SrcReg0, RC);
3301*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(SrcReg1))
3302*9880d681SAndroid Build Coastguard Worker MRI.constrainRegClass(SrcReg1, RC);
3303*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(SrcReg2))
3304*9880d681SAndroid Build Coastguard Worker MRI.constrainRegClass(SrcReg2, RC);
3305*9880d681SAndroid Build Coastguard Worker
3306*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB;
3307*9880d681SAndroid Build Coastguard Worker if (kind == FMAInstKind::Default)
3308*9880d681SAndroid Build Coastguard Worker MIB = BuildMI(MF, Root.getDebugLoc(), TII->get(MaddOpc), ResultReg)
3309*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg0, getKillRegState(Src0IsKill))
3310*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg1, getKillRegState(Src1IsKill))
3311*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg2, getKillRegState(Src2IsKill));
3312*9880d681SAndroid Build Coastguard Worker else if (kind == FMAInstKind::Indexed)
3313*9880d681SAndroid Build Coastguard Worker MIB = BuildMI(MF, Root.getDebugLoc(), TII->get(MaddOpc), ResultReg)
3314*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg2, getKillRegState(Src2IsKill))
3315*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg0, getKillRegState(Src0IsKill))
3316*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg1, getKillRegState(Src1IsKill))
3317*9880d681SAndroid Build Coastguard Worker .addImm(MUL->getOperand(3).getImm());
3318*9880d681SAndroid Build Coastguard Worker else if (kind == FMAInstKind::Accumulator)
3319*9880d681SAndroid Build Coastguard Worker MIB = BuildMI(MF, Root.getDebugLoc(), TII->get(MaddOpc), ResultReg)
3320*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg2, getKillRegState(Src2IsKill))
3321*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg0, getKillRegState(Src0IsKill))
3322*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg1, getKillRegState(Src1IsKill));
3323*9880d681SAndroid Build Coastguard Worker else
3324*9880d681SAndroid Build Coastguard Worker assert(false && "Invalid FMA instruction kind \n");
3325*9880d681SAndroid Build Coastguard Worker // Insert the MADD (MADD, FMA, FMS, FMLA, FMSL)
3326*9880d681SAndroid Build Coastguard Worker InsInstrs.push_back(MIB);
3327*9880d681SAndroid Build Coastguard Worker return MUL;
3328*9880d681SAndroid Build Coastguard Worker }
3329*9880d681SAndroid Build Coastguard Worker
3330*9880d681SAndroid Build Coastguard Worker /// genMaddR - Generate madd instruction and combine mul and add using
3331*9880d681SAndroid Build Coastguard Worker /// an extra virtual register
3332*9880d681SAndroid Build Coastguard Worker /// Example - an ADD intermediate needs to be stored in a register:
3333*9880d681SAndroid Build Coastguard Worker /// MUL I=A,B,0
3334*9880d681SAndroid Build Coastguard Worker /// ADD R,I,Imm
3335*9880d681SAndroid Build Coastguard Worker /// ==> ORR V, ZR, Imm
3336*9880d681SAndroid Build Coastguard Worker /// ==> MADD R,A,B,V
3337*9880d681SAndroid Build Coastguard Worker /// \param Root is the ADD instruction
3338*9880d681SAndroid Build Coastguard Worker /// \param [out] InsInstrs is a vector of machine instructions and will
3339*9880d681SAndroid Build Coastguard Worker /// contain the generated madd instruction
3340*9880d681SAndroid Build Coastguard Worker /// \param IdxMulOpd is index of operand in Root that is the result of
3341*9880d681SAndroid Build Coastguard Worker /// the MUL. In the example above IdxMulOpd is 1.
3342*9880d681SAndroid Build Coastguard Worker /// \param MaddOpc the opcode fo the madd instruction
3343*9880d681SAndroid Build Coastguard Worker /// \param VR is a virtual register that holds the value of an ADD operand
3344*9880d681SAndroid Build Coastguard Worker /// (V in the example above).
genMaddR(MachineFunction & MF,MachineRegisterInfo & MRI,const TargetInstrInfo * TII,MachineInstr & Root,SmallVectorImpl<MachineInstr * > & InsInstrs,unsigned IdxMulOpd,unsigned MaddOpc,unsigned VR,const TargetRegisterClass * RC)3345*9880d681SAndroid Build Coastguard Worker static MachineInstr *genMaddR(MachineFunction &MF, MachineRegisterInfo &MRI,
3346*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII, MachineInstr &Root,
3347*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MachineInstr *> &InsInstrs,
3348*9880d681SAndroid Build Coastguard Worker unsigned IdxMulOpd, unsigned MaddOpc,
3349*9880d681SAndroid Build Coastguard Worker unsigned VR, const TargetRegisterClass *RC) {
3350*9880d681SAndroid Build Coastguard Worker assert(IdxMulOpd == 1 || IdxMulOpd == 2);
3351*9880d681SAndroid Build Coastguard Worker
3352*9880d681SAndroid Build Coastguard Worker MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
3353*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = Root.getOperand(0).getReg();
3354*9880d681SAndroid Build Coastguard Worker unsigned SrcReg0 = MUL->getOperand(1).getReg();
3355*9880d681SAndroid Build Coastguard Worker bool Src0IsKill = MUL->getOperand(1).isKill();
3356*9880d681SAndroid Build Coastguard Worker unsigned SrcReg1 = MUL->getOperand(2).getReg();
3357*9880d681SAndroid Build Coastguard Worker bool Src1IsKill = MUL->getOperand(2).isKill();
3358*9880d681SAndroid Build Coastguard Worker
3359*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(ResultReg))
3360*9880d681SAndroid Build Coastguard Worker MRI.constrainRegClass(ResultReg, RC);
3361*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(SrcReg0))
3362*9880d681SAndroid Build Coastguard Worker MRI.constrainRegClass(SrcReg0, RC);
3363*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(SrcReg1))
3364*9880d681SAndroid Build Coastguard Worker MRI.constrainRegClass(SrcReg1, RC);
3365*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(VR))
3366*9880d681SAndroid Build Coastguard Worker MRI.constrainRegClass(VR, RC);
3367*9880d681SAndroid Build Coastguard Worker
3368*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB = BuildMI(MF, Root.getDebugLoc(), TII->get(MaddOpc),
3369*9880d681SAndroid Build Coastguard Worker ResultReg)
3370*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg0, getKillRegState(Src0IsKill))
3371*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg1, getKillRegState(Src1IsKill))
3372*9880d681SAndroid Build Coastguard Worker .addReg(VR);
3373*9880d681SAndroid Build Coastguard Worker // Insert the MADD
3374*9880d681SAndroid Build Coastguard Worker InsInstrs.push_back(MIB);
3375*9880d681SAndroid Build Coastguard Worker return MUL;
3376*9880d681SAndroid Build Coastguard Worker }
3377*9880d681SAndroid Build Coastguard Worker
3378*9880d681SAndroid Build Coastguard Worker /// When getMachineCombinerPatterns() finds potential patterns,
3379*9880d681SAndroid Build Coastguard Worker /// this function generates the instructions that could replace the
3380*9880d681SAndroid Build Coastguard Worker /// original code sequence
genAlternativeCodeSequence(MachineInstr & Root,MachineCombinerPattern Pattern,SmallVectorImpl<MachineInstr * > & InsInstrs,SmallVectorImpl<MachineInstr * > & DelInstrs,DenseMap<unsigned,unsigned> & InstrIdxForVirtReg) const3381*9880d681SAndroid Build Coastguard Worker void AArch64InstrInfo::genAlternativeCodeSequence(
3382*9880d681SAndroid Build Coastguard Worker MachineInstr &Root, MachineCombinerPattern Pattern,
3383*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MachineInstr *> &InsInstrs,
3384*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MachineInstr *> &DelInstrs,
3385*9880d681SAndroid Build Coastguard Worker DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const {
3386*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *Root.getParent();
3387*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3388*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = *MBB.getParent();
3389*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
3390*9880d681SAndroid Build Coastguard Worker
3391*9880d681SAndroid Build Coastguard Worker MachineInstr *MUL;
3392*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC;
3393*9880d681SAndroid Build Coastguard Worker unsigned Opc;
3394*9880d681SAndroid Build Coastguard Worker switch (Pattern) {
3395*9880d681SAndroid Build Coastguard Worker default:
3396*9880d681SAndroid Build Coastguard Worker // Reassociate instructions.
3397*9880d681SAndroid Build Coastguard Worker TargetInstrInfo::genAlternativeCodeSequence(Root, Pattern, InsInstrs,
3398*9880d681SAndroid Build Coastguard Worker DelInstrs, InstrIdxForVirtReg);
3399*9880d681SAndroid Build Coastguard Worker return;
3400*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::MULADDW_OP1:
3401*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::MULADDX_OP1:
3402*9880d681SAndroid Build Coastguard Worker // MUL I=A,B,0
3403*9880d681SAndroid Build Coastguard Worker // ADD R,I,C
3404*9880d681SAndroid Build Coastguard Worker // ==> MADD R,A,B,C
3405*9880d681SAndroid Build Coastguard Worker // --- Create(MADD);
3406*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::MULADDW_OP1) {
3407*9880d681SAndroid Build Coastguard Worker Opc = AArch64::MADDWrrr;
3408*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR32RegClass;
3409*9880d681SAndroid Build Coastguard Worker } else {
3410*9880d681SAndroid Build Coastguard Worker Opc = AArch64::MADDXrrr;
3411*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR64RegClass;
3412*9880d681SAndroid Build Coastguard Worker }
3413*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
3414*9880d681SAndroid Build Coastguard Worker break;
3415*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::MULADDW_OP2:
3416*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::MULADDX_OP2:
3417*9880d681SAndroid Build Coastguard Worker // MUL I=A,B,0
3418*9880d681SAndroid Build Coastguard Worker // ADD R,C,I
3419*9880d681SAndroid Build Coastguard Worker // ==> MADD R,A,B,C
3420*9880d681SAndroid Build Coastguard Worker // --- Create(MADD);
3421*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::MULADDW_OP2) {
3422*9880d681SAndroid Build Coastguard Worker Opc = AArch64::MADDWrrr;
3423*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR32RegClass;
3424*9880d681SAndroid Build Coastguard Worker } else {
3425*9880d681SAndroid Build Coastguard Worker Opc = AArch64::MADDXrrr;
3426*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR64RegClass;
3427*9880d681SAndroid Build Coastguard Worker }
3428*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
3429*9880d681SAndroid Build Coastguard Worker break;
3430*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::MULADDWI_OP1:
3431*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::MULADDXI_OP1: {
3432*9880d681SAndroid Build Coastguard Worker // MUL I=A,B,0
3433*9880d681SAndroid Build Coastguard Worker // ADD R,I,Imm
3434*9880d681SAndroid Build Coastguard Worker // ==> ORR V, ZR, Imm
3435*9880d681SAndroid Build Coastguard Worker // ==> MADD R,A,B,V
3436*9880d681SAndroid Build Coastguard Worker // --- Create(MADD);
3437*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *OrrRC;
3438*9880d681SAndroid Build Coastguard Worker unsigned BitSize, OrrOpc, ZeroReg;
3439*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::MULADDWI_OP1) {
3440*9880d681SAndroid Build Coastguard Worker OrrOpc = AArch64::ORRWri;
3441*9880d681SAndroid Build Coastguard Worker OrrRC = &AArch64::GPR32spRegClass;
3442*9880d681SAndroid Build Coastguard Worker BitSize = 32;
3443*9880d681SAndroid Build Coastguard Worker ZeroReg = AArch64::WZR;
3444*9880d681SAndroid Build Coastguard Worker Opc = AArch64::MADDWrrr;
3445*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR32RegClass;
3446*9880d681SAndroid Build Coastguard Worker } else {
3447*9880d681SAndroid Build Coastguard Worker OrrOpc = AArch64::ORRXri;
3448*9880d681SAndroid Build Coastguard Worker OrrRC = &AArch64::GPR64spRegClass;
3449*9880d681SAndroid Build Coastguard Worker BitSize = 64;
3450*9880d681SAndroid Build Coastguard Worker ZeroReg = AArch64::XZR;
3451*9880d681SAndroid Build Coastguard Worker Opc = AArch64::MADDXrrr;
3452*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR64RegClass;
3453*9880d681SAndroid Build Coastguard Worker }
3454*9880d681SAndroid Build Coastguard Worker unsigned NewVR = MRI.createVirtualRegister(OrrRC);
3455*9880d681SAndroid Build Coastguard Worker uint64_t Imm = Root.getOperand(2).getImm();
3456*9880d681SAndroid Build Coastguard Worker
3457*9880d681SAndroid Build Coastguard Worker if (Root.getOperand(3).isImm()) {
3458*9880d681SAndroid Build Coastguard Worker unsigned Val = Root.getOperand(3).getImm();
3459*9880d681SAndroid Build Coastguard Worker Imm = Imm << Val;
3460*9880d681SAndroid Build Coastguard Worker }
3461*9880d681SAndroid Build Coastguard Worker uint64_t UImm = Imm << (64 - BitSize) >> (64 - BitSize);
3462*9880d681SAndroid Build Coastguard Worker uint64_t Encoding;
3463*9880d681SAndroid Build Coastguard Worker if (AArch64_AM::processLogicalImmediate(UImm, BitSize, Encoding)) {
3464*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB1 =
3465*9880d681SAndroid Build Coastguard Worker BuildMI(MF, Root.getDebugLoc(), TII->get(OrrOpc), NewVR)
3466*9880d681SAndroid Build Coastguard Worker .addReg(ZeroReg)
3467*9880d681SAndroid Build Coastguard Worker .addImm(Encoding);
3468*9880d681SAndroid Build Coastguard Worker InsInstrs.push_back(MIB1);
3469*9880d681SAndroid Build Coastguard Worker InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
3470*9880d681SAndroid Build Coastguard Worker MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
3471*9880d681SAndroid Build Coastguard Worker }
3472*9880d681SAndroid Build Coastguard Worker break;
3473*9880d681SAndroid Build Coastguard Worker }
3474*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::MULSUBW_OP1:
3475*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::MULSUBX_OP1: {
3476*9880d681SAndroid Build Coastguard Worker // MUL I=A,B,0
3477*9880d681SAndroid Build Coastguard Worker // SUB R,I, C
3478*9880d681SAndroid Build Coastguard Worker // ==> SUB V, 0, C
3479*9880d681SAndroid Build Coastguard Worker // ==> MADD R,A,B,V // = -C + A*B
3480*9880d681SAndroid Build Coastguard Worker // --- Create(MADD);
3481*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *SubRC;
3482*9880d681SAndroid Build Coastguard Worker unsigned SubOpc, ZeroReg;
3483*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::MULSUBW_OP1) {
3484*9880d681SAndroid Build Coastguard Worker SubOpc = AArch64::SUBWrr;
3485*9880d681SAndroid Build Coastguard Worker SubRC = &AArch64::GPR32spRegClass;
3486*9880d681SAndroid Build Coastguard Worker ZeroReg = AArch64::WZR;
3487*9880d681SAndroid Build Coastguard Worker Opc = AArch64::MADDWrrr;
3488*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR32RegClass;
3489*9880d681SAndroid Build Coastguard Worker } else {
3490*9880d681SAndroid Build Coastguard Worker SubOpc = AArch64::SUBXrr;
3491*9880d681SAndroid Build Coastguard Worker SubRC = &AArch64::GPR64spRegClass;
3492*9880d681SAndroid Build Coastguard Worker ZeroReg = AArch64::XZR;
3493*9880d681SAndroid Build Coastguard Worker Opc = AArch64::MADDXrrr;
3494*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR64RegClass;
3495*9880d681SAndroid Build Coastguard Worker }
3496*9880d681SAndroid Build Coastguard Worker unsigned NewVR = MRI.createVirtualRegister(SubRC);
3497*9880d681SAndroid Build Coastguard Worker // SUB NewVR, 0, C
3498*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB1 =
3499*9880d681SAndroid Build Coastguard Worker BuildMI(MF, Root.getDebugLoc(), TII->get(SubOpc), NewVR)
3500*9880d681SAndroid Build Coastguard Worker .addReg(ZeroReg)
3501*9880d681SAndroid Build Coastguard Worker .addOperand(Root.getOperand(2));
3502*9880d681SAndroid Build Coastguard Worker InsInstrs.push_back(MIB1);
3503*9880d681SAndroid Build Coastguard Worker InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
3504*9880d681SAndroid Build Coastguard Worker MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
3505*9880d681SAndroid Build Coastguard Worker break;
3506*9880d681SAndroid Build Coastguard Worker }
3507*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::MULSUBW_OP2:
3508*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::MULSUBX_OP2:
3509*9880d681SAndroid Build Coastguard Worker // MUL I=A,B,0
3510*9880d681SAndroid Build Coastguard Worker // SUB R,C,I
3511*9880d681SAndroid Build Coastguard Worker // ==> MSUB R,A,B,C (computes C - A*B)
3512*9880d681SAndroid Build Coastguard Worker // --- Create(MSUB);
3513*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::MULSUBW_OP2) {
3514*9880d681SAndroid Build Coastguard Worker Opc = AArch64::MSUBWrrr;
3515*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR32RegClass;
3516*9880d681SAndroid Build Coastguard Worker } else {
3517*9880d681SAndroid Build Coastguard Worker Opc = AArch64::MSUBXrrr;
3518*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR64RegClass;
3519*9880d681SAndroid Build Coastguard Worker }
3520*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
3521*9880d681SAndroid Build Coastguard Worker break;
3522*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::MULSUBWI_OP1:
3523*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::MULSUBXI_OP1: {
3524*9880d681SAndroid Build Coastguard Worker // MUL I=A,B,0
3525*9880d681SAndroid Build Coastguard Worker // SUB R,I, Imm
3526*9880d681SAndroid Build Coastguard Worker // ==> ORR V, ZR, -Imm
3527*9880d681SAndroid Build Coastguard Worker // ==> MADD R,A,B,V // = -Imm + A*B
3528*9880d681SAndroid Build Coastguard Worker // --- Create(MADD);
3529*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *OrrRC;
3530*9880d681SAndroid Build Coastguard Worker unsigned BitSize, OrrOpc, ZeroReg;
3531*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::MULSUBWI_OP1) {
3532*9880d681SAndroid Build Coastguard Worker OrrOpc = AArch64::ORRWri;
3533*9880d681SAndroid Build Coastguard Worker OrrRC = &AArch64::GPR32spRegClass;
3534*9880d681SAndroid Build Coastguard Worker BitSize = 32;
3535*9880d681SAndroid Build Coastguard Worker ZeroReg = AArch64::WZR;
3536*9880d681SAndroid Build Coastguard Worker Opc = AArch64::MADDWrrr;
3537*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR32RegClass;
3538*9880d681SAndroid Build Coastguard Worker } else {
3539*9880d681SAndroid Build Coastguard Worker OrrOpc = AArch64::ORRXri;
3540*9880d681SAndroid Build Coastguard Worker OrrRC = &AArch64::GPR64spRegClass;
3541*9880d681SAndroid Build Coastguard Worker BitSize = 64;
3542*9880d681SAndroid Build Coastguard Worker ZeroReg = AArch64::XZR;
3543*9880d681SAndroid Build Coastguard Worker Opc = AArch64::MADDXrrr;
3544*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR64RegClass;
3545*9880d681SAndroid Build Coastguard Worker }
3546*9880d681SAndroid Build Coastguard Worker unsigned NewVR = MRI.createVirtualRegister(OrrRC);
3547*9880d681SAndroid Build Coastguard Worker int Imm = Root.getOperand(2).getImm();
3548*9880d681SAndroid Build Coastguard Worker if (Root.getOperand(3).isImm()) {
3549*9880d681SAndroid Build Coastguard Worker unsigned Val = Root.getOperand(3).getImm();
3550*9880d681SAndroid Build Coastguard Worker Imm = Imm << Val;
3551*9880d681SAndroid Build Coastguard Worker }
3552*9880d681SAndroid Build Coastguard Worker uint64_t UImm = -Imm << (64 - BitSize) >> (64 - BitSize);
3553*9880d681SAndroid Build Coastguard Worker uint64_t Encoding;
3554*9880d681SAndroid Build Coastguard Worker if (AArch64_AM::processLogicalImmediate(UImm, BitSize, Encoding)) {
3555*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB1 =
3556*9880d681SAndroid Build Coastguard Worker BuildMI(MF, Root.getDebugLoc(), TII->get(OrrOpc), NewVR)
3557*9880d681SAndroid Build Coastguard Worker .addReg(ZeroReg)
3558*9880d681SAndroid Build Coastguard Worker .addImm(Encoding);
3559*9880d681SAndroid Build Coastguard Worker InsInstrs.push_back(MIB1);
3560*9880d681SAndroid Build Coastguard Worker InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
3561*9880d681SAndroid Build Coastguard Worker MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
3562*9880d681SAndroid Build Coastguard Worker }
3563*9880d681SAndroid Build Coastguard Worker break;
3564*9880d681SAndroid Build Coastguard Worker }
3565*9880d681SAndroid Build Coastguard Worker // Floating Point Support
3566*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULADDS_OP1:
3567*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULADDD_OP1:
3568*9880d681SAndroid Build Coastguard Worker // MUL I=A,B,0
3569*9880d681SAndroid Build Coastguard Worker // ADD R,I,C
3570*9880d681SAndroid Build Coastguard Worker // ==> MADD R,A,B,C
3571*9880d681SAndroid Build Coastguard Worker // --- Create(MADD);
3572*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::FMULADDS_OP1) {
3573*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMADDSrrr;
3574*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR32RegClass;
3575*9880d681SAndroid Build Coastguard Worker } else {
3576*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMADDDrrr;
3577*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR64RegClass;
3578*9880d681SAndroid Build Coastguard Worker }
3579*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
3580*9880d681SAndroid Build Coastguard Worker break;
3581*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULADDS_OP2:
3582*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULADDD_OP2:
3583*9880d681SAndroid Build Coastguard Worker // FMUL I=A,B,0
3584*9880d681SAndroid Build Coastguard Worker // FADD R,C,I
3585*9880d681SAndroid Build Coastguard Worker // ==> FMADD R,A,B,C
3586*9880d681SAndroid Build Coastguard Worker // --- Create(FMADD);
3587*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::FMULADDS_OP2) {
3588*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMADDSrrr;
3589*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR32RegClass;
3590*9880d681SAndroid Build Coastguard Worker } else {
3591*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMADDDrrr;
3592*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR64RegClass;
3593*9880d681SAndroid Build Coastguard Worker }
3594*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
3595*9880d681SAndroid Build Coastguard Worker break;
3596*9880d681SAndroid Build Coastguard Worker
3597*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv1i32_indexed_OP1:
3598*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv1i32_indexed;
3599*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR32RegClass;
3600*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3601*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3602*9880d681SAndroid Build Coastguard Worker break;
3603*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv1i32_indexed_OP2:
3604*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv1i32_indexed;
3605*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR32RegClass;
3606*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3607*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3608*9880d681SAndroid Build Coastguard Worker break;
3609*9880d681SAndroid Build Coastguard Worker
3610*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv1i64_indexed_OP1:
3611*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv1i64_indexed;
3612*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR64RegClass;
3613*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3614*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3615*9880d681SAndroid Build Coastguard Worker break;
3616*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv1i64_indexed_OP2:
3617*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv1i64_indexed;
3618*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR64RegClass;
3619*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3620*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3621*9880d681SAndroid Build Coastguard Worker break;
3622*9880d681SAndroid Build Coastguard Worker
3623*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2i32_indexed_OP1:
3624*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2f32_OP1:
3625*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR64RegClass;
3626*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::FMLAv2i32_indexed_OP1) {
3627*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv2i32_indexed;
3628*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3629*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3630*9880d681SAndroid Build Coastguard Worker } else {
3631*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv2f32;
3632*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3633*9880d681SAndroid Build Coastguard Worker FMAInstKind::Accumulator);
3634*9880d681SAndroid Build Coastguard Worker }
3635*9880d681SAndroid Build Coastguard Worker break;
3636*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2i32_indexed_OP2:
3637*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2f32_OP2:
3638*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR64RegClass;
3639*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::FMLAv2i32_indexed_OP2) {
3640*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv2i32_indexed;
3641*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3642*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3643*9880d681SAndroid Build Coastguard Worker } else {
3644*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv2f32;
3645*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3646*9880d681SAndroid Build Coastguard Worker FMAInstKind::Accumulator);
3647*9880d681SAndroid Build Coastguard Worker }
3648*9880d681SAndroid Build Coastguard Worker break;
3649*9880d681SAndroid Build Coastguard Worker
3650*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2i64_indexed_OP1:
3651*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2f64_OP1:
3652*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR128RegClass;
3653*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::FMLAv2i64_indexed_OP1) {
3654*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv2i64_indexed;
3655*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3656*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3657*9880d681SAndroid Build Coastguard Worker } else {
3658*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv2f64;
3659*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3660*9880d681SAndroid Build Coastguard Worker FMAInstKind::Accumulator);
3661*9880d681SAndroid Build Coastguard Worker }
3662*9880d681SAndroid Build Coastguard Worker break;
3663*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2i64_indexed_OP2:
3664*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv2f64_OP2:
3665*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR128RegClass;
3666*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::FMLAv2i64_indexed_OP2) {
3667*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv2i64_indexed;
3668*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3669*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3670*9880d681SAndroid Build Coastguard Worker } else {
3671*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv2f64;
3672*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3673*9880d681SAndroid Build Coastguard Worker FMAInstKind::Accumulator);
3674*9880d681SAndroid Build Coastguard Worker }
3675*9880d681SAndroid Build Coastguard Worker break;
3676*9880d681SAndroid Build Coastguard Worker
3677*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv4i32_indexed_OP1:
3678*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv4f32_OP1:
3679*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR128RegClass;
3680*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::FMLAv4i32_indexed_OP1) {
3681*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv4i32_indexed;
3682*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3683*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3684*9880d681SAndroid Build Coastguard Worker } else {
3685*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv4f32;
3686*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3687*9880d681SAndroid Build Coastguard Worker FMAInstKind::Accumulator);
3688*9880d681SAndroid Build Coastguard Worker }
3689*9880d681SAndroid Build Coastguard Worker break;
3690*9880d681SAndroid Build Coastguard Worker
3691*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv4i32_indexed_OP2:
3692*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLAv4f32_OP2:
3693*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR128RegClass;
3694*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::FMLAv4i32_indexed_OP2) {
3695*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv4i32_indexed;
3696*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3697*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3698*9880d681SAndroid Build Coastguard Worker } else {
3699*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLAv4f32;
3700*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3701*9880d681SAndroid Build Coastguard Worker FMAInstKind::Accumulator);
3702*9880d681SAndroid Build Coastguard Worker }
3703*9880d681SAndroid Build Coastguard Worker break;
3704*9880d681SAndroid Build Coastguard Worker
3705*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULSUBS_OP1:
3706*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULSUBD_OP1: {
3707*9880d681SAndroid Build Coastguard Worker // FMUL I=A,B,0
3708*9880d681SAndroid Build Coastguard Worker // FSUB R,I,C
3709*9880d681SAndroid Build Coastguard Worker // ==> FNMSUB R,A,B,C // = -C + A*B
3710*9880d681SAndroid Build Coastguard Worker // --- Create(FNMSUB);
3711*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::FMULSUBS_OP1) {
3712*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FNMSUBSrrr;
3713*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR32RegClass;
3714*9880d681SAndroid Build Coastguard Worker } else {
3715*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FNMSUBDrrr;
3716*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR64RegClass;
3717*9880d681SAndroid Build Coastguard Worker }
3718*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
3719*9880d681SAndroid Build Coastguard Worker break;
3720*9880d681SAndroid Build Coastguard Worker }
3721*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULSUBS_OP2:
3722*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMULSUBD_OP2: {
3723*9880d681SAndroid Build Coastguard Worker // FMUL I=A,B,0
3724*9880d681SAndroid Build Coastguard Worker // FSUB R,C,I
3725*9880d681SAndroid Build Coastguard Worker // ==> FMSUB R,A,B,C (computes C - A*B)
3726*9880d681SAndroid Build Coastguard Worker // --- Create(FMSUB);
3727*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::FMULSUBS_OP2) {
3728*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMSUBSrrr;
3729*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR32RegClass;
3730*9880d681SAndroid Build Coastguard Worker } else {
3731*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMSUBDrrr;
3732*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR64RegClass;
3733*9880d681SAndroid Build Coastguard Worker }
3734*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
3735*9880d681SAndroid Build Coastguard Worker break;
3736*9880d681SAndroid Build Coastguard Worker
3737*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv1i32_indexed_OP2:
3738*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLSv1i32_indexed;
3739*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR32RegClass;
3740*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3741*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3742*9880d681SAndroid Build Coastguard Worker break;
3743*9880d681SAndroid Build Coastguard Worker
3744*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv1i64_indexed_OP2:
3745*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLSv1i64_indexed;
3746*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR64RegClass;
3747*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3748*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3749*9880d681SAndroid Build Coastguard Worker break;
3750*9880d681SAndroid Build Coastguard Worker
3751*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv2f32_OP2:
3752*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv2i32_indexed_OP2:
3753*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR64RegClass;
3754*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::FMLSv2i32_indexed_OP2) {
3755*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLSv2i32_indexed;
3756*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3757*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3758*9880d681SAndroid Build Coastguard Worker } else {
3759*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLSv2f32;
3760*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3761*9880d681SAndroid Build Coastguard Worker FMAInstKind::Accumulator);
3762*9880d681SAndroid Build Coastguard Worker }
3763*9880d681SAndroid Build Coastguard Worker break;
3764*9880d681SAndroid Build Coastguard Worker
3765*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv2f64_OP2:
3766*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv2i64_indexed_OP2:
3767*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR128RegClass;
3768*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::FMLSv2i64_indexed_OP2) {
3769*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLSv2i64_indexed;
3770*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3771*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3772*9880d681SAndroid Build Coastguard Worker } else {
3773*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLSv2f64;
3774*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3775*9880d681SAndroid Build Coastguard Worker FMAInstKind::Accumulator);
3776*9880d681SAndroid Build Coastguard Worker }
3777*9880d681SAndroid Build Coastguard Worker break;
3778*9880d681SAndroid Build Coastguard Worker
3779*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv4f32_OP2:
3780*9880d681SAndroid Build Coastguard Worker case MachineCombinerPattern::FMLSv4i32_indexed_OP2:
3781*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR128RegClass;
3782*9880d681SAndroid Build Coastguard Worker if (Pattern == MachineCombinerPattern::FMLSv4i32_indexed_OP2) {
3783*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLSv4i32_indexed;
3784*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3785*9880d681SAndroid Build Coastguard Worker FMAInstKind::Indexed);
3786*9880d681SAndroid Build Coastguard Worker } else {
3787*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMLSv4f32;
3788*9880d681SAndroid Build Coastguard Worker MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3789*9880d681SAndroid Build Coastguard Worker FMAInstKind::Accumulator);
3790*9880d681SAndroid Build Coastguard Worker }
3791*9880d681SAndroid Build Coastguard Worker break;
3792*9880d681SAndroid Build Coastguard Worker }
3793*9880d681SAndroid Build Coastguard Worker } // end switch (Pattern)
3794*9880d681SAndroid Build Coastguard Worker // Record MUL and ADD/SUB for deletion
3795*9880d681SAndroid Build Coastguard Worker DelInstrs.push_back(MUL);
3796*9880d681SAndroid Build Coastguard Worker DelInstrs.push_back(&Root);
3797*9880d681SAndroid Build Coastguard Worker
3798*9880d681SAndroid Build Coastguard Worker return;
3799*9880d681SAndroid Build Coastguard Worker }
3800*9880d681SAndroid Build Coastguard Worker
3801*9880d681SAndroid Build Coastguard Worker /// \brief Replace csincr-branch sequence by simple conditional branch
3802*9880d681SAndroid Build Coastguard Worker ///
3803*9880d681SAndroid Build Coastguard Worker /// Examples:
3804*9880d681SAndroid Build Coastguard Worker /// 1.
3805*9880d681SAndroid Build Coastguard Worker /// csinc w9, wzr, wzr, <condition code>
3806*9880d681SAndroid Build Coastguard Worker /// tbnz w9, #0, 0x44
3807*9880d681SAndroid Build Coastguard Worker /// to
3808*9880d681SAndroid Build Coastguard Worker /// b.<inverted condition code>
3809*9880d681SAndroid Build Coastguard Worker ///
3810*9880d681SAndroid Build Coastguard Worker /// 2.
3811*9880d681SAndroid Build Coastguard Worker /// csinc w9, wzr, wzr, <condition code>
3812*9880d681SAndroid Build Coastguard Worker /// tbz w9, #0, 0x44
3813*9880d681SAndroid Build Coastguard Worker /// to
3814*9880d681SAndroid Build Coastguard Worker /// b.<condition code>
3815*9880d681SAndroid Build Coastguard Worker ///
3816*9880d681SAndroid Build Coastguard Worker /// Replace compare and branch sequence by TBZ/TBNZ instruction when the
3817*9880d681SAndroid Build Coastguard Worker /// compare's constant operand is power of 2.
3818*9880d681SAndroid Build Coastguard Worker ///
3819*9880d681SAndroid Build Coastguard Worker /// Examples:
3820*9880d681SAndroid Build Coastguard Worker /// and w8, w8, #0x400
3821*9880d681SAndroid Build Coastguard Worker /// cbnz w8, L1
3822*9880d681SAndroid Build Coastguard Worker /// to
3823*9880d681SAndroid Build Coastguard Worker /// tbnz w8, #10, L1
3824*9880d681SAndroid Build Coastguard Worker ///
3825*9880d681SAndroid Build Coastguard Worker /// \param MI Conditional Branch
3826*9880d681SAndroid Build Coastguard Worker /// \return True when the simple conditional branch is generated
3827*9880d681SAndroid Build Coastguard Worker ///
optimizeCondBranch(MachineInstr & MI) const3828*9880d681SAndroid Build Coastguard Worker bool AArch64InstrInfo::optimizeCondBranch(MachineInstr &MI) const {
3829*9880d681SAndroid Build Coastguard Worker bool IsNegativeBranch = false;
3830*9880d681SAndroid Build Coastguard Worker bool IsTestAndBranch = false;
3831*9880d681SAndroid Build Coastguard Worker unsigned TargetBBInMI = 0;
3832*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
3833*9880d681SAndroid Build Coastguard Worker default:
3834*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown branch instruction?");
3835*9880d681SAndroid Build Coastguard Worker case AArch64::Bcc:
3836*9880d681SAndroid Build Coastguard Worker return false;
3837*9880d681SAndroid Build Coastguard Worker case AArch64::CBZW:
3838*9880d681SAndroid Build Coastguard Worker case AArch64::CBZX:
3839*9880d681SAndroid Build Coastguard Worker TargetBBInMI = 1;
3840*9880d681SAndroid Build Coastguard Worker break;
3841*9880d681SAndroid Build Coastguard Worker case AArch64::CBNZW:
3842*9880d681SAndroid Build Coastguard Worker case AArch64::CBNZX:
3843*9880d681SAndroid Build Coastguard Worker TargetBBInMI = 1;
3844*9880d681SAndroid Build Coastguard Worker IsNegativeBranch = true;
3845*9880d681SAndroid Build Coastguard Worker break;
3846*9880d681SAndroid Build Coastguard Worker case AArch64::TBZW:
3847*9880d681SAndroid Build Coastguard Worker case AArch64::TBZX:
3848*9880d681SAndroid Build Coastguard Worker TargetBBInMI = 2;
3849*9880d681SAndroid Build Coastguard Worker IsTestAndBranch = true;
3850*9880d681SAndroid Build Coastguard Worker break;
3851*9880d681SAndroid Build Coastguard Worker case AArch64::TBNZW:
3852*9880d681SAndroid Build Coastguard Worker case AArch64::TBNZX:
3853*9880d681SAndroid Build Coastguard Worker TargetBBInMI = 2;
3854*9880d681SAndroid Build Coastguard Worker IsNegativeBranch = true;
3855*9880d681SAndroid Build Coastguard Worker IsTestAndBranch = true;
3856*9880d681SAndroid Build Coastguard Worker break;
3857*9880d681SAndroid Build Coastguard Worker }
3858*9880d681SAndroid Build Coastguard Worker // So we increment a zero register and test for bits other
3859*9880d681SAndroid Build Coastguard Worker // than bit 0? Conservatively bail out in case the verifier
3860*9880d681SAndroid Build Coastguard Worker // missed this case.
3861*9880d681SAndroid Build Coastguard Worker if (IsTestAndBranch && MI.getOperand(1).getImm())
3862*9880d681SAndroid Build Coastguard Worker return false;
3863*9880d681SAndroid Build Coastguard Worker
3864*9880d681SAndroid Build Coastguard Worker // Find Definition.
3865*9880d681SAndroid Build Coastguard Worker assert(MI.getParent() && "Incomplete machine instruciton\n");
3866*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MBB = MI.getParent();
3867*9880d681SAndroid Build Coastguard Worker MachineFunction *MF = MBB->getParent();
3868*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo *MRI = &MF->getRegInfo();
3869*9880d681SAndroid Build Coastguard Worker unsigned VReg = MI.getOperand(0).getReg();
3870*9880d681SAndroid Build Coastguard Worker if (!TargetRegisterInfo::isVirtualRegister(VReg))
3871*9880d681SAndroid Build Coastguard Worker return false;
3872*9880d681SAndroid Build Coastguard Worker
3873*9880d681SAndroid Build Coastguard Worker MachineInstr *DefMI = MRI->getVRegDef(VReg);
3874*9880d681SAndroid Build Coastguard Worker
3875*9880d681SAndroid Build Coastguard Worker // Look through COPY instructions to find definition.
3876*9880d681SAndroid Build Coastguard Worker while (DefMI->isCopy()) {
3877*9880d681SAndroid Build Coastguard Worker unsigned CopyVReg = DefMI->getOperand(1).getReg();
3878*9880d681SAndroid Build Coastguard Worker if (!MRI->hasOneNonDBGUse(CopyVReg))
3879*9880d681SAndroid Build Coastguard Worker return false;
3880*9880d681SAndroid Build Coastguard Worker if (!MRI->hasOneDef(CopyVReg))
3881*9880d681SAndroid Build Coastguard Worker return false;
3882*9880d681SAndroid Build Coastguard Worker DefMI = MRI->getVRegDef(CopyVReg);
3883*9880d681SAndroid Build Coastguard Worker }
3884*9880d681SAndroid Build Coastguard Worker
3885*9880d681SAndroid Build Coastguard Worker switch (DefMI->getOpcode()) {
3886*9880d681SAndroid Build Coastguard Worker default:
3887*9880d681SAndroid Build Coastguard Worker return false;
3888*9880d681SAndroid Build Coastguard Worker // Fold AND into a TBZ/TBNZ if constant operand is power of 2.
3889*9880d681SAndroid Build Coastguard Worker case AArch64::ANDWri:
3890*9880d681SAndroid Build Coastguard Worker case AArch64::ANDXri: {
3891*9880d681SAndroid Build Coastguard Worker if (IsTestAndBranch)
3892*9880d681SAndroid Build Coastguard Worker return false;
3893*9880d681SAndroid Build Coastguard Worker if (DefMI->getParent() != MBB)
3894*9880d681SAndroid Build Coastguard Worker return false;
3895*9880d681SAndroid Build Coastguard Worker if (!MRI->hasOneNonDBGUse(VReg))
3896*9880d681SAndroid Build Coastguard Worker return false;
3897*9880d681SAndroid Build Coastguard Worker
3898*9880d681SAndroid Build Coastguard Worker bool Is32Bit = (DefMI->getOpcode() == AArch64::ANDWri);
3899*9880d681SAndroid Build Coastguard Worker uint64_t Mask = AArch64_AM::decodeLogicalImmediate(
3900*9880d681SAndroid Build Coastguard Worker DefMI->getOperand(2).getImm(), Is32Bit ? 32 : 64);
3901*9880d681SAndroid Build Coastguard Worker if (!isPowerOf2_64(Mask))
3902*9880d681SAndroid Build Coastguard Worker return false;
3903*9880d681SAndroid Build Coastguard Worker
3904*9880d681SAndroid Build Coastguard Worker MachineOperand &MO = DefMI->getOperand(1);
3905*9880d681SAndroid Build Coastguard Worker unsigned NewReg = MO.getReg();
3906*9880d681SAndroid Build Coastguard Worker if (!TargetRegisterInfo::isVirtualRegister(NewReg))
3907*9880d681SAndroid Build Coastguard Worker return false;
3908*9880d681SAndroid Build Coastguard Worker
3909*9880d681SAndroid Build Coastguard Worker assert(!MRI->def_empty(NewReg) && "Register must be defined.");
3910*9880d681SAndroid Build Coastguard Worker
3911*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &RefToMBB = *MBB;
3912*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *TBB = MI.getOperand(1).getMBB();
3913*9880d681SAndroid Build Coastguard Worker DebugLoc DL = MI.getDebugLoc();
3914*9880d681SAndroid Build Coastguard Worker unsigned Imm = Log2_64(Mask);
3915*9880d681SAndroid Build Coastguard Worker unsigned Opc = (Imm < 32)
3916*9880d681SAndroid Build Coastguard Worker ? (IsNegativeBranch ? AArch64::TBNZW : AArch64::TBZW)
3917*9880d681SAndroid Build Coastguard Worker : (IsNegativeBranch ? AArch64::TBNZX : AArch64::TBZX);
3918*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI = BuildMI(RefToMBB, MI, DL, get(Opc))
3919*9880d681SAndroid Build Coastguard Worker .addReg(NewReg)
3920*9880d681SAndroid Build Coastguard Worker .addImm(Imm)
3921*9880d681SAndroid Build Coastguard Worker .addMBB(TBB);
3922*9880d681SAndroid Build Coastguard Worker // Register lives on to the CBZ now.
3923*9880d681SAndroid Build Coastguard Worker MO.setIsKill(false);
3924*9880d681SAndroid Build Coastguard Worker
3925*9880d681SAndroid Build Coastguard Worker // For immediate smaller than 32, we need to use the 32-bit
3926*9880d681SAndroid Build Coastguard Worker // variant (W) in all cases. Indeed the 64-bit variant does not
3927*9880d681SAndroid Build Coastguard Worker // allow to encode them.
3928*9880d681SAndroid Build Coastguard Worker // Therefore, if the input register is 64-bit, we need to take the
3929*9880d681SAndroid Build Coastguard Worker // 32-bit sub-part.
3930*9880d681SAndroid Build Coastguard Worker if (!Is32Bit && Imm < 32)
3931*9880d681SAndroid Build Coastguard Worker NewMI->getOperand(0).setSubReg(AArch64::sub_32);
3932*9880d681SAndroid Build Coastguard Worker MI.eraseFromParent();
3933*9880d681SAndroid Build Coastguard Worker return true;
3934*9880d681SAndroid Build Coastguard Worker }
3935*9880d681SAndroid Build Coastguard Worker // Look for CSINC
3936*9880d681SAndroid Build Coastguard Worker case AArch64::CSINCWr:
3937*9880d681SAndroid Build Coastguard Worker case AArch64::CSINCXr: {
3938*9880d681SAndroid Build Coastguard Worker if (!(DefMI->getOperand(1).getReg() == AArch64::WZR &&
3939*9880d681SAndroid Build Coastguard Worker DefMI->getOperand(2).getReg() == AArch64::WZR) &&
3940*9880d681SAndroid Build Coastguard Worker !(DefMI->getOperand(1).getReg() == AArch64::XZR &&
3941*9880d681SAndroid Build Coastguard Worker DefMI->getOperand(2).getReg() == AArch64::XZR))
3942*9880d681SAndroid Build Coastguard Worker return false;
3943*9880d681SAndroid Build Coastguard Worker
3944*9880d681SAndroid Build Coastguard Worker if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, true) != -1)
3945*9880d681SAndroid Build Coastguard Worker return false;
3946*9880d681SAndroid Build Coastguard Worker
3947*9880d681SAndroid Build Coastguard Worker AArch64CC::CondCode CC = (AArch64CC::CondCode)DefMI->getOperand(3).getImm();
3948*9880d681SAndroid Build Coastguard Worker // Convert only when the condition code is not modified between
3949*9880d681SAndroid Build Coastguard Worker // the CSINC and the branch. The CC may be used by other
3950*9880d681SAndroid Build Coastguard Worker // instructions in between.
3951*9880d681SAndroid Build Coastguard Worker if (areCFlagsAccessedBetweenInstrs(DefMI, MI, &getRegisterInfo(), AK_Write))
3952*9880d681SAndroid Build Coastguard Worker return false;
3953*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &RefToMBB = *MBB;
3954*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *TBB = MI.getOperand(TargetBBInMI).getMBB();
3955*9880d681SAndroid Build Coastguard Worker DebugLoc DL = MI.getDebugLoc();
3956*9880d681SAndroid Build Coastguard Worker if (IsNegativeBranch)
3957*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::getInvertedCondCode(CC);
3958*9880d681SAndroid Build Coastguard Worker BuildMI(RefToMBB, MI, DL, get(AArch64::Bcc)).addImm(CC).addMBB(TBB);
3959*9880d681SAndroid Build Coastguard Worker MI.eraseFromParent();
3960*9880d681SAndroid Build Coastguard Worker return true;
3961*9880d681SAndroid Build Coastguard Worker }
3962*9880d681SAndroid Build Coastguard Worker }
3963*9880d681SAndroid Build Coastguard Worker }
3964*9880d681SAndroid Build Coastguard Worker
3965*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, unsigned>
decomposeMachineOperandsTargetFlags(unsigned TF) const3966*9880d681SAndroid Build Coastguard Worker AArch64InstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
3967*9880d681SAndroid Build Coastguard Worker const unsigned Mask = AArch64II::MO_FRAGMENT;
3968*9880d681SAndroid Build Coastguard Worker return std::make_pair(TF & Mask, TF & ~Mask);
3969*9880d681SAndroid Build Coastguard Worker }
3970*9880d681SAndroid Build Coastguard Worker
3971*9880d681SAndroid Build Coastguard Worker ArrayRef<std::pair<unsigned, const char *>>
getSerializableDirectMachineOperandTargetFlags() const3972*9880d681SAndroid Build Coastguard Worker AArch64InstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
3973*9880d681SAndroid Build Coastguard Worker using namespace AArch64II;
3974*9880d681SAndroid Build Coastguard Worker static const std::pair<unsigned, const char *> TargetFlags[] = {
3975*9880d681SAndroid Build Coastguard Worker {MO_PAGE, "aarch64-page"},
3976*9880d681SAndroid Build Coastguard Worker {MO_PAGEOFF, "aarch64-pageoff"},
3977*9880d681SAndroid Build Coastguard Worker {MO_G3, "aarch64-g3"},
3978*9880d681SAndroid Build Coastguard Worker {MO_G2, "aarch64-g2"},
3979*9880d681SAndroid Build Coastguard Worker {MO_G1, "aarch64-g1"},
3980*9880d681SAndroid Build Coastguard Worker {MO_G0, "aarch64-g0"},
3981*9880d681SAndroid Build Coastguard Worker {MO_HI12, "aarch64-hi12"}};
3982*9880d681SAndroid Build Coastguard Worker return makeArrayRef(TargetFlags);
3983*9880d681SAndroid Build Coastguard Worker }
3984*9880d681SAndroid Build Coastguard Worker
3985*9880d681SAndroid Build Coastguard Worker ArrayRef<std::pair<unsigned, const char *>>
getSerializableBitmaskMachineOperandTargetFlags() const3986*9880d681SAndroid Build Coastguard Worker AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
3987*9880d681SAndroid Build Coastguard Worker using namespace AArch64II;
3988*9880d681SAndroid Build Coastguard Worker static const std::pair<unsigned, const char *> TargetFlags[] = {
3989*9880d681SAndroid Build Coastguard Worker {MO_GOT, "aarch64-got"},
3990*9880d681SAndroid Build Coastguard Worker {MO_NC, "aarch64-nc"},
3991*9880d681SAndroid Build Coastguard Worker {MO_TLS, "aarch64-tls"}};
3992*9880d681SAndroid Build Coastguard Worker return makeArrayRef(TargetFlags);
3993*9880d681SAndroid Build Coastguard Worker }
3994