xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64FastISel.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- AArch6464FastISel.cpp - AArch64 FastISel implementation ------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the AArch64-specific support for the FastISel class. Some
100b57cec5SDimitry Andric // of the target-specific code is generated by tablegen in the file
110b57cec5SDimitry Andric // AArch64GenFastISel.inc, which is #included here.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "AArch64.h"
160b57cec5SDimitry Andric #include "AArch64CallingConvention.h"
173a9a9c0cSDimitry Andric #include "AArch64MachineFunctionInfo.h"
180b57cec5SDimitry Andric #include "AArch64RegisterInfo.h"
190b57cec5SDimitry Andric #include "AArch64Subtarget.h"
200b57cec5SDimitry Andric #include "MCTargetDesc/AArch64AddressingModes.h"
210b57cec5SDimitry Andric #include "Utils/AArch64BaseInfo.h"
220b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h"
230b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
240b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
250b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
260b57cec5SDimitry Andric #include "llvm/Analysis/BranchProbabilityInfo.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/FastISel.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/FunctionLoweringInfo.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
330b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
340b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
350b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
360b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
370b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
38*0fca6ea1SDimitry Andric #include "llvm/CodeGen/RuntimeLibcallUtil.h"
390b57cec5SDimitry Andric #include "llvm/CodeGen/ValueTypes.h"
40*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h"
410b57cec5SDimitry Andric #include "llvm/IR/Argument.h"
420b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
430b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
440b57cec5SDimitry Andric #include "llvm/IR/CallingConv.h"
450b57cec5SDimitry Andric #include "llvm/IR/Constant.h"
460b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
470b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
480b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
490b57cec5SDimitry Andric #include "llvm/IR/Function.h"
500b57cec5SDimitry Andric #include "llvm/IR/GetElementPtrTypeIterator.h"
510b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
520b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h"
530b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
540b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
550b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
560b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h"
5706c3fb27SDimitry Andric #include "llvm/IR/IntrinsicsAArch64.h"
58*0fca6ea1SDimitry Andric #include "llvm/IR/Module.h"
590b57cec5SDimitry Andric #include "llvm/IR/Operator.h"
600b57cec5SDimitry Andric #include "llvm/IR/Type.h"
610b57cec5SDimitry Andric #include "llvm/IR/User.h"
620b57cec5SDimitry Andric #include "llvm/IR/Value.h"
630b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
640b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
650b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
660b57cec5SDimitry Andric #include "llvm/Support/AtomicOrdering.h"
670b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
680b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h"
690b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
700b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
710b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
720b57cec5SDimitry Andric #include <algorithm>
730b57cec5SDimitry Andric #include <cassert>
740b57cec5SDimitry Andric #include <cstdint>
750b57cec5SDimitry Andric #include <iterator>
760b57cec5SDimitry Andric #include <utility>
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric using namespace llvm;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric namespace {
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric class AArch64FastISel final : public FastISel {
830b57cec5SDimitry Andric   class Address {
840b57cec5SDimitry Andric   public:
850b57cec5SDimitry Andric     using BaseKind = enum {
860b57cec5SDimitry Andric       RegBase,
870b57cec5SDimitry Andric       FrameIndexBase
880b57cec5SDimitry Andric     };
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   private:
910b57cec5SDimitry Andric     BaseKind Kind = RegBase;
920b57cec5SDimitry Andric     AArch64_AM::ShiftExtendType ExtType = AArch64_AM::InvalidShiftExtend;
930b57cec5SDimitry Andric     union {
940b57cec5SDimitry Andric       unsigned Reg;
950b57cec5SDimitry Andric       int FI;
960b57cec5SDimitry Andric     } Base;
970b57cec5SDimitry Andric     unsigned OffsetReg = 0;
980b57cec5SDimitry Andric     unsigned Shift = 0;
990b57cec5SDimitry Andric     int64_t Offset = 0;
1000b57cec5SDimitry Andric     const GlobalValue *GV = nullptr;
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   public:
1030b57cec5SDimitry Andric     Address() { Base.Reg = 0; }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric     void setKind(BaseKind K) { Kind = K; }
1060b57cec5SDimitry Andric     BaseKind getKind() const { return Kind; }
1070b57cec5SDimitry Andric     void setExtendType(AArch64_AM::ShiftExtendType E) { ExtType = E; }
1080b57cec5SDimitry Andric     AArch64_AM::ShiftExtendType getExtendType() const { return ExtType; }
1090b57cec5SDimitry Andric     bool isRegBase() const { return Kind == RegBase; }
1100b57cec5SDimitry Andric     bool isFIBase() const { return Kind == FrameIndexBase; }
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric     void setReg(unsigned Reg) {
1130b57cec5SDimitry Andric       assert(isRegBase() && "Invalid base register access!");
1140b57cec5SDimitry Andric       Base.Reg = Reg;
1150b57cec5SDimitry Andric     }
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric     unsigned getReg() const {
1180b57cec5SDimitry Andric       assert(isRegBase() && "Invalid base register access!");
1190b57cec5SDimitry Andric       return Base.Reg;
1200b57cec5SDimitry Andric     }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric     void setOffsetReg(unsigned Reg) {
1230b57cec5SDimitry Andric       OffsetReg = Reg;
1240b57cec5SDimitry Andric     }
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric     unsigned getOffsetReg() const {
1270b57cec5SDimitry Andric       return OffsetReg;
1280b57cec5SDimitry Andric     }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric     void setFI(unsigned FI) {
1310b57cec5SDimitry Andric       assert(isFIBase() && "Invalid base frame index  access!");
1320b57cec5SDimitry Andric       Base.FI = FI;
1330b57cec5SDimitry Andric     }
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric     unsigned getFI() const {
1360b57cec5SDimitry Andric       assert(isFIBase() && "Invalid base frame index access!");
1370b57cec5SDimitry Andric       return Base.FI;
1380b57cec5SDimitry Andric     }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric     void setOffset(int64_t O) { Offset = O; }
1410b57cec5SDimitry Andric     int64_t getOffset() { return Offset; }
1420b57cec5SDimitry Andric     void setShift(unsigned S) { Shift = S; }
1430b57cec5SDimitry Andric     unsigned getShift() { return Shift; }
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric     void setGlobalValue(const GlobalValue *G) { GV = G; }
1460b57cec5SDimitry Andric     const GlobalValue *getGlobalValue() { return GV; }
1470b57cec5SDimitry Andric   };
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   /// Subtarget - Keep a pointer to the AArch64Subtarget around so that we can
1500b57cec5SDimitry Andric   /// make the right decision when generating code for different targets.
1510b57cec5SDimitry Andric   const AArch64Subtarget *Subtarget;
1520b57cec5SDimitry Andric   LLVMContext *Context;
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   bool fastLowerArguments() override;
1550b57cec5SDimitry Andric   bool fastLowerCall(CallLoweringInfo &CLI) override;
1560b57cec5SDimitry Andric   bool fastLowerIntrinsicCall(const IntrinsicInst *II) override;
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric private:
1590b57cec5SDimitry Andric   // Selection routines.
1600b57cec5SDimitry Andric   bool selectAddSub(const Instruction *I);
1610b57cec5SDimitry Andric   bool selectLogicalOp(const Instruction *I);
1620b57cec5SDimitry Andric   bool selectLoad(const Instruction *I);
1630b57cec5SDimitry Andric   bool selectStore(const Instruction *I);
1640b57cec5SDimitry Andric   bool selectBranch(const Instruction *I);
1650b57cec5SDimitry Andric   bool selectIndirectBr(const Instruction *I);
1660b57cec5SDimitry Andric   bool selectCmp(const Instruction *I);
1670b57cec5SDimitry Andric   bool selectSelect(const Instruction *I);
1680b57cec5SDimitry Andric   bool selectFPExt(const Instruction *I);
1690b57cec5SDimitry Andric   bool selectFPTrunc(const Instruction *I);
1700b57cec5SDimitry Andric   bool selectFPToInt(const Instruction *I, bool Signed);
1710b57cec5SDimitry Andric   bool selectIntToFP(const Instruction *I, bool Signed);
1720b57cec5SDimitry Andric   bool selectRem(const Instruction *I, unsigned ISDOpcode);
1730b57cec5SDimitry Andric   bool selectRet(const Instruction *I);
1740b57cec5SDimitry Andric   bool selectTrunc(const Instruction *I);
1750b57cec5SDimitry Andric   bool selectIntExt(const Instruction *I);
1760b57cec5SDimitry Andric   bool selectMul(const Instruction *I);
1770b57cec5SDimitry Andric   bool selectShift(const Instruction *I);
1780b57cec5SDimitry Andric   bool selectBitCast(const Instruction *I);
1790b57cec5SDimitry Andric   bool selectFRem(const Instruction *I);
1800b57cec5SDimitry Andric   bool selectSDiv(const Instruction *I);
1810b57cec5SDimitry Andric   bool selectGetElementPtr(const Instruction *I);
1820b57cec5SDimitry Andric   bool selectAtomicCmpXchg(const AtomicCmpXchgInst *I);
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   // Utility helper routines.
1850b57cec5SDimitry Andric   bool isTypeLegal(Type *Ty, MVT &VT);
1860b57cec5SDimitry Andric   bool isTypeSupported(Type *Ty, MVT &VT, bool IsVectorAllowed = false);
1870b57cec5SDimitry Andric   bool isValueAvailable(const Value *V) const;
1880b57cec5SDimitry Andric   bool computeAddress(const Value *Obj, Address &Addr, Type *Ty = nullptr);
1890b57cec5SDimitry Andric   bool computeCallAddress(const Value *V, Address &Addr);
1900b57cec5SDimitry Andric   bool simplifyAddress(Address &Addr, MVT VT);
1910b57cec5SDimitry Andric   void addLoadStoreOperands(Address &Addr, const MachineInstrBuilder &MIB,
1920b57cec5SDimitry Andric                             MachineMemOperand::Flags Flags,
1930b57cec5SDimitry Andric                             unsigned ScaleFactor, MachineMemOperand *MMO);
194bdd1243dSDimitry Andric   bool isMemCpySmall(uint64_t Len, MaybeAlign Alignment);
1950b57cec5SDimitry Andric   bool tryEmitSmallMemCpy(Address Dest, Address Src, uint64_t Len,
196bdd1243dSDimitry Andric                           MaybeAlign Alignment);
1970b57cec5SDimitry Andric   bool foldXALUIntrinsic(AArch64CC::CondCode &CC, const Instruction *I,
1980b57cec5SDimitry Andric                          const Value *Cond);
1990b57cec5SDimitry Andric   bool optimizeIntExtLoad(const Instruction *I, MVT RetVT, MVT SrcVT);
2000b57cec5SDimitry Andric   bool optimizeSelect(const SelectInst *SI);
201fe6060f1SDimitry Andric   unsigned getRegForGEPIndex(const Value *Idx);
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   // Emit helper routines.
2040b57cec5SDimitry Andric   unsigned emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS,
2050b57cec5SDimitry Andric                       const Value *RHS, bool SetFlags = false,
2060b57cec5SDimitry Andric                       bool WantResult = true,  bool IsZExt = false);
2070b57cec5SDimitry Andric   unsigned emitAddSub_rr(bool UseAdd, MVT RetVT, unsigned LHSReg,
208fe6060f1SDimitry Andric                          unsigned RHSReg, bool SetFlags = false,
209fe6060f1SDimitry Andric                          bool WantResult = true);
2100b57cec5SDimitry Andric   unsigned emitAddSub_ri(bool UseAdd, MVT RetVT, unsigned LHSReg,
211fe6060f1SDimitry Andric                          uint64_t Imm, bool SetFlags = false,
2120b57cec5SDimitry Andric                          bool WantResult = true);
2130b57cec5SDimitry Andric   unsigned emitAddSub_rs(bool UseAdd, MVT RetVT, unsigned LHSReg,
214fe6060f1SDimitry Andric                          unsigned RHSReg, AArch64_AM::ShiftExtendType ShiftType,
2150b57cec5SDimitry Andric                          uint64_t ShiftImm, bool SetFlags = false,
2160b57cec5SDimitry Andric                          bool WantResult = true);
2170b57cec5SDimitry Andric   unsigned emitAddSub_rx(bool UseAdd, MVT RetVT, unsigned LHSReg,
218fe6060f1SDimitry Andric                          unsigned RHSReg, AArch64_AM::ShiftExtendType ExtType,
2190b57cec5SDimitry Andric                          uint64_t ShiftImm, bool SetFlags = false,
2200b57cec5SDimitry Andric                          bool WantResult = true);
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   // Emit functions.
2230b57cec5SDimitry Andric   bool emitCompareAndBranch(const BranchInst *BI);
2240b57cec5SDimitry Andric   bool emitCmp(const Value *LHS, const Value *RHS, bool IsZExt);
2250b57cec5SDimitry Andric   bool emitICmp(MVT RetVT, const Value *LHS, const Value *RHS, bool IsZExt);
226fe6060f1SDimitry Andric   bool emitICmp_ri(MVT RetVT, unsigned LHSReg, uint64_t Imm);
2270b57cec5SDimitry Andric   bool emitFCmp(MVT RetVT, const Value *LHS, const Value *RHS);
2280b57cec5SDimitry Andric   unsigned emitLoad(MVT VT, MVT ResultVT, Address Addr, bool WantZExt = true,
2290b57cec5SDimitry Andric                     MachineMemOperand *MMO = nullptr);
2300b57cec5SDimitry Andric   bool emitStore(MVT VT, unsigned SrcReg, Address Addr,
2310b57cec5SDimitry Andric                  MachineMemOperand *MMO = nullptr);
2320b57cec5SDimitry Andric   bool emitStoreRelease(MVT VT, unsigned SrcReg, unsigned AddrReg,
2330b57cec5SDimitry Andric                         MachineMemOperand *MMO = nullptr);
2340b57cec5SDimitry Andric   unsigned emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt);
2350b57cec5SDimitry Andric   unsigned emiti1Ext(unsigned SrcReg, MVT DestVT, bool isZExt);
2360b57cec5SDimitry Andric   unsigned emitAdd(MVT RetVT, const Value *LHS, const Value *RHS,
2370b57cec5SDimitry Andric                    bool SetFlags = false, bool WantResult = true,
2380b57cec5SDimitry Andric                    bool IsZExt = false);
239fe6060f1SDimitry Andric   unsigned emitAdd_ri_(MVT VT, unsigned Op0, int64_t Imm);
2400b57cec5SDimitry Andric   unsigned emitSub(MVT RetVT, const Value *LHS, const Value *RHS,
2410b57cec5SDimitry Andric                    bool SetFlags = false, bool WantResult = true,
2420b57cec5SDimitry Andric                    bool IsZExt = false);
243fe6060f1SDimitry Andric   unsigned emitSubs_rr(MVT RetVT, unsigned LHSReg, unsigned RHSReg,
244fe6060f1SDimitry Andric                        bool WantResult = true);
245fe6060f1SDimitry Andric   unsigned emitSubs_rs(MVT RetVT, unsigned LHSReg, unsigned RHSReg,
2460b57cec5SDimitry Andric                        AArch64_AM::ShiftExtendType ShiftType, uint64_t ShiftImm,
2470b57cec5SDimitry Andric                        bool WantResult = true);
2480b57cec5SDimitry Andric   unsigned emitLogicalOp(unsigned ISDOpc, MVT RetVT, const Value *LHS,
2490b57cec5SDimitry Andric                          const Value *RHS);
2500b57cec5SDimitry Andric   unsigned emitLogicalOp_ri(unsigned ISDOpc, MVT RetVT, unsigned LHSReg,
251fe6060f1SDimitry Andric                             uint64_t Imm);
2520b57cec5SDimitry Andric   unsigned emitLogicalOp_rs(unsigned ISDOpc, MVT RetVT, unsigned LHSReg,
253fe6060f1SDimitry Andric                             unsigned RHSReg, uint64_t ShiftImm);
254fe6060f1SDimitry Andric   unsigned emitAnd_ri(MVT RetVT, unsigned LHSReg, uint64_t Imm);
255fe6060f1SDimitry Andric   unsigned emitMul_rr(MVT RetVT, unsigned Op0, unsigned Op1);
256fe6060f1SDimitry Andric   unsigned emitSMULL_rr(MVT RetVT, unsigned Op0, unsigned Op1);
257fe6060f1SDimitry Andric   unsigned emitUMULL_rr(MVT RetVT, unsigned Op0, unsigned Op1);
258fe6060f1SDimitry Andric   unsigned emitLSL_rr(MVT RetVT, unsigned Op0Reg, unsigned Op1Reg);
259fe6060f1SDimitry Andric   unsigned emitLSL_ri(MVT RetVT, MVT SrcVT, unsigned Op0Reg, uint64_t Imm,
260fe6060f1SDimitry Andric                       bool IsZExt = true);
261fe6060f1SDimitry Andric   unsigned emitLSR_rr(MVT RetVT, unsigned Op0Reg, unsigned Op1Reg);
262fe6060f1SDimitry Andric   unsigned emitLSR_ri(MVT RetVT, MVT SrcVT, unsigned Op0Reg, uint64_t Imm,
263fe6060f1SDimitry Andric                       bool IsZExt = true);
264fe6060f1SDimitry Andric   unsigned emitASR_rr(MVT RetVT, unsigned Op0Reg, unsigned Op1Reg);
265fe6060f1SDimitry Andric   unsigned emitASR_ri(MVT RetVT, MVT SrcVT, unsigned Op0Reg, uint64_t Imm,
266fe6060f1SDimitry Andric                       bool IsZExt = false);
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   unsigned materializeInt(const ConstantInt *CI, MVT VT);
2690b57cec5SDimitry Andric   unsigned materializeFP(const ConstantFP *CFP, MVT VT);
2700b57cec5SDimitry Andric   unsigned materializeGV(const GlobalValue *GV);
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   // Call handling routines.
2730b57cec5SDimitry Andric private:
2740b57cec5SDimitry Andric   CCAssignFn *CCAssignFnForCall(CallingConv::ID CC) const;
2750b57cec5SDimitry Andric   bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs,
2760b57cec5SDimitry Andric                        unsigned &NumBytes);
27706c3fb27SDimitry Andric   bool finishCall(CallLoweringInfo &CLI, unsigned NumBytes);
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric public:
2800b57cec5SDimitry Andric   // Backend specific FastISel code.
2810b57cec5SDimitry Andric   unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
2820b57cec5SDimitry Andric   unsigned fastMaterializeConstant(const Constant *C) override;
2830b57cec5SDimitry Andric   unsigned fastMaterializeFloatZero(const ConstantFP* CF) override;
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric   explicit AArch64FastISel(FunctionLoweringInfo &FuncInfo,
2860b57cec5SDimitry Andric                            const TargetLibraryInfo *LibInfo)
2870b57cec5SDimitry Andric       : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
28881ad6265SDimitry Andric     Subtarget = &FuncInfo.MF->getSubtarget<AArch64Subtarget>();
2890b57cec5SDimitry Andric     Context = &FuncInfo.Fn->getContext();
2900b57cec5SDimitry Andric   }
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   bool fastSelectInstruction(const Instruction *I) override;
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric #include "AArch64GenFastISel.inc"
2950b57cec5SDimitry Andric };
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric } // end anonymous namespace
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric /// Check if the sign-/zero-extend will be a noop.
3000b57cec5SDimitry Andric static bool isIntExtFree(const Instruction *I) {
3010b57cec5SDimitry Andric   assert((isa<ZExtInst>(I) || isa<SExtInst>(I)) &&
3020b57cec5SDimitry Andric          "Unexpected integer extend instruction.");
3030b57cec5SDimitry Andric   assert(!I->getType()->isVectorTy() && I->getType()->isIntegerTy() &&
3040b57cec5SDimitry Andric          "Unexpected value type.");
3050b57cec5SDimitry Andric   bool IsZExt = isa<ZExtInst>(I);
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   if (const auto *LI = dyn_cast<LoadInst>(I->getOperand(0)))
3080b57cec5SDimitry Andric     if (LI->hasOneUse())
3090b57cec5SDimitry Andric       return true;
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   if (const auto *Arg = dyn_cast<Argument>(I->getOperand(0)))
3120b57cec5SDimitry Andric     if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr()))
3130b57cec5SDimitry Andric       return true;
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   return false;
3160b57cec5SDimitry Andric }
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric /// Determine the implicit scale factor that is applied by a memory
3190b57cec5SDimitry Andric /// operation for a given value type.
3200b57cec5SDimitry Andric static unsigned getImplicitScaleFactor(MVT VT) {
3210b57cec5SDimitry Andric   switch (VT.SimpleTy) {
3220b57cec5SDimitry Andric   default:
3230b57cec5SDimitry Andric     return 0;    // invalid
3240b57cec5SDimitry Andric   case MVT::i1:  // fall-through
3250b57cec5SDimitry Andric   case MVT::i8:
3260b57cec5SDimitry Andric     return 1;
3270b57cec5SDimitry Andric   case MVT::i16:
3280b57cec5SDimitry Andric     return 2;
3290b57cec5SDimitry Andric   case MVT::i32: // fall-through
3300b57cec5SDimitry Andric   case MVT::f32:
3310b57cec5SDimitry Andric     return 4;
3320b57cec5SDimitry Andric   case MVT::i64: // fall-through
3330b57cec5SDimitry Andric   case MVT::f64:
3340b57cec5SDimitry Andric     return 8;
3350b57cec5SDimitry Andric   }
3360b57cec5SDimitry Andric }
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric CCAssignFn *AArch64FastISel::CCAssignFnForCall(CallingConv::ID CC) const {
3390b57cec5SDimitry Andric   if (CC == CallingConv::GHC)
3400b57cec5SDimitry Andric     return CC_AArch64_GHC;
341480093f4SDimitry Andric   if (CC == CallingConv::CFGuard_Check)
342480093f4SDimitry Andric     return CC_AArch64_Win64_CFGuard_Check;
3435f757f3fSDimitry Andric   if (Subtarget->isTargetDarwin())
3445f757f3fSDimitry Andric     return CC_AArch64_DarwinPCS;
3455f757f3fSDimitry Andric   if (Subtarget->isTargetWindows())
3465f757f3fSDimitry Andric     return CC_AArch64_Win64PCS;
3475f757f3fSDimitry Andric   return CC_AArch64_AAPCS;
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric unsigned AArch64FastISel::fastMaterializeAlloca(const AllocaInst *AI) {
3510b57cec5SDimitry Andric   assert(TLI.getValueType(DL, AI->getType(), true) == MVT::i64 &&
3520b57cec5SDimitry Andric          "Alloca should always return a pointer.");
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric   // Don't handle dynamic allocas.
3550b57cec5SDimitry Andric   if (!FuncInfo.StaticAllocaMap.count(AI))
3560b57cec5SDimitry Andric     return 0;
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   DenseMap<const AllocaInst *, int>::iterator SI =
3590b57cec5SDimitry Andric       FuncInfo.StaticAllocaMap.find(AI);
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   if (SI != FuncInfo.StaticAllocaMap.end()) {
36204eeddc0SDimitry Andric     Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
363bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADDXri),
3640b57cec5SDimitry Andric             ResultReg)
3650b57cec5SDimitry Andric         .addFrameIndex(SI->second)
3660b57cec5SDimitry Andric         .addImm(0)
3670b57cec5SDimitry Andric         .addImm(0);
3680b57cec5SDimitry Andric     return ResultReg;
3690b57cec5SDimitry Andric   }
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric   return 0;
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric unsigned AArch64FastISel::materializeInt(const ConstantInt *CI, MVT VT) {
3750b57cec5SDimitry Andric   if (VT > MVT::i64)
3760b57cec5SDimitry Andric     return 0;
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric   if (!CI->isZero())
3790b57cec5SDimitry Andric     return fastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue());
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   // Create a copy from the zero register to materialize a "0" value.
3820b57cec5SDimitry Andric   const TargetRegisterClass *RC = (VT == MVT::i64) ? &AArch64::GPR64RegClass
3830b57cec5SDimitry Andric                                                    : &AArch64::GPR32RegClass;
3840b57cec5SDimitry Andric   unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
38504eeddc0SDimitry Andric   Register ResultReg = createResultReg(RC);
386bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(TargetOpcode::COPY),
3870b57cec5SDimitry Andric           ResultReg).addReg(ZeroReg, getKillRegState(true));
3880b57cec5SDimitry Andric   return ResultReg;
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric unsigned AArch64FastISel::materializeFP(const ConstantFP *CFP, MVT VT) {
3920b57cec5SDimitry Andric   // Positive zero (+0.0) has to be materialized with a fmov from the zero
3930b57cec5SDimitry Andric   // register, because the immediate version of fmov cannot encode zero.
3940b57cec5SDimitry Andric   if (CFP->isNullValue())
3950b57cec5SDimitry Andric     return fastMaterializeFloatZero(CFP);
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric   if (VT != MVT::f32 && VT != MVT::f64)
3980b57cec5SDimitry Andric     return 0;
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   const APFloat Val = CFP->getValueAPF();
4010b57cec5SDimitry Andric   bool Is64Bit = (VT == MVT::f64);
4020b57cec5SDimitry Andric   // This checks to see if we can use FMOV instructions to materialize
4030b57cec5SDimitry Andric   // a constant, otherwise we have to materialize via the constant pool.
4040b57cec5SDimitry Andric   int Imm =
4050b57cec5SDimitry Andric       Is64Bit ? AArch64_AM::getFP64Imm(Val) : AArch64_AM::getFP32Imm(Val);
4060b57cec5SDimitry Andric   if (Imm != -1) {
4070b57cec5SDimitry Andric     unsigned Opc = Is64Bit ? AArch64::FMOVDi : AArch64::FMOVSi;
4080b57cec5SDimitry Andric     return fastEmitInst_i(Opc, TLI.getRegClassFor(VT), Imm);
4090b57cec5SDimitry Andric   }
4100b57cec5SDimitry Andric 
411fe6060f1SDimitry Andric   // For the large code model materialize the FP constant in code.
412fe6060f1SDimitry Andric   if (TM.getCodeModel() == CodeModel::Large) {
4130b57cec5SDimitry Andric     unsigned Opc1 = Is64Bit ? AArch64::MOVi64imm : AArch64::MOVi32imm;
4140b57cec5SDimitry Andric     const TargetRegisterClass *RC = Is64Bit ?
4150b57cec5SDimitry Andric         &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4160b57cec5SDimitry Andric 
41704eeddc0SDimitry Andric     Register TmpReg = createResultReg(RC);
418bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc1), TmpReg)
4190b57cec5SDimitry Andric         .addImm(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
4200b57cec5SDimitry Andric 
42104eeddc0SDimitry Andric     Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
422bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4230b57cec5SDimitry Andric             TII.get(TargetOpcode::COPY), ResultReg)
4240b57cec5SDimitry Andric         .addReg(TmpReg, getKillRegState(true));
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric     return ResultReg;
4270b57cec5SDimitry Andric   }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   // Materialize via constant pool.  MachineConstantPool wants an explicit
4300b57cec5SDimitry Andric   // alignment.
4315ffd83dbSDimitry Andric   Align Alignment = DL.getPrefTypeAlign(CFP->getType());
4320b57cec5SDimitry Andric 
4335ffd83dbSDimitry Andric   unsigned CPI = MCP.getConstantPoolIndex(cast<Constant>(CFP), Alignment);
43404eeddc0SDimitry Andric   Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
435bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADRP),
4360b57cec5SDimitry Andric           ADRPReg).addConstantPoolIndex(CPI, 0, AArch64II::MO_PAGE);
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric   unsigned Opc = Is64Bit ? AArch64::LDRDui : AArch64::LDRSui;
43904eeddc0SDimitry Andric   Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
440bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
4410b57cec5SDimitry Andric       .addReg(ADRPReg)
4420b57cec5SDimitry Andric       .addConstantPoolIndex(CPI, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
4430b57cec5SDimitry Andric   return ResultReg;
4440b57cec5SDimitry Andric }
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric unsigned AArch64FastISel::materializeGV(const GlobalValue *GV) {
4470b57cec5SDimitry Andric   // We can't handle thread-local variables quickly yet.
4480b57cec5SDimitry Andric   if (GV->isThreadLocal())
4490b57cec5SDimitry Andric     return 0;
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric   // MachO still uses GOT for large code-model accesses, but ELF requires
4520b57cec5SDimitry Andric   // movz/movk sequences, which FastISel doesn't handle yet.
4530b57cec5SDimitry Andric   if (!Subtarget->useSmallAddressing() && !Subtarget->isTargetMachO())
4540b57cec5SDimitry Andric     return 0;
4550b57cec5SDimitry Andric 
4568bcb0991SDimitry Andric   unsigned OpFlags = Subtarget->ClassifyGlobalReference(GV, TM);
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   EVT DestEVT = TLI.getValueType(DL, GV->getType(), true);
4590b57cec5SDimitry Andric   if (!DestEVT.isSimple())
4600b57cec5SDimitry Andric     return 0;
4610b57cec5SDimitry Andric 
46204eeddc0SDimitry Andric   Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
4630b57cec5SDimitry Andric   unsigned ResultReg;
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric   if (OpFlags & AArch64II::MO_GOT) {
4660b57cec5SDimitry Andric     // ADRP + LDRX
467bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADRP),
4680b57cec5SDimitry Andric             ADRPReg)
4690b57cec5SDimitry Andric         .addGlobalAddress(GV, 0, AArch64II::MO_PAGE | OpFlags);
4700b57cec5SDimitry Andric 
4718bcb0991SDimitry Andric     unsigned LdrOpc;
4728bcb0991SDimitry Andric     if (Subtarget->isTargetILP32()) {
4738bcb0991SDimitry Andric       ResultReg = createResultReg(&AArch64::GPR32RegClass);
4748bcb0991SDimitry Andric       LdrOpc = AArch64::LDRWui;
4758bcb0991SDimitry Andric     } else {
4760b57cec5SDimitry Andric       ResultReg = createResultReg(&AArch64::GPR64RegClass);
4778bcb0991SDimitry Andric       LdrOpc = AArch64::LDRXui;
4788bcb0991SDimitry Andric     }
479bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(LdrOpc),
4800b57cec5SDimitry Andric             ResultReg)
4810b57cec5SDimitry Andric       .addReg(ADRPReg)
4828bcb0991SDimitry Andric       .addGlobalAddress(GV, 0, AArch64II::MO_GOT | AArch64II::MO_PAGEOFF |
4838bcb0991SDimitry Andric                         AArch64II::MO_NC | OpFlags);
4848bcb0991SDimitry Andric     if (!Subtarget->isTargetILP32())
4858bcb0991SDimitry Andric       return ResultReg;
4868bcb0991SDimitry Andric 
4878bcb0991SDimitry Andric     // LDRWui produces a 32-bit register, but pointers in-register are 64-bits
4888bcb0991SDimitry Andric     // so we must extend the result on ILP32.
48904eeddc0SDimitry Andric     Register Result64 = createResultReg(&AArch64::GPR64RegClass);
490bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4918bcb0991SDimitry Andric             TII.get(TargetOpcode::SUBREG_TO_REG))
4928bcb0991SDimitry Andric         .addDef(Result64)
4938bcb0991SDimitry Andric         .addImm(0)
4948bcb0991SDimitry Andric         .addReg(ResultReg, RegState::Kill)
4958bcb0991SDimitry Andric         .addImm(AArch64::sub_32);
4968bcb0991SDimitry Andric     return Result64;
4970b57cec5SDimitry Andric   } else {
4980b57cec5SDimitry Andric     // ADRP + ADDX
499bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADRP),
5000b57cec5SDimitry Andric             ADRPReg)
5010b57cec5SDimitry Andric         .addGlobalAddress(GV, 0, AArch64II::MO_PAGE | OpFlags);
5020b57cec5SDimitry Andric 
503bdd1243dSDimitry Andric     if (OpFlags & AArch64II::MO_TAGGED) {
504bdd1243dSDimitry Andric       // MO_TAGGED on the page indicates a tagged address. Set the tag now.
505bdd1243dSDimitry Andric       // We do so by creating a MOVK that sets bits 48-63 of the register to
506bdd1243dSDimitry Andric       // (global address + 0x100000000 - PC) >> 48. This assumes that we're in
507bdd1243dSDimitry Andric       // the small code model so we can assume a binary size of <= 4GB, which
508bdd1243dSDimitry Andric       // makes the untagged PC relative offset positive. The binary must also be
509bdd1243dSDimitry Andric       // loaded into address range [0, 2^48). Both of these properties need to
510bdd1243dSDimitry Andric       // be ensured at runtime when using tagged addresses.
511bdd1243dSDimitry Andric       //
512bdd1243dSDimitry Andric       // TODO: There is duplicate logic in AArch64ExpandPseudoInsts.cpp that
513bdd1243dSDimitry Andric       // also uses BuildMI for making an ADRP (+ MOVK) + ADD, but the operands
514bdd1243dSDimitry Andric       // are not exactly 1:1 with FastISel so we cannot easily abstract this
515bdd1243dSDimitry Andric       // out. At some point, it would be nice to find a way to not have this
516bdd1243dSDimitry Andric       // duplciate code.
517bdd1243dSDimitry Andric       unsigned DstReg = createResultReg(&AArch64::GPR64commonRegClass);
518bdd1243dSDimitry Andric       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::MOVKXi),
519bdd1243dSDimitry Andric               DstReg)
520bdd1243dSDimitry Andric           .addReg(ADRPReg)
521bdd1243dSDimitry Andric           .addGlobalAddress(GV, /*Offset=*/0x100000000,
522bdd1243dSDimitry Andric                             AArch64II::MO_PREL | AArch64II::MO_G3)
523bdd1243dSDimitry Andric           .addImm(48);
524bdd1243dSDimitry Andric       ADRPReg = DstReg;
525bdd1243dSDimitry Andric     }
526bdd1243dSDimitry Andric 
5270b57cec5SDimitry Andric     ResultReg = createResultReg(&AArch64::GPR64spRegClass);
528bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADDXri),
5290b57cec5SDimitry Andric             ResultReg)
5300b57cec5SDimitry Andric         .addReg(ADRPReg)
5310b57cec5SDimitry Andric         .addGlobalAddress(GV, 0,
5320b57cec5SDimitry Andric                           AArch64II::MO_PAGEOFF | AArch64II::MO_NC | OpFlags)
5330b57cec5SDimitry Andric         .addImm(0);
5340b57cec5SDimitry Andric   }
5350b57cec5SDimitry Andric   return ResultReg;
5360b57cec5SDimitry Andric }
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric unsigned AArch64FastISel::fastMaterializeConstant(const Constant *C) {
5390b57cec5SDimitry Andric   EVT CEVT = TLI.getValueType(DL, C->getType(), true);
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric   // Only handle simple types.
5420b57cec5SDimitry Andric   if (!CEVT.isSimple())
5430b57cec5SDimitry Andric     return 0;
5440b57cec5SDimitry Andric   MVT VT = CEVT.getSimpleVT();
5458bcb0991SDimitry Andric   // arm64_32 has 32-bit pointers held in 64-bit registers. Because of that,
5468bcb0991SDimitry Andric   // 'null' pointers need to have a somewhat special treatment.
547fe6060f1SDimitry Andric   if (isa<ConstantPointerNull>(C)) {
5488bcb0991SDimitry Andric     assert(VT == MVT::i64 && "Expected 64-bit pointers");
5498bcb0991SDimitry Andric     return materializeInt(ConstantInt::get(Type::getInt64Ty(*Context), 0), VT);
5508bcb0991SDimitry Andric   }
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   if (const auto *CI = dyn_cast<ConstantInt>(C))
5530b57cec5SDimitry Andric     return materializeInt(CI, VT);
5540b57cec5SDimitry Andric   else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
5550b57cec5SDimitry Andric     return materializeFP(CFP, VT);
5560b57cec5SDimitry Andric   else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
5570b57cec5SDimitry Andric     return materializeGV(GV);
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric   return 0;
5600b57cec5SDimitry Andric }
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric unsigned AArch64FastISel::fastMaterializeFloatZero(const ConstantFP* CFP) {
5630b57cec5SDimitry Andric   assert(CFP->isNullValue() &&
5640b57cec5SDimitry Andric          "Floating-point constant is not a positive zero.");
5650b57cec5SDimitry Andric   MVT VT;
5660b57cec5SDimitry Andric   if (!isTypeLegal(CFP->getType(), VT))
5670b57cec5SDimitry Andric     return 0;
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric   if (VT != MVT::f32 && VT != MVT::f64)
5700b57cec5SDimitry Andric     return 0;
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric   bool Is64Bit = (VT == MVT::f64);
5730b57cec5SDimitry Andric   unsigned ZReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
5740b57cec5SDimitry Andric   unsigned Opc = Is64Bit ? AArch64::FMOVXDr : AArch64::FMOVWSr;
575fe6060f1SDimitry Andric   return fastEmitInst_r(Opc, TLI.getRegClassFor(VT), ZReg);
5760b57cec5SDimitry Andric }
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric /// Check if the multiply is by a power-of-2 constant.
5790b57cec5SDimitry Andric static bool isMulPowOf2(const Value *I) {
5800b57cec5SDimitry Andric   if (const auto *MI = dyn_cast<MulOperator>(I)) {
5810b57cec5SDimitry Andric     if (const auto *C = dyn_cast<ConstantInt>(MI->getOperand(0)))
5820b57cec5SDimitry Andric       if (C->getValue().isPowerOf2())
5830b57cec5SDimitry Andric         return true;
5840b57cec5SDimitry Andric     if (const auto *C = dyn_cast<ConstantInt>(MI->getOperand(1)))
5850b57cec5SDimitry Andric       if (C->getValue().isPowerOf2())
5860b57cec5SDimitry Andric         return true;
5870b57cec5SDimitry Andric   }
5880b57cec5SDimitry Andric   return false;
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric // Computes the address to get to an object.
5920b57cec5SDimitry Andric bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr, Type *Ty)
5930b57cec5SDimitry Andric {
5940b57cec5SDimitry Andric   const User *U = nullptr;
5950b57cec5SDimitry Andric   unsigned Opcode = Instruction::UserOp1;
5960b57cec5SDimitry Andric   if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
5970b57cec5SDimitry Andric     // Don't walk into other basic blocks unless the object is an alloca from
5980b57cec5SDimitry Andric     // another block, otherwise it may not have a virtual register assigned.
5990b57cec5SDimitry Andric     if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
6000b57cec5SDimitry Andric         FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
6010b57cec5SDimitry Andric       Opcode = I->getOpcode();
6020b57cec5SDimitry Andric       U = I;
6030b57cec5SDimitry Andric     }
6040b57cec5SDimitry Andric   } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
6050b57cec5SDimitry Andric     Opcode = C->getOpcode();
6060b57cec5SDimitry Andric     U = C;
6070b57cec5SDimitry Andric   }
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric   if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
6100b57cec5SDimitry Andric     if (Ty->getAddressSpace() > 255)
6110b57cec5SDimitry Andric       // Fast instruction selection doesn't support the special
6120b57cec5SDimitry Andric       // address spaces.
6130b57cec5SDimitry Andric       return false;
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric   switch (Opcode) {
6160b57cec5SDimitry Andric   default:
6170b57cec5SDimitry Andric     break;
6180b57cec5SDimitry Andric   case Instruction::BitCast:
6190b57cec5SDimitry Andric     // Look through bitcasts.
6200b57cec5SDimitry Andric     return computeAddress(U->getOperand(0), Addr, Ty);
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric   case Instruction::IntToPtr:
6230b57cec5SDimitry Andric     // Look past no-op inttoptrs.
6240b57cec5SDimitry Andric     if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
6250b57cec5SDimitry Andric         TLI.getPointerTy(DL))
6260b57cec5SDimitry Andric       return computeAddress(U->getOperand(0), Addr, Ty);
6270b57cec5SDimitry Andric     break;
6280b57cec5SDimitry Andric 
6290b57cec5SDimitry Andric   case Instruction::PtrToInt:
6300b57cec5SDimitry Andric     // Look past no-op ptrtoints.
6310b57cec5SDimitry Andric     if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
6320b57cec5SDimitry Andric       return computeAddress(U->getOperand(0), Addr, Ty);
6330b57cec5SDimitry Andric     break;
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric   case Instruction::GetElementPtr: {
6360b57cec5SDimitry Andric     Address SavedAddr = Addr;
6370b57cec5SDimitry Andric     uint64_t TmpOffset = Addr.getOffset();
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric     // Iterate through the GEP folding the constants into offsets where
6400b57cec5SDimitry Andric     // we can.
6410b57cec5SDimitry Andric     for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
6420b57cec5SDimitry Andric          GTI != E; ++GTI) {
6430b57cec5SDimitry Andric       const Value *Op = GTI.getOperand();
6440b57cec5SDimitry Andric       if (StructType *STy = GTI.getStructTypeOrNull()) {
6450b57cec5SDimitry Andric         const StructLayout *SL = DL.getStructLayout(STy);
6460b57cec5SDimitry Andric         unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
6470b57cec5SDimitry Andric         TmpOffset += SL->getElementOffset(Idx);
6480b57cec5SDimitry Andric       } else {
6491db9f3b2SDimitry Andric         uint64_t S = GTI.getSequentialElementStride(DL);
6500b57cec5SDimitry Andric         while (true) {
6510b57cec5SDimitry Andric           if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
6520b57cec5SDimitry Andric             // Constant-offset addressing.
6530b57cec5SDimitry Andric             TmpOffset += CI->getSExtValue() * S;
6540b57cec5SDimitry Andric             break;
6550b57cec5SDimitry Andric           }
6560b57cec5SDimitry Andric           if (canFoldAddIntoGEP(U, Op)) {
6570b57cec5SDimitry Andric             // A compatible add with a constant operand. Fold the constant.
6580b57cec5SDimitry Andric             ConstantInt *CI =
6590b57cec5SDimitry Andric                 cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
6600b57cec5SDimitry Andric             TmpOffset += CI->getSExtValue() * S;
6610b57cec5SDimitry Andric             // Iterate on the other operand.
6620b57cec5SDimitry Andric             Op = cast<AddOperator>(Op)->getOperand(0);
6630b57cec5SDimitry Andric             continue;
6640b57cec5SDimitry Andric           }
6650b57cec5SDimitry Andric           // Unsupported
6660b57cec5SDimitry Andric           goto unsupported_gep;
6670b57cec5SDimitry Andric         }
6680b57cec5SDimitry Andric       }
6690b57cec5SDimitry Andric     }
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric     // Try to grab the base operand now.
6720b57cec5SDimitry Andric     Addr.setOffset(TmpOffset);
6730b57cec5SDimitry Andric     if (computeAddress(U->getOperand(0), Addr, Ty))
6740b57cec5SDimitry Andric       return true;
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric     // We failed, restore everything and try the other options.
6770b57cec5SDimitry Andric     Addr = SavedAddr;
6780b57cec5SDimitry Andric 
6790b57cec5SDimitry Andric   unsupported_gep:
6800b57cec5SDimitry Andric     break;
6810b57cec5SDimitry Andric   }
6820b57cec5SDimitry Andric   case Instruction::Alloca: {
6830b57cec5SDimitry Andric     const AllocaInst *AI = cast<AllocaInst>(Obj);
6840b57cec5SDimitry Andric     DenseMap<const AllocaInst *, int>::iterator SI =
6850b57cec5SDimitry Andric         FuncInfo.StaticAllocaMap.find(AI);
6860b57cec5SDimitry Andric     if (SI != FuncInfo.StaticAllocaMap.end()) {
6870b57cec5SDimitry Andric       Addr.setKind(Address::FrameIndexBase);
6880b57cec5SDimitry Andric       Addr.setFI(SI->second);
6890b57cec5SDimitry Andric       return true;
6900b57cec5SDimitry Andric     }
6910b57cec5SDimitry Andric     break;
6920b57cec5SDimitry Andric   }
6930b57cec5SDimitry Andric   case Instruction::Add: {
6940b57cec5SDimitry Andric     // Adds of constants are common and easy enough.
6950b57cec5SDimitry Andric     const Value *LHS = U->getOperand(0);
6960b57cec5SDimitry Andric     const Value *RHS = U->getOperand(1);
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric     if (isa<ConstantInt>(LHS))
6990b57cec5SDimitry Andric       std::swap(LHS, RHS);
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric     if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
7020b57cec5SDimitry Andric       Addr.setOffset(Addr.getOffset() + CI->getSExtValue());
7030b57cec5SDimitry Andric       return computeAddress(LHS, Addr, Ty);
7040b57cec5SDimitry Andric     }
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric     Address Backup = Addr;
7070b57cec5SDimitry Andric     if (computeAddress(LHS, Addr, Ty) && computeAddress(RHS, Addr, Ty))
7080b57cec5SDimitry Andric       return true;
7090b57cec5SDimitry Andric     Addr = Backup;
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric     break;
7120b57cec5SDimitry Andric   }
7130b57cec5SDimitry Andric   case Instruction::Sub: {
7140b57cec5SDimitry Andric     // Subs of constants are common and easy enough.
7150b57cec5SDimitry Andric     const Value *LHS = U->getOperand(0);
7160b57cec5SDimitry Andric     const Value *RHS = U->getOperand(1);
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric     if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
7190b57cec5SDimitry Andric       Addr.setOffset(Addr.getOffset() - CI->getSExtValue());
7200b57cec5SDimitry Andric       return computeAddress(LHS, Addr, Ty);
7210b57cec5SDimitry Andric     }
7220b57cec5SDimitry Andric     break;
7230b57cec5SDimitry Andric   }
7240b57cec5SDimitry Andric   case Instruction::Shl: {
7250b57cec5SDimitry Andric     if (Addr.getOffsetReg())
7260b57cec5SDimitry Andric       break;
7270b57cec5SDimitry Andric 
7280b57cec5SDimitry Andric     const auto *CI = dyn_cast<ConstantInt>(U->getOperand(1));
7290b57cec5SDimitry Andric     if (!CI)
7300b57cec5SDimitry Andric       break;
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric     unsigned Val = CI->getZExtValue();
7330b57cec5SDimitry Andric     if (Val < 1 || Val > 3)
7340b57cec5SDimitry Andric       break;
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric     uint64_t NumBytes = 0;
7370b57cec5SDimitry Andric     if (Ty && Ty->isSized()) {
7380b57cec5SDimitry Andric       uint64_t NumBits = DL.getTypeSizeInBits(Ty);
7390b57cec5SDimitry Andric       NumBytes = NumBits / 8;
7400b57cec5SDimitry Andric       if (!isPowerOf2_64(NumBits))
7410b57cec5SDimitry Andric         NumBytes = 0;
7420b57cec5SDimitry Andric     }
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric     if (NumBytes != (1ULL << Val))
7450b57cec5SDimitry Andric       break;
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric     Addr.setShift(Val);
7480b57cec5SDimitry Andric     Addr.setExtendType(AArch64_AM::LSL);
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric     const Value *Src = U->getOperand(0);
7510b57cec5SDimitry Andric     if (const auto *I = dyn_cast<Instruction>(Src)) {
7520b57cec5SDimitry Andric       if (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
7530b57cec5SDimitry Andric         // Fold the zext or sext when it won't become a noop.
7540b57cec5SDimitry Andric         if (const auto *ZE = dyn_cast<ZExtInst>(I)) {
7550b57cec5SDimitry Andric           if (!isIntExtFree(ZE) &&
7560b57cec5SDimitry Andric               ZE->getOperand(0)->getType()->isIntegerTy(32)) {
7570b57cec5SDimitry Andric             Addr.setExtendType(AArch64_AM::UXTW);
7580b57cec5SDimitry Andric             Src = ZE->getOperand(0);
7590b57cec5SDimitry Andric           }
7600b57cec5SDimitry Andric         } else if (const auto *SE = dyn_cast<SExtInst>(I)) {
7610b57cec5SDimitry Andric           if (!isIntExtFree(SE) &&
7620b57cec5SDimitry Andric               SE->getOperand(0)->getType()->isIntegerTy(32)) {
7630b57cec5SDimitry Andric             Addr.setExtendType(AArch64_AM::SXTW);
7640b57cec5SDimitry Andric             Src = SE->getOperand(0);
7650b57cec5SDimitry Andric           }
7660b57cec5SDimitry Andric         }
7670b57cec5SDimitry Andric       }
7680b57cec5SDimitry Andric     }
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric     if (const auto *AI = dyn_cast<BinaryOperator>(Src))
7710b57cec5SDimitry Andric       if (AI->getOpcode() == Instruction::And) {
7720b57cec5SDimitry Andric         const Value *LHS = AI->getOperand(0);
7730b57cec5SDimitry Andric         const Value *RHS = AI->getOperand(1);
7740b57cec5SDimitry Andric 
7750b57cec5SDimitry Andric         if (const auto *C = dyn_cast<ConstantInt>(LHS))
7760b57cec5SDimitry Andric           if (C->getValue() == 0xffffffff)
7770b57cec5SDimitry Andric             std::swap(LHS, RHS);
7780b57cec5SDimitry Andric 
7790b57cec5SDimitry Andric         if (const auto *C = dyn_cast<ConstantInt>(RHS))
7800b57cec5SDimitry Andric           if (C->getValue() == 0xffffffff) {
7810b57cec5SDimitry Andric             Addr.setExtendType(AArch64_AM::UXTW);
78204eeddc0SDimitry Andric             Register Reg = getRegForValue(LHS);
7830b57cec5SDimitry Andric             if (!Reg)
7840b57cec5SDimitry Andric               return false;
785fe6060f1SDimitry Andric             Reg = fastEmitInst_extractsubreg(MVT::i32, Reg, AArch64::sub_32);
7860b57cec5SDimitry Andric             Addr.setOffsetReg(Reg);
7870b57cec5SDimitry Andric             return true;
7880b57cec5SDimitry Andric           }
7890b57cec5SDimitry Andric       }
7900b57cec5SDimitry Andric 
79104eeddc0SDimitry Andric     Register Reg = getRegForValue(Src);
7920b57cec5SDimitry Andric     if (!Reg)
7930b57cec5SDimitry Andric       return false;
7940b57cec5SDimitry Andric     Addr.setOffsetReg(Reg);
7950b57cec5SDimitry Andric     return true;
7960b57cec5SDimitry Andric   }
7970b57cec5SDimitry Andric   case Instruction::Mul: {
7980b57cec5SDimitry Andric     if (Addr.getOffsetReg())
7990b57cec5SDimitry Andric       break;
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric     if (!isMulPowOf2(U))
8020b57cec5SDimitry Andric       break;
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric     const Value *LHS = U->getOperand(0);
8050b57cec5SDimitry Andric     const Value *RHS = U->getOperand(1);
8060b57cec5SDimitry Andric 
8070b57cec5SDimitry Andric     // Canonicalize power-of-2 value to the RHS.
8080b57cec5SDimitry Andric     if (const auto *C = dyn_cast<ConstantInt>(LHS))
8090b57cec5SDimitry Andric       if (C->getValue().isPowerOf2())
8100b57cec5SDimitry Andric         std::swap(LHS, RHS);
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric     assert(isa<ConstantInt>(RHS) && "Expected an ConstantInt.");
8130b57cec5SDimitry Andric     const auto *C = cast<ConstantInt>(RHS);
8140b57cec5SDimitry Andric     unsigned Val = C->getValue().logBase2();
8150b57cec5SDimitry Andric     if (Val < 1 || Val > 3)
8160b57cec5SDimitry Andric       break;
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric     uint64_t NumBytes = 0;
8190b57cec5SDimitry Andric     if (Ty && Ty->isSized()) {
8200b57cec5SDimitry Andric       uint64_t NumBits = DL.getTypeSizeInBits(Ty);
8210b57cec5SDimitry Andric       NumBytes = NumBits / 8;
8220b57cec5SDimitry Andric       if (!isPowerOf2_64(NumBits))
8230b57cec5SDimitry Andric         NumBytes = 0;
8240b57cec5SDimitry Andric     }
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric     if (NumBytes != (1ULL << Val))
8270b57cec5SDimitry Andric       break;
8280b57cec5SDimitry Andric 
8290b57cec5SDimitry Andric     Addr.setShift(Val);
8300b57cec5SDimitry Andric     Addr.setExtendType(AArch64_AM::LSL);
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric     const Value *Src = LHS;
8330b57cec5SDimitry Andric     if (const auto *I = dyn_cast<Instruction>(Src)) {
8340b57cec5SDimitry Andric       if (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
8350b57cec5SDimitry Andric         // Fold the zext or sext when it won't become a noop.
8360b57cec5SDimitry Andric         if (const auto *ZE = dyn_cast<ZExtInst>(I)) {
8370b57cec5SDimitry Andric           if (!isIntExtFree(ZE) &&
8380b57cec5SDimitry Andric               ZE->getOperand(0)->getType()->isIntegerTy(32)) {
8390b57cec5SDimitry Andric             Addr.setExtendType(AArch64_AM::UXTW);
8400b57cec5SDimitry Andric             Src = ZE->getOperand(0);
8410b57cec5SDimitry Andric           }
8420b57cec5SDimitry Andric         } else if (const auto *SE = dyn_cast<SExtInst>(I)) {
8430b57cec5SDimitry Andric           if (!isIntExtFree(SE) &&
8440b57cec5SDimitry Andric               SE->getOperand(0)->getType()->isIntegerTy(32)) {
8450b57cec5SDimitry Andric             Addr.setExtendType(AArch64_AM::SXTW);
8460b57cec5SDimitry Andric             Src = SE->getOperand(0);
8470b57cec5SDimitry Andric           }
8480b57cec5SDimitry Andric         }
8490b57cec5SDimitry Andric       }
8500b57cec5SDimitry Andric     }
8510b57cec5SDimitry Andric 
85204eeddc0SDimitry Andric     Register Reg = getRegForValue(Src);
8530b57cec5SDimitry Andric     if (!Reg)
8540b57cec5SDimitry Andric       return false;
8550b57cec5SDimitry Andric     Addr.setOffsetReg(Reg);
8560b57cec5SDimitry Andric     return true;
8570b57cec5SDimitry Andric   }
8580b57cec5SDimitry Andric   case Instruction::And: {
8590b57cec5SDimitry Andric     if (Addr.getOffsetReg())
8600b57cec5SDimitry Andric       break;
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric     if (!Ty || DL.getTypeSizeInBits(Ty) != 8)
8630b57cec5SDimitry Andric       break;
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric     const Value *LHS = U->getOperand(0);
8660b57cec5SDimitry Andric     const Value *RHS = U->getOperand(1);
8670b57cec5SDimitry Andric 
8680b57cec5SDimitry Andric     if (const auto *C = dyn_cast<ConstantInt>(LHS))
8690b57cec5SDimitry Andric       if (C->getValue() == 0xffffffff)
8700b57cec5SDimitry Andric         std::swap(LHS, RHS);
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric     if (const auto *C = dyn_cast<ConstantInt>(RHS))
8730b57cec5SDimitry Andric       if (C->getValue() == 0xffffffff) {
8740b57cec5SDimitry Andric         Addr.setShift(0);
8750b57cec5SDimitry Andric         Addr.setExtendType(AArch64_AM::LSL);
8760b57cec5SDimitry Andric         Addr.setExtendType(AArch64_AM::UXTW);
8770b57cec5SDimitry Andric 
87804eeddc0SDimitry Andric         Register Reg = getRegForValue(LHS);
8790b57cec5SDimitry Andric         if (!Reg)
8800b57cec5SDimitry Andric           return false;
881fe6060f1SDimitry Andric         Reg = fastEmitInst_extractsubreg(MVT::i32, Reg, AArch64::sub_32);
8820b57cec5SDimitry Andric         Addr.setOffsetReg(Reg);
8830b57cec5SDimitry Andric         return true;
8840b57cec5SDimitry Andric       }
8850b57cec5SDimitry Andric     break;
8860b57cec5SDimitry Andric   }
8870b57cec5SDimitry Andric   case Instruction::SExt:
8880b57cec5SDimitry Andric   case Instruction::ZExt: {
8890b57cec5SDimitry Andric     if (!Addr.getReg() || Addr.getOffsetReg())
8900b57cec5SDimitry Andric       break;
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric     const Value *Src = nullptr;
8930b57cec5SDimitry Andric     // Fold the zext or sext when it won't become a noop.
8940b57cec5SDimitry Andric     if (const auto *ZE = dyn_cast<ZExtInst>(U)) {
8950b57cec5SDimitry Andric       if (!isIntExtFree(ZE) && ZE->getOperand(0)->getType()->isIntegerTy(32)) {
8960b57cec5SDimitry Andric         Addr.setExtendType(AArch64_AM::UXTW);
8970b57cec5SDimitry Andric         Src = ZE->getOperand(0);
8980b57cec5SDimitry Andric       }
8990b57cec5SDimitry Andric     } else if (const auto *SE = dyn_cast<SExtInst>(U)) {
9000b57cec5SDimitry Andric       if (!isIntExtFree(SE) && SE->getOperand(0)->getType()->isIntegerTy(32)) {
9010b57cec5SDimitry Andric         Addr.setExtendType(AArch64_AM::SXTW);
9020b57cec5SDimitry Andric         Src = SE->getOperand(0);
9030b57cec5SDimitry Andric       }
9040b57cec5SDimitry Andric     }
9050b57cec5SDimitry Andric 
9060b57cec5SDimitry Andric     if (!Src)
9070b57cec5SDimitry Andric       break;
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric     Addr.setShift(0);
91004eeddc0SDimitry Andric     Register Reg = getRegForValue(Src);
9110b57cec5SDimitry Andric     if (!Reg)
9120b57cec5SDimitry Andric       return false;
9130b57cec5SDimitry Andric     Addr.setOffsetReg(Reg);
9140b57cec5SDimitry Andric     return true;
9150b57cec5SDimitry Andric   }
9160b57cec5SDimitry Andric   } // end switch
9170b57cec5SDimitry Andric 
9180b57cec5SDimitry Andric   if (Addr.isRegBase() && !Addr.getReg()) {
91904eeddc0SDimitry Andric     Register Reg = getRegForValue(Obj);
9200b57cec5SDimitry Andric     if (!Reg)
9210b57cec5SDimitry Andric       return false;
9220b57cec5SDimitry Andric     Addr.setReg(Reg);
9230b57cec5SDimitry Andric     return true;
9240b57cec5SDimitry Andric   }
9250b57cec5SDimitry Andric 
9260b57cec5SDimitry Andric   if (!Addr.getOffsetReg()) {
92704eeddc0SDimitry Andric     Register Reg = getRegForValue(Obj);
9280b57cec5SDimitry Andric     if (!Reg)
9290b57cec5SDimitry Andric       return false;
9300b57cec5SDimitry Andric     Addr.setOffsetReg(Reg);
9310b57cec5SDimitry Andric     return true;
9320b57cec5SDimitry Andric   }
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric   return false;
9350b57cec5SDimitry Andric }
9360b57cec5SDimitry Andric 
9370b57cec5SDimitry Andric bool AArch64FastISel::computeCallAddress(const Value *V, Address &Addr) {
9380b57cec5SDimitry Andric   const User *U = nullptr;
9390b57cec5SDimitry Andric   unsigned Opcode = Instruction::UserOp1;
9400b57cec5SDimitry Andric   bool InMBB = true;
9410b57cec5SDimitry Andric 
9420b57cec5SDimitry Andric   if (const auto *I = dyn_cast<Instruction>(V)) {
9430b57cec5SDimitry Andric     Opcode = I->getOpcode();
9440b57cec5SDimitry Andric     U = I;
9450b57cec5SDimitry Andric     InMBB = I->getParent() == FuncInfo.MBB->getBasicBlock();
9460b57cec5SDimitry Andric   } else if (const auto *C = dyn_cast<ConstantExpr>(V)) {
9470b57cec5SDimitry Andric     Opcode = C->getOpcode();
9480b57cec5SDimitry Andric     U = C;
9490b57cec5SDimitry Andric   }
9500b57cec5SDimitry Andric 
9510b57cec5SDimitry Andric   switch (Opcode) {
9520b57cec5SDimitry Andric   default: break;
9530b57cec5SDimitry Andric   case Instruction::BitCast:
9540b57cec5SDimitry Andric     // Look past bitcasts if its operand is in the same BB.
9550b57cec5SDimitry Andric     if (InMBB)
9560b57cec5SDimitry Andric       return computeCallAddress(U->getOperand(0), Addr);
9570b57cec5SDimitry Andric     break;
9580b57cec5SDimitry Andric   case Instruction::IntToPtr:
9590b57cec5SDimitry Andric     // Look past no-op inttoptrs if its operand is in the same BB.
9600b57cec5SDimitry Andric     if (InMBB &&
9610b57cec5SDimitry Andric         TLI.getValueType(DL, U->getOperand(0)->getType()) ==
9620b57cec5SDimitry Andric             TLI.getPointerTy(DL))
9630b57cec5SDimitry Andric       return computeCallAddress(U->getOperand(0), Addr);
9640b57cec5SDimitry Andric     break;
9650b57cec5SDimitry Andric   case Instruction::PtrToInt:
9660b57cec5SDimitry Andric     // Look past no-op ptrtoints if its operand is in the same BB.
9670b57cec5SDimitry Andric     if (InMBB && TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
9680b57cec5SDimitry Andric       return computeCallAddress(U->getOperand(0), Addr);
9690b57cec5SDimitry Andric     break;
9700b57cec5SDimitry Andric   }
9710b57cec5SDimitry Andric 
9720b57cec5SDimitry Andric   if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
9730b57cec5SDimitry Andric     Addr.setGlobalValue(GV);
9740b57cec5SDimitry Andric     return true;
9750b57cec5SDimitry Andric   }
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric   // If all else fails, try to materialize the value in a register.
9780b57cec5SDimitry Andric   if (!Addr.getGlobalValue()) {
9790b57cec5SDimitry Andric     Addr.setReg(getRegForValue(V));
9800b57cec5SDimitry Andric     return Addr.getReg() != 0;
9810b57cec5SDimitry Andric   }
9820b57cec5SDimitry Andric 
9830b57cec5SDimitry Andric   return false;
9840b57cec5SDimitry Andric }
9850b57cec5SDimitry Andric 
9860b57cec5SDimitry Andric bool AArch64FastISel::isTypeLegal(Type *Ty, MVT &VT) {
9870b57cec5SDimitry Andric   EVT evt = TLI.getValueType(DL, Ty, true);
9880b57cec5SDimitry Andric 
9898bcb0991SDimitry Andric   if (Subtarget->isTargetILP32() && Ty->isPointerTy())
9908bcb0991SDimitry Andric     return false;
9918bcb0991SDimitry Andric 
9920b57cec5SDimitry Andric   // Only handle simple types.
9930b57cec5SDimitry Andric   if (evt == MVT::Other || !evt.isSimple())
9940b57cec5SDimitry Andric     return false;
9950b57cec5SDimitry Andric   VT = evt.getSimpleVT();
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric   // This is a legal type, but it's not something we handle in fast-isel.
9980b57cec5SDimitry Andric   if (VT == MVT::f128)
9990b57cec5SDimitry Andric     return false;
10000b57cec5SDimitry Andric 
10010b57cec5SDimitry Andric   // Handle all other legal types, i.e. a register that will directly hold this
10020b57cec5SDimitry Andric   // value.
10030b57cec5SDimitry Andric   return TLI.isTypeLegal(VT);
10040b57cec5SDimitry Andric }
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric /// Determine if the value type is supported by FastISel.
10070b57cec5SDimitry Andric ///
10080b57cec5SDimitry Andric /// FastISel for AArch64 can handle more value types than are legal. This adds
10090b57cec5SDimitry Andric /// simple value type such as i1, i8, and i16.
10100b57cec5SDimitry Andric bool AArch64FastISel::isTypeSupported(Type *Ty, MVT &VT, bool IsVectorAllowed) {
10110b57cec5SDimitry Andric   if (Ty->isVectorTy() && !IsVectorAllowed)
10120b57cec5SDimitry Andric     return false;
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric   if (isTypeLegal(Ty, VT))
10150b57cec5SDimitry Andric     return true;
10160b57cec5SDimitry Andric 
10170b57cec5SDimitry Andric   // If this is a type than can be sign or zero-extended to a basic operation
10180b57cec5SDimitry Andric   // go ahead and accept it now.
10190b57cec5SDimitry Andric   if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)
10200b57cec5SDimitry Andric     return true;
10210b57cec5SDimitry Andric 
10220b57cec5SDimitry Andric   return false;
10230b57cec5SDimitry Andric }
10240b57cec5SDimitry Andric 
10250b57cec5SDimitry Andric bool AArch64FastISel::isValueAvailable(const Value *V) const {
10260b57cec5SDimitry Andric   if (!isa<Instruction>(V))
10270b57cec5SDimitry Andric     return true;
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric   const auto *I = cast<Instruction>(V);
10300b57cec5SDimitry Andric   return FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB;
10310b57cec5SDimitry Andric }
10320b57cec5SDimitry Andric 
10330b57cec5SDimitry Andric bool AArch64FastISel::simplifyAddress(Address &Addr, MVT VT) {
10348bcb0991SDimitry Andric   if (Subtarget->isTargetILP32())
10358bcb0991SDimitry Andric     return false;
10368bcb0991SDimitry Andric 
10370b57cec5SDimitry Andric   unsigned ScaleFactor = getImplicitScaleFactor(VT);
10380b57cec5SDimitry Andric   if (!ScaleFactor)
10390b57cec5SDimitry Andric     return false;
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric   bool ImmediateOffsetNeedsLowering = false;
10420b57cec5SDimitry Andric   bool RegisterOffsetNeedsLowering = false;
10430b57cec5SDimitry Andric   int64_t Offset = Addr.getOffset();
10440b57cec5SDimitry Andric   if (((Offset < 0) || (Offset & (ScaleFactor - 1))) && !isInt<9>(Offset))
10450b57cec5SDimitry Andric     ImmediateOffsetNeedsLowering = true;
10460b57cec5SDimitry Andric   else if (Offset > 0 && !(Offset & (ScaleFactor - 1)) &&
10470b57cec5SDimitry Andric            !isUInt<12>(Offset / ScaleFactor))
10480b57cec5SDimitry Andric     ImmediateOffsetNeedsLowering = true;
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric   // Cannot encode an offset register and an immediate offset in the same
10510b57cec5SDimitry Andric   // instruction. Fold the immediate offset into the load/store instruction and
10520b57cec5SDimitry Andric   // emit an additional add to take care of the offset register.
10530b57cec5SDimitry Andric   if (!ImmediateOffsetNeedsLowering && Addr.getOffset() && Addr.getOffsetReg())
10540b57cec5SDimitry Andric     RegisterOffsetNeedsLowering = true;
10550b57cec5SDimitry Andric 
10560b57cec5SDimitry Andric   // Cannot encode zero register as base.
10570b57cec5SDimitry Andric   if (Addr.isRegBase() && Addr.getOffsetReg() && !Addr.getReg())
10580b57cec5SDimitry Andric     RegisterOffsetNeedsLowering = true;
10590b57cec5SDimitry Andric 
10600b57cec5SDimitry Andric   // If this is a stack pointer and the offset needs to be simplified then put
10610b57cec5SDimitry Andric   // the alloca address into a register, set the base type back to register and
10620b57cec5SDimitry Andric   // continue. This should almost never happen.
10630b57cec5SDimitry Andric   if ((ImmediateOffsetNeedsLowering || Addr.getOffsetReg()) && Addr.isFIBase())
10640b57cec5SDimitry Andric   {
106504eeddc0SDimitry Andric     Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
1066bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADDXri),
10670b57cec5SDimitry Andric             ResultReg)
10680b57cec5SDimitry Andric       .addFrameIndex(Addr.getFI())
10690b57cec5SDimitry Andric       .addImm(0)
10700b57cec5SDimitry Andric       .addImm(0);
10710b57cec5SDimitry Andric     Addr.setKind(Address::RegBase);
10720b57cec5SDimitry Andric     Addr.setReg(ResultReg);
10730b57cec5SDimitry Andric   }
10740b57cec5SDimitry Andric 
10750b57cec5SDimitry Andric   if (RegisterOffsetNeedsLowering) {
10760b57cec5SDimitry Andric     unsigned ResultReg = 0;
10770b57cec5SDimitry Andric     if (Addr.getReg()) {
10780b57cec5SDimitry Andric       if (Addr.getExtendType() == AArch64_AM::SXTW ||
10790b57cec5SDimitry Andric           Addr.getExtendType() == AArch64_AM::UXTW   )
10800b57cec5SDimitry Andric         ResultReg = emitAddSub_rx(/*UseAdd=*/true, MVT::i64, Addr.getReg(),
1081fe6060f1SDimitry Andric                                   Addr.getOffsetReg(), Addr.getExtendType(),
10820b57cec5SDimitry Andric                                   Addr.getShift());
10830b57cec5SDimitry Andric       else
10840b57cec5SDimitry Andric         ResultReg = emitAddSub_rs(/*UseAdd=*/true, MVT::i64, Addr.getReg(),
1085fe6060f1SDimitry Andric                                   Addr.getOffsetReg(), AArch64_AM::LSL,
10860b57cec5SDimitry Andric                                   Addr.getShift());
10870b57cec5SDimitry Andric     } else {
10880b57cec5SDimitry Andric       if (Addr.getExtendType() == AArch64_AM::UXTW)
10890b57cec5SDimitry Andric         ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1090fe6060f1SDimitry Andric                                Addr.getShift(), /*IsZExt=*/true);
10910b57cec5SDimitry Andric       else if (Addr.getExtendType() == AArch64_AM::SXTW)
10920b57cec5SDimitry Andric         ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1093fe6060f1SDimitry Andric                                Addr.getShift(), /*IsZExt=*/false);
10940b57cec5SDimitry Andric       else
10950b57cec5SDimitry Andric         ResultReg = emitLSL_ri(MVT::i64, MVT::i64, Addr.getOffsetReg(),
1096fe6060f1SDimitry Andric                                Addr.getShift());
10970b57cec5SDimitry Andric     }
10980b57cec5SDimitry Andric     if (!ResultReg)
10990b57cec5SDimitry Andric       return false;
11000b57cec5SDimitry Andric 
11010b57cec5SDimitry Andric     Addr.setReg(ResultReg);
11020b57cec5SDimitry Andric     Addr.setOffsetReg(0);
11030b57cec5SDimitry Andric     Addr.setShift(0);
11040b57cec5SDimitry Andric     Addr.setExtendType(AArch64_AM::InvalidShiftExtend);
11050b57cec5SDimitry Andric   }
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   // Since the offset is too large for the load/store instruction get the
11080b57cec5SDimitry Andric   // reg+offset into a register.
11090b57cec5SDimitry Andric   if (ImmediateOffsetNeedsLowering) {
11100b57cec5SDimitry Andric     unsigned ResultReg;
11110b57cec5SDimitry Andric     if (Addr.getReg())
11120b57cec5SDimitry Andric       // Try to fold the immediate into the add instruction.
1113fe6060f1SDimitry Andric       ResultReg = emitAdd_ri_(MVT::i64, Addr.getReg(), Offset);
11140b57cec5SDimitry Andric     else
11150b57cec5SDimitry Andric       ResultReg = fastEmit_i(MVT::i64, MVT::i64, ISD::Constant, Offset);
11160b57cec5SDimitry Andric 
11170b57cec5SDimitry Andric     if (!ResultReg)
11180b57cec5SDimitry Andric       return false;
11190b57cec5SDimitry Andric     Addr.setReg(ResultReg);
11200b57cec5SDimitry Andric     Addr.setOffset(0);
11210b57cec5SDimitry Andric   }
11220b57cec5SDimitry Andric   return true;
11230b57cec5SDimitry Andric }
11240b57cec5SDimitry Andric 
11250b57cec5SDimitry Andric void AArch64FastISel::addLoadStoreOperands(Address &Addr,
11260b57cec5SDimitry Andric                                            const MachineInstrBuilder &MIB,
11270b57cec5SDimitry Andric                                            MachineMemOperand::Flags Flags,
11280b57cec5SDimitry Andric                                            unsigned ScaleFactor,
11290b57cec5SDimitry Andric                                            MachineMemOperand *MMO) {
11300b57cec5SDimitry Andric   int64_t Offset = Addr.getOffset() / ScaleFactor;
11310b57cec5SDimitry Andric   // Frame base works a bit differently. Handle it separately.
11320b57cec5SDimitry Andric   if (Addr.isFIBase()) {
11330b57cec5SDimitry Andric     int FI = Addr.getFI();
11340b57cec5SDimitry Andric     // FIXME: We shouldn't be using getObjectSize/getObjectAlignment.  The size
11350b57cec5SDimitry Andric     // and alignment should be based on the VT.
11360b57cec5SDimitry Andric     MMO = FuncInfo.MF->getMachineMemOperand(
11370b57cec5SDimitry Andric         MachinePointerInfo::getFixedStack(*FuncInfo.MF, FI, Offset), Flags,
11385ffd83dbSDimitry Andric         MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
11390b57cec5SDimitry Andric     // Now add the rest of the operands.
11400b57cec5SDimitry Andric     MIB.addFrameIndex(FI).addImm(Offset);
11410b57cec5SDimitry Andric   } else {
11420b57cec5SDimitry Andric     assert(Addr.isRegBase() && "Unexpected address kind.");
11430b57cec5SDimitry Andric     const MCInstrDesc &II = MIB->getDesc();
11440b57cec5SDimitry Andric     unsigned Idx = (Flags & MachineMemOperand::MOStore) ? 1 : 0;
11450b57cec5SDimitry Andric     Addr.setReg(
11460b57cec5SDimitry Andric       constrainOperandRegClass(II, Addr.getReg(), II.getNumDefs()+Idx));
11470b57cec5SDimitry Andric     Addr.setOffsetReg(
11480b57cec5SDimitry Andric       constrainOperandRegClass(II, Addr.getOffsetReg(), II.getNumDefs()+Idx+1));
11490b57cec5SDimitry Andric     if (Addr.getOffsetReg()) {
11500b57cec5SDimitry Andric       assert(Addr.getOffset() == 0 && "Unexpected offset");
11510b57cec5SDimitry Andric       bool IsSigned = Addr.getExtendType() == AArch64_AM::SXTW ||
11520b57cec5SDimitry Andric                       Addr.getExtendType() == AArch64_AM::SXTX;
11530b57cec5SDimitry Andric       MIB.addReg(Addr.getReg());
11540b57cec5SDimitry Andric       MIB.addReg(Addr.getOffsetReg());
11550b57cec5SDimitry Andric       MIB.addImm(IsSigned);
11560b57cec5SDimitry Andric       MIB.addImm(Addr.getShift() != 0);
11570b57cec5SDimitry Andric     } else
11580b57cec5SDimitry Andric       MIB.addReg(Addr.getReg()).addImm(Offset);
11590b57cec5SDimitry Andric   }
11600b57cec5SDimitry Andric 
11610b57cec5SDimitry Andric   if (MMO)
11620b57cec5SDimitry Andric     MIB.addMemOperand(MMO);
11630b57cec5SDimitry Andric }
11640b57cec5SDimitry Andric 
11650b57cec5SDimitry Andric unsigned AArch64FastISel::emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS,
11660b57cec5SDimitry Andric                                      const Value *RHS, bool SetFlags,
11670b57cec5SDimitry Andric                                      bool WantResult,  bool IsZExt) {
11680b57cec5SDimitry Andric   AArch64_AM::ShiftExtendType ExtendType = AArch64_AM::InvalidShiftExtend;
11690b57cec5SDimitry Andric   bool NeedExtend = false;
11700b57cec5SDimitry Andric   switch (RetVT.SimpleTy) {
11710b57cec5SDimitry Andric   default:
11720b57cec5SDimitry Andric     return 0;
11730b57cec5SDimitry Andric   case MVT::i1:
11740b57cec5SDimitry Andric     NeedExtend = true;
11750b57cec5SDimitry Andric     break;
11760b57cec5SDimitry Andric   case MVT::i8:
11770b57cec5SDimitry Andric     NeedExtend = true;
11780b57cec5SDimitry Andric     ExtendType = IsZExt ? AArch64_AM::UXTB : AArch64_AM::SXTB;
11790b57cec5SDimitry Andric     break;
11800b57cec5SDimitry Andric   case MVT::i16:
11810b57cec5SDimitry Andric     NeedExtend = true;
11820b57cec5SDimitry Andric     ExtendType = IsZExt ? AArch64_AM::UXTH : AArch64_AM::SXTH;
11830b57cec5SDimitry Andric     break;
11840b57cec5SDimitry Andric   case MVT::i32:  // fall-through
11850b57cec5SDimitry Andric   case MVT::i64:
11860b57cec5SDimitry Andric     break;
11870b57cec5SDimitry Andric   }
11880b57cec5SDimitry Andric   MVT SrcVT = RetVT;
11890b57cec5SDimitry Andric   RetVT.SimpleTy = std::max(RetVT.SimpleTy, MVT::i32);
11900b57cec5SDimitry Andric 
11910b57cec5SDimitry Andric   // Canonicalize immediates to the RHS first.
11920b57cec5SDimitry Andric   if (UseAdd && isa<Constant>(LHS) && !isa<Constant>(RHS))
11930b57cec5SDimitry Andric     std::swap(LHS, RHS);
11940b57cec5SDimitry Andric 
11950b57cec5SDimitry Andric   // Canonicalize mul by power of 2 to the RHS.
11960b57cec5SDimitry Andric   if (UseAdd && LHS->hasOneUse() && isValueAvailable(LHS))
11970b57cec5SDimitry Andric     if (isMulPowOf2(LHS))
11980b57cec5SDimitry Andric       std::swap(LHS, RHS);
11990b57cec5SDimitry Andric 
12000b57cec5SDimitry Andric   // Canonicalize shift immediate to the RHS.
12010b57cec5SDimitry Andric   if (UseAdd && LHS->hasOneUse() && isValueAvailable(LHS))
12020b57cec5SDimitry Andric     if (const auto *SI = dyn_cast<BinaryOperator>(LHS))
12030b57cec5SDimitry Andric       if (isa<ConstantInt>(SI->getOperand(1)))
12040b57cec5SDimitry Andric         if (SI->getOpcode() == Instruction::Shl  ||
12050b57cec5SDimitry Andric             SI->getOpcode() == Instruction::LShr ||
12060b57cec5SDimitry Andric             SI->getOpcode() == Instruction::AShr   )
12070b57cec5SDimitry Andric           std::swap(LHS, RHS);
12080b57cec5SDimitry Andric 
120904eeddc0SDimitry Andric   Register LHSReg = getRegForValue(LHS);
12100b57cec5SDimitry Andric   if (!LHSReg)
12110b57cec5SDimitry Andric     return 0;
12120b57cec5SDimitry Andric 
12130b57cec5SDimitry Andric   if (NeedExtend)
12140b57cec5SDimitry Andric     LHSReg = emitIntExt(SrcVT, LHSReg, RetVT, IsZExt);
12150b57cec5SDimitry Andric 
12160b57cec5SDimitry Andric   unsigned ResultReg = 0;
12170b57cec5SDimitry Andric   if (const auto *C = dyn_cast<ConstantInt>(RHS)) {
12180b57cec5SDimitry Andric     uint64_t Imm = IsZExt ? C->getZExtValue() : C->getSExtValue();
12190b57cec5SDimitry Andric     if (C->isNegative())
1220fe6060f1SDimitry Andric       ResultReg = emitAddSub_ri(!UseAdd, RetVT, LHSReg, -Imm, SetFlags,
1221fe6060f1SDimitry Andric                                 WantResult);
12220b57cec5SDimitry Andric     else
1223fe6060f1SDimitry Andric       ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, Imm, SetFlags,
12240b57cec5SDimitry Andric                                 WantResult);
12250b57cec5SDimitry Andric   } else if (const auto *C = dyn_cast<Constant>(RHS))
12260b57cec5SDimitry Andric     if (C->isNullValue())
1227fe6060f1SDimitry Andric       ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, 0, SetFlags, WantResult);
12280b57cec5SDimitry Andric 
12290b57cec5SDimitry Andric   if (ResultReg)
12300b57cec5SDimitry Andric     return ResultReg;
12310b57cec5SDimitry Andric 
12320b57cec5SDimitry Andric   // Only extend the RHS within the instruction if there is a valid extend type.
12330b57cec5SDimitry Andric   if (ExtendType != AArch64_AM::InvalidShiftExtend && RHS->hasOneUse() &&
12340b57cec5SDimitry Andric       isValueAvailable(RHS)) {
123504eeddc0SDimitry Andric     Register RHSReg = getRegForValue(RHS);
12360b57cec5SDimitry Andric     if (!RHSReg)
12370b57cec5SDimitry Andric       return 0;
1238fe6060f1SDimitry Andric     return emitAddSub_rx(UseAdd, RetVT, LHSReg, RHSReg, ExtendType, 0,
1239fe6060f1SDimitry Andric                          SetFlags, WantResult);
12400b57cec5SDimitry Andric   }
12410b57cec5SDimitry Andric 
12420b57cec5SDimitry Andric   // Check if the mul can be folded into the instruction.
12430b57cec5SDimitry Andric   if (RHS->hasOneUse() && isValueAvailable(RHS)) {
12440b57cec5SDimitry Andric     if (isMulPowOf2(RHS)) {
12450b57cec5SDimitry Andric       const Value *MulLHS = cast<MulOperator>(RHS)->getOperand(0);
12460b57cec5SDimitry Andric       const Value *MulRHS = cast<MulOperator>(RHS)->getOperand(1);
12470b57cec5SDimitry Andric 
12480b57cec5SDimitry Andric       if (const auto *C = dyn_cast<ConstantInt>(MulLHS))
12490b57cec5SDimitry Andric         if (C->getValue().isPowerOf2())
12500b57cec5SDimitry Andric           std::swap(MulLHS, MulRHS);
12510b57cec5SDimitry Andric 
12520b57cec5SDimitry Andric       assert(isa<ConstantInt>(MulRHS) && "Expected a ConstantInt.");
12530b57cec5SDimitry Andric       uint64_t ShiftVal = cast<ConstantInt>(MulRHS)->getValue().logBase2();
125404eeddc0SDimitry Andric       Register RHSReg = getRegForValue(MulLHS);
12550b57cec5SDimitry Andric       if (!RHSReg)
12560b57cec5SDimitry Andric         return 0;
1257fe6060f1SDimitry Andric       ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg, AArch64_AM::LSL,
1258fe6060f1SDimitry Andric                                 ShiftVal, SetFlags, WantResult);
12590b57cec5SDimitry Andric       if (ResultReg)
12600b57cec5SDimitry Andric         return ResultReg;
12610b57cec5SDimitry Andric     }
12620b57cec5SDimitry Andric   }
12630b57cec5SDimitry Andric 
12640b57cec5SDimitry Andric   // Check if the shift can be folded into the instruction.
12650b57cec5SDimitry Andric   if (RHS->hasOneUse() && isValueAvailable(RHS)) {
12660b57cec5SDimitry Andric     if (const auto *SI = dyn_cast<BinaryOperator>(RHS)) {
12670b57cec5SDimitry Andric       if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1))) {
12680b57cec5SDimitry Andric         AArch64_AM::ShiftExtendType ShiftType = AArch64_AM::InvalidShiftExtend;
12690b57cec5SDimitry Andric         switch (SI->getOpcode()) {
12700b57cec5SDimitry Andric         default: break;
12710b57cec5SDimitry Andric         case Instruction::Shl:  ShiftType = AArch64_AM::LSL; break;
12720b57cec5SDimitry Andric         case Instruction::LShr: ShiftType = AArch64_AM::LSR; break;
12730b57cec5SDimitry Andric         case Instruction::AShr: ShiftType = AArch64_AM::ASR; break;
12740b57cec5SDimitry Andric         }
12750b57cec5SDimitry Andric         uint64_t ShiftVal = C->getZExtValue();
12760b57cec5SDimitry Andric         if (ShiftType != AArch64_AM::InvalidShiftExtend) {
127704eeddc0SDimitry Andric           Register RHSReg = getRegForValue(SI->getOperand(0));
12780b57cec5SDimitry Andric           if (!RHSReg)
12790b57cec5SDimitry Andric             return 0;
1280fe6060f1SDimitry Andric           ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg, ShiftType,
1281fe6060f1SDimitry Andric                                     ShiftVal, SetFlags, WantResult);
12820b57cec5SDimitry Andric           if (ResultReg)
12830b57cec5SDimitry Andric             return ResultReg;
12840b57cec5SDimitry Andric         }
12850b57cec5SDimitry Andric       }
12860b57cec5SDimitry Andric     }
12870b57cec5SDimitry Andric   }
12880b57cec5SDimitry Andric 
128904eeddc0SDimitry Andric   Register RHSReg = getRegForValue(RHS);
12900b57cec5SDimitry Andric   if (!RHSReg)
12910b57cec5SDimitry Andric     return 0;
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric   if (NeedExtend)
12940b57cec5SDimitry Andric     RHSReg = emitIntExt(SrcVT, RHSReg, RetVT, IsZExt);
12950b57cec5SDimitry Andric 
1296fe6060f1SDimitry Andric   return emitAddSub_rr(UseAdd, RetVT, LHSReg, RHSReg, SetFlags, WantResult);
12970b57cec5SDimitry Andric }
12980b57cec5SDimitry Andric 
12990b57cec5SDimitry Andric unsigned AArch64FastISel::emitAddSub_rr(bool UseAdd, MVT RetVT, unsigned LHSReg,
1300fe6060f1SDimitry Andric                                         unsigned RHSReg, bool SetFlags,
13010b57cec5SDimitry Andric                                         bool WantResult) {
13020b57cec5SDimitry Andric   assert(LHSReg && RHSReg && "Invalid register number.");
13030b57cec5SDimitry Andric 
13040b57cec5SDimitry Andric   if (LHSReg == AArch64::SP || LHSReg == AArch64::WSP ||
13050b57cec5SDimitry Andric       RHSReg == AArch64::SP || RHSReg == AArch64::WSP)
13060b57cec5SDimitry Andric     return 0;
13070b57cec5SDimitry Andric 
13080b57cec5SDimitry Andric   if (RetVT != MVT::i32 && RetVT != MVT::i64)
13090b57cec5SDimitry Andric     return 0;
13100b57cec5SDimitry Andric 
13110b57cec5SDimitry Andric   static const unsigned OpcTable[2][2][2] = {
13120b57cec5SDimitry Andric     { { AArch64::SUBWrr,  AArch64::SUBXrr  },
13130b57cec5SDimitry Andric       { AArch64::ADDWrr,  AArch64::ADDXrr  }  },
13140b57cec5SDimitry Andric     { { AArch64::SUBSWrr, AArch64::SUBSXrr },
13150b57cec5SDimitry Andric       { AArch64::ADDSWrr, AArch64::ADDSXrr }  }
13160b57cec5SDimitry Andric   };
13170b57cec5SDimitry Andric   bool Is64Bit = RetVT == MVT::i64;
13180b57cec5SDimitry Andric   unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
13190b57cec5SDimitry Andric   const TargetRegisterClass *RC =
13200b57cec5SDimitry Andric       Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
13210b57cec5SDimitry Andric   unsigned ResultReg;
13220b57cec5SDimitry Andric   if (WantResult)
13230b57cec5SDimitry Andric     ResultReg = createResultReg(RC);
13240b57cec5SDimitry Andric   else
13250b57cec5SDimitry Andric     ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
13260b57cec5SDimitry Andric 
13270b57cec5SDimitry Andric   const MCInstrDesc &II = TII.get(Opc);
13280b57cec5SDimitry Andric   LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
13290b57cec5SDimitry Andric   RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
1330bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)
1331fe6060f1SDimitry Andric       .addReg(LHSReg)
1332fe6060f1SDimitry Andric       .addReg(RHSReg);
13330b57cec5SDimitry Andric   return ResultReg;
13340b57cec5SDimitry Andric }
13350b57cec5SDimitry Andric 
13360b57cec5SDimitry Andric unsigned AArch64FastISel::emitAddSub_ri(bool UseAdd, MVT RetVT, unsigned LHSReg,
1337fe6060f1SDimitry Andric                                         uint64_t Imm, bool SetFlags,
1338fe6060f1SDimitry Andric                                         bool WantResult) {
13390b57cec5SDimitry Andric   assert(LHSReg && "Invalid register number.");
13400b57cec5SDimitry Andric 
13410b57cec5SDimitry Andric   if (RetVT != MVT::i32 && RetVT != MVT::i64)
13420b57cec5SDimitry Andric     return 0;
13430b57cec5SDimitry Andric 
13440b57cec5SDimitry Andric   unsigned ShiftImm;
13450b57cec5SDimitry Andric   if (isUInt<12>(Imm))
13460b57cec5SDimitry Andric     ShiftImm = 0;
13470b57cec5SDimitry Andric   else if ((Imm & 0xfff000) == Imm) {
13480b57cec5SDimitry Andric     ShiftImm = 12;
13490b57cec5SDimitry Andric     Imm >>= 12;
13500b57cec5SDimitry Andric   } else
13510b57cec5SDimitry Andric     return 0;
13520b57cec5SDimitry Andric 
13530b57cec5SDimitry Andric   static const unsigned OpcTable[2][2][2] = {
13540b57cec5SDimitry Andric     { { AArch64::SUBWri,  AArch64::SUBXri  },
13550b57cec5SDimitry Andric       { AArch64::ADDWri,  AArch64::ADDXri  }  },
13560b57cec5SDimitry Andric     { { AArch64::SUBSWri, AArch64::SUBSXri },
13570b57cec5SDimitry Andric       { AArch64::ADDSWri, AArch64::ADDSXri }  }
13580b57cec5SDimitry Andric   };
13590b57cec5SDimitry Andric   bool Is64Bit = RetVT == MVT::i64;
13600b57cec5SDimitry Andric   unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
13610b57cec5SDimitry Andric   const TargetRegisterClass *RC;
13620b57cec5SDimitry Andric   if (SetFlags)
13630b57cec5SDimitry Andric     RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
13640b57cec5SDimitry Andric   else
13650b57cec5SDimitry Andric     RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
13660b57cec5SDimitry Andric   unsigned ResultReg;
13670b57cec5SDimitry Andric   if (WantResult)
13680b57cec5SDimitry Andric     ResultReg = createResultReg(RC);
13690b57cec5SDimitry Andric   else
13700b57cec5SDimitry Andric     ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
13710b57cec5SDimitry Andric 
13720b57cec5SDimitry Andric   const MCInstrDesc &II = TII.get(Opc);
13730b57cec5SDimitry Andric   LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
1374bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)
1375fe6060f1SDimitry Andric       .addReg(LHSReg)
13760b57cec5SDimitry Andric       .addImm(Imm)
13770b57cec5SDimitry Andric       .addImm(getShifterImm(AArch64_AM::LSL, ShiftImm));
13780b57cec5SDimitry Andric   return ResultReg;
13790b57cec5SDimitry Andric }
13800b57cec5SDimitry Andric 
13810b57cec5SDimitry Andric unsigned AArch64FastISel::emitAddSub_rs(bool UseAdd, MVT RetVT, unsigned LHSReg,
1382fe6060f1SDimitry Andric                                         unsigned RHSReg,
13830b57cec5SDimitry Andric                                         AArch64_AM::ShiftExtendType ShiftType,
13840b57cec5SDimitry Andric                                         uint64_t ShiftImm, bool SetFlags,
13850b57cec5SDimitry Andric                                         bool WantResult) {
13860b57cec5SDimitry Andric   assert(LHSReg && RHSReg && "Invalid register number.");
13870b57cec5SDimitry Andric   assert(LHSReg != AArch64::SP && LHSReg != AArch64::WSP &&
13880b57cec5SDimitry Andric          RHSReg != AArch64::SP && RHSReg != AArch64::WSP);
13890b57cec5SDimitry Andric 
13900b57cec5SDimitry Andric   if (RetVT != MVT::i32 && RetVT != MVT::i64)
13910b57cec5SDimitry Andric     return 0;
13920b57cec5SDimitry Andric 
13930b57cec5SDimitry Andric   // Don't deal with undefined shifts.
13940b57cec5SDimitry Andric   if (ShiftImm >= RetVT.getSizeInBits())
13950b57cec5SDimitry Andric     return 0;
13960b57cec5SDimitry Andric 
13970b57cec5SDimitry Andric   static const unsigned OpcTable[2][2][2] = {
13980b57cec5SDimitry Andric     { { AArch64::SUBWrs,  AArch64::SUBXrs  },
13990b57cec5SDimitry Andric       { AArch64::ADDWrs,  AArch64::ADDXrs  }  },
14000b57cec5SDimitry Andric     { { AArch64::SUBSWrs, AArch64::SUBSXrs },
14010b57cec5SDimitry Andric       { AArch64::ADDSWrs, AArch64::ADDSXrs }  }
14020b57cec5SDimitry Andric   };
14030b57cec5SDimitry Andric   bool Is64Bit = RetVT == MVT::i64;
14040b57cec5SDimitry Andric   unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
14050b57cec5SDimitry Andric   const TargetRegisterClass *RC =
14060b57cec5SDimitry Andric       Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
14070b57cec5SDimitry Andric   unsigned ResultReg;
14080b57cec5SDimitry Andric   if (WantResult)
14090b57cec5SDimitry Andric     ResultReg = createResultReg(RC);
14100b57cec5SDimitry Andric   else
14110b57cec5SDimitry Andric     ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
14120b57cec5SDimitry Andric 
14130b57cec5SDimitry Andric   const MCInstrDesc &II = TII.get(Opc);
14140b57cec5SDimitry Andric   LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
14150b57cec5SDimitry Andric   RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
1416bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)
1417fe6060f1SDimitry Andric       .addReg(LHSReg)
1418fe6060f1SDimitry Andric       .addReg(RHSReg)
14190b57cec5SDimitry Andric       .addImm(getShifterImm(ShiftType, ShiftImm));
14200b57cec5SDimitry Andric   return ResultReg;
14210b57cec5SDimitry Andric }
14220b57cec5SDimitry Andric 
14230b57cec5SDimitry Andric unsigned AArch64FastISel::emitAddSub_rx(bool UseAdd, MVT RetVT, unsigned LHSReg,
1424fe6060f1SDimitry Andric                                         unsigned RHSReg,
14250b57cec5SDimitry Andric                                         AArch64_AM::ShiftExtendType ExtType,
14260b57cec5SDimitry Andric                                         uint64_t ShiftImm, bool SetFlags,
14270b57cec5SDimitry Andric                                         bool WantResult) {
14280b57cec5SDimitry Andric   assert(LHSReg && RHSReg && "Invalid register number.");
14290b57cec5SDimitry Andric   assert(LHSReg != AArch64::XZR && LHSReg != AArch64::WZR &&
14300b57cec5SDimitry Andric          RHSReg != AArch64::XZR && RHSReg != AArch64::WZR);
14310b57cec5SDimitry Andric 
14320b57cec5SDimitry Andric   if (RetVT != MVT::i32 && RetVT != MVT::i64)
14330b57cec5SDimitry Andric     return 0;
14340b57cec5SDimitry Andric 
14350b57cec5SDimitry Andric   if (ShiftImm >= 4)
14360b57cec5SDimitry Andric     return 0;
14370b57cec5SDimitry Andric 
14380b57cec5SDimitry Andric   static const unsigned OpcTable[2][2][2] = {
14390b57cec5SDimitry Andric     { { AArch64::SUBWrx,  AArch64::SUBXrx  },
14400b57cec5SDimitry Andric       { AArch64::ADDWrx,  AArch64::ADDXrx  }  },
14410b57cec5SDimitry Andric     { { AArch64::SUBSWrx, AArch64::SUBSXrx },
14420b57cec5SDimitry Andric       { AArch64::ADDSWrx, AArch64::ADDSXrx }  }
14430b57cec5SDimitry Andric   };
14440b57cec5SDimitry Andric   bool Is64Bit = RetVT == MVT::i64;
14450b57cec5SDimitry Andric   unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
14460b57cec5SDimitry Andric   const TargetRegisterClass *RC = nullptr;
14470b57cec5SDimitry Andric   if (SetFlags)
14480b57cec5SDimitry Andric     RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
14490b57cec5SDimitry Andric   else
14500b57cec5SDimitry Andric     RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
14510b57cec5SDimitry Andric   unsigned ResultReg;
14520b57cec5SDimitry Andric   if (WantResult)
14530b57cec5SDimitry Andric     ResultReg = createResultReg(RC);
14540b57cec5SDimitry Andric   else
14550b57cec5SDimitry Andric     ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
14560b57cec5SDimitry Andric 
14570b57cec5SDimitry Andric   const MCInstrDesc &II = TII.get(Opc);
14580b57cec5SDimitry Andric   LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
14590b57cec5SDimitry Andric   RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
1460bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)
1461fe6060f1SDimitry Andric       .addReg(LHSReg)
1462fe6060f1SDimitry Andric       .addReg(RHSReg)
14630b57cec5SDimitry Andric       .addImm(getArithExtendImm(ExtType, ShiftImm));
14640b57cec5SDimitry Andric   return ResultReg;
14650b57cec5SDimitry Andric }
14660b57cec5SDimitry Andric 
14670b57cec5SDimitry Andric bool AArch64FastISel::emitCmp(const Value *LHS, const Value *RHS, bool IsZExt) {
14680b57cec5SDimitry Andric   Type *Ty = LHS->getType();
14690b57cec5SDimitry Andric   EVT EVT = TLI.getValueType(DL, Ty, true);
14700b57cec5SDimitry Andric   if (!EVT.isSimple())
14710b57cec5SDimitry Andric     return false;
14720b57cec5SDimitry Andric   MVT VT = EVT.getSimpleVT();
14730b57cec5SDimitry Andric 
14740b57cec5SDimitry Andric   switch (VT.SimpleTy) {
14750b57cec5SDimitry Andric   default:
14760b57cec5SDimitry Andric     return false;
14770b57cec5SDimitry Andric   case MVT::i1:
14780b57cec5SDimitry Andric   case MVT::i8:
14790b57cec5SDimitry Andric   case MVT::i16:
14800b57cec5SDimitry Andric   case MVT::i32:
14810b57cec5SDimitry Andric   case MVT::i64:
14820b57cec5SDimitry Andric     return emitICmp(VT, LHS, RHS, IsZExt);
14830b57cec5SDimitry Andric   case MVT::f32:
14840b57cec5SDimitry Andric   case MVT::f64:
14850b57cec5SDimitry Andric     return emitFCmp(VT, LHS, RHS);
14860b57cec5SDimitry Andric   }
14870b57cec5SDimitry Andric }
14880b57cec5SDimitry Andric 
14890b57cec5SDimitry Andric bool AArch64FastISel::emitICmp(MVT RetVT, const Value *LHS, const Value *RHS,
14900b57cec5SDimitry Andric                                bool IsZExt) {
14910b57cec5SDimitry Andric   return emitSub(RetVT, LHS, RHS, /*SetFlags=*/true, /*WantResult=*/false,
14920b57cec5SDimitry Andric                  IsZExt) != 0;
14930b57cec5SDimitry Andric }
14940b57cec5SDimitry Andric 
1495fe6060f1SDimitry Andric bool AArch64FastISel::emitICmp_ri(MVT RetVT, unsigned LHSReg, uint64_t Imm) {
1496fe6060f1SDimitry Andric   return emitAddSub_ri(/*UseAdd=*/false, RetVT, LHSReg, Imm,
14970b57cec5SDimitry Andric                        /*SetFlags=*/true, /*WantResult=*/false) != 0;
14980b57cec5SDimitry Andric }
14990b57cec5SDimitry Andric 
15000b57cec5SDimitry Andric bool AArch64FastISel::emitFCmp(MVT RetVT, const Value *LHS, const Value *RHS) {
15010b57cec5SDimitry Andric   if (RetVT != MVT::f32 && RetVT != MVT::f64)
15020b57cec5SDimitry Andric     return false;
15030b57cec5SDimitry Andric 
15040b57cec5SDimitry Andric   // Check to see if the 2nd operand is a constant that we can encode directly
15050b57cec5SDimitry Andric   // in the compare.
15060b57cec5SDimitry Andric   bool UseImm = false;
15070b57cec5SDimitry Andric   if (const auto *CFP = dyn_cast<ConstantFP>(RHS))
15080b57cec5SDimitry Andric     if (CFP->isZero() && !CFP->isNegative())
15090b57cec5SDimitry Andric       UseImm = true;
15100b57cec5SDimitry Andric 
151104eeddc0SDimitry Andric   Register LHSReg = getRegForValue(LHS);
15120b57cec5SDimitry Andric   if (!LHSReg)
15130b57cec5SDimitry Andric     return false;
15140b57cec5SDimitry Andric 
15150b57cec5SDimitry Andric   if (UseImm) {
15160b57cec5SDimitry Andric     unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDri : AArch64::FCMPSri;
1517bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc))
1518fe6060f1SDimitry Andric         .addReg(LHSReg);
15190b57cec5SDimitry Andric     return true;
15200b57cec5SDimitry Andric   }
15210b57cec5SDimitry Andric 
152204eeddc0SDimitry Andric   Register RHSReg = getRegForValue(RHS);
15230b57cec5SDimitry Andric   if (!RHSReg)
15240b57cec5SDimitry Andric     return false;
15250b57cec5SDimitry Andric 
15260b57cec5SDimitry Andric   unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDrr : AArch64::FCMPSrr;
1527bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc))
1528fe6060f1SDimitry Andric       .addReg(LHSReg)
1529fe6060f1SDimitry Andric       .addReg(RHSReg);
15300b57cec5SDimitry Andric   return true;
15310b57cec5SDimitry Andric }
15320b57cec5SDimitry Andric 
15330b57cec5SDimitry Andric unsigned AArch64FastISel::emitAdd(MVT RetVT, const Value *LHS, const Value *RHS,
15340b57cec5SDimitry Andric                                   bool SetFlags, bool WantResult, bool IsZExt) {
15350b57cec5SDimitry Andric   return emitAddSub(/*UseAdd=*/true, RetVT, LHS, RHS, SetFlags, WantResult,
15360b57cec5SDimitry Andric                     IsZExt);
15370b57cec5SDimitry Andric }
15380b57cec5SDimitry Andric 
15390b57cec5SDimitry Andric /// This method is a wrapper to simplify add emission.
15400b57cec5SDimitry Andric ///
15410b57cec5SDimitry Andric /// First try to emit an add with an immediate operand using emitAddSub_ri. If
15420b57cec5SDimitry Andric /// that fails, then try to materialize the immediate into a register and use
15430b57cec5SDimitry Andric /// emitAddSub_rr instead.
1544fe6060f1SDimitry Andric unsigned AArch64FastISel::emitAdd_ri_(MVT VT, unsigned Op0, int64_t Imm) {
15450b57cec5SDimitry Andric   unsigned ResultReg;
15460b57cec5SDimitry Andric   if (Imm < 0)
1547fe6060f1SDimitry Andric     ResultReg = emitAddSub_ri(false, VT, Op0, -Imm);
15480b57cec5SDimitry Andric   else
1549fe6060f1SDimitry Andric     ResultReg = emitAddSub_ri(true, VT, Op0, Imm);
15500b57cec5SDimitry Andric 
15510b57cec5SDimitry Andric   if (ResultReg)
15520b57cec5SDimitry Andric     return ResultReg;
15530b57cec5SDimitry Andric 
15540b57cec5SDimitry Andric   unsigned CReg = fastEmit_i(VT, VT, ISD::Constant, Imm);
15550b57cec5SDimitry Andric   if (!CReg)
15560b57cec5SDimitry Andric     return 0;
15570b57cec5SDimitry Andric 
1558fe6060f1SDimitry Andric   ResultReg = emitAddSub_rr(true, VT, Op0, CReg);
15590b57cec5SDimitry Andric   return ResultReg;
15600b57cec5SDimitry Andric }
15610b57cec5SDimitry Andric 
15620b57cec5SDimitry Andric unsigned AArch64FastISel::emitSub(MVT RetVT, const Value *LHS, const Value *RHS,
15630b57cec5SDimitry Andric                                   bool SetFlags, bool WantResult, bool IsZExt) {
15640b57cec5SDimitry Andric   return emitAddSub(/*UseAdd=*/false, RetVT, LHS, RHS, SetFlags, WantResult,
15650b57cec5SDimitry Andric                     IsZExt);
15660b57cec5SDimitry Andric }
15670b57cec5SDimitry Andric 
15680b57cec5SDimitry Andric unsigned AArch64FastISel::emitSubs_rr(MVT RetVT, unsigned LHSReg,
1569fe6060f1SDimitry Andric                                       unsigned RHSReg, bool WantResult) {
1570fe6060f1SDimitry Andric   return emitAddSub_rr(/*UseAdd=*/false, RetVT, LHSReg, RHSReg,
1571fe6060f1SDimitry Andric                        /*SetFlags=*/true, WantResult);
15720b57cec5SDimitry Andric }
15730b57cec5SDimitry Andric 
15740b57cec5SDimitry Andric unsigned AArch64FastISel::emitSubs_rs(MVT RetVT, unsigned LHSReg,
1575fe6060f1SDimitry Andric                                       unsigned RHSReg,
15760b57cec5SDimitry Andric                                       AArch64_AM::ShiftExtendType ShiftType,
15770b57cec5SDimitry Andric                                       uint64_t ShiftImm, bool WantResult) {
1578fe6060f1SDimitry Andric   return emitAddSub_rs(/*UseAdd=*/false, RetVT, LHSReg, RHSReg, ShiftType,
1579fe6060f1SDimitry Andric                        ShiftImm, /*SetFlags=*/true, WantResult);
15800b57cec5SDimitry Andric }
15810b57cec5SDimitry Andric 
15820b57cec5SDimitry Andric unsigned AArch64FastISel::emitLogicalOp(unsigned ISDOpc, MVT RetVT,
15830b57cec5SDimitry Andric                                         const Value *LHS, const Value *RHS) {
15840b57cec5SDimitry Andric   // Canonicalize immediates to the RHS first.
15850b57cec5SDimitry Andric   if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS))
15860b57cec5SDimitry Andric     std::swap(LHS, RHS);
15870b57cec5SDimitry Andric 
15880b57cec5SDimitry Andric   // Canonicalize mul by power-of-2 to the RHS.
15890b57cec5SDimitry Andric   if (LHS->hasOneUse() && isValueAvailable(LHS))
15900b57cec5SDimitry Andric     if (isMulPowOf2(LHS))
15910b57cec5SDimitry Andric       std::swap(LHS, RHS);
15920b57cec5SDimitry Andric 
15930b57cec5SDimitry Andric   // Canonicalize shift immediate to the RHS.
15940b57cec5SDimitry Andric   if (LHS->hasOneUse() && isValueAvailable(LHS))
15950b57cec5SDimitry Andric     if (const auto *SI = dyn_cast<ShlOperator>(LHS))
15960b57cec5SDimitry Andric       if (isa<ConstantInt>(SI->getOperand(1)))
15970b57cec5SDimitry Andric         std::swap(LHS, RHS);
15980b57cec5SDimitry Andric 
159904eeddc0SDimitry Andric   Register LHSReg = getRegForValue(LHS);
16000b57cec5SDimitry Andric   if (!LHSReg)
16010b57cec5SDimitry Andric     return 0;
16020b57cec5SDimitry Andric 
16030b57cec5SDimitry Andric   unsigned ResultReg = 0;
16040b57cec5SDimitry Andric   if (const auto *C = dyn_cast<ConstantInt>(RHS)) {
16050b57cec5SDimitry Andric     uint64_t Imm = C->getZExtValue();
1606fe6060f1SDimitry Andric     ResultReg = emitLogicalOp_ri(ISDOpc, RetVT, LHSReg, Imm);
16070b57cec5SDimitry Andric   }
16080b57cec5SDimitry Andric   if (ResultReg)
16090b57cec5SDimitry Andric     return ResultReg;
16100b57cec5SDimitry Andric 
16110b57cec5SDimitry Andric   // Check if the mul can be folded into the instruction.
16120b57cec5SDimitry Andric   if (RHS->hasOneUse() && isValueAvailable(RHS)) {
16130b57cec5SDimitry Andric     if (isMulPowOf2(RHS)) {
16140b57cec5SDimitry Andric       const Value *MulLHS = cast<MulOperator>(RHS)->getOperand(0);
16150b57cec5SDimitry Andric       const Value *MulRHS = cast<MulOperator>(RHS)->getOperand(1);
16160b57cec5SDimitry Andric 
16170b57cec5SDimitry Andric       if (const auto *C = dyn_cast<ConstantInt>(MulLHS))
16180b57cec5SDimitry Andric         if (C->getValue().isPowerOf2())
16190b57cec5SDimitry Andric           std::swap(MulLHS, MulRHS);
16200b57cec5SDimitry Andric 
16210b57cec5SDimitry Andric       assert(isa<ConstantInt>(MulRHS) && "Expected a ConstantInt.");
16220b57cec5SDimitry Andric       uint64_t ShiftVal = cast<ConstantInt>(MulRHS)->getValue().logBase2();
16230b57cec5SDimitry Andric 
162404eeddc0SDimitry Andric       Register RHSReg = getRegForValue(MulLHS);
16250b57cec5SDimitry Andric       if (!RHSReg)
16260b57cec5SDimitry Andric         return 0;
1627fe6060f1SDimitry Andric       ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);
16280b57cec5SDimitry Andric       if (ResultReg)
16290b57cec5SDimitry Andric         return ResultReg;
16300b57cec5SDimitry Andric     }
16310b57cec5SDimitry Andric   }
16320b57cec5SDimitry Andric 
16330b57cec5SDimitry Andric   // Check if the shift can be folded into the instruction.
16340b57cec5SDimitry Andric   if (RHS->hasOneUse() && isValueAvailable(RHS)) {
16350b57cec5SDimitry Andric     if (const auto *SI = dyn_cast<ShlOperator>(RHS))
16360b57cec5SDimitry Andric       if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1))) {
16370b57cec5SDimitry Andric         uint64_t ShiftVal = C->getZExtValue();
163804eeddc0SDimitry Andric         Register RHSReg = getRegForValue(SI->getOperand(0));
16390b57cec5SDimitry Andric         if (!RHSReg)
16400b57cec5SDimitry Andric           return 0;
1641fe6060f1SDimitry Andric         ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);
16420b57cec5SDimitry Andric         if (ResultReg)
16430b57cec5SDimitry Andric           return ResultReg;
16440b57cec5SDimitry Andric       }
16450b57cec5SDimitry Andric   }
16460b57cec5SDimitry Andric 
164704eeddc0SDimitry Andric   Register RHSReg = getRegForValue(RHS);
16480b57cec5SDimitry Andric   if (!RHSReg)
16490b57cec5SDimitry Andric     return 0;
16500b57cec5SDimitry Andric 
16510b57cec5SDimitry Andric   MVT VT = std::max(MVT::i32, RetVT.SimpleTy);
1652fe6060f1SDimitry Andric   ResultReg = fastEmit_rr(VT, VT, ISDOpc, LHSReg, RHSReg);
16530b57cec5SDimitry Andric   if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
16540b57cec5SDimitry Andric     uint64_t Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1655fe6060f1SDimitry Andric     ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
16560b57cec5SDimitry Andric   }
16570b57cec5SDimitry Andric   return ResultReg;
16580b57cec5SDimitry Andric }
16590b57cec5SDimitry Andric 
16600b57cec5SDimitry Andric unsigned AArch64FastISel::emitLogicalOp_ri(unsigned ISDOpc, MVT RetVT,
1661fe6060f1SDimitry Andric                                            unsigned LHSReg, uint64_t Imm) {
16620b57cec5SDimitry Andric   static_assert((ISD::AND + 1 == ISD::OR) && (ISD::AND + 2 == ISD::XOR),
16630b57cec5SDimitry Andric                 "ISD nodes are not consecutive!");
16640b57cec5SDimitry Andric   static const unsigned OpcTable[3][2] = {
16650b57cec5SDimitry Andric     { AArch64::ANDWri, AArch64::ANDXri },
16660b57cec5SDimitry Andric     { AArch64::ORRWri, AArch64::ORRXri },
16670b57cec5SDimitry Andric     { AArch64::EORWri, AArch64::EORXri }
16680b57cec5SDimitry Andric   };
16690b57cec5SDimitry Andric   const TargetRegisterClass *RC;
16700b57cec5SDimitry Andric   unsigned Opc;
16710b57cec5SDimitry Andric   unsigned RegSize;
16720b57cec5SDimitry Andric   switch (RetVT.SimpleTy) {
16730b57cec5SDimitry Andric   default:
16740b57cec5SDimitry Andric     return 0;
16750b57cec5SDimitry Andric   case MVT::i1:
16760b57cec5SDimitry Andric   case MVT::i8:
16770b57cec5SDimitry Andric   case MVT::i16:
16780b57cec5SDimitry Andric   case MVT::i32: {
16790b57cec5SDimitry Andric     unsigned Idx = ISDOpc - ISD::AND;
16800b57cec5SDimitry Andric     Opc = OpcTable[Idx][0];
16810b57cec5SDimitry Andric     RC = &AArch64::GPR32spRegClass;
16820b57cec5SDimitry Andric     RegSize = 32;
16830b57cec5SDimitry Andric     break;
16840b57cec5SDimitry Andric   }
16850b57cec5SDimitry Andric   case MVT::i64:
16860b57cec5SDimitry Andric     Opc = OpcTable[ISDOpc - ISD::AND][1];
16870b57cec5SDimitry Andric     RC = &AArch64::GPR64spRegClass;
16880b57cec5SDimitry Andric     RegSize = 64;
16890b57cec5SDimitry Andric     break;
16900b57cec5SDimitry Andric   }
16910b57cec5SDimitry Andric 
16920b57cec5SDimitry Andric   if (!AArch64_AM::isLogicalImmediate(Imm, RegSize))
16930b57cec5SDimitry Andric     return 0;
16940b57cec5SDimitry Andric 
169504eeddc0SDimitry Andric   Register ResultReg =
1696fe6060f1SDimitry Andric       fastEmitInst_ri(Opc, RC, LHSReg,
16970b57cec5SDimitry Andric                       AArch64_AM::encodeLogicalImmediate(Imm, RegSize));
16980b57cec5SDimitry Andric   if (RetVT >= MVT::i8 && RetVT <= MVT::i16 && ISDOpc != ISD::AND) {
16990b57cec5SDimitry Andric     uint64_t Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1700fe6060f1SDimitry Andric     ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
17010b57cec5SDimitry Andric   }
17020b57cec5SDimitry Andric   return ResultReg;
17030b57cec5SDimitry Andric }
17040b57cec5SDimitry Andric 
17050b57cec5SDimitry Andric unsigned AArch64FastISel::emitLogicalOp_rs(unsigned ISDOpc, MVT RetVT,
1706fe6060f1SDimitry Andric                                            unsigned LHSReg, unsigned RHSReg,
17070b57cec5SDimitry Andric                                            uint64_t ShiftImm) {
17080b57cec5SDimitry Andric   static_assert((ISD::AND + 1 == ISD::OR) && (ISD::AND + 2 == ISD::XOR),
17090b57cec5SDimitry Andric                 "ISD nodes are not consecutive!");
17100b57cec5SDimitry Andric   static const unsigned OpcTable[3][2] = {
17110b57cec5SDimitry Andric     { AArch64::ANDWrs, AArch64::ANDXrs },
17120b57cec5SDimitry Andric     { AArch64::ORRWrs, AArch64::ORRXrs },
17130b57cec5SDimitry Andric     { AArch64::EORWrs, AArch64::EORXrs }
17140b57cec5SDimitry Andric   };
17150b57cec5SDimitry Andric 
17160b57cec5SDimitry Andric   // Don't deal with undefined shifts.
17170b57cec5SDimitry Andric   if (ShiftImm >= RetVT.getSizeInBits())
17180b57cec5SDimitry Andric     return 0;
17190b57cec5SDimitry Andric 
17200b57cec5SDimitry Andric   const TargetRegisterClass *RC;
17210b57cec5SDimitry Andric   unsigned Opc;
17220b57cec5SDimitry Andric   switch (RetVT.SimpleTy) {
17230b57cec5SDimitry Andric   default:
17240b57cec5SDimitry Andric     return 0;
17250b57cec5SDimitry Andric   case MVT::i1:
17260b57cec5SDimitry Andric   case MVT::i8:
17270b57cec5SDimitry Andric   case MVT::i16:
17280b57cec5SDimitry Andric   case MVT::i32:
17290b57cec5SDimitry Andric     Opc = OpcTable[ISDOpc - ISD::AND][0];
17300b57cec5SDimitry Andric     RC = &AArch64::GPR32RegClass;
17310b57cec5SDimitry Andric     break;
17320b57cec5SDimitry Andric   case MVT::i64:
17330b57cec5SDimitry Andric     Opc = OpcTable[ISDOpc - ISD::AND][1];
17340b57cec5SDimitry Andric     RC = &AArch64::GPR64RegClass;
17350b57cec5SDimitry Andric     break;
17360b57cec5SDimitry Andric   }
173704eeddc0SDimitry Andric   Register ResultReg =
1738fe6060f1SDimitry Andric       fastEmitInst_rri(Opc, RC, LHSReg, RHSReg,
17390b57cec5SDimitry Andric                        AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftImm));
17400b57cec5SDimitry Andric   if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
17410b57cec5SDimitry Andric     uint64_t Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1742fe6060f1SDimitry Andric     ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
17430b57cec5SDimitry Andric   }
17440b57cec5SDimitry Andric   return ResultReg;
17450b57cec5SDimitry Andric }
17460b57cec5SDimitry Andric 
1747fe6060f1SDimitry Andric unsigned AArch64FastISel::emitAnd_ri(MVT RetVT, unsigned LHSReg,
17480b57cec5SDimitry Andric                                      uint64_t Imm) {
1749fe6060f1SDimitry Andric   return emitLogicalOp_ri(ISD::AND, RetVT, LHSReg, Imm);
17500b57cec5SDimitry Andric }
17510b57cec5SDimitry Andric 
17520b57cec5SDimitry Andric unsigned AArch64FastISel::emitLoad(MVT VT, MVT RetVT, Address Addr,
17530b57cec5SDimitry Andric                                    bool WantZExt, MachineMemOperand *MMO) {
17540b57cec5SDimitry Andric   if (!TLI.allowsMisalignedMemoryAccesses(VT))
17550b57cec5SDimitry Andric     return 0;
17560b57cec5SDimitry Andric 
17570b57cec5SDimitry Andric   // Simplify this down to something we can handle.
17580b57cec5SDimitry Andric   if (!simplifyAddress(Addr, VT))
17590b57cec5SDimitry Andric     return 0;
17600b57cec5SDimitry Andric 
17610b57cec5SDimitry Andric   unsigned ScaleFactor = getImplicitScaleFactor(VT);
17620b57cec5SDimitry Andric   if (!ScaleFactor)
17630b57cec5SDimitry Andric     llvm_unreachable("Unexpected value type.");
17640b57cec5SDimitry Andric 
17650b57cec5SDimitry Andric   // Negative offsets require unscaled, 9-bit, signed immediate offsets.
17660b57cec5SDimitry Andric   // Otherwise, we try using scaled, 12-bit, unsigned immediate offsets.
17670b57cec5SDimitry Andric   bool UseScaled = true;
17680b57cec5SDimitry Andric   if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
17690b57cec5SDimitry Andric     UseScaled = false;
17700b57cec5SDimitry Andric     ScaleFactor = 1;
17710b57cec5SDimitry Andric   }
17720b57cec5SDimitry Andric 
17730b57cec5SDimitry Andric   static const unsigned GPOpcTable[2][8][4] = {
17740b57cec5SDimitry Andric     // Sign-extend.
17750b57cec5SDimitry Andric     { { AArch64::LDURSBWi,  AArch64::LDURSHWi,  AArch64::LDURWi,
17760b57cec5SDimitry Andric         AArch64::LDURXi  },
17770b57cec5SDimitry Andric       { AArch64::LDURSBXi,  AArch64::LDURSHXi,  AArch64::LDURSWi,
17780b57cec5SDimitry Andric         AArch64::LDURXi  },
17790b57cec5SDimitry Andric       { AArch64::LDRSBWui,  AArch64::LDRSHWui,  AArch64::LDRWui,
17800b57cec5SDimitry Andric         AArch64::LDRXui  },
17810b57cec5SDimitry Andric       { AArch64::LDRSBXui,  AArch64::LDRSHXui,  AArch64::LDRSWui,
17820b57cec5SDimitry Andric         AArch64::LDRXui  },
17830b57cec5SDimitry Andric       { AArch64::LDRSBWroX, AArch64::LDRSHWroX, AArch64::LDRWroX,
17840b57cec5SDimitry Andric         AArch64::LDRXroX },
17850b57cec5SDimitry Andric       { AArch64::LDRSBXroX, AArch64::LDRSHXroX, AArch64::LDRSWroX,
17860b57cec5SDimitry Andric         AArch64::LDRXroX },
17870b57cec5SDimitry Andric       { AArch64::LDRSBWroW, AArch64::LDRSHWroW, AArch64::LDRWroW,
17880b57cec5SDimitry Andric         AArch64::LDRXroW },
17890b57cec5SDimitry Andric       { AArch64::LDRSBXroW, AArch64::LDRSHXroW, AArch64::LDRSWroW,
17900b57cec5SDimitry Andric         AArch64::LDRXroW }
17910b57cec5SDimitry Andric     },
17920b57cec5SDimitry Andric     // Zero-extend.
17930b57cec5SDimitry Andric     { { AArch64::LDURBBi,   AArch64::LDURHHi,   AArch64::LDURWi,
17940b57cec5SDimitry Andric         AArch64::LDURXi  },
17950b57cec5SDimitry Andric       { AArch64::LDURBBi,   AArch64::LDURHHi,   AArch64::LDURWi,
17960b57cec5SDimitry Andric         AArch64::LDURXi  },
17970b57cec5SDimitry Andric       { AArch64::LDRBBui,   AArch64::LDRHHui,   AArch64::LDRWui,
17980b57cec5SDimitry Andric         AArch64::LDRXui  },
17990b57cec5SDimitry Andric       { AArch64::LDRBBui,   AArch64::LDRHHui,   AArch64::LDRWui,
18000b57cec5SDimitry Andric         AArch64::LDRXui  },
18010b57cec5SDimitry Andric       { AArch64::LDRBBroX,  AArch64::LDRHHroX,  AArch64::LDRWroX,
18020b57cec5SDimitry Andric         AArch64::LDRXroX },
18030b57cec5SDimitry Andric       { AArch64::LDRBBroX,  AArch64::LDRHHroX,  AArch64::LDRWroX,
18040b57cec5SDimitry Andric         AArch64::LDRXroX },
18050b57cec5SDimitry Andric       { AArch64::LDRBBroW,  AArch64::LDRHHroW,  AArch64::LDRWroW,
18060b57cec5SDimitry Andric         AArch64::LDRXroW },
18070b57cec5SDimitry Andric       { AArch64::LDRBBroW,  AArch64::LDRHHroW,  AArch64::LDRWroW,
18080b57cec5SDimitry Andric         AArch64::LDRXroW }
18090b57cec5SDimitry Andric     }
18100b57cec5SDimitry Andric   };
18110b57cec5SDimitry Andric 
18120b57cec5SDimitry Andric   static const unsigned FPOpcTable[4][2] = {
18130b57cec5SDimitry Andric     { AArch64::LDURSi,  AArch64::LDURDi  },
18140b57cec5SDimitry Andric     { AArch64::LDRSui,  AArch64::LDRDui  },
18150b57cec5SDimitry Andric     { AArch64::LDRSroX, AArch64::LDRDroX },
18160b57cec5SDimitry Andric     { AArch64::LDRSroW, AArch64::LDRDroW }
18170b57cec5SDimitry Andric   };
18180b57cec5SDimitry Andric 
18190b57cec5SDimitry Andric   unsigned Opc;
18200b57cec5SDimitry Andric   const TargetRegisterClass *RC;
18210b57cec5SDimitry Andric   bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
18220b57cec5SDimitry Andric                       Addr.getOffsetReg();
18230b57cec5SDimitry Andric   unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
18240b57cec5SDimitry Andric   if (Addr.getExtendType() == AArch64_AM::UXTW ||
18250b57cec5SDimitry Andric       Addr.getExtendType() == AArch64_AM::SXTW)
18260b57cec5SDimitry Andric     Idx++;
18270b57cec5SDimitry Andric 
18280b57cec5SDimitry Andric   bool IsRet64Bit = RetVT == MVT::i64;
18290b57cec5SDimitry Andric   switch (VT.SimpleTy) {
18300b57cec5SDimitry Andric   default:
18310b57cec5SDimitry Andric     llvm_unreachable("Unexpected value type.");
18320b57cec5SDimitry Andric   case MVT::i1: // Intentional fall-through.
18330b57cec5SDimitry Andric   case MVT::i8:
18340b57cec5SDimitry Andric     Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][0];
18350b57cec5SDimitry Andric     RC = (IsRet64Bit && !WantZExt) ?
18360b57cec5SDimitry Andric              &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
18370b57cec5SDimitry Andric     break;
18380b57cec5SDimitry Andric   case MVT::i16:
18390b57cec5SDimitry Andric     Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][1];
18400b57cec5SDimitry Andric     RC = (IsRet64Bit && !WantZExt) ?
18410b57cec5SDimitry Andric              &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
18420b57cec5SDimitry Andric     break;
18430b57cec5SDimitry Andric   case MVT::i32:
18440b57cec5SDimitry Andric     Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][2];
18450b57cec5SDimitry Andric     RC = (IsRet64Bit && !WantZExt) ?
18460b57cec5SDimitry Andric              &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
18470b57cec5SDimitry Andric     break;
18480b57cec5SDimitry Andric   case MVT::i64:
18490b57cec5SDimitry Andric     Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][3];
18500b57cec5SDimitry Andric     RC = &AArch64::GPR64RegClass;
18510b57cec5SDimitry Andric     break;
18520b57cec5SDimitry Andric   case MVT::f32:
18530b57cec5SDimitry Andric     Opc = FPOpcTable[Idx][0];
18540b57cec5SDimitry Andric     RC = &AArch64::FPR32RegClass;
18550b57cec5SDimitry Andric     break;
18560b57cec5SDimitry Andric   case MVT::f64:
18570b57cec5SDimitry Andric     Opc = FPOpcTable[Idx][1];
18580b57cec5SDimitry Andric     RC = &AArch64::FPR64RegClass;
18590b57cec5SDimitry Andric     break;
18600b57cec5SDimitry Andric   }
18610b57cec5SDimitry Andric 
18620b57cec5SDimitry Andric   // Create the base instruction, then add the operands.
186304eeddc0SDimitry Andric   Register ResultReg = createResultReg(RC);
1864bdd1243dSDimitry Andric   MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
18650b57cec5SDimitry Andric                                     TII.get(Opc), ResultReg);
18660b57cec5SDimitry Andric   addLoadStoreOperands(Addr, MIB, MachineMemOperand::MOLoad, ScaleFactor, MMO);
18670b57cec5SDimitry Andric 
18680b57cec5SDimitry Andric   // Loading an i1 requires special handling.
18690b57cec5SDimitry Andric   if (VT == MVT::i1) {
1870fe6060f1SDimitry Andric     unsigned ANDReg = emitAnd_ri(MVT::i32, ResultReg, 1);
18710b57cec5SDimitry Andric     assert(ANDReg && "Unexpected AND instruction emission failure.");
18720b57cec5SDimitry Andric     ResultReg = ANDReg;
18730b57cec5SDimitry Andric   }
18740b57cec5SDimitry Andric 
18750b57cec5SDimitry Andric   // For zero-extending loads to 64bit we emit a 32bit load and then convert
18760b57cec5SDimitry Andric   // the 32bit reg to a 64bit reg.
18770b57cec5SDimitry Andric   if (WantZExt && RetVT == MVT::i64 && VT <= MVT::i32) {
187804eeddc0SDimitry Andric     Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
1879bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
18800b57cec5SDimitry Andric             TII.get(AArch64::SUBREG_TO_REG), Reg64)
18810b57cec5SDimitry Andric         .addImm(0)
18820b57cec5SDimitry Andric         .addReg(ResultReg, getKillRegState(true))
18830b57cec5SDimitry Andric         .addImm(AArch64::sub_32);
18840b57cec5SDimitry Andric     ResultReg = Reg64;
18850b57cec5SDimitry Andric   }
18860b57cec5SDimitry Andric   return ResultReg;
18870b57cec5SDimitry Andric }
18880b57cec5SDimitry Andric 
18890b57cec5SDimitry Andric bool AArch64FastISel::selectAddSub(const Instruction *I) {
18900b57cec5SDimitry Andric   MVT VT;
18910b57cec5SDimitry Andric   if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true))
18920b57cec5SDimitry Andric     return false;
18930b57cec5SDimitry Andric 
18940b57cec5SDimitry Andric   if (VT.isVector())
18950b57cec5SDimitry Andric     return selectOperator(I, I->getOpcode());
18960b57cec5SDimitry Andric 
18970b57cec5SDimitry Andric   unsigned ResultReg;
18980b57cec5SDimitry Andric   switch (I->getOpcode()) {
18990b57cec5SDimitry Andric   default:
19000b57cec5SDimitry Andric     llvm_unreachable("Unexpected instruction.");
19010b57cec5SDimitry Andric   case Instruction::Add:
19020b57cec5SDimitry Andric     ResultReg = emitAdd(VT, I->getOperand(0), I->getOperand(1));
19030b57cec5SDimitry Andric     break;
19040b57cec5SDimitry Andric   case Instruction::Sub:
19050b57cec5SDimitry Andric     ResultReg = emitSub(VT, I->getOperand(0), I->getOperand(1));
19060b57cec5SDimitry Andric     break;
19070b57cec5SDimitry Andric   }
19080b57cec5SDimitry Andric   if (!ResultReg)
19090b57cec5SDimitry Andric     return false;
19100b57cec5SDimitry Andric 
19110b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
19120b57cec5SDimitry Andric   return true;
19130b57cec5SDimitry Andric }
19140b57cec5SDimitry Andric 
19150b57cec5SDimitry Andric bool AArch64FastISel::selectLogicalOp(const Instruction *I) {
19160b57cec5SDimitry Andric   MVT VT;
19170b57cec5SDimitry Andric   if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true))
19180b57cec5SDimitry Andric     return false;
19190b57cec5SDimitry Andric 
19200b57cec5SDimitry Andric   if (VT.isVector())
19210b57cec5SDimitry Andric     return selectOperator(I, I->getOpcode());
19220b57cec5SDimitry Andric 
19230b57cec5SDimitry Andric   unsigned ResultReg;
19240b57cec5SDimitry Andric   switch (I->getOpcode()) {
19250b57cec5SDimitry Andric   default:
19260b57cec5SDimitry Andric     llvm_unreachable("Unexpected instruction.");
19270b57cec5SDimitry Andric   case Instruction::And:
19280b57cec5SDimitry Andric     ResultReg = emitLogicalOp(ISD::AND, VT, I->getOperand(0), I->getOperand(1));
19290b57cec5SDimitry Andric     break;
19300b57cec5SDimitry Andric   case Instruction::Or:
19310b57cec5SDimitry Andric     ResultReg = emitLogicalOp(ISD::OR, VT, I->getOperand(0), I->getOperand(1));
19320b57cec5SDimitry Andric     break;
19330b57cec5SDimitry Andric   case Instruction::Xor:
19340b57cec5SDimitry Andric     ResultReg = emitLogicalOp(ISD::XOR, VT, I->getOperand(0), I->getOperand(1));
19350b57cec5SDimitry Andric     break;
19360b57cec5SDimitry Andric   }
19370b57cec5SDimitry Andric   if (!ResultReg)
19380b57cec5SDimitry Andric     return false;
19390b57cec5SDimitry Andric 
19400b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
19410b57cec5SDimitry Andric   return true;
19420b57cec5SDimitry Andric }
19430b57cec5SDimitry Andric 
19440b57cec5SDimitry Andric bool AArch64FastISel::selectLoad(const Instruction *I) {
19450b57cec5SDimitry Andric   MVT VT;
19460b57cec5SDimitry Andric   // Verify we have a legal type before going any further.  Currently, we handle
19470b57cec5SDimitry Andric   // simple types that will directly fit in a register (i32/f32/i64/f64) or
19480b57cec5SDimitry Andric   // those that can be sign or zero-extended to a basic operation (i1/i8/i16).
19490b57cec5SDimitry Andric   if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true) ||
19500b57cec5SDimitry Andric       cast<LoadInst>(I)->isAtomic())
19510b57cec5SDimitry Andric     return false;
19520b57cec5SDimitry Andric 
19530b57cec5SDimitry Andric   const Value *SV = I->getOperand(0);
19540b57cec5SDimitry Andric   if (TLI.supportSwiftError()) {
19550b57cec5SDimitry Andric     // Swifterror values can come from either a function parameter with
19560b57cec5SDimitry Andric     // swifterror attribute or an alloca with swifterror attribute.
19570b57cec5SDimitry Andric     if (const Argument *Arg = dyn_cast<Argument>(SV)) {
19580b57cec5SDimitry Andric       if (Arg->hasSwiftErrorAttr())
19590b57cec5SDimitry Andric         return false;
19600b57cec5SDimitry Andric     }
19610b57cec5SDimitry Andric 
19620b57cec5SDimitry Andric     if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(SV)) {
19630b57cec5SDimitry Andric       if (Alloca->isSwiftError())
19640b57cec5SDimitry Andric         return false;
19650b57cec5SDimitry Andric     }
19660b57cec5SDimitry Andric   }
19670b57cec5SDimitry Andric 
19680b57cec5SDimitry Andric   // See if we can handle this address.
19690b57cec5SDimitry Andric   Address Addr;
19700b57cec5SDimitry Andric   if (!computeAddress(I->getOperand(0), Addr, I->getType()))
19710b57cec5SDimitry Andric     return false;
19720b57cec5SDimitry Andric 
19730b57cec5SDimitry Andric   // Fold the following sign-/zero-extend into the load instruction.
19740b57cec5SDimitry Andric   bool WantZExt = true;
19750b57cec5SDimitry Andric   MVT RetVT = VT;
19760b57cec5SDimitry Andric   const Value *IntExtVal = nullptr;
19770b57cec5SDimitry Andric   if (I->hasOneUse()) {
19780b57cec5SDimitry Andric     if (const auto *ZE = dyn_cast<ZExtInst>(I->use_begin()->getUser())) {
19790b57cec5SDimitry Andric       if (isTypeSupported(ZE->getType(), RetVT))
19800b57cec5SDimitry Andric         IntExtVal = ZE;
19810b57cec5SDimitry Andric       else
19820b57cec5SDimitry Andric         RetVT = VT;
19830b57cec5SDimitry Andric     } else if (const auto *SE = dyn_cast<SExtInst>(I->use_begin()->getUser())) {
19840b57cec5SDimitry Andric       if (isTypeSupported(SE->getType(), RetVT))
19850b57cec5SDimitry Andric         IntExtVal = SE;
19860b57cec5SDimitry Andric       else
19870b57cec5SDimitry Andric         RetVT = VT;
19880b57cec5SDimitry Andric       WantZExt = false;
19890b57cec5SDimitry Andric     }
19900b57cec5SDimitry Andric   }
19910b57cec5SDimitry Andric 
19920b57cec5SDimitry Andric   unsigned ResultReg =
19930b57cec5SDimitry Andric       emitLoad(VT, RetVT, Addr, WantZExt, createMachineMemOperandFor(I));
19940b57cec5SDimitry Andric   if (!ResultReg)
19950b57cec5SDimitry Andric     return false;
19960b57cec5SDimitry Andric 
19970b57cec5SDimitry Andric   // There are a few different cases we have to handle, because the load or the
19980b57cec5SDimitry Andric   // sign-/zero-extend might not be selected by FastISel if we fall-back to
19990b57cec5SDimitry Andric   // SelectionDAG. There is also an ordering issue when both instructions are in
20000b57cec5SDimitry Andric   // different basic blocks.
20010b57cec5SDimitry Andric   // 1.) The load instruction is selected by FastISel, but the integer extend
20020b57cec5SDimitry Andric   //     not. This usually happens when the integer extend is in a different
20030b57cec5SDimitry Andric   //     basic block and SelectionDAG took over for that basic block.
20040b57cec5SDimitry Andric   // 2.) The load instruction is selected before the integer extend. This only
20050b57cec5SDimitry Andric   //     happens when the integer extend is in a different basic block.
20060b57cec5SDimitry Andric   // 3.) The load instruction is selected by SelectionDAG and the integer extend
20070b57cec5SDimitry Andric   //     by FastISel. This happens if there are instructions between the load
20080b57cec5SDimitry Andric   //     and the integer extend that couldn't be selected by FastISel.
20090b57cec5SDimitry Andric   if (IntExtVal) {
20100b57cec5SDimitry Andric     // The integer extend hasn't been emitted yet. FastISel or SelectionDAG
20110b57cec5SDimitry Andric     // could select it. Emit a copy to subreg if necessary. FastISel will remove
20120b57cec5SDimitry Andric     // it when it selects the integer extend.
201304eeddc0SDimitry Andric     Register Reg = lookUpRegForValue(IntExtVal);
20140b57cec5SDimitry Andric     auto *MI = MRI.getUniqueVRegDef(Reg);
20150b57cec5SDimitry Andric     if (!MI) {
20160b57cec5SDimitry Andric       if (RetVT == MVT::i64 && VT <= MVT::i32) {
20170b57cec5SDimitry Andric         if (WantZExt) {
20180b57cec5SDimitry Andric           // Delete the last emitted instruction from emitLoad (SUBREG_TO_REG).
20190b57cec5SDimitry Andric           MachineBasicBlock::iterator I(std::prev(FuncInfo.InsertPt));
20200b57cec5SDimitry Andric           ResultReg = std::prev(I)->getOperand(0).getReg();
20210b57cec5SDimitry Andric           removeDeadCode(I, std::next(I));
20220b57cec5SDimitry Andric         } else
20230b57cec5SDimitry Andric           ResultReg = fastEmitInst_extractsubreg(MVT::i32, ResultReg,
20240b57cec5SDimitry Andric                                                  AArch64::sub_32);
20250b57cec5SDimitry Andric       }
20260b57cec5SDimitry Andric       updateValueMap(I, ResultReg);
20270b57cec5SDimitry Andric       return true;
20280b57cec5SDimitry Andric     }
20290b57cec5SDimitry Andric 
20300b57cec5SDimitry Andric     // The integer extend has already been emitted - delete all the instructions
20310b57cec5SDimitry Andric     // that have been emitted by the integer extend lowering code and use the
20320b57cec5SDimitry Andric     // result from the load instruction directly.
20330b57cec5SDimitry Andric     while (MI) {
20340b57cec5SDimitry Andric       Reg = 0;
20350b57cec5SDimitry Andric       for (auto &Opnd : MI->uses()) {
20360b57cec5SDimitry Andric         if (Opnd.isReg()) {
20370b57cec5SDimitry Andric           Reg = Opnd.getReg();
20380b57cec5SDimitry Andric           break;
20390b57cec5SDimitry Andric         }
20400b57cec5SDimitry Andric       }
20410b57cec5SDimitry Andric       MachineBasicBlock::iterator I(MI);
20420b57cec5SDimitry Andric       removeDeadCode(I, std::next(I));
20430b57cec5SDimitry Andric       MI = nullptr;
20440b57cec5SDimitry Andric       if (Reg)
20450b57cec5SDimitry Andric         MI = MRI.getUniqueVRegDef(Reg);
20460b57cec5SDimitry Andric     }
20470b57cec5SDimitry Andric     updateValueMap(IntExtVal, ResultReg);
20480b57cec5SDimitry Andric     return true;
20490b57cec5SDimitry Andric   }
20500b57cec5SDimitry Andric 
20510b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
20520b57cec5SDimitry Andric   return true;
20530b57cec5SDimitry Andric }
20540b57cec5SDimitry Andric 
20550b57cec5SDimitry Andric bool AArch64FastISel::emitStoreRelease(MVT VT, unsigned SrcReg,
20560b57cec5SDimitry Andric                                        unsigned AddrReg,
20570b57cec5SDimitry Andric                                        MachineMemOperand *MMO) {
20580b57cec5SDimitry Andric   unsigned Opc;
20590b57cec5SDimitry Andric   switch (VT.SimpleTy) {
20600b57cec5SDimitry Andric   default: return false;
20610b57cec5SDimitry Andric   case MVT::i8:  Opc = AArch64::STLRB; break;
20620b57cec5SDimitry Andric   case MVT::i16: Opc = AArch64::STLRH; break;
20630b57cec5SDimitry Andric   case MVT::i32: Opc = AArch64::STLRW; break;
20640b57cec5SDimitry Andric   case MVT::i64: Opc = AArch64::STLRX; break;
20650b57cec5SDimitry Andric   }
20660b57cec5SDimitry Andric 
20670b57cec5SDimitry Andric   const MCInstrDesc &II = TII.get(Opc);
20680b57cec5SDimitry Andric   SrcReg = constrainOperandRegClass(II, SrcReg, 0);
20690b57cec5SDimitry Andric   AddrReg = constrainOperandRegClass(II, AddrReg, 1);
2070bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)
20710b57cec5SDimitry Andric       .addReg(SrcReg)
20720b57cec5SDimitry Andric       .addReg(AddrReg)
20730b57cec5SDimitry Andric       .addMemOperand(MMO);
20740b57cec5SDimitry Andric   return true;
20750b57cec5SDimitry Andric }
20760b57cec5SDimitry Andric 
20770b57cec5SDimitry Andric bool AArch64FastISel::emitStore(MVT VT, unsigned SrcReg, Address Addr,
20780b57cec5SDimitry Andric                                 MachineMemOperand *MMO) {
20790b57cec5SDimitry Andric   if (!TLI.allowsMisalignedMemoryAccesses(VT))
20800b57cec5SDimitry Andric     return false;
20810b57cec5SDimitry Andric 
20820b57cec5SDimitry Andric   // Simplify this down to something we can handle.
20830b57cec5SDimitry Andric   if (!simplifyAddress(Addr, VT))
20840b57cec5SDimitry Andric     return false;
20850b57cec5SDimitry Andric 
20860b57cec5SDimitry Andric   unsigned ScaleFactor = getImplicitScaleFactor(VT);
20870b57cec5SDimitry Andric   if (!ScaleFactor)
20880b57cec5SDimitry Andric     llvm_unreachable("Unexpected value type.");
20890b57cec5SDimitry Andric 
20900b57cec5SDimitry Andric   // Negative offsets require unscaled, 9-bit, signed immediate offsets.
20910b57cec5SDimitry Andric   // Otherwise, we try using scaled, 12-bit, unsigned immediate offsets.
20920b57cec5SDimitry Andric   bool UseScaled = true;
20930b57cec5SDimitry Andric   if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
20940b57cec5SDimitry Andric     UseScaled = false;
20950b57cec5SDimitry Andric     ScaleFactor = 1;
20960b57cec5SDimitry Andric   }
20970b57cec5SDimitry Andric 
20980b57cec5SDimitry Andric   static const unsigned OpcTable[4][6] = {
20990b57cec5SDimitry Andric     { AArch64::STURBBi,  AArch64::STURHHi,  AArch64::STURWi,  AArch64::STURXi,
21000b57cec5SDimitry Andric       AArch64::STURSi,   AArch64::STURDi },
21010b57cec5SDimitry Andric     { AArch64::STRBBui,  AArch64::STRHHui,  AArch64::STRWui,  AArch64::STRXui,
21020b57cec5SDimitry Andric       AArch64::STRSui,   AArch64::STRDui },
21030b57cec5SDimitry Andric     { AArch64::STRBBroX, AArch64::STRHHroX, AArch64::STRWroX, AArch64::STRXroX,
21040b57cec5SDimitry Andric       AArch64::STRSroX,  AArch64::STRDroX },
21050b57cec5SDimitry Andric     { AArch64::STRBBroW, AArch64::STRHHroW, AArch64::STRWroW, AArch64::STRXroW,
21060b57cec5SDimitry Andric       AArch64::STRSroW,  AArch64::STRDroW }
21070b57cec5SDimitry Andric   };
21080b57cec5SDimitry Andric 
21090b57cec5SDimitry Andric   unsigned Opc;
21100b57cec5SDimitry Andric   bool VTIsi1 = false;
21110b57cec5SDimitry Andric   bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
21120b57cec5SDimitry Andric                       Addr.getOffsetReg();
21130b57cec5SDimitry Andric   unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
21140b57cec5SDimitry Andric   if (Addr.getExtendType() == AArch64_AM::UXTW ||
21150b57cec5SDimitry Andric       Addr.getExtendType() == AArch64_AM::SXTW)
21160b57cec5SDimitry Andric     Idx++;
21170b57cec5SDimitry Andric 
21180b57cec5SDimitry Andric   switch (VT.SimpleTy) {
21190b57cec5SDimitry Andric   default: llvm_unreachable("Unexpected value type.");
2120bdd1243dSDimitry Andric   case MVT::i1:  VTIsi1 = true; [[fallthrough]];
21210b57cec5SDimitry Andric   case MVT::i8:  Opc = OpcTable[Idx][0]; break;
21220b57cec5SDimitry Andric   case MVT::i16: Opc = OpcTable[Idx][1]; break;
21230b57cec5SDimitry Andric   case MVT::i32: Opc = OpcTable[Idx][2]; break;
21240b57cec5SDimitry Andric   case MVT::i64: Opc = OpcTable[Idx][3]; break;
21250b57cec5SDimitry Andric   case MVT::f32: Opc = OpcTable[Idx][4]; break;
21260b57cec5SDimitry Andric   case MVT::f64: Opc = OpcTable[Idx][5]; break;
21270b57cec5SDimitry Andric   }
21280b57cec5SDimitry Andric 
21290b57cec5SDimitry Andric   // Storing an i1 requires special handling.
21300b57cec5SDimitry Andric   if (VTIsi1 && SrcReg != AArch64::WZR) {
2131fe6060f1SDimitry Andric     unsigned ANDReg = emitAnd_ri(MVT::i32, SrcReg, 1);
21320b57cec5SDimitry Andric     assert(ANDReg && "Unexpected AND instruction emission failure.");
21330b57cec5SDimitry Andric     SrcReg = ANDReg;
21340b57cec5SDimitry Andric   }
21350b57cec5SDimitry Andric   // Create the base instruction, then add the operands.
21360b57cec5SDimitry Andric   const MCInstrDesc &II = TII.get(Opc);
21370b57cec5SDimitry Andric   SrcReg = constrainOperandRegClass(II, SrcReg, II.getNumDefs());
21380b57cec5SDimitry Andric   MachineInstrBuilder MIB =
2139bdd1243dSDimitry Andric       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II).addReg(SrcReg);
21400b57cec5SDimitry Andric   addLoadStoreOperands(Addr, MIB, MachineMemOperand::MOStore, ScaleFactor, MMO);
21410b57cec5SDimitry Andric 
21420b57cec5SDimitry Andric   return true;
21430b57cec5SDimitry Andric }
21440b57cec5SDimitry Andric 
21450b57cec5SDimitry Andric bool AArch64FastISel::selectStore(const Instruction *I) {
21460b57cec5SDimitry Andric   MVT VT;
21470b57cec5SDimitry Andric   const Value *Op0 = I->getOperand(0);
21480b57cec5SDimitry Andric   // Verify we have a legal type before going any further.  Currently, we handle
21490b57cec5SDimitry Andric   // simple types that will directly fit in a register (i32/f32/i64/f64) or
21500b57cec5SDimitry Andric   // those that can be sign or zero-extended to a basic operation (i1/i8/i16).
21510b57cec5SDimitry Andric   if (!isTypeSupported(Op0->getType(), VT, /*IsVectorAllowed=*/true))
21520b57cec5SDimitry Andric     return false;
21530b57cec5SDimitry Andric 
21540b57cec5SDimitry Andric   const Value *PtrV = I->getOperand(1);
21550b57cec5SDimitry Andric   if (TLI.supportSwiftError()) {
21560b57cec5SDimitry Andric     // Swifterror values can come from either a function parameter with
21570b57cec5SDimitry Andric     // swifterror attribute or an alloca with swifterror attribute.
21580b57cec5SDimitry Andric     if (const Argument *Arg = dyn_cast<Argument>(PtrV)) {
21590b57cec5SDimitry Andric       if (Arg->hasSwiftErrorAttr())
21600b57cec5SDimitry Andric         return false;
21610b57cec5SDimitry Andric     }
21620b57cec5SDimitry Andric 
21630b57cec5SDimitry Andric     if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(PtrV)) {
21640b57cec5SDimitry Andric       if (Alloca->isSwiftError())
21650b57cec5SDimitry Andric         return false;
21660b57cec5SDimitry Andric     }
21670b57cec5SDimitry Andric   }
21680b57cec5SDimitry Andric 
21690b57cec5SDimitry Andric   // Get the value to be stored into a register. Use the zero register directly
21700b57cec5SDimitry Andric   // when possible to avoid an unnecessary copy and a wasted register.
21710b57cec5SDimitry Andric   unsigned SrcReg = 0;
21720b57cec5SDimitry Andric   if (const auto *CI = dyn_cast<ConstantInt>(Op0)) {
21730b57cec5SDimitry Andric     if (CI->isZero())
21740b57cec5SDimitry Andric       SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
21750b57cec5SDimitry Andric   } else if (const auto *CF = dyn_cast<ConstantFP>(Op0)) {
21760b57cec5SDimitry Andric     if (CF->isZero() && !CF->isNegative()) {
21770b57cec5SDimitry Andric       VT = MVT::getIntegerVT(VT.getSizeInBits());
21780b57cec5SDimitry Andric       SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
21790b57cec5SDimitry Andric     }
21800b57cec5SDimitry Andric   }
21810b57cec5SDimitry Andric 
21820b57cec5SDimitry Andric   if (!SrcReg)
21830b57cec5SDimitry Andric     SrcReg = getRegForValue(Op0);
21840b57cec5SDimitry Andric 
21850b57cec5SDimitry Andric   if (!SrcReg)
21860b57cec5SDimitry Andric     return false;
21870b57cec5SDimitry Andric 
21880b57cec5SDimitry Andric   auto *SI = cast<StoreInst>(I);
21890b57cec5SDimitry Andric 
21900b57cec5SDimitry Andric   // Try to emit a STLR for seq_cst/release.
21910b57cec5SDimitry Andric   if (SI->isAtomic()) {
21920b57cec5SDimitry Andric     AtomicOrdering Ord = SI->getOrdering();
21930b57cec5SDimitry Andric     // The non-atomic instructions are sufficient for relaxed stores.
21940b57cec5SDimitry Andric     if (isReleaseOrStronger(Ord)) {
21950b57cec5SDimitry Andric       // The STLR addressing mode only supports a base reg; pass that directly.
219604eeddc0SDimitry Andric       Register AddrReg = getRegForValue(PtrV);
21970b57cec5SDimitry Andric       return emitStoreRelease(VT, SrcReg, AddrReg,
21980b57cec5SDimitry Andric                               createMachineMemOperandFor(I));
21990b57cec5SDimitry Andric     }
22000b57cec5SDimitry Andric   }
22010b57cec5SDimitry Andric 
22020b57cec5SDimitry Andric   // See if we can handle this address.
22030b57cec5SDimitry Andric   Address Addr;
22040b57cec5SDimitry Andric   if (!computeAddress(PtrV, Addr, Op0->getType()))
22050b57cec5SDimitry Andric     return false;
22060b57cec5SDimitry Andric 
22070b57cec5SDimitry Andric   if (!emitStore(VT, SrcReg, Addr, createMachineMemOperandFor(I)))
22080b57cec5SDimitry Andric     return false;
22090b57cec5SDimitry Andric   return true;
22100b57cec5SDimitry Andric }
22110b57cec5SDimitry Andric 
22120b57cec5SDimitry Andric static AArch64CC::CondCode getCompareCC(CmpInst::Predicate Pred) {
22130b57cec5SDimitry Andric   switch (Pred) {
22140b57cec5SDimitry Andric   case CmpInst::FCMP_ONE:
22150b57cec5SDimitry Andric   case CmpInst::FCMP_UEQ:
22160b57cec5SDimitry Andric   default:
22170b57cec5SDimitry Andric     // AL is our "false" for now. The other two need more compares.
22180b57cec5SDimitry Andric     return AArch64CC::AL;
22190b57cec5SDimitry Andric   case CmpInst::ICMP_EQ:
22200b57cec5SDimitry Andric   case CmpInst::FCMP_OEQ:
22210b57cec5SDimitry Andric     return AArch64CC::EQ;
22220b57cec5SDimitry Andric   case CmpInst::ICMP_SGT:
22230b57cec5SDimitry Andric   case CmpInst::FCMP_OGT:
22240b57cec5SDimitry Andric     return AArch64CC::GT;
22250b57cec5SDimitry Andric   case CmpInst::ICMP_SGE:
22260b57cec5SDimitry Andric   case CmpInst::FCMP_OGE:
22270b57cec5SDimitry Andric     return AArch64CC::GE;
22280b57cec5SDimitry Andric   case CmpInst::ICMP_UGT:
22290b57cec5SDimitry Andric   case CmpInst::FCMP_UGT:
22300b57cec5SDimitry Andric     return AArch64CC::HI;
22310b57cec5SDimitry Andric   case CmpInst::FCMP_OLT:
22320b57cec5SDimitry Andric     return AArch64CC::MI;
22330b57cec5SDimitry Andric   case CmpInst::ICMP_ULE:
22340b57cec5SDimitry Andric   case CmpInst::FCMP_OLE:
22350b57cec5SDimitry Andric     return AArch64CC::LS;
22360b57cec5SDimitry Andric   case CmpInst::FCMP_ORD:
22370b57cec5SDimitry Andric     return AArch64CC::VC;
22380b57cec5SDimitry Andric   case CmpInst::FCMP_UNO:
22390b57cec5SDimitry Andric     return AArch64CC::VS;
22400b57cec5SDimitry Andric   case CmpInst::FCMP_UGE:
22410b57cec5SDimitry Andric     return AArch64CC::PL;
22420b57cec5SDimitry Andric   case CmpInst::ICMP_SLT:
22430b57cec5SDimitry Andric   case CmpInst::FCMP_ULT:
22440b57cec5SDimitry Andric     return AArch64CC::LT;
22450b57cec5SDimitry Andric   case CmpInst::ICMP_SLE:
22460b57cec5SDimitry Andric   case CmpInst::FCMP_ULE:
22470b57cec5SDimitry Andric     return AArch64CC::LE;
22480b57cec5SDimitry Andric   case CmpInst::FCMP_UNE:
22490b57cec5SDimitry Andric   case CmpInst::ICMP_NE:
22500b57cec5SDimitry Andric     return AArch64CC::NE;
22510b57cec5SDimitry Andric   case CmpInst::ICMP_UGE:
22520b57cec5SDimitry Andric     return AArch64CC::HS;
22530b57cec5SDimitry Andric   case CmpInst::ICMP_ULT:
22540b57cec5SDimitry Andric     return AArch64CC::LO;
22550b57cec5SDimitry Andric   }
22560b57cec5SDimitry Andric }
22570b57cec5SDimitry Andric 
22580b57cec5SDimitry Andric /// Try to emit a combined compare-and-branch instruction.
22590b57cec5SDimitry Andric bool AArch64FastISel::emitCompareAndBranch(const BranchInst *BI) {
22600b57cec5SDimitry Andric   // Speculation tracking/SLH assumes that optimized TB(N)Z/CB(N)Z instructions
22610b57cec5SDimitry Andric   // will not be produced, as they are conditional branch instructions that do
22620b57cec5SDimitry Andric   // not set flags.
22630b57cec5SDimitry Andric   if (FuncInfo.MF->getFunction().hasFnAttribute(
22640b57cec5SDimitry Andric           Attribute::SpeculativeLoadHardening))
22650b57cec5SDimitry Andric     return false;
22660b57cec5SDimitry Andric 
22670b57cec5SDimitry Andric   assert(isa<CmpInst>(BI->getCondition()) && "Expected cmp instruction");
22680b57cec5SDimitry Andric   const CmpInst *CI = cast<CmpInst>(BI->getCondition());
22690b57cec5SDimitry Andric   CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);
22700b57cec5SDimitry Andric 
22710b57cec5SDimitry Andric   const Value *LHS = CI->getOperand(0);
22720b57cec5SDimitry Andric   const Value *RHS = CI->getOperand(1);
22730b57cec5SDimitry Andric 
22740b57cec5SDimitry Andric   MVT VT;
22750b57cec5SDimitry Andric   if (!isTypeSupported(LHS->getType(), VT))
22760b57cec5SDimitry Andric     return false;
22770b57cec5SDimitry Andric 
22780b57cec5SDimitry Andric   unsigned BW = VT.getSizeInBits();
22790b57cec5SDimitry Andric   if (BW > 64)
22800b57cec5SDimitry Andric     return false;
22810b57cec5SDimitry Andric 
22820b57cec5SDimitry Andric   MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)];
22830b57cec5SDimitry Andric   MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];
22840b57cec5SDimitry Andric 
22850b57cec5SDimitry Andric   // Try to take advantage of fallthrough opportunities.
22860b57cec5SDimitry Andric   if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
22870b57cec5SDimitry Andric     std::swap(TBB, FBB);
22880b57cec5SDimitry Andric     Predicate = CmpInst::getInversePredicate(Predicate);
22890b57cec5SDimitry Andric   }
22900b57cec5SDimitry Andric 
22910b57cec5SDimitry Andric   int TestBit = -1;
22920b57cec5SDimitry Andric   bool IsCmpNE;
22930b57cec5SDimitry Andric   switch (Predicate) {
22940b57cec5SDimitry Andric   default:
22950b57cec5SDimitry Andric     return false;
22960b57cec5SDimitry Andric   case CmpInst::ICMP_EQ:
22970b57cec5SDimitry Andric   case CmpInst::ICMP_NE:
22980b57cec5SDimitry Andric     if (isa<Constant>(LHS) && cast<Constant>(LHS)->isNullValue())
22990b57cec5SDimitry Andric       std::swap(LHS, RHS);
23000b57cec5SDimitry Andric 
23010b57cec5SDimitry Andric     if (!isa<Constant>(RHS) || !cast<Constant>(RHS)->isNullValue())
23020b57cec5SDimitry Andric       return false;
23030b57cec5SDimitry Andric 
23040b57cec5SDimitry Andric     if (const auto *AI = dyn_cast<BinaryOperator>(LHS))
23050b57cec5SDimitry Andric       if (AI->getOpcode() == Instruction::And && isValueAvailable(AI)) {
23060b57cec5SDimitry Andric         const Value *AndLHS = AI->getOperand(0);
23070b57cec5SDimitry Andric         const Value *AndRHS = AI->getOperand(1);
23080b57cec5SDimitry Andric 
23090b57cec5SDimitry Andric         if (const auto *C = dyn_cast<ConstantInt>(AndLHS))
23100b57cec5SDimitry Andric           if (C->getValue().isPowerOf2())
23110b57cec5SDimitry Andric             std::swap(AndLHS, AndRHS);
23120b57cec5SDimitry Andric 
23130b57cec5SDimitry Andric         if (const auto *C = dyn_cast<ConstantInt>(AndRHS))
23140b57cec5SDimitry Andric           if (C->getValue().isPowerOf2()) {
23150b57cec5SDimitry Andric             TestBit = C->getValue().logBase2();
23160b57cec5SDimitry Andric             LHS = AndLHS;
23170b57cec5SDimitry Andric           }
23180b57cec5SDimitry Andric       }
23190b57cec5SDimitry Andric 
23200b57cec5SDimitry Andric     if (VT == MVT::i1)
23210b57cec5SDimitry Andric       TestBit = 0;
23220b57cec5SDimitry Andric 
23230b57cec5SDimitry Andric     IsCmpNE = Predicate == CmpInst::ICMP_NE;
23240b57cec5SDimitry Andric     break;
23250b57cec5SDimitry Andric   case CmpInst::ICMP_SLT:
23260b57cec5SDimitry Andric   case CmpInst::ICMP_SGE:
23270b57cec5SDimitry Andric     if (!isa<Constant>(RHS) || !cast<Constant>(RHS)->isNullValue())
23280b57cec5SDimitry Andric       return false;
23290b57cec5SDimitry Andric 
23300b57cec5SDimitry Andric     TestBit = BW - 1;
23310b57cec5SDimitry Andric     IsCmpNE = Predicate == CmpInst::ICMP_SLT;
23320b57cec5SDimitry Andric     break;
23330b57cec5SDimitry Andric   case CmpInst::ICMP_SGT:
23340b57cec5SDimitry Andric   case CmpInst::ICMP_SLE:
23350b57cec5SDimitry Andric     if (!isa<ConstantInt>(RHS))
23360b57cec5SDimitry Andric       return false;
23370b57cec5SDimitry Andric 
23380b57cec5SDimitry Andric     if (cast<ConstantInt>(RHS)->getValue() != APInt(BW, -1, true))
23390b57cec5SDimitry Andric       return false;
23400b57cec5SDimitry Andric 
23410b57cec5SDimitry Andric     TestBit = BW - 1;
23420b57cec5SDimitry Andric     IsCmpNE = Predicate == CmpInst::ICMP_SLE;
23430b57cec5SDimitry Andric     break;
23440b57cec5SDimitry Andric   } // end switch
23450b57cec5SDimitry Andric 
23460b57cec5SDimitry Andric   static const unsigned OpcTable[2][2][2] = {
23470b57cec5SDimitry Andric     { {AArch64::CBZW,  AArch64::CBZX },
23480b57cec5SDimitry Andric       {AArch64::CBNZW, AArch64::CBNZX} },
23490b57cec5SDimitry Andric     { {AArch64::TBZW,  AArch64::TBZX },
23500b57cec5SDimitry Andric       {AArch64::TBNZW, AArch64::TBNZX} }
23510b57cec5SDimitry Andric   };
23520b57cec5SDimitry Andric 
23530b57cec5SDimitry Andric   bool IsBitTest = TestBit != -1;
23540b57cec5SDimitry Andric   bool Is64Bit = BW == 64;
23550b57cec5SDimitry Andric   if (TestBit < 32 && TestBit >= 0)
23560b57cec5SDimitry Andric     Is64Bit = false;
23570b57cec5SDimitry Andric 
23580b57cec5SDimitry Andric   unsigned Opc = OpcTable[IsBitTest][IsCmpNE][Is64Bit];
23590b57cec5SDimitry Andric   const MCInstrDesc &II = TII.get(Opc);
23600b57cec5SDimitry Andric 
236104eeddc0SDimitry Andric   Register SrcReg = getRegForValue(LHS);
23620b57cec5SDimitry Andric   if (!SrcReg)
23630b57cec5SDimitry Andric     return false;
23640b57cec5SDimitry Andric 
23650b57cec5SDimitry Andric   if (BW == 64 && !Is64Bit)
2366fe6060f1SDimitry Andric     SrcReg = fastEmitInst_extractsubreg(MVT::i32, SrcReg, AArch64::sub_32);
23670b57cec5SDimitry Andric 
23680b57cec5SDimitry Andric   if ((BW < 32) && !IsBitTest)
23690b57cec5SDimitry Andric     SrcReg = emitIntExt(VT, SrcReg, MVT::i32, /*isZExt=*/true);
23700b57cec5SDimitry Andric 
23710b57cec5SDimitry Andric   // Emit the combined compare and branch instruction.
23720b57cec5SDimitry Andric   SrcReg = constrainOperandRegClass(II, SrcReg,  II.getNumDefs());
23730b57cec5SDimitry Andric   MachineInstrBuilder MIB =
2374bdd1243dSDimitry Andric       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc))
2375fe6060f1SDimitry Andric           .addReg(SrcReg);
23760b57cec5SDimitry Andric   if (IsBitTest)
23770b57cec5SDimitry Andric     MIB.addImm(TestBit);
23780b57cec5SDimitry Andric   MIB.addMBB(TBB);
23790b57cec5SDimitry Andric 
23800b57cec5SDimitry Andric   finishCondBranch(BI->getParent(), TBB, FBB);
23810b57cec5SDimitry Andric   return true;
23820b57cec5SDimitry Andric }
23830b57cec5SDimitry Andric 
23840b57cec5SDimitry Andric bool AArch64FastISel::selectBranch(const Instruction *I) {
23850b57cec5SDimitry Andric   const BranchInst *BI = cast<BranchInst>(I);
23860b57cec5SDimitry Andric   if (BI->isUnconditional()) {
23870b57cec5SDimitry Andric     MachineBasicBlock *MSucc = FuncInfo.MBBMap[BI->getSuccessor(0)];
23880b57cec5SDimitry Andric     fastEmitBranch(MSucc, BI->getDebugLoc());
23890b57cec5SDimitry Andric     return true;
23900b57cec5SDimitry Andric   }
23910b57cec5SDimitry Andric 
23920b57cec5SDimitry Andric   MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)];
23930b57cec5SDimitry Andric   MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];
23940b57cec5SDimitry Andric 
23950b57cec5SDimitry Andric   if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) {
23960b57cec5SDimitry Andric     if (CI->hasOneUse() && isValueAvailable(CI)) {
23970b57cec5SDimitry Andric       // Try to optimize or fold the cmp.
23980b57cec5SDimitry Andric       CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);
23990b57cec5SDimitry Andric       switch (Predicate) {
24000b57cec5SDimitry Andric       default:
24010b57cec5SDimitry Andric         break;
24020b57cec5SDimitry Andric       case CmpInst::FCMP_FALSE:
2403bdd1243dSDimitry Andric         fastEmitBranch(FBB, MIMD.getDL());
24040b57cec5SDimitry Andric         return true;
24050b57cec5SDimitry Andric       case CmpInst::FCMP_TRUE:
2406bdd1243dSDimitry Andric         fastEmitBranch(TBB, MIMD.getDL());
24070b57cec5SDimitry Andric         return true;
24080b57cec5SDimitry Andric       }
24090b57cec5SDimitry Andric 
24100b57cec5SDimitry Andric       // Try to emit a combined compare-and-branch first.
24110b57cec5SDimitry Andric       if (emitCompareAndBranch(BI))
24120b57cec5SDimitry Andric         return true;
24130b57cec5SDimitry Andric 
24140b57cec5SDimitry Andric       // Try to take advantage of fallthrough opportunities.
24150b57cec5SDimitry Andric       if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
24160b57cec5SDimitry Andric         std::swap(TBB, FBB);
24170b57cec5SDimitry Andric         Predicate = CmpInst::getInversePredicate(Predicate);
24180b57cec5SDimitry Andric       }
24190b57cec5SDimitry Andric 
24200b57cec5SDimitry Andric       // Emit the cmp.
24210b57cec5SDimitry Andric       if (!emitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned()))
24220b57cec5SDimitry Andric         return false;
24230b57cec5SDimitry Andric 
24240b57cec5SDimitry Andric       // FCMP_UEQ and FCMP_ONE cannot be checked with a single branch
24250b57cec5SDimitry Andric       // instruction.
24260b57cec5SDimitry Andric       AArch64CC::CondCode CC = getCompareCC(Predicate);
24270b57cec5SDimitry Andric       AArch64CC::CondCode ExtraCC = AArch64CC::AL;
24280b57cec5SDimitry Andric       switch (Predicate) {
24290b57cec5SDimitry Andric       default:
24300b57cec5SDimitry Andric         break;
24310b57cec5SDimitry Andric       case CmpInst::FCMP_UEQ:
24320b57cec5SDimitry Andric         ExtraCC = AArch64CC::EQ;
24330b57cec5SDimitry Andric         CC = AArch64CC::VS;
24340b57cec5SDimitry Andric         break;
24350b57cec5SDimitry Andric       case CmpInst::FCMP_ONE:
24360b57cec5SDimitry Andric         ExtraCC = AArch64CC::MI;
24370b57cec5SDimitry Andric         CC = AArch64CC::GT;
24380b57cec5SDimitry Andric         break;
24390b57cec5SDimitry Andric       }
24400b57cec5SDimitry Andric       assert((CC != AArch64CC::AL) && "Unexpected condition code.");
24410b57cec5SDimitry Andric 
24420b57cec5SDimitry Andric       // Emit the extra branch for FCMP_UEQ and FCMP_ONE.
24430b57cec5SDimitry Andric       if (ExtraCC != AArch64CC::AL) {
2444bdd1243dSDimitry Andric         BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::Bcc))
24450b57cec5SDimitry Andric             .addImm(ExtraCC)
24460b57cec5SDimitry Andric             .addMBB(TBB);
24470b57cec5SDimitry Andric       }
24480b57cec5SDimitry Andric 
24490b57cec5SDimitry Andric       // Emit the branch.
2450bdd1243dSDimitry Andric       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::Bcc))
24510b57cec5SDimitry Andric           .addImm(CC)
24520b57cec5SDimitry Andric           .addMBB(TBB);
24530b57cec5SDimitry Andric 
24540b57cec5SDimitry Andric       finishCondBranch(BI->getParent(), TBB, FBB);
24550b57cec5SDimitry Andric       return true;
24560b57cec5SDimitry Andric     }
24570b57cec5SDimitry Andric   } else if (const auto *CI = dyn_cast<ConstantInt>(BI->getCondition())) {
24580b57cec5SDimitry Andric     uint64_t Imm = CI->getZExtValue();
24590b57cec5SDimitry Andric     MachineBasicBlock *Target = (Imm == 0) ? FBB : TBB;
2460bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::B))
24610b57cec5SDimitry Andric         .addMBB(Target);
24620b57cec5SDimitry Andric 
24630b57cec5SDimitry Andric     // Obtain the branch probability and add the target to the successor list.
24640b57cec5SDimitry Andric     if (FuncInfo.BPI) {
24650b57cec5SDimitry Andric       auto BranchProbability = FuncInfo.BPI->getEdgeProbability(
24660b57cec5SDimitry Andric           BI->getParent(), Target->getBasicBlock());
24670b57cec5SDimitry Andric       FuncInfo.MBB->addSuccessor(Target, BranchProbability);
24680b57cec5SDimitry Andric     } else
24690b57cec5SDimitry Andric       FuncInfo.MBB->addSuccessorWithoutProb(Target);
24700b57cec5SDimitry Andric     return true;
24710b57cec5SDimitry Andric   } else {
24720b57cec5SDimitry Andric     AArch64CC::CondCode CC = AArch64CC::NE;
24730b57cec5SDimitry Andric     if (foldXALUIntrinsic(CC, I, BI->getCondition())) {
24740b57cec5SDimitry Andric       // Fake request the condition, otherwise the intrinsic might be completely
24750b57cec5SDimitry Andric       // optimized away.
247604eeddc0SDimitry Andric       Register CondReg = getRegForValue(BI->getCondition());
24770b57cec5SDimitry Andric       if (!CondReg)
24780b57cec5SDimitry Andric         return false;
24790b57cec5SDimitry Andric 
24800b57cec5SDimitry Andric       // Emit the branch.
2481bdd1243dSDimitry Andric       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::Bcc))
24820b57cec5SDimitry Andric         .addImm(CC)
24830b57cec5SDimitry Andric         .addMBB(TBB);
24840b57cec5SDimitry Andric 
24850b57cec5SDimitry Andric       finishCondBranch(BI->getParent(), TBB, FBB);
24860b57cec5SDimitry Andric       return true;
24870b57cec5SDimitry Andric     }
24880b57cec5SDimitry Andric   }
24890b57cec5SDimitry Andric 
249004eeddc0SDimitry Andric   Register CondReg = getRegForValue(BI->getCondition());
24910b57cec5SDimitry Andric   if (CondReg == 0)
24920b57cec5SDimitry Andric     return false;
24930b57cec5SDimitry Andric 
24940b57cec5SDimitry Andric   // i1 conditions come as i32 values, test the lowest bit with tb(n)z.
24950b57cec5SDimitry Andric   unsigned Opcode = AArch64::TBNZW;
24960b57cec5SDimitry Andric   if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
24970b57cec5SDimitry Andric     std::swap(TBB, FBB);
24980b57cec5SDimitry Andric     Opcode = AArch64::TBZW;
24990b57cec5SDimitry Andric   }
25000b57cec5SDimitry Andric 
25010b57cec5SDimitry Andric   const MCInstrDesc &II = TII.get(Opcode);
250204eeddc0SDimitry Andric   Register ConstrainedCondReg
25030b57cec5SDimitry Andric     = constrainOperandRegClass(II, CondReg, II.getNumDefs());
2504bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)
2505fe6060f1SDimitry Andric       .addReg(ConstrainedCondReg)
25060b57cec5SDimitry Andric       .addImm(0)
25070b57cec5SDimitry Andric       .addMBB(TBB);
25080b57cec5SDimitry Andric 
25090b57cec5SDimitry Andric   finishCondBranch(BI->getParent(), TBB, FBB);
25100b57cec5SDimitry Andric   return true;
25110b57cec5SDimitry Andric }
25120b57cec5SDimitry Andric 
25130b57cec5SDimitry Andric bool AArch64FastISel::selectIndirectBr(const Instruction *I) {
25140b57cec5SDimitry Andric   const IndirectBrInst *BI = cast<IndirectBrInst>(I);
251504eeddc0SDimitry Andric   Register AddrReg = getRegForValue(BI->getOperand(0));
25160b57cec5SDimitry Andric   if (AddrReg == 0)
25170b57cec5SDimitry Andric     return false;
25180b57cec5SDimitry Andric 
2519*0fca6ea1SDimitry Andric   // Authenticated indirectbr is not implemented yet.
2520*0fca6ea1SDimitry Andric   if (FuncInfo.MF->getFunction().hasFnAttribute("ptrauth-indirect-gotos"))
2521*0fca6ea1SDimitry Andric     return false;
2522*0fca6ea1SDimitry Andric 
25230b57cec5SDimitry Andric   // Emit the indirect branch.
25240b57cec5SDimitry Andric   const MCInstrDesc &II = TII.get(AArch64::BR);
25250b57cec5SDimitry Andric   AddrReg = constrainOperandRegClass(II, AddrReg,  II.getNumDefs());
2526bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II).addReg(AddrReg);
25270b57cec5SDimitry Andric 
25280b57cec5SDimitry Andric   // Make sure the CFG is up-to-date.
2529bdd1243dSDimitry Andric   for (const auto *Succ : BI->successors())
25300b57cec5SDimitry Andric     FuncInfo.MBB->addSuccessor(FuncInfo.MBBMap[Succ]);
25310b57cec5SDimitry Andric 
25320b57cec5SDimitry Andric   return true;
25330b57cec5SDimitry Andric }
25340b57cec5SDimitry Andric 
25350b57cec5SDimitry Andric bool AArch64FastISel::selectCmp(const Instruction *I) {
25360b57cec5SDimitry Andric   const CmpInst *CI = cast<CmpInst>(I);
25370b57cec5SDimitry Andric 
25380b57cec5SDimitry Andric   // Vectors of i1 are weird: bail out.
25390b57cec5SDimitry Andric   if (CI->getType()->isVectorTy())
25400b57cec5SDimitry Andric     return false;
25410b57cec5SDimitry Andric 
25420b57cec5SDimitry Andric   // Try to optimize or fold the cmp.
25430b57cec5SDimitry Andric   CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);
25440b57cec5SDimitry Andric   unsigned ResultReg = 0;
25450b57cec5SDimitry Andric   switch (Predicate) {
25460b57cec5SDimitry Andric   default:
25470b57cec5SDimitry Andric     break;
25480b57cec5SDimitry Andric   case CmpInst::FCMP_FALSE:
25490b57cec5SDimitry Andric     ResultReg = createResultReg(&AArch64::GPR32RegClass);
2550bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
25510b57cec5SDimitry Andric             TII.get(TargetOpcode::COPY), ResultReg)
25520b57cec5SDimitry Andric         .addReg(AArch64::WZR, getKillRegState(true));
25530b57cec5SDimitry Andric     break;
25540b57cec5SDimitry Andric   case CmpInst::FCMP_TRUE:
25550b57cec5SDimitry Andric     ResultReg = fastEmit_i(MVT::i32, MVT::i32, ISD::Constant, 1);
25560b57cec5SDimitry Andric     break;
25570b57cec5SDimitry Andric   }
25580b57cec5SDimitry Andric 
25590b57cec5SDimitry Andric   if (ResultReg) {
25600b57cec5SDimitry Andric     updateValueMap(I, ResultReg);
25610b57cec5SDimitry Andric     return true;
25620b57cec5SDimitry Andric   }
25630b57cec5SDimitry Andric 
25640b57cec5SDimitry Andric   // Emit the cmp.
25650b57cec5SDimitry Andric   if (!emitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned()))
25660b57cec5SDimitry Andric     return false;
25670b57cec5SDimitry Andric 
25680b57cec5SDimitry Andric   ResultReg = createResultReg(&AArch64::GPR32RegClass);
25690b57cec5SDimitry Andric 
25700b57cec5SDimitry Andric   // FCMP_UEQ and FCMP_ONE cannot be checked with a single instruction. These
25710b57cec5SDimitry Andric   // condition codes are inverted, because they are used by CSINC.
25720b57cec5SDimitry Andric   static unsigned CondCodeTable[2][2] = {
25730b57cec5SDimitry Andric     { AArch64CC::NE, AArch64CC::VC },
25740b57cec5SDimitry Andric     { AArch64CC::PL, AArch64CC::LE }
25750b57cec5SDimitry Andric   };
25760b57cec5SDimitry Andric   unsigned *CondCodes = nullptr;
25770b57cec5SDimitry Andric   switch (Predicate) {
25780b57cec5SDimitry Andric   default:
25790b57cec5SDimitry Andric     break;
25800b57cec5SDimitry Andric   case CmpInst::FCMP_UEQ:
25810b57cec5SDimitry Andric     CondCodes = &CondCodeTable[0][0];
25820b57cec5SDimitry Andric     break;
25830b57cec5SDimitry Andric   case CmpInst::FCMP_ONE:
25840b57cec5SDimitry Andric     CondCodes = &CondCodeTable[1][0];
25850b57cec5SDimitry Andric     break;
25860b57cec5SDimitry Andric   }
25870b57cec5SDimitry Andric 
25880b57cec5SDimitry Andric   if (CondCodes) {
258904eeddc0SDimitry Andric     Register TmpReg1 = createResultReg(&AArch64::GPR32RegClass);
2590bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::CSINCWr),
25910b57cec5SDimitry Andric             TmpReg1)
25920b57cec5SDimitry Andric         .addReg(AArch64::WZR, getKillRegState(true))
25930b57cec5SDimitry Andric         .addReg(AArch64::WZR, getKillRegState(true))
25940b57cec5SDimitry Andric         .addImm(CondCodes[0]);
2595bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::CSINCWr),
25960b57cec5SDimitry Andric             ResultReg)
25970b57cec5SDimitry Andric         .addReg(TmpReg1, getKillRegState(true))
25980b57cec5SDimitry Andric         .addReg(AArch64::WZR, getKillRegState(true))
25990b57cec5SDimitry Andric         .addImm(CondCodes[1]);
26000b57cec5SDimitry Andric 
26010b57cec5SDimitry Andric     updateValueMap(I, ResultReg);
26020b57cec5SDimitry Andric     return true;
26030b57cec5SDimitry Andric   }
26040b57cec5SDimitry Andric 
26050b57cec5SDimitry Andric   // Now set a register based on the comparison.
26060b57cec5SDimitry Andric   AArch64CC::CondCode CC = getCompareCC(Predicate);
26070b57cec5SDimitry Andric   assert((CC != AArch64CC::AL) && "Unexpected condition code.");
26080b57cec5SDimitry Andric   AArch64CC::CondCode invertedCC = getInvertedCondCode(CC);
2609bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::CSINCWr),
26100b57cec5SDimitry Andric           ResultReg)
26110b57cec5SDimitry Andric       .addReg(AArch64::WZR, getKillRegState(true))
26120b57cec5SDimitry Andric       .addReg(AArch64::WZR, getKillRegState(true))
26130b57cec5SDimitry Andric       .addImm(invertedCC);
26140b57cec5SDimitry Andric 
26150b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
26160b57cec5SDimitry Andric   return true;
26170b57cec5SDimitry Andric }
26180b57cec5SDimitry Andric 
26190b57cec5SDimitry Andric /// Optimize selects of i1 if one of the operands has a 'true' or 'false'
26200b57cec5SDimitry Andric /// value.
26210b57cec5SDimitry Andric bool AArch64FastISel::optimizeSelect(const SelectInst *SI) {
26220b57cec5SDimitry Andric   if (!SI->getType()->isIntegerTy(1))
26230b57cec5SDimitry Andric     return false;
26240b57cec5SDimitry Andric 
26250b57cec5SDimitry Andric   const Value *Src1Val, *Src2Val;
26260b57cec5SDimitry Andric   unsigned Opc = 0;
26270b57cec5SDimitry Andric   bool NeedExtraOp = false;
26280b57cec5SDimitry Andric   if (auto *CI = dyn_cast<ConstantInt>(SI->getTrueValue())) {
26290b57cec5SDimitry Andric     if (CI->isOne()) {
26300b57cec5SDimitry Andric       Src1Val = SI->getCondition();
26310b57cec5SDimitry Andric       Src2Val = SI->getFalseValue();
26320b57cec5SDimitry Andric       Opc = AArch64::ORRWrr;
26330b57cec5SDimitry Andric     } else {
26340b57cec5SDimitry Andric       assert(CI->isZero());
26350b57cec5SDimitry Andric       Src1Val = SI->getFalseValue();
26360b57cec5SDimitry Andric       Src2Val = SI->getCondition();
26370b57cec5SDimitry Andric       Opc = AArch64::BICWrr;
26380b57cec5SDimitry Andric     }
26390b57cec5SDimitry Andric   } else if (auto *CI = dyn_cast<ConstantInt>(SI->getFalseValue())) {
26400b57cec5SDimitry Andric     if (CI->isOne()) {
26410b57cec5SDimitry Andric       Src1Val = SI->getCondition();
26420b57cec5SDimitry Andric       Src2Val = SI->getTrueValue();
26430b57cec5SDimitry Andric       Opc = AArch64::ORRWrr;
26440b57cec5SDimitry Andric       NeedExtraOp = true;
26450b57cec5SDimitry Andric     } else {
26460b57cec5SDimitry Andric       assert(CI->isZero());
26470b57cec5SDimitry Andric       Src1Val = SI->getCondition();
26480b57cec5SDimitry Andric       Src2Val = SI->getTrueValue();
26490b57cec5SDimitry Andric       Opc = AArch64::ANDWrr;
26500b57cec5SDimitry Andric     }
26510b57cec5SDimitry Andric   }
26520b57cec5SDimitry Andric 
26530b57cec5SDimitry Andric   if (!Opc)
26540b57cec5SDimitry Andric     return false;
26550b57cec5SDimitry Andric 
265604eeddc0SDimitry Andric   Register Src1Reg = getRegForValue(Src1Val);
26570b57cec5SDimitry Andric   if (!Src1Reg)
26580b57cec5SDimitry Andric     return false;
26590b57cec5SDimitry Andric 
266004eeddc0SDimitry Andric   Register Src2Reg = getRegForValue(Src2Val);
26610b57cec5SDimitry Andric   if (!Src2Reg)
26620b57cec5SDimitry Andric     return false;
26630b57cec5SDimitry Andric 
2664fe6060f1SDimitry Andric   if (NeedExtraOp)
2665fe6060f1SDimitry Andric     Src1Reg = emitLogicalOp_ri(ISD::XOR, MVT::i32, Src1Reg, 1);
2666fe6060f1SDimitry Andric 
266704eeddc0SDimitry Andric   Register ResultReg = fastEmitInst_rr(Opc, &AArch64::GPR32RegClass, Src1Reg,
2668fe6060f1SDimitry Andric                                        Src2Reg);
26690b57cec5SDimitry Andric   updateValueMap(SI, ResultReg);
26700b57cec5SDimitry Andric   return true;
26710b57cec5SDimitry Andric }
26720b57cec5SDimitry Andric 
26730b57cec5SDimitry Andric bool AArch64FastISel::selectSelect(const Instruction *I) {
26740b57cec5SDimitry Andric   assert(isa<SelectInst>(I) && "Expected a select instruction.");
26750b57cec5SDimitry Andric   MVT VT;
26760b57cec5SDimitry Andric   if (!isTypeSupported(I->getType(), VT))
26770b57cec5SDimitry Andric     return false;
26780b57cec5SDimitry Andric 
26790b57cec5SDimitry Andric   unsigned Opc;
26800b57cec5SDimitry Andric   const TargetRegisterClass *RC;
26810b57cec5SDimitry Andric   switch (VT.SimpleTy) {
26820b57cec5SDimitry Andric   default:
26830b57cec5SDimitry Andric     return false;
26840b57cec5SDimitry Andric   case MVT::i1:
26850b57cec5SDimitry Andric   case MVT::i8:
26860b57cec5SDimitry Andric   case MVT::i16:
26870b57cec5SDimitry Andric   case MVT::i32:
26880b57cec5SDimitry Andric     Opc = AArch64::CSELWr;
26890b57cec5SDimitry Andric     RC = &AArch64::GPR32RegClass;
26900b57cec5SDimitry Andric     break;
26910b57cec5SDimitry Andric   case MVT::i64:
26920b57cec5SDimitry Andric     Opc = AArch64::CSELXr;
26930b57cec5SDimitry Andric     RC = &AArch64::GPR64RegClass;
26940b57cec5SDimitry Andric     break;
26950b57cec5SDimitry Andric   case MVT::f32:
26960b57cec5SDimitry Andric     Opc = AArch64::FCSELSrrr;
26970b57cec5SDimitry Andric     RC = &AArch64::FPR32RegClass;
26980b57cec5SDimitry Andric     break;
26990b57cec5SDimitry Andric   case MVT::f64:
27000b57cec5SDimitry Andric     Opc = AArch64::FCSELDrrr;
27010b57cec5SDimitry Andric     RC = &AArch64::FPR64RegClass;
27020b57cec5SDimitry Andric     break;
27030b57cec5SDimitry Andric   }
27040b57cec5SDimitry Andric 
27050b57cec5SDimitry Andric   const SelectInst *SI = cast<SelectInst>(I);
27060b57cec5SDimitry Andric   const Value *Cond = SI->getCondition();
27070b57cec5SDimitry Andric   AArch64CC::CondCode CC = AArch64CC::NE;
27080b57cec5SDimitry Andric   AArch64CC::CondCode ExtraCC = AArch64CC::AL;
27090b57cec5SDimitry Andric 
27100b57cec5SDimitry Andric   if (optimizeSelect(SI))
27110b57cec5SDimitry Andric     return true;
27120b57cec5SDimitry Andric 
27130b57cec5SDimitry Andric   // Try to pickup the flags, so we don't have to emit another compare.
27140b57cec5SDimitry Andric   if (foldXALUIntrinsic(CC, I, Cond)) {
27150b57cec5SDimitry Andric     // Fake request the condition to force emission of the XALU intrinsic.
271604eeddc0SDimitry Andric     Register CondReg = getRegForValue(Cond);
27170b57cec5SDimitry Andric     if (!CondReg)
27180b57cec5SDimitry Andric       return false;
27190b57cec5SDimitry Andric   } else if (isa<CmpInst>(Cond) && cast<CmpInst>(Cond)->hasOneUse() &&
27200b57cec5SDimitry Andric              isValueAvailable(Cond)) {
27210b57cec5SDimitry Andric     const auto *Cmp = cast<CmpInst>(Cond);
27220b57cec5SDimitry Andric     // Try to optimize or fold the cmp.
27230b57cec5SDimitry Andric     CmpInst::Predicate Predicate = optimizeCmpPredicate(Cmp);
27240b57cec5SDimitry Andric     const Value *FoldSelect = nullptr;
27250b57cec5SDimitry Andric     switch (Predicate) {
27260b57cec5SDimitry Andric     default:
27270b57cec5SDimitry Andric       break;
27280b57cec5SDimitry Andric     case CmpInst::FCMP_FALSE:
27290b57cec5SDimitry Andric       FoldSelect = SI->getFalseValue();
27300b57cec5SDimitry Andric       break;
27310b57cec5SDimitry Andric     case CmpInst::FCMP_TRUE:
27320b57cec5SDimitry Andric       FoldSelect = SI->getTrueValue();
27330b57cec5SDimitry Andric       break;
27340b57cec5SDimitry Andric     }
27350b57cec5SDimitry Andric 
27360b57cec5SDimitry Andric     if (FoldSelect) {
273704eeddc0SDimitry Andric       Register SrcReg = getRegForValue(FoldSelect);
27380b57cec5SDimitry Andric       if (!SrcReg)
27390b57cec5SDimitry Andric         return false;
27400b57cec5SDimitry Andric 
27410b57cec5SDimitry Andric       updateValueMap(I, SrcReg);
27420b57cec5SDimitry Andric       return true;
27430b57cec5SDimitry Andric     }
27440b57cec5SDimitry Andric 
27450b57cec5SDimitry Andric     // Emit the cmp.
27460b57cec5SDimitry Andric     if (!emitCmp(Cmp->getOperand(0), Cmp->getOperand(1), Cmp->isUnsigned()))
27470b57cec5SDimitry Andric       return false;
27480b57cec5SDimitry Andric 
27490b57cec5SDimitry Andric     // FCMP_UEQ and FCMP_ONE cannot be checked with a single select instruction.
27500b57cec5SDimitry Andric     CC = getCompareCC(Predicate);
27510b57cec5SDimitry Andric     switch (Predicate) {
27520b57cec5SDimitry Andric     default:
27530b57cec5SDimitry Andric       break;
27540b57cec5SDimitry Andric     case CmpInst::FCMP_UEQ:
27550b57cec5SDimitry Andric       ExtraCC = AArch64CC::EQ;
27560b57cec5SDimitry Andric       CC = AArch64CC::VS;
27570b57cec5SDimitry Andric       break;
27580b57cec5SDimitry Andric     case CmpInst::FCMP_ONE:
27590b57cec5SDimitry Andric       ExtraCC = AArch64CC::MI;
27600b57cec5SDimitry Andric       CC = AArch64CC::GT;
27610b57cec5SDimitry Andric       break;
27620b57cec5SDimitry Andric     }
27630b57cec5SDimitry Andric     assert((CC != AArch64CC::AL) && "Unexpected condition code.");
27640b57cec5SDimitry Andric   } else {
276504eeddc0SDimitry Andric     Register CondReg = getRegForValue(Cond);
27660b57cec5SDimitry Andric     if (!CondReg)
27670b57cec5SDimitry Andric       return false;
27680b57cec5SDimitry Andric 
27690b57cec5SDimitry Andric     const MCInstrDesc &II = TII.get(AArch64::ANDSWri);
27700b57cec5SDimitry Andric     CondReg = constrainOperandRegClass(II, CondReg, 1);
27710b57cec5SDimitry Andric 
27720b57cec5SDimitry Andric     // Emit a TST instruction (ANDS wzr, reg, #imm).
2773bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II,
27740b57cec5SDimitry Andric             AArch64::WZR)
2775fe6060f1SDimitry Andric         .addReg(CondReg)
27760b57cec5SDimitry Andric         .addImm(AArch64_AM::encodeLogicalImmediate(1, 32));
27770b57cec5SDimitry Andric   }
27780b57cec5SDimitry Andric 
277904eeddc0SDimitry Andric   Register Src1Reg = getRegForValue(SI->getTrueValue());
278004eeddc0SDimitry Andric   Register Src2Reg = getRegForValue(SI->getFalseValue());
27810b57cec5SDimitry Andric 
27820b57cec5SDimitry Andric   if (!Src1Reg || !Src2Reg)
27830b57cec5SDimitry Andric     return false;
27840b57cec5SDimitry Andric 
2785fe6060f1SDimitry Andric   if (ExtraCC != AArch64CC::AL)
2786fe6060f1SDimitry Andric     Src2Reg = fastEmitInst_rri(Opc, RC, Src1Reg, Src2Reg, ExtraCC);
2787fe6060f1SDimitry Andric 
278804eeddc0SDimitry Andric   Register ResultReg = fastEmitInst_rri(Opc, RC, Src1Reg, Src2Reg, CC);
27890b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
27900b57cec5SDimitry Andric   return true;
27910b57cec5SDimitry Andric }
27920b57cec5SDimitry Andric 
27930b57cec5SDimitry Andric bool AArch64FastISel::selectFPExt(const Instruction *I) {
27940b57cec5SDimitry Andric   Value *V = I->getOperand(0);
27950b57cec5SDimitry Andric   if (!I->getType()->isDoubleTy() || !V->getType()->isFloatTy())
27960b57cec5SDimitry Andric     return false;
27970b57cec5SDimitry Andric 
279804eeddc0SDimitry Andric   Register Op = getRegForValue(V);
27990b57cec5SDimitry Andric   if (Op == 0)
28000b57cec5SDimitry Andric     return false;
28010b57cec5SDimitry Andric 
280204eeddc0SDimitry Andric   Register ResultReg = createResultReg(&AArch64::FPR64RegClass);
2803bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::FCVTDSr),
28040b57cec5SDimitry Andric           ResultReg).addReg(Op);
28050b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
28060b57cec5SDimitry Andric   return true;
28070b57cec5SDimitry Andric }
28080b57cec5SDimitry Andric 
28090b57cec5SDimitry Andric bool AArch64FastISel::selectFPTrunc(const Instruction *I) {
28100b57cec5SDimitry Andric   Value *V = I->getOperand(0);
28110b57cec5SDimitry Andric   if (!I->getType()->isFloatTy() || !V->getType()->isDoubleTy())
28120b57cec5SDimitry Andric     return false;
28130b57cec5SDimitry Andric 
281404eeddc0SDimitry Andric   Register Op = getRegForValue(V);
28150b57cec5SDimitry Andric   if (Op == 0)
28160b57cec5SDimitry Andric     return false;
28170b57cec5SDimitry Andric 
281804eeddc0SDimitry Andric   Register ResultReg = createResultReg(&AArch64::FPR32RegClass);
2819bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::FCVTSDr),
28200b57cec5SDimitry Andric           ResultReg).addReg(Op);
28210b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
28220b57cec5SDimitry Andric   return true;
28230b57cec5SDimitry Andric }
28240b57cec5SDimitry Andric 
28250b57cec5SDimitry Andric // FPToUI and FPToSI
28260b57cec5SDimitry Andric bool AArch64FastISel::selectFPToInt(const Instruction *I, bool Signed) {
28270b57cec5SDimitry Andric   MVT DestVT;
28280b57cec5SDimitry Andric   if (!isTypeLegal(I->getType(), DestVT) || DestVT.isVector())
28290b57cec5SDimitry Andric     return false;
28300b57cec5SDimitry Andric 
283104eeddc0SDimitry Andric   Register SrcReg = getRegForValue(I->getOperand(0));
28320b57cec5SDimitry Andric   if (SrcReg == 0)
28330b57cec5SDimitry Andric     return false;
28340b57cec5SDimitry Andric 
28350b57cec5SDimitry Andric   EVT SrcVT = TLI.getValueType(DL, I->getOperand(0)->getType(), true);
2836*0fca6ea1SDimitry Andric   if (SrcVT == MVT::f128 || SrcVT == MVT::f16 || SrcVT == MVT::bf16)
28370b57cec5SDimitry Andric     return false;
28380b57cec5SDimitry Andric 
28390b57cec5SDimitry Andric   unsigned Opc;
28400b57cec5SDimitry Andric   if (SrcVT == MVT::f64) {
28410b57cec5SDimitry Andric     if (Signed)
28420b57cec5SDimitry Andric       Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWDr : AArch64::FCVTZSUXDr;
28430b57cec5SDimitry Andric     else
28440b57cec5SDimitry Andric       Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWDr : AArch64::FCVTZUUXDr;
28450b57cec5SDimitry Andric   } else {
28460b57cec5SDimitry Andric     if (Signed)
28470b57cec5SDimitry Andric       Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWSr : AArch64::FCVTZSUXSr;
28480b57cec5SDimitry Andric     else
28490b57cec5SDimitry Andric       Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWSr : AArch64::FCVTZUUXSr;
28500b57cec5SDimitry Andric   }
285104eeddc0SDimitry Andric   Register ResultReg = createResultReg(
28520b57cec5SDimitry Andric       DestVT == MVT::i32 ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass);
2853bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
28540b57cec5SDimitry Andric       .addReg(SrcReg);
28550b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
28560b57cec5SDimitry Andric   return true;
28570b57cec5SDimitry Andric }
28580b57cec5SDimitry Andric 
28590b57cec5SDimitry Andric bool AArch64FastISel::selectIntToFP(const Instruction *I, bool Signed) {
28600b57cec5SDimitry Andric   MVT DestVT;
28610b57cec5SDimitry Andric   if (!isTypeLegal(I->getType(), DestVT) || DestVT.isVector())
28620b57cec5SDimitry Andric     return false;
28630b57cec5SDimitry Andric   // Let regular ISEL handle FP16
2864*0fca6ea1SDimitry Andric   if (DestVT == MVT::f16 || DestVT == MVT::bf16)
28650b57cec5SDimitry Andric     return false;
28660b57cec5SDimitry Andric 
28670b57cec5SDimitry Andric   assert((DestVT == MVT::f32 || DestVT == MVT::f64) &&
28680b57cec5SDimitry Andric          "Unexpected value type.");
28690b57cec5SDimitry Andric 
287004eeddc0SDimitry Andric   Register SrcReg = getRegForValue(I->getOperand(0));
28710b57cec5SDimitry Andric   if (!SrcReg)
28720b57cec5SDimitry Andric     return false;
28730b57cec5SDimitry Andric 
28740b57cec5SDimitry Andric   EVT SrcVT = TLI.getValueType(DL, I->getOperand(0)->getType(), true);
28750b57cec5SDimitry Andric 
28760b57cec5SDimitry Andric   // Handle sign-extension.
28770b57cec5SDimitry Andric   if (SrcVT == MVT::i16 || SrcVT == MVT::i8 || SrcVT == MVT::i1) {
28780b57cec5SDimitry Andric     SrcReg =
28790b57cec5SDimitry Andric         emitIntExt(SrcVT.getSimpleVT(), SrcReg, MVT::i32, /*isZExt*/ !Signed);
28800b57cec5SDimitry Andric     if (!SrcReg)
28810b57cec5SDimitry Andric       return false;
28820b57cec5SDimitry Andric   }
28830b57cec5SDimitry Andric 
28840b57cec5SDimitry Andric   unsigned Opc;
28850b57cec5SDimitry Andric   if (SrcVT == MVT::i64) {
28860b57cec5SDimitry Andric     if (Signed)
28870b57cec5SDimitry Andric       Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUXSri : AArch64::SCVTFUXDri;
28880b57cec5SDimitry Andric     else
28890b57cec5SDimitry Andric       Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUXSri : AArch64::UCVTFUXDri;
28900b57cec5SDimitry Andric   } else {
28910b57cec5SDimitry Andric     if (Signed)
28920b57cec5SDimitry Andric       Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUWSri : AArch64::SCVTFUWDri;
28930b57cec5SDimitry Andric     else
28940b57cec5SDimitry Andric       Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUWSri : AArch64::UCVTFUWDri;
28950b57cec5SDimitry Andric   }
28960b57cec5SDimitry Andric 
289704eeddc0SDimitry Andric   Register ResultReg = fastEmitInst_r(Opc, TLI.getRegClassFor(DestVT), SrcReg);
28980b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
28990b57cec5SDimitry Andric   return true;
29000b57cec5SDimitry Andric }
29010b57cec5SDimitry Andric 
29020b57cec5SDimitry Andric bool AArch64FastISel::fastLowerArguments() {
29030b57cec5SDimitry Andric   if (!FuncInfo.CanLowerReturn)
29040b57cec5SDimitry Andric     return false;
29050b57cec5SDimitry Andric 
29060b57cec5SDimitry Andric   const Function *F = FuncInfo.Fn;
29070b57cec5SDimitry Andric   if (F->isVarArg())
29080b57cec5SDimitry Andric     return false;
29090b57cec5SDimitry Andric 
29100b57cec5SDimitry Andric   CallingConv::ID CC = F->getCallingConv();
29110b57cec5SDimitry Andric   if (CC != CallingConv::C && CC != CallingConv::Swift)
29120b57cec5SDimitry Andric     return false;
29130b57cec5SDimitry Andric 
29140b57cec5SDimitry Andric   if (Subtarget->hasCustomCallingConv())
29150b57cec5SDimitry Andric     return false;
29160b57cec5SDimitry Andric 
29170b57cec5SDimitry Andric   // Only handle simple cases of up to 8 GPR and FPR each.
29180b57cec5SDimitry Andric   unsigned GPRCnt = 0;
29190b57cec5SDimitry Andric   unsigned FPRCnt = 0;
29200b57cec5SDimitry Andric   for (auto const &Arg : F->args()) {
29210b57cec5SDimitry Andric     if (Arg.hasAttribute(Attribute::ByVal) ||
29220b57cec5SDimitry Andric         Arg.hasAttribute(Attribute::InReg) ||
29230b57cec5SDimitry Andric         Arg.hasAttribute(Attribute::StructRet) ||
29240b57cec5SDimitry Andric         Arg.hasAttribute(Attribute::SwiftSelf) ||
2925fe6060f1SDimitry Andric         Arg.hasAttribute(Attribute::SwiftAsync) ||
29260b57cec5SDimitry Andric         Arg.hasAttribute(Attribute::SwiftError) ||
29270b57cec5SDimitry Andric         Arg.hasAttribute(Attribute::Nest))
29280b57cec5SDimitry Andric       return false;
29290b57cec5SDimitry Andric 
29300b57cec5SDimitry Andric     Type *ArgTy = Arg.getType();
29310b57cec5SDimitry Andric     if (ArgTy->isStructTy() || ArgTy->isArrayTy())
29320b57cec5SDimitry Andric       return false;
29330b57cec5SDimitry Andric 
29340b57cec5SDimitry Andric     EVT ArgVT = TLI.getValueType(DL, ArgTy);
29350b57cec5SDimitry Andric     if (!ArgVT.isSimple())
29360b57cec5SDimitry Andric       return false;
29370b57cec5SDimitry Andric 
29380b57cec5SDimitry Andric     MVT VT = ArgVT.getSimpleVT().SimpleTy;
29390b57cec5SDimitry Andric     if (VT.isFloatingPoint() && !Subtarget->hasFPARMv8())
29400b57cec5SDimitry Andric       return false;
29410b57cec5SDimitry Andric 
29420b57cec5SDimitry Andric     if (VT.isVector() &&
29430b57cec5SDimitry Andric         (!Subtarget->hasNEON() || !Subtarget->isLittleEndian()))
29440b57cec5SDimitry Andric       return false;
29450b57cec5SDimitry Andric 
29460b57cec5SDimitry Andric     if (VT >= MVT::i1 && VT <= MVT::i64)
29470b57cec5SDimitry Andric       ++GPRCnt;
29480b57cec5SDimitry Andric     else if ((VT >= MVT::f16 && VT <= MVT::f64) || VT.is64BitVector() ||
29490b57cec5SDimitry Andric              VT.is128BitVector())
29500b57cec5SDimitry Andric       ++FPRCnt;
29510b57cec5SDimitry Andric     else
29520b57cec5SDimitry Andric       return false;
29530b57cec5SDimitry Andric 
29540b57cec5SDimitry Andric     if (GPRCnt > 8 || FPRCnt > 8)
29550b57cec5SDimitry Andric       return false;
29560b57cec5SDimitry Andric   }
29570b57cec5SDimitry Andric 
29580b57cec5SDimitry Andric   static const MCPhysReg Registers[6][8] = {
29590b57cec5SDimitry Andric     { AArch64::W0, AArch64::W1, AArch64::W2, AArch64::W3, AArch64::W4,
29600b57cec5SDimitry Andric       AArch64::W5, AArch64::W6, AArch64::W7 },
29610b57cec5SDimitry Andric     { AArch64::X0, AArch64::X1, AArch64::X2, AArch64::X3, AArch64::X4,
29620b57cec5SDimitry Andric       AArch64::X5, AArch64::X6, AArch64::X7 },
29630b57cec5SDimitry Andric     { AArch64::H0, AArch64::H1, AArch64::H2, AArch64::H3, AArch64::H4,
29640b57cec5SDimitry Andric       AArch64::H5, AArch64::H6, AArch64::H7 },
29650b57cec5SDimitry Andric     { AArch64::S0, AArch64::S1, AArch64::S2, AArch64::S3, AArch64::S4,
29660b57cec5SDimitry Andric       AArch64::S5, AArch64::S6, AArch64::S7 },
29670b57cec5SDimitry Andric     { AArch64::D0, AArch64::D1, AArch64::D2, AArch64::D3, AArch64::D4,
29680b57cec5SDimitry Andric       AArch64::D5, AArch64::D6, AArch64::D7 },
29690b57cec5SDimitry Andric     { AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,
29700b57cec5SDimitry Andric       AArch64::Q5, AArch64::Q6, AArch64::Q7 }
29710b57cec5SDimitry Andric   };
29720b57cec5SDimitry Andric 
29730b57cec5SDimitry Andric   unsigned GPRIdx = 0;
29740b57cec5SDimitry Andric   unsigned FPRIdx = 0;
29750b57cec5SDimitry Andric   for (auto const &Arg : F->args()) {
29760b57cec5SDimitry Andric     MVT VT = TLI.getSimpleValueType(DL, Arg.getType());
29770b57cec5SDimitry Andric     unsigned SrcReg;
29780b57cec5SDimitry Andric     const TargetRegisterClass *RC;
29790b57cec5SDimitry Andric     if (VT >= MVT::i1 && VT <= MVT::i32) {
29800b57cec5SDimitry Andric       SrcReg = Registers[0][GPRIdx++];
29810b57cec5SDimitry Andric       RC = &AArch64::GPR32RegClass;
29820b57cec5SDimitry Andric       VT = MVT::i32;
29830b57cec5SDimitry Andric     } else if (VT == MVT::i64) {
29840b57cec5SDimitry Andric       SrcReg = Registers[1][GPRIdx++];
29850b57cec5SDimitry Andric       RC = &AArch64::GPR64RegClass;
2986*0fca6ea1SDimitry Andric     } else if (VT == MVT::f16 || VT == MVT::bf16) {
29870b57cec5SDimitry Andric       SrcReg = Registers[2][FPRIdx++];
29880b57cec5SDimitry Andric       RC = &AArch64::FPR16RegClass;
29890b57cec5SDimitry Andric     } else if (VT ==  MVT::f32) {
29900b57cec5SDimitry Andric       SrcReg = Registers[3][FPRIdx++];
29910b57cec5SDimitry Andric       RC = &AArch64::FPR32RegClass;
29920b57cec5SDimitry Andric     } else if ((VT == MVT::f64) || VT.is64BitVector()) {
29930b57cec5SDimitry Andric       SrcReg = Registers[4][FPRIdx++];
29940b57cec5SDimitry Andric       RC = &AArch64::FPR64RegClass;
29950b57cec5SDimitry Andric     } else if (VT.is128BitVector()) {
29960b57cec5SDimitry Andric       SrcReg = Registers[5][FPRIdx++];
29970b57cec5SDimitry Andric       RC = &AArch64::FPR128RegClass;
29980b57cec5SDimitry Andric     } else
29990b57cec5SDimitry Andric       llvm_unreachable("Unexpected value type.");
30000b57cec5SDimitry Andric 
300104eeddc0SDimitry Andric     Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
30020b57cec5SDimitry Andric     // FIXME: Unfortunately it's necessary to emit a copy from the livein copy.
30030b57cec5SDimitry Andric     // Without this, EmitLiveInCopies may eliminate the livein if its only
30040b57cec5SDimitry Andric     // use is a bitcast (which isn't turned into an instruction).
300504eeddc0SDimitry Andric     Register ResultReg = createResultReg(RC);
3006bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
30070b57cec5SDimitry Andric             TII.get(TargetOpcode::COPY), ResultReg)
30080b57cec5SDimitry Andric         .addReg(DstReg, getKillRegState(true));
30090b57cec5SDimitry Andric     updateValueMap(&Arg, ResultReg);
30100b57cec5SDimitry Andric   }
30110b57cec5SDimitry Andric   return true;
30120b57cec5SDimitry Andric }
30130b57cec5SDimitry Andric 
30140b57cec5SDimitry Andric bool AArch64FastISel::processCallArgs(CallLoweringInfo &CLI,
30150b57cec5SDimitry Andric                                       SmallVectorImpl<MVT> &OutVTs,
30160b57cec5SDimitry Andric                                       unsigned &NumBytes) {
30170b57cec5SDimitry Andric   CallingConv::ID CC = CLI.CallConv;
30180b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> ArgLocs;
30190b57cec5SDimitry Andric   CCState CCInfo(CC, false, *FuncInfo.MF, ArgLocs, *Context);
30200b57cec5SDimitry Andric   CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, CCAssignFnForCall(CC));
30210b57cec5SDimitry Andric 
30220b57cec5SDimitry Andric   // Get a count of how many bytes are to be pushed on the stack.
302306c3fb27SDimitry Andric   NumBytes = CCInfo.getStackSize();
30240b57cec5SDimitry Andric 
30250b57cec5SDimitry Andric   // Issue CALLSEQ_START
30260b57cec5SDimitry Andric   unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
3027bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AdjStackDown))
30280b57cec5SDimitry Andric     .addImm(NumBytes).addImm(0);
30290b57cec5SDimitry Andric 
30300b57cec5SDimitry Andric   // Process the args.
30310b57cec5SDimitry Andric   for (CCValAssign &VA : ArgLocs) {
30320b57cec5SDimitry Andric     const Value *ArgVal = CLI.OutVals[VA.getValNo()];
30330b57cec5SDimitry Andric     MVT ArgVT = OutVTs[VA.getValNo()];
30340b57cec5SDimitry Andric 
303504eeddc0SDimitry Andric     Register ArgReg = getRegForValue(ArgVal);
30360b57cec5SDimitry Andric     if (!ArgReg)
30370b57cec5SDimitry Andric       return false;
30380b57cec5SDimitry Andric 
30390b57cec5SDimitry Andric     // Handle arg promotion: SExt, ZExt, AExt.
30400b57cec5SDimitry Andric     switch (VA.getLocInfo()) {
30410b57cec5SDimitry Andric     case CCValAssign::Full:
30420b57cec5SDimitry Andric       break;
30430b57cec5SDimitry Andric     case CCValAssign::SExt: {
30440b57cec5SDimitry Andric       MVT DestVT = VA.getLocVT();
30450b57cec5SDimitry Andric       MVT SrcVT = ArgVT;
30460b57cec5SDimitry Andric       ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/false);
30470b57cec5SDimitry Andric       if (!ArgReg)
30480b57cec5SDimitry Andric         return false;
30490b57cec5SDimitry Andric       break;
30500b57cec5SDimitry Andric     }
30510b57cec5SDimitry Andric     case CCValAssign::AExt:
30520b57cec5SDimitry Andric     // Intentional fall-through.
30530b57cec5SDimitry Andric     case CCValAssign::ZExt: {
30540b57cec5SDimitry Andric       MVT DestVT = VA.getLocVT();
30550b57cec5SDimitry Andric       MVT SrcVT = ArgVT;
30560b57cec5SDimitry Andric       ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/true);
30570b57cec5SDimitry Andric       if (!ArgReg)
30580b57cec5SDimitry Andric         return false;
30590b57cec5SDimitry Andric       break;
30600b57cec5SDimitry Andric     }
30610b57cec5SDimitry Andric     default:
30620b57cec5SDimitry Andric       llvm_unreachable("Unknown arg promotion!");
30630b57cec5SDimitry Andric     }
30640b57cec5SDimitry Andric 
30650b57cec5SDimitry Andric     // Now copy/store arg to correct locations.
30660b57cec5SDimitry Andric     if (VA.isRegLoc() && !VA.needsCustom()) {
3067bdd1243dSDimitry Andric       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
30680b57cec5SDimitry Andric               TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(ArgReg);
30690b57cec5SDimitry Andric       CLI.OutRegs.push_back(VA.getLocReg());
30700b57cec5SDimitry Andric     } else if (VA.needsCustom()) {
30710b57cec5SDimitry Andric       // FIXME: Handle custom args.
30720b57cec5SDimitry Andric       return false;
30730b57cec5SDimitry Andric     } else {
30740b57cec5SDimitry Andric       assert(VA.isMemLoc() && "Assuming store on stack.");
30750b57cec5SDimitry Andric 
30760b57cec5SDimitry Andric       // Don't emit stores for undef values.
30770b57cec5SDimitry Andric       if (isa<UndefValue>(ArgVal))
30780b57cec5SDimitry Andric         continue;
30790b57cec5SDimitry Andric 
30800b57cec5SDimitry Andric       // Need to store on the stack.
30810b57cec5SDimitry Andric       unsigned ArgSize = (ArgVT.getSizeInBits() + 7) / 8;
30820b57cec5SDimitry Andric 
30830b57cec5SDimitry Andric       unsigned BEAlign = 0;
30840b57cec5SDimitry Andric       if (ArgSize < 8 && !Subtarget->isLittleEndian())
30850b57cec5SDimitry Andric         BEAlign = 8 - ArgSize;
30860b57cec5SDimitry Andric 
30870b57cec5SDimitry Andric       Address Addr;
30880b57cec5SDimitry Andric       Addr.setKind(Address::RegBase);
30890b57cec5SDimitry Andric       Addr.setReg(AArch64::SP);
30900b57cec5SDimitry Andric       Addr.setOffset(VA.getLocMemOffset() + BEAlign);
30910b57cec5SDimitry Andric 
30925ffd83dbSDimitry Andric       Align Alignment = DL.getABITypeAlign(ArgVal->getType());
30930b57cec5SDimitry Andric       MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
30940b57cec5SDimitry Andric           MachinePointerInfo::getStack(*FuncInfo.MF, Addr.getOffset()),
30950b57cec5SDimitry Andric           MachineMemOperand::MOStore, ArgVT.getStoreSize(), Alignment);
30960b57cec5SDimitry Andric 
30970b57cec5SDimitry Andric       if (!emitStore(ArgVT, ArgReg, Addr, MMO))
30980b57cec5SDimitry Andric         return false;
30990b57cec5SDimitry Andric     }
31000b57cec5SDimitry Andric   }
31010b57cec5SDimitry Andric   return true;
31020b57cec5SDimitry Andric }
31030b57cec5SDimitry Andric 
310406c3fb27SDimitry Andric bool AArch64FastISel::finishCall(CallLoweringInfo &CLI, unsigned NumBytes) {
31050b57cec5SDimitry Andric   CallingConv::ID CC = CLI.CallConv;
31060b57cec5SDimitry Andric 
31070b57cec5SDimitry Andric   // Issue CALLSEQ_END
31080b57cec5SDimitry Andric   unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
3109bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AdjStackUp))
31100b57cec5SDimitry Andric     .addImm(NumBytes).addImm(0);
31110b57cec5SDimitry Andric 
311206c3fb27SDimitry Andric   // Now the return values.
31130b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> RVLocs;
31140b57cec5SDimitry Andric   CCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context);
311506c3fb27SDimitry Andric   CCInfo.AnalyzeCallResult(CLI.Ins, CCAssignFnForCall(CC));
31160b57cec5SDimitry Andric 
311706c3fb27SDimitry Andric   Register ResultReg = FuncInfo.CreateRegs(CLI.RetTy);
311806c3fb27SDimitry Andric   for (unsigned i = 0; i != RVLocs.size(); ++i) {
311906c3fb27SDimitry Andric     CCValAssign &VA = RVLocs[i];
312006c3fb27SDimitry Andric     MVT CopyVT = VA.getValVT();
312106c3fb27SDimitry Andric     unsigned CopyReg = ResultReg + i;
31220b57cec5SDimitry Andric 
31230b57cec5SDimitry Andric     // TODO: Handle big-endian results
31240b57cec5SDimitry Andric     if (CopyVT.isVector() && !Subtarget->isLittleEndian())
31250b57cec5SDimitry Andric       return false;
31260b57cec5SDimitry Andric 
312706c3fb27SDimitry Andric     // Copy result out of their specified physreg.
312806c3fb27SDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(TargetOpcode::COPY),
312906c3fb27SDimitry Andric             CopyReg)
313006c3fb27SDimitry Andric         .addReg(VA.getLocReg());
313106c3fb27SDimitry Andric     CLI.InRegs.push_back(VA.getLocReg());
313206c3fb27SDimitry Andric   }
31330b57cec5SDimitry Andric 
31340b57cec5SDimitry Andric   CLI.ResultReg = ResultReg;
313506c3fb27SDimitry Andric   CLI.NumResultRegs = RVLocs.size();
31360b57cec5SDimitry Andric 
31370b57cec5SDimitry Andric   return true;
31380b57cec5SDimitry Andric }
31390b57cec5SDimitry Andric 
31400b57cec5SDimitry Andric bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
31410b57cec5SDimitry Andric   CallingConv::ID CC  = CLI.CallConv;
31420b57cec5SDimitry Andric   bool IsTailCall     = CLI.IsTailCall;
31430b57cec5SDimitry Andric   bool IsVarArg       = CLI.IsVarArg;
31440b57cec5SDimitry Andric   const Value *Callee = CLI.Callee;
31450b57cec5SDimitry Andric   MCSymbol *Symbol = CLI.Symbol;
31460b57cec5SDimitry Andric 
31470b57cec5SDimitry Andric   if (!Callee && !Symbol)
31480b57cec5SDimitry Andric     return false;
31490b57cec5SDimitry Andric 
31503a9a9c0cSDimitry Andric   // Allow SelectionDAG isel to handle calls to functions like setjmp that need
31513a9a9c0cSDimitry Andric   // a bti instruction following the call.
31523a9a9c0cSDimitry Andric   if (CLI.CB && CLI.CB->hasFnAttr(Attribute::ReturnsTwice) &&
31533a9a9c0cSDimitry Andric       !Subtarget->noBTIAtReturnTwice() &&
31543a9a9c0cSDimitry Andric       MF->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement())
31553a9a9c0cSDimitry Andric     return false;
31563a9a9c0cSDimitry Andric 
3157bdd1243dSDimitry Andric   // Allow SelectionDAG isel to handle indirect calls with KCFI checks.
3158bdd1243dSDimitry Andric   if (CLI.CB && CLI.CB->isIndirectCall() &&
3159bdd1243dSDimitry Andric       CLI.CB->getOperandBundle(LLVMContext::OB_kcfi))
3160bdd1243dSDimitry Andric     return false;
3161bdd1243dSDimitry Andric 
31620b57cec5SDimitry Andric   // Allow SelectionDAG isel to handle tail calls.
31630b57cec5SDimitry Andric   if (IsTailCall)
31640b57cec5SDimitry Andric     return false;
31650b57cec5SDimitry Andric 
31668bcb0991SDimitry Andric   // FIXME: we could and should support this, but for now correctness at -O0 is
31678bcb0991SDimitry Andric   // more important.
31688bcb0991SDimitry Andric   if (Subtarget->isTargetILP32())
31698bcb0991SDimitry Andric     return false;
31708bcb0991SDimitry Andric 
31710b57cec5SDimitry Andric   CodeModel::Model CM = TM.getCodeModel();
31720b57cec5SDimitry Andric   // Only support the small-addressing and large code models.
31730b57cec5SDimitry Andric   if (CM != CodeModel::Large && !Subtarget->useSmallAddressing())
31740b57cec5SDimitry Andric     return false;
31750b57cec5SDimitry Andric 
31760b57cec5SDimitry Andric   // FIXME: Add large code model support for ELF.
31770b57cec5SDimitry Andric   if (CM == CodeModel::Large && !Subtarget->isTargetMachO())
31780b57cec5SDimitry Andric     return false;
31790b57cec5SDimitry Andric 
3180*0fca6ea1SDimitry Andric   // ELF -fno-plt compiled intrinsic calls do not have the nonlazybind
3181*0fca6ea1SDimitry Andric   // attribute. Check "RtLibUseGOT" instead.
3182*0fca6ea1SDimitry Andric   if (MF->getFunction().getParent()->getRtLibUseGOT())
3183*0fca6ea1SDimitry Andric     return false;
3184*0fca6ea1SDimitry Andric 
31850b57cec5SDimitry Andric   // Let SDISel handle vararg functions.
31860b57cec5SDimitry Andric   if (IsVarArg)
31870b57cec5SDimitry Andric     return false;
31880b57cec5SDimitry Andric 
31897a6dacacSDimitry Andric   if (Subtarget->isWindowsArm64EC())
31907a6dacacSDimitry Andric     return false;
31917a6dacacSDimitry Andric 
31920b57cec5SDimitry Andric   for (auto Flag : CLI.OutFlags)
31930b57cec5SDimitry Andric     if (Flag.isInReg() || Flag.isSRet() || Flag.isNest() || Flag.isByVal() ||
3194fe6060f1SDimitry Andric         Flag.isSwiftSelf() || Flag.isSwiftAsync() || Flag.isSwiftError())
31950b57cec5SDimitry Andric       return false;
31960b57cec5SDimitry Andric 
31970b57cec5SDimitry Andric   // Set up the argument vectors.
31980b57cec5SDimitry Andric   SmallVector<MVT, 16> OutVTs;
31990b57cec5SDimitry Andric   OutVTs.reserve(CLI.OutVals.size());
32000b57cec5SDimitry Andric 
32010b57cec5SDimitry Andric   for (auto *Val : CLI.OutVals) {
32020b57cec5SDimitry Andric     MVT VT;
32030b57cec5SDimitry Andric     if (!isTypeLegal(Val->getType(), VT) &&
32040b57cec5SDimitry Andric         !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16))
32050b57cec5SDimitry Andric       return false;
32060b57cec5SDimitry Andric 
32070b57cec5SDimitry Andric     // We don't handle vector parameters yet.
32080b57cec5SDimitry Andric     if (VT.isVector() || VT.getSizeInBits() > 64)
32090b57cec5SDimitry Andric       return false;
32100b57cec5SDimitry Andric 
32110b57cec5SDimitry Andric     OutVTs.push_back(VT);
32120b57cec5SDimitry Andric   }
32130b57cec5SDimitry Andric 
32140b57cec5SDimitry Andric   Address Addr;
32150b57cec5SDimitry Andric   if (Callee && !computeCallAddress(Callee, Addr))
32160b57cec5SDimitry Andric     return false;
32170b57cec5SDimitry Andric 
3218480093f4SDimitry Andric   // The weak function target may be zero; in that case we must use indirect
3219480093f4SDimitry Andric   // addressing via a stub on windows as it may be out of range for a
3220480093f4SDimitry Andric   // PC-relative jump.
3221480093f4SDimitry Andric   if (Subtarget->isTargetWindows() && Addr.getGlobalValue() &&
3222480093f4SDimitry Andric       Addr.getGlobalValue()->hasExternalWeakLinkage())
3223480093f4SDimitry Andric     return false;
3224480093f4SDimitry Andric 
32250b57cec5SDimitry Andric   // Handle the arguments now that we've gotten them.
32260b57cec5SDimitry Andric   unsigned NumBytes;
32270b57cec5SDimitry Andric   if (!processCallArgs(CLI, OutVTs, NumBytes))
32280b57cec5SDimitry Andric     return false;
32290b57cec5SDimitry Andric 
32300b57cec5SDimitry Andric   const AArch64RegisterInfo *RegInfo = Subtarget->getRegisterInfo();
32310b57cec5SDimitry Andric   if (RegInfo->isAnyArgRegReserved(*MF))
32320b57cec5SDimitry Andric     RegInfo->emitReservedArgRegCallError(*MF);
32330b57cec5SDimitry Andric 
32340b57cec5SDimitry Andric   // Issue the call.
32350b57cec5SDimitry Andric   MachineInstrBuilder MIB;
32360b57cec5SDimitry Andric   if (Subtarget->useSmallAddressing()) {
32375ffd83dbSDimitry Andric     const MCInstrDesc &II =
32385ffd83dbSDimitry Andric         TII.get(Addr.getReg() ? getBLRCallOpcode(*MF) : (unsigned)AArch64::BL);
3239bdd1243dSDimitry Andric     MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II);
32400b57cec5SDimitry Andric     if (Symbol)
32410b57cec5SDimitry Andric       MIB.addSym(Symbol, 0);
32420b57cec5SDimitry Andric     else if (Addr.getGlobalValue())
32430b57cec5SDimitry Andric       MIB.addGlobalAddress(Addr.getGlobalValue(), 0, 0);
32440b57cec5SDimitry Andric     else if (Addr.getReg()) {
324504eeddc0SDimitry Andric       Register Reg = constrainOperandRegClass(II, Addr.getReg(), 0);
32460b57cec5SDimitry Andric       MIB.addReg(Reg);
32470b57cec5SDimitry Andric     } else
32480b57cec5SDimitry Andric       return false;
32490b57cec5SDimitry Andric   } else {
32500b57cec5SDimitry Andric     unsigned CallReg = 0;
32510b57cec5SDimitry Andric     if (Symbol) {
325204eeddc0SDimitry Andric       Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
3253bdd1243dSDimitry Andric       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADRP),
32540b57cec5SDimitry Andric               ADRPReg)
32550b57cec5SDimitry Andric           .addSym(Symbol, AArch64II::MO_GOT | AArch64II::MO_PAGE);
32560b57cec5SDimitry Andric 
32570b57cec5SDimitry Andric       CallReg = createResultReg(&AArch64::GPR64RegClass);
3258bdd1243dSDimitry Andric       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
32590b57cec5SDimitry Andric               TII.get(AArch64::LDRXui), CallReg)
32600b57cec5SDimitry Andric           .addReg(ADRPReg)
32610b57cec5SDimitry Andric           .addSym(Symbol,
32620b57cec5SDimitry Andric                   AArch64II::MO_GOT | AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
32630b57cec5SDimitry Andric     } else if (Addr.getGlobalValue())
32640b57cec5SDimitry Andric       CallReg = materializeGV(Addr.getGlobalValue());
32650b57cec5SDimitry Andric     else if (Addr.getReg())
32660b57cec5SDimitry Andric       CallReg = Addr.getReg();
32670b57cec5SDimitry Andric 
32680b57cec5SDimitry Andric     if (!CallReg)
32690b57cec5SDimitry Andric       return false;
32700b57cec5SDimitry Andric 
32715ffd83dbSDimitry Andric     const MCInstrDesc &II = TII.get(getBLRCallOpcode(*MF));
32720b57cec5SDimitry Andric     CallReg = constrainOperandRegClass(II, CallReg, 0);
3273bdd1243dSDimitry Andric     MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II).addReg(CallReg);
32740b57cec5SDimitry Andric   }
32750b57cec5SDimitry Andric 
32760b57cec5SDimitry Andric   // Add implicit physical register uses to the call.
32770b57cec5SDimitry Andric   for (auto Reg : CLI.OutRegs)
32780b57cec5SDimitry Andric     MIB.addReg(Reg, RegState::Implicit);
32790b57cec5SDimitry Andric 
32800b57cec5SDimitry Andric   // Add a register mask with the call-preserved registers.
32810b57cec5SDimitry Andric   // Proper defs for return values will be added by setPhysRegsDeadExcept().
32820b57cec5SDimitry Andric   MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC));
32830b57cec5SDimitry Andric 
32840b57cec5SDimitry Andric   CLI.Call = MIB;
32850b57cec5SDimitry Andric 
32860b57cec5SDimitry Andric   // Finish off the call including any return values.
328706c3fb27SDimitry Andric   return finishCall(CLI, NumBytes);
32880b57cec5SDimitry Andric }
32890b57cec5SDimitry Andric 
3290bdd1243dSDimitry Andric bool AArch64FastISel::isMemCpySmall(uint64_t Len, MaybeAlign Alignment) {
32910b57cec5SDimitry Andric   if (Alignment)
3292bdd1243dSDimitry Andric     return Len / Alignment->value() <= 4;
32930b57cec5SDimitry Andric   else
32940b57cec5SDimitry Andric     return Len < 32;
32950b57cec5SDimitry Andric }
32960b57cec5SDimitry Andric 
32970b57cec5SDimitry Andric bool AArch64FastISel::tryEmitSmallMemCpy(Address Dest, Address Src,
3298bdd1243dSDimitry Andric                                          uint64_t Len, MaybeAlign Alignment) {
32990b57cec5SDimitry Andric   // Make sure we don't bloat code by inlining very large memcpy's.
33000b57cec5SDimitry Andric   if (!isMemCpySmall(Len, Alignment))
33010b57cec5SDimitry Andric     return false;
33020b57cec5SDimitry Andric 
33030b57cec5SDimitry Andric   int64_t UnscaledOffset = 0;
33040b57cec5SDimitry Andric   Address OrigDest = Dest;
33050b57cec5SDimitry Andric   Address OrigSrc = Src;
33060b57cec5SDimitry Andric 
33070b57cec5SDimitry Andric   while (Len) {
33080b57cec5SDimitry Andric     MVT VT;
3309bdd1243dSDimitry Andric     if (!Alignment || *Alignment >= 8) {
33100b57cec5SDimitry Andric       if (Len >= 8)
33110b57cec5SDimitry Andric         VT = MVT::i64;
33120b57cec5SDimitry Andric       else if (Len >= 4)
33130b57cec5SDimitry Andric         VT = MVT::i32;
33140b57cec5SDimitry Andric       else if (Len >= 2)
33150b57cec5SDimitry Andric         VT = MVT::i16;
33160b57cec5SDimitry Andric       else {
33170b57cec5SDimitry Andric         VT = MVT::i8;
33180b57cec5SDimitry Andric       }
33190b57cec5SDimitry Andric     } else {
3320bdd1243dSDimitry Andric       assert(Alignment && "Alignment is set in this branch");
33210b57cec5SDimitry Andric       // Bound based on alignment.
3322bdd1243dSDimitry Andric       if (Len >= 4 && *Alignment == 4)
33230b57cec5SDimitry Andric         VT = MVT::i32;
3324bdd1243dSDimitry Andric       else if (Len >= 2 && *Alignment == 2)
33250b57cec5SDimitry Andric         VT = MVT::i16;
33260b57cec5SDimitry Andric       else {
33270b57cec5SDimitry Andric         VT = MVT::i8;
33280b57cec5SDimitry Andric       }
33290b57cec5SDimitry Andric     }
33300b57cec5SDimitry Andric 
33310b57cec5SDimitry Andric     unsigned ResultReg = emitLoad(VT, VT, Src);
33320b57cec5SDimitry Andric     if (!ResultReg)
33330b57cec5SDimitry Andric       return false;
33340b57cec5SDimitry Andric 
33350b57cec5SDimitry Andric     if (!emitStore(VT, ResultReg, Dest))
33360b57cec5SDimitry Andric       return false;
33370b57cec5SDimitry Andric 
33380b57cec5SDimitry Andric     int64_t Size = VT.getSizeInBits() / 8;
33390b57cec5SDimitry Andric     Len -= Size;
33400b57cec5SDimitry Andric     UnscaledOffset += Size;
33410b57cec5SDimitry Andric 
33420b57cec5SDimitry Andric     // We need to recompute the unscaled offset for each iteration.
33430b57cec5SDimitry Andric     Dest.setOffset(OrigDest.getOffset() + UnscaledOffset);
33440b57cec5SDimitry Andric     Src.setOffset(OrigSrc.getOffset() + UnscaledOffset);
33450b57cec5SDimitry Andric   }
33460b57cec5SDimitry Andric 
33470b57cec5SDimitry Andric   return true;
33480b57cec5SDimitry Andric }
33490b57cec5SDimitry Andric 
33500b57cec5SDimitry Andric /// Check if it is possible to fold the condition from the XALU intrinsic
33510b57cec5SDimitry Andric /// into the user. The condition code will only be updated on success.
33520b57cec5SDimitry Andric bool AArch64FastISel::foldXALUIntrinsic(AArch64CC::CondCode &CC,
33530b57cec5SDimitry Andric                                         const Instruction *I,
33540b57cec5SDimitry Andric                                         const Value *Cond) {
33550b57cec5SDimitry Andric   if (!isa<ExtractValueInst>(Cond))
33560b57cec5SDimitry Andric     return false;
33570b57cec5SDimitry Andric 
33580b57cec5SDimitry Andric   const auto *EV = cast<ExtractValueInst>(Cond);
33590b57cec5SDimitry Andric   if (!isa<IntrinsicInst>(EV->getAggregateOperand()))
33600b57cec5SDimitry Andric     return false;
33610b57cec5SDimitry Andric 
33620b57cec5SDimitry Andric   const auto *II = cast<IntrinsicInst>(EV->getAggregateOperand());
33630b57cec5SDimitry Andric   MVT RetVT;
33640b57cec5SDimitry Andric   const Function *Callee = II->getCalledFunction();
33650b57cec5SDimitry Andric   Type *RetTy =
33660b57cec5SDimitry Andric   cast<StructType>(Callee->getReturnType())->getTypeAtIndex(0U);
33670b57cec5SDimitry Andric   if (!isTypeLegal(RetTy, RetVT))
33680b57cec5SDimitry Andric     return false;
33690b57cec5SDimitry Andric 
33700b57cec5SDimitry Andric   if (RetVT != MVT::i32 && RetVT != MVT::i64)
33710b57cec5SDimitry Andric     return false;
33720b57cec5SDimitry Andric 
33730b57cec5SDimitry Andric   const Value *LHS = II->getArgOperand(0);
33740b57cec5SDimitry Andric   const Value *RHS = II->getArgOperand(1);
33750b57cec5SDimitry Andric 
33760b57cec5SDimitry Andric   // Canonicalize immediate to the RHS.
3377e8d8bef9SDimitry Andric   if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS) && II->isCommutative())
33780b57cec5SDimitry Andric     std::swap(LHS, RHS);
33790b57cec5SDimitry Andric 
33800b57cec5SDimitry Andric   // Simplify multiplies.
33810b57cec5SDimitry Andric   Intrinsic::ID IID = II->getIntrinsicID();
33820b57cec5SDimitry Andric   switch (IID) {
33830b57cec5SDimitry Andric   default:
33840b57cec5SDimitry Andric     break;
33850b57cec5SDimitry Andric   case Intrinsic::smul_with_overflow:
33860b57cec5SDimitry Andric     if (const auto *C = dyn_cast<ConstantInt>(RHS))
33870b57cec5SDimitry Andric       if (C->getValue() == 2)
33880b57cec5SDimitry Andric         IID = Intrinsic::sadd_with_overflow;
33890b57cec5SDimitry Andric     break;
33900b57cec5SDimitry Andric   case Intrinsic::umul_with_overflow:
33910b57cec5SDimitry Andric     if (const auto *C = dyn_cast<ConstantInt>(RHS))
33920b57cec5SDimitry Andric       if (C->getValue() == 2)
33930b57cec5SDimitry Andric         IID = Intrinsic::uadd_with_overflow;
33940b57cec5SDimitry Andric     break;
33950b57cec5SDimitry Andric   }
33960b57cec5SDimitry Andric 
33970b57cec5SDimitry Andric   AArch64CC::CondCode TmpCC;
33980b57cec5SDimitry Andric   switch (IID) {
33990b57cec5SDimitry Andric   default:
34000b57cec5SDimitry Andric     return false;
34010b57cec5SDimitry Andric   case Intrinsic::sadd_with_overflow:
34020b57cec5SDimitry Andric   case Intrinsic::ssub_with_overflow:
34030b57cec5SDimitry Andric     TmpCC = AArch64CC::VS;
34040b57cec5SDimitry Andric     break;
34050b57cec5SDimitry Andric   case Intrinsic::uadd_with_overflow:
34060b57cec5SDimitry Andric     TmpCC = AArch64CC::HS;
34070b57cec5SDimitry Andric     break;
34080b57cec5SDimitry Andric   case Intrinsic::usub_with_overflow:
34090b57cec5SDimitry Andric     TmpCC = AArch64CC::LO;
34100b57cec5SDimitry Andric     break;
34110b57cec5SDimitry Andric   case Intrinsic::smul_with_overflow:
34120b57cec5SDimitry Andric   case Intrinsic::umul_with_overflow:
34130b57cec5SDimitry Andric     TmpCC = AArch64CC::NE;
34140b57cec5SDimitry Andric     break;
34150b57cec5SDimitry Andric   }
34160b57cec5SDimitry Andric 
34170b57cec5SDimitry Andric   // Check if both instructions are in the same basic block.
34180b57cec5SDimitry Andric   if (!isValueAvailable(II))
34190b57cec5SDimitry Andric     return false;
34200b57cec5SDimitry Andric 
34210b57cec5SDimitry Andric   // Make sure nothing is in the way
34220b57cec5SDimitry Andric   BasicBlock::const_iterator Start(I);
34230b57cec5SDimitry Andric   BasicBlock::const_iterator End(II);
34240b57cec5SDimitry Andric   for (auto Itr = std::prev(Start); Itr != End; --Itr) {
34250b57cec5SDimitry Andric     // We only expect extractvalue instructions between the intrinsic and the
34260b57cec5SDimitry Andric     // instruction to be selected.
34270b57cec5SDimitry Andric     if (!isa<ExtractValueInst>(Itr))
34280b57cec5SDimitry Andric       return false;
34290b57cec5SDimitry Andric 
34300b57cec5SDimitry Andric     // Check that the extractvalue operand comes from the intrinsic.
34310b57cec5SDimitry Andric     const auto *EVI = cast<ExtractValueInst>(Itr);
34320b57cec5SDimitry Andric     if (EVI->getAggregateOperand() != II)
34330b57cec5SDimitry Andric       return false;
34340b57cec5SDimitry Andric   }
34350b57cec5SDimitry Andric 
34360b57cec5SDimitry Andric   CC = TmpCC;
34370b57cec5SDimitry Andric   return true;
34380b57cec5SDimitry Andric }
34390b57cec5SDimitry Andric 
34400b57cec5SDimitry Andric bool AArch64FastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) {
34410b57cec5SDimitry Andric   // FIXME: Handle more intrinsics.
34420b57cec5SDimitry Andric   switch (II->getIntrinsicID()) {
34430b57cec5SDimitry Andric   default: return false;
34440b57cec5SDimitry Andric   case Intrinsic::frameaddress: {
34450b57cec5SDimitry Andric     MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
34460b57cec5SDimitry Andric     MFI.setFrameAddressIsTaken(true);
34470b57cec5SDimitry Andric 
34480b57cec5SDimitry Andric     const AArch64RegisterInfo *RegInfo = Subtarget->getRegisterInfo();
34498bcb0991SDimitry Andric     Register FramePtr = RegInfo->getFrameRegister(*(FuncInfo.MF));
34508bcb0991SDimitry Andric     Register SrcReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3451bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
34520b57cec5SDimitry Andric             TII.get(TargetOpcode::COPY), SrcReg).addReg(FramePtr);
34530b57cec5SDimitry Andric     // Recursively load frame address
34540b57cec5SDimitry Andric     // ldr x0, [fp]
34550b57cec5SDimitry Andric     // ldr x0, [x0]
34560b57cec5SDimitry Andric     // ldr x0, [x0]
34570b57cec5SDimitry Andric     // ...
34580b57cec5SDimitry Andric     unsigned DestReg;
34590b57cec5SDimitry Andric     unsigned Depth = cast<ConstantInt>(II->getOperand(0))->getZExtValue();
34600b57cec5SDimitry Andric     while (Depth--) {
34610b57cec5SDimitry Andric       DestReg = fastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,
3462fe6060f1SDimitry Andric                                 SrcReg, 0);
34630b57cec5SDimitry Andric       assert(DestReg && "Unexpected LDR instruction emission failure.");
34640b57cec5SDimitry Andric       SrcReg = DestReg;
34650b57cec5SDimitry Andric     }
34660b57cec5SDimitry Andric 
34670b57cec5SDimitry Andric     updateValueMap(II, SrcReg);
34680b57cec5SDimitry Andric     return true;
34690b57cec5SDimitry Andric   }
34700b57cec5SDimitry Andric   case Intrinsic::sponentry: {
34710b57cec5SDimitry Andric     MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
34720b57cec5SDimitry Andric 
34730b57cec5SDimitry Andric     // SP = FP + Fixed Object + 16
34740b57cec5SDimitry Andric     int FI = MFI.CreateFixedObject(4, 0, false);
347504eeddc0SDimitry Andric     Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
3476bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
34770b57cec5SDimitry Andric             TII.get(AArch64::ADDXri), ResultReg)
34780b57cec5SDimitry Andric             .addFrameIndex(FI)
34790b57cec5SDimitry Andric             .addImm(0)
34800b57cec5SDimitry Andric             .addImm(0);
34810b57cec5SDimitry Andric 
34820b57cec5SDimitry Andric     updateValueMap(II, ResultReg);
34830b57cec5SDimitry Andric     return true;
34840b57cec5SDimitry Andric   }
34850b57cec5SDimitry Andric   case Intrinsic::memcpy:
34860b57cec5SDimitry Andric   case Intrinsic::memmove: {
34870b57cec5SDimitry Andric     const auto *MTI = cast<MemTransferInst>(II);
34880b57cec5SDimitry Andric     // Don't handle volatile.
34890b57cec5SDimitry Andric     if (MTI->isVolatile())
34900b57cec5SDimitry Andric       return false;
34910b57cec5SDimitry Andric 
34920b57cec5SDimitry Andric     // Disable inlining for memmove before calls to ComputeAddress.  Otherwise,
34930b57cec5SDimitry Andric     // we would emit dead code because we don't currently handle memmoves.
34940b57cec5SDimitry Andric     bool IsMemCpy = (II->getIntrinsicID() == Intrinsic::memcpy);
34950b57cec5SDimitry Andric     if (isa<ConstantInt>(MTI->getLength()) && IsMemCpy) {
34960b57cec5SDimitry Andric       // Small memcpy's are common enough that we want to do them without a call
34970b57cec5SDimitry Andric       // if possible.
34980b57cec5SDimitry Andric       uint64_t Len = cast<ConstantInt>(MTI->getLength())->getZExtValue();
3499bdd1243dSDimitry Andric       MaybeAlign Alignment;
3500bdd1243dSDimitry Andric       if (MTI->getDestAlign() || MTI->getSourceAlign())
3501bdd1243dSDimitry Andric         Alignment = std::min(MTI->getDestAlign().valueOrOne(),
3502bdd1243dSDimitry Andric                              MTI->getSourceAlign().valueOrOne());
35030b57cec5SDimitry Andric       if (isMemCpySmall(Len, Alignment)) {
35040b57cec5SDimitry Andric         Address Dest, Src;
35050b57cec5SDimitry Andric         if (!computeAddress(MTI->getRawDest(), Dest) ||
35060b57cec5SDimitry Andric             !computeAddress(MTI->getRawSource(), Src))
35070b57cec5SDimitry Andric           return false;
35080b57cec5SDimitry Andric         if (tryEmitSmallMemCpy(Dest, Src, Len, Alignment))
35090b57cec5SDimitry Andric           return true;
35100b57cec5SDimitry Andric       }
35110b57cec5SDimitry Andric     }
35120b57cec5SDimitry Andric 
35130b57cec5SDimitry Andric     if (!MTI->getLength()->getType()->isIntegerTy(64))
35140b57cec5SDimitry Andric       return false;
35150b57cec5SDimitry Andric 
35160b57cec5SDimitry Andric     if (MTI->getSourceAddressSpace() > 255 || MTI->getDestAddressSpace() > 255)
35170b57cec5SDimitry Andric       // Fast instruction selection doesn't support the special
35180b57cec5SDimitry Andric       // address spaces.
35190b57cec5SDimitry Andric       return false;
35200b57cec5SDimitry Andric 
35210b57cec5SDimitry Andric     const char *IntrMemName = isa<MemCpyInst>(II) ? "memcpy" : "memmove";
3522349cc55cSDimitry Andric     return lowerCallTo(II, IntrMemName, II->arg_size() - 1);
35230b57cec5SDimitry Andric   }
35240b57cec5SDimitry Andric   case Intrinsic::memset: {
35250b57cec5SDimitry Andric     const MemSetInst *MSI = cast<MemSetInst>(II);
35260b57cec5SDimitry Andric     // Don't handle volatile.
35270b57cec5SDimitry Andric     if (MSI->isVolatile())
35280b57cec5SDimitry Andric       return false;
35290b57cec5SDimitry Andric 
35300b57cec5SDimitry Andric     if (!MSI->getLength()->getType()->isIntegerTy(64))
35310b57cec5SDimitry Andric       return false;
35320b57cec5SDimitry Andric 
35330b57cec5SDimitry Andric     if (MSI->getDestAddressSpace() > 255)
35340b57cec5SDimitry Andric       // Fast instruction selection doesn't support the special
35350b57cec5SDimitry Andric       // address spaces.
35360b57cec5SDimitry Andric       return false;
35370b57cec5SDimitry Andric 
3538349cc55cSDimitry Andric     return lowerCallTo(II, "memset", II->arg_size() - 1);
35390b57cec5SDimitry Andric   }
35400b57cec5SDimitry Andric   case Intrinsic::sin:
35410b57cec5SDimitry Andric   case Intrinsic::cos:
3542*0fca6ea1SDimitry Andric   case Intrinsic::tan:
35430b57cec5SDimitry Andric   case Intrinsic::pow: {
35440b57cec5SDimitry Andric     MVT RetVT;
35450b57cec5SDimitry Andric     if (!isTypeLegal(II->getType(), RetVT))
35460b57cec5SDimitry Andric       return false;
35470b57cec5SDimitry Andric 
35480b57cec5SDimitry Andric     if (RetVT != MVT::f32 && RetVT != MVT::f64)
35490b57cec5SDimitry Andric       return false;
35500b57cec5SDimitry Andric 
3551*0fca6ea1SDimitry Andric     static const RTLIB::Libcall LibCallTable[4][2] = {
35520b57cec5SDimitry Andric         {RTLIB::SIN_F32, RTLIB::SIN_F64},
35530b57cec5SDimitry Andric         {RTLIB::COS_F32, RTLIB::COS_F64},
3554*0fca6ea1SDimitry Andric         {RTLIB::TAN_F32, RTLIB::TAN_F64},
3555*0fca6ea1SDimitry Andric         {RTLIB::POW_F32, RTLIB::POW_F64}};
35560b57cec5SDimitry Andric     RTLIB::Libcall LC;
35570b57cec5SDimitry Andric     bool Is64Bit = RetVT == MVT::f64;
35580b57cec5SDimitry Andric     switch (II->getIntrinsicID()) {
35590b57cec5SDimitry Andric     default:
35600b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic.");
35610b57cec5SDimitry Andric     case Intrinsic::sin:
35620b57cec5SDimitry Andric       LC = LibCallTable[0][Is64Bit];
35630b57cec5SDimitry Andric       break;
35640b57cec5SDimitry Andric     case Intrinsic::cos:
35650b57cec5SDimitry Andric       LC = LibCallTable[1][Is64Bit];
35660b57cec5SDimitry Andric       break;
3567*0fca6ea1SDimitry Andric     case Intrinsic::tan:
35680b57cec5SDimitry Andric       LC = LibCallTable[2][Is64Bit];
35690b57cec5SDimitry Andric       break;
3570*0fca6ea1SDimitry Andric     case Intrinsic::pow:
3571*0fca6ea1SDimitry Andric       LC = LibCallTable[3][Is64Bit];
3572*0fca6ea1SDimitry Andric       break;
35730b57cec5SDimitry Andric     }
35740b57cec5SDimitry Andric 
35750b57cec5SDimitry Andric     ArgListTy Args;
3576349cc55cSDimitry Andric     Args.reserve(II->arg_size());
35770b57cec5SDimitry Andric 
35780b57cec5SDimitry Andric     // Populate the argument list.
3579349cc55cSDimitry Andric     for (auto &Arg : II->args()) {
35800b57cec5SDimitry Andric       ArgListEntry Entry;
35810b57cec5SDimitry Andric       Entry.Val = Arg;
35820b57cec5SDimitry Andric       Entry.Ty = Arg->getType();
35830b57cec5SDimitry Andric       Args.push_back(Entry);
35840b57cec5SDimitry Andric     }
35850b57cec5SDimitry Andric 
35860b57cec5SDimitry Andric     CallLoweringInfo CLI;
35870b57cec5SDimitry Andric     MCContext &Ctx = MF->getContext();
35880b57cec5SDimitry Andric     CLI.setCallee(DL, Ctx, TLI.getLibcallCallingConv(LC), II->getType(),
35890b57cec5SDimitry Andric                   TLI.getLibcallName(LC), std::move(Args));
35900b57cec5SDimitry Andric     if (!lowerCallTo(CLI))
35910b57cec5SDimitry Andric       return false;
35920b57cec5SDimitry Andric     updateValueMap(II, CLI.ResultReg);
35930b57cec5SDimitry Andric     return true;
35940b57cec5SDimitry Andric   }
35950b57cec5SDimitry Andric   case Intrinsic::fabs: {
35960b57cec5SDimitry Andric     MVT VT;
35970b57cec5SDimitry Andric     if (!isTypeLegal(II->getType(), VT))
35980b57cec5SDimitry Andric       return false;
35990b57cec5SDimitry Andric 
36000b57cec5SDimitry Andric     unsigned Opc;
36010b57cec5SDimitry Andric     switch (VT.SimpleTy) {
36020b57cec5SDimitry Andric     default:
36030b57cec5SDimitry Andric       return false;
36040b57cec5SDimitry Andric     case MVT::f32:
36050b57cec5SDimitry Andric       Opc = AArch64::FABSSr;
36060b57cec5SDimitry Andric       break;
36070b57cec5SDimitry Andric     case MVT::f64:
36080b57cec5SDimitry Andric       Opc = AArch64::FABSDr;
36090b57cec5SDimitry Andric       break;
36100b57cec5SDimitry Andric     }
361104eeddc0SDimitry Andric     Register SrcReg = getRegForValue(II->getOperand(0));
36120b57cec5SDimitry Andric     if (!SrcReg)
36130b57cec5SDimitry Andric       return false;
361404eeddc0SDimitry Andric     Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3615bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
3616fe6060f1SDimitry Andric       .addReg(SrcReg);
36170b57cec5SDimitry Andric     updateValueMap(II, ResultReg);
36180b57cec5SDimitry Andric     return true;
36190b57cec5SDimitry Andric   }
36200b57cec5SDimitry Andric   case Intrinsic::trap:
3621bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::BRK))
36220b57cec5SDimitry Andric         .addImm(1);
36230b57cec5SDimitry Andric     return true;
3624e8d8bef9SDimitry Andric   case Intrinsic::debugtrap:
3625bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::BRK))
36260b57cec5SDimitry Andric         .addImm(0xF000);
36270b57cec5SDimitry Andric     return true;
36280b57cec5SDimitry Andric 
36290b57cec5SDimitry Andric   case Intrinsic::sqrt: {
36300b57cec5SDimitry Andric     Type *RetTy = II->getCalledFunction()->getReturnType();
36310b57cec5SDimitry Andric 
36320b57cec5SDimitry Andric     MVT VT;
36330b57cec5SDimitry Andric     if (!isTypeLegal(RetTy, VT))
36340b57cec5SDimitry Andric       return false;
36350b57cec5SDimitry Andric 
363604eeddc0SDimitry Andric     Register Op0Reg = getRegForValue(II->getOperand(0));
36370b57cec5SDimitry Andric     if (!Op0Reg)
36380b57cec5SDimitry Andric       return false;
36390b57cec5SDimitry Andric 
3640fe6060f1SDimitry Andric     unsigned ResultReg = fastEmit_r(VT, VT, ISD::FSQRT, Op0Reg);
36410b57cec5SDimitry Andric     if (!ResultReg)
36420b57cec5SDimitry Andric       return false;
36430b57cec5SDimitry Andric 
36440b57cec5SDimitry Andric     updateValueMap(II, ResultReg);
36450b57cec5SDimitry Andric     return true;
36460b57cec5SDimitry Andric   }
36470b57cec5SDimitry Andric   case Intrinsic::sadd_with_overflow:
36480b57cec5SDimitry Andric   case Intrinsic::uadd_with_overflow:
36490b57cec5SDimitry Andric   case Intrinsic::ssub_with_overflow:
36500b57cec5SDimitry Andric   case Intrinsic::usub_with_overflow:
36510b57cec5SDimitry Andric   case Intrinsic::smul_with_overflow:
36520b57cec5SDimitry Andric   case Intrinsic::umul_with_overflow: {
36530b57cec5SDimitry Andric     // This implements the basic lowering of the xalu with overflow intrinsics.
36540b57cec5SDimitry Andric     const Function *Callee = II->getCalledFunction();
36550b57cec5SDimitry Andric     auto *Ty = cast<StructType>(Callee->getReturnType());
36560b57cec5SDimitry Andric     Type *RetTy = Ty->getTypeAtIndex(0U);
36570b57cec5SDimitry Andric 
36580b57cec5SDimitry Andric     MVT VT;
36590b57cec5SDimitry Andric     if (!isTypeLegal(RetTy, VT))
36600b57cec5SDimitry Andric       return false;
36610b57cec5SDimitry Andric 
36620b57cec5SDimitry Andric     if (VT != MVT::i32 && VT != MVT::i64)
36630b57cec5SDimitry Andric       return false;
36640b57cec5SDimitry Andric 
36650b57cec5SDimitry Andric     const Value *LHS = II->getArgOperand(0);
36660b57cec5SDimitry Andric     const Value *RHS = II->getArgOperand(1);
36670b57cec5SDimitry Andric     // Canonicalize immediate to the RHS.
3668e8d8bef9SDimitry Andric     if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS) && II->isCommutative())
36690b57cec5SDimitry Andric       std::swap(LHS, RHS);
36700b57cec5SDimitry Andric 
36710b57cec5SDimitry Andric     // Simplify multiplies.
36720b57cec5SDimitry Andric     Intrinsic::ID IID = II->getIntrinsicID();
36730b57cec5SDimitry Andric     switch (IID) {
36740b57cec5SDimitry Andric     default:
36750b57cec5SDimitry Andric       break;
36760b57cec5SDimitry Andric     case Intrinsic::smul_with_overflow:
36770b57cec5SDimitry Andric       if (const auto *C = dyn_cast<ConstantInt>(RHS))
36780b57cec5SDimitry Andric         if (C->getValue() == 2) {
36790b57cec5SDimitry Andric           IID = Intrinsic::sadd_with_overflow;
36800b57cec5SDimitry Andric           RHS = LHS;
36810b57cec5SDimitry Andric         }
36820b57cec5SDimitry Andric       break;
36830b57cec5SDimitry Andric     case Intrinsic::umul_with_overflow:
36840b57cec5SDimitry Andric       if (const auto *C = dyn_cast<ConstantInt>(RHS))
36850b57cec5SDimitry Andric         if (C->getValue() == 2) {
36860b57cec5SDimitry Andric           IID = Intrinsic::uadd_with_overflow;
36870b57cec5SDimitry Andric           RHS = LHS;
36880b57cec5SDimitry Andric         }
36890b57cec5SDimitry Andric       break;
36900b57cec5SDimitry Andric     }
36910b57cec5SDimitry Andric 
36920b57cec5SDimitry Andric     unsigned ResultReg1 = 0, ResultReg2 = 0, MulReg = 0;
36930b57cec5SDimitry Andric     AArch64CC::CondCode CC = AArch64CC::Invalid;
36940b57cec5SDimitry Andric     switch (IID) {
36950b57cec5SDimitry Andric     default: llvm_unreachable("Unexpected intrinsic!");
36960b57cec5SDimitry Andric     case Intrinsic::sadd_with_overflow:
36970b57cec5SDimitry Andric       ResultReg1 = emitAdd(VT, LHS, RHS, /*SetFlags=*/true);
36980b57cec5SDimitry Andric       CC = AArch64CC::VS;
36990b57cec5SDimitry Andric       break;
37000b57cec5SDimitry Andric     case Intrinsic::uadd_with_overflow:
37010b57cec5SDimitry Andric       ResultReg1 = emitAdd(VT, LHS, RHS, /*SetFlags=*/true);
37020b57cec5SDimitry Andric       CC = AArch64CC::HS;
37030b57cec5SDimitry Andric       break;
37040b57cec5SDimitry Andric     case Intrinsic::ssub_with_overflow:
37050b57cec5SDimitry Andric       ResultReg1 = emitSub(VT, LHS, RHS, /*SetFlags=*/true);
37060b57cec5SDimitry Andric       CC = AArch64CC::VS;
37070b57cec5SDimitry Andric       break;
37080b57cec5SDimitry Andric     case Intrinsic::usub_with_overflow:
37090b57cec5SDimitry Andric       ResultReg1 = emitSub(VT, LHS, RHS, /*SetFlags=*/true);
37100b57cec5SDimitry Andric       CC = AArch64CC::LO;
37110b57cec5SDimitry Andric       break;
37120b57cec5SDimitry Andric     case Intrinsic::smul_with_overflow: {
37130b57cec5SDimitry Andric       CC = AArch64CC::NE;
371404eeddc0SDimitry Andric       Register LHSReg = getRegForValue(LHS);
37150b57cec5SDimitry Andric       if (!LHSReg)
37160b57cec5SDimitry Andric         return false;
37170b57cec5SDimitry Andric 
371804eeddc0SDimitry Andric       Register RHSReg = getRegForValue(RHS);
37190b57cec5SDimitry Andric       if (!RHSReg)
37200b57cec5SDimitry Andric         return false;
37210b57cec5SDimitry Andric 
37220b57cec5SDimitry Andric       if (VT == MVT::i32) {
3723fe6060f1SDimitry Andric         MulReg = emitSMULL_rr(MVT::i64, LHSReg, RHSReg);
372404eeddc0SDimitry Andric         Register MulSubReg =
3725fe6060f1SDimitry Andric             fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3726fe6060f1SDimitry Andric         // cmp xreg, wreg, sxtw
3727fe6060f1SDimitry Andric         emitAddSub_rx(/*UseAdd=*/false, MVT::i64, MulReg, MulSubReg,
3728fe6060f1SDimitry Andric                       AArch64_AM::SXTW, /*ShiftImm=*/0, /*SetFlags=*/true,
3729fe6060f1SDimitry Andric                       /*WantResult=*/false);
3730fe6060f1SDimitry Andric         MulReg = MulSubReg;
37310b57cec5SDimitry Andric       } else {
37320b57cec5SDimitry Andric         assert(VT == MVT::i64 && "Unexpected value type.");
37330b57cec5SDimitry Andric         // LHSReg and RHSReg cannot be killed by this Mul, since they are
37340b57cec5SDimitry Andric         // reused in the next instruction.
3735fe6060f1SDimitry Andric         MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3736fe6060f1SDimitry Andric         unsigned SMULHReg = fastEmit_rr(VT, VT, ISD::MULHS, LHSReg, RHSReg);
3737fe6060f1SDimitry Andric         emitSubs_rs(VT, SMULHReg, MulReg, AArch64_AM::ASR, 63,
3738fe6060f1SDimitry Andric                     /*WantResult=*/false);
37390b57cec5SDimitry Andric       }
37400b57cec5SDimitry Andric       break;
37410b57cec5SDimitry Andric     }
37420b57cec5SDimitry Andric     case Intrinsic::umul_with_overflow: {
37430b57cec5SDimitry Andric       CC = AArch64CC::NE;
374404eeddc0SDimitry Andric       Register LHSReg = getRegForValue(LHS);
37450b57cec5SDimitry Andric       if (!LHSReg)
37460b57cec5SDimitry Andric         return false;
37470b57cec5SDimitry Andric 
374804eeddc0SDimitry Andric       Register RHSReg = getRegForValue(RHS);
37490b57cec5SDimitry Andric       if (!RHSReg)
37500b57cec5SDimitry Andric         return false;
37510b57cec5SDimitry Andric 
37520b57cec5SDimitry Andric       if (VT == MVT::i32) {
3753fe6060f1SDimitry Andric         MulReg = emitUMULL_rr(MVT::i64, LHSReg, RHSReg);
3754fe6060f1SDimitry Andric         // tst xreg, #0xffffffff00000000
3755bdd1243dSDimitry Andric         BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3756fe6060f1SDimitry Andric                 TII.get(AArch64::ANDSXri), AArch64::XZR)
3757fe6060f1SDimitry Andric             .addReg(MulReg)
3758fe6060f1SDimitry Andric             .addImm(AArch64_AM::encodeLogicalImmediate(0xFFFFFFFF00000000, 64));
3759fe6060f1SDimitry Andric         MulReg = fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
37600b57cec5SDimitry Andric       } else {
37610b57cec5SDimitry Andric         assert(VT == MVT::i64 && "Unexpected value type.");
37620b57cec5SDimitry Andric         // LHSReg and RHSReg cannot be killed by this Mul, since they are
37630b57cec5SDimitry Andric         // reused in the next instruction.
3764fe6060f1SDimitry Andric         MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3765fe6060f1SDimitry Andric         unsigned UMULHReg = fastEmit_rr(VT, VT, ISD::MULHU, LHSReg, RHSReg);
3766fe6060f1SDimitry Andric         emitSubs_rr(VT, AArch64::XZR, UMULHReg, /*WantResult=*/false);
37670b57cec5SDimitry Andric       }
37680b57cec5SDimitry Andric       break;
37690b57cec5SDimitry Andric     }
37700b57cec5SDimitry Andric     }
37710b57cec5SDimitry Andric 
37720b57cec5SDimitry Andric     if (MulReg) {
37730b57cec5SDimitry Andric       ResultReg1 = createResultReg(TLI.getRegClassFor(VT));
3774bdd1243dSDimitry Andric       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
37750b57cec5SDimitry Andric               TII.get(TargetOpcode::COPY), ResultReg1).addReg(MulReg);
37760b57cec5SDimitry Andric     }
37770b57cec5SDimitry Andric 
37780b57cec5SDimitry Andric     if (!ResultReg1)
37790b57cec5SDimitry Andric       return false;
37800b57cec5SDimitry Andric 
37810b57cec5SDimitry Andric     ResultReg2 = fastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,
3782fe6060f1SDimitry Andric                                   AArch64::WZR, AArch64::WZR,
3783fe6060f1SDimitry Andric                                   getInvertedCondCode(CC));
37840b57cec5SDimitry Andric     (void)ResultReg2;
37850b57cec5SDimitry Andric     assert((ResultReg1 + 1) == ResultReg2 &&
37860b57cec5SDimitry Andric            "Nonconsecutive result registers.");
37870b57cec5SDimitry Andric     updateValueMap(II, ResultReg1, 2);
37880b57cec5SDimitry Andric     return true;
37890b57cec5SDimitry Andric   }
379006c3fb27SDimitry Andric   case Intrinsic::aarch64_crc32b:
379106c3fb27SDimitry Andric   case Intrinsic::aarch64_crc32h:
379206c3fb27SDimitry Andric   case Intrinsic::aarch64_crc32w:
379306c3fb27SDimitry Andric   case Intrinsic::aarch64_crc32x:
379406c3fb27SDimitry Andric   case Intrinsic::aarch64_crc32cb:
379506c3fb27SDimitry Andric   case Intrinsic::aarch64_crc32ch:
379606c3fb27SDimitry Andric   case Intrinsic::aarch64_crc32cw:
379706c3fb27SDimitry Andric   case Intrinsic::aarch64_crc32cx: {
379806c3fb27SDimitry Andric     if (!Subtarget->hasCRC())
379906c3fb27SDimitry Andric       return false;
380006c3fb27SDimitry Andric 
380106c3fb27SDimitry Andric     unsigned Opc;
380206c3fb27SDimitry Andric     switch (II->getIntrinsicID()) {
380306c3fb27SDimitry Andric     default:
380406c3fb27SDimitry Andric       llvm_unreachable("Unexpected intrinsic!");
380506c3fb27SDimitry Andric     case Intrinsic::aarch64_crc32b:
380606c3fb27SDimitry Andric       Opc = AArch64::CRC32Brr;
380706c3fb27SDimitry Andric       break;
380806c3fb27SDimitry Andric     case Intrinsic::aarch64_crc32h:
380906c3fb27SDimitry Andric       Opc = AArch64::CRC32Hrr;
381006c3fb27SDimitry Andric       break;
381106c3fb27SDimitry Andric     case Intrinsic::aarch64_crc32w:
381206c3fb27SDimitry Andric       Opc = AArch64::CRC32Wrr;
381306c3fb27SDimitry Andric       break;
381406c3fb27SDimitry Andric     case Intrinsic::aarch64_crc32x:
381506c3fb27SDimitry Andric       Opc = AArch64::CRC32Xrr;
381606c3fb27SDimitry Andric       break;
381706c3fb27SDimitry Andric     case Intrinsic::aarch64_crc32cb:
381806c3fb27SDimitry Andric       Opc = AArch64::CRC32CBrr;
381906c3fb27SDimitry Andric       break;
382006c3fb27SDimitry Andric     case Intrinsic::aarch64_crc32ch:
382106c3fb27SDimitry Andric       Opc = AArch64::CRC32CHrr;
382206c3fb27SDimitry Andric       break;
382306c3fb27SDimitry Andric     case Intrinsic::aarch64_crc32cw:
382406c3fb27SDimitry Andric       Opc = AArch64::CRC32CWrr;
382506c3fb27SDimitry Andric       break;
382606c3fb27SDimitry Andric     case Intrinsic::aarch64_crc32cx:
382706c3fb27SDimitry Andric       Opc = AArch64::CRC32CXrr;
382806c3fb27SDimitry Andric       break;
382906c3fb27SDimitry Andric     }
383006c3fb27SDimitry Andric 
383106c3fb27SDimitry Andric     Register LHSReg = getRegForValue(II->getArgOperand(0));
383206c3fb27SDimitry Andric     Register RHSReg = getRegForValue(II->getArgOperand(1));
383306c3fb27SDimitry Andric     if (!LHSReg || !RHSReg)
383406c3fb27SDimitry Andric       return false;
383506c3fb27SDimitry Andric 
383606c3fb27SDimitry Andric     Register ResultReg =
383706c3fb27SDimitry Andric         fastEmitInst_rr(Opc, &AArch64::GPR32RegClass, LHSReg, RHSReg);
383806c3fb27SDimitry Andric     updateValueMap(II, ResultReg);
383906c3fb27SDimitry Andric     return true;
384006c3fb27SDimitry Andric   }
38410b57cec5SDimitry Andric   }
38420b57cec5SDimitry Andric   return false;
38430b57cec5SDimitry Andric }
38440b57cec5SDimitry Andric 
38450b57cec5SDimitry Andric bool AArch64FastISel::selectRet(const Instruction *I) {
38460b57cec5SDimitry Andric   const ReturnInst *Ret = cast<ReturnInst>(I);
38470b57cec5SDimitry Andric   const Function &F = *I->getParent()->getParent();
38480b57cec5SDimitry Andric 
38490b57cec5SDimitry Andric   if (!FuncInfo.CanLowerReturn)
38500b57cec5SDimitry Andric     return false;
38510b57cec5SDimitry Andric 
38520b57cec5SDimitry Andric   if (F.isVarArg())
38530b57cec5SDimitry Andric     return false;
38540b57cec5SDimitry Andric 
38550b57cec5SDimitry Andric   if (TLI.supportSwiftError() &&
38560b57cec5SDimitry Andric       F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
38570b57cec5SDimitry Andric     return false;
38580b57cec5SDimitry Andric 
38590b57cec5SDimitry Andric   if (TLI.supportSplitCSR(FuncInfo.MF))
38600b57cec5SDimitry Andric     return false;
38610b57cec5SDimitry Andric 
38620b57cec5SDimitry Andric   // Build a list of return value registers.
38630b57cec5SDimitry Andric   SmallVector<unsigned, 4> RetRegs;
38640b57cec5SDimitry Andric 
38650b57cec5SDimitry Andric   if (Ret->getNumOperands() > 0) {
38660b57cec5SDimitry Andric     CallingConv::ID CC = F.getCallingConv();
38670b57cec5SDimitry Andric     SmallVector<ISD::OutputArg, 4> Outs;
38680b57cec5SDimitry Andric     GetReturnInfo(CC, F.getReturnType(), F.getAttributes(), Outs, TLI, DL);
38690b57cec5SDimitry Andric 
38700b57cec5SDimitry Andric     // Analyze operands of the call, assigning locations to each operand.
38710b57cec5SDimitry Andric     SmallVector<CCValAssign, 16> ValLocs;
38720b57cec5SDimitry Andric     CCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs, I->getContext());
38735f757f3fSDimitry Andric     CCInfo.AnalyzeReturn(Outs, RetCC_AArch64_AAPCS);
38740b57cec5SDimitry Andric 
38750b57cec5SDimitry Andric     // Only handle a single return value for now.
38760b57cec5SDimitry Andric     if (ValLocs.size() != 1)
38770b57cec5SDimitry Andric       return false;
38780b57cec5SDimitry Andric 
38790b57cec5SDimitry Andric     CCValAssign &VA = ValLocs[0];
38800b57cec5SDimitry Andric     const Value *RV = Ret->getOperand(0);
38810b57cec5SDimitry Andric 
38820b57cec5SDimitry Andric     // Don't bother handling odd stuff for now.
38830b57cec5SDimitry Andric     if ((VA.getLocInfo() != CCValAssign::Full) &&
38840b57cec5SDimitry Andric         (VA.getLocInfo() != CCValAssign::BCvt))
38850b57cec5SDimitry Andric       return false;
38860b57cec5SDimitry Andric 
38870b57cec5SDimitry Andric     // Only handle register returns for now.
38880b57cec5SDimitry Andric     if (!VA.isRegLoc())
38890b57cec5SDimitry Andric       return false;
38900b57cec5SDimitry Andric 
389104eeddc0SDimitry Andric     Register Reg = getRegForValue(RV);
38920b57cec5SDimitry Andric     if (Reg == 0)
38930b57cec5SDimitry Andric       return false;
38940b57cec5SDimitry Andric 
38950b57cec5SDimitry Andric     unsigned SrcReg = Reg + VA.getValNo();
38968bcb0991SDimitry Andric     Register DestReg = VA.getLocReg();
38970b57cec5SDimitry Andric     // Avoid a cross-class copy. This is very unlikely.
38980b57cec5SDimitry Andric     if (!MRI.getRegClass(SrcReg)->contains(DestReg))
38990b57cec5SDimitry Andric       return false;
39000b57cec5SDimitry Andric 
39010b57cec5SDimitry Andric     EVT RVEVT = TLI.getValueType(DL, RV->getType());
39020b57cec5SDimitry Andric     if (!RVEVT.isSimple())
39030b57cec5SDimitry Andric       return false;
39040b57cec5SDimitry Andric 
39050b57cec5SDimitry Andric     // Vectors (of > 1 lane) in big endian need tricky handling.
3906fe6060f1SDimitry Andric     if (RVEVT.isVector() && RVEVT.getVectorElementCount().isVector() &&
39070b57cec5SDimitry Andric         !Subtarget->isLittleEndian())
39080b57cec5SDimitry Andric       return false;
39090b57cec5SDimitry Andric 
39100b57cec5SDimitry Andric     MVT RVVT = RVEVT.getSimpleVT();
39110b57cec5SDimitry Andric     if (RVVT == MVT::f128)
39120b57cec5SDimitry Andric       return false;
39130b57cec5SDimitry Andric 
39140b57cec5SDimitry Andric     MVT DestVT = VA.getValVT();
39150b57cec5SDimitry Andric     // Special handling for extended integers.
39160b57cec5SDimitry Andric     if (RVVT != DestVT) {
39170b57cec5SDimitry Andric       if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
39180b57cec5SDimitry Andric         return false;
39190b57cec5SDimitry Andric 
39200b57cec5SDimitry Andric       if (!Outs[0].Flags.isZExt() && !Outs[0].Flags.isSExt())
39210b57cec5SDimitry Andric         return false;
39220b57cec5SDimitry Andric 
39230b57cec5SDimitry Andric       bool IsZExt = Outs[0].Flags.isZExt();
39240b57cec5SDimitry Andric       SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
39250b57cec5SDimitry Andric       if (SrcReg == 0)
39260b57cec5SDimitry Andric         return false;
39270b57cec5SDimitry Andric     }
39280b57cec5SDimitry Andric 
3929480093f4SDimitry Andric     // "Callee" (i.e. value producer) zero extends pointers at function
3930480093f4SDimitry Andric     // boundary.
3931480093f4SDimitry Andric     if (Subtarget->isTargetILP32() && RV->getType()->isPointerTy())
3932fe6060f1SDimitry Andric       SrcReg = emitAnd_ri(MVT::i64, SrcReg, 0xffffffff);
3933480093f4SDimitry Andric 
39340b57cec5SDimitry Andric     // Make the copy.
3935bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
39360b57cec5SDimitry Andric             TII.get(TargetOpcode::COPY), DestReg).addReg(SrcReg);
39370b57cec5SDimitry Andric 
39380b57cec5SDimitry Andric     // Add register to return instruction.
39390b57cec5SDimitry Andric     RetRegs.push_back(VA.getLocReg());
39400b57cec5SDimitry Andric   }
39410b57cec5SDimitry Andric 
3942bdd1243dSDimitry Andric   MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
39430b57cec5SDimitry Andric                                     TII.get(AArch64::RET_ReallyLR));
39440b57cec5SDimitry Andric   for (unsigned RetReg : RetRegs)
39450b57cec5SDimitry Andric     MIB.addReg(RetReg, RegState::Implicit);
39460b57cec5SDimitry Andric   return true;
39470b57cec5SDimitry Andric }
39480b57cec5SDimitry Andric 
39490b57cec5SDimitry Andric bool AArch64FastISel::selectTrunc(const Instruction *I) {
39500b57cec5SDimitry Andric   Type *DestTy = I->getType();
39510b57cec5SDimitry Andric   Value *Op = I->getOperand(0);
39520b57cec5SDimitry Andric   Type *SrcTy = Op->getType();
39530b57cec5SDimitry Andric 
39540b57cec5SDimitry Andric   EVT SrcEVT = TLI.getValueType(DL, SrcTy, true);
39550b57cec5SDimitry Andric   EVT DestEVT = TLI.getValueType(DL, DestTy, true);
39560b57cec5SDimitry Andric   if (!SrcEVT.isSimple())
39570b57cec5SDimitry Andric     return false;
39580b57cec5SDimitry Andric   if (!DestEVT.isSimple())
39590b57cec5SDimitry Andric     return false;
39600b57cec5SDimitry Andric 
39610b57cec5SDimitry Andric   MVT SrcVT = SrcEVT.getSimpleVT();
39620b57cec5SDimitry Andric   MVT DestVT = DestEVT.getSimpleVT();
39630b57cec5SDimitry Andric 
39640b57cec5SDimitry Andric   if (SrcVT != MVT::i64 && SrcVT != MVT::i32 && SrcVT != MVT::i16 &&
39650b57cec5SDimitry Andric       SrcVT != MVT::i8)
39660b57cec5SDimitry Andric     return false;
39670b57cec5SDimitry Andric   if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8 &&
39680b57cec5SDimitry Andric       DestVT != MVT::i1)
39690b57cec5SDimitry Andric     return false;
39700b57cec5SDimitry Andric 
397104eeddc0SDimitry Andric   Register SrcReg = getRegForValue(Op);
39720b57cec5SDimitry Andric   if (!SrcReg)
39730b57cec5SDimitry Andric     return false;
39740b57cec5SDimitry Andric 
39750b57cec5SDimitry Andric   // If we're truncating from i64 to a smaller non-legal type then generate an
39760b57cec5SDimitry Andric   // AND. Otherwise, we know the high bits are undefined and a truncate only
39770b57cec5SDimitry Andric   // generate a COPY. We cannot mark the source register also as result
39780b57cec5SDimitry Andric   // register, because this can incorrectly transfer the kill flag onto the
39790b57cec5SDimitry Andric   // source register.
39800b57cec5SDimitry Andric   unsigned ResultReg;
39810b57cec5SDimitry Andric   if (SrcVT == MVT::i64) {
39820b57cec5SDimitry Andric     uint64_t Mask = 0;
39830b57cec5SDimitry Andric     switch (DestVT.SimpleTy) {
39840b57cec5SDimitry Andric     default:
39850b57cec5SDimitry Andric       // Trunc i64 to i32 is handled by the target-independent fast-isel.
39860b57cec5SDimitry Andric       return false;
39870b57cec5SDimitry Andric     case MVT::i1:
39880b57cec5SDimitry Andric       Mask = 0x1;
39890b57cec5SDimitry Andric       break;
39900b57cec5SDimitry Andric     case MVT::i8:
39910b57cec5SDimitry Andric       Mask = 0xff;
39920b57cec5SDimitry Andric       break;
39930b57cec5SDimitry Andric     case MVT::i16:
39940b57cec5SDimitry Andric       Mask = 0xffff;
39950b57cec5SDimitry Andric       break;
39960b57cec5SDimitry Andric     }
39970b57cec5SDimitry Andric     // Issue an extract_subreg to get the lower 32-bits.
399804eeddc0SDimitry Andric     Register Reg32 = fastEmitInst_extractsubreg(MVT::i32, SrcReg,
39990b57cec5SDimitry Andric                                                 AArch64::sub_32);
40000b57cec5SDimitry Andric     // Create the AND instruction which performs the actual truncation.
4001fe6060f1SDimitry Andric     ResultReg = emitAnd_ri(MVT::i32, Reg32, Mask);
40020b57cec5SDimitry Andric     assert(ResultReg && "Unexpected AND instruction emission failure.");
40030b57cec5SDimitry Andric   } else {
40040b57cec5SDimitry Andric     ResultReg = createResultReg(&AArch64::GPR32RegClass);
4005bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
40060b57cec5SDimitry Andric             TII.get(TargetOpcode::COPY), ResultReg)
4007fe6060f1SDimitry Andric         .addReg(SrcReg);
40080b57cec5SDimitry Andric   }
40090b57cec5SDimitry Andric 
40100b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
40110b57cec5SDimitry Andric   return true;
40120b57cec5SDimitry Andric }
40130b57cec5SDimitry Andric 
40140b57cec5SDimitry Andric unsigned AArch64FastISel::emiti1Ext(unsigned SrcReg, MVT DestVT, bool IsZExt) {
40150b57cec5SDimitry Andric   assert((DestVT == MVT::i8 || DestVT == MVT::i16 || DestVT == MVT::i32 ||
40160b57cec5SDimitry Andric           DestVT == MVT::i64) &&
40170b57cec5SDimitry Andric          "Unexpected value type.");
40180b57cec5SDimitry Andric   // Handle i8 and i16 as i32.
40190b57cec5SDimitry Andric   if (DestVT == MVT::i8 || DestVT == MVT::i16)
40200b57cec5SDimitry Andric     DestVT = MVT::i32;
40210b57cec5SDimitry Andric 
40220b57cec5SDimitry Andric   if (IsZExt) {
4023fe6060f1SDimitry Andric     unsigned ResultReg = emitAnd_ri(MVT::i32, SrcReg, 1);
40240b57cec5SDimitry Andric     assert(ResultReg && "Unexpected AND instruction emission failure.");
40250b57cec5SDimitry Andric     if (DestVT == MVT::i64) {
40260b57cec5SDimitry Andric       // We're ZExt i1 to i64.  The ANDWri Wd, Ws, #1 implicitly clears the
40270b57cec5SDimitry Andric       // upper 32 bits.  Emit a SUBREG_TO_REG to extend from Wd to Xd.
40288bcb0991SDimitry Andric       Register Reg64 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4029bdd1243dSDimitry Andric       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
40300b57cec5SDimitry Andric               TII.get(AArch64::SUBREG_TO_REG), Reg64)
40310b57cec5SDimitry Andric           .addImm(0)
40320b57cec5SDimitry Andric           .addReg(ResultReg)
40330b57cec5SDimitry Andric           .addImm(AArch64::sub_32);
40340b57cec5SDimitry Andric       ResultReg = Reg64;
40350b57cec5SDimitry Andric     }
40360b57cec5SDimitry Andric     return ResultReg;
40370b57cec5SDimitry Andric   } else {
40380b57cec5SDimitry Andric     if (DestVT == MVT::i64) {
40390b57cec5SDimitry Andric       // FIXME: We're SExt i1 to i64.
40400b57cec5SDimitry Andric       return 0;
40410b57cec5SDimitry Andric     }
40420b57cec5SDimitry Andric     return fastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,
4043fe6060f1SDimitry Andric                             0, 0);
40440b57cec5SDimitry Andric   }
40450b57cec5SDimitry Andric }
40460b57cec5SDimitry Andric 
4047fe6060f1SDimitry Andric unsigned AArch64FastISel::emitMul_rr(MVT RetVT, unsigned Op0, unsigned Op1) {
40480b57cec5SDimitry Andric   unsigned Opc, ZReg;
40490b57cec5SDimitry Andric   switch (RetVT.SimpleTy) {
40500b57cec5SDimitry Andric   default: return 0;
40510b57cec5SDimitry Andric   case MVT::i8:
40520b57cec5SDimitry Andric   case MVT::i16:
40530b57cec5SDimitry Andric   case MVT::i32:
40540b57cec5SDimitry Andric     RetVT = MVT::i32;
40550b57cec5SDimitry Andric     Opc = AArch64::MADDWrrr; ZReg = AArch64::WZR; break;
40560b57cec5SDimitry Andric   case MVT::i64:
40570b57cec5SDimitry Andric     Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR; break;
40580b57cec5SDimitry Andric   }
40590b57cec5SDimitry Andric 
40600b57cec5SDimitry Andric   const TargetRegisterClass *RC =
40610b57cec5SDimitry Andric       (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4062fe6060f1SDimitry Andric   return fastEmitInst_rrr(Opc, RC, Op0, Op1, ZReg);
40630b57cec5SDimitry Andric }
40640b57cec5SDimitry Andric 
4065fe6060f1SDimitry Andric unsigned AArch64FastISel::emitSMULL_rr(MVT RetVT, unsigned Op0, unsigned Op1) {
40660b57cec5SDimitry Andric   if (RetVT != MVT::i64)
40670b57cec5SDimitry Andric     return 0;
40680b57cec5SDimitry Andric 
40690b57cec5SDimitry Andric   return fastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,
4070fe6060f1SDimitry Andric                           Op0, Op1, AArch64::XZR);
40710b57cec5SDimitry Andric }
40720b57cec5SDimitry Andric 
4073fe6060f1SDimitry Andric unsigned AArch64FastISel::emitUMULL_rr(MVT RetVT, unsigned Op0, unsigned Op1) {
40740b57cec5SDimitry Andric   if (RetVT != MVT::i64)
40750b57cec5SDimitry Andric     return 0;
40760b57cec5SDimitry Andric 
40770b57cec5SDimitry Andric   return fastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,
4078fe6060f1SDimitry Andric                           Op0, Op1, AArch64::XZR);
40790b57cec5SDimitry Andric }
40800b57cec5SDimitry Andric 
4081fe6060f1SDimitry Andric unsigned AArch64FastISel::emitLSL_rr(MVT RetVT, unsigned Op0Reg,
4082fe6060f1SDimitry Andric                                      unsigned Op1Reg) {
40830b57cec5SDimitry Andric   unsigned Opc = 0;
40840b57cec5SDimitry Andric   bool NeedTrunc = false;
40850b57cec5SDimitry Andric   uint64_t Mask = 0;
40860b57cec5SDimitry Andric   switch (RetVT.SimpleTy) {
40870b57cec5SDimitry Andric   default: return 0;
40880b57cec5SDimitry Andric   case MVT::i8:  Opc = AArch64::LSLVWr; NeedTrunc = true; Mask = 0xff;   break;
40890b57cec5SDimitry Andric   case MVT::i16: Opc = AArch64::LSLVWr; NeedTrunc = true; Mask = 0xffff; break;
40900b57cec5SDimitry Andric   case MVT::i32: Opc = AArch64::LSLVWr;                                  break;
40910b57cec5SDimitry Andric   case MVT::i64: Opc = AArch64::LSLVXr;                                  break;
40920b57cec5SDimitry Andric   }
40930b57cec5SDimitry Andric 
40940b57cec5SDimitry Andric   const TargetRegisterClass *RC =
40950b57cec5SDimitry Andric       (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
40960b57cec5SDimitry Andric   if (NeedTrunc)
4097fe6060f1SDimitry Andric     Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4098fe6060f1SDimitry Andric 
409904eeddc0SDimitry Andric   Register ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op1Reg);
4100fe6060f1SDimitry Andric   if (NeedTrunc)
4101fe6060f1SDimitry Andric     ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
41020b57cec5SDimitry Andric   return ResultReg;
41030b57cec5SDimitry Andric }
41040b57cec5SDimitry Andric 
41050b57cec5SDimitry Andric unsigned AArch64FastISel::emitLSL_ri(MVT RetVT, MVT SrcVT, unsigned Op0,
4106fe6060f1SDimitry Andric                                      uint64_t Shift, bool IsZExt) {
41070b57cec5SDimitry Andric   assert(RetVT.SimpleTy >= SrcVT.SimpleTy &&
41080b57cec5SDimitry Andric          "Unexpected source/return type pair.");
41090b57cec5SDimitry Andric   assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
41100b57cec5SDimitry Andric           SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
41110b57cec5SDimitry Andric          "Unexpected source value type.");
41120b57cec5SDimitry Andric   assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
41130b57cec5SDimitry Andric           RetVT == MVT::i64) && "Unexpected return value type.");
41140b57cec5SDimitry Andric 
41150b57cec5SDimitry Andric   bool Is64Bit = (RetVT == MVT::i64);
41160b57cec5SDimitry Andric   unsigned RegSize = Is64Bit ? 64 : 32;
41170b57cec5SDimitry Andric   unsigned DstBits = RetVT.getSizeInBits();
41180b57cec5SDimitry Andric   unsigned SrcBits = SrcVT.getSizeInBits();
41190b57cec5SDimitry Andric   const TargetRegisterClass *RC =
41200b57cec5SDimitry Andric       Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
41210b57cec5SDimitry Andric 
41220b57cec5SDimitry Andric   // Just emit a copy for "zero" shifts.
41230b57cec5SDimitry Andric   if (Shift == 0) {
41240b57cec5SDimitry Andric     if (RetVT == SrcVT) {
412504eeddc0SDimitry Andric       Register ResultReg = createResultReg(RC);
4126bdd1243dSDimitry Andric       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
41270b57cec5SDimitry Andric               TII.get(TargetOpcode::COPY), ResultReg)
4128fe6060f1SDimitry Andric           .addReg(Op0);
41290b57cec5SDimitry Andric       return ResultReg;
41300b57cec5SDimitry Andric     } else
41310b57cec5SDimitry Andric       return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
41320b57cec5SDimitry Andric   }
41330b57cec5SDimitry Andric 
41340b57cec5SDimitry Andric   // Don't deal with undefined shifts.
41350b57cec5SDimitry Andric   if (Shift >= DstBits)
41360b57cec5SDimitry Andric     return 0;
41370b57cec5SDimitry Andric 
41380b57cec5SDimitry Andric   // For immediate shifts we can fold the zero-/sign-extension into the shift.
41390b57cec5SDimitry Andric   // {S|U}BFM Wd, Wn, #r, #s
41400b57cec5SDimitry Andric   // Wd<32+s-r,32-r> = Wn<s:0> when r > s
41410b57cec5SDimitry Andric 
41420b57cec5SDimitry Andric   // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
41430b57cec5SDimitry Andric   // %2 = shl i16 %1, 4
41440b57cec5SDimitry Andric   // Wd<32+7-28,32-28> = Wn<7:0> <- clamp s to 7
41450b57cec5SDimitry Andric   // 0b1111_1111_1111_1111__1111_1010_1010_0000 sext
41460b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0101_0101_0000 sext | zext
41470b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_1010_1010_0000 zext
41480b57cec5SDimitry Andric 
41490b57cec5SDimitry Andric   // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
41500b57cec5SDimitry Andric   // %2 = shl i16 %1, 8
41510b57cec5SDimitry Andric   // Wd<32+7-24,32-24> = Wn<7:0>
41520b57cec5SDimitry Andric   // 0b1111_1111_1111_1111__1010_1010_0000_0000 sext
41530b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0101_0101_0000_0000 sext | zext
41540b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__1010_1010_0000_0000 zext
41550b57cec5SDimitry Andric 
41560b57cec5SDimitry Andric   // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
41570b57cec5SDimitry Andric   // %2 = shl i16 %1, 12
41580b57cec5SDimitry Andric   // Wd<32+3-20,32-20> = Wn<3:0>
41590b57cec5SDimitry Andric   // 0b1111_1111_1111_1111__1010_0000_0000_0000 sext
41600b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0101_0000_0000_0000 sext | zext
41610b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__1010_0000_0000_0000 zext
41620b57cec5SDimitry Andric 
41630b57cec5SDimitry Andric   unsigned ImmR = RegSize - Shift;
41640b57cec5SDimitry Andric   // Limit the width to the length of the source type.
41650b57cec5SDimitry Andric   unsigned ImmS = std::min<unsigned>(SrcBits - 1, DstBits - 1 - Shift);
41660b57cec5SDimitry Andric   static const unsigned OpcTable[2][2] = {
41670b57cec5SDimitry Andric     {AArch64::SBFMWri, AArch64::SBFMXri},
41680b57cec5SDimitry Andric     {AArch64::UBFMWri, AArch64::UBFMXri}
41690b57cec5SDimitry Andric   };
41700b57cec5SDimitry Andric   unsigned Opc = OpcTable[IsZExt][Is64Bit];
41710b57cec5SDimitry Andric   if (SrcVT.SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
41728bcb0991SDimitry Andric     Register TmpReg = MRI.createVirtualRegister(RC);
4173bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
41740b57cec5SDimitry Andric             TII.get(AArch64::SUBREG_TO_REG), TmpReg)
41750b57cec5SDimitry Andric         .addImm(0)
4176fe6060f1SDimitry Andric         .addReg(Op0)
41770b57cec5SDimitry Andric         .addImm(AArch64::sub_32);
41780b57cec5SDimitry Andric     Op0 = TmpReg;
41790b57cec5SDimitry Andric   }
4180fe6060f1SDimitry Andric   return fastEmitInst_rii(Opc, RC, Op0, ImmR, ImmS);
41810b57cec5SDimitry Andric }
41820b57cec5SDimitry Andric 
4183fe6060f1SDimitry Andric unsigned AArch64FastISel::emitLSR_rr(MVT RetVT, unsigned Op0Reg,
4184fe6060f1SDimitry Andric                                      unsigned Op1Reg) {
41850b57cec5SDimitry Andric   unsigned Opc = 0;
41860b57cec5SDimitry Andric   bool NeedTrunc = false;
41870b57cec5SDimitry Andric   uint64_t Mask = 0;
41880b57cec5SDimitry Andric   switch (RetVT.SimpleTy) {
41890b57cec5SDimitry Andric   default: return 0;
41900b57cec5SDimitry Andric   case MVT::i8:  Opc = AArch64::LSRVWr; NeedTrunc = true; Mask = 0xff;   break;
41910b57cec5SDimitry Andric   case MVT::i16: Opc = AArch64::LSRVWr; NeedTrunc = true; Mask = 0xffff; break;
41920b57cec5SDimitry Andric   case MVT::i32: Opc = AArch64::LSRVWr; break;
41930b57cec5SDimitry Andric   case MVT::i64: Opc = AArch64::LSRVXr; break;
41940b57cec5SDimitry Andric   }
41950b57cec5SDimitry Andric 
41960b57cec5SDimitry Andric   const TargetRegisterClass *RC =
41970b57cec5SDimitry Andric       (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
41980b57cec5SDimitry Andric   if (NeedTrunc) {
4199fe6060f1SDimitry Andric     Op0Reg = emitAnd_ri(MVT::i32, Op0Reg, Mask);
4200fe6060f1SDimitry Andric     Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
42010b57cec5SDimitry Andric   }
420204eeddc0SDimitry Andric   Register ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op1Reg);
42030b57cec5SDimitry Andric   if (NeedTrunc)
4204fe6060f1SDimitry Andric     ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
42050b57cec5SDimitry Andric   return ResultReg;
42060b57cec5SDimitry Andric }
42070b57cec5SDimitry Andric 
42080b57cec5SDimitry Andric unsigned AArch64FastISel::emitLSR_ri(MVT RetVT, MVT SrcVT, unsigned Op0,
4209fe6060f1SDimitry Andric                                      uint64_t Shift, bool IsZExt) {
42100b57cec5SDimitry Andric   assert(RetVT.SimpleTy >= SrcVT.SimpleTy &&
42110b57cec5SDimitry Andric          "Unexpected source/return type pair.");
42120b57cec5SDimitry Andric   assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
42130b57cec5SDimitry Andric           SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
42140b57cec5SDimitry Andric          "Unexpected source value type.");
42150b57cec5SDimitry Andric   assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
42160b57cec5SDimitry Andric           RetVT == MVT::i64) && "Unexpected return value type.");
42170b57cec5SDimitry Andric 
42180b57cec5SDimitry Andric   bool Is64Bit = (RetVT == MVT::i64);
42190b57cec5SDimitry Andric   unsigned RegSize = Is64Bit ? 64 : 32;
42200b57cec5SDimitry Andric   unsigned DstBits = RetVT.getSizeInBits();
42210b57cec5SDimitry Andric   unsigned SrcBits = SrcVT.getSizeInBits();
42220b57cec5SDimitry Andric   const TargetRegisterClass *RC =
42230b57cec5SDimitry Andric       Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
42240b57cec5SDimitry Andric 
42250b57cec5SDimitry Andric   // Just emit a copy for "zero" shifts.
42260b57cec5SDimitry Andric   if (Shift == 0) {
42270b57cec5SDimitry Andric     if (RetVT == SrcVT) {
422804eeddc0SDimitry Andric       Register ResultReg = createResultReg(RC);
4229bdd1243dSDimitry Andric       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
42300b57cec5SDimitry Andric               TII.get(TargetOpcode::COPY), ResultReg)
4231fe6060f1SDimitry Andric       .addReg(Op0);
42320b57cec5SDimitry Andric       return ResultReg;
42330b57cec5SDimitry Andric     } else
42340b57cec5SDimitry Andric       return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
42350b57cec5SDimitry Andric   }
42360b57cec5SDimitry Andric 
42370b57cec5SDimitry Andric   // Don't deal with undefined shifts.
42380b57cec5SDimitry Andric   if (Shift >= DstBits)
42390b57cec5SDimitry Andric     return 0;
42400b57cec5SDimitry Andric 
42410b57cec5SDimitry Andric   // For immediate shifts we can fold the zero-/sign-extension into the shift.
42420b57cec5SDimitry Andric   // {S|U}BFM Wd, Wn, #r, #s
42430b57cec5SDimitry Andric   // Wd<s-r:0> = Wn<s:r> when r <= s
42440b57cec5SDimitry Andric 
42450b57cec5SDimitry Andric   // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
42460b57cec5SDimitry Andric   // %2 = lshr i16 %1, 4
42470b57cec5SDimitry Andric   // Wd<7-4:0> = Wn<7:4>
42480b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_1111_1111_1010 sext
42490b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0000_0000_0101 sext | zext
42500b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0000_0000_1010 zext
42510b57cec5SDimitry Andric 
42520b57cec5SDimitry Andric   // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
42530b57cec5SDimitry Andric   // %2 = lshr i16 %1, 8
42540b57cec5SDimitry Andric   // Wd<7-7,0> = Wn<7:7>
42550b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0000_1111_1111 sext
42560b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext
42570b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext
42580b57cec5SDimitry Andric 
42590b57cec5SDimitry Andric   // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
42600b57cec5SDimitry Andric   // %2 = lshr i16 %1, 12
42610b57cec5SDimitry Andric   // Wd<7-7,0> = Wn<7:7> <- clamp r to 7
42620b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0000_0000_1111 sext
42630b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext
42640b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext
42650b57cec5SDimitry Andric 
42660b57cec5SDimitry Andric   if (Shift >= SrcBits && IsZExt)
42670b57cec5SDimitry Andric     return materializeInt(ConstantInt::get(*Context, APInt(RegSize, 0)), RetVT);
42680b57cec5SDimitry Andric 
42690b57cec5SDimitry Andric   // It is not possible to fold a sign-extend into the LShr instruction. In this
42700b57cec5SDimitry Andric   // case emit a sign-extend.
42710b57cec5SDimitry Andric   if (!IsZExt) {
42720b57cec5SDimitry Andric     Op0 = emitIntExt(SrcVT, Op0, RetVT, IsZExt);
42730b57cec5SDimitry Andric     if (!Op0)
42740b57cec5SDimitry Andric       return 0;
42750b57cec5SDimitry Andric     SrcVT = RetVT;
42760b57cec5SDimitry Andric     SrcBits = SrcVT.getSizeInBits();
42770b57cec5SDimitry Andric     IsZExt = true;
42780b57cec5SDimitry Andric   }
42790b57cec5SDimitry Andric 
42800b57cec5SDimitry Andric   unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
42810b57cec5SDimitry Andric   unsigned ImmS = SrcBits - 1;
42820b57cec5SDimitry Andric   static const unsigned OpcTable[2][2] = {
42830b57cec5SDimitry Andric     {AArch64::SBFMWri, AArch64::SBFMXri},
42840b57cec5SDimitry Andric     {AArch64::UBFMWri, AArch64::UBFMXri}
42850b57cec5SDimitry Andric   };
42860b57cec5SDimitry Andric   unsigned Opc = OpcTable[IsZExt][Is64Bit];
42870b57cec5SDimitry Andric   if (SrcVT.SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
42888bcb0991SDimitry Andric     Register TmpReg = MRI.createVirtualRegister(RC);
4289bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
42900b57cec5SDimitry Andric             TII.get(AArch64::SUBREG_TO_REG), TmpReg)
42910b57cec5SDimitry Andric         .addImm(0)
4292fe6060f1SDimitry Andric         .addReg(Op0)
42930b57cec5SDimitry Andric         .addImm(AArch64::sub_32);
42940b57cec5SDimitry Andric     Op0 = TmpReg;
42950b57cec5SDimitry Andric   }
4296fe6060f1SDimitry Andric   return fastEmitInst_rii(Opc, RC, Op0, ImmR, ImmS);
42970b57cec5SDimitry Andric }
42980b57cec5SDimitry Andric 
4299fe6060f1SDimitry Andric unsigned AArch64FastISel::emitASR_rr(MVT RetVT, unsigned Op0Reg,
4300fe6060f1SDimitry Andric                                      unsigned Op1Reg) {
43010b57cec5SDimitry Andric   unsigned Opc = 0;
43020b57cec5SDimitry Andric   bool NeedTrunc = false;
43030b57cec5SDimitry Andric   uint64_t Mask = 0;
43040b57cec5SDimitry Andric   switch (RetVT.SimpleTy) {
43050b57cec5SDimitry Andric   default: return 0;
43060b57cec5SDimitry Andric   case MVT::i8:  Opc = AArch64::ASRVWr; NeedTrunc = true; Mask = 0xff;   break;
43070b57cec5SDimitry Andric   case MVT::i16: Opc = AArch64::ASRVWr; NeedTrunc = true; Mask = 0xffff; break;
43080b57cec5SDimitry Andric   case MVT::i32: Opc = AArch64::ASRVWr;                                  break;
43090b57cec5SDimitry Andric   case MVT::i64: Opc = AArch64::ASRVXr;                                  break;
43100b57cec5SDimitry Andric   }
43110b57cec5SDimitry Andric 
43120b57cec5SDimitry Andric   const TargetRegisterClass *RC =
43130b57cec5SDimitry Andric       (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
43140b57cec5SDimitry Andric   if (NeedTrunc) {
43150b57cec5SDimitry Andric     Op0Reg = emitIntExt(RetVT, Op0Reg, MVT::i32, /*isZExt=*/false);
4316fe6060f1SDimitry Andric     Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
43170b57cec5SDimitry Andric   }
431804eeddc0SDimitry Andric   Register ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op1Reg);
43190b57cec5SDimitry Andric   if (NeedTrunc)
4320fe6060f1SDimitry Andric     ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
43210b57cec5SDimitry Andric   return ResultReg;
43220b57cec5SDimitry Andric }
43230b57cec5SDimitry Andric 
43240b57cec5SDimitry Andric unsigned AArch64FastISel::emitASR_ri(MVT RetVT, MVT SrcVT, unsigned Op0,
4325fe6060f1SDimitry Andric                                      uint64_t Shift, bool IsZExt) {
43260b57cec5SDimitry Andric   assert(RetVT.SimpleTy >= SrcVT.SimpleTy &&
43270b57cec5SDimitry Andric          "Unexpected source/return type pair.");
43280b57cec5SDimitry Andric   assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
43290b57cec5SDimitry Andric           SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
43300b57cec5SDimitry Andric          "Unexpected source value type.");
43310b57cec5SDimitry Andric   assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
43320b57cec5SDimitry Andric           RetVT == MVT::i64) && "Unexpected return value type.");
43330b57cec5SDimitry Andric 
43340b57cec5SDimitry Andric   bool Is64Bit = (RetVT == MVT::i64);
43350b57cec5SDimitry Andric   unsigned RegSize = Is64Bit ? 64 : 32;
43360b57cec5SDimitry Andric   unsigned DstBits = RetVT.getSizeInBits();
43370b57cec5SDimitry Andric   unsigned SrcBits = SrcVT.getSizeInBits();
43380b57cec5SDimitry Andric   const TargetRegisterClass *RC =
43390b57cec5SDimitry Andric       Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
43400b57cec5SDimitry Andric 
43410b57cec5SDimitry Andric   // Just emit a copy for "zero" shifts.
43420b57cec5SDimitry Andric   if (Shift == 0) {
43430b57cec5SDimitry Andric     if (RetVT == SrcVT) {
434404eeddc0SDimitry Andric       Register ResultReg = createResultReg(RC);
4345bdd1243dSDimitry Andric       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
43460b57cec5SDimitry Andric               TII.get(TargetOpcode::COPY), ResultReg)
4347fe6060f1SDimitry Andric       .addReg(Op0);
43480b57cec5SDimitry Andric       return ResultReg;
43490b57cec5SDimitry Andric     } else
43500b57cec5SDimitry Andric       return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
43510b57cec5SDimitry Andric   }
43520b57cec5SDimitry Andric 
43530b57cec5SDimitry Andric   // Don't deal with undefined shifts.
43540b57cec5SDimitry Andric   if (Shift >= DstBits)
43550b57cec5SDimitry Andric     return 0;
43560b57cec5SDimitry Andric 
43570b57cec5SDimitry Andric   // For immediate shifts we can fold the zero-/sign-extension into the shift.
43580b57cec5SDimitry Andric   // {S|U}BFM Wd, Wn, #r, #s
43590b57cec5SDimitry Andric   // Wd<s-r:0> = Wn<s:r> when r <= s
43600b57cec5SDimitry Andric 
43610b57cec5SDimitry Andric   // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
43620b57cec5SDimitry Andric   // %2 = ashr i16 %1, 4
43630b57cec5SDimitry Andric   // Wd<7-4:0> = Wn<7:4>
43640b57cec5SDimitry Andric   // 0b1111_1111_1111_1111__1111_1111_1111_1010 sext
43650b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0000_0000_0101 sext | zext
43660b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0000_0000_1010 zext
43670b57cec5SDimitry Andric 
43680b57cec5SDimitry Andric   // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
43690b57cec5SDimitry Andric   // %2 = ashr i16 %1, 8
43700b57cec5SDimitry Andric   // Wd<7-7,0> = Wn<7:7>
43710b57cec5SDimitry Andric   // 0b1111_1111_1111_1111__1111_1111_1111_1111 sext
43720b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext
43730b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext
43740b57cec5SDimitry Andric 
43750b57cec5SDimitry Andric   // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
43760b57cec5SDimitry Andric   // %2 = ashr i16 %1, 12
43770b57cec5SDimitry Andric   // Wd<7-7,0> = Wn<7:7> <- clamp r to 7
43780b57cec5SDimitry Andric   // 0b1111_1111_1111_1111__1111_1111_1111_1111 sext
43790b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext
43800b57cec5SDimitry Andric   // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext
43810b57cec5SDimitry Andric 
43820b57cec5SDimitry Andric   if (Shift >= SrcBits && IsZExt)
43830b57cec5SDimitry Andric     return materializeInt(ConstantInt::get(*Context, APInt(RegSize, 0)), RetVT);
43840b57cec5SDimitry Andric 
43850b57cec5SDimitry Andric   unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
43860b57cec5SDimitry Andric   unsigned ImmS = SrcBits - 1;
43870b57cec5SDimitry Andric   static const unsigned OpcTable[2][2] = {
43880b57cec5SDimitry Andric     {AArch64::SBFMWri, AArch64::SBFMXri},
43890b57cec5SDimitry Andric     {AArch64::UBFMWri, AArch64::UBFMXri}
43900b57cec5SDimitry Andric   };
43910b57cec5SDimitry Andric   unsigned Opc = OpcTable[IsZExt][Is64Bit];
43920b57cec5SDimitry Andric   if (SrcVT.SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
43938bcb0991SDimitry Andric     Register TmpReg = MRI.createVirtualRegister(RC);
4394bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
43950b57cec5SDimitry Andric             TII.get(AArch64::SUBREG_TO_REG), TmpReg)
43960b57cec5SDimitry Andric         .addImm(0)
4397fe6060f1SDimitry Andric         .addReg(Op0)
43980b57cec5SDimitry Andric         .addImm(AArch64::sub_32);
43990b57cec5SDimitry Andric     Op0 = TmpReg;
44000b57cec5SDimitry Andric   }
4401fe6060f1SDimitry Andric   return fastEmitInst_rii(Opc, RC, Op0, ImmR, ImmS);
44020b57cec5SDimitry Andric }
44030b57cec5SDimitry Andric 
44040b57cec5SDimitry Andric unsigned AArch64FastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
44050b57cec5SDimitry Andric                                      bool IsZExt) {
44060b57cec5SDimitry Andric   assert(DestVT != MVT::i1 && "ZeroExt/SignExt an i1?");
44070b57cec5SDimitry Andric 
44080b57cec5SDimitry Andric   // FastISel does not have plumbing to deal with extensions where the SrcVT or
44090b57cec5SDimitry Andric   // DestVT are odd things, so test to make sure that they are both types we can
44100b57cec5SDimitry Andric   // handle (i1/i8/i16/i32 for SrcVT and i8/i16/i32/i64 for DestVT), otherwise
44110b57cec5SDimitry Andric   // bail out to SelectionDAG.
44120b57cec5SDimitry Andric   if (((DestVT != MVT::i8) && (DestVT != MVT::i16) &&
44130b57cec5SDimitry Andric        (DestVT != MVT::i32) && (DestVT != MVT::i64)) ||
44140b57cec5SDimitry Andric       ((SrcVT !=  MVT::i1) && (SrcVT !=  MVT::i8) &&
44150b57cec5SDimitry Andric        (SrcVT !=  MVT::i16) && (SrcVT !=  MVT::i32)))
44160b57cec5SDimitry Andric     return 0;
44170b57cec5SDimitry Andric 
44180b57cec5SDimitry Andric   unsigned Opc;
44190b57cec5SDimitry Andric   unsigned Imm = 0;
44200b57cec5SDimitry Andric 
44210b57cec5SDimitry Andric   switch (SrcVT.SimpleTy) {
44220b57cec5SDimitry Andric   default:
44230b57cec5SDimitry Andric     return 0;
44240b57cec5SDimitry Andric   case MVT::i1:
44250b57cec5SDimitry Andric     return emiti1Ext(SrcReg, DestVT, IsZExt);
44260b57cec5SDimitry Andric   case MVT::i8:
44270b57cec5SDimitry Andric     if (DestVT == MVT::i64)
44280b57cec5SDimitry Andric       Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
44290b57cec5SDimitry Andric     else
44300b57cec5SDimitry Andric       Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
44310b57cec5SDimitry Andric     Imm = 7;
44320b57cec5SDimitry Andric     break;
44330b57cec5SDimitry Andric   case MVT::i16:
44340b57cec5SDimitry Andric     if (DestVT == MVT::i64)
44350b57cec5SDimitry Andric       Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
44360b57cec5SDimitry Andric     else
44370b57cec5SDimitry Andric       Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
44380b57cec5SDimitry Andric     Imm = 15;
44390b57cec5SDimitry Andric     break;
44400b57cec5SDimitry Andric   case MVT::i32:
44410b57cec5SDimitry Andric     assert(DestVT == MVT::i64 && "IntExt i32 to i32?!?");
44420b57cec5SDimitry Andric     Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
44430b57cec5SDimitry Andric     Imm = 31;
44440b57cec5SDimitry Andric     break;
44450b57cec5SDimitry Andric   }
44460b57cec5SDimitry Andric 
44470b57cec5SDimitry Andric   // Handle i8 and i16 as i32.
44480b57cec5SDimitry Andric   if (DestVT == MVT::i8 || DestVT == MVT::i16)
44490b57cec5SDimitry Andric     DestVT = MVT::i32;
44500b57cec5SDimitry Andric   else if (DestVT == MVT::i64) {
44518bcb0991SDimitry Andric     Register Src64 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4452bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
44530b57cec5SDimitry Andric             TII.get(AArch64::SUBREG_TO_REG), Src64)
44540b57cec5SDimitry Andric         .addImm(0)
44550b57cec5SDimitry Andric         .addReg(SrcReg)
44560b57cec5SDimitry Andric         .addImm(AArch64::sub_32);
44570b57cec5SDimitry Andric     SrcReg = Src64;
44580b57cec5SDimitry Andric   }
44590b57cec5SDimitry Andric 
44600b57cec5SDimitry Andric   const TargetRegisterClass *RC =
44610b57cec5SDimitry Andric       (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4462fe6060f1SDimitry Andric   return fastEmitInst_rii(Opc, RC, SrcReg, 0, Imm);
44630b57cec5SDimitry Andric }
44640b57cec5SDimitry Andric 
44650b57cec5SDimitry Andric static bool isZExtLoad(const MachineInstr *LI) {
44660b57cec5SDimitry Andric   switch (LI->getOpcode()) {
44670b57cec5SDimitry Andric   default:
44680b57cec5SDimitry Andric     return false;
44690b57cec5SDimitry Andric   case AArch64::LDURBBi:
44700b57cec5SDimitry Andric   case AArch64::LDURHHi:
44710b57cec5SDimitry Andric   case AArch64::LDURWi:
44720b57cec5SDimitry Andric   case AArch64::LDRBBui:
44730b57cec5SDimitry Andric   case AArch64::LDRHHui:
44740b57cec5SDimitry Andric   case AArch64::LDRWui:
44750b57cec5SDimitry Andric   case AArch64::LDRBBroX:
44760b57cec5SDimitry Andric   case AArch64::LDRHHroX:
44770b57cec5SDimitry Andric   case AArch64::LDRWroX:
44780b57cec5SDimitry Andric   case AArch64::LDRBBroW:
44790b57cec5SDimitry Andric   case AArch64::LDRHHroW:
44800b57cec5SDimitry Andric   case AArch64::LDRWroW:
44810b57cec5SDimitry Andric     return true;
44820b57cec5SDimitry Andric   }
44830b57cec5SDimitry Andric }
44840b57cec5SDimitry Andric 
44850b57cec5SDimitry Andric static bool isSExtLoad(const MachineInstr *LI) {
44860b57cec5SDimitry Andric   switch (LI->getOpcode()) {
44870b57cec5SDimitry Andric   default:
44880b57cec5SDimitry Andric     return false;
44890b57cec5SDimitry Andric   case AArch64::LDURSBWi:
44900b57cec5SDimitry Andric   case AArch64::LDURSHWi:
44910b57cec5SDimitry Andric   case AArch64::LDURSBXi:
44920b57cec5SDimitry Andric   case AArch64::LDURSHXi:
44930b57cec5SDimitry Andric   case AArch64::LDURSWi:
44940b57cec5SDimitry Andric   case AArch64::LDRSBWui:
44950b57cec5SDimitry Andric   case AArch64::LDRSHWui:
44960b57cec5SDimitry Andric   case AArch64::LDRSBXui:
44970b57cec5SDimitry Andric   case AArch64::LDRSHXui:
44980b57cec5SDimitry Andric   case AArch64::LDRSWui:
44990b57cec5SDimitry Andric   case AArch64::LDRSBWroX:
45000b57cec5SDimitry Andric   case AArch64::LDRSHWroX:
45010b57cec5SDimitry Andric   case AArch64::LDRSBXroX:
45020b57cec5SDimitry Andric   case AArch64::LDRSHXroX:
45030b57cec5SDimitry Andric   case AArch64::LDRSWroX:
45040b57cec5SDimitry Andric   case AArch64::LDRSBWroW:
45050b57cec5SDimitry Andric   case AArch64::LDRSHWroW:
45060b57cec5SDimitry Andric   case AArch64::LDRSBXroW:
45070b57cec5SDimitry Andric   case AArch64::LDRSHXroW:
45080b57cec5SDimitry Andric   case AArch64::LDRSWroW:
45090b57cec5SDimitry Andric     return true;
45100b57cec5SDimitry Andric   }
45110b57cec5SDimitry Andric }
45120b57cec5SDimitry Andric 
45130b57cec5SDimitry Andric bool AArch64FastISel::optimizeIntExtLoad(const Instruction *I, MVT RetVT,
45140b57cec5SDimitry Andric                                          MVT SrcVT) {
45150b57cec5SDimitry Andric   const auto *LI = dyn_cast<LoadInst>(I->getOperand(0));
45160b57cec5SDimitry Andric   if (!LI || !LI->hasOneUse())
45170b57cec5SDimitry Andric     return false;
45180b57cec5SDimitry Andric 
45190b57cec5SDimitry Andric   // Check if the load instruction has already been selected.
452004eeddc0SDimitry Andric   Register Reg = lookUpRegForValue(LI);
45210b57cec5SDimitry Andric   if (!Reg)
45220b57cec5SDimitry Andric     return false;
45230b57cec5SDimitry Andric 
45240b57cec5SDimitry Andric   MachineInstr *MI = MRI.getUniqueVRegDef(Reg);
45250b57cec5SDimitry Andric   if (!MI)
45260b57cec5SDimitry Andric     return false;
45270b57cec5SDimitry Andric 
45280b57cec5SDimitry Andric   // Check if the correct load instruction has been emitted - SelectionDAG might
45290b57cec5SDimitry Andric   // have emitted a zero-extending load, but we need a sign-extending load.
45300b57cec5SDimitry Andric   bool IsZExt = isa<ZExtInst>(I);
45310b57cec5SDimitry Andric   const auto *LoadMI = MI;
45320b57cec5SDimitry Andric   if (LoadMI->getOpcode() == TargetOpcode::COPY &&
45330b57cec5SDimitry Andric       LoadMI->getOperand(1).getSubReg() == AArch64::sub_32) {
45348bcb0991SDimitry Andric     Register LoadReg = MI->getOperand(1).getReg();
45350b57cec5SDimitry Andric     LoadMI = MRI.getUniqueVRegDef(LoadReg);
45360b57cec5SDimitry Andric     assert(LoadMI && "Expected valid instruction");
45370b57cec5SDimitry Andric   }
45380b57cec5SDimitry Andric   if (!(IsZExt && isZExtLoad(LoadMI)) && !(!IsZExt && isSExtLoad(LoadMI)))
45390b57cec5SDimitry Andric     return false;
45400b57cec5SDimitry Andric 
45410b57cec5SDimitry Andric   // Nothing to be done.
45420b57cec5SDimitry Andric   if (RetVT != MVT::i64 || SrcVT > MVT::i32) {
45430b57cec5SDimitry Andric     updateValueMap(I, Reg);
45440b57cec5SDimitry Andric     return true;
45450b57cec5SDimitry Andric   }
45460b57cec5SDimitry Andric 
45470b57cec5SDimitry Andric   if (IsZExt) {
454804eeddc0SDimitry Andric     Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
4549bdd1243dSDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
45500b57cec5SDimitry Andric             TII.get(AArch64::SUBREG_TO_REG), Reg64)
45510b57cec5SDimitry Andric         .addImm(0)
45520b57cec5SDimitry Andric         .addReg(Reg, getKillRegState(true))
45530b57cec5SDimitry Andric         .addImm(AArch64::sub_32);
45540b57cec5SDimitry Andric     Reg = Reg64;
45550b57cec5SDimitry Andric   } else {
45560b57cec5SDimitry Andric     assert((MI->getOpcode() == TargetOpcode::COPY &&
45570b57cec5SDimitry Andric             MI->getOperand(1).getSubReg() == AArch64::sub_32) &&
45580b57cec5SDimitry Andric            "Expected copy instruction");
45590b57cec5SDimitry Andric     Reg = MI->getOperand(1).getReg();
45600b57cec5SDimitry Andric     MachineBasicBlock::iterator I(MI);
45610b57cec5SDimitry Andric     removeDeadCode(I, std::next(I));
45620b57cec5SDimitry Andric   }
45630b57cec5SDimitry Andric   updateValueMap(I, Reg);
45640b57cec5SDimitry Andric   return true;
45650b57cec5SDimitry Andric }
45660b57cec5SDimitry Andric 
45670b57cec5SDimitry Andric bool AArch64FastISel::selectIntExt(const Instruction *I) {
45680b57cec5SDimitry Andric   assert((isa<ZExtInst>(I) || isa<SExtInst>(I)) &&
45690b57cec5SDimitry Andric          "Unexpected integer extend instruction.");
45700b57cec5SDimitry Andric   MVT RetVT;
45710b57cec5SDimitry Andric   MVT SrcVT;
45720b57cec5SDimitry Andric   if (!isTypeSupported(I->getType(), RetVT))
45730b57cec5SDimitry Andric     return false;
45740b57cec5SDimitry Andric 
45750b57cec5SDimitry Andric   if (!isTypeSupported(I->getOperand(0)->getType(), SrcVT))
45760b57cec5SDimitry Andric     return false;
45770b57cec5SDimitry Andric 
45780b57cec5SDimitry Andric   // Try to optimize already sign-/zero-extended values from load instructions.
45790b57cec5SDimitry Andric   if (optimizeIntExtLoad(I, RetVT, SrcVT))
45800b57cec5SDimitry Andric     return true;
45810b57cec5SDimitry Andric 
458204eeddc0SDimitry Andric   Register SrcReg = getRegForValue(I->getOperand(0));
45830b57cec5SDimitry Andric   if (!SrcReg)
45840b57cec5SDimitry Andric     return false;
45850b57cec5SDimitry Andric 
45860b57cec5SDimitry Andric   // Try to optimize already sign-/zero-extended values from function arguments.
45870b57cec5SDimitry Andric   bool IsZExt = isa<ZExtInst>(I);
45880b57cec5SDimitry Andric   if (const auto *Arg = dyn_cast<Argument>(I->getOperand(0))) {
45890b57cec5SDimitry Andric     if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr())) {
45900b57cec5SDimitry Andric       if (RetVT == MVT::i64 && SrcVT != MVT::i64) {
459104eeddc0SDimitry Andric         Register ResultReg = createResultReg(&AArch64::GPR64RegClass);
4592bdd1243dSDimitry Andric         BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
45930b57cec5SDimitry Andric                 TII.get(AArch64::SUBREG_TO_REG), ResultReg)
45940b57cec5SDimitry Andric             .addImm(0)
4595fe6060f1SDimitry Andric             .addReg(SrcReg)
45960b57cec5SDimitry Andric             .addImm(AArch64::sub_32);
45970b57cec5SDimitry Andric         SrcReg = ResultReg;
45980b57cec5SDimitry Andric       }
45990b57cec5SDimitry Andric 
46000b57cec5SDimitry Andric       updateValueMap(I, SrcReg);
46010b57cec5SDimitry Andric       return true;
46020b57cec5SDimitry Andric     }
46030b57cec5SDimitry Andric   }
46040b57cec5SDimitry Andric 
46050b57cec5SDimitry Andric   unsigned ResultReg = emitIntExt(SrcVT, SrcReg, RetVT, IsZExt);
46060b57cec5SDimitry Andric   if (!ResultReg)
46070b57cec5SDimitry Andric     return false;
46080b57cec5SDimitry Andric 
46090b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
46100b57cec5SDimitry Andric   return true;
46110b57cec5SDimitry Andric }
46120b57cec5SDimitry Andric 
46130b57cec5SDimitry Andric bool AArch64FastISel::selectRem(const Instruction *I, unsigned ISDOpcode) {
46140b57cec5SDimitry Andric   EVT DestEVT = TLI.getValueType(DL, I->getType(), true);
46150b57cec5SDimitry Andric   if (!DestEVT.isSimple())
46160b57cec5SDimitry Andric     return false;
46170b57cec5SDimitry Andric 
46180b57cec5SDimitry Andric   MVT DestVT = DestEVT.getSimpleVT();
46190b57cec5SDimitry Andric   if (DestVT != MVT::i64 && DestVT != MVT::i32)
46200b57cec5SDimitry Andric     return false;
46210b57cec5SDimitry Andric 
46220b57cec5SDimitry Andric   unsigned DivOpc;
46230b57cec5SDimitry Andric   bool Is64bit = (DestVT == MVT::i64);
46240b57cec5SDimitry Andric   switch (ISDOpcode) {
46250b57cec5SDimitry Andric   default:
46260b57cec5SDimitry Andric     return false;
46270b57cec5SDimitry Andric   case ISD::SREM:
46280b57cec5SDimitry Andric     DivOpc = Is64bit ? AArch64::SDIVXr : AArch64::SDIVWr;
46290b57cec5SDimitry Andric     break;
46300b57cec5SDimitry Andric   case ISD::UREM:
46310b57cec5SDimitry Andric     DivOpc = Is64bit ? AArch64::UDIVXr : AArch64::UDIVWr;
46320b57cec5SDimitry Andric     break;
46330b57cec5SDimitry Andric   }
46340b57cec5SDimitry Andric   unsigned MSubOpc = Is64bit ? AArch64::MSUBXrrr : AArch64::MSUBWrrr;
463504eeddc0SDimitry Andric   Register Src0Reg = getRegForValue(I->getOperand(0));
46360b57cec5SDimitry Andric   if (!Src0Reg)
46370b57cec5SDimitry Andric     return false;
46380b57cec5SDimitry Andric 
463904eeddc0SDimitry Andric   Register Src1Reg = getRegForValue(I->getOperand(1));
46400b57cec5SDimitry Andric   if (!Src1Reg)
46410b57cec5SDimitry Andric     return false;
46420b57cec5SDimitry Andric 
46430b57cec5SDimitry Andric   const TargetRegisterClass *RC =
46440b57cec5SDimitry Andric       (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
464504eeddc0SDimitry Andric   Register QuotReg = fastEmitInst_rr(DivOpc, RC, Src0Reg, Src1Reg);
46460b57cec5SDimitry Andric   assert(QuotReg && "Unexpected DIV instruction emission failure.");
46470b57cec5SDimitry Andric   // The remainder is computed as numerator - (quotient * denominator) using the
46480b57cec5SDimitry Andric   // MSUB instruction.
464904eeddc0SDimitry Andric   Register ResultReg = fastEmitInst_rrr(MSubOpc, RC, QuotReg, Src1Reg, Src0Reg);
46500b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
46510b57cec5SDimitry Andric   return true;
46520b57cec5SDimitry Andric }
46530b57cec5SDimitry Andric 
46540b57cec5SDimitry Andric bool AArch64FastISel::selectMul(const Instruction *I) {
46550b57cec5SDimitry Andric   MVT VT;
46560b57cec5SDimitry Andric   if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true))
46570b57cec5SDimitry Andric     return false;
46580b57cec5SDimitry Andric 
46590b57cec5SDimitry Andric   if (VT.isVector())
46600b57cec5SDimitry Andric     return selectBinaryOp(I, ISD::MUL);
46610b57cec5SDimitry Andric 
46620b57cec5SDimitry Andric   const Value *Src0 = I->getOperand(0);
46630b57cec5SDimitry Andric   const Value *Src1 = I->getOperand(1);
46640b57cec5SDimitry Andric   if (const auto *C = dyn_cast<ConstantInt>(Src0))
46650b57cec5SDimitry Andric     if (C->getValue().isPowerOf2())
46660b57cec5SDimitry Andric       std::swap(Src0, Src1);
46670b57cec5SDimitry Andric 
46680b57cec5SDimitry Andric   // Try to simplify to a shift instruction.
46690b57cec5SDimitry Andric   if (const auto *C = dyn_cast<ConstantInt>(Src1))
46700b57cec5SDimitry Andric     if (C->getValue().isPowerOf2()) {
46710b57cec5SDimitry Andric       uint64_t ShiftVal = C->getValue().logBase2();
46720b57cec5SDimitry Andric       MVT SrcVT = VT;
46730b57cec5SDimitry Andric       bool IsZExt = true;
46740b57cec5SDimitry Andric       if (const auto *ZExt = dyn_cast<ZExtInst>(Src0)) {
46750b57cec5SDimitry Andric         if (!isIntExtFree(ZExt)) {
46760b57cec5SDimitry Andric           MVT VT;
46770b57cec5SDimitry Andric           if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), VT)) {
46780b57cec5SDimitry Andric             SrcVT = VT;
46790b57cec5SDimitry Andric             IsZExt = true;
46800b57cec5SDimitry Andric             Src0 = ZExt->getOperand(0);
46810b57cec5SDimitry Andric           }
46820b57cec5SDimitry Andric         }
46830b57cec5SDimitry Andric       } else if (const auto *SExt = dyn_cast<SExtInst>(Src0)) {
46840b57cec5SDimitry Andric         if (!isIntExtFree(SExt)) {
46850b57cec5SDimitry Andric           MVT VT;
46860b57cec5SDimitry Andric           if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), VT)) {
46870b57cec5SDimitry Andric             SrcVT = VT;
46880b57cec5SDimitry Andric             IsZExt = false;
46890b57cec5SDimitry Andric             Src0 = SExt->getOperand(0);
46900b57cec5SDimitry Andric           }
46910b57cec5SDimitry Andric         }
46920b57cec5SDimitry Andric       }
46930b57cec5SDimitry Andric 
469404eeddc0SDimitry Andric       Register Src0Reg = getRegForValue(Src0);
46950b57cec5SDimitry Andric       if (!Src0Reg)
46960b57cec5SDimitry Andric         return false;
46970b57cec5SDimitry Andric 
46980b57cec5SDimitry Andric       unsigned ResultReg =
4699fe6060f1SDimitry Andric           emitLSL_ri(VT, SrcVT, Src0Reg, ShiftVal, IsZExt);
47000b57cec5SDimitry Andric 
47010b57cec5SDimitry Andric       if (ResultReg) {
47020b57cec5SDimitry Andric         updateValueMap(I, ResultReg);
47030b57cec5SDimitry Andric         return true;
47040b57cec5SDimitry Andric       }
47050b57cec5SDimitry Andric     }
47060b57cec5SDimitry Andric 
470704eeddc0SDimitry Andric   Register Src0Reg = getRegForValue(I->getOperand(0));
47080b57cec5SDimitry Andric   if (!Src0Reg)
47090b57cec5SDimitry Andric     return false;
47100b57cec5SDimitry Andric 
471104eeddc0SDimitry Andric   Register Src1Reg = getRegForValue(I->getOperand(1));
47120b57cec5SDimitry Andric   if (!Src1Reg)
47130b57cec5SDimitry Andric     return false;
47140b57cec5SDimitry Andric 
4715fe6060f1SDimitry Andric   unsigned ResultReg = emitMul_rr(VT, Src0Reg, Src1Reg);
47160b57cec5SDimitry Andric 
47170b57cec5SDimitry Andric   if (!ResultReg)
47180b57cec5SDimitry Andric     return false;
47190b57cec5SDimitry Andric 
47200b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
47210b57cec5SDimitry Andric   return true;
47220b57cec5SDimitry Andric }
47230b57cec5SDimitry Andric 
47240b57cec5SDimitry Andric bool AArch64FastISel::selectShift(const Instruction *I) {
47250b57cec5SDimitry Andric   MVT RetVT;
47260b57cec5SDimitry Andric   if (!isTypeSupported(I->getType(), RetVT, /*IsVectorAllowed=*/true))
47270b57cec5SDimitry Andric     return false;
47280b57cec5SDimitry Andric 
47290b57cec5SDimitry Andric   if (RetVT.isVector())
47300b57cec5SDimitry Andric     return selectOperator(I, I->getOpcode());
47310b57cec5SDimitry Andric 
47320b57cec5SDimitry Andric   if (const auto *C = dyn_cast<ConstantInt>(I->getOperand(1))) {
47330b57cec5SDimitry Andric     unsigned ResultReg = 0;
47340b57cec5SDimitry Andric     uint64_t ShiftVal = C->getZExtValue();
47350b57cec5SDimitry Andric     MVT SrcVT = RetVT;
47360b57cec5SDimitry Andric     bool IsZExt = I->getOpcode() != Instruction::AShr;
47370b57cec5SDimitry Andric     const Value *Op0 = I->getOperand(0);
47380b57cec5SDimitry Andric     if (const auto *ZExt = dyn_cast<ZExtInst>(Op0)) {
47390b57cec5SDimitry Andric       if (!isIntExtFree(ZExt)) {
47400b57cec5SDimitry Andric         MVT TmpVT;
47410b57cec5SDimitry Andric         if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), TmpVT)) {
47420b57cec5SDimitry Andric           SrcVT = TmpVT;
47430b57cec5SDimitry Andric           IsZExt = true;
47440b57cec5SDimitry Andric           Op0 = ZExt->getOperand(0);
47450b57cec5SDimitry Andric         }
47460b57cec5SDimitry Andric       }
47470b57cec5SDimitry Andric     } else if (const auto *SExt = dyn_cast<SExtInst>(Op0)) {
47480b57cec5SDimitry Andric       if (!isIntExtFree(SExt)) {
47490b57cec5SDimitry Andric         MVT TmpVT;
47500b57cec5SDimitry Andric         if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), TmpVT)) {
47510b57cec5SDimitry Andric           SrcVT = TmpVT;
47520b57cec5SDimitry Andric           IsZExt = false;
47530b57cec5SDimitry Andric           Op0 = SExt->getOperand(0);
47540b57cec5SDimitry Andric         }
47550b57cec5SDimitry Andric       }
47560b57cec5SDimitry Andric     }
47570b57cec5SDimitry Andric 
475804eeddc0SDimitry Andric     Register Op0Reg = getRegForValue(Op0);
47590b57cec5SDimitry Andric     if (!Op0Reg)
47600b57cec5SDimitry Andric       return false;
47610b57cec5SDimitry Andric 
47620b57cec5SDimitry Andric     switch (I->getOpcode()) {
47630b57cec5SDimitry Andric     default: llvm_unreachable("Unexpected instruction.");
47640b57cec5SDimitry Andric     case Instruction::Shl:
4765fe6060f1SDimitry Andric       ResultReg = emitLSL_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
47660b57cec5SDimitry Andric       break;
47670b57cec5SDimitry Andric     case Instruction::AShr:
4768fe6060f1SDimitry Andric       ResultReg = emitASR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
47690b57cec5SDimitry Andric       break;
47700b57cec5SDimitry Andric     case Instruction::LShr:
4771fe6060f1SDimitry Andric       ResultReg = emitLSR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
47720b57cec5SDimitry Andric       break;
47730b57cec5SDimitry Andric     }
47740b57cec5SDimitry Andric     if (!ResultReg)
47750b57cec5SDimitry Andric       return false;
47760b57cec5SDimitry Andric 
47770b57cec5SDimitry Andric     updateValueMap(I, ResultReg);
47780b57cec5SDimitry Andric     return true;
47790b57cec5SDimitry Andric   }
47800b57cec5SDimitry Andric 
478104eeddc0SDimitry Andric   Register Op0Reg = getRegForValue(I->getOperand(0));
47820b57cec5SDimitry Andric   if (!Op0Reg)
47830b57cec5SDimitry Andric     return false;
47840b57cec5SDimitry Andric 
478504eeddc0SDimitry Andric   Register Op1Reg = getRegForValue(I->getOperand(1));
47860b57cec5SDimitry Andric   if (!Op1Reg)
47870b57cec5SDimitry Andric     return false;
47880b57cec5SDimitry Andric 
47890b57cec5SDimitry Andric   unsigned ResultReg = 0;
47900b57cec5SDimitry Andric   switch (I->getOpcode()) {
47910b57cec5SDimitry Andric   default: llvm_unreachable("Unexpected instruction.");
47920b57cec5SDimitry Andric   case Instruction::Shl:
4793fe6060f1SDimitry Andric     ResultReg = emitLSL_rr(RetVT, Op0Reg, Op1Reg);
47940b57cec5SDimitry Andric     break;
47950b57cec5SDimitry Andric   case Instruction::AShr:
4796fe6060f1SDimitry Andric     ResultReg = emitASR_rr(RetVT, Op0Reg, Op1Reg);
47970b57cec5SDimitry Andric     break;
47980b57cec5SDimitry Andric   case Instruction::LShr:
4799fe6060f1SDimitry Andric     ResultReg = emitLSR_rr(RetVT, Op0Reg, Op1Reg);
48000b57cec5SDimitry Andric     break;
48010b57cec5SDimitry Andric   }
48020b57cec5SDimitry Andric 
48030b57cec5SDimitry Andric   if (!ResultReg)
48040b57cec5SDimitry Andric     return false;
48050b57cec5SDimitry Andric 
48060b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
48070b57cec5SDimitry Andric   return true;
48080b57cec5SDimitry Andric }
48090b57cec5SDimitry Andric 
48100b57cec5SDimitry Andric bool AArch64FastISel::selectBitCast(const Instruction *I) {
48110b57cec5SDimitry Andric   MVT RetVT, SrcVT;
48120b57cec5SDimitry Andric 
48130b57cec5SDimitry Andric   if (!isTypeLegal(I->getOperand(0)->getType(), SrcVT))
48140b57cec5SDimitry Andric     return false;
48150b57cec5SDimitry Andric   if (!isTypeLegal(I->getType(), RetVT))
48160b57cec5SDimitry Andric     return false;
48170b57cec5SDimitry Andric 
48180b57cec5SDimitry Andric   unsigned Opc;
48190b57cec5SDimitry Andric   if (RetVT == MVT::f32 && SrcVT == MVT::i32)
48200b57cec5SDimitry Andric     Opc = AArch64::FMOVWSr;
48210b57cec5SDimitry Andric   else if (RetVT == MVT::f64 && SrcVT == MVT::i64)
48220b57cec5SDimitry Andric     Opc = AArch64::FMOVXDr;
48230b57cec5SDimitry Andric   else if (RetVT == MVT::i32 && SrcVT == MVT::f32)
48240b57cec5SDimitry Andric     Opc = AArch64::FMOVSWr;
48250b57cec5SDimitry Andric   else if (RetVT == MVT::i64 && SrcVT == MVT::f64)
48260b57cec5SDimitry Andric     Opc = AArch64::FMOVDXr;
48270b57cec5SDimitry Andric   else
48280b57cec5SDimitry Andric     return false;
48290b57cec5SDimitry Andric 
48300b57cec5SDimitry Andric   const TargetRegisterClass *RC = nullptr;
48310b57cec5SDimitry Andric   switch (RetVT.SimpleTy) {
48320b57cec5SDimitry Andric   default: llvm_unreachable("Unexpected value type.");
48330b57cec5SDimitry Andric   case MVT::i32: RC = &AArch64::GPR32RegClass; break;
48340b57cec5SDimitry Andric   case MVT::i64: RC = &AArch64::GPR64RegClass; break;
48350b57cec5SDimitry Andric   case MVT::f32: RC = &AArch64::FPR32RegClass; break;
48360b57cec5SDimitry Andric   case MVT::f64: RC = &AArch64::FPR64RegClass; break;
48370b57cec5SDimitry Andric   }
483804eeddc0SDimitry Andric   Register Op0Reg = getRegForValue(I->getOperand(0));
48390b57cec5SDimitry Andric   if (!Op0Reg)
48400b57cec5SDimitry Andric     return false;
48410b57cec5SDimitry Andric 
484204eeddc0SDimitry Andric   Register ResultReg = fastEmitInst_r(Opc, RC, Op0Reg);
48430b57cec5SDimitry Andric   if (!ResultReg)
48440b57cec5SDimitry Andric     return false;
48450b57cec5SDimitry Andric 
48460b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
48470b57cec5SDimitry Andric   return true;
48480b57cec5SDimitry Andric }
48490b57cec5SDimitry Andric 
48500b57cec5SDimitry Andric bool AArch64FastISel::selectFRem(const Instruction *I) {
48510b57cec5SDimitry Andric   MVT RetVT;
48520b57cec5SDimitry Andric   if (!isTypeLegal(I->getType(), RetVT))
48530b57cec5SDimitry Andric     return false;
48540b57cec5SDimitry Andric 
48550b57cec5SDimitry Andric   RTLIB::Libcall LC;
48560b57cec5SDimitry Andric   switch (RetVT.SimpleTy) {
48570b57cec5SDimitry Andric   default:
48580b57cec5SDimitry Andric     return false;
48590b57cec5SDimitry Andric   case MVT::f32:
48600b57cec5SDimitry Andric     LC = RTLIB::REM_F32;
48610b57cec5SDimitry Andric     break;
48620b57cec5SDimitry Andric   case MVT::f64:
48630b57cec5SDimitry Andric     LC = RTLIB::REM_F64;
48640b57cec5SDimitry Andric     break;
48650b57cec5SDimitry Andric   }
48660b57cec5SDimitry Andric 
48670b57cec5SDimitry Andric   ArgListTy Args;
48680b57cec5SDimitry Andric   Args.reserve(I->getNumOperands());
48690b57cec5SDimitry Andric 
48700b57cec5SDimitry Andric   // Populate the argument list.
48710b57cec5SDimitry Andric   for (auto &Arg : I->operands()) {
48720b57cec5SDimitry Andric     ArgListEntry Entry;
48730b57cec5SDimitry Andric     Entry.Val = Arg;
48740b57cec5SDimitry Andric     Entry.Ty = Arg->getType();
48750b57cec5SDimitry Andric     Args.push_back(Entry);
48760b57cec5SDimitry Andric   }
48770b57cec5SDimitry Andric 
48780b57cec5SDimitry Andric   CallLoweringInfo CLI;
48790b57cec5SDimitry Andric   MCContext &Ctx = MF->getContext();
48800b57cec5SDimitry Andric   CLI.setCallee(DL, Ctx, TLI.getLibcallCallingConv(LC), I->getType(),
48810b57cec5SDimitry Andric                 TLI.getLibcallName(LC), std::move(Args));
48820b57cec5SDimitry Andric   if (!lowerCallTo(CLI))
48830b57cec5SDimitry Andric     return false;
48840b57cec5SDimitry Andric   updateValueMap(I, CLI.ResultReg);
48850b57cec5SDimitry Andric   return true;
48860b57cec5SDimitry Andric }
48870b57cec5SDimitry Andric 
48880b57cec5SDimitry Andric bool AArch64FastISel::selectSDiv(const Instruction *I) {
48890b57cec5SDimitry Andric   MVT VT;
48900b57cec5SDimitry Andric   if (!isTypeLegal(I->getType(), VT))
48910b57cec5SDimitry Andric     return false;
48920b57cec5SDimitry Andric 
48930b57cec5SDimitry Andric   if (!isa<ConstantInt>(I->getOperand(1)))
48940b57cec5SDimitry Andric     return selectBinaryOp(I, ISD::SDIV);
48950b57cec5SDimitry Andric 
48960b57cec5SDimitry Andric   const APInt &C = cast<ConstantInt>(I->getOperand(1))->getValue();
48970b57cec5SDimitry Andric   if ((VT != MVT::i32 && VT != MVT::i64) || !C ||
4898349cc55cSDimitry Andric       !(C.isPowerOf2() || C.isNegatedPowerOf2()))
48990b57cec5SDimitry Andric     return selectBinaryOp(I, ISD::SDIV);
49000b57cec5SDimitry Andric 
490106c3fb27SDimitry Andric   unsigned Lg2 = C.countr_zero();
490204eeddc0SDimitry Andric   Register Src0Reg = getRegForValue(I->getOperand(0));
49030b57cec5SDimitry Andric   if (!Src0Reg)
49040b57cec5SDimitry Andric     return false;
49050b57cec5SDimitry Andric 
49060b57cec5SDimitry Andric   if (cast<BinaryOperator>(I)->isExact()) {
4907fe6060f1SDimitry Andric     unsigned ResultReg = emitASR_ri(VT, VT, Src0Reg, Lg2);
49080b57cec5SDimitry Andric     if (!ResultReg)
49090b57cec5SDimitry Andric       return false;
49100b57cec5SDimitry Andric     updateValueMap(I, ResultReg);
49110b57cec5SDimitry Andric     return true;
49120b57cec5SDimitry Andric   }
49130b57cec5SDimitry Andric 
49140b57cec5SDimitry Andric   int64_t Pow2MinusOne = (1ULL << Lg2) - 1;
4915fe6060f1SDimitry Andric   unsigned AddReg = emitAdd_ri_(VT, Src0Reg, Pow2MinusOne);
49160b57cec5SDimitry Andric   if (!AddReg)
49170b57cec5SDimitry Andric     return false;
49180b57cec5SDimitry Andric 
49190b57cec5SDimitry Andric   // (Src0 < 0) ? Pow2 - 1 : 0;
4920fe6060f1SDimitry Andric   if (!emitICmp_ri(VT, Src0Reg, 0))
49210b57cec5SDimitry Andric     return false;
49220b57cec5SDimitry Andric 
49230b57cec5SDimitry Andric   unsigned SelectOpc;
49240b57cec5SDimitry Andric   const TargetRegisterClass *RC;
49250b57cec5SDimitry Andric   if (VT == MVT::i64) {
49260b57cec5SDimitry Andric     SelectOpc = AArch64::CSELXr;
49270b57cec5SDimitry Andric     RC = &AArch64::GPR64RegClass;
49280b57cec5SDimitry Andric   } else {
49290b57cec5SDimitry Andric     SelectOpc = AArch64::CSELWr;
49300b57cec5SDimitry Andric     RC = &AArch64::GPR32RegClass;
49310b57cec5SDimitry Andric   }
493204eeddc0SDimitry Andric   Register SelectReg = fastEmitInst_rri(SelectOpc, RC, AddReg, Src0Reg,
4933fe6060f1SDimitry Andric                                         AArch64CC::LT);
49340b57cec5SDimitry Andric   if (!SelectReg)
49350b57cec5SDimitry Andric     return false;
49360b57cec5SDimitry Andric 
49370b57cec5SDimitry Andric   // Divide by Pow2 --> ashr. If we're dividing by a negative value we must also
49380b57cec5SDimitry Andric   // negate the result.
49390b57cec5SDimitry Andric   unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
49400b57cec5SDimitry Andric   unsigned ResultReg;
49410b57cec5SDimitry Andric   if (C.isNegative())
4942fe6060f1SDimitry Andric     ResultReg = emitAddSub_rs(/*UseAdd=*/false, VT, ZeroReg, SelectReg,
4943fe6060f1SDimitry Andric                               AArch64_AM::ASR, Lg2);
49440b57cec5SDimitry Andric   else
4945fe6060f1SDimitry Andric     ResultReg = emitASR_ri(VT, VT, SelectReg, Lg2);
49460b57cec5SDimitry Andric 
49470b57cec5SDimitry Andric   if (!ResultReg)
49480b57cec5SDimitry Andric     return false;
49490b57cec5SDimitry Andric 
49500b57cec5SDimitry Andric   updateValueMap(I, ResultReg);
49510b57cec5SDimitry Andric   return true;
49520b57cec5SDimitry Andric }
49530b57cec5SDimitry Andric 
49540b57cec5SDimitry Andric /// This is mostly a copy of the existing FastISel getRegForGEPIndex code. We
49550b57cec5SDimitry Andric /// have to duplicate it for AArch64, because otherwise we would fail during the
49560b57cec5SDimitry Andric /// sign-extend emission.
4957fe6060f1SDimitry Andric unsigned AArch64FastISel::getRegForGEPIndex(const Value *Idx) {
495804eeddc0SDimitry Andric   Register IdxN = getRegForValue(Idx);
49590b57cec5SDimitry Andric   if (IdxN == 0)
49600b57cec5SDimitry Andric     // Unhandled operand. Halt "fast" selection and bail.
4961fe6060f1SDimitry Andric     return 0;
49620b57cec5SDimitry Andric 
49630b57cec5SDimitry Andric   // If the index is smaller or larger than intptr_t, truncate or extend it.
49640b57cec5SDimitry Andric   MVT PtrVT = TLI.getPointerTy(DL);
49650b57cec5SDimitry Andric   EVT IdxVT = EVT::getEVT(Idx->getType(), /*HandleUnknown=*/false);
49660b57cec5SDimitry Andric   if (IdxVT.bitsLT(PtrVT)) {
49670b57cec5SDimitry Andric     IdxN = emitIntExt(IdxVT.getSimpleVT(), IdxN, PtrVT, /*isZExt=*/false);
49680b57cec5SDimitry Andric   } else if (IdxVT.bitsGT(PtrVT))
49690b57cec5SDimitry Andric     llvm_unreachable("AArch64 FastISel doesn't support types larger than i64");
4970fe6060f1SDimitry Andric   return IdxN;
49710b57cec5SDimitry Andric }
49720b57cec5SDimitry Andric 
49730b57cec5SDimitry Andric /// This is mostly a copy of the existing FastISel GEP code, but we have to
49740b57cec5SDimitry Andric /// duplicate it for AArch64, because otherwise we would bail out even for
49750b57cec5SDimitry Andric /// simple cases. This is because the standard fastEmit functions don't cover
49760b57cec5SDimitry Andric /// MUL at all and ADD is lowered very inefficientily.
49770b57cec5SDimitry Andric bool AArch64FastISel::selectGetElementPtr(const Instruction *I) {
4978480093f4SDimitry Andric   if (Subtarget->isTargetILP32())
4979480093f4SDimitry Andric     return false;
4980480093f4SDimitry Andric 
498104eeddc0SDimitry Andric   Register N = getRegForValue(I->getOperand(0));
49820b57cec5SDimitry Andric   if (!N)
49830b57cec5SDimitry Andric     return false;
49840b57cec5SDimitry Andric 
49850b57cec5SDimitry Andric   // Keep a running tab of the total offset to coalesce multiple N = N + Offset
49860b57cec5SDimitry Andric   // into a single N = N + TotalOffset.
49870b57cec5SDimitry Andric   uint64_t TotalOffs = 0;
49880b57cec5SDimitry Andric   MVT VT = TLI.getPointerTy(DL);
49890b57cec5SDimitry Andric   for (gep_type_iterator GTI = gep_type_begin(I), E = gep_type_end(I);
49900b57cec5SDimitry Andric        GTI != E; ++GTI) {
49910b57cec5SDimitry Andric     const Value *Idx = GTI.getOperand();
49920b57cec5SDimitry Andric     if (auto *StTy = GTI.getStructTypeOrNull()) {
49930b57cec5SDimitry Andric       unsigned Field = cast<ConstantInt>(Idx)->getZExtValue();
49940b57cec5SDimitry Andric       // N = N + Offset
49950b57cec5SDimitry Andric       if (Field)
49960b57cec5SDimitry Andric         TotalOffs += DL.getStructLayout(StTy)->getElementOffset(Field);
49970b57cec5SDimitry Andric     } else {
49980b57cec5SDimitry Andric       // If this is a constant subscript, handle it quickly.
49990b57cec5SDimitry Andric       if (const auto *CI = dyn_cast<ConstantInt>(Idx)) {
50000b57cec5SDimitry Andric         if (CI->isZero())
50010b57cec5SDimitry Andric           continue;
50020b57cec5SDimitry Andric         // N = N + Offset
50031db9f3b2SDimitry Andric         TotalOffs += GTI.getSequentialElementStride(DL) *
50041db9f3b2SDimitry Andric                      cast<ConstantInt>(CI)->getSExtValue();
50050b57cec5SDimitry Andric         continue;
50060b57cec5SDimitry Andric       }
50070b57cec5SDimitry Andric       if (TotalOffs) {
5008fe6060f1SDimitry Andric         N = emitAdd_ri_(VT, N, TotalOffs);
50090b57cec5SDimitry Andric         if (!N)
50100b57cec5SDimitry Andric           return false;
50110b57cec5SDimitry Andric         TotalOffs = 0;
50120b57cec5SDimitry Andric       }
50130b57cec5SDimitry Andric 
50140b57cec5SDimitry Andric       // N = N + Idx * ElementSize;
50151db9f3b2SDimitry Andric       uint64_t ElementSize = GTI.getSequentialElementStride(DL);
5016fe6060f1SDimitry Andric       unsigned IdxN = getRegForGEPIndex(Idx);
50170b57cec5SDimitry Andric       if (!IdxN)
50180b57cec5SDimitry Andric         return false;
50190b57cec5SDimitry Andric 
50200b57cec5SDimitry Andric       if (ElementSize != 1) {
50210b57cec5SDimitry Andric         unsigned C = fastEmit_i(VT, VT, ISD::Constant, ElementSize);
50220b57cec5SDimitry Andric         if (!C)
50230b57cec5SDimitry Andric           return false;
5024fe6060f1SDimitry Andric         IdxN = emitMul_rr(VT, IdxN, C);
50250b57cec5SDimitry Andric         if (!IdxN)
50260b57cec5SDimitry Andric           return false;
50270b57cec5SDimitry Andric       }
5028fe6060f1SDimitry Andric       N = fastEmit_rr(VT, VT, ISD::ADD, N, IdxN);
50290b57cec5SDimitry Andric       if (!N)
50300b57cec5SDimitry Andric         return false;
50310b57cec5SDimitry Andric     }
50320b57cec5SDimitry Andric   }
50330b57cec5SDimitry Andric   if (TotalOffs) {
5034fe6060f1SDimitry Andric     N = emitAdd_ri_(VT, N, TotalOffs);
50350b57cec5SDimitry Andric     if (!N)
50360b57cec5SDimitry Andric       return false;
50370b57cec5SDimitry Andric   }
50380b57cec5SDimitry Andric   updateValueMap(I, N);
50390b57cec5SDimitry Andric   return true;
50400b57cec5SDimitry Andric }
50410b57cec5SDimitry Andric 
50420b57cec5SDimitry Andric bool AArch64FastISel::selectAtomicCmpXchg(const AtomicCmpXchgInst *I) {
50435f757f3fSDimitry Andric   assert(TM.getOptLevel() == CodeGenOptLevel::None &&
50440b57cec5SDimitry Andric          "cmpxchg survived AtomicExpand at optlevel > -O0");
50450b57cec5SDimitry Andric 
50460b57cec5SDimitry Andric   auto *RetPairTy = cast<StructType>(I->getType());
50470b57cec5SDimitry Andric   Type *RetTy = RetPairTy->getTypeAtIndex(0U);
50480b57cec5SDimitry Andric   assert(RetPairTy->getTypeAtIndex(1U)->isIntegerTy(1) &&
50490b57cec5SDimitry Andric          "cmpxchg has a non-i1 status result");
50500b57cec5SDimitry Andric 
50510b57cec5SDimitry Andric   MVT VT;
50520b57cec5SDimitry Andric   if (!isTypeLegal(RetTy, VT))
50530b57cec5SDimitry Andric     return false;
50540b57cec5SDimitry Andric 
50550b57cec5SDimitry Andric   const TargetRegisterClass *ResRC;
50560b57cec5SDimitry Andric   unsigned Opc, CmpOpc;
50570b57cec5SDimitry Andric   // This only supports i32/i64, because i8/i16 aren't legal, and the generic
50580b57cec5SDimitry Andric   // extractvalue selection doesn't support that.
50590b57cec5SDimitry Andric   if (VT == MVT::i32) {
50600b57cec5SDimitry Andric     Opc = AArch64::CMP_SWAP_32;
50610b57cec5SDimitry Andric     CmpOpc = AArch64::SUBSWrs;
50620b57cec5SDimitry Andric     ResRC = &AArch64::GPR32RegClass;
50630b57cec5SDimitry Andric   } else if (VT == MVT::i64) {
50640b57cec5SDimitry Andric     Opc = AArch64::CMP_SWAP_64;
50650b57cec5SDimitry Andric     CmpOpc = AArch64::SUBSXrs;
50660b57cec5SDimitry Andric     ResRC = &AArch64::GPR64RegClass;
50670b57cec5SDimitry Andric   } else {
50680b57cec5SDimitry Andric     return false;
50690b57cec5SDimitry Andric   }
50700b57cec5SDimitry Andric 
50710b57cec5SDimitry Andric   const MCInstrDesc &II = TII.get(Opc);
50720b57cec5SDimitry Andric 
507304eeddc0SDimitry Andric   const Register AddrReg = constrainOperandRegClass(
50740b57cec5SDimitry Andric       II, getRegForValue(I->getPointerOperand()), II.getNumDefs());
507504eeddc0SDimitry Andric   const Register DesiredReg = constrainOperandRegClass(
50760b57cec5SDimitry Andric       II, getRegForValue(I->getCompareOperand()), II.getNumDefs() + 1);
507704eeddc0SDimitry Andric   const Register NewReg = constrainOperandRegClass(
50780b57cec5SDimitry Andric       II, getRegForValue(I->getNewValOperand()), II.getNumDefs() + 2);
50790b57cec5SDimitry Andric 
508004eeddc0SDimitry Andric   const Register ResultReg1 = createResultReg(ResRC);
508104eeddc0SDimitry Andric   const Register ResultReg2 = createResultReg(&AArch64::GPR32RegClass);
508204eeddc0SDimitry Andric   const Register ScratchReg = createResultReg(&AArch64::GPR32RegClass);
50830b57cec5SDimitry Andric 
50840b57cec5SDimitry Andric   // FIXME: MachineMemOperand doesn't support cmpxchg yet.
5085bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)
50860b57cec5SDimitry Andric       .addDef(ResultReg1)
50870b57cec5SDimitry Andric       .addDef(ScratchReg)
50880b57cec5SDimitry Andric       .addUse(AddrReg)
50890b57cec5SDimitry Andric       .addUse(DesiredReg)
50900b57cec5SDimitry Andric       .addUse(NewReg);
50910b57cec5SDimitry Andric 
5092bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(CmpOpc))
50930b57cec5SDimitry Andric       .addDef(VT == MVT::i32 ? AArch64::WZR : AArch64::XZR)
50940b57cec5SDimitry Andric       .addUse(ResultReg1)
50950b57cec5SDimitry Andric       .addUse(DesiredReg)
50960b57cec5SDimitry Andric       .addImm(0);
50970b57cec5SDimitry Andric 
5098bdd1243dSDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::CSINCWr))
50990b57cec5SDimitry Andric       .addDef(ResultReg2)
51000b57cec5SDimitry Andric       .addUse(AArch64::WZR)
51010b57cec5SDimitry Andric       .addUse(AArch64::WZR)
51020b57cec5SDimitry Andric       .addImm(AArch64CC::NE);
51030b57cec5SDimitry Andric 
51040b57cec5SDimitry Andric   assert((ResultReg1 + 1) == ResultReg2 && "Nonconsecutive result registers.");
51050b57cec5SDimitry Andric   updateValueMap(I, ResultReg1, 2);
51060b57cec5SDimitry Andric   return true;
51070b57cec5SDimitry Andric }
51080b57cec5SDimitry Andric 
51090b57cec5SDimitry Andric bool AArch64FastISel::fastSelectInstruction(const Instruction *I) {
5110bdd1243dSDimitry Andric   if (TLI.fallBackToDAGISel(*I))
5111bdd1243dSDimitry Andric     return false;
51120b57cec5SDimitry Andric   switch (I->getOpcode()) {
51130b57cec5SDimitry Andric   default:
51140b57cec5SDimitry Andric     break;
51150b57cec5SDimitry Andric   case Instruction::Add:
51160b57cec5SDimitry Andric   case Instruction::Sub:
51170b57cec5SDimitry Andric     return selectAddSub(I);
51180b57cec5SDimitry Andric   case Instruction::Mul:
51190b57cec5SDimitry Andric     return selectMul(I);
51200b57cec5SDimitry Andric   case Instruction::SDiv:
51210b57cec5SDimitry Andric     return selectSDiv(I);
51220b57cec5SDimitry Andric   case Instruction::SRem:
51230b57cec5SDimitry Andric     if (!selectBinaryOp(I, ISD::SREM))
51240b57cec5SDimitry Andric       return selectRem(I, ISD::SREM);
51250b57cec5SDimitry Andric     return true;
51260b57cec5SDimitry Andric   case Instruction::URem:
51270b57cec5SDimitry Andric     if (!selectBinaryOp(I, ISD::UREM))
51280b57cec5SDimitry Andric       return selectRem(I, ISD::UREM);
51290b57cec5SDimitry Andric     return true;
51300b57cec5SDimitry Andric   case Instruction::Shl:
51310b57cec5SDimitry Andric   case Instruction::LShr:
51320b57cec5SDimitry Andric   case Instruction::AShr:
51330b57cec5SDimitry Andric     return selectShift(I);
51340b57cec5SDimitry Andric   case Instruction::And:
51350b57cec5SDimitry Andric   case Instruction::Or:
51360b57cec5SDimitry Andric   case Instruction::Xor:
51370b57cec5SDimitry Andric     return selectLogicalOp(I);
51380b57cec5SDimitry Andric   case Instruction::Br:
51390b57cec5SDimitry Andric     return selectBranch(I);
51400b57cec5SDimitry Andric   case Instruction::IndirectBr:
51410b57cec5SDimitry Andric     return selectIndirectBr(I);
51420b57cec5SDimitry Andric   case Instruction::BitCast:
51430b57cec5SDimitry Andric     if (!FastISel::selectBitCast(I))
51440b57cec5SDimitry Andric       return selectBitCast(I);
51450b57cec5SDimitry Andric     return true;
51460b57cec5SDimitry Andric   case Instruction::FPToSI:
51470b57cec5SDimitry Andric     if (!selectCast(I, ISD::FP_TO_SINT))
51480b57cec5SDimitry Andric       return selectFPToInt(I, /*Signed=*/true);
51490b57cec5SDimitry Andric     return true;
51500b57cec5SDimitry Andric   case Instruction::FPToUI:
51510b57cec5SDimitry Andric     return selectFPToInt(I, /*Signed=*/false);
51520b57cec5SDimitry Andric   case Instruction::ZExt:
51530b57cec5SDimitry Andric   case Instruction::SExt:
51540b57cec5SDimitry Andric     return selectIntExt(I);
51550b57cec5SDimitry Andric   case Instruction::Trunc:
51560b57cec5SDimitry Andric     if (!selectCast(I, ISD::TRUNCATE))
51570b57cec5SDimitry Andric       return selectTrunc(I);
51580b57cec5SDimitry Andric     return true;
51590b57cec5SDimitry Andric   case Instruction::FPExt:
51600b57cec5SDimitry Andric     return selectFPExt(I);
51610b57cec5SDimitry Andric   case Instruction::FPTrunc:
51620b57cec5SDimitry Andric     return selectFPTrunc(I);
51630b57cec5SDimitry Andric   case Instruction::SIToFP:
51640b57cec5SDimitry Andric     if (!selectCast(I, ISD::SINT_TO_FP))
51650b57cec5SDimitry Andric       return selectIntToFP(I, /*Signed=*/true);
51660b57cec5SDimitry Andric     return true;
51670b57cec5SDimitry Andric   case Instruction::UIToFP:
51680b57cec5SDimitry Andric     return selectIntToFP(I, /*Signed=*/false);
51690b57cec5SDimitry Andric   case Instruction::Load:
51700b57cec5SDimitry Andric     return selectLoad(I);
51710b57cec5SDimitry Andric   case Instruction::Store:
51720b57cec5SDimitry Andric     return selectStore(I);
51730b57cec5SDimitry Andric   case Instruction::FCmp:
51740b57cec5SDimitry Andric   case Instruction::ICmp:
51750b57cec5SDimitry Andric     return selectCmp(I);
51760b57cec5SDimitry Andric   case Instruction::Select:
51770b57cec5SDimitry Andric     return selectSelect(I);
51780b57cec5SDimitry Andric   case Instruction::Ret:
51790b57cec5SDimitry Andric     return selectRet(I);
51800b57cec5SDimitry Andric   case Instruction::FRem:
51810b57cec5SDimitry Andric     return selectFRem(I);
51820b57cec5SDimitry Andric   case Instruction::GetElementPtr:
51830b57cec5SDimitry Andric     return selectGetElementPtr(I);
51840b57cec5SDimitry Andric   case Instruction::AtomicCmpXchg:
51850b57cec5SDimitry Andric     return selectAtomicCmpXchg(cast<AtomicCmpXchgInst>(I));
51860b57cec5SDimitry Andric   }
51870b57cec5SDimitry Andric 
51880b57cec5SDimitry Andric   // fall-back to target-independent instruction selection.
51890b57cec5SDimitry Andric   return selectOperator(I, I->getOpcode());
51900b57cec5SDimitry Andric }
51910b57cec5SDimitry Andric 
51920b57cec5SDimitry Andric FastISel *AArch64::createFastISel(FunctionLoweringInfo &FuncInfo,
51930b57cec5SDimitry Andric                                         const TargetLibraryInfo *LibInfo) {
5194bdd1243dSDimitry Andric 
5195bdd1243dSDimitry Andric   SMEAttrs CallerAttrs(*FuncInfo.Fn);
5196*0fca6ea1SDimitry Andric   if (CallerAttrs.hasZAState() || CallerAttrs.hasZT0State() ||
5197*0fca6ea1SDimitry Andric       CallerAttrs.hasStreamingInterfaceOrBody() ||
51985f757f3fSDimitry Andric       CallerAttrs.hasStreamingCompatibleInterface())
5199bdd1243dSDimitry Andric     return nullptr;
52000b57cec5SDimitry Andric   return new AArch64FastISel(FuncInfo, LibInfo);
52010b57cec5SDimitry Andric }
5202