1*9880d681SAndroid Build Coastguard Worker //===-- AArch6464FastISel.cpp - AArch64 FastISel implementation -----------===//
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 defines the AArch64-specific support for the FastISel class. Some
11*9880d681SAndroid Build Coastguard Worker // of the target-specific code is generated by tablegen in the file
12*9880d681SAndroid Build Coastguard Worker // AArch64GenFastISel.inc, which is #included here.
13*9880d681SAndroid Build Coastguard Worker //
14*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*9880d681SAndroid Build Coastguard Worker
16*9880d681SAndroid Build Coastguard Worker #include "AArch64.h"
17*9880d681SAndroid Build Coastguard Worker #include "AArch64CallingConvention.h"
18*9880d681SAndroid Build Coastguard Worker #include "AArch64Subtarget.h"
19*9880d681SAndroid Build Coastguard Worker #include "AArch64TargetMachine.h"
20*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/AArch64AddressingModes.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/BranchProbabilityInfo.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/CallingConvLower.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/FastISel.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/FunctionLoweringInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineConstantPool.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/CallingConv.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DataLayout.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DerivedTypes.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/GetElementPtrTypeIterator.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/GlobalAlias.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/GlobalVariable.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IntrinsicInst.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Operator.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbol.h"
40*9880d681SAndroid Build Coastguard Worker using namespace llvm;
41*9880d681SAndroid Build Coastguard Worker
42*9880d681SAndroid Build Coastguard Worker namespace {
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Worker class AArch64FastISel final : public FastISel {
45*9880d681SAndroid Build Coastguard Worker class Address {
46*9880d681SAndroid Build Coastguard Worker public:
47*9880d681SAndroid Build Coastguard Worker typedef enum {
48*9880d681SAndroid Build Coastguard Worker RegBase,
49*9880d681SAndroid Build Coastguard Worker FrameIndexBase
50*9880d681SAndroid Build Coastguard Worker } BaseKind;
51*9880d681SAndroid Build Coastguard Worker
52*9880d681SAndroid Build Coastguard Worker private:
53*9880d681SAndroid Build Coastguard Worker BaseKind Kind;
54*9880d681SAndroid Build Coastguard Worker AArch64_AM::ShiftExtendType ExtType;
55*9880d681SAndroid Build Coastguard Worker union {
56*9880d681SAndroid Build Coastguard Worker unsigned Reg;
57*9880d681SAndroid Build Coastguard Worker int FI;
58*9880d681SAndroid Build Coastguard Worker } Base;
59*9880d681SAndroid Build Coastguard Worker unsigned OffsetReg;
60*9880d681SAndroid Build Coastguard Worker unsigned Shift;
61*9880d681SAndroid Build Coastguard Worker int64_t Offset;
62*9880d681SAndroid Build Coastguard Worker const GlobalValue *GV;
63*9880d681SAndroid Build Coastguard Worker
64*9880d681SAndroid Build Coastguard Worker public:
Address()65*9880d681SAndroid Build Coastguard Worker Address() : Kind(RegBase), ExtType(AArch64_AM::InvalidShiftExtend),
66*9880d681SAndroid Build Coastguard Worker OffsetReg(0), Shift(0), Offset(0), GV(nullptr) { Base.Reg = 0; }
setKind(BaseKind K)67*9880d681SAndroid Build Coastguard Worker void setKind(BaseKind K) { Kind = K; }
getKind() const68*9880d681SAndroid Build Coastguard Worker BaseKind getKind() const { return Kind; }
setExtendType(AArch64_AM::ShiftExtendType E)69*9880d681SAndroid Build Coastguard Worker void setExtendType(AArch64_AM::ShiftExtendType E) { ExtType = E; }
getExtendType() const70*9880d681SAndroid Build Coastguard Worker AArch64_AM::ShiftExtendType getExtendType() const { return ExtType; }
isRegBase() const71*9880d681SAndroid Build Coastguard Worker bool isRegBase() const { return Kind == RegBase; }
isFIBase() const72*9880d681SAndroid Build Coastguard Worker bool isFIBase() const { return Kind == FrameIndexBase; }
setReg(unsigned Reg)73*9880d681SAndroid Build Coastguard Worker void setReg(unsigned Reg) {
74*9880d681SAndroid Build Coastguard Worker assert(isRegBase() && "Invalid base register access!");
75*9880d681SAndroid Build Coastguard Worker Base.Reg = Reg;
76*9880d681SAndroid Build Coastguard Worker }
getReg() const77*9880d681SAndroid Build Coastguard Worker unsigned getReg() const {
78*9880d681SAndroid Build Coastguard Worker assert(isRegBase() && "Invalid base register access!");
79*9880d681SAndroid Build Coastguard Worker return Base.Reg;
80*9880d681SAndroid Build Coastguard Worker }
setOffsetReg(unsigned Reg)81*9880d681SAndroid Build Coastguard Worker void setOffsetReg(unsigned Reg) {
82*9880d681SAndroid Build Coastguard Worker OffsetReg = Reg;
83*9880d681SAndroid Build Coastguard Worker }
getOffsetReg() const84*9880d681SAndroid Build Coastguard Worker unsigned getOffsetReg() const {
85*9880d681SAndroid Build Coastguard Worker return OffsetReg;
86*9880d681SAndroid Build Coastguard Worker }
setFI(unsigned FI)87*9880d681SAndroid Build Coastguard Worker void setFI(unsigned FI) {
88*9880d681SAndroid Build Coastguard Worker assert(isFIBase() && "Invalid base frame index access!");
89*9880d681SAndroid Build Coastguard Worker Base.FI = FI;
90*9880d681SAndroid Build Coastguard Worker }
getFI() const91*9880d681SAndroid Build Coastguard Worker unsigned getFI() const {
92*9880d681SAndroid Build Coastguard Worker assert(isFIBase() && "Invalid base frame index access!");
93*9880d681SAndroid Build Coastguard Worker return Base.FI;
94*9880d681SAndroid Build Coastguard Worker }
setOffset(int64_t O)95*9880d681SAndroid Build Coastguard Worker void setOffset(int64_t O) { Offset = O; }
getOffset()96*9880d681SAndroid Build Coastguard Worker int64_t getOffset() { return Offset; }
setShift(unsigned S)97*9880d681SAndroid Build Coastguard Worker void setShift(unsigned S) { Shift = S; }
getShift()98*9880d681SAndroid Build Coastguard Worker unsigned getShift() { return Shift; }
99*9880d681SAndroid Build Coastguard Worker
setGlobalValue(const GlobalValue * G)100*9880d681SAndroid Build Coastguard Worker void setGlobalValue(const GlobalValue *G) { GV = G; }
getGlobalValue()101*9880d681SAndroid Build Coastguard Worker const GlobalValue *getGlobalValue() { return GV; }
102*9880d681SAndroid Build Coastguard Worker };
103*9880d681SAndroid Build Coastguard Worker
104*9880d681SAndroid Build Coastguard Worker /// Subtarget - Keep a pointer to the AArch64Subtarget around so that we can
105*9880d681SAndroid Build Coastguard Worker /// make the right decision when generating code for different targets.
106*9880d681SAndroid Build Coastguard Worker const AArch64Subtarget *Subtarget;
107*9880d681SAndroid Build Coastguard Worker LLVMContext *Context;
108*9880d681SAndroid Build Coastguard Worker
109*9880d681SAndroid Build Coastguard Worker bool fastLowerArguments() override;
110*9880d681SAndroid Build Coastguard Worker bool fastLowerCall(CallLoweringInfo &CLI) override;
111*9880d681SAndroid Build Coastguard Worker bool fastLowerIntrinsicCall(const IntrinsicInst *II) override;
112*9880d681SAndroid Build Coastguard Worker
113*9880d681SAndroid Build Coastguard Worker private:
114*9880d681SAndroid Build Coastguard Worker // Selection routines.
115*9880d681SAndroid Build Coastguard Worker bool selectAddSub(const Instruction *I);
116*9880d681SAndroid Build Coastguard Worker bool selectLogicalOp(const Instruction *I);
117*9880d681SAndroid Build Coastguard Worker bool selectLoad(const Instruction *I);
118*9880d681SAndroid Build Coastguard Worker bool selectStore(const Instruction *I);
119*9880d681SAndroid Build Coastguard Worker bool selectBranch(const Instruction *I);
120*9880d681SAndroid Build Coastguard Worker bool selectIndirectBr(const Instruction *I);
121*9880d681SAndroid Build Coastguard Worker bool selectCmp(const Instruction *I);
122*9880d681SAndroid Build Coastguard Worker bool selectSelect(const Instruction *I);
123*9880d681SAndroid Build Coastguard Worker bool selectFPExt(const Instruction *I);
124*9880d681SAndroid Build Coastguard Worker bool selectFPTrunc(const Instruction *I);
125*9880d681SAndroid Build Coastguard Worker bool selectFPToInt(const Instruction *I, bool Signed);
126*9880d681SAndroid Build Coastguard Worker bool selectIntToFP(const Instruction *I, bool Signed);
127*9880d681SAndroid Build Coastguard Worker bool selectRem(const Instruction *I, unsigned ISDOpcode);
128*9880d681SAndroid Build Coastguard Worker bool selectRet(const Instruction *I);
129*9880d681SAndroid Build Coastguard Worker bool selectTrunc(const Instruction *I);
130*9880d681SAndroid Build Coastguard Worker bool selectIntExt(const Instruction *I);
131*9880d681SAndroid Build Coastguard Worker bool selectMul(const Instruction *I);
132*9880d681SAndroid Build Coastguard Worker bool selectShift(const Instruction *I);
133*9880d681SAndroid Build Coastguard Worker bool selectBitCast(const Instruction *I);
134*9880d681SAndroid Build Coastguard Worker bool selectFRem(const Instruction *I);
135*9880d681SAndroid Build Coastguard Worker bool selectSDiv(const Instruction *I);
136*9880d681SAndroid Build Coastguard Worker bool selectGetElementPtr(const Instruction *I);
137*9880d681SAndroid Build Coastguard Worker
138*9880d681SAndroid Build Coastguard Worker // Utility helper routines.
139*9880d681SAndroid Build Coastguard Worker bool isTypeLegal(Type *Ty, MVT &VT);
140*9880d681SAndroid Build Coastguard Worker bool isTypeSupported(Type *Ty, MVT &VT, bool IsVectorAllowed = false);
141*9880d681SAndroid Build Coastguard Worker bool isValueAvailable(const Value *V) const;
142*9880d681SAndroid Build Coastguard Worker bool computeAddress(const Value *Obj, Address &Addr, Type *Ty = nullptr);
143*9880d681SAndroid Build Coastguard Worker bool computeCallAddress(const Value *V, Address &Addr);
144*9880d681SAndroid Build Coastguard Worker bool simplifyAddress(Address &Addr, MVT VT);
145*9880d681SAndroid Build Coastguard Worker void addLoadStoreOperands(Address &Addr, const MachineInstrBuilder &MIB,
146*9880d681SAndroid Build Coastguard Worker unsigned Flags, unsigned ScaleFactor,
147*9880d681SAndroid Build Coastguard Worker MachineMemOperand *MMO);
148*9880d681SAndroid Build Coastguard Worker bool isMemCpySmall(uint64_t Len, unsigned Alignment);
149*9880d681SAndroid Build Coastguard Worker bool tryEmitSmallMemCpy(Address Dest, Address Src, uint64_t Len,
150*9880d681SAndroid Build Coastguard Worker unsigned Alignment);
151*9880d681SAndroid Build Coastguard Worker bool foldXALUIntrinsic(AArch64CC::CondCode &CC, const Instruction *I,
152*9880d681SAndroid Build Coastguard Worker const Value *Cond);
153*9880d681SAndroid Build Coastguard Worker bool optimizeIntExtLoad(const Instruction *I, MVT RetVT, MVT SrcVT);
154*9880d681SAndroid Build Coastguard Worker bool optimizeSelect(const SelectInst *SI);
155*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, bool> getRegForGEPIndex(const Value *Idx);
156*9880d681SAndroid Build Coastguard Worker
157*9880d681SAndroid Build Coastguard Worker // Emit helper routines.
158*9880d681SAndroid Build Coastguard Worker unsigned emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS,
159*9880d681SAndroid Build Coastguard Worker const Value *RHS, bool SetFlags = false,
160*9880d681SAndroid Build Coastguard Worker bool WantResult = true, bool IsZExt = false);
161*9880d681SAndroid Build Coastguard Worker unsigned emitAddSub_rr(bool UseAdd, MVT RetVT, unsigned LHSReg,
162*9880d681SAndroid Build Coastguard Worker bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
163*9880d681SAndroid Build Coastguard Worker bool SetFlags = false, bool WantResult = true);
164*9880d681SAndroid Build Coastguard Worker unsigned emitAddSub_ri(bool UseAdd, MVT RetVT, unsigned LHSReg,
165*9880d681SAndroid Build Coastguard Worker bool LHSIsKill, uint64_t Imm, bool SetFlags = false,
166*9880d681SAndroid Build Coastguard Worker bool WantResult = true);
167*9880d681SAndroid Build Coastguard Worker unsigned emitAddSub_rs(bool UseAdd, MVT RetVT, unsigned LHSReg,
168*9880d681SAndroid Build Coastguard Worker bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
169*9880d681SAndroid Build Coastguard Worker AArch64_AM::ShiftExtendType ShiftType,
170*9880d681SAndroid Build Coastguard Worker uint64_t ShiftImm, bool SetFlags = false,
171*9880d681SAndroid Build Coastguard Worker bool WantResult = true);
172*9880d681SAndroid Build Coastguard Worker unsigned emitAddSub_rx(bool UseAdd, MVT RetVT, unsigned LHSReg,
173*9880d681SAndroid Build Coastguard Worker bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
174*9880d681SAndroid Build Coastguard Worker AArch64_AM::ShiftExtendType ExtType,
175*9880d681SAndroid Build Coastguard Worker uint64_t ShiftImm, bool SetFlags = false,
176*9880d681SAndroid Build Coastguard Worker bool WantResult = true);
177*9880d681SAndroid Build Coastguard Worker
178*9880d681SAndroid Build Coastguard Worker // Emit functions.
179*9880d681SAndroid Build Coastguard Worker bool emitCompareAndBranch(const BranchInst *BI);
180*9880d681SAndroid Build Coastguard Worker bool emitCmp(const Value *LHS, const Value *RHS, bool IsZExt);
181*9880d681SAndroid Build Coastguard Worker bool emitICmp(MVT RetVT, const Value *LHS, const Value *RHS, bool IsZExt);
182*9880d681SAndroid Build Coastguard Worker bool emitICmp_ri(MVT RetVT, unsigned LHSReg, bool LHSIsKill, uint64_t Imm);
183*9880d681SAndroid Build Coastguard Worker bool emitFCmp(MVT RetVT, const Value *LHS, const Value *RHS);
184*9880d681SAndroid Build Coastguard Worker unsigned emitLoad(MVT VT, MVT ResultVT, Address Addr, bool WantZExt = true,
185*9880d681SAndroid Build Coastguard Worker MachineMemOperand *MMO = nullptr);
186*9880d681SAndroid Build Coastguard Worker bool emitStore(MVT VT, unsigned SrcReg, Address Addr,
187*9880d681SAndroid Build Coastguard Worker MachineMemOperand *MMO = nullptr);
188*9880d681SAndroid Build Coastguard Worker unsigned emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt);
189*9880d681SAndroid Build Coastguard Worker unsigned emiti1Ext(unsigned SrcReg, MVT DestVT, bool isZExt);
190*9880d681SAndroid Build Coastguard Worker unsigned emitAdd(MVT RetVT, const Value *LHS, const Value *RHS,
191*9880d681SAndroid Build Coastguard Worker bool SetFlags = false, bool WantResult = true,
192*9880d681SAndroid Build Coastguard Worker bool IsZExt = false);
193*9880d681SAndroid Build Coastguard Worker unsigned emitAdd_ri_(MVT VT, unsigned Op0, bool Op0IsKill, int64_t Imm);
194*9880d681SAndroid Build Coastguard Worker unsigned emitSub(MVT RetVT, const Value *LHS, const Value *RHS,
195*9880d681SAndroid Build Coastguard Worker bool SetFlags = false, bool WantResult = true,
196*9880d681SAndroid Build Coastguard Worker bool IsZExt = false);
197*9880d681SAndroid Build Coastguard Worker unsigned emitSubs_rr(MVT RetVT, unsigned LHSReg, bool LHSIsKill,
198*9880d681SAndroid Build Coastguard Worker unsigned RHSReg, bool RHSIsKill, bool WantResult = true);
199*9880d681SAndroid Build Coastguard Worker unsigned emitSubs_rs(MVT RetVT, unsigned LHSReg, bool LHSIsKill,
200*9880d681SAndroid Build Coastguard Worker unsigned RHSReg, bool RHSIsKill,
201*9880d681SAndroid Build Coastguard Worker AArch64_AM::ShiftExtendType ShiftType, uint64_t ShiftImm,
202*9880d681SAndroid Build Coastguard Worker bool WantResult = true);
203*9880d681SAndroid Build Coastguard Worker unsigned emitLogicalOp(unsigned ISDOpc, MVT RetVT, const Value *LHS,
204*9880d681SAndroid Build Coastguard Worker const Value *RHS);
205*9880d681SAndroid Build Coastguard Worker unsigned emitLogicalOp_ri(unsigned ISDOpc, MVT RetVT, unsigned LHSReg,
206*9880d681SAndroid Build Coastguard Worker bool LHSIsKill, uint64_t Imm);
207*9880d681SAndroid Build Coastguard Worker unsigned emitLogicalOp_rs(unsigned ISDOpc, MVT RetVT, unsigned LHSReg,
208*9880d681SAndroid Build Coastguard Worker bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
209*9880d681SAndroid Build Coastguard Worker uint64_t ShiftImm);
210*9880d681SAndroid Build Coastguard Worker unsigned emitAnd_ri(MVT RetVT, unsigned LHSReg, bool LHSIsKill, uint64_t Imm);
211*9880d681SAndroid Build Coastguard Worker unsigned emitMul_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
212*9880d681SAndroid Build Coastguard Worker unsigned Op1, bool Op1IsKill);
213*9880d681SAndroid Build Coastguard Worker unsigned emitSMULL_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
214*9880d681SAndroid Build Coastguard Worker unsigned Op1, bool Op1IsKill);
215*9880d681SAndroid Build Coastguard Worker unsigned emitUMULL_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
216*9880d681SAndroid Build Coastguard Worker unsigned Op1, bool Op1IsKill);
217*9880d681SAndroid Build Coastguard Worker unsigned emitLSL_rr(MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
218*9880d681SAndroid Build Coastguard Worker unsigned Op1Reg, bool Op1IsKill);
219*9880d681SAndroid Build Coastguard Worker unsigned emitLSL_ri(MVT RetVT, MVT SrcVT, unsigned Op0Reg, bool Op0IsKill,
220*9880d681SAndroid Build Coastguard Worker uint64_t Imm, bool IsZExt = true);
221*9880d681SAndroid Build Coastguard Worker unsigned emitLSR_rr(MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
222*9880d681SAndroid Build Coastguard Worker unsigned Op1Reg, bool Op1IsKill);
223*9880d681SAndroid Build Coastguard Worker unsigned emitLSR_ri(MVT RetVT, MVT SrcVT, unsigned Op0Reg, bool Op0IsKill,
224*9880d681SAndroid Build Coastguard Worker uint64_t Imm, bool IsZExt = true);
225*9880d681SAndroid Build Coastguard Worker unsigned emitASR_rr(MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
226*9880d681SAndroid Build Coastguard Worker unsigned Op1Reg, bool Op1IsKill);
227*9880d681SAndroid Build Coastguard Worker unsigned emitASR_ri(MVT RetVT, MVT SrcVT, unsigned Op0Reg, bool Op0IsKill,
228*9880d681SAndroid Build Coastguard Worker uint64_t Imm, bool IsZExt = false);
229*9880d681SAndroid Build Coastguard Worker
230*9880d681SAndroid Build Coastguard Worker unsigned materializeInt(const ConstantInt *CI, MVT VT);
231*9880d681SAndroid Build Coastguard Worker unsigned materializeFP(const ConstantFP *CFP, MVT VT);
232*9880d681SAndroid Build Coastguard Worker unsigned materializeGV(const GlobalValue *GV);
233*9880d681SAndroid Build Coastguard Worker
234*9880d681SAndroid Build Coastguard Worker // Call handling routines.
235*9880d681SAndroid Build Coastguard Worker private:
236*9880d681SAndroid Build Coastguard Worker CCAssignFn *CCAssignFnForCall(CallingConv::ID CC) const;
237*9880d681SAndroid Build Coastguard Worker bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs,
238*9880d681SAndroid Build Coastguard Worker unsigned &NumBytes);
239*9880d681SAndroid Build Coastguard Worker bool finishCall(CallLoweringInfo &CLI, MVT RetVT, unsigned NumBytes);
240*9880d681SAndroid Build Coastguard Worker
241*9880d681SAndroid Build Coastguard Worker public:
242*9880d681SAndroid Build Coastguard Worker // Backend specific FastISel code.
243*9880d681SAndroid Build Coastguard Worker unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
244*9880d681SAndroid Build Coastguard Worker unsigned fastMaterializeConstant(const Constant *C) override;
245*9880d681SAndroid Build Coastguard Worker unsigned fastMaterializeFloatZero(const ConstantFP* CF) override;
246*9880d681SAndroid Build Coastguard Worker
AArch64FastISel(FunctionLoweringInfo & FuncInfo,const TargetLibraryInfo * LibInfo)247*9880d681SAndroid Build Coastguard Worker explicit AArch64FastISel(FunctionLoweringInfo &FuncInfo,
248*9880d681SAndroid Build Coastguard Worker const TargetLibraryInfo *LibInfo)
249*9880d681SAndroid Build Coastguard Worker : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
250*9880d681SAndroid Build Coastguard Worker Subtarget =
251*9880d681SAndroid Build Coastguard Worker &static_cast<const AArch64Subtarget &>(FuncInfo.MF->getSubtarget());
252*9880d681SAndroid Build Coastguard Worker Context = &FuncInfo.Fn->getContext();
253*9880d681SAndroid Build Coastguard Worker }
254*9880d681SAndroid Build Coastguard Worker
255*9880d681SAndroid Build Coastguard Worker bool fastSelectInstruction(const Instruction *I) override;
256*9880d681SAndroid Build Coastguard Worker
257*9880d681SAndroid Build Coastguard Worker #include "AArch64GenFastISel.inc"
258*9880d681SAndroid Build Coastguard Worker };
259*9880d681SAndroid Build Coastguard Worker
260*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
261*9880d681SAndroid Build Coastguard Worker
262*9880d681SAndroid Build Coastguard Worker #include "AArch64GenCallingConv.inc"
263*9880d681SAndroid Build Coastguard Worker
264*9880d681SAndroid Build Coastguard Worker /// \brief Check if the sign-/zero-extend will be a noop.
isIntExtFree(const Instruction * I)265*9880d681SAndroid Build Coastguard Worker static bool isIntExtFree(const Instruction *I) {
266*9880d681SAndroid Build Coastguard Worker assert((isa<ZExtInst>(I) || isa<SExtInst>(I)) &&
267*9880d681SAndroid Build Coastguard Worker "Unexpected integer extend instruction.");
268*9880d681SAndroid Build Coastguard Worker assert(!I->getType()->isVectorTy() && I->getType()->isIntegerTy() &&
269*9880d681SAndroid Build Coastguard Worker "Unexpected value type.");
270*9880d681SAndroid Build Coastguard Worker bool IsZExt = isa<ZExtInst>(I);
271*9880d681SAndroid Build Coastguard Worker
272*9880d681SAndroid Build Coastguard Worker if (const auto *LI = dyn_cast<LoadInst>(I->getOperand(0)))
273*9880d681SAndroid Build Coastguard Worker if (LI->hasOneUse())
274*9880d681SAndroid Build Coastguard Worker return true;
275*9880d681SAndroid Build Coastguard Worker
276*9880d681SAndroid Build Coastguard Worker if (const auto *Arg = dyn_cast<Argument>(I->getOperand(0)))
277*9880d681SAndroid Build Coastguard Worker if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr()))
278*9880d681SAndroid Build Coastguard Worker return true;
279*9880d681SAndroid Build Coastguard Worker
280*9880d681SAndroid Build Coastguard Worker return false;
281*9880d681SAndroid Build Coastguard Worker }
282*9880d681SAndroid Build Coastguard Worker
283*9880d681SAndroid Build Coastguard Worker /// \brief Determine the implicit scale factor that is applied by a memory
284*9880d681SAndroid Build Coastguard Worker /// operation for a given value type.
getImplicitScaleFactor(MVT VT)285*9880d681SAndroid Build Coastguard Worker static unsigned getImplicitScaleFactor(MVT VT) {
286*9880d681SAndroid Build Coastguard Worker switch (VT.SimpleTy) {
287*9880d681SAndroid Build Coastguard Worker default:
288*9880d681SAndroid Build Coastguard Worker return 0; // invalid
289*9880d681SAndroid Build Coastguard Worker case MVT::i1: // fall-through
290*9880d681SAndroid Build Coastguard Worker case MVT::i8:
291*9880d681SAndroid Build Coastguard Worker return 1;
292*9880d681SAndroid Build Coastguard Worker case MVT::i16:
293*9880d681SAndroid Build Coastguard Worker return 2;
294*9880d681SAndroid Build Coastguard Worker case MVT::i32: // fall-through
295*9880d681SAndroid Build Coastguard Worker case MVT::f32:
296*9880d681SAndroid Build Coastguard Worker return 4;
297*9880d681SAndroid Build Coastguard Worker case MVT::i64: // fall-through
298*9880d681SAndroid Build Coastguard Worker case MVT::f64:
299*9880d681SAndroid Build Coastguard Worker return 8;
300*9880d681SAndroid Build Coastguard Worker }
301*9880d681SAndroid Build Coastguard Worker }
302*9880d681SAndroid Build Coastguard Worker
CCAssignFnForCall(CallingConv::ID CC) const303*9880d681SAndroid Build Coastguard Worker CCAssignFn *AArch64FastISel::CCAssignFnForCall(CallingConv::ID CC) const {
304*9880d681SAndroid Build Coastguard Worker if (CC == CallingConv::WebKit_JS)
305*9880d681SAndroid Build Coastguard Worker return CC_AArch64_WebKit_JS;
306*9880d681SAndroid Build Coastguard Worker if (CC == CallingConv::GHC)
307*9880d681SAndroid Build Coastguard Worker return CC_AArch64_GHC;
308*9880d681SAndroid Build Coastguard Worker return Subtarget->isTargetDarwin() ? CC_AArch64_DarwinPCS : CC_AArch64_AAPCS;
309*9880d681SAndroid Build Coastguard Worker }
310*9880d681SAndroid Build Coastguard Worker
fastMaterializeAlloca(const AllocaInst * AI)311*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::fastMaterializeAlloca(const AllocaInst *AI) {
312*9880d681SAndroid Build Coastguard Worker assert(TLI.getValueType(DL, AI->getType(), true) == MVT::i64 &&
313*9880d681SAndroid Build Coastguard Worker "Alloca should always return a pointer.");
314*9880d681SAndroid Build Coastguard Worker
315*9880d681SAndroid Build Coastguard Worker // Don't handle dynamic allocas.
316*9880d681SAndroid Build Coastguard Worker if (!FuncInfo.StaticAllocaMap.count(AI))
317*9880d681SAndroid Build Coastguard Worker return 0;
318*9880d681SAndroid Build Coastguard Worker
319*9880d681SAndroid Build Coastguard Worker DenseMap<const AllocaInst *, int>::iterator SI =
320*9880d681SAndroid Build Coastguard Worker FuncInfo.StaticAllocaMap.find(AI);
321*9880d681SAndroid Build Coastguard Worker
322*9880d681SAndroid Build Coastguard Worker if (SI != FuncInfo.StaticAllocaMap.end()) {
323*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(&AArch64::GPR64spRegClass);
324*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADDXri),
325*9880d681SAndroid Build Coastguard Worker ResultReg)
326*9880d681SAndroid Build Coastguard Worker .addFrameIndex(SI->second)
327*9880d681SAndroid Build Coastguard Worker .addImm(0)
328*9880d681SAndroid Build Coastguard Worker .addImm(0);
329*9880d681SAndroid Build Coastguard Worker return ResultReg;
330*9880d681SAndroid Build Coastguard Worker }
331*9880d681SAndroid Build Coastguard Worker
332*9880d681SAndroid Build Coastguard Worker return 0;
333*9880d681SAndroid Build Coastguard Worker }
334*9880d681SAndroid Build Coastguard Worker
materializeInt(const ConstantInt * CI,MVT VT)335*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::materializeInt(const ConstantInt *CI, MVT VT) {
336*9880d681SAndroid Build Coastguard Worker if (VT > MVT::i64)
337*9880d681SAndroid Build Coastguard Worker return 0;
338*9880d681SAndroid Build Coastguard Worker
339*9880d681SAndroid Build Coastguard Worker if (!CI->isZero())
340*9880d681SAndroid Build Coastguard Worker return fastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue());
341*9880d681SAndroid Build Coastguard Worker
342*9880d681SAndroid Build Coastguard Worker // Create a copy from the zero register to materialize a "0" value.
343*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = (VT == MVT::i64) ? &AArch64::GPR64RegClass
344*9880d681SAndroid Build Coastguard Worker : &AArch64::GPR32RegClass;
345*9880d681SAndroid Build Coastguard Worker unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
346*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(RC);
347*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TargetOpcode::COPY),
348*9880d681SAndroid Build Coastguard Worker ResultReg).addReg(ZeroReg, getKillRegState(true));
349*9880d681SAndroid Build Coastguard Worker return ResultReg;
350*9880d681SAndroid Build Coastguard Worker }
351*9880d681SAndroid Build Coastguard Worker
materializeFP(const ConstantFP * CFP,MVT VT)352*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::materializeFP(const ConstantFP *CFP, MVT VT) {
353*9880d681SAndroid Build Coastguard Worker // Positive zero (+0.0) has to be materialized with a fmov from the zero
354*9880d681SAndroid Build Coastguard Worker // register, because the immediate version of fmov cannot encode zero.
355*9880d681SAndroid Build Coastguard Worker if (CFP->isNullValue())
356*9880d681SAndroid Build Coastguard Worker return fastMaterializeFloatZero(CFP);
357*9880d681SAndroid Build Coastguard Worker
358*9880d681SAndroid Build Coastguard Worker if (VT != MVT::f32 && VT != MVT::f64)
359*9880d681SAndroid Build Coastguard Worker return 0;
360*9880d681SAndroid Build Coastguard Worker
361*9880d681SAndroid Build Coastguard Worker const APFloat Val = CFP->getValueAPF();
362*9880d681SAndroid Build Coastguard Worker bool Is64Bit = (VT == MVT::f64);
363*9880d681SAndroid Build Coastguard Worker // This checks to see if we can use FMOV instructions to materialize
364*9880d681SAndroid Build Coastguard Worker // a constant, otherwise we have to materialize via the constant pool.
365*9880d681SAndroid Build Coastguard Worker if (TLI.isFPImmLegal(Val, VT)) {
366*9880d681SAndroid Build Coastguard Worker int Imm =
367*9880d681SAndroid Build Coastguard Worker Is64Bit ? AArch64_AM::getFP64Imm(Val) : AArch64_AM::getFP32Imm(Val);
368*9880d681SAndroid Build Coastguard Worker assert((Imm != -1) && "Cannot encode floating-point constant.");
369*9880d681SAndroid Build Coastguard Worker unsigned Opc = Is64Bit ? AArch64::FMOVDi : AArch64::FMOVSi;
370*9880d681SAndroid Build Coastguard Worker return fastEmitInst_i(Opc, TLI.getRegClassFor(VT), Imm);
371*9880d681SAndroid Build Coastguard Worker }
372*9880d681SAndroid Build Coastguard Worker
373*9880d681SAndroid Build Coastguard Worker // For the MachO large code model materialize the FP constant in code.
374*9880d681SAndroid Build Coastguard Worker if (Subtarget->isTargetMachO() && TM.getCodeModel() == CodeModel::Large) {
375*9880d681SAndroid Build Coastguard Worker unsigned Opc1 = Is64Bit ? AArch64::MOVi64imm : AArch64::MOVi32imm;
376*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = Is64Bit ?
377*9880d681SAndroid Build Coastguard Worker &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
378*9880d681SAndroid Build Coastguard Worker
379*9880d681SAndroid Build Coastguard Worker unsigned TmpReg = createResultReg(RC);
380*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc1), TmpReg)
381*9880d681SAndroid Build Coastguard Worker .addImm(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
382*9880d681SAndroid Build Coastguard Worker
383*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(TLI.getRegClassFor(VT));
384*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
385*9880d681SAndroid Build Coastguard Worker TII.get(TargetOpcode::COPY), ResultReg)
386*9880d681SAndroid Build Coastguard Worker .addReg(TmpReg, getKillRegState(true));
387*9880d681SAndroid Build Coastguard Worker
388*9880d681SAndroid Build Coastguard Worker return ResultReg;
389*9880d681SAndroid Build Coastguard Worker }
390*9880d681SAndroid Build Coastguard Worker
391*9880d681SAndroid Build Coastguard Worker // Materialize via constant pool. MachineConstantPool wants an explicit
392*9880d681SAndroid Build Coastguard Worker // alignment.
393*9880d681SAndroid Build Coastguard Worker unsigned Align = DL.getPrefTypeAlignment(CFP->getType());
394*9880d681SAndroid Build Coastguard Worker if (Align == 0)
395*9880d681SAndroid Build Coastguard Worker Align = DL.getTypeAllocSize(CFP->getType());
396*9880d681SAndroid Build Coastguard Worker
397*9880d681SAndroid Build Coastguard Worker unsigned CPI = MCP.getConstantPoolIndex(cast<Constant>(CFP), Align);
398*9880d681SAndroid Build Coastguard Worker unsigned ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
399*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADRP),
400*9880d681SAndroid Build Coastguard Worker ADRPReg).addConstantPoolIndex(CPI, 0, AArch64II::MO_PAGE);
401*9880d681SAndroid Build Coastguard Worker
402*9880d681SAndroid Build Coastguard Worker unsigned Opc = Is64Bit ? AArch64::LDRDui : AArch64::LDRSui;
403*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(TLI.getRegClassFor(VT));
404*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
405*9880d681SAndroid Build Coastguard Worker .addReg(ADRPReg)
406*9880d681SAndroid Build Coastguard Worker .addConstantPoolIndex(CPI, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
407*9880d681SAndroid Build Coastguard Worker return ResultReg;
408*9880d681SAndroid Build Coastguard Worker }
409*9880d681SAndroid Build Coastguard Worker
materializeGV(const GlobalValue * GV)410*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::materializeGV(const GlobalValue *GV) {
411*9880d681SAndroid Build Coastguard Worker // We can't handle thread-local variables quickly yet.
412*9880d681SAndroid Build Coastguard Worker if (GV->isThreadLocal())
413*9880d681SAndroid Build Coastguard Worker return 0;
414*9880d681SAndroid Build Coastguard Worker
415*9880d681SAndroid Build Coastguard Worker // MachO still uses GOT for large code-model accesses, but ELF requires
416*9880d681SAndroid Build Coastguard Worker // movz/movk sequences, which FastISel doesn't handle yet.
417*9880d681SAndroid Build Coastguard Worker if (TM.getCodeModel() != CodeModel::Small && !Subtarget->isTargetMachO())
418*9880d681SAndroid Build Coastguard Worker return 0;
419*9880d681SAndroid Build Coastguard Worker
420*9880d681SAndroid Build Coastguard Worker unsigned char OpFlags = Subtarget->ClassifyGlobalReference(GV, TM);
421*9880d681SAndroid Build Coastguard Worker
422*9880d681SAndroid Build Coastguard Worker EVT DestEVT = TLI.getValueType(DL, GV->getType(), true);
423*9880d681SAndroid Build Coastguard Worker if (!DestEVT.isSimple())
424*9880d681SAndroid Build Coastguard Worker return 0;
425*9880d681SAndroid Build Coastguard Worker
426*9880d681SAndroid Build Coastguard Worker unsigned ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
427*9880d681SAndroid Build Coastguard Worker unsigned ResultReg;
428*9880d681SAndroid Build Coastguard Worker
429*9880d681SAndroid Build Coastguard Worker if (OpFlags & AArch64II::MO_GOT) {
430*9880d681SAndroid Build Coastguard Worker // ADRP + LDRX
431*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADRP),
432*9880d681SAndroid Build Coastguard Worker ADRPReg)
433*9880d681SAndroid Build Coastguard Worker .addGlobalAddress(GV, 0, AArch64II::MO_GOT | AArch64II::MO_PAGE);
434*9880d681SAndroid Build Coastguard Worker
435*9880d681SAndroid Build Coastguard Worker ResultReg = createResultReg(&AArch64::GPR64RegClass);
436*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::LDRXui),
437*9880d681SAndroid Build Coastguard Worker ResultReg)
438*9880d681SAndroid Build Coastguard Worker .addReg(ADRPReg)
439*9880d681SAndroid Build Coastguard Worker .addGlobalAddress(GV, 0, AArch64II::MO_GOT | AArch64II::MO_PAGEOFF |
440*9880d681SAndroid Build Coastguard Worker AArch64II::MO_NC);
441*9880d681SAndroid Build Coastguard Worker } else {
442*9880d681SAndroid Build Coastguard Worker // ADRP + ADDX
443*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADRP),
444*9880d681SAndroid Build Coastguard Worker ADRPReg)
445*9880d681SAndroid Build Coastguard Worker .addGlobalAddress(GV, 0, AArch64II::MO_PAGE);
446*9880d681SAndroid Build Coastguard Worker
447*9880d681SAndroid Build Coastguard Worker ResultReg = createResultReg(&AArch64::GPR64spRegClass);
448*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADDXri),
449*9880d681SAndroid Build Coastguard Worker ResultReg)
450*9880d681SAndroid Build Coastguard Worker .addReg(ADRPReg)
451*9880d681SAndroid Build Coastguard Worker .addGlobalAddress(GV, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC)
452*9880d681SAndroid Build Coastguard Worker .addImm(0);
453*9880d681SAndroid Build Coastguard Worker }
454*9880d681SAndroid Build Coastguard Worker return ResultReg;
455*9880d681SAndroid Build Coastguard Worker }
456*9880d681SAndroid Build Coastguard Worker
fastMaterializeConstant(const Constant * C)457*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::fastMaterializeConstant(const Constant *C) {
458*9880d681SAndroid Build Coastguard Worker EVT CEVT = TLI.getValueType(DL, C->getType(), true);
459*9880d681SAndroid Build Coastguard Worker
460*9880d681SAndroid Build Coastguard Worker // Only handle simple types.
461*9880d681SAndroid Build Coastguard Worker if (!CEVT.isSimple())
462*9880d681SAndroid Build Coastguard Worker return 0;
463*9880d681SAndroid Build Coastguard Worker MVT VT = CEVT.getSimpleVT();
464*9880d681SAndroid Build Coastguard Worker
465*9880d681SAndroid Build Coastguard Worker if (const auto *CI = dyn_cast<ConstantInt>(C))
466*9880d681SAndroid Build Coastguard Worker return materializeInt(CI, VT);
467*9880d681SAndroid Build Coastguard Worker else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
468*9880d681SAndroid Build Coastguard Worker return materializeFP(CFP, VT);
469*9880d681SAndroid Build Coastguard Worker else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
470*9880d681SAndroid Build Coastguard Worker return materializeGV(GV);
471*9880d681SAndroid Build Coastguard Worker
472*9880d681SAndroid Build Coastguard Worker return 0;
473*9880d681SAndroid Build Coastguard Worker }
474*9880d681SAndroid Build Coastguard Worker
fastMaterializeFloatZero(const ConstantFP * CFP)475*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::fastMaterializeFloatZero(const ConstantFP* CFP) {
476*9880d681SAndroid Build Coastguard Worker assert(CFP->isNullValue() &&
477*9880d681SAndroid Build Coastguard Worker "Floating-point constant is not a positive zero.");
478*9880d681SAndroid Build Coastguard Worker MVT VT;
479*9880d681SAndroid Build Coastguard Worker if (!isTypeLegal(CFP->getType(), VT))
480*9880d681SAndroid Build Coastguard Worker return 0;
481*9880d681SAndroid Build Coastguard Worker
482*9880d681SAndroid Build Coastguard Worker if (VT != MVT::f32 && VT != MVT::f64)
483*9880d681SAndroid Build Coastguard Worker return 0;
484*9880d681SAndroid Build Coastguard Worker
485*9880d681SAndroid Build Coastguard Worker bool Is64Bit = (VT == MVT::f64);
486*9880d681SAndroid Build Coastguard Worker unsigned ZReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
487*9880d681SAndroid Build Coastguard Worker unsigned Opc = Is64Bit ? AArch64::FMOVXDr : AArch64::FMOVWSr;
488*9880d681SAndroid Build Coastguard Worker return fastEmitInst_r(Opc, TLI.getRegClassFor(VT), ZReg, /*IsKill=*/true);
489*9880d681SAndroid Build Coastguard Worker }
490*9880d681SAndroid Build Coastguard Worker
491*9880d681SAndroid Build Coastguard Worker /// \brief Check if the multiply is by a power-of-2 constant.
isMulPowOf2(const Value * I)492*9880d681SAndroid Build Coastguard Worker static bool isMulPowOf2(const Value *I) {
493*9880d681SAndroid Build Coastguard Worker if (const auto *MI = dyn_cast<MulOperator>(I)) {
494*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(MI->getOperand(0)))
495*9880d681SAndroid Build Coastguard Worker if (C->getValue().isPowerOf2())
496*9880d681SAndroid Build Coastguard Worker return true;
497*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(MI->getOperand(1)))
498*9880d681SAndroid Build Coastguard Worker if (C->getValue().isPowerOf2())
499*9880d681SAndroid Build Coastguard Worker return true;
500*9880d681SAndroid Build Coastguard Worker }
501*9880d681SAndroid Build Coastguard Worker return false;
502*9880d681SAndroid Build Coastguard Worker }
503*9880d681SAndroid Build Coastguard Worker
504*9880d681SAndroid Build Coastguard Worker // Computes the address to get to an object.
computeAddress(const Value * Obj,Address & Addr,Type * Ty)505*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr, Type *Ty)
506*9880d681SAndroid Build Coastguard Worker {
507*9880d681SAndroid Build Coastguard Worker const User *U = nullptr;
508*9880d681SAndroid Build Coastguard Worker unsigned Opcode = Instruction::UserOp1;
509*9880d681SAndroid Build Coastguard Worker if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
510*9880d681SAndroid Build Coastguard Worker // Don't walk into other basic blocks unless the object is an alloca from
511*9880d681SAndroid Build Coastguard Worker // another block, otherwise it may not have a virtual register assigned.
512*9880d681SAndroid Build Coastguard Worker if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
513*9880d681SAndroid Build Coastguard Worker FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
514*9880d681SAndroid Build Coastguard Worker Opcode = I->getOpcode();
515*9880d681SAndroid Build Coastguard Worker U = I;
516*9880d681SAndroid Build Coastguard Worker }
517*9880d681SAndroid Build Coastguard Worker } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
518*9880d681SAndroid Build Coastguard Worker Opcode = C->getOpcode();
519*9880d681SAndroid Build Coastguard Worker U = C;
520*9880d681SAndroid Build Coastguard Worker }
521*9880d681SAndroid Build Coastguard Worker
522*9880d681SAndroid Build Coastguard Worker if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
523*9880d681SAndroid Build Coastguard Worker if (Ty->getAddressSpace() > 255)
524*9880d681SAndroid Build Coastguard Worker // Fast instruction selection doesn't support the special
525*9880d681SAndroid Build Coastguard Worker // address spaces.
526*9880d681SAndroid Build Coastguard Worker return false;
527*9880d681SAndroid Build Coastguard Worker
528*9880d681SAndroid Build Coastguard Worker switch (Opcode) {
529*9880d681SAndroid Build Coastguard Worker default:
530*9880d681SAndroid Build Coastguard Worker break;
531*9880d681SAndroid Build Coastguard Worker case Instruction::BitCast: {
532*9880d681SAndroid Build Coastguard Worker // Look through bitcasts.
533*9880d681SAndroid Build Coastguard Worker return computeAddress(U->getOperand(0), Addr, Ty);
534*9880d681SAndroid Build Coastguard Worker }
535*9880d681SAndroid Build Coastguard Worker case Instruction::IntToPtr: {
536*9880d681SAndroid Build Coastguard Worker // Look past no-op inttoptrs.
537*9880d681SAndroid Build Coastguard Worker if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
538*9880d681SAndroid Build Coastguard Worker TLI.getPointerTy(DL))
539*9880d681SAndroid Build Coastguard Worker return computeAddress(U->getOperand(0), Addr, Ty);
540*9880d681SAndroid Build Coastguard Worker break;
541*9880d681SAndroid Build Coastguard Worker }
542*9880d681SAndroid Build Coastguard Worker case Instruction::PtrToInt: {
543*9880d681SAndroid Build Coastguard Worker // Look past no-op ptrtoints.
544*9880d681SAndroid Build Coastguard Worker if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
545*9880d681SAndroid Build Coastguard Worker return computeAddress(U->getOperand(0), Addr, Ty);
546*9880d681SAndroid Build Coastguard Worker break;
547*9880d681SAndroid Build Coastguard Worker }
548*9880d681SAndroid Build Coastguard Worker case Instruction::GetElementPtr: {
549*9880d681SAndroid Build Coastguard Worker Address SavedAddr = Addr;
550*9880d681SAndroid Build Coastguard Worker uint64_t TmpOffset = Addr.getOffset();
551*9880d681SAndroid Build Coastguard Worker
552*9880d681SAndroid Build Coastguard Worker // Iterate through the GEP folding the constants into offsets where
553*9880d681SAndroid Build Coastguard Worker // we can.
554*9880d681SAndroid Build Coastguard Worker for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
555*9880d681SAndroid Build Coastguard Worker GTI != E; ++GTI) {
556*9880d681SAndroid Build Coastguard Worker const Value *Op = GTI.getOperand();
557*9880d681SAndroid Build Coastguard Worker if (StructType *STy = dyn_cast<StructType>(*GTI)) {
558*9880d681SAndroid Build Coastguard Worker const StructLayout *SL = DL.getStructLayout(STy);
559*9880d681SAndroid Build Coastguard Worker unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
560*9880d681SAndroid Build Coastguard Worker TmpOffset += SL->getElementOffset(Idx);
561*9880d681SAndroid Build Coastguard Worker } else {
562*9880d681SAndroid Build Coastguard Worker uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
563*9880d681SAndroid Build Coastguard Worker for (;;) {
564*9880d681SAndroid Build Coastguard Worker if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
565*9880d681SAndroid Build Coastguard Worker // Constant-offset addressing.
566*9880d681SAndroid Build Coastguard Worker TmpOffset += CI->getSExtValue() * S;
567*9880d681SAndroid Build Coastguard Worker break;
568*9880d681SAndroid Build Coastguard Worker }
569*9880d681SAndroid Build Coastguard Worker if (canFoldAddIntoGEP(U, Op)) {
570*9880d681SAndroid Build Coastguard Worker // A compatible add with a constant operand. Fold the constant.
571*9880d681SAndroid Build Coastguard Worker ConstantInt *CI =
572*9880d681SAndroid Build Coastguard Worker cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
573*9880d681SAndroid Build Coastguard Worker TmpOffset += CI->getSExtValue() * S;
574*9880d681SAndroid Build Coastguard Worker // Iterate on the other operand.
575*9880d681SAndroid Build Coastguard Worker Op = cast<AddOperator>(Op)->getOperand(0);
576*9880d681SAndroid Build Coastguard Worker continue;
577*9880d681SAndroid Build Coastguard Worker }
578*9880d681SAndroid Build Coastguard Worker // Unsupported
579*9880d681SAndroid Build Coastguard Worker goto unsupported_gep;
580*9880d681SAndroid Build Coastguard Worker }
581*9880d681SAndroid Build Coastguard Worker }
582*9880d681SAndroid Build Coastguard Worker }
583*9880d681SAndroid Build Coastguard Worker
584*9880d681SAndroid Build Coastguard Worker // Try to grab the base operand now.
585*9880d681SAndroid Build Coastguard Worker Addr.setOffset(TmpOffset);
586*9880d681SAndroid Build Coastguard Worker if (computeAddress(U->getOperand(0), Addr, Ty))
587*9880d681SAndroid Build Coastguard Worker return true;
588*9880d681SAndroid Build Coastguard Worker
589*9880d681SAndroid Build Coastguard Worker // We failed, restore everything and try the other options.
590*9880d681SAndroid Build Coastguard Worker Addr = SavedAddr;
591*9880d681SAndroid Build Coastguard Worker
592*9880d681SAndroid Build Coastguard Worker unsupported_gep:
593*9880d681SAndroid Build Coastguard Worker break;
594*9880d681SAndroid Build Coastguard Worker }
595*9880d681SAndroid Build Coastguard Worker case Instruction::Alloca: {
596*9880d681SAndroid Build Coastguard Worker const AllocaInst *AI = cast<AllocaInst>(Obj);
597*9880d681SAndroid Build Coastguard Worker DenseMap<const AllocaInst *, int>::iterator SI =
598*9880d681SAndroid Build Coastguard Worker FuncInfo.StaticAllocaMap.find(AI);
599*9880d681SAndroid Build Coastguard Worker if (SI != FuncInfo.StaticAllocaMap.end()) {
600*9880d681SAndroid Build Coastguard Worker Addr.setKind(Address::FrameIndexBase);
601*9880d681SAndroid Build Coastguard Worker Addr.setFI(SI->second);
602*9880d681SAndroid Build Coastguard Worker return true;
603*9880d681SAndroid Build Coastguard Worker }
604*9880d681SAndroid Build Coastguard Worker break;
605*9880d681SAndroid Build Coastguard Worker }
606*9880d681SAndroid Build Coastguard Worker case Instruction::Add: {
607*9880d681SAndroid Build Coastguard Worker // Adds of constants are common and easy enough.
608*9880d681SAndroid Build Coastguard Worker const Value *LHS = U->getOperand(0);
609*9880d681SAndroid Build Coastguard Worker const Value *RHS = U->getOperand(1);
610*9880d681SAndroid Build Coastguard Worker
611*9880d681SAndroid Build Coastguard Worker if (isa<ConstantInt>(LHS))
612*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
613*9880d681SAndroid Build Coastguard Worker
614*9880d681SAndroid Build Coastguard Worker if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
615*9880d681SAndroid Build Coastguard Worker Addr.setOffset(Addr.getOffset() + CI->getSExtValue());
616*9880d681SAndroid Build Coastguard Worker return computeAddress(LHS, Addr, Ty);
617*9880d681SAndroid Build Coastguard Worker }
618*9880d681SAndroid Build Coastguard Worker
619*9880d681SAndroid Build Coastguard Worker Address Backup = Addr;
620*9880d681SAndroid Build Coastguard Worker if (computeAddress(LHS, Addr, Ty) && computeAddress(RHS, Addr, Ty))
621*9880d681SAndroid Build Coastguard Worker return true;
622*9880d681SAndroid Build Coastguard Worker Addr = Backup;
623*9880d681SAndroid Build Coastguard Worker
624*9880d681SAndroid Build Coastguard Worker break;
625*9880d681SAndroid Build Coastguard Worker }
626*9880d681SAndroid Build Coastguard Worker case Instruction::Sub: {
627*9880d681SAndroid Build Coastguard Worker // Subs of constants are common and easy enough.
628*9880d681SAndroid Build Coastguard Worker const Value *LHS = U->getOperand(0);
629*9880d681SAndroid Build Coastguard Worker const Value *RHS = U->getOperand(1);
630*9880d681SAndroid Build Coastguard Worker
631*9880d681SAndroid Build Coastguard Worker if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
632*9880d681SAndroid Build Coastguard Worker Addr.setOffset(Addr.getOffset() - CI->getSExtValue());
633*9880d681SAndroid Build Coastguard Worker return computeAddress(LHS, Addr, Ty);
634*9880d681SAndroid Build Coastguard Worker }
635*9880d681SAndroid Build Coastguard Worker break;
636*9880d681SAndroid Build Coastguard Worker }
637*9880d681SAndroid Build Coastguard Worker case Instruction::Shl: {
638*9880d681SAndroid Build Coastguard Worker if (Addr.getOffsetReg())
639*9880d681SAndroid Build Coastguard Worker break;
640*9880d681SAndroid Build Coastguard Worker
641*9880d681SAndroid Build Coastguard Worker const auto *CI = dyn_cast<ConstantInt>(U->getOperand(1));
642*9880d681SAndroid Build Coastguard Worker if (!CI)
643*9880d681SAndroid Build Coastguard Worker break;
644*9880d681SAndroid Build Coastguard Worker
645*9880d681SAndroid Build Coastguard Worker unsigned Val = CI->getZExtValue();
646*9880d681SAndroid Build Coastguard Worker if (Val < 1 || Val > 3)
647*9880d681SAndroid Build Coastguard Worker break;
648*9880d681SAndroid Build Coastguard Worker
649*9880d681SAndroid Build Coastguard Worker uint64_t NumBytes = 0;
650*9880d681SAndroid Build Coastguard Worker if (Ty && Ty->isSized()) {
651*9880d681SAndroid Build Coastguard Worker uint64_t NumBits = DL.getTypeSizeInBits(Ty);
652*9880d681SAndroid Build Coastguard Worker NumBytes = NumBits / 8;
653*9880d681SAndroid Build Coastguard Worker if (!isPowerOf2_64(NumBits))
654*9880d681SAndroid Build Coastguard Worker NumBytes = 0;
655*9880d681SAndroid Build Coastguard Worker }
656*9880d681SAndroid Build Coastguard Worker
657*9880d681SAndroid Build Coastguard Worker if (NumBytes != (1ULL << Val))
658*9880d681SAndroid Build Coastguard Worker break;
659*9880d681SAndroid Build Coastguard Worker
660*9880d681SAndroid Build Coastguard Worker Addr.setShift(Val);
661*9880d681SAndroid Build Coastguard Worker Addr.setExtendType(AArch64_AM::LSL);
662*9880d681SAndroid Build Coastguard Worker
663*9880d681SAndroid Build Coastguard Worker const Value *Src = U->getOperand(0);
664*9880d681SAndroid Build Coastguard Worker if (const auto *I = dyn_cast<Instruction>(Src)) {
665*9880d681SAndroid Build Coastguard Worker if (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
666*9880d681SAndroid Build Coastguard Worker // Fold the zext or sext when it won't become a noop.
667*9880d681SAndroid Build Coastguard Worker if (const auto *ZE = dyn_cast<ZExtInst>(I)) {
668*9880d681SAndroid Build Coastguard Worker if (!isIntExtFree(ZE) &&
669*9880d681SAndroid Build Coastguard Worker ZE->getOperand(0)->getType()->isIntegerTy(32)) {
670*9880d681SAndroid Build Coastguard Worker Addr.setExtendType(AArch64_AM::UXTW);
671*9880d681SAndroid Build Coastguard Worker Src = ZE->getOperand(0);
672*9880d681SAndroid Build Coastguard Worker }
673*9880d681SAndroid Build Coastguard Worker } else if (const auto *SE = dyn_cast<SExtInst>(I)) {
674*9880d681SAndroid Build Coastguard Worker if (!isIntExtFree(SE) &&
675*9880d681SAndroid Build Coastguard Worker SE->getOperand(0)->getType()->isIntegerTy(32)) {
676*9880d681SAndroid Build Coastguard Worker Addr.setExtendType(AArch64_AM::SXTW);
677*9880d681SAndroid Build Coastguard Worker Src = SE->getOperand(0);
678*9880d681SAndroid Build Coastguard Worker }
679*9880d681SAndroid Build Coastguard Worker }
680*9880d681SAndroid Build Coastguard Worker }
681*9880d681SAndroid Build Coastguard Worker }
682*9880d681SAndroid Build Coastguard Worker
683*9880d681SAndroid Build Coastguard Worker if (const auto *AI = dyn_cast<BinaryOperator>(Src))
684*9880d681SAndroid Build Coastguard Worker if (AI->getOpcode() == Instruction::And) {
685*9880d681SAndroid Build Coastguard Worker const Value *LHS = AI->getOperand(0);
686*9880d681SAndroid Build Coastguard Worker const Value *RHS = AI->getOperand(1);
687*9880d681SAndroid Build Coastguard Worker
688*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(LHS))
689*9880d681SAndroid Build Coastguard Worker if (C->getValue() == 0xffffffff)
690*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
691*9880d681SAndroid Build Coastguard Worker
692*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(RHS))
693*9880d681SAndroid Build Coastguard Worker if (C->getValue() == 0xffffffff) {
694*9880d681SAndroid Build Coastguard Worker Addr.setExtendType(AArch64_AM::UXTW);
695*9880d681SAndroid Build Coastguard Worker unsigned Reg = getRegForValue(LHS);
696*9880d681SAndroid Build Coastguard Worker if (!Reg)
697*9880d681SAndroid Build Coastguard Worker return false;
698*9880d681SAndroid Build Coastguard Worker bool RegIsKill = hasTrivialKill(LHS);
699*9880d681SAndroid Build Coastguard Worker Reg = fastEmitInst_extractsubreg(MVT::i32, Reg, RegIsKill,
700*9880d681SAndroid Build Coastguard Worker AArch64::sub_32);
701*9880d681SAndroid Build Coastguard Worker Addr.setOffsetReg(Reg);
702*9880d681SAndroid Build Coastguard Worker return true;
703*9880d681SAndroid Build Coastguard Worker }
704*9880d681SAndroid Build Coastguard Worker }
705*9880d681SAndroid Build Coastguard Worker
706*9880d681SAndroid Build Coastguard Worker unsigned Reg = getRegForValue(Src);
707*9880d681SAndroid Build Coastguard Worker if (!Reg)
708*9880d681SAndroid Build Coastguard Worker return false;
709*9880d681SAndroid Build Coastguard Worker Addr.setOffsetReg(Reg);
710*9880d681SAndroid Build Coastguard Worker return true;
711*9880d681SAndroid Build Coastguard Worker }
712*9880d681SAndroid Build Coastguard Worker case Instruction::Mul: {
713*9880d681SAndroid Build Coastguard Worker if (Addr.getOffsetReg())
714*9880d681SAndroid Build Coastguard Worker break;
715*9880d681SAndroid Build Coastguard Worker
716*9880d681SAndroid Build Coastguard Worker if (!isMulPowOf2(U))
717*9880d681SAndroid Build Coastguard Worker break;
718*9880d681SAndroid Build Coastguard Worker
719*9880d681SAndroid Build Coastguard Worker const Value *LHS = U->getOperand(0);
720*9880d681SAndroid Build Coastguard Worker const Value *RHS = U->getOperand(1);
721*9880d681SAndroid Build Coastguard Worker
722*9880d681SAndroid Build Coastguard Worker // Canonicalize power-of-2 value to the RHS.
723*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(LHS))
724*9880d681SAndroid Build Coastguard Worker if (C->getValue().isPowerOf2())
725*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
726*9880d681SAndroid Build Coastguard Worker
727*9880d681SAndroid Build Coastguard Worker assert(isa<ConstantInt>(RHS) && "Expected an ConstantInt.");
728*9880d681SAndroid Build Coastguard Worker const auto *C = cast<ConstantInt>(RHS);
729*9880d681SAndroid Build Coastguard Worker unsigned Val = C->getValue().logBase2();
730*9880d681SAndroid Build Coastguard Worker if (Val < 1 || Val > 3)
731*9880d681SAndroid Build Coastguard Worker break;
732*9880d681SAndroid Build Coastguard Worker
733*9880d681SAndroid Build Coastguard Worker uint64_t NumBytes = 0;
734*9880d681SAndroid Build Coastguard Worker if (Ty && Ty->isSized()) {
735*9880d681SAndroid Build Coastguard Worker uint64_t NumBits = DL.getTypeSizeInBits(Ty);
736*9880d681SAndroid Build Coastguard Worker NumBytes = NumBits / 8;
737*9880d681SAndroid Build Coastguard Worker if (!isPowerOf2_64(NumBits))
738*9880d681SAndroid Build Coastguard Worker NumBytes = 0;
739*9880d681SAndroid Build Coastguard Worker }
740*9880d681SAndroid Build Coastguard Worker
741*9880d681SAndroid Build Coastguard Worker if (NumBytes != (1ULL << Val))
742*9880d681SAndroid Build Coastguard Worker break;
743*9880d681SAndroid Build Coastguard Worker
744*9880d681SAndroid Build Coastguard Worker Addr.setShift(Val);
745*9880d681SAndroid Build Coastguard Worker Addr.setExtendType(AArch64_AM::LSL);
746*9880d681SAndroid Build Coastguard Worker
747*9880d681SAndroid Build Coastguard Worker const Value *Src = LHS;
748*9880d681SAndroid Build Coastguard Worker if (const auto *I = dyn_cast<Instruction>(Src)) {
749*9880d681SAndroid Build Coastguard Worker if (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
750*9880d681SAndroid Build Coastguard Worker // Fold the zext or sext when it won't become a noop.
751*9880d681SAndroid Build Coastguard Worker if (const auto *ZE = dyn_cast<ZExtInst>(I)) {
752*9880d681SAndroid Build Coastguard Worker if (!isIntExtFree(ZE) &&
753*9880d681SAndroid Build Coastguard Worker ZE->getOperand(0)->getType()->isIntegerTy(32)) {
754*9880d681SAndroid Build Coastguard Worker Addr.setExtendType(AArch64_AM::UXTW);
755*9880d681SAndroid Build Coastguard Worker Src = ZE->getOperand(0);
756*9880d681SAndroid Build Coastguard Worker }
757*9880d681SAndroid Build Coastguard Worker } else if (const auto *SE = dyn_cast<SExtInst>(I)) {
758*9880d681SAndroid Build Coastguard Worker if (!isIntExtFree(SE) &&
759*9880d681SAndroid Build Coastguard Worker SE->getOperand(0)->getType()->isIntegerTy(32)) {
760*9880d681SAndroid Build Coastguard Worker Addr.setExtendType(AArch64_AM::SXTW);
761*9880d681SAndroid Build Coastguard Worker Src = SE->getOperand(0);
762*9880d681SAndroid Build Coastguard Worker }
763*9880d681SAndroid Build Coastguard Worker }
764*9880d681SAndroid Build Coastguard Worker }
765*9880d681SAndroid Build Coastguard Worker }
766*9880d681SAndroid Build Coastguard Worker
767*9880d681SAndroid Build Coastguard Worker unsigned Reg = getRegForValue(Src);
768*9880d681SAndroid Build Coastguard Worker if (!Reg)
769*9880d681SAndroid Build Coastguard Worker return false;
770*9880d681SAndroid Build Coastguard Worker Addr.setOffsetReg(Reg);
771*9880d681SAndroid Build Coastguard Worker return true;
772*9880d681SAndroid Build Coastguard Worker }
773*9880d681SAndroid Build Coastguard Worker case Instruction::And: {
774*9880d681SAndroid Build Coastguard Worker if (Addr.getOffsetReg())
775*9880d681SAndroid Build Coastguard Worker break;
776*9880d681SAndroid Build Coastguard Worker
777*9880d681SAndroid Build Coastguard Worker if (!Ty || DL.getTypeSizeInBits(Ty) != 8)
778*9880d681SAndroid Build Coastguard Worker break;
779*9880d681SAndroid Build Coastguard Worker
780*9880d681SAndroid Build Coastguard Worker const Value *LHS = U->getOperand(0);
781*9880d681SAndroid Build Coastguard Worker const Value *RHS = U->getOperand(1);
782*9880d681SAndroid Build Coastguard Worker
783*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(LHS))
784*9880d681SAndroid Build Coastguard Worker if (C->getValue() == 0xffffffff)
785*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
786*9880d681SAndroid Build Coastguard Worker
787*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(RHS))
788*9880d681SAndroid Build Coastguard Worker if (C->getValue() == 0xffffffff) {
789*9880d681SAndroid Build Coastguard Worker Addr.setShift(0);
790*9880d681SAndroid Build Coastguard Worker Addr.setExtendType(AArch64_AM::LSL);
791*9880d681SAndroid Build Coastguard Worker Addr.setExtendType(AArch64_AM::UXTW);
792*9880d681SAndroid Build Coastguard Worker
793*9880d681SAndroid Build Coastguard Worker unsigned Reg = getRegForValue(LHS);
794*9880d681SAndroid Build Coastguard Worker if (!Reg)
795*9880d681SAndroid Build Coastguard Worker return false;
796*9880d681SAndroid Build Coastguard Worker bool RegIsKill = hasTrivialKill(LHS);
797*9880d681SAndroid Build Coastguard Worker Reg = fastEmitInst_extractsubreg(MVT::i32, Reg, RegIsKill,
798*9880d681SAndroid Build Coastguard Worker AArch64::sub_32);
799*9880d681SAndroid Build Coastguard Worker Addr.setOffsetReg(Reg);
800*9880d681SAndroid Build Coastguard Worker return true;
801*9880d681SAndroid Build Coastguard Worker }
802*9880d681SAndroid Build Coastguard Worker break;
803*9880d681SAndroid Build Coastguard Worker }
804*9880d681SAndroid Build Coastguard Worker case Instruction::SExt:
805*9880d681SAndroid Build Coastguard Worker case Instruction::ZExt: {
806*9880d681SAndroid Build Coastguard Worker if (!Addr.getReg() || Addr.getOffsetReg())
807*9880d681SAndroid Build Coastguard Worker break;
808*9880d681SAndroid Build Coastguard Worker
809*9880d681SAndroid Build Coastguard Worker const Value *Src = nullptr;
810*9880d681SAndroid Build Coastguard Worker // Fold the zext or sext when it won't become a noop.
811*9880d681SAndroid Build Coastguard Worker if (const auto *ZE = dyn_cast<ZExtInst>(U)) {
812*9880d681SAndroid Build Coastguard Worker if (!isIntExtFree(ZE) && ZE->getOperand(0)->getType()->isIntegerTy(32)) {
813*9880d681SAndroid Build Coastguard Worker Addr.setExtendType(AArch64_AM::UXTW);
814*9880d681SAndroid Build Coastguard Worker Src = ZE->getOperand(0);
815*9880d681SAndroid Build Coastguard Worker }
816*9880d681SAndroid Build Coastguard Worker } else if (const auto *SE = dyn_cast<SExtInst>(U)) {
817*9880d681SAndroid Build Coastguard Worker if (!isIntExtFree(SE) && SE->getOperand(0)->getType()->isIntegerTy(32)) {
818*9880d681SAndroid Build Coastguard Worker Addr.setExtendType(AArch64_AM::SXTW);
819*9880d681SAndroid Build Coastguard Worker Src = SE->getOperand(0);
820*9880d681SAndroid Build Coastguard Worker }
821*9880d681SAndroid Build Coastguard Worker }
822*9880d681SAndroid Build Coastguard Worker
823*9880d681SAndroid Build Coastguard Worker if (!Src)
824*9880d681SAndroid Build Coastguard Worker break;
825*9880d681SAndroid Build Coastguard Worker
826*9880d681SAndroid Build Coastguard Worker Addr.setShift(0);
827*9880d681SAndroid Build Coastguard Worker unsigned Reg = getRegForValue(Src);
828*9880d681SAndroid Build Coastguard Worker if (!Reg)
829*9880d681SAndroid Build Coastguard Worker return false;
830*9880d681SAndroid Build Coastguard Worker Addr.setOffsetReg(Reg);
831*9880d681SAndroid Build Coastguard Worker return true;
832*9880d681SAndroid Build Coastguard Worker }
833*9880d681SAndroid Build Coastguard Worker } // end switch
834*9880d681SAndroid Build Coastguard Worker
835*9880d681SAndroid Build Coastguard Worker if (Addr.isRegBase() && !Addr.getReg()) {
836*9880d681SAndroid Build Coastguard Worker unsigned Reg = getRegForValue(Obj);
837*9880d681SAndroid Build Coastguard Worker if (!Reg)
838*9880d681SAndroid Build Coastguard Worker return false;
839*9880d681SAndroid Build Coastguard Worker Addr.setReg(Reg);
840*9880d681SAndroid Build Coastguard Worker return true;
841*9880d681SAndroid Build Coastguard Worker }
842*9880d681SAndroid Build Coastguard Worker
843*9880d681SAndroid Build Coastguard Worker if (!Addr.getOffsetReg()) {
844*9880d681SAndroid Build Coastguard Worker unsigned Reg = getRegForValue(Obj);
845*9880d681SAndroid Build Coastguard Worker if (!Reg)
846*9880d681SAndroid Build Coastguard Worker return false;
847*9880d681SAndroid Build Coastguard Worker Addr.setOffsetReg(Reg);
848*9880d681SAndroid Build Coastguard Worker return true;
849*9880d681SAndroid Build Coastguard Worker }
850*9880d681SAndroid Build Coastguard Worker
851*9880d681SAndroid Build Coastguard Worker return false;
852*9880d681SAndroid Build Coastguard Worker }
853*9880d681SAndroid Build Coastguard Worker
computeCallAddress(const Value * V,Address & Addr)854*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::computeCallAddress(const Value *V, Address &Addr) {
855*9880d681SAndroid Build Coastguard Worker const User *U = nullptr;
856*9880d681SAndroid Build Coastguard Worker unsigned Opcode = Instruction::UserOp1;
857*9880d681SAndroid Build Coastguard Worker bool InMBB = true;
858*9880d681SAndroid Build Coastguard Worker
859*9880d681SAndroid Build Coastguard Worker if (const auto *I = dyn_cast<Instruction>(V)) {
860*9880d681SAndroid Build Coastguard Worker Opcode = I->getOpcode();
861*9880d681SAndroid Build Coastguard Worker U = I;
862*9880d681SAndroid Build Coastguard Worker InMBB = I->getParent() == FuncInfo.MBB->getBasicBlock();
863*9880d681SAndroid Build Coastguard Worker } else if (const auto *C = dyn_cast<ConstantExpr>(V)) {
864*9880d681SAndroid Build Coastguard Worker Opcode = C->getOpcode();
865*9880d681SAndroid Build Coastguard Worker U = C;
866*9880d681SAndroid Build Coastguard Worker }
867*9880d681SAndroid Build Coastguard Worker
868*9880d681SAndroid Build Coastguard Worker switch (Opcode) {
869*9880d681SAndroid Build Coastguard Worker default: break;
870*9880d681SAndroid Build Coastguard Worker case Instruction::BitCast:
871*9880d681SAndroid Build Coastguard Worker // Look past bitcasts if its operand is in the same BB.
872*9880d681SAndroid Build Coastguard Worker if (InMBB)
873*9880d681SAndroid Build Coastguard Worker return computeCallAddress(U->getOperand(0), Addr);
874*9880d681SAndroid Build Coastguard Worker break;
875*9880d681SAndroid Build Coastguard Worker case Instruction::IntToPtr:
876*9880d681SAndroid Build Coastguard Worker // Look past no-op inttoptrs if its operand is in the same BB.
877*9880d681SAndroid Build Coastguard Worker if (InMBB &&
878*9880d681SAndroid Build Coastguard Worker TLI.getValueType(DL, U->getOperand(0)->getType()) ==
879*9880d681SAndroid Build Coastguard Worker TLI.getPointerTy(DL))
880*9880d681SAndroid Build Coastguard Worker return computeCallAddress(U->getOperand(0), Addr);
881*9880d681SAndroid Build Coastguard Worker break;
882*9880d681SAndroid Build Coastguard Worker case Instruction::PtrToInt:
883*9880d681SAndroid Build Coastguard Worker // Look past no-op ptrtoints if its operand is in the same BB.
884*9880d681SAndroid Build Coastguard Worker if (InMBB && TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
885*9880d681SAndroid Build Coastguard Worker return computeCallAddress(U->getOperand(0), Addr);
886*9880d681SAndroid Build Coastguard Worker break;
887*9880d681SAndroid Build Coastguard Worker }
888*9880d681SAndroid Build Coastguard Worker
889*9880d681SAndroid Build Coastguard Worker if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
890*9880d681SAndroid Build Coastguard Worker Addr.setGlobalValue(GV);
891*9880d681SAndroid Build Coastguard Worker return true;
892*9880d681SAndroid Build Coastguard Worker }
893*9880d681SAndroid Build Coastguard Worker
894*9880d681SAndroid Build Coastguard Worker // If all else fails, try to materialize the value in a register.
895*9880d681SAndroid Build Coastguard Worker if (!Addr.getGlobalValue()) {
896*9880d681SAndroid Build Coastguard Worker Addr.setReg(getRegForValue(V));
897*9880d681SAndroid Build Coastguard Worker return Addr.getReg() != 0;
898*9880d681SAndroid Build Coastguard Worker }
899*9880d681SAndroid Build Coastguard Worker
900*9880d681SAndroid Build Coastguard Worker return false;
901*9880d681SAndroid Build Coastguard Worker }
902*9880d681SAndroid Build Coastguard Worker
903*9880d681SAndroid Build Coastguard Worker
isTypeLegal(Type * Ty,MVT & VT)904*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::isTypeLegal(Type *Ty, MVT &VT) {
905*9880d681SAndroid Build Coastguard Worker EVT evt = TLI.getValueType(DL, Ty, true);
906*9880d681SAndroid Build Coastguard Worker
907*9880d681SAndroid Build Coastguard Worker // Only handle simple types.
908*9880d681SAndroid Build Coastguard Worker if (evt == MVT::Other || !evt.isSimple())
909*9880d681SAndroid Build Coastguard Worker return false;
910*9880d681SAndroid Build Coastguard Worker VT = evt.getSimpleVT();
911*9880d681SAndroid Build Coastguard Worker
912*9880d681SAndroid Build Coastguard Worker // This is a legal type, but it's not something we handle in fast-isel.
913*9880d681SAndroid Build Coastguard Worker if (VT == MVT::f128)
914*9880d681SAndroid Build Coastguard Worker return false;
915*9880d681SAndroid Build Coastguard Worker
916*9880d681SAndroid Build Coastguard Worker // Handle all other legal types, i.e. a register that will directly hold this
917*9880d681SAndroid Build Coastguard Worker // value.
918*9880d681SAndroid Build Coastguard Worker return TLI.isTypeLegal(VT);
919*9880d681SAndroid Build Coastguard Worker }
920*9880d681SAndroid Build Coastguard Worker
921*9880d681SAndroid Build Coastguard Worker /// \brief Determine if the value type is supported by FastISel.
922*9880d681SAndroid Build Coastguard Worker ///
923*9880d681SAndroid Build Coastguard Worker /// FastISel for AArch64 can handle more value types than are legal. This adds
924*9880d681SAndroid Build Coastguard Worker /// simple value type such as i1, i8, and i16.
isTypeSupported(Type * Ty,MVT & VT,bool IsVectorAllowed)925*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::isTypeSupported(Type *Ty, MVT &VT, bool IsVectorAllowed) {
926*9880d681SAndroid Build Coastguard Worker if (Ty->isVectorTy() && !IsVectorAllowed)
927*9880d681SAndroid Build Coastguard Worker return false;
928*9880d681SAndroid Build Coastguard Worker
929*9880d681SAndroid Build Coastguard Worker if (isTypeLegal(Ty, VT))
930*9880d681SAndroid Build Coastguard Worker return true;
931*9880d681SAndroid Build Coastguard Worker
932*9880d681SAndroid Build Coastguard Worker // If this is a type than can be sign or zero-extended to a basic operation
933*9880d681SAndroid Build Coastguard Worker // go ahead and accept it now.
934*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)
935*9880d681SAndroid Build Coastguard Worker return true;
936*9880d681SAndroid Build Coastguard Worker
937*9880d681SAndroid Build Coastguard Worker return false;
938*9880d681SAndroid Build Coastguard Worker }
939*9880d681SAndroid Build Coastguard Worker
isValueAvailable(const Value * V) const940*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::isValueAvailable(const Value *V) const {
941*9880d681SAndroid Build Coastguard Worker if (!isa<Instruction>(V))
942*9880d681SAndroid Build Coastguard Worker return true;
943*9880d681SAndroid Build Coastguard Worker
944*9880d681SAndroid Build Coastguard Worker const auto *I = cast<Instruction>(V);
945*9880d681SAndroid Build Coastguard Worker return FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB;
946*9880d681SAndroid Build Coastguard Worker }
947*9880d681SAndroid Build Coastguard Worker
simplifyAddress(Address & Addr,MVT VT)948*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::simplifyAddress(Address &Addr, MVT VT) {
949*9880d681SAndroid Build Coastguard Worker unsigned ScaleFactor = getImplicitScaleFactor(VT);
950*9880d681SAndroid Build Coastguard Worker if (!ScaleFactor)
951*9880d681SAndroid Build Coastguard Worker return false;
952*9880d681SAndroid Build Coastguard Worker
953*9880d681SAndroid Build Coastguard Worker bool ImmediateOffsetNeedsLowering = false;
954*9880d681SAndroid Build Coastguard Worker bool RegisterOffsetNeedsLowering = false;
955*9880d681SAndroid Build Coastguard Worker int64_t Offset = Addr.getOffset();
956*9880d681SAndroid Build Coastguard Worker if (((Offset < 0) || (Offset & (ScaleFactor - 1))) && !isInt<9>(Offset))
957*9880d681SAndroid Build Coastguard Worker ImmediateOffsetNeedsLowering = true;
958*9880d681SAndroid Build Coastguard Worker else if (Offset > 0 && !(Offset & (ScaleFactor - 1)) &&
959*9880d681SAndroid Build Coastguard Worker !isUInt<12>(Offset / ScaleFactor))
960*9880d681SAndroid Build Coastguard Worker ImmediateOffsetNeedsLowering = true;
961*9880d681SAndroid Build Coastguard Worker
962*9880d681SAndroid Build Coastguard Worker // Cannot encode an offset register and an immediate offset in the same
963*9880d681SAndroid Build Coastguard Worker // instruction. Fold the immediate offset into the load/store instruction and
964*9880d681SAndroid Build Coastguard Worker // emit an additional add to take care of the offset register.
965*9880d681SAndroid Build Coastguard Worker if (!ImmediateOffsetNeedsLowering && Addr.getOffset() && Addr.getOffsetReg())
966*9880d681SAndroid Build Coastguard Worker RegisterOffsetNeedsLowering = true;
967*9880d681SAndroid Build Coastguard Worker
968*9880d681SAndroid Build Coastguard Worker // Cannot encode zero register as base.
969*9880d681SAndroid Build Coastguard Worker if (Addr.isRegBase() && Addr.getOffsetReg() && !Addr.getReg())
970*9880d681SAndroid Build Coastguard Worker RegisterOffsetNeedsLowering = true;
971*9880d681SAndroid Build Coastguard Worker
972*9880d681SAndroid Build Coastguard Worker // If this is a stack pointer and the offset needs to be simplified then put
973*9880d681SAndroid Build Coastguard Worker // the alloca address into a register, set the base type back to register and
974*9880d681SAndroid Build Coastguard Worker // continue. This should almost never happen.
975*9880d681SAndroid Build Coastguard Worker if ((ImmediateOffsetNeedsLowering || Addr.getOffsetReg()) && Addr.isFIBase())
976*9880d681SAndroid Build Coastguard Worker {
977*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(&AArch64::GPR64spRegClass);
978*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADDXri),
979*9880d681SAndroid Build Coastguard Worker ResultReg)
980*9880d681SAndroid Build Coastguard Worker .addFrameIndex(Addr.getFI())
981*9880d681SAndroid Build Coastguard Worker .addImm(0)
982*9880d681SAndroid Build Coastguard Worker .addImm(0);
983*9880d681SAndroid Build Coastguard Worker Addr.setKind(Address::RegBase);
984*9880d681SAndroid Build Coastguard Worker Addr.setReg(ResultReg);
985*9880d681SAndroid Build Coastguard Worker }
986*9880d681SAndroid Build Coastguard Worker
987*9880d681SAndroid Build Coastguard Worker if (RegisterOffsetNeedsLowering) {
988*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = 0;
989*9880d681SAndroid Build Coastguard Worker if (Addr.getReg()) {
990*9880d681SAndroid Build Coastguard Worker if (Addr.getExtendType() == AArch64_AM::SXTW ||
991*9880d681SAndroid Build Coastguard Worker Addr.getExtendType() == AArch64_AM::UXTW )
992*9880d681SAndroid Build Coastguard Worker ResultReg = emitAddSub_rx(/*UseAdd=*/true, MVT::i64, Addr.getReg(),
993*9880d681SAndroid Build Coastguard Worker /*TODO:IsKill=*/false, Addr.getOffsetReg(),
994*9880d681SAndroid Build Coastguard Worker /*TODO:IsKill=*/false, Addr.getExtendType(),
995*9880d681SAndroid Build Coastguard Worker Addr.getShift());
996*9880d681SAndroid Build Coastguard Worker else
997*9880d681SAndroid Build Coastguard Worker ResultReg = emitAddSub_rs(/*UseAdd=*/true, MVT::i64, Addr.getReg(),
998*9880d681SAndroid Build Coastguard Worker /*TODO:IsKill=*/false, Addr.getOffsetReg(),
999*9880d681SAndroid Build Coastguard Worker /*TODO:IsKill=*/false, AArch64_AM::LSL,
1000*9880d681SAndroid Build Coastguard Worker Addr.getShift());
1001*9880d681SAndroid Build Coastguard Worker } else {
1002*9880d681SAndroid Build Coastguard Worker if (Addr.getExtendType() == AArch64_AM::UXTW)
1003*9880d681SAndroid Build Coastguard Worker ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1004*9880d681SAndroid Build Coastguard Worker /*Op0IsKill=*/false, Addr.getShift(),
1005*9880d681SAndroid Build Coastguard Worker /*IsZExt=*/true);
1006*9880d681SAndroid Build Coastguard Worker else if (Addr.getExtendType() == AArch64_AM::SXTW)
1007*9880d681SAndroid Build Coastguard Worker ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1008*9880d681SAndroid Build Coastguard Worker /*Op0IsKill=*/false, Addr.getShift(),
1009*9880d681SAndroid Build Coastguard Worker /*IsZExt=*/false);
1010*9880d681SAndroid Build Coastguard Worker else
1011*9880d681SAndroid Build Coastguard Worker ResultReg = emitLSL_ri(MVT::i64, MVT::i64, Addr.getOffsetReg(),
1012*9880d681SAndroid Build Coastguard Worker /*Op0IsKill=*/false, Addr.getShift());
1013*9880d681SAndroid Build Coastguard Worker }
1014*9880d681SAndroid Build Coastguard Worker if (!ResultReg)
1015*9880d681SAndroid Build Coastguard Worker return false;
1016*9880d681SAndroid Build Coastguard Worker
1017*9880d681SAndroid Build Coastguard Worker Addr.setReg(ResultReg);
1018*9880d681SAndroid Build Coastguard Worker Addr.setOffsetReg(0);
1019*9880d681SAndroid Build Coastguard Worker Addr.setShift(0);
1020*9880d681SAndroid Build Coastguard Worker Addr.setExtendType(AArch64_AM::InvalidShiftExtend);
1021*9880d681SAndroid Build Coastguard Worker }
1022*9880d681SAndroid Build Coastguard Worker
1023*9880d681SAndroid Build Coastguard Worker // Since the offset is too large for the load/store instruction get the
1024*9880d681SAndroid Build Coastguard Worker // reg+offset into a register.
1025*9880d681SAndroid Build Coastguard Worker if (ImmediateOffsetNeedsLowering) {
1026*9880d681SAndroid Build Coastguard Worker unsigned ResultReg;
1027*9880d681SAndroid Build Coastguard Worker if (Addr.getReg())
1028*9880d681SAndroid Build Coastguard Worker // Try to fold the immediate into the add instruction.
1029*9880d681SAndroid Build Coastguard Worker ResultReg = emitAdd_ri_(MVT::i64, Addr.getReg(), /*IsKill=*/false, Offset);
1030*9880d681SAndroid Build Coastguard Worker else
1031*9880d681SAndroid Build Coastguard Worker ResultReg = fastEmit_i(MVT::i64, MVT::i64, ISD::Constant, Offset);
1032*9880d681SAndroid Build Coastguard Worker
1033*9880d681SAndroid Build Coastguard Worker if (!ResultReg)
1034*9880d681SAndroid Build Coastguard Worker return false;
1035*9880d681SAndroid Build Coastguard Worker Addr.setReg(ResultReg);
1036*9880d681SAndroid Build Coastguard Worker Addr.setOffset(0);
1037*9880d681SAndroid Build Coastguard Worker }
1038*9880d681SAndroid Build Coastguard Worker return true;
1039*9880d681SAndroid Build Coastguard Worker }
1040*9880d681SAndroid Build Coastguard Worker
addLoadStoreOperands(Address & Addr,const MachineInstrBuilder & MIB,unsigned Flags,unsigned ScaleFactor,MachineMemOperand * MMO)1041*9880d681SAndroid Build Coastguard Worker void AArch64FastISel::addLoadStoreOperands(Address &Addr,
1042*9880d681SAndroid Build Coastguard Worker const MachineInstrBuilder &MIB,
1043*9880d681SAndroid Build Coastguard Worker unsigned Flags,
1044*9880d681SAndroid Build Coastguard Worker unsigned ScaleFactor,
1045*9880d681SAndroid Build Coastguard Worker MachineMemOperand *MMO) {
1046*9880d681SAndroid Build Coastguard Worker int64_t Offset = Addr.getOffset() / ScaleFactor;
1047*9880d681SAndroid Build Coastguard Worker // Frame base works a bit differently. Handle it separately.
1048*9880d681SAndroid Build Coastguard Worker if (Addr.isFIBase()) {
1049*9880d681SAndroid Build Coastguard Worker int FI = Addr.getFI();
1050*9880d681SAndroid Build Coastguard Worker // FIXME: We shouldn't be using getObjectSize/getObjectAlignment. The size
1051*9880d681SAndroid Build Coastguard Worker // and alignment should be based on the VT.
1052*9880d681SAndroid Build Coastguard Worker MMO = FuncInfo.MF->getMachineMemOperand(
1053*9880d681SAndroid Build Coastguard Worker MachinePointerInfo::getFixedStack(*FuncInfo.MF, FI, Offset), Flags,
1054*9880d681SAndroid Build Coastguard Worker MFI.getObjectSize(FI), MFI.getObjectAlignment(FI));
1055*9880d681SAndroid Build Coastguard Worker // Now add the rest of the operands.
1056*9880d681SAndroid Build Coastguard Worker MIB.addFrameIndex(FI).addImm(Offset);
1057*9880d681SAndroid Build Coastguard Worker } else {
1058*9880d681SAndroid Build Coastguard Worker assert(Addr.isRegBase() && "Unexpected address kind.");
1059*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &II = MIB->getDesc();
1060*9880d681SAndroid Build Coastguard Worker unsigned Idx = (Flags & MachineMemOperand::MOStore) ? 1 : 0;
1061*9880d681SAndroid Build Coastguard Worker Addr.setReg(
1062*9880d681SAndroid Build Coastguard Worker constrainOperandRegClass(II, Addr.getReg(), II.getNumDefs()+Idx));
1063*9880d681SAndroid Build Coastguard Worker Addr.setOffsetReg(
1064*9880d681SAndroid Build Coastguard Worker constrainOperandRegClass(II, Addr.getOffsetReg(), II.getNumDefs()+Idx+1));
1065*9880d681SAndroid Build Coastguard Worker if (Addr.getOffsetReg()) {
1066*9880d681SAndroid Build Coastguard Worker assert(Addr.getOffset() == 0 && "Unexpected offset");
1067*9880d681SAndroid Build Coastguard Worker bool IsSigned = Addr.getExtendType() == AArch64_AM::SXTW ||
1068*9880d681SAndroid Build Coastguard Worker Addr.getExtendType() == AArch64_AM::SXTX;
1069*9880d681SAndroid Build Coastguard Worker MIB.addReg(Addr.getReg());
1070*9880d681SAndroid Build Coastguard Worker MIB.addReg(Addr.getOffsetReg());
1071*9880d681SAndroid Build Coastguard Worker MIB.addImm(IsSigned);
1072*9880d681SAndroid Build Coastguard Worker MIB.addImm(Addr.getShift() != 0);
1073*9880d681SAndroid Build Coastguard Worker } else
1074*9880d681SAndroid Build Coastguard Worker MIB.addReg(Addr.getReg()).addImm(Offset);
1075*9880d681SAndroid Build Coastguard Worker }
1076*9880d681SAndroid Build Coastguard Worker
1077*9880d681SAndroid Build Coastguard Worker if (MMO)
1078*9880d681SAndroid Build Coastguard Worker MIB.addMemOperand(MMO);
1079*9880d681SAndroid Build Coastguard Worker }
1080*9880d681SAndroid Build Coastguard Worker
emitAddSub(bool UseAdd,MVT RetVT,const Value * LHS,const Value * RHS,bool SetFlags,bool WantResult,bool IsZExt)1081*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS,
1082*9880d681SAndroid Build Coastguard Worker const Value *RHS, bool SetFlags,
1083*9880d681SAndroid Build Coastguard Worker bool WantResult, bool IsZExt) {
1084*9880d681SAndroid Build Coastguard Worker AArch64_AM::ShiftExtendType ExtendType = AArch64_AM::InvalidShiftExtend;
1085*9880d681SAndroid Build Coastguard Worker bool NeedExtend = false;
1086*9880d681SAndroid Build Coastguard Worker switch (RetVT.SimpleTy) {
1087*9880d681SAndroid Build Coastguard Worker default:
1088*9880d681SAndroid Build Coastguard Worker return 0;
1089*9880d681SAndroid Build Coastguard Worker case MVT::i1:
1090*9880d681SAndroid Build Coastguard Worker NeedExtend = true;
1091*9880d681SAndroid Build Coastguard Worker break;
1092*9880d681SAndroid Build Coastguard Worker case MVT::i8:
1093*9880d681SAndroid Build Coastguard Worker NeedExtend = true;
1094*9880d681SAndroid Build Coastguard Worker ExtendType = IsZExt ? AArch64_AM::UXTB : AArch64_AM::SXTB;
1095*9880d681SAndroid Build Coastguard Worker break;
1096*9880d681SAndroid Build Coastguard Worker case MVT::i16:
1097*9880d681SAndroid Build Coastguard Worker NeedExtend = true;
1098*9880d681SAndroid Build Coastguard Worker ExtendType = IsZExt ? AArch64_AM::UXTH : AArch64_AM::SXTH;
1099*9880d681SAndroid Build Coastguard Worker break;
1100*9880d681SAndroid Build Coastguard Worker case MVT::i32: // fall-through
1101*9880d681SAndroid Build Coastguard Worker case MVT::i64:
1102*9880d681SAndroid Build Coastguard Worker break;
1103*9880d681SAndroid Build Coastguard Worker }
1104*9880d681SAndroid Build Coastguard Worker MVT SrcVT = RetVT;
1105*9880d681SAndroid Build Coastguard Worker RetVT.SimpleTy = std::max(RetVT.SimpleTy, MVT::i32);
1106*9880d681SAndroid Build Coastguard Worker
1107*9880d681SAndroid Build Coastguard Worker // Canonicalize immediates to the RHS first.
1108*9880d681SAndroid Build Coastguard Worker if (UseAdd && isa<Constant>(LHS) && !isa<Constant>(RHS))
1109*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
1110*9880d681SAndroid Build Coastguard Worker
1111*9880d681SAndroid Build Coastguard Worker // Canonicalize mul by power of 2 to the RHS.
1112*9880d681SAndroid Build Coastguard Worker if (UseAdd && LHS->hasOneUse() && isValueAvailable(LHS))
1113*9880d681SAndroid Build Coastguard Worker if (isMulPowOf2(LHS))
1114*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
1115*9880d681SAndroid Build Coastguard Worker
1116*9880d681SAndroid Build Coastguard Worker // Canonicalize shift immediate to the RHS.
1117*9880d681SAndroid Build Coastguard Worker if (UseAdd && LHS->hasOneUse() && isValueAvailable(LHS))
1118*9880d681SAndroid Build Coastguard Worker if (const auto *SI = dyn_cast<BinaryOperator>(LHS))
1119*9880d681SAndroid Build Coastguard Worker if (isa<ConstantInt>(SI->getOperand(1)))
1120*9880d681SAndroid Build Coastguard Worker if (SI->getOpcode() == Instruction::Shl ||
1121*9880d681SAndroid Build Coastguard Worker SI->getOpcode() == Instruction::LShr ||
1122*9880d681SAndroid Build Coastguard Worker SI->getOpcode() == Instruction::AShr )
1123*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
1124*9880d681SAndroid Build Coastguard Worker
1125*9880d681SAndroid Build Coastguard Worker unsigned LHSReg = getRegForValue(LHS);
1126*9880d681SAndroid Build Coastguard Worker if (!LHSReg)
1127*9880d681SAndroid Build Coastguard Worker return 0;
1128*9880d681SAndroid Build Coastguard Worker bool LHSIsKill = hasTrivialKill(LHS);
1129*9880d681SAndroid Build Coastguard Worker
1130*9880d681SAndroid Build Coastguard Worker if (NeedExtend)
1131*9880d681SAndroid Build Coastguard Worker LHSReg = emitIntExt(SrcVT, LHSReg, RetVT, IsZExt);
1132*9880d681SAndroid Build Coastguard Worker
1133*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = 0;
1134*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(RHS)) {
1135*9880d681SAndroid Build Coastguard Worker uint64_t Imm = IsZExt ? C->getZExtValue() : C->getSExtValue();
1136*9880d681SAndroid Build Coastguard Worker if (C->isNegative())
1137*9880d681SAndroid Build Coastguard Worker ResultReg = emitAddSub_ri(!UseAdd, RetVT, LHSReg, LHSIsKill, -Imm,
1138*9880d681SAndroid Build Coastguard Worker SetFlags, WantResult);
1139*9880d681SAndroid Build Coastguard Worker else
1140*9880d681SAndroid Build Coastguard Worker ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, LHSIsKill, Imm, SetFlags,
1141*9880d681SAndroid Build Coastguard Worker WantResult);
1142*9880d681SAndroid Build Coastguard Worker } else if (const auto *C = dyn_cast<Constant>(RHS))
1143*9880d681SAndroid Build Coastguard Worker if (C->isNullValue())
1144*9880d681SAndroid Build Coastguard Worker ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, LHSIsKill, 0, SetFlags,
1145*9880d681SAndroid Build Coastguard Worker WantResult);
1146*9880d681SAndroid Build Coastguard Worker
1147*9880d681SAndroid Build Coastguard Worker if (ResultReg)
1148*9880d681SAndroid Build Coastguard Worker return ResultReg;
1149*9880d681SAndroid Build Coastguard Worker
1150*9880d681SAndroid Build Coastguard Worker // Only extend the RHS within the instruction if there is a valid extend type.
1151*9880d681SAndroid Build Coastguard Worker if (ExtendType != AArch64_AM::InvalidShiftExtend && RHS->hasOneUse() &&
1152*9880d681SAndroid Build Coastguard Worker isValueAvailable(RHS)) {
1153*9880d681SAndroid Build Coastguard Worker if (const auto *SI = dyn_cast<BinaryOperator>(RHS))
1154*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1)))
1155*9880d681SAndroid Build Coastguard Worker if ((SI->getOpcode() == Instruction::Shl) && (C->getZExtValue() < 4)) {
1156*9880d681SAndroid Build Coastguard Worker unsigned RHSReg = getRegForValue(SI->getOperand(0));
1157*9880d681SAndroid Build Coastguard Worker if (!RHSReg)
1158*9880d681SAndroid Build Coastguard Worker return 0;
1159*9880d681SAndroid Build Coastguard Worker bool RHSIsKill = hasTrivialKill(SI->getOperand(0));
1160*9880d681SAndroid Build Coastguard Worker return emitAddSub_rx(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg,
1161*9880d681SAndroid Build Coastguard Worker RHSIsKill, ExtendType, C->getZExtValue(),
1162*9880d681SAndroid Build Coastguard Worker SetFlags, WantResult);
1163*9880d681SAndroid Build Coastguard Worker }
1164*9880d681SAndroid Build Coastguard Worker unsigned RHSReg = getRegForValue(RHS);
1165*9880d681SAndroid Build Coastguard Worker if (!RHSReg)
1166*9880d681SAndroid Build Coastguard Worker return 0;
1167*9880d681SAndroid Build Coastguard Worker bool RHSIsKill = hasTrivialKill(RHS);
1168*9880d681SAndroid Build Coastguard Worker return emitAddSub_rx(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
1169*9880d681SAndroid Build Coastguard Worker ExtendType, 0, SetFlags, WantResult);
1170*9880d681SAndroid Build Coastguard Worker }
1171*9880d681SAndroid Build Coastguard Worker
1172*9880d681SAndroid Build Coastguard Worker // Check if the mul can be folded into the instruction.
1173*9880d681SAndroid Build Coastguard Worker if (RHS->hasOneUse() && isValueAvailable(RHS)) {
1174*9880d681SAndroid Build Coastguard Worker if (isMulPowOf2(RHS)) {
1175*9880d681SAndroid Build Coastguard Worker const Value *MulLHS = cast<MulOperator>(RHS)->getOperand(0);
1176*9880d681SAndroid Build Coastguard Worker const Value *MulRHS = cast<MulOperator>(RHS)->getOperand(1);
1177*9880d681SAndroid Build Coastguard Worker
1178*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(MulLHS))
1179*9880d681SAndroid Build Coastguard Worker if (C->getValue().isPowerOf2())
1180*9880d681SAndroid Build Coastguard Worker std::swap(MulLHS, MulRHS);
1181*9880d681SAndroid Build Coastguard Worker
1182*9880d681SAndroid Build Coastguard Worker assert(isa<ConstantInt>(MulRHS) && "Expected a ConstantInt.");
1183*9880d681SAndroid Build Coastguard Worker uint64_t ShiftVal = cast<ConstantInt>(MulRHS)->getValue().logBase2();
1184*9880d681SAndroid Build Coastguard Worker unsigned RHSReg = getRegForValue(MulLHS);
1185*9880d681SAndroid Build Coastguard Worker if (!RHSReg)
1186*9880d681SAndroid Build Coastguard Worker return 0;
1187*9880d681SAndroid Build Coastguard Worker bool RHSIsKill = hasTrivialKill(MulLHS);
1188*9880d681SAndroid Build Coastguard Worker ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg,
1189*9880d681SAndroid Build Coastguard Worker RHSIsKill, AArch64_AM::LSL, ShiftVal, SetFlags,
1190*9880d681SAndroid Build Coastguard Worker WantResult);
1191*9880d681SAndroid Build Coastguard Worker if (ResultReg)
1192*9880d681SAndroid Build Coastguard Worker return ResultReg;
1193*9880d681SAndroid Build Coastguard Worker }
1194*9880d681SAndroid Build Coastguard Worker }
1195*9880d681SAndroid Build Coastguard Worker
1196*9880d681SAndroid Build Coastguard Worker // Check if the shift can be folded into the instruction.
1197*9880d681SAndroid Build Coastguard Worker if (RHS->hasOneUse() && isValueAvailable(RHS)) {
1198*9880d681SAndroid Build Coastguard Worker if (const auto *SI = dyn_cast<BinaryOperator>(RHS)) {
1199*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1))) {
1200*9880d681SAndroid Build Coastguard Worker AArch64_AM::ShiftExtendType ShiftType = AArch64_AM::InvalidShiftExtend;
1201*9880d681SAndroid Build Coastguard Worker switch (SI->getOpcode()) {
1202*9880d681SAndroid Build Coastguard Worker default: break;
1203*9880d681SAndroid Build Coastguard Worker case Instruction::Shl: ShiftType = AArch64_AM::LSL; break;
1204*9880d681SAndroid Build Coastguard Worker case Instruction::LShr: ShiftType = AArch64_AM::LSR; break;
1205*9880d681SAndroid Build Coastguard Worker case Instruction::AShr: ShiftType = AArch64_AM::ASR; break;
1206*9880d681SAndroid Build Coastguard Worker }
1207*9880d681SAndroid Build Coastguard Worker uint64_t ShiftVal = C->getZExtValue();
1208*9880d681SAndroid Build Coastguard Worker if (ShiftType != AArch64_AM::InvalidShiftExtend) {
1209*9880d681SAndroid Build Coastguard Worker unsigned RHSReg = getRegForValue(SI->getOperand(0));
1210*9880d681SAndroid Build Coastguard Worker if (!RHSReg)
1211*9880d681SAndroid Build Coastguard Worker return 0;
1212*9880d681SAndroid Build Coastguard Worker bool RHSIsKill = hasTrivialKill(SI->getOperand(0));
1213*9880d681SAndroid Build Coastguard Worker ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg,
1214*9880d681SAndroid Build Coastguard Worker RHSIsKill, ShiftType, ShiftVal, SetFlags,
1215*9880d681SAndroid Build Coastguard Worker WantResult);
1216*9880d681SAndroid Build Coastguard Worker if (ResultReg)
1217*9880d681SAndroid Build Coastguard Worker return ResultReg;
1218*9880d681SAndroid Build Coastguard Worker }
1219*9880d681SAndroid Build Coastguard Worker }
1220*9880d681SAndroid Build Coastguard Worker }
1221*9880d681SAndroid Build Coastguard Worker }
1222*9880d681SAndroid Build Coastguard Worker
1223*9880d681SAndroid Build Coastguard Worker unsigned RHSReg = getRegForValue(RHS);
1224*9880d681SAndroid Build Coastguard Worker if (!RHSReg)
1225*9880d681SAndroid Build Coastguard Worker return 0;
1226*9880d681SAndroid Build Coastguard Worker bool RHSIsKill = hasTrivialKill(RHS);
1227*9880d681SAndroid Build Coastguard Worker
1228*9880d681SAndroid Build Coastguard Worker if (NeedExtend)
1229*9880d681SAndroid Build Coastguard Worker RHSReg = emitIntExt(SrcVT, RHSReg, RetVT, IsZExt);
1230*9880d681SAndroid Build Coastguard Worker
1231*9880d681SAndroid Build Coastguard Worker return emitAddSub_rr(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
1232*9880d681SAndroid Build Coastguard Worker SetFlags, WantResult);
1233*9880d681SAndroid Build Coastguard Worker }
1234*9880d681SAndroid Build Coastguard Worker
emitAddSub_rr(bool UseAdd,MVT RetVT,unsigned LHSReg,bool LHSIsKill,unsigned RHSReg,bool RHSIsKill,bool SetFlags,bool WantResult)1235*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitAddSub_rr(bool UseAdd, MVT RetVT, unsigned LHSReg,
1236*9880d681SAndroid Build Coastguard Worker bool LHSIsKill, unsigned RHSReg,
1237*9880d681SAndroid Build Coastguard Worker bool RHSIsKill, bool SetFlags,
1238*9880d681SAndroid Build Coastguard Worker bool WantResult) {
1239*9880d681SAndroid Build Coastguard Worker assert(LHSReg && RHSReg && "Invalid register number.");
1240*9880d681SAndroid Build Coastguard Worker
1241*9880d681SAndroid Build Coastguard Worker if (RetVT != MVT::i32 && RetVT != MVT::i64)
1242*9880d681SAndroid Build Coastguard Worker return 0;
1243*9880d681SAndroid Build Coastguard Worker
1244*9880d681SAndroid Build Coastguard Worker static const unsigned OpcTable[2][2][2] = {
1245*9880d681SAndroid Build Coastguard Worker { { AArch64::SUBWrr, AArch64::SUBXrr },
1246*9880d681SAndroid Build Coastguard Worker { AArch64::ADDWrr, AArch64::ADDXrr } },
1247*9880d681SAndroid Build Coastguard Worker { { AArch64::SUBSWrr, AArch64::SUBSXrr },
1248*9880d681SAndroid Build Coastguard Worker { AArch64::ADDSWrr, AArch64::ADDSXrr } }
1249*9880d681SAndroid Build Coastguard Worker };
1250*9880d681SAndroid Build Coastguard Worker bool Is64Bit = RetVT == MVT::i64;
1251*9880d681SAndroid Build Coastguard Worker unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1252*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC =
1253*9880d681SAndroid Build Coastguard Worker Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1254*9880d681SAndroid Build Coastguard Worker unsigned ResultReg;
1255*9880d681SAndroid Build Coastguard Worker if (WantResult)
1256*9880d681SAndroid Build Coastguard Worker ResultReg = createResultReg(RC);
1257*9880d681SAndroid Build Coastguard Worker else
1258*9880d681SAndroid Build Coastguard Worker ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1259*9880d681SAndroid Build Coastguard Worker
1260*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &II = TII.get(Opc);
1261*9880d681SAndroid Build Coastguard Worker LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
1262*9880d681SAndroid Build Coastguard Worker RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
1263*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
1264*9880d681SAndroid Build Coastguard Worker .addReg(LHSReg, getKillRegState(LHSIsKill))
1265*9880d681SAndroid Build Coastguard Worker .addReg(RHSReg, getKillRegState(RHSIsKill));
1266*9880d681SAndroid Build Coastguard Worker return ResultReg;
1267*9880d681SAndroid Build Coastguard Worker }
1268*9880d681SAndroid Build Coastguard Worker
emitAddSub_ri(bool UseAdd,MVT RetVT,unsigned LHSReg,bool LHSIsKill,uint64_t Imm,bool SetFlags,bool WantResult)1269*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitAddSub_ri(bool UseAdd, MVT RetVT, unsigned LHSReg,
1270*9880d681SAndroid Build Coastguard Worker bool LHSIsKill, uint64_t Imm,
1271*9880d681SAndroid Build Coastguard Worker bool SetFlags, bool WantResult) {
1272*9880d681SAndroid Build Coastguard Worker assert(LHSReg && "Invalid register number.");
1273*9880d681SAndroid Build Coastguard Worker
1274*9880d681SAndroid Build Coastguard Worker if (RetVT != MVT::i32 && RetVT != MVT::i64)
1275*9880d681SAndroid Build Coastguard Worker return 0;
1276*9880d681SAndroid Build Coastguard Worker
1277*9880d681SAndroid Build Coastguard Worker unsigned ShiftImm;
1278*9880d681SAndroid Build Coastguard Worker if (isUInt<12>(Imm))
1279*9880d681SAndroid Build Coastguard Worker ShiftImm = 0;
1280*9880d681SAndroid Build Coastguard Worker else if ((Imm & 0xfff000) == Imm) {
1281*9880d681SAndroid Build Coastguard Worker ShiftImm = 12;
1282*9880d681SAndroid Build Coastguard Worker Imm >>= 12;
1283*9880d681SAndroid Build Coastguard Worker } else
1284*9880d681SAndroid Build Coastguard Worker return 0;
1285*9880d681SAndroid Build Coastguard Worker
1286*9880d681SAndroid Build Coastguard Worker static const unsigned OpcTable[2][2][2] = {
1287*9880d681SAndroid Build Coastguard Worker { { AArch64::SUBWri, AArch64::SUBXri },
1288*9880d681SAndroid Build Coastguard Worker { AArch64::ADDWri, AArch64::ADDXri } },
1289*9880d681SAndroid Build Coastguard Worker { { AArch64::SUBSWri, AArch64::SUBSXri },
1290*9880d681SAndroid Build Coastguard Worker { AArch64::ADDSWri, AArch64::ADDSXri } }
1291*9880d681SAndroid Build Coastguard Worker };
1292*9880d681SAndroid Build Coastguard Worker bool Is64Bit = RetVT == MVT::i64;
1293*9880d681SAndroid Build Coastguard Worker unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1294*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC;
1295*9880d681SAndroid Build Coastguard Worker if (SetFlags)
1296*9880d681SAndroid Build Coastguard Worker RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1297*9880d681SAndroid Build Coastguard Worker else
1298*9880d681SAndroid Build Coastguard Worker RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1299*9880d681SAndroid Build Coastguard Worker unsigned ResultReg;
1300*9880d681SAndroid Build Coastguard Worker if (WantResult)
1301*9880d681SAndroid Build Coastguard Worker ResultReg = createResultReg(RC);
1302*9880d681SAndroid Build Coastguard Worker else
1303*9880d681SAndroid Build Coastguard Worker ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1304*9880d681SAndroid Build Coastguard Worker
1305*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &II = TII.get(Opc);
1306*9880d681SAndroid Build Coastguard Worker LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
1307*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
1308*9880d681SAndroid Build Coastguard Worker .addReg(LHSReg, getKillRegState(LHSIsKill))
1309*9880d681SAndroid Build Coastguard Worker .addImm(Imm)
1310*9880d681SAndroid Build Coastguard Worker .addImm(getShifterImm(AArch64_AM::LSL, ShiftImm));
1311*9880d681SAndroid Build Coastguard Worker return ResultReg;
1312*9880d681SAndroid Build Coastguard Worker }
1313*9880d681SAndroid Build Coastguard Worker
emitAddSub_rs(bool UseAdd,MVT RetVT,unsigned LHSReg,bool LHSIsKill,unsigned RHSReg,bool RHSIsKill,AArch64_AM::ShiftExtendType ShiftType,uint64_t ShiftImm,bool SetFlags,bool WantResult)1314*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitAddSub_rs(bool UseAdd, MVT RetVT, unsigned LHSReg,
1315*9880d681SAndroid Build Coastguard Worker bool LHSIsKill, unsigned RHSReg,
1316*9880d681SAndroid Build Coastguard Worker bool RHSIsKill,
1317*9880d681SAndroid Build Coastguard Worker AArch64_AM::ShiftExtendType ShiftType,
1318*9880d681SAndroid Build Coastguard Worker uint64_t ShiftImm, bool SetFlags,
1319*9880d681SAndroid Build Coastguard Worker bool WantResult) {
1320*9880d681SAndroid Build Coastguard Worker assert(LHSReg && RHSReg && "Invalid register number.");
1321*9880d681SAndroid Build Coastguard Worker
1322*9880d681SAndroid Build Coastguard Worker if (RetVT != MVT::i32 && RetVT != MVT::i64)
1323*9880d681SAndroid Build Coastguard Worker return 0;
1324*9880d681SAndroid Build Coastguard Worker
1325*9880d681SAndroid Build Coastguard Worker // Don't deal with undefined shifts.
1326*9880d681SAndroid Build Coastguard Worker if (ShiftImm >= RetVT.getSizeInBits())
1327*9880d681SAndroid Build Coastguard Worker return 0;
1328*9880d681SAndroid Build Coastguard Worker
1329*9880d681SAndroid Build Coastguard Worker static const unsigned OpcTable[2][2][2] = {
1330*9880d681SAndroid Build Coastguard Worker { { AArch64::SUBWrs, AArch64::SUBXrs },
1331*9880d681SAndroid Build Coastguard Worker { AArch64::ADDWrs, AArch64::ADDXrs } },
1332*9880d681SAndroid Build Coastguard Worker { { AArch64::SUBSWrs, AArch64::SUBSXrs },
1333*9880d681SAndroid Build Coastguard Worker { AArch64::ADDSWrs, AArch64::ADDSXrs } }
1334*9880d681SAndroid Build Coastguard Worker };
1335*9880d681SAndroid Build Coastguard Worker bool Is64Bit = RetVT == MVT::i64;
1336*9880d681SAndroid Build Coastguard Worker unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1337*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC =
1338*9880d681SAndroid Build Coastguard Worker Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1339*9880d681SAndroid Build Coastguard Worker unsigned ResultReg;
1340*9880d681SAndroid Build Coastguard Worker if (WantResult)
1341*9880d681SAndroid Build Coastguard Worker ResultReg = createResultReg(RC);
1342*9880d681SAndroid Build Coastguard Worker else
1343*9880d681SAndroid Build Coastguard Worker ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1344*9880d681SAndroid Build Coastguard Worker
1345*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &II = TII.get(Opc);
1346*9880d681SAndroid Build Coastguard Worker LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
1347*9880d681SAndroid Build Coastguard Worker RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
1348*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
1349*9880d681SAndroid Build Coastguard Worker .addReg(LHSReg, getKillRegState(LHSIsKill))
1350*9880d681SAndroid Build Coastguard Worker .addReg(RHSReg, getKillRegState(RHSIsKill))
1351*9880d681SAndroid Build Coastguard Worker .addImm(getShifterImm(ShiftType, ShiftImm));
1352*9880d681SAndroid Build Coastguard Worker return ResultReg;
1353*9880d681SAndroid Build Coastguard Worker }
1354*9880d681SAndroid Build Coastguard Worker
emitAddSub_rx(bool UseAdd,MVT RetVT,unsigned LHSReg,bool LHSIsKill,unsigned RHSReg,bool RHSIsKill,AArch64_AM::ShiftExtendType ExtType,uint64_t ShiftImm,bool SetFlags,bool WantResult)1355*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitAddSub_rx(bool UseAdd, MVT RetVT, unsigned LHSReg,
1356*9880d681SAndroid Build Coastguard Worker bool LHSIsKill, unsigned RHSReg,
1357*9880d681SAndroid Build Coastguard Worker bool RHSIsKill,
1358*9880d681SAndroid Build Coastguard Worker AArch64_AM::ShiftExtendType ExtType,
1359*9880d681SAndroid Build Coastguard Worker uint64_t ShiftImm, bool SetFlags,
1360*9880d681SAndroid Build Coastguard Worker bool WantResult) {
1361*9880d681SAndroid Build Coastguard Worker assert(LHSReg && RHSReg && "Invalid register number.");
1362*9880d681SAndroid Build Coastguard Worker
1363*9880d681SAndroid Build Coastguard Worker if (RetVT != MVT::i32 && RetVT != MVT::i64)
1364*9880d681SAndroid Build Coastguard Worker return 0;
1365*9880d681SAndroid Build Coastguard Worker
1366*9880d681SAndroid Build Coastguard Worker if (ShiftImm >= 4)
1367*9880d681SAndroid Build Coastguard Worker return 0;
1368*9880d681SAndroid Build Coastguard Worker
1369*9880d681SAndroid Build Coastguard Worker static const unsigned OpcTable[2][2][2] = {
1370*9880d681SAndroid Build Coastguard Worker { { AArch64::SUBWrx, AArch64::SUBXrx },
1371*9880d681SAndroid Build Coastguard Worker { AArch64::ADDWrx, AArch64::ADDXrx } },
1372*9880d681SAndroid Build Coastguard Worker { { AArch64::SUBSWrx, AArch64::SUBSXrx },
1373*9880d681SAndroid Build Coastguard Worker { AArch64::ADDSWrx, AArch64::ADDSXrx } }
1374*9880d681SAndroid Build Coastguard Worker };
1375*9880d681SAndroid Build Coastguard Worker bool Is64Bit = RetVT == MVT::i64;
1376*9880d681SAndroid Build Coastguard Worker unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1377*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = nullptr;
1378*9880d681SAndroid Build Coastguard Worker if (SetFlags)
1379*9880d681SAndroid Build Coastguard Worker RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1380*9880d681SAndroid Build Coastguard Worker else
1381*9880d681SAndroid Build Coastguard Worker RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1382*9880d681SAndroid Build Coastguard Worker unsigned ResultReg;
1383*9880d681SAndroid Build Coastguard Worker if (WantResult)
1384*9880d681SAndroid Build Coastguard Worker ResultReg = createResultReg(RC);
1385*9880d681SAndroid Build Coastguard Worker else
1386*9880d681SAndroid Build Coastguard Worker ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1387*9880d681SAndroid Build Coastguard Worker
1388*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &II = TII.get(Opc);
1389*9880d681SAndroid Build Coastguard Worker LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
1390*9880d681SAndroid Build Coastguard Worker RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
1391*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
1392*9880d681SAndroid Build Coastguard Worker .addReg(LHSReg, getKillRegState(LHSIsKill))
1393*9880d681SAndroid Build Coastguard Worker .addReg(RHSReg, getKillRegState(RHSIsKill))
1394*9880d681SAndroid Build Coastguard Worker .addImm(getArithExtendImm(ExtType, ShiftImm));
1395*9880d681SAndroid Build Coastguard Worker return ResultReg;
1396*9880d681SAndroid Build Coastguard Worker }
1397*9880d681SAndroid Build Coastguard Worker
emitCmp(const Value * LHS,const Value * RHS,bool IsZExt)1398*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::emitCmp(const Value *LHS, const Value *RHS, bool IsZExt) {
1399*9880d681SAndroid Build Coastguard Worker Type *Ty = LHS->getType();
1400*9880d681SAndroid Build Coastguard Worker EVT EVT = TLI.getValueType(DL, Ty, true);
1401*9880d681SAndroid Build Coastguard Worker if (!EVT.isSimple())
1402*9880d681SAndroid Build Coastguard Worker return false;
1403*9880d681SAndroid Build Coastguard Worker MVT VT = EVT.getSimpleVT();
1404*9880d681SAndroid Build Coastguard Worker
1405*9880d681SAndroid Build Coastguard Worker switch (VT.SimpleTy) {
1406*9880d681SAndroid Build Coastguard Worker default:
1407*9880d681SAndroid Build Coastguard Worker return false;
1408*9880d681SAndroid Build Coastguard Worker case MVT::i1:
1409*9880d681SAndroid Build Coastguard Worker case MVT::i8:
1410*9880d681SAndroid Build Coastguard Worker case MVT::i16:
1411*9880d681SAndroid Build Coastguard Worker case MVT::i32:
1412*9880d681SAndroid Build Coastguard Worker case MVT::i64:
1413*9880d681SAndroid Build Coastguard Worker return emitICmp(VT, LHS, RHS, IsZExt);
1414*9880d681SAndroid Build Coastguard Worker case MVT::f32:
1415*9880d681SAndroid Build Coastguard Worker case MVT::f64:
1416*9880d681SAndroid Build Coastguard Worker return emitFCmp(VT, LHS, RHS);
1417*9880d681SAndroid Build Coastguard Worker }
1418*9880d681SAndroid Build Coastguard Worker }
1419*9880d681SAndroid Build Coastguard Worker
emitICmp(MVT RetVT,const Value * LHS,const Value * RHS,bool IsZExt)1420*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::emitICmp(MVT RetVT, const Value *LHS, const Value *RHS,
1421*9880d681SAndroid Build Coastguard Worker bool IsZExt) {
1422*9880d681SAndroid Build Coastguard Worker return emitSub(RetVT, LHS, RHS, /*SetFlags=*/true, /*WantResult=*/false,
1423*9880d681SAndroid Build Coastguard Worker IsZExt) != 0;
1424*9880d681SAndroid Build Coastguard Worker }
1425*9880d681SAndroid Build Coastguard Worker
emitICmp_ri(MVT RetVT,unsigned LHSReg,bool LHSIsKill,uint64_t Imm)1426*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::emitICmp_ri(MVT RetVT, unsigned LHSReg, bool LHSIsKill,
1427*9880d681SAndroid Build Coastguard Worker uint64_t Imm) {
1428*9880d681SAndroid Build Coastguard Worker return emitAddSub_ri(/*UseAdd=*/false, RetVT, LHSReg, LHSIsKill, Imm,
1429*9880d681SAndroid Build Coastguard Worker /*SetFlags=*/true, /*WantResult=*/false) != 0;
1430*9880d681SAndroid Build Coastguard Worker }
1431*9880d681SAndroid Build Coastguard Worker
emitFCmp(MVT RetVT,const Value * LHS,const Value * RHS)1432*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::emitFCmp(MVT RetVT, const Value *LHS, const Value *RHS) {
1433*9880d681SAndroid Build Coastguard Worker if (RetVT != MVT::f32 && RetVT != MVT::f64)
1434*9880d681SAndroid Build Coastguard Worker return false;
1435*9880d681SAndroid Build Coastguard Worker
1436*9880d681SAndroid Build Coastguard Worker // Check to see if the 2nd operand is a constant that we can encode directly
1437*9880d681SAndroid Build Coastguard Worker // in the compare.
1438*9880d681SAndroid Build Coastguard Worker bool UseImm = false;
1439*9880d681SAndroid Build Coastguard Worker if (const auto *CFP = dyn_cast<ConstantFP>(RHS))
1440*9880d681SAndroid Build Coastguard Worker if (CFP->isZero() && !CFP->isNegative())
1441*9880d681SAndroid Build Coastguard Worker UseImm = true;
1442*9880d681SAndroid Build Coastguard Worker
1443*9880d681SAndroid Build Coastguard Worker unsigned LHSReg = getRegForValue(LHS);
1444*9880d681SAndroid Build Coastguard Worker if (!LHSReg)
1445*9880d681SAndroid Build Coastguard Worker return false;
1446*9880d681SAndroid Build Coastguard Worker bool LHSIsKill = hasTrivialKill(LHS);
1447*9880d681SAndroid Build Coastguard Worker
1448*9880d681SAndroid Build Coastguard Worker if (UseImm) {
1449*9880d681SAndroid Build Coastguard Worker unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDri : AArch64::FCMPSri;
1450*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1451*9880d681SAndroid Build Coastguard Worker .addReg(LHSReg, getKillRegState(LHSIsKill));
1452*9880d681SAndroid Build Coastguard Worker return true;
1453*9880d681SAndroid Build Coastguard Worker }
1454*9880d681SAndroid Build Coastguard Worker
1455*9880d681SAndroid Build Coastguard Worker unsigned RHSReg = getRegForValue(RHS);
1456*9880d681SAndroid Build Coastguard Worker if (!RHSReg)
1457*9880d681SAndroid Build Coastguard Worker return false;
1458*9880d681SAndroid Build Coastguard Worker bool RHSIsKill = hasTrivialKill(RHS);
1459*9880d681SAndroid Build Coastguard Worker
1460*9880d681SAndroid Build Coastguard Worker unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDrr : AArch64::FCMPSrr;
1461*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1462*9880d681SAndroid Build Coastguard Worker .addReg(LHSReg, getKillRegState(LHSIsKill))
1463*9880d681SAndroid Build Coastguard Worker .addReg(RHSReg, getKillRegState(RHSIsKill));
1464*9880d681SAndroid Build Coastguard Worker return true;
1465*9880d681SAndroid Build Coastguard Worker }
1466*9880d681SAndroid Build Coastguard Worker
emitAdd(MVT RetVT,const Value * LHS,const Value * RHS,bool SetFlags,bool WantResult,bool IsZExt)1467*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitAdd(MVT RetVT, const Value *LHS, const Value *RHS,
1468*9880d681SAndroid Build Coastguard Worker bool SetFlags, bool WantResult, bool IsZExt) {
1469*9880d681SAndroid Build Coastguard Worker return emitAddSub(/*UseAdd=*/true, RetVT, LHS, RHS, SetFlags, WantResult,
1470*9880d681SAndroid Build Coastguard Worker IsZExt);
1471*9880d681SAndroid Build Coastguard Worker }
1472*9880d681SAndroid Build Coastguard Worker
1473*9880d681SAndroid Build Coastguard Worker /// \brief This method is a wrapper to simplify add emission.
1474*9880d681SAndroid Build Coastguard Worker ///
1475*9880d681SAndroid Build Coastguard Worker /// First try to emit an add with an immediate operand using emitAddSub_ri. If
1476*9880d681SAndroid Build Coastguard Worker /// that fails, then try to materialize the immediate into a register and use
1477*9880d681SAndroid Build Coastguard Worker /// emitAddSub_rr instead.
emitAdd_ri_(MVT VT,unsigned Op0,bool Op0IsKill,int64_t Imm)1478*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitAdd_ri_(MVT VT, unsigned Op0, bool Op0IsKill,
1479*9880d681SAndroid Build Coastguard Worker int64_t Imm) {
1480*9880d681SAndroid Build Coastguard Worker unsigned ResultReg;
1481*9880d681SAndroid Build Coastguard Worker if (Imm < 0)
1482*9880d681SAndroid Build Coastguard Worker ResultReg = emitAddSub_ri(false, VT, Op0, Op0IsKill, -Imm);
1483*9880d681SAndroid Build Coastguard Worker else
1484*9880d681SAndroid Build Coastguard Worker ResultReg = emitAddSub_ri(true, VT, Op0, Op0IsKill, Imm);
1485*9880d681SAndroid Build Coastguard Worker
1486*9880d681SAndroid Build Coastguard Worker if (ResultReg)
1487*9880d681SAndroid Build Coastguard Worker return ResultReg;
1488*9880d681SAndroid Build Coastguard Worker
1489*9880d681SAndroid Build Coastguard Worker unsigned CReg = fastEmit_i(VT, VT, ISD::Constant, Imm);
1490*9880d681SAndroid Build Coastguard Worker if (!CReg)
1491*9880d681SAndroid Build Coastguard Worker return 0;
1492*9880d681SAndroid Build Coastguard Worker
1493*9880d681SAndroid Build Coastguard Worker ResultReg = emitAddSub_rr(true, VT, Op0, Op0IsKill, CReg, true);
1494*9880d681SAndroid Build Coastguard Worker return ResultReg;
1495*9880d681SAndroid Build Coastguard Worker }
1496*9880d681SAndroid Build Coastguard Worker
emitSub(MVT RetVT,const Value * LHS,const Value * RHS,bool SetFlags,bool WantResult,bool IsZExt)1497*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitSub(MVT RetVT, const Value *LHS, const Value *RHS,
1498*9880d681SAndroid Build Coastguard Worker bool SetFlags, bool WantResult, bool IsZExt) {
1499*9880d681SAndroid Build Coastguard Worker return emitAddSub(/*UseAdd=*/false, RetVT, LHS, RHS, SetFlags, WantResult,
1500*9880d681SAndroid Build Coastguard Worker IsZExt);
1501*9880d681SAndroid Build Coastguard Worker }
1502*9880d681SAndroid Build Coastguard Worker
emitSubs_rr(MVT RetVT,unsigned LHSReg,bool LHSIsKill,unsigned RHSReg,bool RHSIsKill,bool WantResult)1503*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitSubs_rr(MVT RetVT, unsigned LHSReg,
1504*9880d681SAndroid Build Coastguard Worker bool LHSIsKill, unsigned RHSReg,
1505*9880d681SAndroid Build Coastguard Worker bool RHSIsKill, bool WantResult) {
1506*9880d681SAndroid Build Coastguard Worker return emitAddSub_rr(/*UseAdd=*/false, RetVT, LHSReg, LHSIsKill, RHSReg,
1507*9880d681SAndroid Build Coastguard Worker RHSIsKill, /*SetFlags=*/true, WantResult);
1508*9880d681SAndroid Build Coastguard Worker }
1509*9880d681SAndroid Build Coastguard Worker
emitSubs_rs(MVT RetVT,unsigned LHSReg,bool LHSIsKill,unsigned RHSReg,bool RHSIsKill,AArch64_AM::ShiftExtendType ShiftType,uint64_t ShiftImm,bool WantResult)1510*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitSubs_rs(MVT RetVT, unsigned LHSReg,
1511*9880d681SAndroid Build Coastguard Worker bool LHSIsKill, unsigned RHSReg,
1512*9880d681SAndroid Build Coastguard Worker bool RHSIsKill,
1513*9880d681SAndroid Build Coastguard Worker AArch64_AM::ShiftExtendType ShiftType,
1514*9880d681SAndroid Build Coastguard Worker uint64_t ShiftImm, bool WantResult) {
1515*9880d681SAndroid Build Coastguard Worker return emitAddSub_rs(/*UseAdd=*/false, RetVT, LHSReg, LHSIsKill, RHSReg,
1516*9880d681SAndroid Build Coastguard Worker RHSIsKill, ShiftType, ShiftImm, /*SetFlags=*/true,
1517*9880d681SAndroid Build Coastguard Worker WantResult);
1518*9880d681SAndroid Build Coastguard Worker }
1519*9880d681SAndroid Build Coastguard Worker
emitLogicalOp(unsigned ISDOpc,MVT RetVT,const Value * LHS,const Value * RHS)1520*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitLogicalOp(unsigned ISDOpc, MVT RetVT,
1521*9880d681SAndroid Build Coastguard Worker const Value *LHS, const Value *RHS) {
1522*9880d681SAndroid Build Coastguard Worker // Canonicalize immediates to the RHS first.
1523*9880d681SAndroid Build Coastguard Worker if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS))
1524*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
1525*9880d681SAndroid Build Coastguard Worker
1526*9880d681SAndroid Build Coastguard Worker // Canonicalize mul by power-of-2 to the RHS.
1527*9880d681SAndroid Build Coastguard Worker if (LHS->hasOneUse() && isValueAvailable(LHS))
1528*9880d681SAndroid Build Coastguard Worker if (isMulPowOf2(LHS))
1529*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
1530*9880d681SAndroid Build Coastguard Worker
1531*9880d681SAndroid Build Coastguard Worker // Canonicalize shift immediate to the RHS.
1532*9880d681SAndroid Build Coastguard Worker if (LHS->hasOneUse() && isValueAvailable(LHS))
1533*9880d681SAndroid Build Coastguard Worker if (const auto *SI = dyn_cast<ShlOperator>(LHS))
1534*9880d681SAndroid Build Coastguard Worker if (isa<ConstantInt>(SI->getOperand(1)))
1535*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
1536*9880d681SAndroid Build Coastguard Worker
1537*9880d681SAndroid Build Coastguard Worker unsigned LHSReg = getRegForValue(LHS);
1538*9880d681SAndroid Build Coastguard Worker if (!LHSReg)
1539*9880d681SAndroid Build Coastguard Worker return 0;
1540*9880d681SAndroid Build Coastguard Worker bool LHSIsKill = hasTrivialKill(LHS);
1541*9880d681SAndroid Build Coastguard Worker
1542*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = 0;
1543*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(RHS)) {
1544*9880d681SAndroid Build Coastguard Worker uint64_t Imm = C->getZExtValue();
1545*9880d681SAndroid Build Coastguard Worker ResultReg = emitLogicalOp_ri(ISDOpc, RetVT, LHSReg, LHSIsKill, Imm);
1546*9880d681SAndroid Build Coastguard Worker }
1547*9880d681SAndroid Build Coastguard Worker if (ResultReg)
1548*9880d681SAndroid Build Coastguard Worker return ResultReg;
1549*9880d681SAndroid Build Coastguard Worker
1550*9880d681SAndroid Build Coastguard Worker // Check if the mul can be folded into the instruction.
1551*9880d681SAndroid Build Coastguard Worker if (RHS->hasOneUse() && isValueAvailable(RHS)) {
1552*9880d681SAndroid Build Coastguard Worker if (isMulPowOf2(RHS)) {
1553*9880d681SAndroid Build Coastguard Worker const Value *MulLHS = cast<MulOperator>(RHS)->getOperand(0);
1554*9880d681SAndroid Build Coastguard Worker const Value *MulRHS = cast<MulOperator>(RHS)->getOperand(1);
1555*9880d681SAndroid Build Coastguard Worker
1556*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(MulLHS))
1557*9880d681SAndroid Build Coastguard Worker if (C->getValue().isPowerOf2())
1558*9880d681SAndroid Build Coastguard Worker std::swap(MulLHS, MulRHS);
1559*9880d681SAndroid Build Coastguard Worker
1560*9880d681SAndroid Build Coastguard Worker assert(isa<ConstantInt>(MulRHS) && "Expected a ConstantInt.");
1561*9880d681SAndroid Build Coastguard Worker uint64_t ShiftVal = cast<ConstantInt>(MulRHS)->getValue().logBase2();
1562*9880d681SAndroid Build Coastguard Worker
1563*9880d681SAndroid Build Coastguard Worker unsigned RHSReg = getRegForValue(MulLHS);
1564*9880d681SAndroid Build Coastguard Worker if (!RHSReg)
1565*9880d681SAndroid Build Coastguard Worker return 0;
1566*9880d681SAndroid Build Coastguard Worker bool RHSIsKill = hasTrivialKill(MulLHS);
1567*9880d681SAndroid Build Coastguard Worker ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, LHSIsKill, RHSReg,
1568*9880d681SAndroid Build Coastguard Worker RHSIsKill, ShiftVal);
1569*9880d681SAndroid Build Coastguard Worker if (ResultReg)
1570*9880d681SAndroid Build Coastguard Worker return ResultReg;
1571*9880d681SAndroid Build Coastguard Worker }
1572*9880d681SAndroid Build Coastguard Worker }
1573*9880d681SAndroid Build Coastguard Worker
1574*9880d681SAndroid Build Coastguard Worker // Check if the shift can be folded into the instruction.
1575*9880d681SAndroid Build Coastguard Worker if (RHS->hasOneUse() && isValueAvailable(RHS)) {
1576*9880d681SAndroid Build Coastguard Worker if (const auto *SI = dyn_cast<ShlOperator>(RHS))
1577*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1))) {
1578*9880d681SAndroid Build Coastguard Worker uint64_t ShiftVal = C->getZExtValue();
1579*9880d681SAndroid Build Coastguard Worker unsigned RHSReg = getRegForValue(SI->getOperand(0));
1580*9880d681SAndroid Build Coastguard Worker if (!RHSReg)
1581*9880d681SAndroid Build Coastguard Worker return 0;
1582*9880d681SAndroid Build Coastguard Worker bool RHSIsKill = hasTrivialKill(SI->getOperand(0));
1583*9880d681SAndroid Build Coastguard Worker ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, LHSIsKill, RHSReg,
1584*9880d681SAndroid Build Coastguard Worker RHSIsKill, ShiftVal);
1585*9880d681SAndroid Build Coastguard Worker if (ResultReg)
1586*9880d681SAndroid Build Coastguard Worker return ResultReg;
1587*9880d681SAndroid Build Coastguard Worker }
1588*9880d681SAndroid Build Coastguard Worker }
1589*9880d681SAndroid Build Coastguard Worker
1590*9880d681SAndroid Build Coastguard Worker unsigned RHSReg = getRegForValue(RHS);
1591*9880d681SAndroid Build Coastguard Worker if (!RHSReg)
1592*9880d681SAndroid Build Coastguard Worker return 0;
1593*9880d681SAndroid Build Coastguard Worker bool RHSIsKill = hasTrivialKill(RHS);
1594*9880d681SAndroid Build Coastguard Worker
1595*9880d681SAndroid Build Coastguard Worker MVT VT = std::max(MVT::i32, RetVT.SimpleTy);
1596*9880d681SAndroid Build Coastguard Worker ResultReg = fastEmit_rr(VT, VT, ISDOpc, LHSReg, LHSIsKill, RHSReg, RHSIsKill);
1597*9880d681SAndroid Build Coastguard Worker if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1598*9880d681SAndroid Build Coastguard Worker uint64_t Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1599*9880d681SAndroid Build Coastguard Worker ResultReg = emitAnd_ri(MVT::i32, ResultReg, /*IsKill=*/true, Mask);
1600*9880d681SAndroid Build Coastguard Worker }
1601*9880d681SAndroid Build Coastguard Worker return ResultReg;
1602*9880d681SAndroid Build Coastguard Worker }
1603*9880d681SAndroid Build Coastguard Worker
emitLogicalOp_ri(unsigned ISDOpc,MVT RetVT,unsigned LHSReg,bool LHSIsKill,uint64_t Imm)1604*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitLogicalOp_ri(unsigned ISDOpc, MVT RetVT,
1605*9880d681SAndroid Build Coastguard Worker unsigned LHSReg, bool LHSIsKill,
1606*9880d681SAndroid Build Coastguard Worker uint64_t Imm) {
1607*9880d681SAndroid Build Coastguard Worker static_assert((ISD::AND + 1 == ISD::OR) && (ISD::AND + 2 == ISD::XOR),
1608*9880d681SAndroid Build Coastguard Worker "ISD nodes are not consecutive!");
1609*9880d681SAndroid Build Coastguard Worker static const unsigned OpcTable[3][2] = {
1610*9880d681SAndroid Build Coastguard Worker { AArch64::ANDWri, AArch64::ANDXri },
1611*9880d681SAndroid Build Coastguard Worker { AArch64::ORRWri, AArch64::ORRXri },
1612*9880d681SAndroid Build Coastguard Worker { AArch64::EORWri, AArch64::EORXri }
1613*9880d681SAndroid Build Coastguard Worker };
1614*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC;
1615*9880d681SAndroid Build Coastguard Worker unsigned Opc;
1616*9880d681SAndroid Build Coastguard Worker unsigned RegSize;
1617*9880d681SAndroid Build Coastguard Worker switch (RetVT.SimpleTy) {
1618*9880d681SAndroid Build Coastguard Worker default:
1619*9880d681SAndroid Build Coastguard Worker return 0;
1620*9880d681SAndroid Build Coastguard Worker case MVT::i1:
1621*9880d681SAndroid Build Coastguard Worker case MVT::i8:
1622*9880d681SAndroid Build Coastguard Worker case MVT::i16:
1623*9880d681SAndroid Build Coastguard Worker case MVT::i32: {
1624*9880d681SAndroid Build Coastguard Worker unsigned Idx = ISDOpc - ISD::AND;
1625*9880d681SAndroid Build Coastguard Worker Opc = OpcTable[Idx][0];
1626*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR32spRegClass;
1627*9880d681SAndroid Build Coastguard Worker RegSize = 32;
1628*9880d681SAndroid Build Coastguard Worker break;
1629*9880d681SAndroid Build Coastguard Worker }
1630*9880d681SAndroid Build Coastguard Worker case MVT::i64:
1631*9880d681SAndroid Build Coastguard Worker Opc = OpcTable[ISDOpc - ISD::AND][1];
1632*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR64spRegClass;
1633*9880d681SAndroid Build Coastguard Worker RegSize = 64;
1634*9880d681SAndroid Build Coastguard Worker break;
1635*9880d681SAndroid Build Coastguard Worker }
1636*9880d681SAndroid Build Coastguard Worker
1637*9880d681SAndroid Build Coastguard Worker if (!AArch64_AM::isLogicalImmediate(Imm, RegSize))
1638*9880d681SAndroid Build Coastguard Worker return 0;
1639*9880d681SAndroid Build Coastguard Worker
1640*9880d681SAndroid Build Coastguard Worker unsigned ResultReg =
1641*9880d681SAndroid Build Coastguard Worker fastEmitInst_ri(Opc, RC, LHSReg, LHSIsKill,
1642*9880d681SAndroid Build Coastguard Worker AArch64_AM::encodeLogicalImmediate(Imm, RegSize));
1643*9880d681SAndroid Build Coastguard Worker if (RetVT >= MVT::i8 && RetVT <= MVT::i16 && ISDOpc != ISD::AND) {
1644*9880d681SAndroid Build Coastguard Worker uint64_t Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1645*9880d681SAndroid Build Coastguard Worker ResultReg = emitAnd_ri(MVT::i32, ResultReg, /*IsKill=*/true, Mask);
1646*9880d681SAndroid Build Coastguard Worker }
1647*9880d681SAndroid Build Coastguard Worker return ResultReg;
1648*9880d681SAndroid Build Coastguard Worker }
1649*9880d681SAndroid Build Coastguard Worker
emitLogicalOp_rs(unsigned ISDOpc,MVT RetVT,unsigned LHSReg,bool LHSIsKill,unsigned RHSReg,bool RHSIsKill,uint64_t ShiftImm)1650*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitLogicalOp_rs(unsigned ISDOpc, MVT RetVT,
1651*9880d681SAndroid Build Coastguard Worker unsigned LHSReg, bool LHSIsKill,
1652*9880d681SAndroid Build Coastguard Worker unsigned RHSReg, bool RHSIsKill,
1653*9880d681SAndroid Build Coastguard Worker uint64_t ShiftImm) {
1654*9880d681SAndroid Build Coastguard Worker static_assert((ISD::AND + 1 == ISD::OR) && (ISD::AND + 2 == ISD::XOR),
1655*9880d681SAndroid Build Coastguard Worker "ISD nodes are not consecutive!");
1656*9880d681SAndroid Build Coastguard Worker static const unsigned OpcTable[3][2] = {
1657*9880d681SAndroid Build Coastguard Worker { AArch64::ANDWrs, AArch64::ANDXrs },
1658*9880d681SAndroid Build Coastguard Worker { AArch64::ORRWrs, AArch64::ORRXrs },
1659*9880d681SAndroid Build Coastguard Worker { AArch64::EORWrs, AArch64::EORXrs }
1660*9880d681SAndroid Build Coastguard Worker };
1661*9880d681SAndroid Build Coastguard Worker
1662*9880d681SAndroid Build Coastguard Worker // Don't deal with undefined shifts.
1663*9880d681SAndroid Build Coastguard Worker if (ShiftImm >= RetVT.getSizeInBits())
1664*9880d681SAndroid Build Coastguard Worker return 0;
1665*9880d681SAndroid Build Coastguard Worker
1666*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC;
1667*9880d681SAndroid Build Coastguard Worker unsigned Opc;
1668*9880d681SAndroid Build Coastguard Worker switch (RetVT.SimpleTy) {
1669*9880d681SAndroid Build Coastguard Worker default:
1670*9880d681SAndroid Build Coastguard Worker return 0;
1671*9880d681SAndroid Build Coastguard Worker case MVT::i1:
1672*9880d681SAndroid Build Coastguard Worker case MVT::i8:
1673*9880d681SAndroid Build Coastguard Worker case MVT::i16:
1674*9880d681SAndroid Build Coastguard Worker case MVT::i32:
1675*9880d681SAndroid Build Coastguard Worker Opc = OpcTable[ISDOpc - ISD::AND][0];
1676*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR32RegClass;
1677*9880d681SAndroid Build Coastguard Worker break;
1678*9880d681SAndroid Build Coastguard Worker case MVT::i64:
1679*9880d681SAndroid Build Coastguard Worker Opc = OpcTable[ISDOpc - ISD::AND][1];
1680*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR64RegClass;
1681*9880d681SAndroid Build Coastguard Worker break;
1682*9880d681SAndroid Build Coastguard Worker }
1683*9880d681SAndroid Build Coastguard Worker unsigned ResultReg =
1684*9880d681SAndroid Build Coastguard Worker fastEmitInst_rri(Opc, RC, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
1685*9880d681SAndroid Build Coastguard Worker AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftImm));
1686*9880d681SAndroid Build Coastguard Worker if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1687*9880d681SAndroid Build Coastguard Worker uint64_t Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1688*9880d681SAndroid Build Coastguard Worker ResultReg = emitAnd_ri(MVT::i32, ResultReg, /*IsKill=*/true, Mask);
1689*9880d681SAndroid Build Coastguard Worker }
1690*9880d681SAndroid Build Coastguard Worker return ResultReg;
1691*9880d681SAndroid Build Coastguard Worker }
1692*9880d681SAndroid Build Coastguard Worker
emitAnd_ri(MVT RetVT,unsigned LHSReg,bool LHSIsKill,uint64_t Imm)1693*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitAnd_ri(MVT RetVT, unsigned LHSReg, bool LHSIsKill,
1694*9880d681SAndroid Build Coastguard Worker uint64_t Imm) {
1695*9880d681SAndroid Build Coastguard Worker return emitLogicalOp_ri(ISD::AND, RetVT, LHSReg, LHSIsKill, Imm);
1696*9880d681SAndroid Build Coastguard Worker }
1697*9880d681SAndroid Build Coastguard Worker
emitLoad(MVT VT,MVT RetVT,Address Addr,bool WantZExt,MachineMemOperand * MMO)1698*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitLoad(MVT VT, MVT RetVT, Address Addr,
1699*9880d681SAndroid Build Coastguard Worker bool WantZExt, MachineMemOperand *MMO) {
1700*9880d681SAndroid Build Coastguard Worker if (!TLI.allowsMisalignedMemoryAccesses(VT))
1701*9880d681SAndroid Build Coastguard Worker return 0;
1702*9880d681SAndroid Build Coastguard Worker
1703*9880d681SAndroid Build Coastguard Worker // Simplify this down to something we can handle.
1704*9880d681SAndroid Build Coastguard Worker if (!simplifyAddress(Addr, VT))
1705*9880d681SAndroid Build Coastguard Worker return 0;
1706*9880d681SAndroid Build Coastguard Worker
1707*9880d681SAndroid Build Coastguard Worker unsigned ScaleFactor = getImplicitScaleFactor(VT);
1708*9880d681SAndroid Build Coastguard Worker if (!ScaleFactor)
1709*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected value type.");
1710*9880d681SAndroid Build Coastguard Worker
1711*9880d681SAndroid Build Coastguard Worker // Negative offsets require unscaled, 9-bit, signed immediate offsets.
1712*9880d681SAndroid Build Coastguard Worker // Otherwise, we try using scaled, 12-bit, unsigned immediate offsets.
1713*9880d681SAndroid Build Coastguard Worker bool UseScaled = true;
1714*9880d681SAndroid Build Coastguard Worker if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
1715*9880d681SAndroid Build Coastguard Worker UseScaled = false;
1716*9880d681SAndroid Build Coastguard Worker ScaleFactor = 1;
1717*9880d681SAndroid Build Coastguard Worker }
1718*9880d681SAndroid Build Coastguard Worker
1719*9880d681SAndroid Build Coastguard Worker static const unsigned GPOpcTable[2][8][4] = {
1720*9880d681SAndroid Build Coastguard Worker // Sign-extend.
1721*9880d681SAndroid Build Coastguard Worker { { AArch64::LDURSBWi, AArch64::LDURSHWi, AArch64::LDURWi,
1722*9880d681SAndroid Build Coastguard Worker AArch64::LDURXi },
1723*9880d681SAndroid Build Coastguard Worker { AArch64::LDURSBXi, AArch64::LDURSHXi, AArch64::LDURSWi,
1724*9880d681SAndroid Build Coastguard Worker AArch64::LDURXi },
1725*9880d681SAndroid Build Coastguard Worker { AArch64::LDRSBWui, AArch64::LDRSHWui, AArch64::LDRWui,
1726*9880d681SAndroid Build Coastguard Worker AArch64::LDRXui },
1727*9880d681SAndroid Build Coastguard Worker { AArch64::LDRSBXui, AArch64::LDRSHXui, AArch64::LDRSWui,
1728*9880d681SAndroid Build Coastguard Worker AArch64::LDRXui },
1729*9880d681SAndroid Build Coastguard Worker { AArch64::LDRSBWroX, AArch64::LDRSHWroX, AArch64::LDRWroX,
1730*9880d681SAndroid Build Coastguard Worker AArch64::LDRXroX },
1731*9880d681SAndroid Build Coastguard Worker { AArch64::LDRSBXroX, AArch64::LDRSHXroX, AArch64::LDRSWroX,
1732*9880d681SAndroid Build Coastguard Worker AArch64::LDRXroX },
1733*9880d681SAndroid Build Coastguard Worker { AArch64::LDRSBWroW, AArch64::LDRSHWroW, AArch64::LDRWroW,
1734*9880d681SAndroid Build Coastguard Worker AArch64::LDRXroW },
1735*9880d681SAndroid Build Coastguard Worker { AArch64::LDRSBXroW, AArch64::LDRSHXroW, AArch64::LDRSWroW,
1736*9880d681SAndroid Build Coastguard Worker AArch64::LDRXroW }
1737*9880d681SAndroid Build Coastguard Worker },
1738*9880d681SAndroid Build Coastguard Worker // Zero-extend.
1739*9880d681SAndroid Build Coastguard Worker { { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1740*9880d681SAndroid Build Coastguard Worker AArch64::LDURXi },
1741*9880d681SAndroid Build Coastguard Worker { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1742*9880d681SAndroid Build Coastguard Worker AArch64::LDURXi },
1743*9880d681SAndroid Build Coastguard Worker { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1744*9880d681SAndroid Build Coastguard Worker AArch64::LDRXui },
1745*9880d681SAndroid Build Coastguard Worker { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1746*9880d681SAndroid Build Coastguard Worker AArch64::LDRXui },
1747*9880d681SAndroid Build Coastguard Worker { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1748*9880d681SAndroid Build Coastguard Worker AArch64::LDRXroX },
1749*9880d681SAndroid Build Coastguard Worker { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1750*9880d681SAndroid Build Coastguard Worker AArch64::LDRXroX },
1751*9880d681SAndroid Build Coastguard Worker { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1752*9880d681SAndroid Build Coastguard Worker AArch64::LDRXroW },
1753*9880d681SAndroid Build Coastguard Worker { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1754*9880d681SAndroid Build Coastguard Worker AArch64::LDRXroW }
1755*9880d681SAndroid Build Coastguard Worker }
1756*9880d681SAndroid Build Coastguard Worker };
1757*9880d681SAndroid Build Coastguard Worker
1758*9880d681SAndroid Build Coastguard Worker static const unsigned FPOpcTable[4][2] = {
1759*9880d681SAndroid Build Coastguard Worker { AArch64::LDURSi, AArch64::LDURDi },
1760*9880d681SAndroid Build Coastguard Worker { AArch64::LDRSui, AArch64::LDRDui },
1761*9880d681SAndroid Build Coastguard Worker { AArch64::LDRSroX, AArch64::LDRDroX },
1762*9880d681SAndroid Build Coastguard Worker { AArch64::LDRSroW, AArch64::LDRDroW }
1763*9880d681SAndroid Build Coastguard Worker };
1764*9880d681SAndroid Build Coastguard Worker
1765*9880d681SAndroid Build Coastguard Worker unsigned Opc;
1766*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC;
1767*9880d681SAndroid Build Coastguard Worker bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
1768*9880d681SAndroid Build Coastguard Worker Addr.getOffsetReg();
1769*9880d681SAndroid Build Coastguard Worker unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
1770*9880d681SAndroid Build Coastguard Worker if (Addr.getExtendType() == AArch64_AM::UXTW ||
1771*9880d681SAndroid Build Coastguard Worker Addr.getExtendType() == AArch64_AM::SXTW)
1772*9880d681SAndroid Build Coastguard Worker Idx++;
1773*9880d681SAndroid Build Coastguard Worker
1774*9880d681SAndroid Build Coastguard Worker bool IsRet64Bit = RetVT == MVT::i64;
1775*9880d681SAndroid Build Coastguard Worker switch (VT.SimpleTy) {
1776*9880d681SAndroid Build Coastguard Worker default:
1777*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected value type.");
1778*9880d681SAndroid Build Coastguard Worker case MVT::i1: // Intentional fall-through.
1779*9880d681SAndroid Build Coastguard Worker case MVT::i8:
1780*9880d681SAndroid Build Coastguard Worker Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][0];
1781*9880d681SAndroid Build Coastguard Worker RC = (IsRet64Bit && !WantZExt) ?
1782*9880d681SAndroid Build Coastguard Worker &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1783*9880d681SAndroid Build Coastguard Worker break;
1784*9880d681SAndroid Build Coastguard Worker case MVT::i16:
1785*9880d681SAndroid Build Coastguard Worker Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][1];
1786*9880d681SAndroid Build Coastguard Worker RC = (IsRet64Bit && !WantZExt) ?
1787*9880d681SAndroid Build Coastguard Worker &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1788*9880d681SAndroid Build Coastguard Worker break;
1789*9880d681SAndroid Build Coastguard Worker case MVT::i32:
1790*9880d681SAndroid Build Coastguard Worker Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][2];
1791*9880d681SAndroid Build Coastguard Worker RC = (IsRet64Bit && !WantZExt) ?
1792*9880d681SAndroid Build Coastguard Worker &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1793*9880d681SAndroid Build Coastguard Worker break;
1794*9880d681SAndroid Build Coastguard Worker case MVT::i64:
1795*9880d681SAndroid Build Coastguard Worker Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][3];
1796*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR64RegClass;
1797*9880d681SAndroid Build Coastguard Worker break;
1798*9880d681SAndroid Build Coastguard Worker case MVT::f32:
1799*9880d681SAndroid Build Coastguard Worker Opc = FPOpcTable[Idx][0];
1800*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR32RegClass;
1801*9880d681SAndroid Build Coastguard Worker break;
1802*9880d681SAndroid Build Coastguard Worker case MVT::f64:
1803*9880d681SAndroid Build Coastguard Worker Opc = FPOpcTable[Idx][1];
1804*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR64RegClass;
1805*9880d681SAndroid Build Coastguard Worker break;
1806*9880d681SAndroid Build Coastguard Worker }
1807*9880d681SAndroid Build Coastguard Worker
1808*9880d681SAndroid Build Coastguard Worker // Create the base instruction, then add the operands.
1809*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(RC);
1810*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1811*9880d681SAndroid Build Coastguard Worker TII.get(Opc), ResultReg);
1812*9880d681SAndroid Build Coastguard Worker addLoadStoreOperands(Addr, MIB, MachineMemOperand::MOLoad, ScaleFactor, MMO);
1813*9880d681SAndroid Build Coastguard Worker
1814*9880d681SAndroid Build Coastguard Worker // Loading an i1 requires special handling.
1815*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i1) {
1816*9880d681SAndroid Build Coastguard Worker unsigned ANDReg = emitAnd_ri(MVT::i32, ResultReg, /*IsKill=*/true, 1);
1817*9880d681SAndroid Build Coastguard Worker assert(ANDReg && "Unexpected AND instruction emission failure.");
1818*9880d681SAndroid Build Coastguard Worker ResultReg = ANDReg;
1819*9880d681SAndroid Build Coastguard Worker }
1820*9880d681SAndroid Build Coastguard Worker
1821*9880d681SAndroid Build Coastguard Worker // For zero-extending loads to 64bit we emit a 32bit load and then convert
1822*9880d681SAndroid Build Coastguard Worker // the 32bit reg to a 64bit reg.
1823*9880d681SAndroid Build Coastguard Worker if (WantZExt && RetVT == MVT::i64 && VT <= MVT::i32) {
1824*9880d681SAndroid Build Coastguard Worker unsigned Reg64 = createResultReg(&AArch64::GPR64RegClass);
1825*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1826*9880d681SAndroid Build Coastguard Worker TII.get(AArch64::SUBREG_TO_REG), Reg64)
1827*9880d681SAndroid Build Coastguard Worker .addImm(0)
1828*9880d681SAndroid Build Coastguard Worker .addReg(ResultReg, getKillRegState(true))
1829*9880d681SAndroid Build Coastguard Worker .addImm(AArch64::sub_32);
1830*9880d681SAndroid Build Coastguard Worker ResultReg = Reg64;
1831*9880d681SAndroid Build Coastguard Worker }
1832*9880d681SAndroid Build Coastguard Worker return ResultReg;
1833*9880d681SAndroid Build Coastguard Worker }
1834*9880d681SAndroid Build Coastguard Worker
selectAddSub(const Instruction * I)1835*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectAddSub(const Instruction *I) {
1836*9880d681SAndroid Build Coastguard Worker MVT VT;
1837*9880d681SAndroid Build Coastguard Worker if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true))
1838*9880d681SAndroid Build Coastguard Worker return false;
1839*9880d681SAndroid Build Coastguard Worker
1840*9880d681SAndroid Build Coastguard Worker if (VT.isVector())
1841*9880d681SAndroid Build Coastguard Worker return selectOperator(I, I->getOpcode());
1842*9880d681SAndroid Build Coastguard Worker
1843*9880d681SAndroid Build Coastguard Worker unsigned ResultReg;
1844*9880d681SAndroid Build Coastguard Worker switch (I->getOpcode()) {
1845*9880d681SAndroid Build Coastguard Worker default:
1846*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected instruction.");
1847*9880d681SAndroid Build Coastguard Worker case Instruction::Add:
1848*9880d681SAndroid Build Coastguard Worker ResultReg = emitAdd(VT, I->getOperand(0), I->getOperand(1));
1849*9880d681SAndroid Build Coastguard Worker break;
1850*9880d681SAndroid Build Coastguard Worker case Instruction::Sub:
1851*9880d681SAndroid Build Coastguard Worker ResultReg = emitSub(VT, I->getOperand(0), I->getOperand(1));
1852*9880d681SAndroid Build Coastguard Worker break;
1853*9880d681SAndroid Build Coastguard Worker }
1854*9880d681SAndroid Build Coastguard Worker if (!ResultReg)
1855*9880d681SAndroid Build Coastguard Worker return false;
1856*9880d681SAndroid Build Coastguard Worker
1857*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
1858*9880d681SAndroid Build Coastguard Worker return true;
1859*9880d681SAndroid Build Coastguard Worker }
1860*9880d681SAndroid Build Coastguard Worker
selectLogicalOp(const Instruction * I)1861*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectLogicalOp(const Instruction *I) {
1862*9880d681SAndroid Build Coastguard Worker MVT VT;
1863*9880d681SAndroid Build Coastguard Worker if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true))
1864*9880d681SAndroid Build Coastguard Worker return false;
1865*9880d681SAndroid Build Coastguard Worker
1866*9880d681SAndroid Build Coastguard Worker if (VT.isVector())
1867*9880d681SAndroid Build Coastguard Worker return selectOperator(I, I->getOpcode());
1868*9880d681SAndroid Build Coastguard Worker
1869*9880d681SAndroid Build Coastguard Worker unsigned ResultReg;
1870*9880d681SAndroid Build Coastguard Worker switch (I->getOpcode()) {
1871*9880d681SAndroid Build Coastguard Worker default:
1872*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected instruction.");
1873*9880d681SAndroid Build Coastguard Worker case Instruction::And:
1874*9880d681SAndroid Build Coastguard Worker ResultReg = emitLogicalOp(ISD::AND, VT, I->getOperand(0), I->getOperand(1));
1875*9880d681SAndroid Build Coastguard Worker break;
1876*9880d681SAndroid Build Coastguard Worker case Instruction::Or:
1877*9880d681SAndroid Build Coastguard Worker ResultReg = emitLogicalOp(ISD::OR, VT, I->getOperand(0), I->getOperand(1));
1878*9880d681SAndroid Build Coastguard Worker break;
1879*9880d681SAndroid Build Coastguard Worker case Instruction::Xor:
1880*9880d681SAndroid Build Coastguard Worker ResultReg = emitLogicalOp(ISD::XOR, VT, I->getOperand(0), I->getOperand(1));
1881*9880d681SAndroid Build Coastguard Worker break;
1882*9880d681SAndroid Build Coastguard Worker }
1883*9880d681SAndroid Build Coastguard Worker if (!ResultReg)
1884*9880d681SAndroid Build Coastguard Worker return false;
1885*9880d681SAndroid Build Coastguard Worker
1886*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
1887*9880d681SAndroid Build Coastguard Worker return true;
1888*9880d681SAndroid Build Coastguard Worker }
1889*9880d681SAndroid Build Coastguard Worker
selectLoad(const Instruction * I)1890*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectLoad(const Instruction *I) {
1891*9880d681SAndroid Build Coastguard Worker MVT VT;
1892*9880d681SAndroid Build Coastguard Worker // Verify we have a legal type before going any further. Currently, we handle
1893*9880d681SAndroid Build Coastguard Worker // simple types that will directly fit in a register (i32/f32/i64/f64) or
1894*9880d681SAndroid Build Coastguard Worker // those that can be sign or zero-extended to a basic operation (i1/i8/i16).
1895*9880d681SAndroid Build Coastguard Worker if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true) ||
1896*9880d681SAndroid Build Coastguard Worker cast<LoadInst>(I)->isAtomic())
1897*9880d681SAndroid Build Coastguard Worker return false;
1898*9880d681SAndroid Build Coastguard Worker
1899*9880d681SAndroid Build Coastguard Worker const Value *SV = I->getOperand(0);
1900*9880d681SAndroid Build Coastguard Worker if (TLI.supportSwiftError()) {
1901*9880d681SAndroid Build Coastguard Worker // Swifterror values can come from either a function parameter with
1902*9880d681SAndroid Build Coastguard Worker // swifterror attribute or an alloca with swifterror attribute.
1903*9880d681SAndroid Build Coastguard Worker if (const Argument *Arg = dyn_cast<Argument>(SV)) {
1904*9880d681SAndroid Build Coastguard Worker if (Arg->hasSwiftErrorAttr())
1905*9880d681SAndroid Build Coastguard Worker return false;
1906*9880d681SAndroid Build Coastguard Worker }
1907*9880d681SAndroid Build Coastguard Worker
1908*9880d681SAndroid Build Coastguard Worker if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(SV)) {
1909*9880d681SAndroid Build Coastguard Worker if (Alloca->isSwiftError())
1910*9880d681SAndroid Build Coastguard Worker return false;
1911*9880d681SAndroid Build Coastguard Worker }
1912*9880d681SAndroid Build Coastguard Worker }
1913*9880d681SAndroid Build Coastguard Worker
1914*9880d681SAndroid Build Coastguard Worker // See if we can handle this address.
1915*9880d681SAndroid Build Coastguard Worker Address Addr;
1916*9880d681SAndroid Build Coastguard Worker if (!computeAddress(I->getOperand(0), Addr, I->getType()))
1917*9880d681SAndroid Build Coastguard Worker return false;
1918*9880d681SAndroid Build Coastguard Worker
1919*9880d681SAndroid Build Coastguard Worker // Fold the following sign-/zero-extend into the load instruction.
1920*9880d681SAndroid Build Coastguard Worker bool WantZExt = true;
1921*9880d681SAndroid Build Coastguard Worker MVT RetVT = VT;
1922*9880d681SAndroid Build Coastguard Worker const Value *IntExtVal = nullptr;
1923*9880d681SAndroid Build Coastguard Worker if (I->hasOneUse()) {
1924*9880d681SAndroid Build Coastguard Worker if (const auto *ZE = dyn_cast<ZExtInst>(I->use_begin()->getUser())) {
1925*9880d681SAndroid Build Coastguard Worker if (isTypeSupported(ZE->getType(), RetVT))
1926*9880d681SAndroid Build Coastguard Worker IntExtVal = ZE;
1927*9880d681SAndroid Build Coastguard Worker else
1928*9880d681SAndroid Build Coastguard Worker RetVT = VT;
1929*9880d681SAndroid Build Coastguard Worker } else if (const auto *SE = dyn_cast<SExtInst>(I->use_begin()->getUser())) {
1930*9880d681SAndroid Build Coastguard Worker if (isTypeSupported(SE->getType(), RetVT))
1931*9880d681SAndroid Build Coastguard Worker IntExtVal = SE;
1932*9880d681SAndroid Build Coastguard Worker else
1933*9880d681SAndroid Build Coastguard Worker RetVT = VT;
1934*9880d681SAndroid Build Coastguard Worker WantZExt = false;
1935*9880d681SAndroid Build Coastguard Worker }
1936*9880d681SAndroid Build Coastguard Worker }
1937*9880d681SAndroid Build Coastguard Worker
1938*9880d681SAndroid Build Coastguard Worker unsigned ResultReg =
1939*9880d681SAndroid Build Coastguard Worker emitLoad(VT, RetVT, Addr, WantZExt, createMachineMemOperandFor(I));
1940*9880d681SAndroid Build Coastguard Worker if (!ResultReg)
1941*9880d681SAndroid Build Coastguard Worker return false;
1942*9880d681SAndroid Build Coastguard Worker
1943*9880d681SAndroid Build Coastguard Worker // There are a few different cases we have to handle, because the load or the
1944*9880d681SAndroid Build Coastguard Worker // sign-/zero-extend might not be selected by FastISel if we fall-back to
1945*9880d681SAndroid Build Coastguard Worker // SelectionDAG. There is also an ordering issue when both instructions are in
1946*9880d681SAndroid Build Coastguard Worker // different basic blocks.
1947*9880d681SAndroid Build Coastguard Worker // 1.) The load instruction is selected by FastISel, but the integer extend
1948*9880d681SAndroid Build Coastguard Worker // not. This usually happens when the integer extend is in a different
1949*9880d681SAndroid Build Coastguard Worker // basic block and SelectionDAG took over for that basic block.
1950*9880d681SAndroid Build Coastguard Worker // 2.) The load instruction is selected before the integer extend. This only
1951*9880d681SAndroid Build Coastguard Worker // happens when the integer extend is in a different basic block.
1952*9880d681SAndroid Build Coastguard Worker // 3.) The load instruction is selected by SelectionDAG and the integer extend
1953*9880d681SAndroid Build Coastguard Worker // by FastISel. This happens if there are instructions between the load
1954*9880d681SAndroid Build Coastguard Worker // and the integer extend that couldn't be selected by FastISel.
1955*9880d681SAndroid Build Coastguard Worker if (IntExtVal) {
1956*9880d681SAndroid Build Coastguard Worker // The integer extend hasn't been emitted yet. FastISel or SelectionDAG
1957*9880d681SAndroid Build Coastguard Worker // could select it. Emit a copy to subreg if necessary. FastISel will remove
1958*9880d681SAndroid Build Coastguard Worker // it when it selects the integer extend.
1959*9880d681SAndroid Build Coastguard Worker unsigned Reg = lookUpRegForValue(IntExtVal);
1960*9880d681SAndroid Build Coastguard Worker auto *MI = MRI.getUniqueVRegDef(Reg);
1961*9880d681SAndroid Build Coastguard Worker if (!MI) {
1962*9880d681SAndroid Build Coastguard Worker if (RetVT == MVT::i64 && VT <= MVT::i32) {
1963*9880d681SAndroid Build Coastguard Worker if (WantZExt) {
1964*9880d681SAndroid Build Coastguard Worker // Delete the last emitted instruction from emitLoad (SUBREG_TO_REG).
1965*9880d681SAndroid Build Coastguard Worker std::prev(FuncInfo.InsertPt)->eraseFromParent();
1966*9880d681SAndroid Build Coastguard Worker ResultReg = std::prev(FuncInfo.InsertPt)->getOperand(0).getReg();
1967*9880d681SAndroid Build Coastguard Worker } else
1968*9880d681SAndroid Build Coastguard Worker ResultReg = fastEmitInst_extractsubreg(MVT::i32, ResultReg,
1969*9880d681SAndroid Build Coastguard Worker /*IsKill=*/true,
1970*9880d681SAndroid Build Coastguard Worker AArch64::sub_32);
1971*9880d681SAndroid Build Coastguard Worker }
1972*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
1973*9880d681SAndroid Build Coastguard Worker return true;
1974*9880d681SAndroid Build Coastguard Worker }
1975*9880d681SAndroid Build Coastguard Worker
1976*9880d681SAndroid Build Coastguard Worker // The integer extend has already been emitted - delete all the instructions
1977*9880d681SAndroid Build Coastguard Worker // that have been emitted by the integer extend lowering code and use the
1978*9880d681SAndroid Build Coastguard Worker // result from the load instruction directly.
1979*9880d681SAndroid Build Coastguard Worker while (MI) {
1980*9880d681SAndroid Build Coastguard Worker Reg = 0;
1981*9880d681SAndroid Build Coastguard Worker for (auto &Opnd : MI->uses()) {
1982*9880d681SAndroid Build Coastguard Worker if (Opnd.isReg()) {
1983*9880d681SAndroid Build Coastguard Worker Reg = Opnd.getReg();
1984*9880d681SAndroid Build Coastguard Worker break;
1985*9880d681SAndroid Build Coastguard Worker }
1986*9880d681SAndroid Build Coastguard Worker }
1987*9880d681SAndroid Build Coastguard Worker MI->eraseFromParent();
1988*9880d681SAndroid Build Coastguard Worker MI = nullptr;
1989*9880d681SAndroid Build Coastguard Worker if (Reg)
1990*9880d681SAndroid Build Coastguard Worker MI = MRI.getUniqueVRegDef(Reg);
1991*9880d681SAndroid Build Coastguard Worker }
1992*9880d681SAndroid Build Coastguard Worker updateValueMap(IntExtVal, ResultReg);
1993*9880d681SAndroid Build Coastguard Worker return true;
1994*9880d681SAndroid Build Coastguard Worker }
1995*9880d681SAndroid Build Coastguard Worker
1996*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
1997*9880d681SAndroid Build Coastguard Worker return true;
1998*9880d681SAndroid Build Coastguard Worker }
1999*9880d681SAndroid Build Coastguard Worker
emitStore(MVT VT,unsigned SrcReg,Address Addr,MachineMemOperand * MMO)2000*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::emitStore(MVT VT, unsigned SrcReg, Address Addr,
2001*9880d681SAndroid Build Coastguard Worker MachineMemOperand *MMO) {
2002*9880d681SAndroid Build Coastguard Worker if (!TLI.allowsMisalignedMemoryAccesses(VT))
2003*9880d681SAndroid Build Coastguard Worker return false;
2004*9880d681SAndroid Build Coastguard Worker
2005*9880d681SAndroid Build Coastguard Worker // Simplify this down to something we can handle.
2006*9880d681SAndroid Build Coastguard Worker if (!simplifyAddress(Addr, VT))
2007*9880d681SAndroid Build Coastguard Worker return false;
2008*9880d681SAndroid Build Coastguard Worker
2009*9880d681SAndroid Build Coastguard Worker unsigned ScaleFactor = getImplicitScaleFactor(VT);
2010*9880d681SAndroid Build Coastguard Worker if (!ScaleFactor)
2011*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected value type.");
2012*9880d681SAndroid Build Coastguard Worker
2013*9880d681SAndroid Build Coastguard Worker // Negative offsets require unscaled, 9-bit, signed immediate offsets.
2014*9880d681SAndroid Build Coastguard Worker // Otherwise, we try using scaled, 12-bit, unsigned immediate offsets.
2015*9880d681SAndroid Build Coastguard Worker bool UseScaled = true;
2016*9880d681SAndroid Build Coastguard Worker if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
2017*9880d681SAndroid Build Coastguard Worker UseScaled = false;
2018*9880d681SAndroid Build Coastguard Worker ScaleFactor = 1;
2019*9880d681SAndroid Build Coastguard Worker }
2020*9880d681SAndroid Build Coastguard Worker
2021*9880d681SAndroid Build Coastguard Worker static const unsigned OpcTable[4][6] = {
2022*9880d681SAndroid Build Coastguard Worker { AArch64::STURBBi, AArch64::STURHHi, AArch64::STURWi, AArch64::STURXi,
2023*9880d681SAndroid Build Coastguard Worker AArch64::STURSi, AArch64::STURDi },
2024*9880d681SAndroid Build Coastguard Worker { AArch64::STRBBui, AArch64::STRHHui, AArch64::STRWui, AArch64::STRXui,
2025*9880d681SAndroid Build Coastguard Worker AArch64::STRSui, AArch64::STRDui },
2026*9880d681SAndroid Build Coastguard Worker { AArch64::STRBBroX, AArch64::STRHHroX, AArch64::STRWroX, AArch64::STRXroX,
2027*9880d681SAndroid Build Coastguard Worker AArch64::STRSroX, AArch64::STRDroX },
2028*9880d681SAndroid Build Coastguard Worker { AArch64::STRBBroW, AArch64::STRHHroW, AArch64::STRWroW, AArch64::STRXroW,
2029*9880d681SAndroid Build Coastguard Worker AArch64::STRSroW, AArch64::STRDroW }
2030*9880d681SAndroid Build Coastguard Worker };
2031*9880d681SAndroid Build Coastguard Worker
2032*9880d681SAndroid Build Coastguard Worker unsigned Opc;
2033*9880d681SAndroid Build Coastguard Worker bool VTIsi1 = false;
2034*9880d681SAndroid Build Coastguard Worker bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
2035*9880d681SAndroid Build Coastguard Worker Addr.getOffsetReg();
2036*9880d681SAndroid Build Coastguard Worker unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
2037*9880d681SAndroid Build Coastguard Worker if (Addr.getExtendType() == AArch64_AM::UXTW ||
2038*9880d681SAndroid Build Coastguard Worker Addr.getExtendType() == AArch64_AM::SXTW)
2039*9880d681SAndroid Build Coastguard Worker Idx++;
2040*9880d681SAndroid Build Coastguard Worker
2041*9880d681SAndroid Build Coastguard Worker switch (VT.SimpleTy) {
2042*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Unexpected value type.");
2043*9880d681SAndroid Build Coastguard Worker case MVT::i1: VTIsi1 = true;
2044*9880d681SAndroid Build Coastguard Worker case MVT::i8: Opc = OpcTable[Idx][0]; break;
2045*9880d681SAndroid Build Coastguard Worker case MVT::i16: Opc = OpcTable[Idx][1]; break;
2046*9880d681SAndroid Build Coastguard Worker case MVT::i32: Opc = OpcTable[Idx][2]; break;
2047*9880d681SAndroid Build Coastguard Worker case MVT::i64: Opc = OpcTable[Idx][3]; break;
2048*9880d681SAndroid Build Coastguard Worker case MVT::f32: Opc = OpcTable[Idx][4]; break;
2049*9880d681SAndroid Build Coastguard Worker case MVT::f64: Opc = OpcTable[Idx][5]; break;
2050*9880d681SAndroid Build Coastguard Worker }
2051*9880d681SAndroid Build Coastguard Worker
2052*9880d681SAndroid Build Coastguard Worker // Storing an i1 requires special handling.
2053*9880d681SAndroid Build Coastguard Worker if (VTIsi1 && SrcReg != AArch64::WZR) {
2054*9880d681SAndroid Build Coastguard Worker unsigned ANDReg = emitAnd_ri(MVT::i32, SrcReg, /*TODO:IsKill=*/false, 1);
2055*9880d681SAndroid Build Coastguard Worker assert(ANDReg && "Unexpected AND instruction emission failure.");
2056*9880d681SAndroid Build Coastguard Worker SrcReg = ANDReg;
2057*9880d681SAndroid Build Coastguard Worker }
2058*9880d681SAndroid Build Coastguard Worker // Create the base instruction, then add the operands.
2059*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &II = TII.get(Opc);
2060*9880d681SAndroid Build Coastguard Worker SrcReg = constrainOperandRegClass(II, SrcReg, II.getNumDefs());
2061*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB =
2062*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II).addReg(SrcReg);
2063*9880d681SAndroid Build Coastguard Worker addLoadStoreOperands(Addr, MIB, MachineMemOperand::MOStore, ScaleFactor, MMO);
2064*9880d681SAndroid Build Coastguard Worker
2065*9880d681SAndroid Build Coastguard Worker return true;
2066*9880d681SAndroid Build Coastguard Worker }
2067*9880d681SAndroid Build Coastguard Worker
selectStore(const Instruction * I)2068*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectStore(const Instruction *I) {
2069*9880d681SAndroid Build Coastguard Worker MVT VT;
2070*9880d681SAndroid Build Coastguard Worker const Value *Op0 = I->getOperand(0);
2071*9880d681SAndroid Build Coastguard Worker // Verify we have a legal type before going any further. Currently, we handle
2072*9880d681SAndroid Build Coastguard Worker // simple types that will directly fit in a register (i32/f32/i64/f64) or
2073*9880d681SAndroid Build Coastguard Worker // those that can be sign or zero-extended to a basic operation (i1/i8/i16).
2074*9880d681SAndroid Build Coastguard Worker if (!isTypeSupported(Op0->getType(), VT, /*IsVectorAllowed=*/true) ||
2075*9880d681SAndroid Build Coastguard Worker cast<StoreInst>(I)->isAtomic())
2076*9880d681SAndroid Build Coastguard Worker return false;
2077*9880d681SAndroid Build Coastguard Worker
2078*9880d681SAndroid Build Coastguard Worker const Value *PtrV = I->getOperand(1);
2079*9880d681SAndroid Build Coastguard Worker if (TLI.supportSwiftError()) {
2080*9880d681SAndroid Build Coastguard Worker // Swifterror values can come from either a function parameter with
2081*9880d681SAndroid Build Coastguard Worker // swifterror attribute or an alloca with swifterror attribute.
2082*9880d681SAndroid Build Coastguard Worker if (const Argument *Arg = dyn_cast<Argument>(PtrV)) {
2083*9880d681SAndroid Build Coastguard Worker if (Arg->hasSwiftErrorAttr())
2084*9880d681SAndroid Build Coastguard Worker return false;
2085*9880d681SAndroid Build Coastguard Worker }
2086*9880d681SAndroid Build Coastguard Worker
2087*9880d681SAndroid Build Coastguard Worker if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(PtrV)) {
2088*9880d681SAndroid Build Coastguard Worker if (Alloca->isSwiftError())
2089*9880d681SAndroid Build Coastguard Worker return false;
2090*9880d681SAndroid Build Coastguard Worker }
2091*9880d681SAndroid Build Coastguard Worker }
2092*9880d681SAndroid Build Coastguard Worker
2093*9880d681SAndroid Build Coastguard Worker // Get the value to be stored into a register. Use the zero register directly
2094*9880d681SAndroid Build Coastguard Worker // when possible to avoid an unnecessary copy and a wasted register.
2095*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = 0;
2096*9880d681SAndroid Build Coastguard Worker if (const auto *CI = dyn_cast<ConstantInt>(Op0)) {
2097*9880d681SAndroid Build Coastguard Worker if (CI->isZero())
2098*9880d681SAndroid Build Coastguard Worker SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2099*9880d681SAndroid Build Coastguard Worker } else if (const auto *CF = dyn_cast<ConstantFP>(Op0)) {
2100*9880d681SAndroid Build Coastguard Worker if (CF->isZero() && !CF->isNegative()) {
2101*9880d681SAndroid Build Coastguard Worker VT = MVT::getIntegerVT(VT.getSizeInBits());
2102*9880d681SAndroid Build Coastguard Worker SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2103*9880d681SAndroid Build Coastguard Worker }
2104*9880d681SAndroid Build Coastguard Worker }
2105*9880d681SAndroid Build Coastguard Worker
2106*9880d681SAndroid Build Coastguard Worker if (!SrcReg)
2107*9880d681SAndroid Build Coastguard Worker SrcReg = getRegForValue(Op0);
2108*9880d681SAndroid Build Coastguard Worker
2109*9880d681SAndroid Build Coastguard Worker if (!SrcReg)
2110*9880d681SAndroid Build Coastguard Worker return false;
2111*9880d681SAndroid Build Coastguard Worker
2112*9880d681SAndroid Build Coastguard Worker // See if we can handle this address.
2113*9880d681SAndroid Build Coastguard Worker Address Addr;
2114*9880d681SAndroid Build Coastguard Worker if (!computeAddress(I->getOperand(1), Addr, I->getOperand(0)->getType()))
2115*9880d681SAndroid Build Coastguard Worker return false;
2116*9880d681SAndroid Build Coastguard Worker
2117*9880d681SAndroid Build Coastguard Worker if (!emitStore(VT, SrcReg, Addr, createMachineMemOperandFor(I)))
2118*9880d681SAndroid Build Coastguard Worker return false;
2119*9880d681SAndroid Build Coastguard Worker return true;
2120*9880d681SAndroid Build Coastguard Worker }
2121*9880d681SAndroid Build Coastguard Worker
getCompareCC(CmpInst::Predicate Pred)2122*9880d681SAndroid Build Coastguard Worker static AArch64CC::CondCode getCompareCC(CmpInst::Predicate Pred) {
2123*9880d681SAndroid Build Coastguard Worker switch (Pred) {
2124*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_ONE:
2125*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_UEQ:
2126*9880d681SAndroid Build Coastguard Worker default:
2127*9880d681SAndroid Build Coastguard Worker // AL is our "false" for now. The other two need more compares.
2128*9880d681SAndroid Build Coastguard Worker return AArch64CC::AL;
2129*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_EQ:
2130*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_OEQ:
2131*9880d681SAndroid Build Coastguard Worker return AArch64CC::EQ;
2132*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_SGT:
2133*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_OGT:
2134*9880d681SAndroid Build Coastguard Worker return AArch64CC::GT;
2135*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_SGE:
2136*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_OGE:
2137*9880d681SAndroid Build Coastguard Worker return AArch64CC::GE;
2138*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_UGT:
2139*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_UGT:
2140*9880d681SAndroid Build Coastguard Worker return AArch64CC::HI;
2141*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_OLT:
2142*9880d681SAndroid Build Coastguard Worker return AArch64CC::MI;
2143*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_ULE:
2144*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_OLE:
2145*9880d681SAndroid Build Coastguard Worker return AArch64CC::LS;
2146*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_ORD:
2147*9880d681SAndroid Build Coastguard Worker return AArch64CC::VC;
2148*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_UNO:
2149*9880d681SAndroid Build Coastguard Worker return AArch64CC::VS;
2150*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_UGE:
2151*9880d681SAndroid Build Coastguard Worker return AArch64CC::PL;
2152*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_SLT:
2153*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_ULT:
2154*9880d681SAndroid Build Coastguard Worker return AArch64CC::LT;
2155*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_SLE:
2156*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_ULE:
2157*9880d681SAndroid Build Coastguard Worker return AArch64CC::LE;
2158*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_UNE:
2159*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_NE:
2160*9880d681SAndroid Build Coastguard Worker return AArch64CC::NE;
2161*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_UGE:
2162*9880d681SAndroid Build Coastguard Worker return AArch64CC::HS;
2163*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_ULT:
2164*9880d681SAndroid Build Coastguard Worker return AArch64CC::LO;
2165*9880d681SAndroid Build Coastguard Worker }
2166*9880d681SAndroid Build Coastguard Worker }
2167*9880d681SAndroid Build Coastguard Worker
2168*9880d681SAndroid Build Coastguard Worker /// \brief Try to emit a combined compare-and-branch instruction.
emitCompareAndBranch(const BranchInst * BI)2169*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::emitCompareAndBranch(const BranchInst *BI) {
2170*9880d681SAndroid Build Coastguard Worker assert(isa<CmpInst>(BI->getCondition()) && "Expected cmp instruction");
2171*9880d681SAndroid Build Coastguard Worker const CmpInst *CI = cast<CmpInst>(BI->getCondition());
2172*9880d681SAndroid Build Coastguard Worker CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);
2173*9880d681SAndroid Build Coastguard Worker
2174*9880d681SAndroid Build Coastguard Worker const Value *LHS = CI->getOperand(0);
2175*9880d681SAndroid Build Coastguard Worker const Value *RHS = CI->getOperand(1);
2176*9880d681SAndroid Build Coastguard Worker
2177*9880d681SAndroid Build Coastguard Worker MVT VT;
2178*9880d681SAndroid Build Coastguard Worker if (!isTypeSupported(LHS->getType(), VT))
2179*9880d681SAndroid Build Coastguard Worker return false;
2180*9880d681SAndroid Build Coastguard Worker
2181*9880d681SAndroid Build Coastguard Worker unsigned BW = VT.getSizeInBits();
2182*9880d681SAndroid Build Coastguard Worker if (BW > 64)
2183*9880d681SAndroid Build Coastguard Worker return false;
2184*9880d681SAndroid Build Coastguard Worker
2185*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)];
2186*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];
2187*9880d681SAndroid Build Coastguard Worker
2188*9880d681SAndroid Build Coastguard Worker // Try to take advantage of fallthrough opportunities.
2189*9880d681SAndroid Build Coastguard Worker if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
2190*9880d681SAndroid Build Coastguard Worker std::swap(TBB, FBB);
2191*9880d681SAndroid Build Coastguard Worker Predicate = CmpInst::getInversePredicate(Predicate);
2192*9880d681SAndroid Build Coastguard Worker }
2193*9880d681SAndroid Build Coastguard Worker
2194*9880d681SAndroid Build Coastguard Worker int TestBit = -1;
2195*9880d681SAndroid Build Coastguard Worker bool IsCmpNE;
2196*9880d681SAndroid Build Coastguard Worker switch (Predicate) {
2197*9880d681SAndroid Build Coastguard Worker default:
2198*9880d681SAndroid Build Coastguard Worker return false;
2199*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_EQ:
2200*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_NE:
2201*9880d681SAndroid Build Coastguard Worker if (isa<Constant>(LHS) && cast<Constant>(LHS)->isNullValue())
2202*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
2203*9880d681SAndroid Build Coastguard Worker
2204*9880d681SAndroid Build Coastguard Worker if (!isa<Constant>(RHS) || !cast<Constant>(RHS)->isNullValue())
2205*9880d681SAndroid Build Coastguard Worker return false;
2206*9880d681SAndroid Build Coastguard Worker
2207*9880d681SAndroid Build Coastguard Worker if (const auto *AI = dyn_cast<BinaryOperator>(LHS))
2208*9880d681SAndroid Build Coastguard Worker if (AI->getOpcode() == Instruction::And && isValueAvailable(AI)) {
2209*9880d681SAndroid Build Coastguard Worker const Value *AndLHS = AI->getOperand(0);
2210*9880d681SAndroid Build Coastguard Worker const Value *AndRHS = AI->getOperand(1);
2211*9880d681SAndroid Build Coastguard Worker
2212*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(AndLHS))
2213*9880d681SAndroid Build Coastguard Worker if (C->getValue().isPowerOf2())
2214*9880d681SAndroid Build Coastguard Worker std::swap(AndLHS, AndRHS);
2215*9880d681SAndroid Build Coastguard Worker
2216*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(AndRHS))
2217*9880d681SAndroid Build Coastguard Worker if (C->getValue().isPowerOf2()) {
2218*9880d681SAndroid Build Coastguard Worker TestBit = C->getValue().logBase2();
2219*9880d681SAndroid Build Coastguard Worker LHS = AndLHS;
2220*9880d681SAndroid Build Coastguard Worker }
2221*9880d681SAndroid Build Coastguard Worker }
2222*9880d681SAndroid Build Coastguard Worker
2223*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i1)
2224*9880d681SAndroid Build Coastguard Worker TestBit = 0;
2225*9880d681SAndroid Build Coastguard Worker
2226*9880d681SAndroid Build Coastguard Worker IsCmpNE = Predicate == CmpInst::ICMP_NE;
2227*9880d681SAndroid Build Coastguard Worker break;
2228*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_SLT:
2229*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_SGE:
2230*9880d681SAndroid Build Coastguard Worker if (!isa<Constant>(RHS) || !cast<Constant>(RHS)->isNullValue())
2231*9880d681SAndroid Build Coastguard Worker return false;
2232*9880d681SAndroid Build Coastguard Worker
2233*9880d681SAndroid Build Coastguard Worker TestBit = BW - 1;
2234*9880d681SAndroid Build Coastguard Worker IsCmpNE = Predicate == CmpInst::ICMP_SLT;
2235*9880d681SAndroid Build Coastguard Worker break;
2236*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_SGT:
2237*9880d681SAndroid Build Coastguard Worker case CmpInst::ICMP_SLE:
2238*9880d681SAndroid Build Coastguard Worker if (!isa<ConstantInt>(RHS))
2239*9880d681SAndroid Build Coastguard Worker return false;
2240*9880d681SAndroid Build Coastguard Worker
2241*9880d681SAndroid Build Coastguard Worker if (cast<ConstantInt>(RHS)->getValue() != APInt(BW, -1, true))
2242*9880d681SAndroid Build Coastguard Worker return false;
2243*9880d681SAndroid Build Coastguard Worker
2244*9880d681SAndroid Build Coastguard Worker TestBit = BW - 1;
2245*9880d681SAndroid Build Coastguard Worker IsCmpNE = Predicate == CmpInst::ICMP_SLE;
2246*9880d681SAndroid Build Coastguard Worker break;
2247*9880d681SAndroid Build Coastguard Worker } // end switch
2248*9880d681SAndroid Build Coastguard Worker
2249*9880d681SAndroid Build Coastguard Worker static const unsigned OpcTable[2][2][2] = {
2250*9880d681SAndroid Build Coastguard Worker { {AArch64::CBZW, AArch64::CBZX },
2251*9880d681SAndroid Build Coastguard Worker {AArch64::CBNZW, AArch64::CBNZX} },
2252*9880d681SAndroid Build Coastguard Worker { {AArch64::TBZW, AArch64::TBZX },
2253*9880d681SAndroid Build Coastguard Worker {AArch64::TBNZW, AArch64::TBNZX} }
2254*9880d681SAndroid Build Coastguard Worker };
2255*9880d681SAndroid Build Coastguard Worker
2256*9880d681SAndroid Build Coastguard Worker bool IsBitTest = TestBit != -1;
2257*9880d681SAndroid Build Coastguard Worker bool Is64Bit = BW == 64;
2258*9880d681SAndroid Build Coastguard Worker if (TestBit < 32 && TestBit >= 0)
2259*9880d681SAndroid Build Coastguard Worker Is64Bit = false;
2260*9880d681SAndroid Build Coastguard Worker
2261*9880d681SAndroid Build Coastguard Worker unsigned Opc = OpcTable[IsBitTest][IsCmpNE][Is64Bit];
2262*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &II = TII.get(Opc);
2263*9880d681SAndroid Build Coastguard Worker
2264*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = getRegForValue(LHS);
2265*9880d681SAndroid Build Coastguard Worker if (!SrcReg)
2266*9880d681SAndroid Build Coastguard Worker return false;
2267*9880d681SAndroid Build Coastguard Worker bool SrcIsKill = hasTrivialKill(LHS);
2268*9880d681SAndroid Build Coastguard Worker
2269*9880d681SAndroid Build Coastguard Worker if (BW == 64 && !Is64Bit)
2270*9880d681SAndroid Build Coastguard Worker SrcReg = fastEmitInst_extractsubreg(MVT::i32, SrcReg, SrcIsKill,
2271*9880d681SAndroid Build Coastguard Worker AArch64::sub_32);
2272*9880d681SAndroid Build Coastguard Worker
2273*9880d681SAndroid Build Coastguard Worker if ((BW < 32) && !IsBitTest)
2274*9880d681SAndroid Build Coastguard Worker SrcReg = emitIntExt(VT, SrcReg, MVT::i32, /*IsZExt=*/true);
2275*9880d681SAndroid Build Coastguard Worker
2276*9880d681SAndroid Build Coastguard Worker // Emit the combined compare and branch instruction.
2277*9880d681SAndroid Build Coastguard Worker SrcReg = constrainOperandRegClass(II, SrcReg, II.getNumDefs());
2278*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB =
2279*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
2280*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(SrcIsKill));
2281*9880d681SAndroid Build Coastguard Worker if (IsBitTest)
2282*9880d681SAndroid Build Coastguard Worker MIB.addImm(TestBit);
2283*9880d681SAndroid Build Coastguard Worker MIB.addMBB(TBB);
2284*9880d681SAndroid Build Coastguard Worker
2285*9880d681SAndroid Build Coastguard Worker finishCondBranch(BI->getParent(), TBB, FBB);
2286*9880d681SAndroid Build Coastguard Worker return true;
2287*9880d681SAndroid Build Coastguard Worker }
2288*9880d681SAndroid Build Coastguard Worker
selectBranch(const Instruction * I)2289*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectBranch(const Instruction *I) {
2290*9880d681SAndroid Build Coastguard Worker const BranchInst *BI = cast<BranchInst>(I);
2291*9880d681SAndroid Build Coastguard Worker if (BI->isUnconditional()) {
2292*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MSucc = FuncInfo.MBBMap[BI->getSuccessor(0)];
2293*9880d681SAndroid Build Coastguard Worker fastEmitBranch(MSucc, BI->getDebugLoc());
2294*9880d681SAndroid Build Coastguard Worker return true;
2295*9880d681SAndroid Build Coastguard Worker }
2296*9880d681SAndroid Build Coastguard Worker
2297*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)];
2298*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];
2299*9880d681SAndroid Build Coastguard Worker
2300*9880d681SAndroid Build Coastguard Worker if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) {
2301*9880d681SAndroid Build Coastguard Worker if (CI->hasOneUse() && isValueAvailable(CI)) {
2302*9880d681SAndroid Build Coastguard Worker // Try to optimize or fold the cmp.
2303*9880d681SAndroid Build Coastguard Worker CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);
2304*9880d681SAndroid Build Coastguard Worker switch (Predicate) {
2305*9880d681SAndroid Build Coastguard Worker default:
2306*9880d681SAndroid Build Coastguard Worker break;
2307*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_FALSE:
2308*9880d681SAndroid Build Coastguard Worker fastEmitBranch(FBB, DbgLoc);
2309*9880d681SAndroid Build Coastguard Worker return true;
2310*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_TRUE:
2311*9880d681SAndroid Build Coastguard Worker fastEmitBranch(TBB, DbgLoc);
2312*9880d681SAndroid Build Coastguard Worker return true;
2313*9880d681SAndroid Build Coastguard Worker }
2314*9880d681SAndroid Build Coastguard Worker
2315*9880d681SAndroid Build Coastguard Worker // Try to emit a combined compare-and-branch first.
2316*9880d681SAndroid Build Coastguard Worker if (emitCompareAndBranch(BI))
2317*9880d681SAndroid Build Coastguard Worker return true;
2318*9880d681SAndroid Build Coastguard Worker
2319*9880d681SAndroid Build Coastguard Worker // Try to take advantage of fallthrough opportunities.
2320*9880d681SAndroid Build Coastguard Worker if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
2321*9880d681SAndroid Build Coastguard Worker std::swap(TBB, FBB);
2322*9880d681SAndroid Build Coastguard Worker Predicate = CmpInst::getInversePredicate(Predicate);
2323*9880d681SAndroid Build Coastguard Worker }
2324*9880d681SAndroid Build Coastguard Worker
2325*9880d681SAndroid Build Coastguard Worker // Emit the cmp.
2326*9880d681SAndroid Build Coastguard Worker if (!emitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned()))
2327*9880d681SAndroid Build Coastguard Worker return false;
2328*9880d681SAndroid Build Coastguard Worker
2329*9880d681SAndroid Build Coastguard Worker // FCMP_UEQ and FCMP_ONE cannot be checked with a single branch
2330*9880d681SAndroid Build Coastguard Worker // instruction.
2331*9880d681SAndroid Build Coastguard Worker AArch64CC::CondCode CC = getCompareCC(Predicate);
2332*9880d681SAndroid Build Coastguard Worker AArch64CC::CondCode ExtraCC = AArch64CC::AL;
2333*9880d681SAndroid Build Coastguard Worker switch (Predicate) {
2334*9880d681SAndroid Build Coastguard Worker default:
2335*9880d681SAndroid Build Coastguard Worker break;
2336*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_UEQ:
2337*9880d681SAndroid Build Coastguard Worker ExtraCC = AArch64CC::EQ;
2338*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::VS;
2339*9880d681SAndroid Build Coastguard Worker break;
2340*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_ONE:
2341*9880d681SAndroid Build Coastguard Worker ExtraCC = AArch64CC::MI;
2342*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::GT;
2343*9880d681SAndroid Build Coastguard Worker break;
2344*9880d681SAndroid Build Coastguard Worker }
2345*9880d681SAndroid Build Coastguard Worker assert((CC != AArch64CC::AL) && "Unexpected condition code.");
2346*9880d681SAndroid Build Coastguard Worker
2347*9880d681SAndroid Build Coastguard Worker // Emit the extra branch for FCMP_UEQ and FCMP_ONE.
2348*9880d681SAndroid Build Coastguard Worker if (ExtraCC != AArch64CC::AL) {
2349*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::Bcc))
2350*9880d681SAndroid Build Coastguard Worker .addImm(ExtraCC)
2351*9880d681SAndroid Build Coastguard Worker .addMBB(TBB);
2352*9880d681SAndroid Build Coastguard Worker }
2353*9880d681SAndroid Build Coastguard Worker
2354*9880d681SAndroid Build Coastguard Worker // Emit the branch.
2355*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::Bcc))
2356*9880d681SAndroid Build Coastguard Worker .addImm(CC)
2357*9880d681SAndroid Build Coastguard Worker .addMBB(TBB);
2358*9880d681SAndroid Build Coastguard Worker
2359*9880d681SAndroid Build Coastguard Worker finishCondBranch(BI->getParent(), TBB, FBB);
2360*9880d681SAndroid Build Coastguard Worker return true;
2361*9880d681SAndroid Build Coastguard Worker }
2362*9880d681SAndroid Build Coastguard Worker } else if (const auto *CI = dyn_cast<ConstantInt>(BI->getCondition())) {
2363*9880d681SAndroid Build Coastguard Worker uint64_t Imm = CI->getZExtValue();
2364*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *Target = (Imm == 0) ? FBB : TBB;
2365*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::B))
2366*9880d681SAndroid Build Coastguard Worker .addMBB(Target);
2367*9880d681SAndroid Build Coastguard Worker
2368*9880d681SAndroid Build Coastguard Worker // Obtain the branch probability and add the target to the successor list.
2369*9880d681SAndroid Build Coastguard Worker if (FuncInfo.BPI) {
2370*9880d681SAndroid Build Coastguard Worker auto BranchProbability = FuncInfo.BPI->getEdgeProbability(
2371*9880d681SAndroid Build Coastguard Worker BI->getParent(), Target->getBasicBlock());
2372*9880d681SAndroid Build Coastguard Worker FuncInfo.MBB->addSuccessor(Target, BranchProbability);
2373*9880d681SAndroid Build Coastguard Worker } else
2374*9880d681SAndroid Build Coastguard Worker FuncInfo.MBB->addSuccessorWithoutProb(Target);
2375*9880d681SAndroid Build Coastguard Worker return true;
2376*9880d681SAndroid Build Coastguard Worker } else {
2377*9880d681SAndroid Build Coastguard Worker AArch64CC::CondCode CC = AArch64CC::NE;
2378*9880d681SAndroid Build Coastguard Worker if (foldXALUIntrinsic(CC, I, BI->getCondition())) {
2379*9880d681SAndroid Build Coastguard Worker // Fake request the condition, otherwise the intrinsic might be completely
2380*9880d681SAndroid Build Coastguard Worker // optimized away.
2381*9880d681SAndroid Build Coastguard Worker unsigned CondReg = getRegForValue(BI->getCondition());
2382*9880d681SAndroid Build Coastguard Worker if (!CondReg)
2383*9880d681SAndroid Build Coastguard Worker return false;
2384*9880d681SAndroid Build Coastguard Worker
2385*9880d681SAndroid Build Coastguard Worker // Emit the branch.
2386*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::Bcc))
2387*9880d681SAndroid Build Coastguard Worker .addImm(CC)
2388*9880d681SAndroid Build Coastguard Worker .addMBB(TBB);
2389*9880d681SAndroid Build Coastguard Worker
2390*9880d681SAndroid Build Coastguard Worker finishCondBranch(BI->getParent(), TBB, FBB);
2391*9880d681SAndroid Build Coastguard Worker return true;
2392*9880d681SAndroid Build Coastguard Worker }
2393*9880d681SAndroid Build Coastguard Worker }
2394*9880d681SAndroid Build Coastguard Worker
2395*9880d681SAndroid Build Coastguard Worker unsigned CondReg = getRegForValue(BI->getCondition());
2396*9880d681SAndroid Build Coastguard Worker if (CondReg == 0)
2397*9880d681SAndroid Build Coastguard Worker return false;
2398*9880d681SAndroid Build Coastguard Worker bool CondRegIsKill = hasTrivialKill(BI->getCondition());
2399*9880d681SAndroid Build Coastguard Worker
2400*9880d681SAndroid Build Coastguard Worker // i1 conditions come as i32 values, test the lowest bit with tb(n)z.
2401*9880d681SAndroid Build Coastguard Worker unsigned Opcode = AArch64::TBNZW;
2402*9880d681SAndroid Build Coastguard Worker if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
2403*9880d681SAndroid Build Coastguard Worker std::swap(TBB, FBB);
2404*9880d681SAndroid Build Coastguard Worker Opcode = AArch64::TBZW;
2405*9880d681SAndroid Build Coastguard Worker }
2406*9880d681SAndroid Build Coastguard Worker
2407*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &II = TII.get(Opcode);
2408*9880d681SAndroid Build Coastguard Worker unsigned ConstrainedCondReg
2409*9880d681SAndroid Build Coastguard Worker = constrainOperandRegClass(II, CondReg, II.getNumDefs());
2410*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
2411*9880d681SAndroid Build Coastguard Worker .addReg(ConstrainedCondReg, getKillRegState(CondRegIsKill))
2412*9880d681SAndroid Build Coastguard Worker .addImm(0)
2413*9880d681SAndroid Build Coastguard Worker .addMBB(TBB);
2414*9880d681SAndroid Build Coastguard Worker
2415*9880d681SAndroid Build Coastguard Worker finishCondBranch(BI->getParent(), TBB, FBB);
2416*9880d681SAndroid Build Coastguard Worker return true;
2417*9880d681SAndroid Build Coastguard Worker }
2418*9880d681SAndroid Build Coastguard Worker
selectIndirectBr(const Instruction * I)2419*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectIndirectBr(const Instruction *I) {
2420*9880d681SAndroid Build Coastguard Worker const IndirectBrInst *BI = cast<IndirectBrInst>(I);
2421*9880d681SAndroid Build Coastguard Worker unsigned AddrReg = getRegForValue(BI->getOperand(0));
2422*9880d681SAndroid Build Coastguard Worker if (AddrReg == 0)
2423*9880d681SAndroid Build Coastguard Worker return false;
2424*9880d681SAndroid Build Coastguard Worker
2425*9880d681SAndroid Build Coastguard Worker // Emit the indirect branch.
2426*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &II = TII.get(AArch64::BR);
2427*9880d681SAndroid Build Coastguard Worker AddrReg = constrainOperandRegClass(II, AddrReg, II.getNumDefs());
2428*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II).addReg(AddrReg);
2429*9880d681SAndroid Build Coastguard Worker
2430*9880d681SAndroid Build Coastguard Worker // Make sure the CFG is up-to-date.
2431*9880d681SAndroid Build Coastguard Worker for (auto *Succ : BI->successors())
2432*9880d681SAndroid Build Coastguard Worker FuncInfo.MBB->addSuccessor(FuncInfo.MBBMap[Succ]);
2433*9880d681SAndroid Build Coastguard Worker
2434*9880d681SAndroid Build Coastguard Worker return true;
2435*9880d681SAndroid Build Coastguard Worker }
2436*9880d681SAndroid Build Coastguard Worker
selectCmp(const Instruction * I)2437*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectCmp(const Instruction *I) {
2438*9880d681SAndroid Build Coastguard Worker const CmpInst *CI = cast<CmpInst>(I);
2439*9880d681SAndroid Build Coastguard Worker
2440*9880d681SAndroid Build Coastguard Worker // Vectors of i1 are weird: bail out.
2441*9880d681SAndroid Build Coastguard Worker if (CI->getType()->isVectorTy())
2442*9880d681SAndroid Build Coastguard Worker return false;
2443*9880d681SAndroid Build Coastguard Worker
2444*9880d681SAndroid Build Coastguard Worker // Try to optimize or fold the cmp.
2445*9880d681SAndroid Build Coastguard Worker CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);
2446*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = 0;
2447*9880d681SAndroid Build Coastguard Worker switch (Predicate) {
2448*9880d681SAndroid Build Coastguard Worker default:
2449*9880d681SAndroid Build Coastguard Worker break;
2450*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_FALSE:
2451*9880d681SAndroid Build Coastguard Worker ResultReg = createResultReg(&AArch64::GPR32RegClass);
2452*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
2453*9880d681SAndroid Build Coastguard Worker TII.get(TargetOpcode::COPY), ResultReg)
2454*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::WZR, getKillRegState(true));
2455*9880d681SAndroid Build Coastguard Worker break;
2456*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_TRUE:
2457*9880d681SAndroid Build Coastguard Worker ResultReg = fastEmit_i(MVT::i32, MVT::i32, ISD::Constant, 1);
2458*9880d681SAndroid Build Coastguard Worker break;
2459*9880d681SAndroid Build Coastguard Worker }
2460*9880d681SAndroid Build Coastguard Worker
2461*9880d681SAndroid Build Coastguard Worker if (ResultReg) {
2462*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
2463*9880d681SAndroid Build Coastguard Worker return true;
2464*9880d681SAndroid Build Coastguard Worker }
2465*9880d681SAndroid Build Coastguard Worker
2466*9880d681SAndroid Build Coastguard Worker // Emit the cmp.
2467*9880d681SAndroid Build Coastguard Worker if (!emitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned()))
2468*9880d681SAndroid Build Coastguard Worker return false;
2469*9880d681SAndroid Build Coastguard Worker
2470*9880d681SAndroid Build Coastguard Worker ResultReg = createResultReg(&AArch64::GPR32RegClass);
2471*9880d681SAndroid Build Coastguard Worker
2472*9880d681SAndroid Build Coastguard Worker // FCMP_UEQ and FCMP_ONE cannot be checked with a single instruction. These
2473*9880d681SAndroid Build Coastguard Worker // condition codes are inverted, because they are used by CSINC.
2474*9880d681SAndroid Build Coastguard Worker static unsigned CondCodeTable[2][2] = {
2475*9880d681SAndroid Build Coastguard Worker { AArch64CC::NE, AArch64CC::VC },
2476*9880d681SAndroid Build Coastguard Worker { AArch64CC::PL, AArch64CC::LE }
2477*9880d681SAndroid Build Coastguard Worker };
2478*9880d681SAndroid Build Coastguard Worker unsigned *CondCodes = nullptr;
2479*9880d681SAndroid Build Coastguard Worker switch (Predicate) {
2480*9880d681SAndroid Build Coastguard Worker default:
2481*9880d681SAndroid Build Coastguard Worker break;
2482*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_UEQ:
2483*9880d681SAndroid Build Coastguard Worker CondCodes = &CondCodeTable[0][0];
2484*9880d681SAndroid Build Coastguard Worker break;
2485*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_ONE:
2486*9880d681SAndroid Build Coastguard Worker CondCodes = &CondCodeTable[1][0];
2487*9880d681SAndroid Build Coastguard Worker break;
2488*9880d681SAndroid Build Coastguard Worker }
2489*9880d681SAndroid Build Coastguard Worker
2490*9880d681SAndroid Build Coastguard Worker if (CondCodes) {
2491*9880d681SAndroid Build Coastguard Worker unsigned TmpReg1 = createResultReg(&AArch64::GPR32RegClass);
2492*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::CSINCWr),
2493*9880d681SAndroid Build Coastguard Worker TmpReg1)
2494*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::WZR, getKillRegState(true))
2495*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::WZR, getKillRegState(true))
2496*9880d681SAndroid Build Coastguard Worker .addImm(CondCodes[0]);
2497*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::CSINCWr),
2498*9880d681SAndroid Build Coastguard Worker ResultReg)
2499*9880d681SAndroid Build Coastguard Worker .addReg(TmpReg1, getKillRegState(true))
2500*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::WZR, getKillRegState(true))
2501*9880d681SAndroid Build Coastguard Worker .addImm(CondCodes[1]);
2502*9880d681SAndroid Build Coastguard Worker
2503*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
2504*9880d681SAndroid Build Coastguard Worker return true;
2505*9880d681SAndroid Build Coastguard Worker }
2506*9880d681SAndroid Build Coastguard Worker
2507*9880d681SAndroid Build Coastguard Worker // Now set a register based on the comparison.
2508*9880d681SAndroid Build Coastguard Worker AArch64CC::CondCode CC = getCompareCC(Predicate);
2509*9880d681SAndroid Build Coastguard Worker assert((CC != AArch64CC::AL) && "Unexpected condition code.");
2510*9880d681SAndroid Build Coastguard Worker AArch64CC::CondCode invertedCC = getInvertedCondCode(CC);
2511*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::CSINCWr),
2512*9880d681SAndroid Build Coastguard Worker ResultReg)
2513*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::WZR, getKillRegState(true))
2514*9880d681SAndroid Build Coastguard Worker .addReg(AArch64::WZR, getKillRegState(true))
2515*9880d681SAndroid Build Coastguard Worker .addImm(invertedCC);
2516*9880d681SAndroid Build Coastguard Worker
2517*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
2518*9880d681SAndroid Build Coastguard Worker return true;
2519*9880d681SAndroid Build Coastguard Worker }
2520*9880d681SAndroid Build Coastguard Worker
2521*9880d681SAndroid Build Coastguard Worker /// \brief Optimize selects of i1 if one of the operands has a 'true' or 'false'
2522*9880d681SAndroid Build Coastguard Worker /// value.
optimizeSelect(const SelectInst * SI)2523*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::optimizeSelect(const SelectInst *SI) {
2524*9880d681SAndroid Build Coastguard Worker if (!SI->getType()->isIntegerTy(1))
2525*9880d681SAndroid Build Coastguard Worker return false;
2526*9880d681SAndroid Build Coastguard Worker
2527*9880d681SAndroid Build Coastguard Worker const Value *Src1Val, *Src2Val;
2528*9880d681SAndroid Build Coastguard Worker unsigned Opc = 0;
2529*9880d681SAndroid Build Coastguard Worker bool NeedExtraOp = false;
2530*9880d681SAndroid Build Coastguard Worker if (auto *CI = dyn_cast<ConstantInt>(SI->getTrueValue())) {
2531*9880d681SAndroid Build Coastguard Worker if (CI->isOne()) {
2532*9880d681SAndroid Build Coastguard Worker Src1Val = SI->getCondition();
2533*9880d681SAndroid Build Coastguard Worker Src2Val = SI->getFalseValue();
2534*9880d681SAndroid Build Coastguard Worker Opc = AArch64::ORRWrr;
2535*9880d681SAndroid Build Coastguard Worker } else {
2536*9880d681SAndroid Build Coastguard Worker assert(CI->isZero());
2537*9880d681SAndroid Build Coastguard Worker Src1Val = SI->getFalseValue();
2538*9880d681SAndroid Build Coastguard Worker Src2Val = SI->getCondition();
2539*9880d681SAndroid Build Coastguard Worker Opc = AArch64::BICWrr;
2540*9880d681SAndroid Build Coastguard Worker }
2541*9880d681SAndroid Build Coastguard Worker } else if (auto *CI = dyn_cast<ConstantInt>(SI->getFalseValue())) {
2542*9880d681SAndroid Build Coastguard Worker if (CI->isOne()) {
2543*9880d681SAndroid Build Coastguard Worker Src1Val = SI->getCondition();
2544*9880d681SAndroid Build Coastguard Worker Src2Val = SI->getTrueValue();
2545*9880d681SAndroid Build Coastguard Worker Opc = AArch64::ORRWrr;
2546*9880d681SAndroid Build Coastguard Worker NeedExtraOp = true;
2547*9880d681SAndroid Build Coastguard Worker } else {
2548*9880d681SAndroid Build Coastguard Worker assert(CI->isZero());
2549*9880d681SAndroid Build Coastguard Worker Src1Val = SI->getCondition();
2550*9880d681SAndroid Build Coastguard Worker Src2Val = SI->getTrueValue();
2551*9880d681SAndroid Build Coastguard Worker Opc = AArch64::ANDWrr;
2552*9880d681SAndroid Build Coastguard Worker }
2553*9880d681SAndroid Build Coastguard Worker }
2554*9880d681SAndroid Build Coastguard Worker
2555*9880d681SAndroid Build Coastguard Worker if (!Opc)
2556*9880d681SAndroid Build Coastguard Worker return false;
2557*9880d681SAndroid Build Coastguard Worker
2558*9880d681SAndroid Build Coastguard Worker unsigned Src1Reg = getRegForValue(Src1Val);
2559*9880d681SAndroid Build Coastguard Worker if (!Src1Reg)
2560*9880d681SAndroid Build Coastguard Worker return false;
2561*9880d681SAndroid Build Coastguard Worker bool Src1IsKill = hasTrivialKill(Src1Val);
2562*9880d681SAndroid Build Coastguard Worker
2563*9880d681SAndroid Build Coastguard Worker unsigned Src2Reg = getRegForValue(Src2Val);
2564*9880d681SAndroid Build Coastguard Worker if (!Src2Reg)
2565*9880d681SAndroid Build Coastguard Worker return false;
2566*9880d681SAndroid Build Coastguard Worker bool Src2IsKill = hasTrivialKill(Src2Val);
2567*9880d681SAndroid Build Coastguard Worker
2568*9880d681SAndroid Build Coastguard Worker if (NeedExtraOp) {
2569*9880d681SAndroid Build Coastguard Worker Src1Reg = emitLogicalOp_ri(ISD::XOR, MVT::i32, Src1Reg, Src1IsKill, 1);
2570*9880d681SAndroid Build Coastguard Worker Src1IsKill = true;
2571*9880d681SAndroid Build Coastguard Worker }
2572*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = fastEmitInst_rr(Opc, &AArch64::GPR32RegClass, Src1Reg,
2573*9880d681SAndroid Build Coastguard Worker Src1IsKill, Src2Reg, Src2IsKill);
2574*9880d681SAndroid Build Coastguard Worker updateValueMap(SI, ResultReg);
2575*9880d681SAndroid Build Coastguard Worker return true;
2576*9880d681SAndroid Build Coastguard Worker }
2577*9880d681SAndroid Build Coastguard Worker
selectSelect(const Instruction * I)2578*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectSelect(const Instruction *I) {
2579*9880d681SAndroid Build Coastguard Worker assert(isa<SelectInst>(I) && "Expected a select instruction.");
2580*9880d681SAndroid Build Coastguard Worker MVT VT;
2581*9880d681SAndroid Build Coastguard Worker if (!isTypeSupported(I->getType(), VT))
2582*9880d681SAndroid Build Coastguard Worker return false;
2583*9880d681SAndroid Build Coastguard Worker
2584*9880d681SAndroid Build Coastguard Worker unsigned Opc;
2585*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC;
2586*9880d681SAndroid Build Coastguard Worker switch (VT.SimpleTy) {
2587*9880d681SAndroid Build Coastguard Worker default:
2588*9880d681SAndroid Build Coastguard Worker return false;
2589*9880d681SAndroid Build Coastguard Worker case MVT::i1:
2590*9880d681SAndroid Build Coastguard Worker case MVT::i8:
2591*9880d681SAndroid Build Coastguard Worker case MVT::i16:
2592*9880d681SAndroid Build Coastguard Worker case MVT::i32:
2593*9880d681SAndroid Build Coastguard Worker Opc = AArch64::CSELWr;
2594*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR32RegClass;
2595*9880d681SAndroid Build Coastguard Worker break;
2596*9880d681SAndroid Build Coastguard Worker case MVT::i64:
2597*9880d681SAndroid Build Coastguard Worker Opc = AArch64::CSELXr;
2598*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR64RegClass;
2599*9880d681SAndroid Build Coastguard Worker break;
2600*9880d681SAndroid Build Coastguard Worker case MVT::f32:
2601*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FCSELSrrr;
2602*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR32RegClass;
2603*9880d681SAndroid Build Coastguard Worker break;
2604*9880d681SAndroid Build Coastguard Worker case MVT::f64:
2605*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FCSELDrrr;
2606*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR64RegClass;
2607*9880d681SAndroid Build Coastguard Worker break;
2608*9880d681SAndroid Build Coastguard Worker }
2609*9880d681SAndroid Build Coastguard Worker
2610*9880d681SAndroid Build Coastguard Worker const SelectInst *SI = cast<SelectInst>(I);
2611*9880d681SAndroid Build Coastguard Worker const Value *Cond = SI->getCondition();
2612*9880d681SAndroid Build Coastguard Worker AArch64CC::CondCode CC = AArch64CC::NE;
2613*9880d681SAndroid Build Coastguard Worker AArch64CC::CondCode ExtraCC = AArch64CC::AL;
2614*9880d681SAndroid Build Coastguard Worker
2615*9880d681SAndroid Build Coastguard Worker if (optimizeSelect(SI))
2616*9880d681SAndroid Build Coastguard Worker return true;
2617*9880d681SAndroid Build Coastguard Worker
2618*9880d681SAndroid Build Coastguard Worker // Try to pickup the flags, so we don't have to emit another compare.
2619*9880d681SAndroid Build Coastguard Worker if (foldXALUIntrinsic(CC, I, Cond)) {
2620*9880d681SAndroid Build Coastguard Worker // Fake request the condition to force emission of the XALU intrinsic.
2621*9880d681SAndroid Build Coastguard Worker unsigned CondReg = getRegForValue(Cond);
2622*9880d681SAndroid Build Coastguard Worker if (!CondReg)
2623*9880d681SAndroid Build Coastguard Worker return false;
2624*9880d681SAndroid Build Coastguard Worker } else if (isa<CmpInst>(Cond) && cast<CmpInst>(Cond)->hasOneUse() &&
2625*9880d681SAndroid Build Coastguard Worker isValueAvailable(Cond)) {
2626*9880d681SAndroid Build Coastguard Worker const auto *Cmp = cast<CmpInst>(Cond);
2627*9880d681SAndroid Build Coastguard Worker // Try to optimize or fold the cmp.
2628*9880d681SAndroid Build Coastguard Worker CmpInst::Predicate Predicate = optimizeCmpPredicate(Cmp);
2629*9880d681SAndroid Build Coastguard Worker const Value *FoldSelect = nullptr;
2630*9880d681SAndroid Build Coastguard Worker switch (Predicate) {
2631*9880d681SAndroid Build Coastguard Worker default:
2632*9880d681SAndroid Build Coastguard Worker break;
2633*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_FALSE:
2634*9880d681SAndroid Build Coastguard Worker FoldSelect = SI->getFalseValue();
2635*9880d681SAndroid Build Coastguard Worker break;
2636*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_TRUE:
2637*9880d681SAndroid Build Coastguard Worker FoldSelect = SI->getTrueValue();
2638*9880d681SAndroid Build Coastguard Worker break;
2639*9880d681SAndroid Build Coastguard Worker }
2640*9880d681SAndroid Build Coastguard Worker
2641*9880d681SAndroid Build Coastguard Worker if (FoldSelect) {
2642*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = getRegForValue(FoldSelect);
2643*9880d681SAndroid Build Coastguard Worker if (!SrcReg)
2644*9880d681SAndroid Build Coastguard Worker return false;
2645*9880d681SAndroid Build Coastguard Worker unsigned UseReg = lookUpRegForValue(SI);
2646*9880d681SAndroid Build Coastguard Worker if (UseReg)
2647*9880d681SAndroid Build Coastguard Worker MRI.clearKillFlags(UseReg);
2648*9880d681SAndroid Build Coastguard Worker
2649*9880d681SAndroid Build Coastguard Worker updateValueMap(I, SrcReg);
2650*9880d681SAndroid Build Coastguard Worker return true;
2651*9880d681SAndroid Build Coastguard Worker }
2652*9880d681SAndroid Build Coastguard Worker
2653*9880d681SAndroid Build Coastguard Worker // Emit the cmp.
2654*9880d681SAndroid Build Coastguard Worker if (!emitCmp(Cmp->getOperand(0), Cmp->getOperand(1), Cmp->isUnsigned()))
2655*9880d681SAndroid Build Coastguard Worker return false;
2656*9880d681SAndroid Build Coastguard Worker
2657*9880d681SAndroid Build Coastguard Worker // FCMP_UEQ and FCMP_ONE cannot be checked with a single select instruction.
2658*9880d681SAndroid Build Coastguard Worker CC = getCompareCC(Predicate);
2659*9880d681SAndroid Build Coastguard Worker switch (Predicate) {
2660*9880d681SAndroid Build Coastguard Worker default:
2661*9880d681SAndroid Build Coastguard Worker break;
2662*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_UEQ:
2663*9880d681SAndroid Build Coastguard Worker ExtraCC = AArch64CC::EQ;
2664*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::VS;
2665*9880d681SAndroid Build Coastguard Worker break;
2666*9880d681SAndroid Build Coastguard Worker case CmpInst::FCMP_ONE:
2667*9880d681SAndroid Build Coastguard Worker ExtraCC = AArch64CC::MI;
2668*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::GT;
2669*9880d681SAndroid Build Coastguard Worker break;
2670*9880d681SAndroid Build Coastguard Worker }
2671*9880d681SAndroid Build Coastguard Worker assert((CC != AArch64CC::AL) && "Unexpected condition code.");
2672*9880d681SAndroid Build Coastguard Worker } else {
2673*9880d681SAndroid Build Coastguard Worker unsigned CondReg = getRegForValue(Cond);
2674*9880d681SAndroid Build Coastguard Worker if (!CondReg)
2675*9880d681SAndroid Build Coastguard Worker return false;
2676*9880d681SAndroid Build Coastguard Worker bool CondIsKill = hasTrivialKill(Cond);
2677*9880d681SAndroid Build Coastguard Worker
2678*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &II = TII.get(AArch64::ANDSWri);
2679*9880d681SAndroid Build Coastguard Worker CondReg = constrainOperandRegClass(II, CondReg, 1);
2680*9880d681SAndroid Build Coastguard Worker
2681*9880d681SAndroid Build Coastguard Worker // Emit a TST instruction (ANDS wzr, reg, #imm).
2682*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II,
2683*9880d681SAndroid Build Coastguard Worker AArch64::WZR)
2684*9880d681SAndroid Build Coastguard Worker .addReg(CondReg, getKillRegState(CondIsKill))
2685*9880d681SAndroid Build Coastguard Worker .addImm(AArch64_AM::encodeLogicalImmediate(1, 32));
2686*9880d681SAndroid Build Coastguard Worker }
2687*9880d681SAndroid Build Coastguard Worker
2688*9880d681SAndroid Build Coastguard Worker unsigned Src1Reg = getRegForValue(SI->getTrueValue());
2689*9880d681SAndroid Build Coastguard Worker bool Src1IsKill = hasTrivialKill(SI->getTrueValue());
2690*9880d681SAndroid Build Coastguard Worker
2691*9880d681SAndroid Build Coastguard Worker unsigned Src2Reg = getRegForValue(SI->getFalseValue());
2692*9880d681SAndroid Build Coastguard Worker bool Src2IsKill = hasTrivialKill(SI->getFalseValue());
2693*9880d681SAndroid Build Coastguard Worker
2694*9880d681SAndroid Build Coastguard Worker if (!Src1Reg || !Src2Reg)
2695*9880d681SAndroid Build Coastguard Worker return false;
2696*9880d681SAndroid Build Coastguard Worker
2697*9880d681SAndroid Build Coastguard Worker if (ExtraCC != AArch64CC::AL) {
2698*9880d681SAndroid Build Coastguard Worker Src2Reg = fastEmitInst_rri(Opc, RC, Src1Reg, Src1IsKill, Src2Reg,
2699*9880d681SAndroid Build Coastguard Worker Src2IsKill, ExtraCC);
2700*9880d681SAndroid Build Coastguard Worker Src2IsKill = true;
2701*9880d681SAndroid Build Coastguard Worker }
2702*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = fastEmitInst_rri(Opc, RC, Src1Reg, Src1IsKill, Src2Reg,
2703*9880d681SAndroid Build Coastguard Worker Src2IsKill, CC);
2704*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
2705*9880d681SAndroid Build Coastguard Worker return true;
2706*9880d681SAndroid Build Coastguard Worker }
2707*9880d681SAndroid Build Coastguard Worker
selectFPExt(const Instruction * I)2708*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectFPExt(const Instruction *I) {
2709*9880d681SAndroid Build Coastguard Worker Value *V = I->getOperand(0);
2710*9880d681SAndroid Build Coastguard Worker if (!I->getType()->isDoubleTy() || !V->getType()->isFloatTy())
2711*9880d681SAndroid Build Coastguard Worker return false;
2712*9880d681SAndroid Build Coastguard Worker
2713*9880d681SAndroid Build Coastguard Worker unsigned Op = getRegForValue(V);
2714*9880d681SAndroid Build Coastguard Worker if (Op == 0)
2715*9880d681SAndroid Build Coastguard Worker return false;
2716*9880d681SAndroid Build Coastguard Worker
2717*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(&AArch64::FPR64RegClass);
2718*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::FCVTDSr),
2719*9880d681SAndroid Build Coastguard Worker ResultReg).addReg(Op);
2720*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
2721*9880d681SAndroid Build Coastguard Worker return true;
2722*9880d681SAndroid Build Coastguard Worker }
2723*9880d681SAndroid Build Coastguard Worker
selectFPTrunc(const Instruction * I)2724*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectFPTrunc(const Instruction *I) {
2725*9880d681SAndroid Build Coastguard Worker Value *V = I->getOperand(0);
2726*9880d681SAndroid Build Coastguard Worker if (!I->getType()->isFloatTy() || !V->getType()->isDoubleTy())
2727*9880d681SAndroid Build Coastguard Worker return false;
2728*9880d681SAndroid Build Coastguard Worker
2729*9880d681SAndroid Build Coastguard Worker unsigned Op = getRegForValue(V);
2730*9880d681SAndroid Build Coastguard Worker if (Op == 0)
2731*9880d681SAndroid Build Coastguard Worker return false;
2732*9880d681SAndroid Build Coastguard Worker
2733*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(&AArch64::FPR32RegClass);
2734*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::FCVTSDr),
2735*9880d681SAndroid Build Coastguard Worker ResultReg).addReg(Op);
2736*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
2737*9880d681SAndroid Build Coastguard Worker return true;
2738*9880d681SAndroid Build Coastguard Worker }
2739*9880d681SAndroid Build Coastguard Worker
2740*9880d681SAndroid Build Coastguard Worker // FPToUI and FPToSI
selectFPToInt(const Instruction * I,bool Signed)2741*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectFPToInt(const Instruction *I, bool Signed) {
2742*9880d681SAndroid Build Coastguard Worker MVT DestVT;
2743*9880d681SAndroid Build Coastguard Worker if (!isTypeLegal(I->getType(), DestVT) || DestVT.isVector())
2744*9880d681SAndroid Build Coastguard Worker return false;
2745*9880d681SAndroid Build Coastguard Worker
2746*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = getRegForValue(I->getOperand(0));
2747*9880d681SAndroid Build Coastguard Worker if (SrcReg == 0)
2748*9880d681SAndroid Build Coastguard Worker return false;
2749*9880d681SAndroid Build Coastguard Worker
2750*9880d681SAndroid Build Coastguard Worker EVT SrcVT = TLI.getValueType(DL, I->getOperand(0)->getType(), true);
2751*9880d681SAndroid Build Coastguard Worker if (SrcVT == MVT::f128 || SrcVT == MVT::f16)
2752*9880d681SAndroid Build Coastguard Worker return false;
2753*9880d681SAndroid Build Coastguard Worker
2754*9880d681SAndroid Build Coastguard Worker unsigned Opc;
2755*9880d681SAndroid Build Coastguard Worker if (SrcVT == MVT::f64) {
2756*9880d681SAndroid Build Coastguard Worker if (Signed)
2757*9880d681SAndroid Build Coastguard Worker Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWDr : AArch64::FCVTZSUXDr;
2758*9880d681SAndroid Build Coastguard Worker else
2759*9880d681SAndroid Build Coastguard Worker Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWDr : AArch64::FCVTZUUXDr;
2760*9880d681SAndroid Build Coastguard Worker } else {
2761*9880d681SAndroid Build Coastguard Worker if (Signed)
2762*9880d681SAndroid Build Coastguard Worker Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWSr : AArch64::FCVTZSUXSr;
2763*9880d681SAndroid Build Coastguard Worker else
2764*9880d681SAndroid Build Coastguard Worker Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWSr : AArch64::FCVTZUUXSr;
2765*9880d681SAndroid Build Coastguard Worker }
2766*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(
2767*9880d681SAndroid Build Coastguard Worker DestVT == MVT::i32 ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass);
2768*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
2769*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg);
2770*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
2771*9880d681SAndroid Build Coastguard Worker return true;
2772*9880d681SAndroid Build Coastguard Worker }
2773*9880d681SAndroid Build Coastguard Worker
selectIntToFP(const Instruction * I,bool Signed)2774*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectIntToFP(const Instruction *I, bool Signed) {
2775*9880d681SAndroid Build Coastguard Worker MVT DestVT;
2776*9880d681SAndroid Build Coastguard Worker if (!isTypeLegal(I->getType(), DestVT) || DestVT.isVector())
2777*9880d681SAndroid Build Coastguard Worker return false;
2778*9880d681SAndroid Build Coastguard Worker // Let regular ISEL handle FP16
2779*9880d681SAndroid Build Coastguard Worker if (DestVT == MVT::f16)
2780*9880d681SAndroid Build Coastguard Worker return false;
2781*9880d681SAndroid Build Coastguard Worker
2782*9880d681SAndroid Build Coastguard Worker assert((DestVT == MVT::f32 || DestVT == MVT::f64) &&
2783*9880d681SAndroid Build Coastguard Worker "Unexpected value type.");
2784*9880d681SAndroid Build Coastguard Worker
2785*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = getRegForValue(I->getOperand(0));
2786*9880d681SAndroid Build Coastguard Worker if (!SrcReg)
2787*9880d681SAndroid Build Coastguard Worker return false;
2788*9880d681SAndroid Build Coastguard Worker bool SrcIsKill = hasTrivialKill(I->getOperand(0));
2789*9880d681SAndroid Build Coastguard Worker
2790*9880d681SAndroid Build Coastguard Worker EVT SrcVT = TLI.getValueType(DL, I->getOperand(0)->getType(), true);
2791*9880d681SAndroid Build Coastguard Worker
2792*9880d681SAndroid Build Coastguard Worker // Handle sign-extension.
2793*9880d681SAndroid Build Coastguard Worker if (SrcVT == MVT::i16 || SrcVT == MVT::i8 || SrcVT == MVT::i1) {
2794*9880d681SAndroid Build Coastguard Worker SrcReg =
2795*9880d681SAndroid Build Coastguard Worker emitIntExt(SrcVT.getSimpleVT(), SrcReg, MVT::i32, /*isZExt*/ !Signed);
2796*9880d681SAndroid Build Coastguard Worker if (!SrcReg)
2797*9880d681SAndroid Build Coastguard Worker return false;
2798*9880d681SAndroid Build Coastguard Worker SrcIsKill = true;
2799*9880d681SAndroid Build Coastguard Worker }
2800*9880d681SAndroid Build Coastguard Worker
2801*9880d681SAndroid Build Coastguard Worker unsigned Opc;
2802*9880d681SAndroid Build Coastguard Worker if (SrcVT == MVT::i64) {
2803*9880d681SAndroid Build Coastguard Worker if (Signed)
2804*9880d681SAndroid Build Coastguard Worker Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUXSri : AArch64::SCVTFUXDri;
2805*9880d681SAndroid Build Coastguard Worker else
2806*9880d681SAndroid Build Coastguard Worker Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUXSri : AArch64::UCVTFUXDri;
2807*9880d681SAndroid Build Coastguard Worker } else {
2808*9880d681SAndroid Build Coastguard Worker if (Signed)
2809*9880d681SAndroid Build Coastguard Worker Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUWSri : AArch64::SCVTFUWDri;
2810*9880d681SAndroid Build Coastguard Worker else
2811*9880d681SAndroid Build Coastguard Worker Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUWSri : AArch64::UCVTFUWDri;
2812*9880d681SAndroid Build Coastguard Worker }
2813*9880d681SAndroid Build Coastguard Worker
2814*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = fastEmitInst_r(Opc, TLI.getRegClassFor(DestVT), SrcReg,
2815*9880d681SAndroid Build Coastguard Worker SrcIsKill);
2816*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
2817*9880d681SAndroid Build Coastguard Worker return true;
2818*9880d681SAndroid Build Coastguard Worker }
2819*9880d681SAndroid Build Coastguard Worker
fastLowerArguments()2820*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::fastLowerArguments() {
2821*9880d681SAndroid Build Coastguard Worker if (!FuncInfo.CanLowerReturn)
2822*9880d681SAndroid Build Coastguard Worker return false;
2823*9880d681SAndroid Build Coastguard Worker
2824*9880d681SAndroid Build Coastguard Worker const Function *F = FuncInfo.Fn;
2825*9880d681SAndroid Build Coastguard Worker if (F->isVarArg())
2826*9880d681SAndroid Build Coastguard Worker return false;
2827*9880d681SAndroid Build Coastguard Worker
2828*9880d681SAndroid Build Coastguard Worker CallingConv::ID CC = F->getCallingConv();
2829*9880d681SAndroid Build Coastguard Worker if (CC != CallingConv::C)
2830*9880d681SAndroid Build Coastguard Worker return false;
2831*9880d681SAndroid Build Coastguard Worker
2832*9880d681SAndroid Build Coastguard Worker // Only handle simple cases of up to 8 GPR and FPR each.
2833*9880d681SAndroid Build Coastguard Worker unsigned GPRCnt = 0;
2834*9880d681SAndroid Build Coastguard Worker unsigned FPRCnt = 0;
2835*9880d681SAndroid Build Coastguard Worker unsigned Idx = 0;
2836*9880d681SAndroid Build Coastguard Worker for (auto const &Arg : F->args()) {
2837*9880d681SAndroid Build Coastguard Worker // The first argument is at index 1.
2838*9880d681SAndroid Build Coastguard Worker ++Idx;
2839*9880d681SAndroid Build Coastguard Worker if (F->getAttributes().hasAttribute(Idx, Attribute::ByVal) ||
2840*9880d681SAndroid Build Coastguard Worker F->getAttributes().hasAttribute(Idx, Attribute::InReg) ||
2841*9880d681SAndroid Build Coastguard Worker F->getAttributes().hasAttribute(Idx, Attribute::StructRet) ||
2842*9880d681SAndroid Build Coastguard Worker F->getAttributes().hasAttribute(Idx, Attribute::SwiftSelf) ||
2843*9880d681SAndroid Build Coastguard Worker F->getAttributes().hasAttribute(Idx, Attribute::SwiftError) ||
2844*9880d681SAndroid Build Coastguard Worker F->getAttributes().hasAttribute(Idx, Attribute::Nest))
2845*9880d681SAndroid Build Coastguard Worker return false;
2846*9880d681SAndroid Build Coastguard Worker
2847*9880d681SAndroid Build Coastguard Worker Type *ArgTy = Arg.getType();
2848*9880d681SAndroid Build Coastguard Worker if (ArgTy->isStructTy() || ArgTy->isArrayTy())
2849*9880d681SAndroid Build Coastguard Worker return false;
2850*9880d681SAndroid Build Coastguard Worker
2851*9880d681SAndroid Build Coastguard Worker EVT ArgVT = TLI.getValueType(DL, ArgTy);
2852*9880d681SAndroid Build Coastguard Worker if (!ArgVT.isSimple())
2853*9880d681SAndroid Build Coastguard Worker return false;
2854*9880d681SAndroid Build Coastguard Worker
2855*9880d681SAndroid Build Coastguard Worker MVT VT = ArgVT.getSimpleVT().SimpleTy;
2856*9880d681SAndroid Build Coastguard Worker if (VT.isFloatingPoint() && !Subtarget->hasFPARMv8())
2857*9880d681SAndroid Build Coastguard Worker return false;
2858*9880d681SAndroid Build Coastguard Worker
2859*9880d681SAndroid Build Coastguard Worker if (VT.isVector() &&
2860*9880d681SAndroid Build Coastguard Worker (!Subtarget->hasNEON() || !Subtarget->isLittleEndian()))
2861*9880d681SAndroid Build Coastguard Worker return false;
2862*9880d681SAndroid Build Coastguard Worker
2863*9880d681SAndroid Build Coastguard Worker if (VT >= MVT::i1 && VT <= MVT::i64)
2864*9880d681SAndroid Build Coastguard Worker ++GPRCnt;
2865*9880d681SAndroid Build Coastguard Worker else if ((VT >= MVT::f16 && VT <= MVT::f64) || VT.is64BitVector() ||
2866*9880d681SAndroid Build Coastguard Worker VT.is128BitVector())
2867*9880d681SAndroid Build Coastguard Worker ++FPRCnt;
2868*9880d681SAndroid Build Coastguard Worker else
2869*9880d681SAndroid Build Coastguard Worker return false;
2870*9880d681SAndroid Build Coastguard Worker
2871*9880d681SAndroid Build Coastguard Worker if (GPRCnt > 8 || FPRCnt > 8)
2872*9880d681SAndroid Build Coastguard Worker return false;
2873*9880d681SAndroid Build Coastguard Worker }
2874*9880d681SAndroid Build Coastguard Worker
2875*9880d681SAndroid Build Coastguard Worker static const MCPhysReg Registers[6][8] = {
2876*9880d681SAndroid Build Coastguard Worker { AArch64::W0, AArch64::W1, AArch64::W2, AArch64::W3, AArch64::W4,
2877*9880d681SAndroid Build Coastguard Worker AArch64::W5, AArch64::W6, AArch64::W7 },
2878*9880d681SAndroid Build Coastguard Worker { AArch64::X0, AArch64::X1, AArch64::X2, AArch64::X3, AArch64::X4,
2879*9880d681SAndroid Build Coastguard Worker AArch64::X5, AArch64::X6, AArch64::X7 },
2880*9880d681SAndroid Build Coastguard Worker { AArch64::H0, AArch64::H1, AArch64::H2, AArch64::H3, AArch64::H4,
2881*9880d681SAndroid Build Coastguard Worker AArch64::H5, AArch64::H6, AArch64::H7 },
2882*9880d681SAndroid Build Coastguard Worker { AArch64::S0, AArch64::S1, AArch64::S2, AArch64::S3, AArch64::S4,
2883*9880d681SAndroid Build Coastguard Worker AArch64::S5, AArch64::S6, AArch64::S7 },
2884*9880d681SAndroid Build Coastguard Worker { AArch64::D0, AArch64::D1, AArch64::D2, AArch64::D3, AArch64::D4,
2885*9880d681SAndroid Build Coastguard Worker AArch64::D5, AArch64::D6, AArch64::D7 },
2886*9880d681SAndroid Build Coastguard Worker { AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,
2887*9880d681SAndroid Build Coastguard Worker AArch64::Q5, AArch64::Q6, AArch64::Q7 }
2888*9880d681SAndroid Build Coastguard Worker };
2889*9880d681SAndroid Build Coastguard Worker
2890*9880d681SAndroid Build Coastguard Worker unsigned GPRIdx = 0;
2891*9880d681SAndroid Build Coastguard Worker unsigned FPRIdx = 0;
2892*9880d681SAndroid Build Coastguard Worker for (auto const &Arg : F->args()) {
2893*9880d681SAndroid Build Coastguard Worker MVT VT = TLI.getSimpleValueType(DL, Arg.getType());
2894*9880d681SAndroid Build Coastguard Worker unsigned SrcReg;
2895*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC;
2896*9880d681SAndroid Build Coastguard Worker if (VT >= MVT::i1 && VT <= MVT::i32) {
2897*9880d681SAndroid Build Coastguard Worker SrcReg = Registers[0][GPRIdx++];
2898*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR32RegClass;
2899*9880d681SAndroid Build Coastguard Worker VT = MVT::i32;
2900*9880d681SAndroid Build Coastguard Worker } else if (VT == MVT::i64) {
2901*9880d681SAndroid Build Coastguard Worker SrcReg = Registers[1][GPRIdx++];
2902*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR64RegClass;
2903*9880d681SAndroid Build Coastguard Worker } else if (VT == MVT::f16) {
2904*9880d681SAndroid Build Coastguard Worker SrcReg = Registers[2][FPRIdx++];
2905*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR16RegClass;
2906*9880d681SAndroid Build Coastguard Worker } else if (VT == MVT::f32) {
2907*9880d681SAndroid Build Coastguard Worker SrcReg = Registers[3][FPRIdx++];
2908*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR32RegClass;
2909*9880d681SAndroid Build Coastguard Worker } else if ((VT == MVT::f64) || VT.is64BitVector()) {
2910*9880d681SAndroid Build Coastguard Worker SrcReg = Registers[4][FPRIdx++];
2911*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR64RegClass;
2912*9880d681SAndroid Build Coastguard Worker } else if (VT.is128BitVector()) {
2913*9880d681SAndroid Build Coastguard Worker SrcReg = Registers[5][FPRIdx++];
2914*9880d681SAndroid Build Coastguard Worker RC = &AArch64::FPR128RegClass;
2915*9880d681SAndroid Build Coastguard Worker } else
2916*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected value type.");
2917*9880d681SAndroid Build Coastguard Worker
2918*9880d681SAndroid Build Coastguard Worker unsigned DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
2919*9880d681SAndroid Build Coastguard Worker // FIXME: Unfortunately it's necessary to emit a copy from the livein copy.
2920*9880d681SAndroid Build Coastguard Worker // Without this, EmitLiveInCopies may eliminate the livein if its only
2921*9880d681SAndroid Build Coastguard Worker // use is a bitcast (which isn't turned into an instruction).
2922*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(RC);
2923*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
2924*9880d681SAndroid Build Coastguard Worker TII.get(TargetOpcode::COPY), ResultReg)
2925*9880d681SAndroid Build Coastguard Worker .addReg(DstReg, getKillRegState(true));
2926*9880d681SAndroid Build Coastguard Worker updateValueMap(&Arg, ResultReg);
2927*9880d681SAndroid Build Coastguard Worker }
2928*9880d681SAndroid Build Coastguard Worker return true;
2929*9880d681SAndroid Build Coastguard Worker }
2930*9880d681SAndroid Build Coastguard Worker
processCallArgs(CallLoweringInfo & CLI,SmallVectorImpl<MVT> & OutVTs,unsigned & NumBytes)2931*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::processCallArgs(CallLoweringInfo &CLI,
2932*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MVT> &OutVTs,
2933*9880d681SAndroid Build Coastguard Worker unsigned &NumBytes) {
2934*9880d681SAndroid Build Coastguard Worker CallingConv::ID CC = CLI.CallConv;
2935*9880d681SAndroid Build Coastguard Worker SmallVector<CCValAssign, 16> ArgLocs;
2936*9880d681SAndroid Build Coastguard Worker CCState CCInfo(CC, false, *FuncInfo.MF, ArgLocs, *Context);
2937*9880d681SAndroid Build Coastguard Worker CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, CCAssignFnForCall(CC));
2938*9880d681SAndroid Build Coastguard Worker
2939*9880d681SAndroid Build Coastguard Worker // Get a count of how many bytes are to be pushed on the stack.
2940*9880d681SAndroid Build Coastguard Worker NumBytes = CCInfo.getNextStackOffset();
2941*9880d681SAndroid Build Coastguard Worker
2942*9880d681SAndroid Build Coastguard Worker // Issue CALLSEQ_START
2943*9880d681SAndroid Build Coastguard Worker unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
2944*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AdjStackDown))
2945*9880d681SAndroid Build Coastguard Worker .addImm(NumBytes);
2946*9880d681SAndroid Build Coastguard Worker
2947*9880d681SAndroid Build Coastguard Worker // Process the args.
2948*9880d681SAndroid Build Coastguard Worker for (CCValAssign &VA : ArgLocs) {
2949*9880d681SAndroid Build Coastguard Worker const Value *ArgVal = CLI.OutVals[VA.getValNo()];
2950*9880d681SAndroid Build Coastguard Worker MVT ArgVT = OutVTs[VA.getValNo()];
2951*9880d681SAndroid Build Coastguard Worker
2952*9880d681SAndroid Build Coastguard Worker unsigned ArgReg = getRegForValue(ArgVal);
2953*9880d681SAndroid Build Coastguard Worker if (!ArgReg)
2954*9880d681SAndroid Build Coastguard Worker return false;
2955*9880d681SAndroid Build Coastguard Worker
2956*9880d681SAndroid Build Coastguard Worker // Handle arg promotion: SExt, ZExt, AExt.
2957*9880d681SAndroid Build Coastguard Worker switch (VA.getLocInfo()) {
2958*9880d681SAndroid Build Coastguard Worker case CCValAssign::Full:
2959*9880d681SAndroid Build Coastguard Worker break;
2960*9880d681SAndroid Build Coastguard Worker case CCValAssign::SExt: {
2961*9880d681SAndroid Build Coastguard Worker MVT DestVT = VA.getLocVT();
2962*9880d681SAndroid Build Coastguard Worker MVT SrcVT = ArgVT;
2963*9880d681SAndroid Build Coastguard Worker ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/false);
2964*9880d681SAndroid Build Coastguard Worker if (!ArgReg)
2965*9880d681SAndroid Build Coastguard Worker return false;
2966*9880d681SAndroid Build Coastguard Worker break;
2967*9880d681SAndroid Build Coastguard Worker }
2968*9880d681SAndroid Build Coastguard Worker case CCValAssign::AExt:
2969*9880d681SAndroid Build Coastguard Worker // Intentional fall-through.
2970*9880d681SAndroid Build Coastguard Worker case CCValAssign::ZExt: {
2971*9880d681SAndroid Build Coastguard Worker MVT DestVT = VA.getLocVT();
2972*9880d681SAndroid Build Coastguard Worker MVT SrcVT = ArgVT;
2973*9880d681SAndroid Build Coastguard Worker ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/true);
2974*9880d681SAndroid Build Coastguard Worker if (!ArgReg)
2975*9880d681SAndroid Build Coastguard Worker return false;
2976*9880d681SAndroid Build Coastguard Worker break;
2977*9880d681SAndroid Build Coastguard Worker }
2978*9880d681SAndroid Build Coastguard Worker default:
2979*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown arg promotion!");
2980*9880d681SAndroid Build Coastguard Worker }
2981*9880d681SAndroid Build Coastguard Worker
2982*9880d681SAndroid Build Coastguard Worker // Now copy/store arg to correct locations.
2983*9880d681SAndroid Build Coastguard Worker if (VA.isRegLoc() && !VA.needsCustom()) {
2984*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
2985*9880d681SAndroid Build Coastguard Worker TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(ArgReg);
2986*9880d681SAndroid Build Coastguard Worker CLI.OutRegs.push_back(VA.getLocReg());
2987*9880d681SAndroid Build Coastguard Worker } else if (VA.needsCustom()) {
2988*9880d681SAndroid Build Coastguard Worker // FIXME: Handle custom args.
2989*9880d681SAndroid Build Coastguard Worker return false;
2990*9880d681SAndroid Build Coastguard Worker } else {
2991*9880d681SAndroid Build Coastguard Worker assert(VA.isMemLoc() && "Assuming store on stack.");
2992*9880d681SAndroid Build Coastguard Worker
2993*9880d681SAndroid Build Coastguard Worker // Don't emit stores for undef values.
2994*9880d681SAndroid Build Coastguard Worker if (isa<UndefValue>(ArgVal))
2995*9880d681SAndroid Build Coastguard Worker continue;
2996*9880d681SAndroid Build Coastguard Worker
2997*9880d681SAndroid Build Coastguard Worker // Need to store on the stack.
2998*9880d681SAndroid Build Coastguard Worker unsigned ArgSize = (ArgVT.getSizeInBits() + 7) / 8;
2999*9880d681SAndroid Build Coastguard Worker
3000*9880d681SAndroid Build Coastguard Worker unsigned BEAlign = 0;
3001*9880d681SAndroid Build Coastguard Worker if (ArgSize < 8 && !Subtarget->isLittleEndian())
3002*9880d681SAndroid Build Coastguard Worker BEAlign = 8 - ArgSize;
3003*9880d681SAndroid Build Coastguard Worker
3004*9880d681SAndroid Build Coastguard Worker Address Addr;
3005*9880d681SAndroid Build Coastguard Worker Addr.setKind(Address::RegBase);
3006*9880d681SAndroid Build Coastguard Worker Addr.setReg(AArch64::SP);
3007*9880d681SAndroid Build Coastguard Worker Addr.setOffset(VA.getLocMemOffset() + BEAlign);
3008*9880d681SAndroid Build Coastguard Worker
3009*9880d681SAndroid Build Coastguard Worker unsigned Alignment = DL.getABITypeAlignment(ArgVal->getType());
3010*9880d681SAndroid Build Coastguard Worker MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
3011*9880d681SAndroid Build Coastguard Worker MachinePointerInfo::getStack(*FuncInfo.MF, Addr.getOffset()),
3012*9880d681SAndroid Build Coastguard Worker MachineMemOperand::MOStore, ArgVT.getStoreSize(), Alignment);
3013*9880d681SAndroid Build Coastguard Worker
3014*9880d681SAndroid Build Coastguard Worker if (!emitStore(ArgVT, ArgReg, Addr, MMO))
3015*9880d681SAndroid Build Coastguard Worker return false;
3016*9880d681SAndroid Build Coastguard Worker }
3017*9880d681SAndroid Build Coastguard Worker }
3018*9880d681SAndroid Build Coastguard Worker return true;
3019*9880d681SAndroid Build Coastguard Worker }
3020*9880d681SAndroid Build Coastguard Worker
finishCall(CallLoweringInfo & CLI,MVT RetVT,unsigned NumBytes)3021*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::finishCall(CallLoweringInfo &CLI, MVT RetVT,
3022*9880d681SAndroid Build Coastguard Worker unsigned NumBytes) {
3023*9880d681SAndroid Build Coastguard Worker CallingConv::ID CC = CLI.CallConv;
3024*9880d681SAndroid Build Coastguard Worker
3025*9880d681SAndroid Build Coastguard Worker // Issue CALLSEQ_END
3026*9880d681SAndroid Build Coastguard Worker unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
3027*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AdjStackUp))
3028*9880d681SAndroid Build Coastguard Worker .addImm(NumBytes).addImm(0);
3029*9880d681SAndroid Build Coastguard Worker
3030*9880d681SAndroid Build Coastguard Worker // Now the return value.
3031*9880d681SAndroid Build Coastguard Worker if (RetVT != MVT::isVoid) {
3032*9880d681SAndroid Build Coastguard Worker SmallVector<CCValAssign, 16> RVLocs;
3033*9880d681SAndroid Build Coastguard Worker CCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context);
3034*9880d681SAndroid Build Coastguard Worker CCInfo.AnalyzeCallResult(RetVT, CCAssignFnForCall(CC));
3035*9880d681SAndroid Build Coastguard Worker
3036*9880d681SAndroid Build Coastguard Worker // Only handle a single return value.
3037*9880d681SAndroid Build Coastguard Worker if (RVLocs.size() != 1)
3038*9880d681SAndroid Build Coastguard Worker return false;
3039*9880d681SAndroid Build Coastguard Worker
3040*9880d681SAndroid Build Coastguard Worker // Copy all of the result registers out of their specified physreg.
3041*9880d681SAndroid Build Coastguard Worker MVT CopyVT = RVLocs[0].getValVT();
3042*9880d681SAndroid Build Coastguard Worker
3043*9880d681SAndroid Build Coastguard Worker // TODO: Handle big-endian results
3044*9880d681SAndroid Build Coastguard Worker if (CopyVT.isVector() && !Subtarget->isLittleEndian())
3045*9880d681SAndroid Build Coastguard Worker return false;
3046*9880d681SAndroid Build Coastguard Worker
3047*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(TLI.getRegClassFor(CopyVT));
3048*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3049*9880d681SAndroid Build Coastguard Worker TII.get(TargetOpcode::COPY), ResultReg)
3050*9880d681SAndroid Build Coastguard Worker .addReg(RVLocs[0].getLocReg());
3051*9880d681SAndroid Build Coastguard Worker CLI.InRegs.push_back(RVLocs[0].getLocReg());
3052*9880d681SAndroid Build Coastguard Worker
3053*9880d681SAndroid Build Coastguard Worker CLI.ResultReg = ResultReg;
3054*9880d681SAndroid Build Coastguard Worker CLI.NumResultRegs = 1;
3055*9880d681SAndroid Build Coastguard Worker }
3056*9880d681SAndroid Build Coastguard Worker
3057*9880d681SAndroid Build Coastguard Worker return true;
3058*9880d681SAndroid Build Coastguard Worker }
3059*9880d681SAndroid Build Coastguard Worker
fastLowerCall(CallLoweringInfo & CLI)3060*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
3061*9880d681SAndroid Build Coastguard Worker CallingConv::ID CC = CLI.CallConv;
3062*9880d681SAndroid Build Coastguard Worker bool IsTailCall = CLI.IsTailCall;
3063*9880d681SAndroid Build Coastguard Worker bool IsVarArg = CLI.IsVarArg;
3064*9880d681SAndroid Build Coastguard Worker const Value *Callee = CLI.Callee;
3065*9880d681SAndroid Build Coastguard Worker MCSymbol *Symbol = CLI.Symbol;
3066*9880d681SAndroid Build Coastguard Worker
3067*9880d681SAndroid Build Coastguard Worker if (!Callee && !Symbol)
3068*9880d681SAndroid Build Coastguard Worker return false;
3069*9880d681SAndroid Build Coastguard Worker
3070*9880d681SAndroid Build Coastguard Worker // Allow SelectionDAG isel to handle tail calls.
3071*9880d681SAndroid Build Coastguard Worker if (IsTailCall)
3072*9880d681SAndroid Build Coastguard Worker return false;
3073*9880d681SAndroid Build Coastguard Worker
3074*9880d681SAndroid Build Coastguard Worker CodeModel::Model CM = TM.getCodeModel();
3075*9880d681SAndroid Build Coastguard Worker // Only support the small and large code model.
3076*9880d681SAndroid Build Coastguard Worker if (CM != CodeModel::Small && CM != CodeModel::Large)
3077*9880d681SAndroid Build Coastguard Worker return false;
3078*9880d681SAndroid Build Coastguard Worker
3079*9880d681SAndroid Build Coastguard Worker // FIXME: Add large code model support for ELF.
3080*9880d681SAndroid Build Coastguard Worker if (CM == CodeModel::Large && !Subtarget->isTargetMachO())
3081*9880d681SAndroid Build Coastguard Worker return false;
3082*9880d681SAndroid Build Coastguard Worker
3083*9880d681SAndroid Build Coastguard Worker // Let SDISel handle vararg functions.
3084*9880d681SAndroid Build Coastguard Worker if (IsVarArg)
3085*9880d681SAndroid Build Coastguard Worker return false;
3086*9880d681SAndroid Build Coastguard Worker
3087*9880d681SAndroid Build Coastguard Worker // FIXME: Only handle *simple* calls for now.
3088*9880d681SAndroid Build Coastguard Worker MVT RetVT;
3089*9880d681SAndroid Build Coastguard Worker if (CLI.RetTy->isVoidTy())
3090*9880d681SAndroid Build Coastguard Worker RetVT = MVT::isVoid;
3091*9880d681SAndroid Build Coastguard Worker else if (!isTypeLegal(CLI.RetTy, RetVT))
3092*9880d681SAndroid Build Coastguard Worker return false;
3093*9880d681SAndroid Build Coastguard Worker
3094*9880d681SAndroid Build Coastguard Worker for (auto Flag : CLI.OutFlags)
3095*9880d681SAndroid Build Coastguard Worker if (Flag.isInReg() || Flag.isSRet() || Flag.isNest() || Flag.isByVal() ||
3096*9880d681SAndroid Build Coastguard Worker Flag.isSwiftSelf() || Flag.isSwiftError())
3097*9880d681SAndroid Build Coastguard Worker return false;
3098*9880d681SAndroid Build Coastguard Worker
3099*9880d681SAndroid Build Coastguard Worker // Set up the argument vectors.
3100*9880d681SAndroid Build Coastguard Worker SmallVector<MVT, 16> OutVTs;
3101*9880d681SAndroid Build Coastguard Worker OutVTs.reserve(CLI.OutVals.size());
3102*9880d681SAndroid Build Coastguard Worker
3103*9880d681SAndroid Build Coastguard Worker for (auto *Val : CLI.OutVals) {
3104*9880d681SAndroid Build Coastguard Worker MVT VT;
3105*9880d681SAndroid Build Coastguard Worker if (!isTypeLegal(Val->getType(), VT) &&
3106*9880d681SAndroid Build Coastguard Worker !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16))
3107*9880d681SAndroid Build Coastguard Worker return false;
3108*9880d681SAndroid Build Coastguard Worker
3109*9880d681SAndroid Build Coastguard Worker // We don't handle vector parameters yet.
3110*9880d681SAndroid Build Coastguard Worker if (VT.isVector() || VT.getSizeInBits() > 64)
3111*9880d681SAndroid Build Coastguard Worker return false;
3112*9880d681SAndroid Build Coastguard Worker
3113*9880d681SAndroid Build Coastguard Worker OutVTs.push_back(VT);
3114*9880d681SAndroid Build Coastguard Worker }
3115*9880d681SAndroid Build Coastguard Worker
3116*9880d681SAndroid Build Coastguard Worker Address Addr;
3117*9880d681SAndroid Build Coastguard Worker if (Callee && !computeCallAddress(Callee, Addr))
3118*9880d681SAndroid Build Coastguard Worker return false;
3119*9880d681SAndroid Build Coastguard Worker
3120*9880d681SAndroid Build Coastguard Worker // Handle the arguments now that we've gotten them.
3121*9880d681SAndroid Build Coastguard Worker unsigned NumBytes;
3122*9880d681SAndroid Build Coastguard Worker if (!processCallArgs(CLI, OutVTs, NumBytes))
3123*9880d681SAndroid Build Coastguard Worker return false;
3124*9880d681SAndroid Build Coastguard Worker
3125*9880d681SAndroid Build Coastguard Worker // Issue the call.
3126*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB;
3127*9880d681SAndroid Build Coastguard Worker if (CM == CodeModel::Small) {
3128*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &II = TII.get(Addr.getReg() ? AArch64::BLR : AArch64::BL);
3129*9880d681SAndroid Build Coastguard Worker MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II);
3130*9880d681SAndroid Build Coastguard Worker if (Symbol)
3131*9880d681SAndroid Build Coastguard Worker MIB.addSym(Symbol, 0);
3132*9880d681SAndroid Build Coastguard Worker else if (Addr.getGlobalValue())
3133*9880d681SAndroid Build Coastguard Worker MIB.addGlobalAddress(Addr.getGlobalValue(), 0, 0);
3134*9880d681SAndroid Build Coastguard Worker else if (Addr.getReg()) {
3135*9880d681SAndroid Build Coastguard Worker unsigned Reg = constrainOperandRegClass(II, Addr.getReg(), 0);
3136*9880d681SAndroid Build Coastguard Worker MIB.addReg(Reg);
3137*9880d681SAndroid Build Coastguard Worker } else
3138*9880d681SAndroid Build Coastguard Worker return false;
3139*9880d681SAndroid Build Coastguard Worker } else {
3140*9880d681SAndroid Build Coastguard Worker unsigned CallReg = 0;
3141*9880d681SAndroid Build Coastguard Worker if (Symbol) {
3142*9880d681SAndroid Build Coastguard Worker unsigned ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
3143*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADRP),
3144*9880d681SAndroid Build Coastguard Worker ADRPReg)
3145*9880d681SAndroid Build Coastguard Worker .addSym(Symbol, AArch64II::MO_GOT | AArch64II::MO_PAGE);
3146*9880d681SAndroid Build Coastguard Worker
3147*9880d681SAndroid Build Coastguard Worker CallReg = createResultReg(&AArch64::GPR64RegClass);
3148*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3149*9880d681SAndroid Build Coastguard Worker TII.get(AArch64::LDRXui), CallReg)
3150*9880d681SAndroid Build Coastguard Worker .addReg(ADRPReg)
3151*9880d681SAndroid Build Coastguard Worker .addSym(Symbol,
3152*9880d681SAndroid Build Coastguard Worker AArch64II::MO_GOT | AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
3153*9880d681SAndroid Build Coastguard Worker } else if (Addr.getGlobalValue())
3154*9880d681SAndroid Build Coastguard Worker CallReg = materializeGV(Addr.getGlobalValue());
3155*9880d681SAndroid Build Coastguard Worker else if (Addr.getReg())
3156*9880d681SAndroid Build Coastguard Worker CallReg = Addr.getReg();
3157*9880d681SAndroid Build Coastguard Worker
3158*9880d681SAndroid Build Coastguard Worker if (!CallReg)
3159*9880d681SAndroid Build Coastguard Worker return false;
3160*9880d681SAndroid Build Coastguard Worker
3161*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &II = TII.get(AArch64::BLR);
3162*9880d681SAndroid Build Coastguard Worker CallReg = constrainOperandRegClass(II, CallReg, 0);
3163*9880d681SAndroid Build Coastguard Worker MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II).addReg(CallReg);
3164*9880d681SAndroid Build Coastguard Worker }
3165*9880d681SAndroid Build Coastguard Worker
3166*9880d681SAndroid Build Coastguard Worker // Add implicit physical register uses to the call.
3167*9880d681SAndroid Build Coastguard Worker for (auto Reg : CLI.OutRegs)
3168*9880d681SAndroid Build Coastguard Worker MIB.addReg(Reg, RegState::Implicit);
3169*9880d681SAndroid Build Coastguard Worker
3170*9880d681SAndroid Build Coastguard Worker // Add a register mask with the call-preserved registers.
3171*9880d681SAndroid Build Coastguard Worker // Proper defs for return values will be added by setPhysRegsDeadExcept().
3172*9880d681SAndroid Build Coastguard Worker MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC));
3173*9880d681SAndroid Build Coastguard Worker
3174*9880d681SAndroid Build Coastguard Worker CLI.Call = MIB;
3175*9880d681SAndroid Build Coastguard Worker
3176*9880d681SAndroid Build Coastguard Worker // Finish off the call including any return values.
3177*9880d681SAndroid Build Coastguard Worker return finishCall(CLI, RetVT, NumBytes);
3178*9880d681SAndroid Build Coastguard Worker }
3179*9880d681SAndroid Build Coastguard Worker
isMemCpySmall(uint64_t Len,unsigned Alignment)3180*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::isMemCpySmall(uint64_t Len, unsigned Alignment) {
3181*9880d681SAndroid Build Coastguard Worker if (Alignment)
3182*9880d681SAndroid Build Coastguard Worker return Len / Alignment <= 4;
3183*9880d681SAndroid Build Coastguard Worker else
3184*9880d681SAndroid Build Coastguard Worker return Len < 32;
3185*9880d681SAndroid Build Coastguard Worker }
3186*9880d681SAndroid Build Coastguard Worker
tryEmitSmallMemCpy(Address Dest,Address Src,uint64_t Len,unsigned Alignment)3187*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::tryEmitSmallMemCpy(Address Dest, Address Src,
3188*9880d681SAndroid Build Coastguard Worker uint64_t Len, unsigned Alignment) {
3189*9880d681SAndroid Build Coastguard Worker // Make sure we don't bloat code by inlining very large memcpy's.
3190*9880d681SAndroid Build Coastguard Worker if (!isMemCpySmall(Len, Alignment))
3191*9880d681SAndroid Build Coastguard Worker return false;
3192*9880d681SAndroid Build Coastguard Worker
3193*9880d681SAndroid Build Coastguard Worker int64_t UnscaledOffset = 0;
3194*9880d681SAndroid Build Coastguard Worker Address OrigDest = Dest;
3195*9880d681SAndroid Build Coastguard Worker Address OrigSrc = Src;
3196*9880d681SAndroid Build Coastguard Worker
3197*9880d681SAndroid Build Coastguard Worker while (Len) {
3198*9880d681SAndroid Build Coastguard Worker MVT VT;
3199*9880d681SAndroid Build Coastguard Worker if (!Alignment || Alignment >= 8) {
3200*9880d681SAndroid Build Coastguard Worker if (Len >= 8)
3201*9880d681SAndroid Build Coastguard Worker VT = MVT::i64;
3202*9880d681SAndroid Build Coastguard Worker else if (Len >= 4)
3203*9880d681SAndroid Build Coastguard Worker VT = MVT::i32;
3204*9880d681SAndroid Build Coastguard Worker else if (Len >= 2)
3205*9880d681SAndroid Build Coastguard Worker VT = MVT::i16;
3206*9880d681SAndroid Build Coastguard Worker else {
3207*9880d681SAndroid Build Coastguard Worker VT = MVT::i8;
3208*9880d681SAndroid Build Coastguard Worker }
3209*9880d681SAndroid Build Coastguard Worker } else {
3210*9880d681SAndroid Build Coastguard Worker // Bound based on alignment.
3211*9880d681SAndroid Build Coastguard Worker if (Len >= 4 && Alignment == 4)
3212*9880d681SAndroid Build Coastguard Worker VT = MVT::i32;
3213*9880d681SAndroid Build Coastguard Worker else if (Len >= 2 && Alignment == 2)
3214*9880d681SAndroid Build Coastguard Worker VT = MVT::i16;
3215*9880d681SAndroid Build Coastguard Worker else {
3216*9880d681SAndroid Build Coastguard Worker VT = MVT::i8;
3217*9880d681SAndroid Build Coastguard Worker }
3218*9880d681SAndroid Build Coastguard Worker }
3219*9880d681SAndroid Build Coastguard Worker
3220*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = emitLoad(VT, VT, Src);
3221*9880d681SAndroid Build Coastguard Worker if (!ResultReg)
3222*9880d681SAndroid Build Coastguard Worker return false;
3223*9880d681SAndroid Build Coastguard Worker
3224*9880d681SAndroid Build Coastguard Worker if (!emitStore(VT, ResultReg, Dest))
3225*9880d681SAndroid Build Coastguard Worker return false;
3226*9880d681SAndroid Build Coastguard Worker
3227*9880d681SAndroid Build Coastguard Worker int64_t Size = VT.getSizeInBits() / 8;
3228*9880d681SAndroid Build Coastguard Worker Len -= Size;
3229*9880d681SAndroid Build Coastguard Worker UnscaledOffset += Size;
3230*9880d681SAndroid Build Coastguard Worker
3231*9880d681SAndroid Build Coastguard Worker // We need to recompute the unscaled offset for each iteration.
3232*9880d681SAndroid Build Coastguard Worker Dest.setOffset(OrigDest.getOffset() + UnscaledOffset);
3233*9880d681SAndroid Build Coastguard Worker Src.setOffset(OrigSrc.getOffset() + UnscaledOffset);
3234*9880d681SAndroid Build Coastguard Worker }
3235*9880d681SAndroid Build Coastguard Worker
3236*9880d681SAndroid Build Coastguard Worker return true;
3237*9880d681SAndroid Build Coastguard Worker }
3238*9880d681SAndroid Build Coastguard Worker
3239*9880d681SAndroid Build Coastguard Worker /// \brief Check if it is possible to fold the condition from the XALU intrinsic
3240*9880d681SAndroid Build Coastguard Worker /// into the user. The condition code will only be updated on success.
foldXALUIntrinsic(AArch64CC::CondCode & CC,const Instruction * I,const Value * Cond)3241*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::foldXALUIntrinsic(AArch64CC::CondCode &CC,
3242*9880d681SAndroid Build Coastguard Worker const Instruction *I,
3243*9880d681SAndroid Build Coastguard Worker const Value *Cond) {
3244*9880d681SAndroid Build Coastguard Worker if (!isa<ExtractValueInst>(Cond))
3245*9880d681SAndroid Build Coastguard Worker return false;
3246*9880d681SAndroid Build Coastguard Worker
3247*9880d681SAndroid Build Coastguard Worker const auto *EV = cast<ExtractValueInst>(Cond);
3248*9880d681SAndroid Build Coastguard Worker if (!isa<IntrinsicInst>(EV->getAggregateOperand()))
3249*9880d681SAndroid Build Coastguard Worker return false;
3250*9880d681SAndroid Build Coastguard Worker
3251*9880d681SAndroid Build Coastguard Worker const auto *II = cast<IntrinsicInst>(EV->getAggregateOperand());
3252*9880d681SAndroid Build Coastguard Worker MVT RetVT;
3253*9880d681SAndroid Build Coastguard Worker const Function *Callee = II->getCalledFunction();
3254*9880d681SAndroid Build Coastguard Worker Type *RetTy =
3255*9880d681SAndroid Build Coastguard Worker cast<StructType>(Callee->getReturnType())->getTypeAtIndex(0U);
3256*9880d681SAndroid Build Coastguard Worker if (!isTypeLegal(RetTy, RetVT))
3257*9880d681SAndroid Build Coastguard Worker return false;
3258*9880d681SAndroid Build Coastguard Worker
3259*9880d681SAndroid Build Coastguard Worker if (RetVT != MVT::i32 && RetVT != MVT::i64)
3260*9880d681SAndroid Build Coastguard Worker return false;
3261*9880d681SAndroid Build Coastguard Worker
3262*9880d681SAndroid Build Coastguard Worker const Value *LHS = II->getArgOperand(0);
3263*9880d681SAndroid Build Coastguard Worker const Value *RHS = II->getArgOperand(1);
3264*9880d681SAndroid Build Coastguard Worker
3265*9880d681SAndroid Build Coastguard Worker // Canonicalize immediate to the RHS.
3266*9880d681SAndroid Build Coastguard Worker if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS) &&
3267*9880d681SAndroid Build Coastguard Worker isCommutativeIntrinsic(II))
3268*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
3269*9880d681SAndroid Build Coastguard Worker
3270*9880d681SAndroid Build Coastguard Worker // Simplify multiplies.
3271*9880d681SAndroid Build Coastguard Worker Intrinsic::ID IID = II->getIntrinsicID();
3272*9880d681SAndroid Build Coastguard Worker switch (IID) {
3273*9880d681SAndroid Build Coastguard Worker default:
3274*9880d681SAndroid Build Coastguard Worker break;
3275*9880d681SAndroid Build Coastguard Worker case Intrinsic::smul_with_overflow:
3276*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(RHS))
3277*9880d681SAndroid Build Coastguard Worker if (C->getValue() == 2)
3278*9880d681SAndroid Build Coastguard Worker IID = Intrinsic::sadd_with_overflow;
3279*9880d681SAndroid Build Coastguard Worker break;
3280*9880d681SAndroid Build Coastguard Worker case Intrinsic::umul_with_overflow:
3281*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(RHS))
3282*9880d681SAndroid Build Coastguard Worker if (C->getValue() == 2)
3283*9880d681SAndroid Build Coastguard Worker IID = Intrinsic::uadd_with_overflow;
3284*9880d681SAndroid Build Coastguard Worker break;
3285*9880d681SAndroid Build Coastguard Worker }
3286*9880d681SAndroid Build Coastguard Worker
3287*9880d681SAndroid Build Coastguard Worker AArch64CC::CondCode TmpCC;
3288*9880d681SAndroid Build Coastguard Worker switch (IID) {
3289*9880d681SAndroid Build Coastguard Worker default:
3290*9880d681SAndroid Build Coastguard Worker return false;
3291*9880d681SAndroid Build Coastguard Worker case Intrinsic::sadd_with_overflow:
3292*9880d681SAndroid Build Coastguard Worker case Intrinsic::ssub_with_overflow:
3293*9880d681SAndroid Build Coastguard Worker TmpCC = AArch64CC::VS;
3294*9880d681SAndroid Build Coastguard Worker break;
3295*9880d681SAndroid Build Coastguard Worker case Intrinsic::uadd_with_overflow:
3296*9880d681SAndroid Build Coastguard Worker TmpCC = AArch64CC::HS;
3297*9880d681SAndroid Build Coastguard Worker break;
3298*9880d681SAndroid Build Coastguard Worker case Intrinsic::usub_with_overflow:
3299*9880d681SAndroid Build Coastguard Worker TmpCC = AArch64CC::LO;
3300*9880d681SAndroid Build Coastguard Worker break;
3301*9880d681SAndroid Build Coastguard Worker case Intrinsic::smul_with_overflow:
3302*9880d681SAndroid Build Coastguard Worker case Intrinsic::umul_with_overflow:
3303*9880d681SAndroid Build Coastguard Worker TmpCC = AArch64CC::NE;
3304*9880d681SAndroid Build Coastguard Worker break;
3305*9880d681SAndroid Build Coastguard Worker }
3306*9880d681SAndroid Build Coastguard Worker
3307*9880d681SAndroid Build Coastguard Worker // Check if both instructions are in the same basic block.
3308*9880d681SAndroid Build Coastguard Worker if (!isValueAvailable(II))
3309*9880d681SAndroid Build Coastguard Worker return false;
3310*9880d681SAndroid Build Coastguard Worker
3311*9880d681SAndroid Build Coastguard Worker // Make sure nothing is in the way
3312*9880d681SAndroid Build Coastguard Worker BasicBlock::const_iterator Start(I);
3313*9880d681SAndroid Build Coastguard Worker BasicBlock::const_iterator End(II);
3314*9880d681SAndroid Build Coastguard Worker for (auto Itr = std::prev(Start); Itr != End; --Itr) {
3315*9880d681SAndroid Build Coastguard Worker // We only expect extractvalue instructions between the intrinsic and the
3316*9880d681SAndroid Build Coastguard Worker // instruction to be selected.
3317*9880d681SAndroid Build Coastguard Worker if (!isa<ExtractValueInst>(Itr))
3318*9880d681SAndroid Build Coastguard Worker return false;
3319*9880d681SAndroid Build Coastguard Worker
3320*9880d681SAndroid Build Coastguard Worker // Check that the extractvalue operand comes from the intrinsic.
3321*9880d681SAndroid Build Coastguard Worker const auto *EVI = cast<ExtractValueInst>(Itr);
3322*9880d681SAndroid Build Coastguard Worker if (EVI->getAggregateOperand() != II)
3323*9880d681SAndroid Build Coastguard Worker return false;
3324*9880d681SAndroid Build Coastguard Worker }
3325*9880d681SAndroid Build Coastguard Worker
3326*9880d681SAndroid Build Coastguard Worker CC = TmpCC;
3327*9880d681SAndroid Build Coastguard Worker return true;
3328*9880d681SAndroid Build Coastguard Worker }
3329*9880d681SAndroid Build Coastguard Worker
fastLowerIntrinsicCall(const IntrinsicInst * II)3330*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) {
3331*9880d681SAndroid Build Coastguard Worker // FIXME: Handle more intrinsics.
3332*9880d681SAndroid Build Coastguard Worker switch (II->getIntrinsicID()) {
3333*9880d681SAndroid Build Coastguard Worker default: return false;
3334*9880d681SAndroid Build Coastguard Worker case Intrinsic::frameaddress: {
3335*9880d681SAndroid Build Coastguard Worker MachineFrameInfo *MFI = FuncInfo.MF->getFrameInfo();
3336*9880d681SAndroid Build Coastguard Worker MFI->setFrameAddressIsTaken(true);
3337*9880d681SAndroid Build Coastguard Worker
3338*9880d681SAndroid Build Coastguard Worker const AArch64RegisterInfo *RegInfo =
3339*9880d681SAndroid Build Coastguard Worker static_cast<const AArch64RegisterInfo *>(Subtarget->getRegisterInfo());
3340*9880d681SAndroid Build Coastguard Worker unsigned FramePtr = RegInfo->getFrameRegister(*(FuncInfo.MF));
3341*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3342*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3343*9880d681SAndroid Build Coastguard Worker TII.get(TargetOpcode::COPY), SrcReg).addReg(FramePtr);
3344*9880d681SAndroid Build Coastguard Worker // Recursively load frame address
3345*9880d681SAndroid Build Coastguard Worker // ldr x0, [fp]
3346*9880d681SAndroid Build Coastguard Worker // ldr x0, [x0]
3347*9880d681SAndroid Build Coastguard Worker // ldr x0, [x0]
3348*9880d681SAndroid Build Coastguard Worker // ...
3349*9880d681SAndroid Build Coastguard Worker unsigned DestReg;
3350*9880d681SAndroid Build Coastguard Worker unsigned Depth = cast<ConstantInt>(II->getOperand(0))->getZExtValue();
3351*9880d681SAndroid Build Coastguard Worker while (Depth--) {
3352*9880d681SAndroid Build Coastguard Worker DestReg = fastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,
3353*9880d681SAndroid Build Coastguard Worker SrcReg, /*IsKill=*/true, 0);
3354*9880d681SAndroid Build Coastguard Worker assert(DestReg && "Unexpected LDR instruction emission failure.");
3355*9880d681SAndroid Build Coastguard Worker SrcReg = DestReg;
3356*9880d681SAndroid Build Coastguard Worker }
3357*9880d681SAndroid Build Coastguard Worker
3358*9880d681SAndroid Build Coastguard Worker updateValueMap(II, SrcReg);
3359*9880d681SAndroid Build Coastguard Worker return true;
3360*9880d681SAndroid Build Coastguard Worker }
3361*9880d681SAndroid Build Coastguard Worker case Intrinsic::memcpy:
3362*9880d681SAndroid Build Coastguard Worker case Intrinsic::memmove: {
3363*9880d681SAndroid Build Coastguard Worker const auto *MTI = cast<MemTransferInst>(II);
3364*9880d681SAndroid Build Coastguard Worker // Don't handle volatile.
3365*9880d681SAndroid Build Coastguard Worker if (MTI->isVolatile())
3366*9880d681SAndroid Build Coastguard Worker return false;
3367*9880d681SAndroid Build Coastguard Worker
3368*9880d681SAndroid Build Coastguard Worker // Disable inlining for memmove before calls to ComputeAddress. Otherwise,
3369*9880d681SAndroid Build Coastguard Worker // we would emit dead code because we don't currently handle memmoves.
3370*9880d681SAndroid Build Coastguard Worker bool IsMemCpy = (II->getIntrinsicID() == Intrinsic::memcpy);
3371*9880d681SAndroid Build Coastguard Worker if (isa<ConstantInt>(MTI->getLength()) && IsMemCpy) {
3372*9880d681SAndroid Build Coastguard Worker // Small memcpy's are common enough that we want to do them without a call
3373*9880d681SAndroid Build Coastguard Worker // if possible.
3374*9880d681SAndroid Build Coastguard Worker uint64_t Len = cast<ConstantInt>(MTI->getLength())->getZExtValue();
3375*9880d681SAndroid Build Coastguard Worker unsigned Alignment = MTI->getAlignment();
3376*9880d681SAndroid Build Coastguard Worker if (isMemCpySmall(Len, Alignment)) {
3377*9880d681SAndroid Build Coastguard Worker Address Dest, Src;
3378*9880d681SAndroid Build Coastguard Worker if (!computeAddress(MTI->getRawDest(), Dest) ||
3379*9880d681SAndroid Build Coastguard Worker !computeAddress(MTI->getRawSource(), Src))
3380*9880d681SAndroid Build Coastguard Worker return false;
3381*9880d681SAndroid Build Coastguard Worker if (tryEmitSmallMemCpy(Dest, Src, Len, Alignment))
3382*9880d681SAndroid Build Coastguard Worker return true;
3383*9880d681SAndroid Build Coastguard Worker }
3384*9880d681SAndroid Build Coastguard Worker }
3385*9880d681SAndroid Build Coastguard Worker
3386*9880d681SAndroid Build Coastguard Worker if (!MTI->getLength()->getType()->isIntegerTy(64))
3387*9880d681SAndroid Build Coastguard Worker return false;
3388*9880d681SAndroid Build Coastguard Worker
3389*9880d681SAndroid Build Coastguard Worker if (MTI->getSourceAddressSpace() > 255 || MTI->getDestAddressSpace() > 255)
3390*9880d681SAndroid Build Coastguard Worker // Fast instruction selection doesn't support the special
3391*9880d681SAndroid Build Coastguard Worker // address spaces.
3392*9880d681SAndroid Build Coastguard Worker return false;
3393*9880d681SAndroid Build Coastguard Worker
3394*9880d681SAndroid Build Coastguard Worker const char *IntrMemName = isa<MemCpyInst>(II) ? "memcpy" : "memmove";
3395*9880d681SAndroid Build Coastguard Worker return lowerCallTo(II, IntrMemName, II->getNumArgOperands() - 2);
3396*9880d681SAndroid Build Coastguard Worker }
3397*9880d681SAndroid Build Coastguard Worker case Intrinsic::memset: {
3398*9880d681SAndroid Build Coastguard Worker const MemSetInst *MSI = cast<MemSetInst>(II);
3399*9880d681SAndroid Build Coastguard Worker // Don't handle volatile.
3400*9880d681SAndroid Build Coastguard Worker if (MSI->isVolatile())
3401*9880d681SAndroid Build Coastguard Worker return false;
3402*9880d681SAndroid Build Coastguard Worker
3403*9880d681SAndroid Build Coastguard Worker if (!MSI->getLength()->getType()->isIntegerTy(64))
3404*9880d681SAndroid Build Coastguard Worker return false;
3405*9880d681SAndroid Build Coastguard Worker
3406*9880d681SAndroid Build Coastguard Worker if (MSI->getDestAddressSpace() > 255)
3407*9880d681SAndroid Build Coastguard Worker // Fast instruction selection doesn't support the special
3408*9880d681SAndroid Build Coastguard Worker // address spaces.
3409*9880d681SAndroid Build Coastguard Worker return false;
3410*9880d681SAndroid Build Coastguard Worker
3411*9880d681SAndroid Build Coastguard Worker return lowerCallTo(II, "memset", II->getNumArgOperands() - 2);
3412*9880d681SAndroid Build Coastguard Worker }
3413*9880d681SAndroid Build Coastguard Worker case Intrinsic::sin:
3414*9880d681SAndroid Build Coastguard Worker case Intrinsic::cos:
3415*9880d681SAndroid Build Coastguard Worker case Intrinsic::pow: {
3416*9880d681SAndroid Build Coastguard Worker MVT RetVT;
3417*9880d681SAndroid Build Coastguard Worker if (!isTypeLegal(II->getType(), RetVT))
3418*9880d681SAndroid Build Coastguard Worker return false;
3419*9880d681SAndroid Build Coastguard Worker
3420*9880d681SAndroid Build Coastguard Worker if (RetVT != MVT::f32 && RetVT != MVT::f64)
3421*9880d681SAndroid Build Coastguard Worker return false;
3422*9880d681SAndroid Build Coastguard Worker
3423*9880d681SAndroid Build Coastguard Worker static const RTLIB::Libcall LibCallTable[3][2] = {
3424*9880d681SAndroid Build Coastguard Worker { RTLIB::SIN_F32, RTLIB::SIN_F64 },
3425*9880d681SAndroid Build Coastguard Worker { RTLIB::COS_F32, RTLIB::COS_F64 },
3426*9880d681SAndroid Build Coastguard Worker { RTLIB::POW_F32, RTLIB::POW_F64 }
3427*9880d681SAndroid Build Coastguard Worker };
3428*9880d681SAndroid Build Coastguard Worker RTLIB::Libcall LC;
3429*9880d681SAndroid Build Coastguard Worker bool Is64Bit = RetVT == MVT::f64;
3430*9880d681SAndroid Build Coastguard Worker switch (II->getIntrinsicID()) {
3431*9880d681SAndroid Build Coastguard Worker default:
3432*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected intrinsic.");
3433*9880d681SAndroid Build Coastguard Worker case Intrinsic::sin:
3434*9880d681SAndroid Build Coastguard Worker LC = LibCallTable[0][Is64Bit];
3435*9880d681SAndroid Build Coastguard Worker break;
3436*9880d681SAndroid Build Coastguard Worker case Intrinsic::cos:
3437*9880d681SAndroid Build Coastguard Worker LC = LibCallTable[1][Is64Bit];
3438*9880d681SAndroid Build Coastguard Worker break;
3439*9880d681SAndroid Build Coastguard Worker case Intrinsic::pow:
3440*9880d681SAndroid Build Coastguard Worker LC = LibCallTable[2][Is64Bit];
3441*9880d681SAndroid Build Coastguard Worker break;
3442*9880d681SAndroid Build Coastguard Worker }
3443*9880d681SAndroid Build Coastguard Worker
3444*9880d681SAndroid Build Coastguard Worker ArgListTy Args;
3445*9880d681SAndroid Build Coastguard Worker Args.reserve(II->getNumArgOperands());
3446*9880d681SAndroid Build Coastguard Worker
3447*9880d681SAndroid Build Coastguard Worker // Populate the argument list.
3448*9880d681SAndroid Build Coastguard Worker for (auto &Arg : II->arg_operands()) {
3449*9880d681SAndroid Build Coastguard Worker ArgListEntry Entry;
3450*9880d681SAndroid Build Coastguard Worker Entry.Val = Arg;
3451*9880d681SAndroid Build Coastguard Worker Entry.Ty = Arg->getType();
3452*9880d681SAndroid Build Coastguard Worker Args.push_back(Entry);
3453*9880d681SAndroid Build Coastguard Worker }
3454*9880d681SAndroid Build Coastguard Worker
3455*9880d681SAndroid Build Coastguard Worker CallLoweringInfo CLI;
3456*9880d681SAndroid Build Coastguard Worker MCContext &Ctx = MF->getContext();
3457*9880d681SAndroid Build Coastguard Worker CLI.setCallee(DL, Ctx, TLI.getLibcallCallingConv(LC), II->getType(),
3458*9880d681SAndroid Build Coastguard Worker TLI.getLibcallName(LC), std::move(Args));
3459*9880d681SAndroid Build Coastguard Worker if (!lowerCallTo(CLI))
3460*9880d681SAndroid Build Coastguard Worker return false;
3461*9880d681SAndroid Build Coastguard Worker updateValueMap(II, CLI.ResultReg);
3462*9880d681SAndroid Build Coastguard Worker return true;
3463*9880d681SAndroid Build Coastguard Worker }
3464*9880d681SAndroid Build Coastguard Worker case Intrinsic::fabs: {
3465*9880d681SAndroid Build Coastguard Worker MVT VT;
3466*9880d681SAndroid Build Coastguard Worker if (!isTypeLegal(II->getType(), VT))
3467*9880d681SAndroid Build Coastguard Worker return false;
3468*9880d681SAndroid Build Coastguard Worker
3469*9880d681SAndroid Build Coastguard Worker unsigned Opc;
3470*9880d681SAndroid Build Coastguard Worker switch (VT.SimpleTy) {
3471*9880d681SAndroid Build Coastguard Worker default:
3472*9880d681SAndroid Build Coastguard Worker return false;
3473*9880d681SAndroid Build Coastguard Worker case MVT::f32:
3474*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FABSSr;
3475*9880d681SAndroid Build Coastguard Worker break;
3476*9880d681SAndroid Build Coastguard Worker case MVT::f64:
3477*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FABSDr;
3478*9880d681SAndroid Build Coastguard Worker break;
3479*9880d681SAndroid Build Coastguard Worker }
3480*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = getRegForValue(II->getOperand(0));
3481*9880d681SAndroid Build Coastguard Worker if (!SrcReg)
3482*9880d681SAndroid Build Coastguard Worker return false;
3483*9880d681SAndroid Build Coastguard Worker bool SrcRegIsKill = hasTrivialKill(II->getOperand(0));
3484*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(TLI.getRegClassFor(VT));
3485*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
3486*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(SrcRegIsKill));
3487*9880d681SAndroid Build Coastguard Worker updateValueMap(II, ResultReg);
3488*9880d681SAndroid Build Coastguard Worker return true;
3489*9880d681SAndroid Build Coastguard Worker }
3490*9880d681SAndroid Build Coastguard Worker case Intrinsic::trap: {
3491*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::BRK))
3492*9880d681SAndroid Build Coastguard Worker .addImm(1);
3493*9880d681SAndroid Build Coastguard Worker return true;
3494*9880d681SAndroid Build Coastguard Worker }
3495*9880d681SAndroid Build Coastguard Worker case Intrinsic::sqrt: {
3496*9880d681SAndroid Build Coastguard Worker Type *RetTy = II->getCalledFunction()->getReturnType();
3497*9880d681SAndroid Build Coastguard Worker
3498*9880d681SAndroid Build Coastguard Worker MVT VT;
3499*9880d681SAndroid Build Coastguard Worker if (!isTypeLegal(RetTy, VT))
3500*9880d681SAndroid Build Coastguard Worker return false;
3501*9880d681SAndroid Build Coastguard Worker
3502*9880d681SAndroid Build Coastguard Worker unsigned Op0Reg = getRegForValue(II->getOperand(0));
3503*9880d681SAndroid Build Coastguard Worker if (!Op0Reg)
3504*9880d681SAndroid Build Coastguard Worker return false;
3505*9880d681SAndroid Build Coastguard Worker bool Op0IsKill = hasTrivialKill(II->getOperand(0));
3506*9880d681SAndroid Build Coastguard Worker
3507*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = fastEmit_r(VT, VT, ISD::FSQRT, Op0Reg, Op0IsKill);
3508*9880d681SAndroid Build Coastguard Worker if (!ResultReg)
3509*9880d681SAndroid Build Coastguard Worker return false;
3510*9880d681SAndroid Build Coastguard Worker
3511*9880d681SAndroid Build Coastguard Worker updateValueMap(II, ResultReg);
3512*9880d681SAndroid Build Coastguard Worker return true;
3513*9880d681SAndroid Build Coastguard Worker }
3514*9880d681SAndroid Build Coastguard Worker case Intrinsic::sadd_with_overflow:
3515*9880d681SAndroid Build Coastguard Worker case Intrinsic::uadd_with_overflow:
3516*9880d681SAndroid Build Coastguard Worker case Intrinsic::ssub_with_overflow:
3517*9880d681SAndroid Build Coastguard Worker case Intrinsic::usub_with_overflow:
3518*9880d681SAndroid Build Coastguard Worker case Intrinsic::smul_with_overflow:
3519*9880d681SAndroid Build Coastguard Worker case Intrinsic::umul_with_overflow: {
3520*9880d681SAndroid Build Coastguard Worker // This implements the basic lowering of the xalu with overflow intrinsics.
3521*9880d681SAndroid Build Coastguard Worker const Function *Callee = II->getCalledFunction();
3522*9880d681SAndroid Build Coastguard Worker auto *Ty = cast<StructType>(Callee->getReturnType());
3523*9880d681SAndroid Build Coastguard Worker Type *RetTy = Ty->getTypeAtIndex(0U);
3524*9880d681SAndroid Build Coastguard Worker
3525*9880d681SAndroid Build Coastguard Worker MVT VT;
3526*9880d681SAndroid Build Coastguard Worker if (!isTypeLegal(RetTy, VT))
3527*9880d681SAndroid Build Coastguard Worker return false;
3528*9880d681SAndroid Build Coastguard Worker
3529*9880d681SAndroid Build Coastguard Worker if (VT != MVT::i32 && VT != MVT::i64)
3530*9880d681SAndroid Build Coastguard Worker return false;
3531*9880d681SAndroid Build Coastguard Worker
3532*9880d681SAndroid Build Coastguard Worker const Value *LHS = II->getArgOperand(0);
3533*9880d681SAndroid Build Coastguard Worker const Value *RHS = II->getArgOperand(1);
3534*9880d681SAndroid Build Coastguard Worker // Canonicalize immediate to the RHS.
3535*9880d681SAndroid Build Coastguard Worker if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS) &&
3536*9880d681SAndroid Build Coastguard Worker isCommutativeIntrinsic(II))
3537*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
3538*9880d681SAndroid Build Coastguard Worker
3539*9880d681SAndroid Build Coastguard Worker // Simplify multiplies.
3540*9880d681SAndroid Build Coastguard Worker Intrinsic::ID IID = II->getIntrinsicID();
3541*9880d681SAndroid Build Coastguard Worker switch (IID) {
3542*9880d681SAndroid Build Coastguard Worker default:
3543*9880d681SAndroid Build Coastguard Worker break;
3544*9880d681SAndroid Build Coastguard Worker case Intrinsic::smul_with_overflow:
3545*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(RHS))
3546*9880d681SAndroid Build Coastguard Worker if (C->getValue() == 2) {
3547*9880d681SAndroid Build Coastguard Worker IID = Intrinsic::sadd_with_overflow;
3548*9880d681SAndroid Build Coastguard Worker RHS = LHS;
3549*9880d681SAndroid Build Coastguard Worker }
3550*9880d681SAndroid Build Coastguard Worker break;
3551*9880d681SAndroid Build Coastguard Worker case Intrinsic::umul_with_overflow:
3552*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(RHS))
3553*9880d681SAndroid Build Coastguard Worker if (C->getValue() == 2) {
3554*9880d681SAndroid Build Coastguard Worker IID = Intrinsic::uadd_with_overflow;
3555*9880d681SAndroid Build Coastguard Worker RHS = LHS;
3556*9880d681SAndroid Build Coastguard Worker }
3557*9880d681SAndroid Build Coastguard Worker break;
3558*9880d681SAndroid Build Coastguard Worker }
3559*9880d681SAndroid Build Coastguard Worker
3560*9880d681SAndroid Build Coastguard Worker unsigned ResultReg1 = 0, ResultReg2 = 0, MulReg = 0;
3561*9880d681SAndroid Build Coastguard Worker AArch64CC::CondCode CC = AArch64CC::Invalid;
3562*9880d681SAndroid Build Coastguard Worker switch (IID) {
3563*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Unexpected intrinsic!");
3564*9880d681SAndroid Build Coastguard Worker case Intrinsic::sadd_with_overflow:
3565*9880d681SAndroid Build Coastguard Worker ResultReg1 = emitAdd(VT, LHS, RHS, /*SetFlags=*/true);
3566*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::VS;
3567*9880d681SAndroid Build Coastguard Worker break;
3568*9880d681SAndroid Build Coastguard Worker case Intrinsic::uadd_with_overflow:
3569*9880d681SAndroid Build Coastguard Worker ResultReg1 = emitAdd(VT, LHS, RHS, /*SetFlags=*/true);
3570*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::HS;
3571*9880d681SAndroid Build Coastguard Worker break;
3572*9880d681SAndroid Build Coastguard Worker case Intrinsic::ssub_with_overflow:
3573*9880d681SAndroid Build Coastguard Worker ResultReg1 = emitSub(VT, LHS, RHS, /*SetFlags=*/true);
3574*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::VS;
3575*9880d681SAndroid Build Coastguard Worker break;
3576*9880d681SAndroid Build Coastguard Worker case Intrinsic::usub_with_overflow:
3577*9880d681SAndroid Build Coastguard Worker ResultReg1 = emitSub(VT, LHS, RHS, /*SetFlags=*/true);
3578*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::LO;
3579*9880d681SAndroid Build Coastguard Worker break;
3580*9880d681SAndroid Build Coastguard Worker case Intrinsic::smul_with_overflow: {
3581*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::NE;
3582*9880d681SAndroid Build Coastguard Worker unsigned LHSReg = getRegForValue(LHS);
3583*9880d681SAndroid Build Coastguard Worker if (!LHSReg)
3584*9880d681SAndroid Build Coastguard Worker return false;
3585*9880d681SAndroid Build Coastguard Worker bool LHSIsKill = hasTrivialKill(LHS);
3586*9880d681SAndroid Build Coastguard Worker
3587*9880d681SAndroid Build Coastguard Worker unsigned RHSReg = getRegForValue(RHS);
3588*9880d681SAndroid Build Coastguard Worker if (!RHSReg)
3589*9880d681SAndroid Build Coastguard Worker return false;
3590*9880d681SAndroid Build Coastguard Worker bool RHSIsKill = hasTrivialKill(RHS);
3591*9880d681SAndroid Build Coastguard Worker
3592*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i32) {
3593*9880d681SAndroid Build Coastguard Worker MulReg = emitSMULL_rr(MVT::i64, LHSReg, LHSIsKill, RHSReg, RHSIsKill);
3594*9880d681SAndroid Build Coastguard Worker unsigned ShiftReg = emitLSR_ri(MVT::i64, MVT::i64, MulReg,
3595*9880d681SAndroid Build Coastguard Worker /*IsKill=*/false, 32);
3596*9880d681SAndroid Build Coastguard Worker MulReg = fastEmitInst_extractsubreg(VT, MulReg, /*IsKill=*/true,
3597*9880d681SAndroid Build Coastguard Worker AArch64::sub_32);
3598*9880d681SAndroid Build Coastguard Worker ShiftReg = fastEmitInst_extractsubreg(VT, ShiftReg, /*IsKill=*/true,
3599*9880d681SAndroid Build Coastguard Worker AArch64::sub_32);
3600*9880d681SAndroid Build Coastguard Worker emitSubs_rs(VT, ShiftReg, /*IsKill=*/true, MulReg, /*IsKill=*/false,
3601*9880d681SAndroid Build Coastguard Worker AArch64_AM::ASR, 31, /*WantResult=*/false);
3602*9880d681SAndroid Build Coastguard Worker } else {
3603*9880d681SAndroid Build Coastguard Worker assert(VT == MVT::i64 && "Unexpected value type.");
3604*9880d681SAndroid Build Coastguard Worker // LHSReg and RHSReg cannot be killed by this Mul, since they are
3605*9880d681SAndroid Build Coastguard Worker // reused in the next instruction.
3606*9880d681SAndroid Build Coastguard Worker MulReg = emitMul_rr(VT, LHSReg, /*IsKill=*/false, RHSReg,
3607*9880d681SAndroid Build Coastguard Worker /*IsKill=*/false);
3608*9880d681SAndroid Build Coastguard Worker unsigned SMULHReg = fastEmit_rr(VT, VT, ISD::MULHS, LHSReg, LHSIsKill,
3609*9880d681SAndroid Build Coastguard Worker RHSReg, RHSIsKill);
3610*9880d681SAndroid Build Coastguard Worker emitSubs_rs(VT, SMULHReg, /*IsKill=*/true, MulReg, /*IsKill=*/false,
3611*9880d681SAndroid Build Coastguard Worker AArch64_AM::ASR, 63, /*WantResult=*/false);
3612*9880d681SAndroid Build Coastguard Worker }
3613*9880d681SAndroid Build Coastguard Worker break;
3614*9880d681SAndroid Build Coastguard Worker }
3615*9880d681SAndroid Build Coastguard Worker case Intrinsic::umul_with_overflow: {
3616*9880d681SAndroid Build Coastguard Worker CC = AArch64CC::NE;
3617*9880d681SAndroid Build Coastguard Worker unsigned LHSReg = getRegForValue(LHS);
3618*9880d681SAndroid Build Coastguard Worker if (!LHSReg)
3619*9880d681SAndroid Build Coastguard Worker return false;
3620*9880d681SAndroid Build Coastguard Worker bool LHSIsKill = hasTrivialKill(LHS);
3621*9880d681SAndroid Build Coastguard Worker
3622*9880d681SAndroid Build Coastguard Worker unsigned RHSReg = getRegForValue(RHS);
3623*9880d681SAndroid Build Coastguard Worker if (!RHSReg)
3624*9880d681SAndroid Build Coastguard Worker return false;
3625*9880d681SAndroid Build Coastguard Worker bool RHSIsKill = hasTrivialKill(RHS);
3626*9880d681SAndroid Build Coastguard Worker
3627*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i32) {
3628*9880d681SAndroid Build Coastguard Worker MulReg = emitUMULL_rr(MVT::i64, LHSReg, LHSIsKill, RHSReg, RHSIsKill);
3629*9880d681SAndroid Build Coastguard Worker emitSubs_rs(MVT::i64, AArch64::XZR, /*IsKill=*/true, MulReg,
3630*9880d681SAndroid Build Coastguard Worker /*IsKill=*/false, AArch64_AM::LSR, 32,
3631*9880d681SAndroid Build Coastguard Worker /*WantResult=*/false);
3632*9880d681SAndroid Build Coastguard Worker MulReg = fastEmitInst_extractsubreg(VT, MulReg, /*IsKill=*/true,
3633*9880d681SAndroid Build Coastguard Worker AArch64::sub_32);
3634*9880d681SAndroid Build Coastguard Worker } else {
3635*9880d681SAndroid Build Coastguard Worker assert(VT == MVT::i64 && "Unexpected value type.");
3636*9880d681SAndroid Build Coastguard Worker // LHSReg and RHSReg cannot be killed by this Mul, since they are
3637*9880d681SAndroid Build Coastguard Worker // reused in the next instruction.
3638*9880d681SAndroid Build Coastguard Worker MulReg = emitMul_rr(VT, LHSReg, /*IsKill=*/false, RHSReg,
3639*9880d681SAndroid Build Coastguard Worker /*IsKill=*/false);
3640*9880d681SAndroid Build Coastguard Worker unsigned UMULHReg = fastEmit_rr(VT, VT, ISD::MULHU, LHSReg, LHSIsKill,
3641*9880d681SAndroid Build Coastguard Worker RHSReg, RHSIsKill);
3642*9880d681SAndroid Build Coastguard Worker emitSubs_rr(VT, AArch64::XZR, /*IsKill=*/true, UMULHReg,
3643*9880d681SAndroid Build Coastguard Worker /*IsKill=*/false, /*WantResult=*/false);
3644*9880d681SAndroid Build Coastguard Worker }
3645*9880d681SAndroid Build Coastguard Worker break;
3646*9880d681SAndroid Build Coastguard Worker }
3647*9880d681SAndroid Build Coastguard Worker }
3648*9880d681SAndroid Build Coastguard Worker
3649*9880d681SAndroid Build Coastguard Worker if (MulReg) {
3650*9880d681SAndroid Build Coastguard Worker ResultReg1 = createResultReg(TLI.getRegClassFor(VT));
3651*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3652*9880d681SAndroid Build Coastguard Worker TII.get(TargetOpcode::COPY), ResultReg1).addReg(MulReg);
3653*9880d681SAndroid Build Coastguard Worker }
3654*9880d681SAndroid Build Coastguard Worker
3655*9880d681SAndroid Build Coastguard Worker ResultReg2 = fastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,
3656*9880d681SAndroid Build Coastguard Worker AArch64::WZR, /*IsKill=*/true, AArch64::WZR,
3657*9880d681SAndroid Build Coastguard Worker /*IsKill=*/true, getInvertedCondCode(CC));
3658*9880d681SAndroid Build Coastguard Worker (void)ResultReg2;
3659*9880d681SAndroid Build Coastguard Worker assert((ResultReg1 + 1) == ResultReg2 &&
3660*9880d681SAndroid Build Coastguard Worker "Nonconsecutive result registers.");
3661*9880d681SAndroid Build Coastguard Worker updateValueMap(II, ResultReg1, 2);
3662*9880d681SAndroid Build Coastguard Worker return true;
3663*9880d681SAndroid Build Coastguard Worker }
3664*9880d681SAndroid Build Coastguard Worker }
3665*9880d681SAndroid Build Coastguard Worker return false;
3666*9880d681SAndroid Build Coastguard Worker }
3667*9880d681SAndroid Build Coastguard Worker
selectRet(const Instruction * I)3668*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectRet(const Instruction *I) {
3669*9880d681SAndroid Build Coastguard Worker const ReturnInst *Ret = cast<ReturnInst>(I);
3670*9880d681SAndroid Build Coastguard Worker const Function &F = *I->getParent()->getParent();
3671*9880d681SAndroid Build Coastguard Worker
3672*9880d681SAndroid Build Coastguard Worker if (!FuncInfo.CanLowerReturn)
3673*9880d681SAndroid Build Coastguard Worker return false;
3674*9880d681SAndroid Build Coastguard Worker
3675*9880d681SAndroid Build Coastguard Worker if (F.isVarArg())
3676*9880d681SAndroid Build Coastguard Worker return false;
3677*9880d681SAndroid Build Coastguard Worker
3678*9880d681SAndroid Build Coastguard Worker if (TLI.supportSwiftError() &&
3679*9880d681SAndroid Build Coastguard Worker F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
3680*9880d681SAndroid Build Coastguard Worker return false;
3681*9880d681SAndroid Build Coastguard Worker
3682*9880d681SAndroid Build Coastguard Worker if (TLI.supportSplitCSR(FuncInfo.MF))
3683*9880d681SAndroid Build Coastguard Worker return false;
3684*9880d681SAndroid Build Coastguard Worker
3685*9880d681SAndroid Build Coastguard Worker // Build a list of return value registers.
3686*9880d681SAndroid Build Coastguard Worker SmallVector<unsigned, 4> RetRegs;
3687*9880d681SAndroid Build Coastguard Worker
3688*9880d681SAndroid Build Coastguard Worker if (Ret->getNumOperands() > 0) {
3689*9880d681SAndroid Build Coastguard Worker CallingConv::ID CC = F.getCallingConv();
3690*9880d681SAndroid Build Coastguard Worker SmallVector<ISD::OutputArg, 4> Outs;
3691*9880d681SAndroid Build Coastguard Worker GetReturnInfo(F.getReturnType(), F.getAttributes(), Outs, TLI, DL);
3692*9880d681SAndroid Build Coastguard Worker
3693*9880d681SAndroid Build Coastguard Worker // Analyze operands of the call, assigning locations to each operand.
3694*9880d681SAndroid Build Coastguard Worker SmallVector<CCValAssign, 16> ValLocs;
3695*9880d681SAndroid Build Coastguard Worker CCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs, I->getContext());
3696*9880d681SAndroid Build Coastguard Worker CCAssignFn *RetCC = CC == CallingConv::WebKit_JS ? RetCC_AArch64_WebKit_JS
3697*9880d681SAndroid Build Coastguard Worker : RetCC_AArch64_AAPCS;
3698*9880d681SAndroid Build Coastguard Worker CCInfo.AnalyzeReturn(Outs, RetCC);
3699*9880d681SAndroid Build Coastguard Worker
3700*9880d681SAndroid Build Coastguard Worker // Only handle a single return value for now.
3701*9880d681SAndroid Build Coastguard Worker if (ValLocs.size() != 1)
3702*9880d681SAndroid Build Coastguard Worker return false;
3703*9880d681SAndroid Build Coastguard Worker
3704*9880d681SAndroid Build Coastguard Worker CCValAssign &VA = ValLocs[0];
3705*9880d681SAndroid Build Coastguard Worker const Value *RV = Ret->getOperand(0);
3706*9880d681SAndroid Build Coastguard Worker
3707*9880d681SAndroid Build Coastguard Worker // Don't bother handling odd stuff for now.
3708*9880d681SAndroid Build Coastguard Worker if ((VA.getLocInfo() != CCValAssign::Full) &&
3709*9880d681SAndroid Build Coastguard Worker (VA.getLocInfo() != CCValAssign::BCvt))
3710*9880d681SAndroid Build Coastguard Worker return false;
3711*9880d681SAndroid Build Coastguard Worker
3712*9880d681SAndroid Build Coastguard Worker // Only handle register returns for now.
3713*9880d681SAndroid Build Coastguard Worker if (!VA.isRegLoc())
3714*9880d681SAndroid Build Coastguard Worker return false;
3715*9880d681SAndroid Build Coastguard Worker
3716*9880d681SAndroid Build Coastguard Worker unsigned Reg = getRegForValue(RV);
3717*9880d681SAndroid Build Coastguard Worker if (Reg == 0)
3718*9880d681SAndroid Build Coastguard Worker return false;
3719*9880d681SAndroid Build Coastguard Worker
3720*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = Reg + VA.getValNo();
3721*9880d681SAndroid Build Coastguard Worker unsigned DestReg = VA.getLocReg();
3722*9880d681SAndroid Build Coastguard Worker // Avoid a cross-class copy. This is very unlikely.
3723*9880d681SAndroid Build Coastguard Worker if (!MRI.getRegClass(SrcReg)->contains(DestReg))
3724*9880d681SAndroid Build Coastguard Worker return false;
3725*9880d681SAndroid Build Coastguard Worker
3726*9880d681SAndroid Build Coastguard Worker EVT RVEVT = TLI.getValueType(DL, RV->getType());
3727*9880d681SAndroid Build Coastguard Worker if (!RVEVT.isSimple())
3728*9880d681SAndroid Build Coastguard Worker return false;
3729*9880d681SAndroid Build Coastguard Worker
3730*9880d681SAndroid Build Coastguard Worker // Vectors (of > 1 lane) in big endian need tricky handling.
3731*9880d681SAndroid Build Coastguard Worker if (RVEVT.isVector() && RVEVT.getVectorNumElements() > 1 &&
3732*9880d681SAndroid Build Coastguard Worker !Subtarget->isLittleEndian())
3733*9880d681SAndroid Build Coastguard Worker return false;
3734*9880d681SAndroid Build Coastguard Worker
3735*9880d681SAndroid Build Coastguard Worker MVT RVVT = RVEVT.getSimpleVT();
3736*9880d681SAndroid Build Coastguard Worker if (RVVT == MVT::f128)
3737*9880d681SAndroid Build Coastguard Worker return false;
3738*9880d681SAndroid Build Coastguard Worker
3739*9880d681SAndroid Build Coastguard Worker MVT DestVT = VA.getValVT();
3740*9880d681SAndroid Build Coastguard Worker // Special handling for extended integers.
3741*9880d681SAndroid Build Coastguard Worker if (RVVT != DestVT) {
3742*9880d681SAndroid Build Coastguard Worker if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
3743*9880d681SAndroid Build Coastguard Worker return false;
3744*9880d681SAndroid Build Coastguard Worker
3745*9880d681SAndroid Build Coastguard Worker if (!Outs[0].Flags.isZExt() && !Outs[0].Flags.isSExt())
3746*9880d681SAndroid Build Coastguard Worker return false;
3747*9880d681SAndroid Build Coastguard Worker
3748*9880d681SAndroid Build Coastguard Worker bool IsZExt = Outs[0].Flags.isZExt();
3749*9880d681SAndroid Build Coastguard Worker SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
3750*9880d681SAndroid Build Coastguard Worker if (SrcReg == 0)
3751*9880d681SAndroid Build Coastguard Worker return false;
3752*9880d681SAndroid Build Coastguard Worker }
3753*9880d681SAndroid Build Coastguard Worker
3754*9880d681SAndroid Build Coastguard Worker // Make the copy.
3755*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3756*9880d681SAndroid Build Coastguard Worker TII.get(TargetOpcode::COPY), DestReg).addReg(SrcReg);
3757*9880d681SAndroid Build Coastguard Worker
3758*9880d681SAndroid Build Coastguard Worker // Add register to return instruction.
3759*9880d681SAndroid Build Coastguard Worker RetRegs.push_back(VA.getLocReg());
3760*9880d681SAndroid Build Coastguard Worker }
3761*9880d681SAndroid Build Coastguard Worker
3762*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3763*9880d681SAndroid Build Coastguard Worker TII.get(AArch64::RET_ReallyLR));
3764*9880d681SAndroid Build Coastguard Worker for (unsigned RetReg : RetRegs)
3765*9880d681SAndroid Build Coastguard Worker MIB.addReg(RetReg, RegState::Implicit);
3766*9880d681SAndroid Build Coastguard Worker return true;
3767*9880d681SAndroid Build Coastguard Worker }
3768*9880d681SAndroid Build Coastguard Worker
selectTrunc(const Instruction * I)3769*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectTrunc(const Instruction *I) {
3770*9880d681SAndroid Build Coastguard Worker Type *DestTy = I->getType();
3771*9880d681SAndroid Build Coastguard Worker Value *Op = I->getOperand(0);
3772*9880d681SAndroid Build Coastguard Worker Type *SrcTy = Op->getType();
3773*9880d681SAndroid Build Coastguard Worker
3774*9880d681SAndroid Build Coastguard Worker EVT SrcEVT = TLI.getValueType(DL, SrcTy, true);
3775*9880d681SAndroid Build Coastguard Worker EVT DestEVT = TLI.getValueType(DL, DestTy, true);
3776*9880d681SAndroid Build Coastguard Worker if (!SrcEVT.isSimple())
3777*9880d681SAndroid Build Coastguard Worker return false;
3778*9880d681SAndroid Build Coastguard Worker if (!DestEVT.isSimple())
3779*9880d681SAndroid Build Coastguard Worker return false;
3780*9880d681SAndroid Build Coastguard Worker
3781*9880d681SAndroid Build Coastguard Worker MVT SrcVT = SrcEVT.getSimpleVT();
3782*9880d681SAndroid Build Coastguard Worker MVT DestVT = DestEVT.getSimpleVT();
3783*9880d681SAndroid Build Coastguard Worker
3784*9880d681SAndroid Build Coastguard Worker if (SrcVT != MVT::i64 && SrcVT != MVT::i32 && SrcVT != MVT::i16 &&
3785*9880d681SAndroid Build Coastguard Worker SrcVT != MVT::i8)
3786*9880d681SAndroid Build Coastguard Worker return false;
3787*9880d681SAndroid Build Coastguard Worker if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8 &&
3788*9880d681SAndroid Build Coastguard Worker DestVT != MVT::i1)
3789*9880d681SAndroid Build Coastguard Worker return false;
3790*9880d681SAndroid Build Coastguard Worker
3791*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = getRegForValue(Op);
3792*9880d681SAndroid Build Coastguard Worker if (!SrcReg)
3793*9880d681SAndroid Build Coastguard Worker return false;
3794*9880d681SAndroid Build Coastguard Worker bool SrcIsKill = hasTrivialKill(Op);
3795*9880d681SAndroid Build Coastguard Worker
3796*9880d681SAndroid Build Coastguard Worker // If we're truncating from i64 to a smaller non-legal type then generate an
3797*9880d681SAndroid Build Coastguard Worker // AND. Otherwise, we know the high bits are undefined and a truncate only
3798*9880d681SAndroid Build Coastguard Worker // generate a COPY. We cannot mark the source register also as result
3799*9880d681SAndroid Build Coastguard Worker // register, because this can incorrectly transfer the kill flag onto the
3800*9880d681SAndroid Build Coastguard Worker // source register.
3801*9880d681SAndroid Build Coastguard Worker unsigned ResultReg;
3802*9880d681SAndroid Build Coastguard Worker if (SrcVT == MVT::i64) {
3803*9880d681SAndroid Build Coastguard Worker uint64_t Mask = 0;
3804*9880d681SAndroid Build Coastguard Worker switch (DestVT.SimpleTy) {
3805*9880d681SAndroid Build Coastguard Worker default:
3806*9880d681SAndroid Build Coastguard Worker // Trunc i64 to i32 is handled by the target-independent fast-isel.
3807*9880d681SAndroid Build Coastguard Worker return false;
3808*9880d681SAndroid Build Coastguard Worker case MVT::i1:
3809*9880d681SAndroid Build Coastguard Worker Mask = 0x1;
3810*9880d681SAndroid Build Coastguard Worker break;
3811*9880d681SAndroid Build Coastguard Worker case MVT::i8:
3812*9880d681SAndroid Build Coastguard Worker Mask = 0xff;
3813*9880d681SAndroid Build Coastguard Worker break;
3814*9880d681SAndroid Build Coastguard Worker case MVT::i16:
3815*9880d681SAndroid Build Coastguard Worker Mask = 0xffff;
3816*9880d681SAndroid Build Coastguard Worker break;
3817*9880d681SAndroid Build Coastguard Worker }
3818*9880d681SAndroid Build Coastguard Worker // Issue an extract_subreg to get the lower 32-bits.
3819*9880d681SAndroid Build Coastguard Worker unsigned Reg32 = fastEmitInst_extractsubreg(MVT::i32, SrcReg, SrcIsKill,
3820*9880d681SAndroid Build Coastguard Worker AArch64::sub_32);
3821*9880d681SAndroid Build Coastguard Worker // Create the AND instruction which performs the actual truncation.
3822*9880d681SAndroid Build Coastguard Worker ResultReg = emitAnd_ri(MVT::i32, Reg32, /*IsKill=*/true, Mask);
3823*9880d681SAndroid Build Coastguard Worker assert(ResultReg && "Unexpected AND instruction emission failure.");
3824*9880d681SAndroid Build Coastguard Worker } else {
3825*9880d681SAndroid Build Coastguard Worker ResultReg = createResultReg(&AArch64::GPR32RegClass);
3826*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3827*9880d681SAndroid Build Coastguard Worker TII.get(TargetOpcode::COPY), ResultReg)
3828*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(SrcIsKill));
3829*9880d681SAndroid Build Coastguard Worker }
3830*9880d681SAndroid Build Coastguard Worker
3831*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
3832*9880d681SAndroid Build Coastguard Worker return true;
3833*9880d681SAndroid Build Coastguard Worker }
3834*9880d681SAndroid Build Coastguard Worker
emiti1Ext(unsigned SrcReg,MVT DestVT,bool IsZExt)3835*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emiti1Ext(unsigned SrcReg, MVT DestVT, bool IsZExt) {
3836*9880d681SAndroid Build Coastguard Worker assert((DestVT == MVT::i8 || DestVT == MVT::i16 || DestVT == MVT::i32 ||
3837*9880d681SAndroid Build Coastguard Worker DestVT == MVT::i64) &&
3838*9880d681SAndroid Build Coastguard Worker "Unexpected value type.");
3839*9880d681SAndroid Build Coastguard Worker // Handle i8 and i16 as i32.
3840*9880d681SAndroid Build Coastguard Worker if (DestVT == MVT::i8 || DestVT == MVT::i16)
3841*9880d681SAndroid Build Coastguard Worker DestVT = MVT::i32;
3842*9880d681SAndroid Build Coastguard Worker
3843*9880d681SAndroid Build Coastguard Worker if (IsZExt) {
3844*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = emitAnd_ri(MVT::i32, SrcReg, /*TODO:IsKill=*/false, 1);
3845*9880d681SAndroid Build Coastguard Worker assert(ResultReg && "Unexpected AND instruction emission failure.");
3846*9880d681SAndroid Build Coastguard Worker if (DestVT == MVT::i64) {
3847*9880d681SAndroid Build Coastguard Worker // We're ZExt i1 to i64. The ANDWri Wd, Ws, #1 implicitly clears the
3848*9880d681SAndroid Build Coastguard Worker // upper 32 bits. Emit a SUBREG_TO_REG to extend from Wd to Xd.
3849*9880d681SAndroid Build Coastguard Worker unsigned Reg64 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3850*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3851*9880d681SAndroid Build Coastguard Worker TII.get(AArch64::SUBREG_TO_REG), Reg64)
3852*9880d681SAndroid Build Coastguard Worker .addImm(0)
3853*9880d681SAndroid Build Coastguard Worker .addReg(ResultReg)
3854*9880d681SAndroid Build Coastguard Worker .addImm(AArch64::sub_32);
3855*9880d681SAndroid Build Coastguard Worker ResultReg = Reg64;
3856*9880d681SAndroid Build Coastguard Worker }
3857*9880d681SAndroid Build Coastguard Worker return ResultReg;
3858*9880d681SAndroid Build Coastguard Worker } else {
3859*9880d681SAndroid Build Coastguard Worker if (DestVT == MVT::i64) {
3860*9880d681SAndroid Build Coastguard Worker // FIXME: We're SExt i1 to i64.
3861*9880d681SAndroid Build Coastguard Worker return 0;
3862*9880d681SAndroid Build Coastguard Worker }
3863*9880d681SAndroid Build Coastguard Worker return fastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,
3864*9880d681SAndroid Build Coastguard Worker /*TODO:IsKill=*/false, 0, 0);
3865*9880d681SAndroid Build Coastguard Worker }
3866*9880d681SAndroid Build Coastguard Worker }
3867*9880d681SAndroid Build Coastguard Worker
emitMul_rr(MVT RetVT,unsigned Op0,bool Op0IsKill,unsigned Op1,bool Op1IsKill)3868*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitMul_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
3869*9880d681SAndroid Build Coastguard Worker unsigned Op1, bool Op1IsKill) {
3870*9880d681SAndroid Build Coastguard Worker unsigned Opc, ZReg;
3871*9880d681SAndroid Build Coastguard Worker switch (RetVT.SimpleTy) {
3872*9880d681SAndroid Build Coastguard Worker default: return 0;
3873*9880d681SAndroid Build Coastguard Worker case MVT::i8:
3874*9880d681SAndroid Build Coastguard Worker case MVT::i16:
3875*9880d681SAndroid Build Coastguard Worker case MVT::i32:
3876*9880d681SAndroid Build Coastguard Worker RetVT = MVT::i32;
3877*9880d681SAndroid Build Coastguard Worker Opc = AArch64::MADDWrrr; ZReg = AArch64::WZR; break;
3878*9880d681SAndroid Build Coastguard Worker case MVT::i64:
3879*9880d681SAndroid Build Coastguard Worker Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR; break;
3880*9880d681SAndroid Build Coastguard Worker }
3881*9880d681SAndroid Build Coastguard Worker
3882*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC =
3883*9880d681SAndroid Build Coastguard Worker (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
3884*9880d681SAndroid Build Coastguard Worker return fastEmitInst_rrr(Opc, RC, Op0, Op0IsKill, Op1, Op1IsKill,
3885*9880d681SAndroid Build Coastguard Worker /*IsKill=*/ZReg, true);
3886*9880d681SAndroid Build Coastguard Worker }
3887*9880d681SAndroid Build Coastguard Worker
emitSMULL_rr(MVT RetVT,unsigned Op0,bool Op0IsKill,unsigned Op1,bool Op1IsKill)3888*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitSMULL_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
3889*9880d681SAndroid Build Coastguard Worker unsigned Op1, bool Op1IsKill) {
3890*9880d681SAndroid Build Coastguard Worker if (RetVT != MVT::i64)
3891*9880d681SAndroid Build Coastguard Worker return 0;
3892*9880d681SAndroid Build Coastguard Worker
3893*9880d681SAndroid Build Coastguard Worker return fastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,
3894*9880d681SAndroid Build Coastguard Worker Op0, Op0IsKill, Op1, Op1IsKill,
3895*9880d681SAndroid Build Coastguard Worker AArch64::XZR, /*IsKill=*/true);
3896*9880d681SAndroid Build Coastguard Worker }
3897*9880d681SAndroid Build Coastguard Worker
emitUMULL_rr(MVT RetVT,unsigned Op0,bool Op0IsKill,unsigned Op1,bool Op1IsKill)3898*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitUMULL_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
3899*9880d681SAndroid Build Coastguard Worker unsigned Op1, bool Op1IsKill) {
3900*9880d681SAndroid Build Coastguard Worker if (RetVT != MVT::i64)
3901*9880d681SAndroid Build Coastguard Worker return 0;
3902*9880d681SAndroid Build Coastguard Worker
3903*9880d681SAndroid Build Coastguard Worker return fastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,
3904*9880d681SAndroid Build Coastguard Worker Op0, Op0IsKill, Op1, Op1IsKill,
3905*9880d681SAndroid Build Coastguard Worker AArch64::XZR, /*IsKill=*/true);
3906*9880d681SAndroid Build Coastguard Worker }
3907*9880d681SAndroid Build Coastguard Worker
emitLSL_rr(MVT RetVT,unsigned Op0Reg,bool Op0IsKill,unsigned Op1Reg,bool Op1IsKill)3908*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitLSL_rr(MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
3909*9880d681SAndroid Build Coastguard Worker unsigned Op1Reg, bool Op1IsKill) {
3910*9880d681SAndroid Build Coastguard Worker unsigned Opc = 0;
3911*9880d681SAndroid Build Coastguard Worker bool NeedTrunc = false;
3912*9880d681SAndroid Build Coastguard Worker uint64_t Mask = 0;
3913*9880d681SAndroid Build Coastguard Worker switch (RetVT.SimpleTy) {
3914*9880d681SAndroid Build Coastguard Worker default: return 0;
3915*9880d681SAndroid Build Coastguard Worker case MVT::i8: Opc = AArch64::LSLVWr; NeedTrunc = true; Mask = 0xff; break;
3916*9880d681SAndroid Build Coastguard Worker case MVT::i16: Opc = AArch64::LSLVWr; NeedTrunc = true; Mask = 0xffff; break;
3917*9880d681SAndroid Build Coastguard Worker case MVT::i32: Opc = AArch64::LSLVWr; break;
3918*9880d681SAndroid Build Coastguard Worker case MVT::i64: Opc = AArch64::LSLVXr; break;
3919*9880d681SAndroid Build Coastguard Worker }
3920*9880d681SAndroid Build Coastguard Worker
3921*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC =
3922*9880d681SAndroid Build Coastguard Worker (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
3923*9880d681SAndroid Build Coastguard Worker if (NeedTrunc) {
3924*9880d681SAndroid Build Coastguard Worker Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Op1IsKill, Mask);
3925*9880d681SAndroid Build Coastguard Worker Op1IsKill = true;
3926*9880d681SAndroid Build Coastguard Worker }
3927*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op0IsKill, Op1Reg,
3928*9880d681SAndroid Build Coastguard Worker Op1IsKill);
3929*9880d681SAndroid Build Coastguard Worker if (NeedTrunc)
3930*9880d681SAndroid Build Coastguard Worker ResultReg = emitAnd_ri(MVT::i32, ResultReg, /*IsKill=*/true, Mask);
3931*9880d681SAndroid Build Coastguard Worker return ResultReg;
3932*9880d681SAndroid Build Coastguard Worker }
3933*9880d681SAndroid Build Coastguard Worker
emitLSL_ri(MVT RetVT,MVT SrcVT,unsigned Op0,bool Op0IsKill,uint64_t Shift,bool IsZExt)3934*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitLSL_ri(MVT RetVT, MVT SrcVT, unsigned Op0,
3935*9880d681SAndroid Build Coastguard Worker bool Op0IsKill, uint64_t Shift,
3936*9880d681SAndroid Build Coastguard Worker bool IsZExt) {
3937*9880d681SAndroid Build Coastguard Worker assert(RetVT.SimpleTy >= SrcVT.SimpleTy &&
3938*9880d681SAndroid Build Coastguard Worker "Unexpected source/return type pair.");
3939*9880d681SAndroid Build Coastguard Worker assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
3940*9880d681SAndroid Build Coastguard Worker SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
3941*9880d681SAndroid Build Coastguard Worker "Unexpected source value type.");
3942*9880d681SAndroid Build Coastguard Worker assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
3943*9880d681SAndroid Build Coastguard Worker RetVT == MVT::i64) && "Unexpected return value type.");
3944*9880d681SAndroid Build Coastguard Worker
3945*9880d681SAndroid Build Coastguard Worker bool Is64Bit = (RetVT == MVT::i64);
3946*9880d681SAndroid Build Coastguard Worker unsigned RegSize = Is64Bit ? 64 : 32;
3947*9880d681SAndroid Build Coastguard Worker unsigned DstBits = RetVT.getSizeInBits();
3948*9880d681SAndroid Build Coastguard Worker unsigned SrcBits = SrcVT.getSizeInBits();
3949*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC =
3950*9880d681SAndroid Build Coastguard Worker Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
3951*9880d681SAndroid Build Coastguard Worker
3952*9880d681SAndroid Build Coastguard Worker // Just emit a copy for "zero" shifts.
3953*9880d681SAndroid Build Coastguard Worker if (Shift == 0) {
3954*9880d681SAndroid Build Coastguard Worker if (RetVT == SrcVT) {
3955*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(RC);
3956*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3957*9880d681SAndroid Build Coastguard Worker TII.get(TargetOpcode::COPY), ResultReg)
3958*9880d681SAndroid Build Coastguard Worker .addReg(Op0, getKillRegState(Op0IsKill));
3959*9880d681SAndroid Build Coastguard Worker return ResultReg;
3960*9880d681SAndroid Build Coastguard Worker } else
3961*9880d681SAndroid Build Coastguard Worker return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
3962*9880d681SAndroid Build Coastguard Worker }
3963*9880d681SAndroid Build Coastguard Worker
3964*9880d681SAndroid Build Coastguard Worker // Don't deal with undefined shifts.
3965*9880d681SAndroid Build Coastguard Worker if (Shift >= DstBits)
3966*9880d681SAndroid Build Coastguard Worker return 0;
3967*9880d681SAndroid Build Coastguard Worker
3968*9880d681SAndroid Build Coastguard Worker // For immediate shifts we can fold the zero-/sign-extension into the shift.
3969*9880d681SAndroid Build Coastguard Worker // {S|U}BFM Wd, Wn, #r, #s
3970*9880d681SAndroid Build Coastguard Worker // Wd<32+s-r,32-r> = Wn<s:0> when r > s
3971*9880d681SAndroid Build Coastguard Worker
3972*9880d681SAndroid Build Coastguard Worker // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
3973*9880d681SAndroid Build Coastguard Worker // %2 = shl i16 %1, 4
3974*9880d681SAndroid Build Coastguard Worker // Wd<32+7-28,32-28> = Wn<7:0> <- clamp s to 7
3975*9880d681SAndroid Build Coastguard Worker // 0b1111_1111_1111_1111__1111_1010_1010_0000 sext
3976*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0101_0101_0000 sext | zext
3977*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_1010_1010_0000 zext
3978*9880d681SAndroid Build Coastguard Worker
3979*9880d681SAndroid Build Coastguard Worker // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
3980*9880d681SAndroid Build Coastguard Worker // %2 = shl i16 %1, 8
3981*9880d681SAndroid Build Coastguard Worker // Wd<32+7-24,32-24> = Wn<7:0>
3982*9880d681SAndroid Build Coastguard Worker // 0b1111_1111_1111_1111__1010_1010_0000_0000 sext
3983*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0101_0101_0000_0000 sext | zext
3984*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__1010_1010_0000_0000 zext
3985*9880d681SAndroid Build Coastguard Worker
3986*9880d681SAndroid Build Coastguard Worker // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
3987*9880d681SAndroid Build Coastguard Worker // %2 = shl i16 %1, 12
3988*9880d681SAndroid Build Coastguard Worker // Wd<32+3-20,32-20> = Wn<3:0>
3989*9880d681SAndroid Build Coastguard Worker // 0b1111_1111_1111_1111__1010_0000_0000_0000 sext
3990*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0101_0000_0000_0000 sext | zext
3991*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__1010_0000_0000_0000 zext
3992*9880d681SAndroid Build Coastguard Worker
3993*9880d681SAndroid Build Coastguard Worker unsigned ImmR = RegSize - Shift;
3994*9880d681SAndroid Build Coastguard Worker // Limit the width to the length of the source type.
3995*9880d681SAndroid Build Coastguard Worker unsigned ImmS = std::min<unsigned>(SrcBits - 1, DstBits - 1 - Shift);
3996*9880d681SAndroid Build Coastguard Worker static const unsigned OpcTable[2][2] = {
3997*9880d681SAndroid Build Coastguard Worker {AArch64::SBFMWri, AArch64::SBFMXri},
3998*9880d681SAndroid Build Coastguard Worker {AArch64::UBFMWri, AArch64::UBFMXri}
3999*9880d681SAndroid Build Coastguard Worker };
4000*9880d681SAndroid Build Coastguard Worker unsigned Opc = OpcTable[IsZExt][Is64Bit];
4001*9880d681SAndroid Build Coastguard Worker if (SrcVT.SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4002*9880d681SAndroid Build Coastguard Worker unsigned TmpReg = MRI.createVirtualRegister(RC);
4003*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4004*9880d681SAndroid Build Coastguard Worker TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4005*9880d681SAndroid Build Coastguard Worker .addImm(0)
4006*9880d681SAndroid Build Coastguard Worker .addReg(Op0, getKillRegState(Op0IsKill))
4007*9880d681SAndroid Build Coastguard Worker .addImm(AArch64::sub_32);
4008*9880d681SAndroid Build Coastguard Worker Op0 = TmpReg;
4009*9880d681SAndroid Build Coastguard Worker Op0IsKill = true;
4010*9880d681SAndroid Build Coastguard Worker }
4011*9880d681SAndroid Build Coastguard Worker return fastEmitInst_rii(Opc, RC, Op0, Op0IsKill, ImmR, ImmS);
4012*9880d681SAndroid Build Coastguard Worker }
4013*9880d681SAndroid Build Coastguard Worker
emitLSR_rr(MVT RetVT,unsigned Op0Reg,bool Op0IsKill,unsigned Op1Reg,bool Op1IsKill)4014*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitLSR_rr(MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
4015*9880d681SAndroid Build Coastguard Worker unsigned Op1Reg, bool Op1IsKill) {
4016*9880d681SAndroid Build Coastguard Worker unsigned Opc = 0;
4017*9880d681SAndroid Build Coastguard Worker bool NeedTrunc = false;
4018*9880d681SAndroid Build Coastguard Worker uint64_t Mask = 0;
4019*9880d681SAndroid Build Coastguard Worker switch (RetVT.SimpleTy) {
4020*9880d681SAndroid Build Coastguard Worker default: return 0;
4021*9880d681SAndroid Build Coastguard Worker case MVT::i8: Opc = AArch64::LSRVWr; NeedTrunc = true; Mask = 0xff; break;
4022*9880d681SAndroid Build Coastguard Worker case MVT::i16: Opc = AArch64::LSRVWr; NeedTrunc = true; Mask = 0xffff; break;
4023*9880d681SAndroid Build Coastguard Worker case MVT::i32: Opc = AArch64::LSRVWr; break;
4024*9880d681SAndroid Build Coastguard Worker case MVT::i64: Opc = AArch64::LSRVXr; break;
4025*9880d681SAndroid Build Coastguard Worker }
4026*9880d681SAndroid Build Coastguard Worker
4027*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC =
4028*9880d681SAndroid Build Coastguard Worker (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4029*9880d681SAndroid Build Coastguard Worker if (NeedTrunc) {
4030*9880d681SAndroid Build Coastguard Worker Op0Reg = emitAnd_ri(MVT::i32, Op0Reg, Op0IsKill, Mask);
4031*9880d681SAndroid Build Coastguard Worker Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Op1IsKill, Mask);
4032*9880d681SAndroid Build Coastguard Worker Op0IsKill = Op1IsKill = true;
4033*9880d681SAndroid Build Coastguard Worker }
4034*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op0IsKill, Op1Reg,
4035*9880d681SAndroid Build Coastguard Worker Op1IsKill);
4036*9880d681SAndroid Build Coastguard Worker if (NeedTrunc)
4037*9880d681SAndroid Build Coastguard Worker ResultReg = emitAnd_ri(MVT::i32, ResultReg, /*IsKill=*/true, Mask);
4038*9880d681SAndroid Build Coastguard Worker return ResultReg;
4039*9880d681SAndroid Build Coastguard Worker }
4040*9880d681SAndroid Build Coastguard Worker
emitLSR_ri(MVT RetVT,MVT SrcVT,unsigned Op0,bool Op0IsKill,uint64_t Shift,bool IsZExt)4041*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitLSR_ri(MVT RetVT, MVT SrcVT, unsigned Op0,
4042*9880d681SAndroid Build Coastguard Worker bool Op0IsKill, uint64_t Shift,
4043*9880d681SAndroid Build Coastguard Worker bool IsZExt) {
4044*9880d681SAndroid Build Coastguard Worker assert(RetVT.SimpleTy >= SrcVT.SimpleTy &&
4045*9880d681SAndroid Build Coastguard Worker "Unexpected source/return type pair.");
4046*9880d681SAndroid Build Coastguard Worker assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4047*9880d681SAndroid Build Coastguard Worker SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4048*9880d681SAndroid Build Coastguard Worker "Unexpected source value type.");
4049*9880d681SAndroid Build Coastguard Worker assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4050*9880d681SAndroid Build Coastguard Worker RetVT == MVT::i64) && "Unexpected return value type.");
4051*9880d681SAndroid Build Coastguard Worker
4052*9880d681SAndroid Build Coastguard Worker bool Is64Bit = (RetVT == MVT::i64);
4053*9880d681SAndroid Build Coastguard Worker unsigned RegSize = Is64Bit ? 64 : 32;
4054*9880d681SAndroid Build Coastguard Worker unsigned DstBits = RetVT.getSizeInBits();
4055*9880d681SAndroid Build Coastguard Worker unsigned SrcBits = SrcVT.getSizeInBits();
4056*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC =
4057*9880d681SAndroid Build Coastguard Worker Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4058*9880d681SAndroid Build Coastguard Worker
4059*9880d681SAndroid Build Coastguard Worker // Just emit a copy for "zero" shifts.
4060*9880d681SAndroid Build Coastguard Worker if (Shift == 0) {
4061*9880d681SAndroid Build Coastguard Worker if (RetVT == SrcVT) {
4062*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(RC);
4063*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4064*9880d681SAndroid Build Coastguard Worker TII.get(TargetOpcode::COPY), ResultReg)
4065*9880d681SAndroid Build Coastguard Worker .addReg(Op0, getKillRegState(Op0IsKill));
4066*9880d681SAndroid Build Coastguard Worker return ResultReg;
4067*9880d681SAndroid Build Coastguard Worker } else
4068*9880d681SAndroid Build Coastguard Worker return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4069*9880d681SAndroid Build Coastguard Worker }
4070*9880d681SAndroid Build Coastguard Worker
4071*9880d681SAndroid Build Coastguard Worker // Don't deal with undefined shifts.
4072*9880d681SAndroid Build Coastguard Worker if (Shift >= DstBits)
4073*9880d681SAndroid Build Coastguard Worker return 0;
4074*9880d681SAndroid Build Coastguard Worker
4075*9880d681SAndroid Build Coastguard Worker // For immediate shifts we can fold the zero-/sign-extension into the shift.
4076*9880d681SAndroid Build Coastguard Worker // {S|U}BFM Wd, Wn, #r, #s
4077*9880d681SAndroid Build Coastguard Worker // Wd<s-r:0> = Wn<s:r> when r <= s
4078*9880d681SAndroid Build Coastguard Worker
4079*9880d681SAndroid Build Coastguard Worker // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4080*9880d681SAndroid Build Coastguard Worker // %2 = lshr i16 %1, 4
4081*9880d681SAndroid Build Coastguard Worker // Wd<7-4:0> = Wn<7:4>
4082*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_1111_1111_1010 sext
4083*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0000_0000_0101 sext | zext
4084*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0000_0000_1010 zext
4085*9880d681SAndroid Build Coastguard Worker
4086*9880d681SAndroid Build Coastguard Worker // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4087*9880d681SAndroid Build Coastguard Worker // %2 = lshr i16 %1, 8
4088*9880d681SAndroid Build Coastguard Worker // Wd<7-7,0> = Wn<7:7>
4089*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0000_1111_1111 sext
4090*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext
4091*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext
4092*9880d681SAndroid Build Coastguard Worker
4093*9880d681SAndroid Build Coastguard Worker // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4094*9880d681SAndroid Build Coastguard Worker // %2 = lshr i16 %1, 12
4095*9880d681SAndroid Build Coastguard Worker // Wd<7-7,0> = Wn<7:7> <- clamp r to 7
4096*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0000_0000_1111 sext
4097*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext
4098*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext
4099*9880d681SAndroid Build Coastguard Worker
4100*9880d681SAndroid Build Coastguard Worker if (Shift >= SrcBits && IsZExt)
4101*9880d681SAndroid Build Coastguard Worker return materializeInt(ConstantInt::get(*Context, APInt(RegSize, 0)), RetVT);
4102*9880d681SAndroid Build Coastguard Worker
4103*9880d681SAndroid Build Coastguard Worker // It is not possible to fold a sign-extend into the LShr instruction. In this
4104*9880d681SAndroid Build Coastguard Worker // case emit a sign-extend.
4105*9880d681SAndroid Build Coastguard Worker if (!IsZExt) {
4106*9880d681SAndroid Build Coastguard Worker Op0 = emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4107*9880d681SAndroid Build Coastguard Worker if (!Op0)
4108*9880d681SAndroid Build Coastguard Worker return 0;
4109*9880d681SAndroid Build Coastguard Worker Op0IsKill = true;
4110*9880d681SAndroid Build Coastguard Worker SrcVT = RetVT;
4111*9880d681SAndroid Build Coastguard Worker SrcBits = SrcVT.getSizeInBits();
4112*9880d681SAndroid Build Coastguard Worker IsZExt = true;
4113*9880d681SAndroid Build Coastguard Worker }
4114*9880d681SAndroid Build Coastguard Worker
4115*9880d681SAndroid Build Coastguard Worker unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4116*9880d681SAndroid Build Coastguard Worker unsigned ImmS = SrcBits - 1;
4117*9880d681SAndroid Build Coastguard Worker static const unsigned OpcTable[2][2] = {
4118*9880d681SAndroid Build Coastguard Worker {AArch64::SBFMWri, AArch64::SBFMXri},
4119*9880d681SAndroid Build Coastguard Worker {AArch64::UBFMWri, AArch64::UBFMXri}
4120*9880d681SAndroid Build Coastguard Worker };
4121*9880d681SAndroid Build Coastguard Worker unsigned Opc = OpcTable[IsZExt][Is64Bit];
4122*9880d681SAndroid Build Coastguard Worker if (SrcVT.SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4123*9880d681SAndroid Build Coastguard Worker unsigned TmpReg = MRI.createVirtualRegister(RC);
4124*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4125*9880d681SAndroid Build Coastguard Worker TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4126*9880d681SAndroid Build Coastguard Worker .addImm(0)
4127*9880d681SAndroid Build Coastguard Worker .addReg(Op0, getKillRegState(Op0IsKill))
4128*9880d681SAndroid Build Coastguard Worker .addImm(AArch64::sub_32);
4129*9880d681SAndroid Build Coastguard Worker Op0 = TmpReg;
4130*9880d681SAndroid Build Coastguard Worker Op0IsKill = true;
4131*9880d681SAndroid Build Coastguard Worker }
4132*9880d681SAndroid Build Coastguard Worker return fastEmitInst_rii(Opc, RC, Op0, Op0IsKill, ImmR, ImmS);
4133*9880d681SAndroid Build Coastguard Worker }
4134*9880d681SAndroid Build Coastguard Worker
emitASR_rr(MVT RetVT,unsigned Op0Reg,bool Op0IsKill,unsigned Op1Reg,bool Op1IsKill)4135*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitASR_rr(MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
4136*9880d681SAndroid Build Coastguard Worker unsigned Op1Reg, bool Op1IsKill) {
4137*9880d681SAndroid Build Coastguard Worker unsigned Opc = 0;
4138*9880d681SAndroid Build Coastguard Worker bool NeedTrunc = false;
4139*9880d681SAndroid Build Coastguard Worker uint64_t Mask = 0;
4140*9880d681SAndroid Build Coastguard Worker switch (RetVT.SimpleTy) {
4141*9880d681SAndroid Build Coastguard Worker default: return 0;
4142*9880d681SAndroid Build Coastguard Worker case MVT::i8: Opc = AArch64::ASRVWr; NeedTrunc = true; Mask = 0xff; break;
4143*9880d681SAndroid Build Coastguard Worker case MVT::i16: Opc = AArch64::ASRVWr; NeedTrunc = true; Mask = 0xffff; break;
4144*9880d681SAndroid Build Coastguard Worker case MVT::i32: Opc = AArch64::ASRVWr; break;
4145*9880d681SAndroid Build Coastguard Worker case MVT::i64: Opc = AArch64::ASRVXr; break;
4146*9880d681SAndroid Build Coastguard Worker }
4147*9880d681SAndroid Build Coastguard Worker
4148*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC =
4149*9880d681SAndroid Build Coastguard Worker (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4150*9880d681SAndroid Build Coastguard Worker if (NeedTrunc) {
4151*9880d681SAndroid Build Coastguard Worker Op0Reg = emitIntExt(RetVT, Op0Reg, MVT::i32, /*IsZExt=*/false);
4152*9880d681SAndroid Build Coastguard Worker Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Op1IsKill, Mask);
4153*9880d681SAndroid Build Coastguard Worker Op0IsKill = Op1IsKill = true;
4154*9880d681SAndroid Build Coastguard Worker }
4155*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op0IsKill, Op1Reg,
4156*9880d681SAndroid Build Coastguard Worker Op1IsKill);
4157*9880d681SAndroid Build Coastguard Worker if (NeedTrunc)
4158*9880d681SAndroid Build Coastguard Worker ResultReg = emitAnd_ri(MVT::i32, ResultReg, /*IsKill=*/true, Mask);
4159*9880d681SAndroid Build Coastguard Worker return ResultReg;
4160*9880d681SAndroid Build Coastguard Worker }
4161*9880d681SAndroid Build Coastguard Worker
emitASR_ri(MVT RetVT,MVT SrcVT,unsigned Op0,bool Op0IsKill,uint64_t Shift,bool IsZExt)4162*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitASR_ri(MVT RetVT, MVT SrcVT, unsigned Op0,
4163*9880d681SAndroid Build Coastguard Worker bool Op0IsKill, uint64_t Shift,
4164*9880d681SAndroid Build Coastguard Worker bool IsZExt) {
4165*9880d681SAndroid Build Coastguard Worker assert(RetVT.SimpleTy >= SrcVT.SimpleTy &&
4166*9880d681SAndroid Build Coastguard Worker "Unexpected source/return type pair.");
4167*9880d681SAndroid Build Coastguard Worker assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4168*9880d681SAndroid Build Coastguard Worker SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4169*9880d681SAndroid Build Coastguard Worker "Unexpected source value type.");
4170*9880d681SAndroid Build Coastguard Worker assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4171*9880d681SAndroid Build Coastguard Worker RetVT == MVT::i64) && "Unexpected return value type.");
4172*9880d681SAndroid Build Coastguard Worker
4173*9880d681SAndroid Build Coastguard Worker bool Is64Bit = (RetVT == MVT::i64);
4174*9880d681SAndroid Build Coastguard Worker unsigned RegSize = Is64Bit ? 64 : 32;
4175*9880d681SAndroid Build Coastguard Worker unsigned DstBits = RetVT.getSizeInBits();
4176*9880d681SAndroid Build Coastguard Worker unsigned SrcBits = SrcVT.getSizeInBits();
4177*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC =
4178*9880d681SAndroid Build Coastguard Worker Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4179*9880d681SAndroid Build Coastguard Worker
4180*9880d681SAndroid Build Coastguard Worker // Just emit a copy for "zero" shifts.
4181*9880d681SAndroid Build Coastguard Worker if (Shift == 0) {
4182*9880d681SAndroid Build Coastguard Worker if (RetVT == SrcVT) {
4183*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(RC);
4184*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4185*9880d681SAndroid Build Coastguard Worker TII.get(TargetOpcode::COPY), ResultReg)
4186*9880d681SAndroid Build Coastguard Worker .addReg(Op0, getKillRegState(Op0IsKill));
4187*9880d681SAndroid Build Coastguard Worker return ResultReg;
4188*9880d681SAndroid Build Coastguard Worker } else
4189*9880d681SAndroid Build Coastguard Worker return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4190*9880d681SAndroid Build Coastguard Worker }
4191*9880d681SAndroid Build Coastguard Worker
4192*9880d681SAndroid Build Coastguard Worker // Don't deal with undefined shifts.
4193*9880d681SAndroid Build Coastguard Worker if (Shift >= DstBits)
4194*9880d681SAndroid Build Coastguard Worker return 0;
4195*9880d681SAndroid Build Coastguard Worker
4196*9880d681SAndroid Build Coastguard Worker // For immediate shifts we can fold the zero-/sign-extension into the shift.
4197*9880d681SAndroid Build Coastguard Worker // {S|U}BFM Wd, Wn, #r, #s
4198*9880d681SAndroid Build Coastguard Worker // Wd<s-r:0> = Wn<s:r> when r <= s
4199*9880d681SAndroid Build Coastguard Worker
4200*9880d681SAndroid Build Coastguard Worker // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4201*9880d681SAndroid Build Coastguard Worker // %2 = ashr i16 %1, 4
4202*9880d681SAndroid Build Coastguard Worker // Wd<7-4:0> = Wn<7:4>
4203*9880d681SAndroid Build Coastguard Worker // 0b1111_1111_1111_1111__1111_1111_1111_1010 sext
4204*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0000_0000_0101 sext | zext
4205*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0000_0000_1010 zext
4206*9880d681SAndroid Build Coastguard Worker
4207*9880d681SAndroid Build Coastguard Worker // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4208*9880d681SAndroid Build Coastguard Worker // %2 = ashr i16 %1, 8
4209*9880d681SAndroid Build Coastguard Worker // Wd<7-7,0> = Wn<7:7>
4210*9880d681SAndroid Build Coastguard Worker // 0b1111_1111_1111_1111__1111_1111_1111_1111 sext
4211*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext
4212*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext
4213*9880d681SAndroid Build Coastguard Worker
4214*9880d681SAndroid Build Coastguard Worker // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4215*9880d681SAndroid Build Coastguard Worker // %2 = ashr i16 %1, 12
4216*9880d681SAndroid Build Coastguard Worker // Wd<7-7,0> = Wn<7:7> <- clamp r to 7
4217*9880d681SAndroid Build Coastguard Worker // 0b1111_1111_1111_1111__1111_1111_1111_1111 sext
4218*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext
4219*9880d681SAndroid Build Coastguard Worker // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext
4220*9880d681SAndroid Build Coastguard Worker
4221*9880d681SAndroid Build Coastguard Worker if (Shift >= SrcBits && IsZExt)
4222*9880d681SAndroid Build Coastguard Worker return materializeInt(ConstantInt::get(*Context, APInt(RegSize, 0)), RetVT);
4223*9880d681SAndroid Build Coastguard Worker
4224*9880d681SAndroid Build Coastguard Worker unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4225*9880d681SAndroid Build Coastguard Worker unsigned ImmS = SrcBits - 1;
4226*9880d681SAndroid Build Coastguard Worker static const unsigned OpcTable[2][2] = {
4227*9880d681SAndroid Build Coastguard Worker {AArch64::SBFMWri, AArch64::SBFMXri},
4228*9880d681SAndroid Build Coastguard Worker {AArch64::UBFMWri, AArch64::UBFMXri}
4229*9880d681SAndroid Build Coastguard Worker };
4230*9880d681SAndroid Build Coastguard Worker unsigned Opc = OpcTable[IsZExt][Is64Bit];
4231*9880d681SAndroid Build Coastguard Worker if (SrcVT.SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4232*9880d681SAndroid Build Coastguard Worker unsigned TmpReg = MRI.createVirtualRegister(RC);
4233*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4234*9880d681SAndroid Build Coastguard Worker TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4235*9880d681SAndroid Build Coastguard Worker .addImm(0)
4236*9880d681SAndroid Build Coastguard Worker .addReg(Op0, getKillRegState(Op0IsKill))
4237*9880d681SAndroid Build Coastguard Worker .addImm(AArch64::sub_32);
4238*9880d681SAndroid Build Coastguard Worker Op0 = TmpReg;
4239*9880d681SAndroid Build Coastguard Worker Op0IsKill = true;
4240*9880d681SAndroid Build Coastguard Worker }
4241*9880d681SAndroid Build Coastguard Worker return fastEmitInst_rii(Opc, RC, Op0, Op0IsKill, ImmR, ImmS);
4242*9880d681SAndroid Build Coastguard Worker }
4243*9880d681SAndroid Build Coastguard Worker
emitIntExt(MVT SrcVT,unsigned SrcReg,MVT DestVT,bool IsZExt)4244*9880d681SAndroid Build Coastguard Worker unsigned AArch64FastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
4245*9880d681SAndroid Build Coastguard Worker bool IsZExt) {
4246*9880d681SAndroid Build Coastguard Worker assert(DestVT != MVT::i1 && "ZeroExt/SignExt an i1?");
4247*9880d681SAndroid Build Coastguard Worker
4248*9880d681SAndroid Build Coastguard Worker // FastISel does not have plumbing to deal with extensions where the SrcVT or
4249*9880d681SAndroid Build Coastguard Worker // DestVT are odd things, so test to make sure that they are both types we can
4250*9880d681SAndroid Build Coastguard Worker // handle (i1/i8/i16/i32 for SrcVT and i8/i16/i32/i64 for DestVT), otherwise
4251*9880d681SAndroid Build Coastguard Worker // bail out to SelectionDAG.
4252*9880d681SAndroid Build Coastguard Worker if (((DestVT != MVT::i8) && (DestVT != MVT::i16) &&
4253*9880d681SAndroid Build Coastguard Worker (DestVT != MVT::i32) && (DestVT != MVT::i64)) ||
4254*9880d681SAndroid Build Coastguard Worker ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) &&
4255*9880d681SAndroid Build Coastguard Worker (SrcVT != MVT::i16) && (SrcVT != MVT::i32)))
4256*9880d681SAndroid Build Coastguard Worker return 0;
4257*9880d681SAndroid Build Coastguard Worker
4258*9880d681SAndroid Build Coastguard Worker unsigned Opc;
4259*9880d681SAndroid Build Coastguard Worker unsigned Imm = 0;
4260*9880d681SAndroid Build Coastguard Worker
4261*9880d681SAndroid Build Coastguard Worker switch (SrcVT.SimpleTy) {
4262*9880d681SAndroid Build Coastguard Worker default:
4263*9880d681SAndroid Build Coastguard Worker return 0;
4264*9880d681SAndroid Build Coastguard Worker case MVT::i1:
4265*9880d681SAndroid Build Coastguard Worker return emiti1Ext(SrcReg, DestVT, IsZExt);
4266*9880d681SAndroid Build Coastguard Worker case MVT::i8:
4267*9880d681SAndroid Build Coastguard Worker if (DestVT == MVT::i64)
4268*9880d681SAndroid Build Coastguard Worker Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4269*9880d681SAndroid Build Coastguard Worker else
4270*9880d681SAndroid Build Coastguard Worker Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4271*9880d681SAndroid Build Coastguard Worker Imm = 7;
4272*9880d681SAndroid Build Coastguard Worker break;
4273*9880d681SAndroid Build Coastguard Worker case MVT::i16:
4274*9880d681SAndroid Build Coastguard Worker if (DestVT == MVT::i64)
4275*9880d681SAndroid Build Coastguard Worker Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4276*9880d681SAndroid Build Coastguard Worker else
4277*9880d681SAndroid Build Coastguard Worker Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4278*9880d681SAndroid Build Coastguard Worker Imm = 15;
4279*9880d681SAndroid Build Coastguard Worker break;
4280*9880d681SAndroid Build Coastguard Worker case MVT::i32:
4281*9880d681SAndroid Build Coastguard Worker assert(DestVT == MVT::i64 && "IntExt i32 to i32?!?");
4282*9880d681SAndroid Build Coastguard Worker Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4283*9880d681SAndroid Build Coastguard Worker Imm = 31;
4284*9880d681SAndroid Build Coastguard Worker break;
4285*9880d681SAndroid Build Coastguard Worker }
4286*9880d681SAndroid Build Coastguard Worker
4287*9880d681SAndroid Build Coastguard Worker // Handle i8 and i16 as i32.
4288*9880d681SAndroid Build Coastguard Worker if (DestVT == MVT::i8 || DestVT == MVT::i16)
4289*9880d681SAndroid Build Coastguard Worker DestVT = MVT::i32;
4290*9880d681SAndroid Build Coastguard Worker else if (DestVT == MVT::i64) {
4291*9880d681SAndroid Build Coastguard Worker unsigned Src64 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4292*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4293*9880d681SAndroid Build Coastguard Worker TII.get(AArch64::SUBREG_TO_REG), Src64)
4294*9880d681SAndroid Build Coastguard Worker .addImm(0)
4295*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg)
4296*9880d681SAndroid Build Coastguard Worker .addImm(AArch64::sub_32);
4297*9880d681SAndroid Build Coastguard Worker SrcReg = Src64;
4298*9880d681SAndroid Build Coastguard Worker }
4299*9880d681SAndroid Build Coastguard Worker
4300*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC =
4301*9880d681SAndroid Build Coastguard Worker (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4302*9880d681SAndroid Build Coastguard Worker return fastEmitInst_rii(Opc, RC, SrcReg, /*TODO:IsKill=*/false, 0, Imm);
4303*9880d681SAndroid Build Coastguard Worker }
4304*9880d681SAndroid Build Coastguard Worker
isZExtLoad(const MachineInstr * LI)4305*9880d681SAndroid Build Coastguard Worker static bool isZExtLoad(const MachineInstr *LI) {
4306*9880d681SAndroid Build Coastguard Worker switch (LI->getOpcode()) {
4307*9880d681SAndroid Build Coastguard Worker default:
4308*9880d681SAndroid Build Coastguard Worker return false;
4309*9880d681SAndroid Build Coastguard Worker case AArch64::LDURBBi:
4310*9880d681SAndroid Build Coastguard Worker case AArch64::LDURHHi:
4311*9880d681SAndroid Build Coastguard Worker case AArch64::LDURWi:
4312*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBui:
4313*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHui:
4314*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
4315*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBroX:
4316*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHroX:
4317*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWroX:
4318*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBroW:
4319*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHroW:
4320*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWroW:
4321*9880d681SAndroid Build Coastguard Worker return true;
4322*9880d681SAndroid Build Coastguard Worker }
4323*9880d681SAndroid Build Coastguard Worker }
4324*9880d681SAndroid Build Coastguard Worker
isSExtLoad(const MachineInstr * LI)4325*9880d681SAndroid Build Coastguard Worker static bool isSExtLoad(const MachineInstr *LI) {
4326*9880d681SAndroid Build Coastguard Worker switch (LI->getOpcode()) {
4327*9880d681SAndroid Build Coastguard Worker default:
4328*9880d681SAndroid Build Coastguard Worker return false;
4329*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSBWi:
4330*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSHWi:
4331*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSBXi:
4332*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSHXi:
4333*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSWi:
4334*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBWui:
4335*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHWui:
4336*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBXui:
4337*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHXui:
4338*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWui:
4339*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBWroX:
4340*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHWroX:
4341*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBXroX:
4342*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHXroX:
4343*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWroX:
4344*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBWroW:
4345*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHWroW:
4346*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBXroW:
4347*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHXroW:
4348*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWroW:
4349*9880d681SAndroid Build Coastguard Worker return true;
4350*9880d681SAndroid Build Coastguard Worker }
4351*9880d681SAndroid Build Coastguard Worker }
4352*9880d681SAndroid Build Coastguard Worker
optimizeIntExtLoad(const Instruction * I,MVT RetVT,MVT SrcVT)4353*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::optimizeIntExtLoad(const Instruction *I, MVT RetVT,
4354*9880d681SAndroid Build Coastguard Worker MVT SrcVT) {
4355*9880d681SAndroid Build Coastguard Worker const auto *LI = dyn_cast<LoadInst>(I->getOperand(0));
4356*9880d681SAndroid Build Coastguard Worker if (!LI || !LI->hasOneUse())
4357*9880d681SAndroid Build Coastguard Worker return false;
4358*9880d681SAndroid Build Coastguard Worker
4359*9880d681SAndroid Build Coastguard Worker // Check if the load instruction has already been selected.
4360*9880d681SAndroid Build Coastguard Worker unsigned Reg = lookUpRegForValue(LI);
4361*9880d681SAndroid Build Coastguard Worker if (!Reg)
4362*9880d681SAndroid Build Coastguard Worker return false;
4363*9880d681SAndroid Build Coastguard Worker
4364*9880d681SAndroid Build Coastguard Worker MachineInstr *MI = MRI.getUniqueVRegDef(Reg);
4365*9880d681SAndroid Build Coastguard Worker if (!MI)
4366*9880d681SAndroid Build Coastguard Worker return false;
4367*9880d681SAndroid Build Coastguard Worker
4368*9880d681SAndroid Build Coastguard Worker // Check if the correct load instruction has been emitted - SelectionDAG might
4369*9880d681SAndroid Build Coastguard Worker // have emitted a zero-extending load, but we need a sign-extending load.
4370*9880d681SAndroid Build Coastguard Worker bool IsZExt = isa<ZExtInst>(I);
4371*9880d681SAndroid Build Coastguard Worker const auto *LoadMI = MI;
4372*9880d681SAndroid Build Coastguard Worker if (LoadMI->getOpcode() == TargetOpcode::COPY &&
4373*9880d681SAndroid Build Coastguard Worker LoadMI->getOperand(1).getSubReg() == AArch64::sub_32) {
4374*9880d681SAndroid Build Coastguard Worker unsigned LoadReg = MI->getOperand(1).getReg();
4375*9880d681SAndroid Build Coastguard Worker LoadMI = MRI.getUniqueVRegDef(LoadReg);
4376*9880d681SAndroid Build Coastguard Worker assert(LoadMI && "Expected valid instruction");
4377*9880d681SAndroid Build Coastguard Worker }
4378*9880d681SAndroid Build Coastguard Worker if (!(IsZExt && isZExtLoad(LoadMI)) && !(!IsZExt && isSExtLoad(LoadMI)))
4379*9880d681SAndroid Build Coastguard Worker return false;
4380*9880d681SAndroid Build Coastguard Worker
4381*9880d681SAndroid Build Coastguard Worker // Nothing to be done.
4382*9880d681SAndroid Build Coastguard Worker if (RetVT != MVT::i64 || SrcVT > MVT::i32) {
4383*9880d681SAndroid Build Coastguard Worker updateValueMap(I, Reg);
4384*9880d681SAndroid Build Coastguard Worker return true;
4385*9880d681SAndroid Build Coastguard Worker }
4386*9880d681SAndroid Build Coastguard Worker
4387*9880d681SAndroid Build Coastguard Worker if (IsZExt) {
4388*9880d681SAndroid Build Coastguard Worker unsigned Reg64 = createResultReg(&AArch64::GPR64RegClass);
4389*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4390*9880d681SAndroid Build Coastguard Worker TII.get(AArch64::SUBREG_TO_REG), Reg64)
4391*9880d681SAndroid Build Coastguard Worker .addImm(0)
4392*9880d681SAndroid Build Coastguard Worker .addReg(Reg, getKillRegState(true))
4393*9880d681SAndroid Build Coastguard Worker .addImm(AArch64::sub_32);
4394*9880d681SAndroid Build Coastguard Worker Reg = Reg64;
4395*9880d681SAndroid Build Coastguard Worker } else {
4396*9880d681SAndroid Build Coastguard Worker assert((MI->getOpcode() == TargetOpcode::COPY &&
4397*9880d681SAndroid Build Coastguard Worker MI->getOperand(1).getSubReg() == AArch64::sub_32) &&
4398*9880d681SAndroid Build Coastguard Worker "Expected copy instruction");
4399*9880d681SAndroid Build Coastguard Worker Reg = MI->getOperand(1).getReg();
4400*9880d681SAndroid Build Coastguard Worker MI->eraseFromParent();
4401*9880d681SAndroid Build Coastguard Worker }
4402*9880d681SAndroid Build Coastguard Worker updateValueMap(I, Reg);
4403*9880d681SAndroid Build Coastguard Worker return true;
4404*9880d681SAndroid Build Coastguard Worker }
4405*9880d681SAndroid Build Coastguard Worker
selectIntExt(const Instruction * I)4406*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectIntExt(const Instruction *I) {
4407*9880d681SAndroid Build Coastguard Worker assert((isa<ZExtInst>(I) || isa<SExtInst>(I)) &&
4408*9880d681SAndroid Build Coastguard Worker "Unexpected integer extend instruction.");
4409*9880d681SAndroid Build Coastguard Worker MVT RetVT;
4410*9880d681SAndroid Build Coastguard Worker MVT SrcVT;
4411*9880d681SAndroid Build Coastguard Worker if (!isTypeSupported(I->getType(), RetVT))
4412*9880d681SAndroid Build Coastguard Worker return false;
4413*9880d681SAndroid Build Coastguard Worker
4414*9880d681SAndroid Build Coastguard Worker if (!isTypeSupported(I->getOperand(0)->getType(), SrcVT))
4415*9880d681SAndroid Build Coastguard Worker return false;
4416*9880d681SAndroid Build Coastguard Worker
4417*9880d681SAndroid Build Coastguard Worker // Try to optimize already sign-/zero-extended values from load instructions.
4418*9880d681SAndroid Build Coastguard Worker if (optimizeIntExtLoad(I, RetVT, SrcVT))
4419*9880d681SAndroid Build Coastguard Worker return true;
4420*9880d681SAndroid Build Coastguard Worker
4421*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = getRegForValue(I->getOperand(0));
4422*9880d681SAndroid Build Coastguard Worker if (!SrcReg)
4423*9880d681SAndroid Build Coastguard Worker return false;
4424*9880d681SAndroid Build Coastguard Worker bool SrcIsKill = hasTrivialKill(I->getOperand(0));
4425*9880d681SAndroid Build Coastguard Worker
4426*9880d681SAndroid Build Coastguard Worker // Try to optimize already sign-/zero-extended values from function arguments.
4427*9880d681SAndroid Build Coastguard Worker bool IsZExt = isa<ZExtInst>(I);
4428*9880d681SAndroid Build Coastguard Worker if (const auto *Arg = dyn_cast<Argument>(I->getOperand(0))) {
4429*9880d681SAndroid Build Coastguard Worker if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr())) {
4430*9880d681SAndroid Build Coastguard Worker if (RetVT == MVT::i64 && SrcVT != MVT::i64) {
4431*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = createResultReg(&AArch64::GPR64RegClass);
4432*9880d681SAndroid Build Coastguard Worker BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4433*9880d681SAndroid Build Coastguard Worker TII.get(AArch64::SUBREG_TO_REG), ResultReg)
4434*9880d681SAndroid Build Coastguard Worker .addImm(0)
4435*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(SrcIsKill))
4436*9880d681SAndroid Build Coastguard Worker .addImm(AArch64::sub_32);
4437*9880d681SAndroid Build Coastguard Worker SrcReg = ResultReg;
4438*9880d681SAndroid Build Coastguard Worker }
4439*9880d681SAndroid Build Coastguard Worker // Conservatively clear all kill flags from all uses, because we are
4440*9880d681SAndroid Build Coastguard Worker // replacing a sign-/zero-extend instruction at IR level with a nop at MI
4441*9880d681SAndroid Build Coastguard Worker // level. The result of the instruction at IR level might have been
4442*9880d681SAndroid Build Coastguard Worker // trivially dead, which is now not longer true.
4443*9880d681SAndroid Build Coastguard Worker unsigned UseReg = lookUpRegForValue(I);
4444*9880d681SAndroid Build Coastguard Worker if (UseReg)
4445*9880d681SAndroid Build Coastguard Worker MRI.clearKillFlags(UseReg);
4446*9880d681SAndroid Build Coastguard Worker
4447*9880d681SAndroid Build Coastguard Worker updateValueMap(I, SrcReg);
4448*9880d681SAndroid Build Coastguard Worker return true;
4449*9880d681SAndroid Build Coastguard Worker }
4450*9880d681SAndroid Build Coastguard Worker }
4451*9880d681SAndroid Build Coastguard Worker
4452*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = emitIntExt(SrcVT, SrcReg, RetVT, IsZExt);
4453*9880d681SAndroid Build Coastguard Worker if (!ResultReg)
4454*9880d681SAndroid Build Coastguard Worker return false;
4455*9880d681SAndroid Build Coastguard Worker
4456*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
4457*9880d681SAndroid Build Coastguard Worker return true;
4458*9880d681SAndroid Build Coastguard Worker }
4459*9880d681SAndroid Build Coastguard Worker
selectRem(const Instruction * I,unsigned ISDOpcode)4460*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectRem(const Instruction *I, unsigned ISDOpcode) {
4461*9880d681SAndroid Build Coastguard Worker EVT DestEVT = TLI.getValueType(DL, I->getType(), true);
4462*9880d681SAndroid Build Coastguard Worker if (!DestEVT.isSimple())
4463*9880d681SAndroid Build Coastguard Worker return false;
4464*9880d681SAndroid Build Coastguard Worker
4465*9880d681SAndroid Build Coastguard Worker MVT DestVT = DestEVT.getSimpleVT();
4466*9880d681SAndroid Build Coastguard Worker if (DestVT != MVT::i64 && DestVT != MVT::i32)
4467*9880d681SAndroid Build Coastguard Worker return false;
4468*9880d681SAndroid Build Coastguard Worker
4469*9880d681SAndroid Build Coastguard Worker unsigned DivOpc;
4470*9880d681SAndroid Build Coastguard Worker bool Is64bit = (DestVT == MVT::i64);
4471*9880d681SAndroid Build Coastguard Worker switch (ISDOpcode) {
4472*9880d681SAndroid Build Coastguard Worker default:
4473*9880d681SAndroid Build Coastguard Worker return false;
4474*9880d681SAndroid Build Coastguard Worker case ISD::SREM:
4475*9880d681SAndroid Build Coastguard Worker DivOpc = Is64bit ? AArch64::SDIVXr : AArch64::SDIVWr;
4476*9880d681SAndroid Build Coastguard Worker break;
4477*9880d681SAndroid Build Coastguard Worker case ISD::UREM:
4478*9880d681SAndroid Build Coastguard Worker DivOpc = Is64bit ? AArch64::UDIVXr : AArch64::UDIVWr;
4479*9880d681SAndroid Build Coastguard Worker break;
4480*9880d681SAndroid Build Coastguard Worker }
4481*9880d681SAndroid Build Coastguard Worker unsigned MSubOpc = Is64bit ? AArch64::MSUBXrrr : AArch64::MSUBWrrr;
4482*9880d681SAndroid Build Coastguard Worker unsigned Src0Reg = getRegForValue(I->getOperand(0));
4483*9880d681SAndroid Build Coastguard Worker if (!Src0Reg)
4484*9880d681SAndroid Build Coastguard Worker return false;
4485*9880d681SAndroid Build Coastguard Worker bool Src0IsKill = hasTrivialKill(I->getOperand(0));
4486*9880d681SAndroid Build Coastguard Worker
4487*9880d681SAndroid Build Coastguard Worker unsigned Src1Reg = getRegForValue(I->getOperand(1));
4488*9880d681SAndroid Build Coastguard Worker if (!Src1Reg)
4489*9880d681SAndroid Build Coastguard Worker return false;
4490*9880d681SAndroid Build Coastguard Worker bool Src1IsKill = hasTrivialKill(I->getOperand(1));
4491*9880d681SAndroid Build Coastguard Worker
4492*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC =
4493*9880d681SAndroid Build Coastguard Worker (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4494*9880d681SAndroid Build Coastguard Worker unsigned QuotReg = fastEmitInst_rr(DivOpc, RC, Src0Reg, /*IsKill=*/false,
4495*9880d681SAndroid Build Coastguard Worker Src1Reg, /*IsKill=*/false);
4496*9880d681SAndroid Build Coastguard Worker assert(QuotReg && "Unexpected DIV instruction emission failure.");
4497*9880d681SAndroid Build Coastguard Worker // The remainder is computed as numerator - (quotient * denominator) using the
4498*9880d681SAndroid Build Coastguard Worker // MSUB instruction.
4499*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = fastEmitInst_rrr(MSubOpc, RC, QuotReg, /*IsKill=*/true,
4500*9880d681SAndroid Build Coastguard Worker Src1Reg, Src1IsKill, Src0Reg,
4501*9880d681SAndroid Build Coastguard Worker Src0IsKill);
4502*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
4503*9880d681SAndroid Build Coastguard Worker return true;
4504*9880d681SAndroid Build Coastguard Worker }
4505*9880d681SAndroid Build Coastguard Worker
selectMul(const Instruction * I)4506*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectMul(const Instruction *I) {
4507*9880d681SAndroid Build Coastguard Worker MVT VT;
4508*9880d681SAndroid Build Coastguard Worker if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true))
4509*9880d681SAndroid Build Coastguard Worker return false;
4510*9880d681SAndroid Build Coastguard Worker
4511*9880d681SAndroid Build Coastguard Worker if (VT.isVector())
4512*9880d681SAndroid Build Coastguard Worker return selectBinaryOp(I, ISD::MUL);
4513*9880d681SAndroid Build Coastguard Worker
4514*9880d681SAndroid Build Coastguard Worker const Value *Src0 = I->getOperand(0);
4515*9880d681SAndroid Build Coastguard Worker const Value *Src1 = I->getOperand(1);
4516*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(Src0))
4517*9880d681SAndroid Build Coastguard Worker if (C->getValue().isPowerOf2())
4518*9880d681SAndroid Build Coastguard Worker std::swap(Src0, Src1);
4519*9880d681SAndroid Build Coastguard Worker
4520*9880d681SAndroid Build Coastguard Worker // Try to simplify to a shift instruction.
4521*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(Src1))
4522*9880d681SAndroid Build Coastguard Worker if (C->getValue().isPowerOf2()) {
4523*9880d681SAndroid Build Coastguard Worker uint64_t ShiftVal = C->getValue().logBase2();
4524*9880d681SAndroid Build Coastguard Worker MVT SrcVT = VT;
4525*9880d681SAndroid Build Coastguard Worker bool IsZExt = true;
4526*9880d681SAndroid Build Coastguard Worker if (const auto *ZExt = dyn_cast<ZExtInst>(Src0)) {
4527*9880d681SAndroid Build Coastguard Worker if (!isIntExtFree(ZExt)) {
4528*9880d681SAndroid Build Coastguard Worker MVT VT;
4529*9880d681SAndroid Build Coastguard Worker if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), VT)) {
4530*9880d681SAndroid Build Coastguard Worker SrcVT = VT;
4531*9880d681SAndroid Build Coastguard Worker IsZExt = true;
4532*9880d681SAndroid Build Coastguard Worker Src0 = ZExt->getOperand(0);
4533*9880d681SAndroid Build Coastguard Worker }
4534*9880d681SAndroid Build Coastguard Worker }
4535*9880d681SAndroid Build Coastguard Worker } else if (const auto *SExt = dyn_cast<SExtInst>(Src0)) {
4536*9880d681SAndroid Build Coastguard Worker if (!isIntExtFree(SExt)) {
4537*9880d681SAndroid Build Coastguard Worker MVT VT;
4538*9880d681SAndroid Build Coastguard Worker if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), VT)) {
4539*9880d681SAndroid Build Coastguard Worker SrcVT = VT;
4540*9880d681SAndroid Build Coastguard Worker IsZExt = false;
4541*9880d681SAndroid Build Coastguard Worker Src0 = SExt->getOperand(0);
4542*9880d681SAndroid Build Coastguard Worker }
4543*9880d681SAndroid Build Coastguard Worker }
4544*9880d681SAndroid Build Coastguard Worker }
4545*9880d681SAndroid Build Coastguard Worker
4546*9880d681SAndroid Build Coastguard Worker unsigned Src0Reg = getRegForValue(Src0);
4547*9880d681SAndroid Build Coastguard Worker if (!Src0Reg)
4548*9880d681SAndroid Build Coastguard Worker return false;
4549*9880d681SAndroid Build Coastguard Worker bool Src0IsKill = hasTrivialKill(Src0);
4550*9880d681SAndroid Build Coastguard Worker
4551*9880d681SAndroid Build Coastguard Worker unsigned ResultReg =
4552*9880d681SAndroid Build Coastguard Worker emitLSL_ri(VT, SrcVT, Src0Reg, Src0IsKill, ShiftVal, IsZExt);
4553*9880d681SAndroid Build Coastguard Worker
4554*9880d681SAndroid Build Coastguard Worker if (ResultReg) {
4555*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
4556*9880d681SAndroid Build Coastguard Worker return true;
4557*9880d681SAndroid Build Coastguard Worker }
4558*9880d681SAndroid Build Coastguard Worker }
4559*9880d681SAndroid Build Coastguard Worker
4560*9880d681SAndroid Build Coastguard Worker unsigned Src0Reg = getRegForValue(I->getOperand(0));
4561*9880d681SAndroid Build Coastguard Worker if (!Src0Reg)
4562*9880d681SAndroid Build Coastguard Worker return false;
4563*9880d681SAndroid Build Coastguard Worker bool Src0IsKill = hasTrivialKill(I->getOperand(0));
4564*9880d681SAndroid Build Coastguard Worker
4565*9880d681SAndroid Build Coastguard Worker unsigned Src1Reg = getRegForValue(I->getOperand(1));
4566*9880d681SAndroid Build Coastguard Worker if (!Src1Reg)
4567*9880d681SAndroid Build Coastguard Worker return false;
4568*9880d681SAndroid Build Coastguard Worker bool Src1IsKill = hasTrivialKill(I->getOperand(1));
4569*9880d681SAndroid Build Coastguard Worker
4570*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = emitMul_rr(VT, Src0Reg, Src0IsKill, Src1Reg, Src1IsKill);
4571*9880d681SAndroid Build Coastguard Worker
4572*9880d681SAndroid Build Coastguard Worker if (!ResultReg)
4573*9880d681SAndroid Build Coastguard Worker return false;
4574*9880d681SAndroid Build Coastguard Worker
4575*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
4576*9880d681SAndroid Build Coastguard Worker return true;
4577*9880d681SAndroid Build Coastguard Worker }
4578*9880d681SAndroid Build Coastguard Worker
selectShift(const Instruction * I)4579*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectShift(const Instruction *I) {
4580*9880d681SAndroid Build Coastguard Worker MVT RetVT;
4581*9880d681SAndroid Build Coastguard Worker if (!isTypeSupported(I->getType(), RetVT, /*IsVectorAllowed=*/true))
4582*9880d681SAndroid Build Coastguard Worker return false;
4583*9880d681SAndroid Build Coastguard Worker
4584*9880d681SAndroid Build Coastguard Worker if (RetVT.isVector())
4585*9880d681SAndroid Build Coastguard Worker return selectOperator(I, I->getOpcode());
4586*9880d681SAndroid Build Coastguard Worker
4587*9880d681SAndroid Build Coastguard Worker if (const auto *C = dyn_cast<ConstantInt>(I->getOperand(1))) {
4588*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = 0;
4589*9880d681SAndroid Build Coastguard Worker uint64_t ShiftVal = C->getZExtValue();
4590*9880d681SAndroid Build Coastguard Worker MVT SrcVT = RetVT;
4591*9880d681SAndroid Build Coastguard Worker bool IsZExt = I->getOpcode() != Instruction::AShr;
4592*9880d681SAndroid Build Coastguard Worker const Value *Op0 = I->getOperand(0);
4593*9880d681SAndroid Build Coastguard Worker if (const auto *ZExt = dyn_cast<ZExtInst>(Op0)) {
4594*9880d681SAndroid Build Coastguard Worker if (!isIntExtFree(ZExt)) {
4595*9880d681SAndroid Build Coastguard Worker MVT TmpVT;
4596*9880d681SAndroid Build Coastguard Worker if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), TmpVT)) {
4597*9880d681SAndroid Build Coastguard Worker SrcVT = TmpVT;
4598*9880d681SAndroid Build Coastguard Worker IsZExt = true;
4599*9880d681SAndroid Build Coastguard Worker Op0 = ZExt->getOperand(0);
4600*9880d681SAndroid Build Coastguard Worker }
4601*9880d681SAndroid Build Coastguard Worker }
4602*9880d681SAndroid Build Coastguard Worker } else if (const auto *SExt = dyn_cast<SExtInst>(Op0)) {
4603*9880d681SAndroid Build Coastguard Worker if (!isIntExtFree(SExt)) {
4604*9880d681SAndroid Build Coastguard Worker MVT TmpVT;
4605*9880d681SAndroid Build Coastguard Worker if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), TmpVT)) {
4606*9880d681SAndroid Build Coastguard Worker SrcVT = TmpVT;
4607*9880d681SAndroid Build Coastguard Worker IsZExt = false;
4608*9880d681SAndroid Build Coastguard Worker Op0 = SExt->getOperand(0);
4609*9880d681SAndroid Build Coastguard Worker }
4610*9880d681SAndroid Build Coastguard Worker }
4611*9880d681SAndroid Build Coastguard Worker }
4612*9880d681SAndroid Build Coastguard Worker
4613*9880d681SAndroid Build Coastguard Worker unsigned Op0Reg = getRegForValue(Op0);
4614*9880d681SAndroid Build Coastguard Worker if (!Op0Reg)
4615*9880d681SAndroid Build Coastguard Worker return false;
4616*9880d681SAndroid Build Coastguard Worker bool Op0IsKill = hasTrivialKill(Op0);
4617*9880d681SAndroid Build Coastguard Worker
4618*9880d681SAndroid Build Coastguard Worker switch (I->getOpcode()) {
4619*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Unexpected instruction.");
4620*9880d681SAndroid Build Coastguard Worker case Instruction::Shl:
4621*9880d681SAndroid Build Coastguard Worker ResultReg = emitLSL_ri(RetVT, SrcVT, Op0Reg, Op0IsKill, ShiftVal, IsZExt);
4622*9880d681SAndroid Build Coastguard Worker break;
4623*9880d681SAndroid Build Coastguard Worker case Instruction::AShr:
4624*9880d681SAndroid Build Coastguard Worker ResultReg = emitASR_ri(RetVT, SrcVT, Op0Reg, Op0IsKill, ShiftVal, IsZExt);
4625*9880d681SAndroid Build Coastguard Worker break;
4626*9880d681SAndroid Build Coastguard Worker case Instruction::LShr:
4627*9880d681SAndroid Build Coastguard Worker ResultReg = emitLSR_ri(RetVT, SrcVT, Op0Reg, Op0IsKill, ShiftVal, IsZExt);
4628*9880d681SAndroid Build Coastguard Worker break;
4629*9880d681SAndroid Build Coastguard Worker }
4630*9880d681SAndroid Build Coastguard Worker if (!ResultReg)
4631*9880d681SAndroid Build Coastguard Worker return false;
4632*9880d681SAndroid Build Coastguard Worker
4633*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
4634*9880d681SAndroid Build Coastguard Worker return true;
4635*9880d681SAndroid Build Coastguard Worker }
4636*9880d681SAndroid Build Coastguard Worker
4637*9880d681SAndroid Build Coastguard Worker unsigned Op0Reg = getRegForValue(I->getOperand(0));
4638*9880d681SAndroid Build Coastguard Worker if (!Op0Reg)
4639*9880d681SAndroid Build Coastguard Worker return false;
4640*9880d681SAndroid Build Coastguard Worker bool Op0IsKill = hasTrivialKill(I->getOperand(0));
4641*9880d681SAndroid Build Coastguard Worker
4642*9880d681SAndroid Build Coastguard Worker unsigned Op1Reg = getRegForValue(I->getOperand(1));
4643*9880d681SAndroid Build Coastguard Worker if (!Op1Reg)
4644*9880d681SAndroid Build Coastguard Worker return false;
4645*9880d681SAndroid Build Coastguard Worker bool Op1IsKill = hasTrivialKill(I->getOperand(1));
4646*9880d681SAndroid Build Coastguard Worker
4647*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = 0;
4648*9880d681SAndroid Build Coastguard Worker switch (I->getOpcode()) {
4649*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Unexpected instruction.");
4650*9880d681SAndroid Build Coastguard Worker case Instruction::Shl:
4651*9880d681SAndroid Build Coastguard Worker ResultReg = emitLSL_rr(RetVT, Op0Reg, Op0IsKill, Op1Reg, Op1IsKill);
4652*9880d681SAndroid Build Coastguard Worker break;
4653*9880d681SAndroid Build Coastguard Worker case Instruction::AShr:
4654*9880d681SAndroid Build Coastguard Worker ResultReg = emitASR_rr(RetVT, Op0Reg, Op0IsKill, Op1Reg, Op1IsKill);
4655*9880d681SAndroid Build Coastguard Worker break;
4656*9880d681SAndroid Build Coastguard Worker case Instruction::LShr:
4657*9880d681SAndroid Build Coastguard Worker ResultReg = emitLSR_rr(RetVT, Op0Reg, Op0IsKill, Op1Reg, Op1IsKill);
4658*9880d681SAndroid Build Coastguard Worker break;
4659*9880d681SAndroid Build Coastguard Worker }
4660*9880d681SAndroid Build Coastguard Worker
4661*9880d681SAndroid Build Coastguard Worker if (!ResultReg)
4662*9880d681SAndroid Build Coastguard Worker return false;
4663*9880d681SAndroid Build Coastguard Worker
4664*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
4665*9880d681SAndroid Build Coastguard Worker return true;
4666*9880d681SAndroid Build Coastguard Worker }
4667*9880d681SAndroid Build Coastguard Worker
selectBitCast(const Instruction * I)4668*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectBitCast(const Instruction *I) {
4669*9880d681SAndroid Build Coastguard Worker MVT RetVT, SrcVT;
4670*9880d681SAndroid Build Coastguard Worker
4671*9880d681SAndroid Build Coastguard Worker if (!isTypeLegal(I->getOperand(0)->getType(), SrcVT))
4672*9880d681SAndroid Build Coastguard Worker return false;
4673*9880d681SAndroid Build Coastguard Worker if (!isTypeLegal(I->getType(), RetVT))
4674*9880d681SAndroid Build Coastguard Worker return false;
4675*9880d681SAndroid Build Coastguard Worker
4676*9880d681SAndroid Build Coastguard Worker unsigned Opc;
4677*9880d681SAndroid Build Coastguard Worker if (RetVT == MVT::f32 && SrcVT == MVT::i32)
4678*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMOVWSr;
4679*9880d681SAndroid Build Coastguard Worker else if (RetVT == MVT::f64 && SrcVT == MVT::i64)
4680*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMOVXDr;
4681*9880d681SAndroid Build Coastguard Worker else if (RetVT == MVT::i32 && SrcVT == MVT::f32)
4682*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMOVSWr;
4683*9880d681SAndroid Build Coastguard Worker else if (RetVT == MVT::i64 && SrcVT == MVT::f64)
4684*9880d681SAndroid Build Coastguard Worker Opc = AArch64::FMOVDXr;
4685*9880d681SAndroid Build Coastguard Worker else
4686*9880d681SAndroid Build Coastguard Worker return false;
4687*9880d681SAndroid Build Coastguard Worker
4688*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = nullptr;
4689*9880d681SAndroid Build Coastguard Worker switch (RetVT.SimpleTy) {
4690*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Unexpected value type.");
4691*9880d681SAndroid Build Coastguard Worker case MVT::i32: RC = &AArch64::GPR32RegClass; break;
4692*9880d681SAndroid Build Coastguard Worker case MVT::i64: RC = &AArch64::GPR64RegClass; break;
4693*9880d681SAndroid Build Coastguard Worker case MVT::f32: RC = &AArch64::FPR32RegClass; break;
4694*9880d681SAndroid Build Coastguard Worker case MVT::f64: RC = &AArch64::FPR64RegClass; break;
4695*9880d681SAndroid Build Coastguard Worker }
4696*9880d681SAndroid Build Coastguard Worker unsigned Op0Reg = getRegForValue(I->getOperand(0));
4697*9880d681SAndroid Build Coastguard Worker if (!Op0Reg)
4698*9880d681SAndroid Build Coastguard Worker return false;
4699*9880d681SAndroid Build Coastguard Worker bool Op0IsKill = hasTrivialKill(I->getOperand(0));
4700*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = fastEmitInst_r(Opc, RC, Op0Reg, Op0IsKill);
4701*9880d681SAndroid Build Coastguard Worker
4702*9880d681SAndroid Build Coastguard Worker if (!ResultReg)
4703*9880d681SAndroid Build Coastguard Worker return false;
4704*9880d681SAndroid Build Coastguard Worker
4705*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
4706*9880d681SAndroid Build Coastguard Worker return true;
4707*9880d681SAndroid Build Coastguard Worker }
4708*9880d681SAndroid Build Coastguard Worker
selectFRem(const Instruction * I)4709*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectFRem(const Instruction *I) {
4710*9880d681SAndroid Build Coastguard Worker MVT RetVT;
4711*9880d681SAndroid Build Coastguard Worker if (!isTypeLegal(I->getType(), RetVT))
4712*9880d681SAndroid Build Coastguard Worker return false;
4713*9880d681SAndroid Build Coastguard Worker
4714*9880d681SAndroid Build Coastguard Worker RTLIB::Libcall LC;
4715*9880d681SAndroid Build Coastguard Worker switch (RetVT.SimpleTy) {
4716*9880d681SAndroid Build Coastguard Worker default:
4717*9880d681SAndroid Build Coastguard Worker return false;
4718*9880d681SAndroid Build Coastguard Worker case MVT::f32:
4719*9880d681SAndroid Build Coastguard Worker LC = RTLIB::REM_F32;
4720*9880d681SAndroid Build Coastguard Worker break;
4721*9880d681SAndroid Build Coastguard Worker case MVT::f64:
4722*9880d681SAndroid Build Coastguard Worker LC = RTLIB::REM_F64;
4723*9880d681SAndroid Build Coastguard Worker break;
4724*9880d681SAndroid Build Coastguard Worker }
4725*9880d681SAndroid Build Coastguard Worker
4726*9880d681SAndroid Build Coastguard Worker ArgListTy Args;
4727*9880d681SAndroid Build Coastguard Worker Args.reserve(I->getNumOperands());
4728*9880d681SAndroid Build Coastguard Worker
4729*9880d681SAndroid Build Coastguard Worker // Populate the argument list.
4730*9880d681SAndroid Build Coastguard Worker for (auto &Arg : I->operands()) {
4731*9880d681SAndroid Build Coastguard Worker ArgListEntry Entry;
4732*9880d681SAndroid Build Coastguard Worker Entry.Val = Arg;
4733*9880d681SAndroid Build Coastguard Worker Entry.Ty = Arg->getType();
4734*9880d681SAndroid Build Coastguard Worker Args.push_back(Entry);
4735*9880d681SAndroid Build Coastguard Worker }
4736*9880d681SAndroid Build Coastguard Worker
4737*9880d681SAndroid Build Coastguard Worker CallLoweringInfo CLI;
4738*9880d681SAndroid Build Coastguard Worker MCContext &Ctx = MF->getContext();
4739*9880d681SAndroid Build Coastguard Worker CLI.setCallee(DL, Ctx, TLI.getLibcallCallingConv(LC), I->getType(),
4740*9880d681SAndroid Build Coastguard Worker TLI.getLibcallName(LC), std::move(Args));
4741*9880d681SAndroid Build Coastguard Worker if (!lowerCallTo(CLI))
4742*9880d681SAndroid Build Coastguard Worker return false;
4743*9880d681SAndroid Build Coastguard Worker updateValueMap(I, CLI.ResultReg);
4744*9880d681SAndroid Build Coastguard Worker return true;
4745*9880d681SAndroid Build Coastguard Worker }
4746*9880d681SAndroid Build Coastguard Worker
selectSDiv(const Instruction * I)4747*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectSDiv(const Instruction *I) {
4748*9880d681SAndroid Build Coastguard Worker MVT VT;
4749*9880d681SAndroid Build Coastguard Worker if (!isTypeLegal(I->getType(), VT))
4750*9880d681SAndroid Build Coastguard Worker return false;
4751*9880d681SAndroid Build Coastguard Worker
4752*9880d681SAndroid Build Coastguard Worker if (!isa<ConstantInt>(I->getOperand(1)))
4753*9880d681SAndroid Build Coastguard Worker return selectBinaryOp(I, ISD::SDIV);
4754*9880d681SAndroid Build Coastguard Worker
4755*9880d681SAndroid Build Coastguard Worker const APInt &C = cast<ConstantInt>(I->getOperand(1))->getValue();
4756*9880d681SAndroid Build Coastguard Worker if ((VT != MVT::i32 && VT != MVT::i64) || !C ||
4757*9880d681SAndroid Build Coastguard Worker !(C.isPowerOf2() || (-C).isPowerOf2()))
4758*9880d681SAndroid Build Coastguard Worker return selectBinaryOp(I, ISD::SDIV);
4759*9880d681SAndroid Build Coastguard Worker
4760*9880d681SAndroid Build Coastguard Worker unsigned Lg2 = C.countTrailingZeros();
4761*9880d681SAndroid Build Coastguard Worker unsigned Src0Reg = getRegForValue(I->getOperand(0));
4762*9880d681SAndroid Build Coastguard Worker if (!Src0Reg)
4763*9880d681SAndroid Build Coastguard Worker return false;
4764*9880d681SAndroid Build Coastguard Worker bool Src0IsKill = hasTrivialKill(I->getOperand(0));
4765*9880d681SAndroid Build Coastguard Worker
4766*9880d681SAndroid Build Coastguard Worker if (cast<BinaryOperator>(I)->isExact()) {
4767*9880d681SAndroid Build Coastguard Worker unsigned ResultReg = emitASR_ri(VT, VT, Src0Reg, Src0IsKill, Lg2);
4768*9880d681SAndroid Build Coastguard Worker if (!ResultReg)
4769*9880d681SAndroid Build Coastguard Worker return false;
4770*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
4771*9880d681SAndroid Build Coastguard Worker return true;
4772*9880d681SAndroid Build Coastguard Worker }
4773*9880d681SAndroid Build Coastguard Worker
4774*9880d681SAndroid Build Coastguard Worker int64_t Pow2MinusOne = (1ULL << Lg2) - 1;
4775*9880d681SAndroid Build Coastguard Worker unsigned AddReg = emitAdd_ri_(VT, Src0Reg, /*IsKill=*/false, Pow2MinusOne);
4776*9880d681SAndroid Build Coastguard Worker if (!AddReg)
4777*9880d681SAndroid Build Coastguard Worker return false;
4778*9880d681SAndroid Build Coastguard Worker
4779*9880d681SAndroid Build Coastguard Worker // (Src0 < 0) ? Pow2 - 1 : 0;
4780*9880d681SAndroid Build Coastguard Worker if (!emitICmp_ri(VT, Src0Reg, /*IsKill=*/false, 0))
4781*9880d681SAndroid Build Coastguard Worker return false;
4782*9880d681SAndroid Build Coastguard Worker
4783*9880d681SAndroid Build Coastguard Worker unsigned SelectOpc;
4784*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC;
4785*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i64) {
4786*9880d681SAndroid Build Coastguard Worker SelectOpc = AArch64::CSELXr;
4787*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR64RegClass;
4788*9880d681SAndroid Build Coastguard Worker } else {
4789*9880d681SAndroid Build Coastguard Worker SelectOpc = AArch64::CSELWr;
4790*9880d681SAndroid Build Coastguard Worker RC = &AArch64::GPR32RegClass;
4791*9880d681SAndroid Build Coastguard Worker }
4792*9880d681SAndroid Build Coastguard Worker unsigned SelectReg =
4793*9880d681SAndroid Build Coastguard Worker fastEmitInst_rri(SelectOpc, RC, AddReg, /*IsKill=*/true, Src0Reg,
4794*9880d681SAndroid Build Coastguard Worker Src0IsKill, AArch64CC::LT);
4795*9880d681SAndroid Build Coastguard Worker if (!SelectReg)
4796*9880d681SAndroid Build Coastguard Worker return false;
4797*9880d681SAndroid Build Coastguard Worker
4798*9880d681SAndroid Build Coastguard Worker // Divide by Pow2 --> ashr. If we're dividing by a negative value we must also
4799*9880d681SAndroid Build Coastguard Worker // negate the result.
4800*9880d681SAndroid Build Coastguard Worker unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
4801*9880d681SAndroid Build Coastguard Worker unsigned ResultReg;
4802*9880d681SAndroid Build Coastguard Worker if (C.isNegative())
4803*9880d681SAndroid Build Coastguard Worker ResultReg = emitAddSub_rs(/*UseAdd=*/false, VT, ZeroReg, /*IsKill=*/true,
4804*9880d681SAndroid Build Coastguard Worker SelectReg, /*IsKill=*/true, AArch64_AM::ASR, Lg2);
4805*9880d681SAndroid Build Coastguard Worker else
4806*9880d681SAndroid Build Coastguard Worker ResultReg = emitASR_ri(VT, VT, SelectReg, /*IsKill=*/true, Lg2);
4807*9880d681SAndroid Build Coastguard Worker
4808*9880d681SAndroid Build Coastguard Worker if (!ResultReg)
4809*9880d681SAndroid Build Coastguard Worker return false;
4810*9880d681SAndroid Build Coastguard Worker
4811*9880d681SAndroid Build Coastguard Worker updateValueMap(I, ResultReg);
4812*9880d681SAndroid Build Coastguard Worker return true;
4813*9880d681SAndroid Build Coastguard Worker }
4814*9880d681SAndroid Build Coastguard Worker
4815*9880d681SAndroid Build Coastguard Worker /// This is mostly a copy of the existing FastISel getRegForGEPIndex code. We
4816*9880d681SAndroid Build Coastguard Worker /// have to duplicate it for AArch64, because otherwise we would fail during the
4817*9880d681SAndroid Build Coastguard Worker /// sign-extend emission.
getRegForGEPIndex(const Value * Idx)4818*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, bool> AArch64FastISel::getRegForGEPIndex(const Value *Idx) {
4819*9880d681SAndroid Build Coastguard Worker unsigned IdxN = getRegForValue(Idx);
4820*9880d681SAndroid Build Coastguard Worker if (IdxN == 0)
4821*9880d681SAndroid Build Coastguard Worker // Unhandled operand. Halt "fast" selection and bail.
4822*9880d681SAndroid Build Coastguard Worker return std::pair<unsigned, bool>(0, false);
4823*9880d681SAndroid Build Coastguard Worker
4824*9880d681SAndroid Build Coastguard Worker bool IdxNIsKill = hasTrivialKill(Idx);
4825*9880d681SAndroid Build Coastguard Worker
4826*9880d681SAndroid Build Coastguard Worker // If the index is smaller or larger than intptr_t, truncate or extend it.
4827*9880d681SAndroid Build Coastguard Worker MVT PtrVT = TLI.getPointerTy(DL);
4828*9880d681SAndroid Build Coastguard Worker EVT IdxVT = EVT::getEVT(Idx->getType(), /*HandleUnknown=*/false);
4829*9880d681SAndroid Build Coastguard Worker if (IdxVT.bitsLT(PtrVT)) {
4830*9880d681SAndroid Build Coastguard Worker IdxN = emitIntExt(IdxVT.getSimpleVT(), IdxN, PtrVT, /*IsZExt=*/false);
4831*9880d681SAndroid Build Coastguard Worker IdxNIsKill = true;
4832*9880d681SAndroid Build Coastguard Worker } else if (IdxVT.bitsGT(PtrVT))
4833*9880d681SAndroid Build Coastguard Worker llvm_unreachable("AArch64 FastISel doesn't support types larger than i64");
4834*9880d681SAndroid Build Coastguard Worker return std::pair<unsigned, bool>(IdxN, IdxNIsKill);
4835*9880d681SAndroid Build Coastguard Worker }
4836*9880d681SAndroid Build Coastguard Worker
4837*9880d681SAndroid Build Coastguard Worker /// This is mostly a copy of the existing FastISel GEP code, but we have to
4838*9880d681SAndroid Build Coastguard Worker /// duplicate it for AArch64, because otherwise we would bail out even for
4839*9880d681SAndroid Build Coastguard Worker /// simple cases. This is because the standard fastEmit functions don't cover
4840*9880d681SAndroid Build Coastguard Worker /// MUL at all and ADD is lowered very inefficientily.
selectGetElementPtr(const Instruction * I)4841*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::selectGetElementPtr(const Instruction *I) {
4842*9880d681SAndroid Build Coastguard Worker unsigned N = getRegForValue(I->getOperand(0));
4843*9880d681SAndroid Build Coastguard Worker if (!N)
4844*9880d681SAndroid Build Coastguard Worker return false;
4845*9880d681SAndroid Build Coastguard Worker bool NIsKill = hasTrivialKill(I->getOperand(0));
4846*9880d681SAndroid Build Coastguard Worker
4847*9880d681SAndroid Build Coastguard Worker // Keep a running tab of the total offset to coalesce multiple N = N + Offset
4848*9880d681SAndroid Build Coastguard Worker // into a single N = N + TotalOffset.
4849*9880d681SAndroid Build Coastguard Worker uint64_t TotalOffs = 0;
4850*9880d681SAndroid Build Coastguard Worker MVT VT = TLI.getPointerTy(DL);
4851*9880d681SAndroid Build Coastguard Worker for (gep_type_iterator GTI = gep_type_begin(I), E = gep_type_end(I);
4852*9880d681SAndroid Build Coastguard Worker GTI != E; ++GTI) {
4853*9880d681SAndroid Build Coastguard Worker const Value *Idx = GTI.getOperand();
4854*9880d681SAndroid Build Coastguard Worker if (auto *StTy = dyn_cast<StructType>(*GTI)) {
4855*9880d681SAndroid Build Coastguard Worker unsigned Field = cast<ConstantInt>(Idx)->getZExtValue();
4856*9880d681SAndroid Build Coastguard Worker // N = N + Offset
4857*9880d681SAndroid Build Coastguard Worker if (Field)
4858*9880d681SAndroid Build Coastguard Worker TotalOffs += DL.getStructLayout(StTy)->getElementOffset(Field);
4859*9880d681SAndroid Build Coastguard Worker } else {
4860*9880d681SAndroid Build Coastguard Worker Type *Ty = GTI.getIndexedType();
4861*9880d681SAndroid Build Coastguard Worker
4862*9880d681SAndroid Build Coastguard Worker // If this is a constant subscript, handle it quickly.
4863*9880d681SAndroid Build Coastguard Worker if (const auto *CI = dyn_cast<ConstantInt>(Idx)) {
4864*9880d681SAndroid Build Coastguard Worker if (CI->isZero())
4865*9880d681SAndroid Build Coastguard Worker continue;
4866*9880d681SAndroid Build Coastguard Worker // N = N + Offset
4867*9880d681SAndroid Build Coastguard Worker TotalOffs +=
4868*9880d681SAndroid Build Coastguard Worker DL.getTypeAllocSize(Ty) * cast<ConstantInt>(CI)->getSExtValue();
4869*9880d681SAndroid Build Coastguard Worker continue;
4870*9880d681SAndroid Build Coastguard Worker }
4871*9880d681SAndroid Build Coastguard Worker if (TotalOffs) {
4872*9880d681SAndroid Build Coastguard Worker N = emitAdd_ri_(VT, N, NIsKill, TotalOffs);
4873*9880d681SAndroid Build Coastguard Worker if (!N)
4874*9880d681SAndroid Build Coastguard Worker return false;
4875*9880d681SAndroid Build Coastguard Worker NIsKill = true;
4876*9880d681SAndroid Build Coastguard Worker TotalOffs = 0;
4877*9880d681SAndroid Build Coastguard Worker }
4878*9880d681SAndroid Build Coastguard Worker
4879*9880d681SAndroid Build Coastguard Worker // N = N + Idx * ElementSize;
4880*9880d681SAndroid Build Coastguard Worker uint64_t ElementSize = DL.getTypeAllocSize(Ty);
4881*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, bool> Pair = getRegForGEPIndex(Idx);
4882*9880d681SAndroid Build Coastguard Worker unsigned IdxN = Pair.first;
4883*9880d681SAndroid Build Coastguard Worker bool IdxNIsKill = Pair.second;
4884*9880d681SAndroid Build Coastguard Worker if (!IdxN)
4885*9880d681SAndroid Build Coastguard Worker return false;
4886*9880d681SAndroid Build Coastguard Worker
4887*9880d681SAndroid Build Coastguard Worker if (ElementSize != 1) {
4888*9880d681SAndroid Build Coastguard Worker unsigned C = fastEmit_i(VT, VT, ISD::Constant, ElementSize);
4889*9880d681SAndroid Build Coastguard Worker if (!C)
4890*9880d681SAndroid Build Coastguard Worker return false;
4891*9880d681SAndroid Build Coastguard Worker IdxN = emitMul_rr(VT, IdxN, IdxNIsKill, C, true);
4892*9880d681SAndroid Build Coastguard Worker if (!IdxN)
4893*9880d681SAndroid Build Coastguard Worker return false;
4894*9880d681SAndroid Build Coastguard Worker IdxNIsKill = true;
4895*9880d681SAndroid Build Coastguard Worker }
4896*9880d681SAndroid Build Coastguard Worker N = fastEmit_rr(VT, VT, ISD::ADD, N, NIsKill, IdxN, IdxNIsKill);
4897*9880d681SAndroid Build Coastguard Worker if (!N)
4898*9880d681SAndroid Build Coastguard Worker return false;
4899*9880d681SAndroid Build Coastguard Worker }
4900*9880d681SAndroid Build Coastguard Worker }
4901*9880d681SAndroid Build Coastguard Worker if (TotalOffs) {
4902*9880d681SAndroid Build Coastguard Worker N = emitAdd_ri_(VT, N, NIsKill, TotalOffs);
4903*9880d681SAndroid Build Coastguard Worker if (!N)
4904*9880d681SAndroid Build Coastguard Worker return false;
4905*9880d681SAndroid Build Coastguard Worker }
4906*9880d681SAndroid Build Coastguard Worker updateValueMap(I, N);
4907*9880d681SAndroid Build Coastguard Worker return true;
4908*9880d681SAndroid Build Coastguard Worker }
4909*9880d681SAndroid Build Coastguard Worker
fastSelectInstruction(const Instruction * I)4910*9880d681SAndroid Build Coastguard Worker bool AArch64FastISel::fastSelectInstruction(const Instruction *I) {
4911*9880d681SAndroid Build Coastguard Worker switch (I->getOpcode()) {
4912*9880d681SAndroid Build Coastguard Worker default:
4913*9880d681SAndroid Build Coastguard Worker break;
4914*9880d681SAndroid Build Coastguard Worker case Instruction::Add:
4915*9880d681SAndroid Build Coastguard Worker case Instruction::Sub:
4916*9880d681SAndroid Build Coastguard Worker return selectAddSub(I);
4917*9880d681SAndroid Build Coastguard Worker case Instruction::Mul:
4918*9880d681SAndroid Build Coastguard Worker return selectMul(I);
4919*9880d681SAndroid Build Coastguard Worker case Instruction::SDiv:
4920*9880d681SAndroid Build Coastguard Worker return selectSDiv(I);
4921*9880d681SAndroid Build Coastguard Worker case Instruction::SRem:
4922*9880d681SAndroid Build Coastguard Worker if (!selectBinaryOp(I, ISD::SREM))
4923*9880d681SAndroid Build Coastguard Worker return selectRem(I, ISD::SREM);
4924*9880d681SAndroid Build Coastguard Worker return true;
4925*9880d681SAndroid Build Coastguard Worker case Instruction::URem:
4926*9880d681SAndroid Build Coastguard Worker if (!selectBinaryOp(I, ISD::UREM))
4927*9880d681SAndroid Build Coastguard Worker return selectRem(I, ISD::UREM);
4928*9880d681SAndroid Build Coastguard Worker return true;
4929*9880d681SAndroid Build Coastguard Worker case Instruction::Shl:
4930*9880d681SAndroid Build Coastguard Worker case Instruction::LShr:
4931*9880d681SAndroid Build Coastguard Worker case Instruction::AShr:
4932*9880d681SAndroid Build Coastguard Worker return selectShift(I);
4933*9880d681SAndroid Build Coastguard Worker case Instruction::And:
4934*9880d681SAndroid Build Coastguard Worker case Instruction::Or:
4935*9880d681SAndroid Build Coastguard Worker case Instruction::Xor:
4936*9880d681SAndroid Build Coastguard Worker return selectLogicalOp(I);
4937*9880d681SAndroid Build Coastguard Worker case Instruction::Br:
4938*9880d681SAndroid Build Coastguard Worker return selectBranch(I);
4939*9880d681SAndroid Build Coastguard Worker case Instruction::IndirectBr:
4940*9880d681SAndroid Build Coastguard Worker return selectIndirectBr(I);
4941*9880d681SAndroid Build Coastguard Worker case Instruction::BitCast:
4942*9880d681SAndroid Build Coastguard Worker if (!FastISel::selectBitCast(I))
4943*9880d681SAndroid Build Coastguard Worker return selectBitCast(I);
4944*9880d681SAndroid Build Coastguard Worker return true;
4945*9880d681SAndroid Build Coastguard Worker case Instruction::FPToSI:
4946*9880d681SAndroid Build Coastguard Worker if (!selectCast(I, ISD::FP_TO_SINT))
4947*9880d681SAndroid Build Coastguard Worker return selectFPToInt(I, /*Signed=*/true);
4948*9880d681SAndroid Build Coastguard Worker return true;
4949*9880d681SAndroid Build Coastguard Worker case Instruction::FPToUI:
4950*9880d681SAndroid Build Coastguard Worker return selectFPToInt(I, /*Signed=*/false);
4951*9880d681SAndroid Build Coastguard Worker case Instruction::ZExt:
4952*9880d681SAndroid Build Coastguard Worker case Instruction::SExt:
4953*9880d681SAndroid Build Coastguard Worker return selectIntExt(I);
4954*9880d681SAndroid Build Coastguard Worker case Instruction::Trunc:
4955*9880d681SAndroid Build Coastguard Worker if (!selectCast(I, ISD::TRUNCATE))
4956*9880d681SAndroid Build Coastguard Worker return selectTrunc(I);
4957*9880d681SAndroid Build Coastguard Worker return true;
4958*9880d681SAndroid Build Coastguard Worker case Instruction::FPExt:
4959*9880d681SAndroid Build Coastguard Worker return selectFPExt(I);
4960*9880d681SAndroid Build Coastguard Worker case Instruction::FPTrunc:
4961*9880d681SAndroid Build Coastguard Worker return selectFPTrunc(I);
4962*9880d681SAndroid Build Coastguard Worker case Instruction::SIToFP:
4963*9880d681SAndroid Build Coastguard Worker if (!selectCast(I, ISD::SINT_TO_FP))
4964*9880d681SAndroid Build Coastguard Worker return selectIntToFP(I, /*Signed=*/true);
4965*9880d681SAndroid Build Coastguard Worker return true;
4966*9880d681SAndroid Build Coastguard Worker case Instruction::UIToFP:
4967*9880d681SAndroid Build Coastguard Worker return selectIntToFP(I, /*Signed=*/false);
4968*9880d681SAndroid Build Coastguard Worker case Instruction::Load:
4969*9880d681SAndroid Build Coastguard Worker return selectLoad(I);
4970*9880d681SAndroid Build Coastguard Worker case Instruction::Store:
4971*9880d681SAndroid Build Coastguard Worker return selectStore(I);
4972*9880d681SAndroid Build Coastguard Worker case Instruction::FCmp:
4973*9880d681SAndroid Build Coastguard Worker case Instruction::ICmp:
4974*9880d681SAndroid Build Coastguard Worker return selectCmp(I);
4975*9880d681SAndroid Build Coastguard Worker case Instruction::Select:
4976*9880d681SAndroid Build Coastguard Worker return selectSelect(I);
4977*9880d681SAndroid Build Coastguard Worker case Instruction::Ret:
4978*9880d681SAndroid Build Coastguard Worker return selectRet(I);
4979*9880d681SAndroid Build Coastguard Worker case Instruction::FRem:
4980*9880d681SAndroid Build Coastguard Worker return selectFRem(I);
4981*9880d681SAndroid Build Coastguard Worker case Instruction::GetElementPtr:
4982*9880d681SAndroid Build Coastguard Worker return selectGetElementPtr(I);
4983*9880d681SAndroid Build Coastguard Worker }
4984*9880d681SAndroid Build Coastguard Worker
4985*9880d681SAndroid Build Coastguard Worker // fall-back to target-independent instruction selection.
4986*9880d681SAndroid Build Coastguard Worker return selectOperator(I, I->getOpcode());
4987*9880d681SAndroid Build Coastguard Worker // Silence warnings.
4988*9880d681SAndroid Build Coastguard Worker (void)&CC_AArch64_DarwinPCS_VarArg;
4989*9880d681SAndroid Build Coastguard Worker }
4990*9880d681SAndroid Build Coastguard Worker
4991*9880d681SAndroid Build Coastguard Worker namespace llvm {
createFastISel(FunctionLoweringInfo & FuncInfo,const TargetLibraryInfo * LibInfo)4992*9880d681SAndroid Build Coastguard Worker llvm::FastISel *AArch64::createFastISel(FunctionLoweringInfo &FuncInfo,
4993*9880d681SAndroid Build Coastguard Worker const TargetLibraryInfo *LibInfo) {
4994*9880d681SAndroid Build Coastguard Worker return new AArch64FastISel(FuncInfo, LibInfo);
4995*9880d681SAndroid Build Coastguard Worker }
4996*9880d681SAndroid Build Coastguard Worker }
4997