10b57cec5SDimitry Andric //===- ARMFastISel.cpp - ARM 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 ARM-specific support for the FastISel class. Some
100b57cec5SDimitry Andric // of the target-specific code is generated by tablegen in the file
110b57cec5SDimitry Andric // ARMGenFastISel.inc, which is #included here.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include "ARM.h"
160b57cec5SDimitry Andric #include "ARMBaseInstrInfo.h"
170b57cec5SDimitry Andric #include "ARMBaseRegisterInfo.h"
180b57cec5SDimitry Andric #include "ARMCallingConv.h"
190b57cec5SDimitry Andric #include "ARMConstantPoolValue.h"
200b57cec5SDimitry Andric #include "ARMISelLowering.h"
210b57cec5SDimitry Andric #include "ARMMachineFunctionInfo.h"
220b57cec5SDimitry Andric #include "ARMSubtarget.h"
230b57cec5SDimitry Andric #include "MCTargetDesc/ARMAddressingModes.h"
240b57cec5SDimitry Andric #include "MCTargetDesc/ARMBaseInfo.h"
250b57cec5SDimitry Andric #include "Utils/ARMBaseInfo.h"
260b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h"
270b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
280b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
290b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/FastISel.h"
320b57cec5SDimitry Andric #include "llvm/CodeGen/FunctionLoweringInfo.h"
330b57cec5SDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h"
340b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
350b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
360b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
370b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
380b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
390b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
400b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
410b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
420b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
43*0fca6ea1SDimitry Andric #include "llvm/CodeGen/RuntimeLibcallUtil.h"
440b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
450b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
460b57cec5SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h"
470b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
480b57cec5SDimitry Andric #include "llvm/CodeGen/ValueTypes.h"
49*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h"
500b57cec5SDimitry Andric #include "llvm/IR/Argument.h"
510b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
520b57cec5SDimitry Andric #include "llvm/IR/CallingConv.h"
530b57cec5SDimitry Andric #include "llvm/IR/Constant.h"
540b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
550b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
560b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
570b57cec5SDimitry Andric #include "llvm/IR/Function.h"
580b57cec5SDimitry Andric #include "llvm/IR/GetElementPtrTypeIterator.h"
590b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
600b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
610b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h"
620b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
630b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
640b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
650b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h"
660b57cec5SDimitry Andric #include "llvm/IR/Module.h"
670b57cec5SDimitry Andric #include "llvm/IR/Operator.h"
680b57cec5SDimitry Andric #include "llvm/IR/Type.h"
690b57cec5SDimitry Andric #include "llvm/IR/User.h"
700b57cec5SDimitry Andric #include "llvm/IR/Value.h"
710b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
720b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
730b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
740b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
750b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
760b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
770b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
780b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h"
790b57cec5SDimitry Andric #include <cassert>
800b57cec5SDimitry Andric #include <cstdint>
810b57cec5SDimitry Andric #include <utility>
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric using namespace llvm;
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric namespace {
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric // All possible address modes, plus some.
880b57cec5SDimitry Andric struct Address {
890b57cec5SDimitry Andric enum {
900b57cec5SDimitry Andric RegBase,
910b57cec5SDimitry Andric FrameIndexBase
920b57cec5SDimitry Andric } BaseType = RegBase;
930b57cec5SDimitry Andric
940b57cec5SDimitry Andric union {
950b57cec5SDimitry Andric unsigned Reg;
960b57cec5SDimitry Andric int FI;
970b57cec5SDimitry Andric } Base;
980b57cec5SDimitry Andric
990b57cec5SDimitry Andric int Offset = 0;
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric // Innocuous defaults for our address.
Address__anone34823300111::Address1020b57cec5SDimitry Andric Address() {
1030b57cec5SDimitry Andric Base.Reg = 0;
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric };
1060b57cec5SDimitry Andric
1070b57cec5SDimitry Andric class ARMFastISel final : public FastISel {
1080b57cec5SDimitry Andric /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
1090b57cec5SDimitry Andric /// make the right decision when generating code for different targets.
1100b57cec5SDimitry Andric const ARMSubtarget *Subtarget;
1110b57cec5SDimitry Andric Module &M;
1120b57cec5SDimitry Andric const TargetMachine &TM;
1130b57cec5SDimitry Andric const TargetInstrInfo &TII;
1140b57cec5SDimitry Andric const TargetLowering &TLI;
1150b57cec5SDimitry Andric ARMFunctionInfo *AFI;
1160b57cec5SDimitry Andric
1170b57cec5SDimitry Andric // Convenience variables to avoid some queries.
1180b57cec5SDimitry Andric bool isThumb2;
1190b57cec5SDimitry Andric LLVMContext *Context;
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric public:
ARMFastISel(FunctionLoweringInfo & funcInfo,const TargetLibraryInfo * libInfo)1220b57cec5SDimitry Andric explicit ARMFastISel(FunctionLoweringInfo &funcInfo,
1230b57cec5SDimitry Andric const TargetLibraryInfo *libInfo)
1240b57cec5SDimitry Andric : FastISel(funcInfo, libInfo),
12581ad6265SDimitry Andric Subtarget(&funcInfo.MF->getSubtarget<ARMSubtarget>()),
1260b57cec5SDimitry Andric M(const_cast<Module &>(*funcInfo.Fn->getParent())),
1270b57cec5SDimitry Andric TM(funcInfo.MF->getTarget()), TII(*Subtarget->getInstrInfo()),
1280b57cec5SDimitry Andric TLI(*Subtarget->getTargetLowering()) {
1290b57cec5SDimitry Andric AFI = funcInfo.MF->getInfo<ARMFunctionInfo>();
1300b57cec5SDimitry Andric isThumb2 = AFI->isThumbFunction();
1310b57cec5SDimitry Andric Context = &funcInfo.Fn->getContext();
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric private:
1350b57cec5SDimitry Andric // Code from FastISel.cpp.
1360b57cec5SDimitry Andric
1370b57cec5SDimitry Andric unsigned fastEmitInst_r(unsigned MachineInstOpcode,
138fe6060f1SDimitry Andric const TargetRegisterClass *RC, unsigned Op0);
1390b57cec5SDimitry Andric unsigned fastEmitInst_rr(unsigned MachineInstOpcode,
1400b57cec5SDimitry Andric const TargetRegisterClass *RC,
141fe6060f1SDimitry Andric unsigned Op0, unsigned Op1);
1420b57cec5SDimitry Andric unsigned fastEmitInst_ri(unsigned MachineInstOpcode,
1430b57cec5SDimitry Andric const TargetRegisterClass *RC,
144fe6060f1SDimitry Andric unsigned Op0, uint64_t Imm);
1450b57cec5SDimitry Andric unsigned fastEmitInst_i(unsigned MachineInstOpcode,
1460b57cec5SDimitry Andric const TargetRegisterClass *RC,
1470b57cec5SDimitry Andric uint64_t Imm);
1480b57cec5SDimitry Andric
1490b57cec5SDimitry Andric // Backend specific FastISel code.
1500b57cec5SDimitry Andric
1510b57cec5SDimitry Andric bool fastSelectInstruction(const Instruction *I) override;
1520b57cec5SDimitry Andric unsigned fastMaterializeConstant(const Constant *C) override;
1530b57cec5SDimitry Andric unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
1540b57cec5SDimitry Andric bool tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
1550b57cec5SDimitry Andric const LoadInst *LI) override;
1560b57cec5SDimitry Andric bool fastLowerArguments() override;
1570b57cec5SDimitry Andric
1580b57cec5SDimitry Andric #include "ARMGenFastISel.inc"
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andric // Instruction selection routines.
1610b57cec5SDimitry Andric
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 SelectFPExt(const Instruction *I);
1680b57cec5SDimitry Andric bool SelectFPTrunc(const Instruction *I);
1690b57cec5SDimitry Andric bool SelectBinaryIntOp(const Instruction *I, unsigned ISDOpcode);
1700b57cec5SDimitry Andric bool SelectBinaryFPOp(const Instruction *I, unsigned ISDOpcode);
1710b57cec5SDimitry Andric bool SelectIToFP(const Instruction *I, bool isSigned);
1720b57cec5SDimitry Andric bool SelectFPToI(const Instruction *I, bool isSigned);
1730b57cec5SDimitry Andric bool SelectDiv(const Instruction *I, bool isSigned);
1740b57cec5SDimitry Andric bool SelectRem(const Instruction *I, bool isSigned);
1750b57cec5SDimitry Andric bool SelectCall(const Instruction *I, const char *IntrMemName);
1760b57cec5SDimitry Andric bool SelectIntrinsicCall(const IntrinsicInst &I);
1770b57cec5SDimitry Andric bool SelectSelect(const Instruction *I);
1780b57cec5SDimitry Andric bool SelectRet(const Instruction *I);
1790b57cec5SDimitry Andric bool SelectTrunc(const Instruction *I);
1800b57cec5SDimitry Andric bool SelectIntExt(const Instruction *I);
1810b57cec5SDimitry Andric bool SelectShift(const Instruction *I, ARM_AM::ShiftOpc ShiftTy);
1820b57cec5SDimitry Andric
1830b57cec5SDimitry Andric // Utility routines.
1840b57cec5SDimitry Andric
1850b57cec5SDimitry Andric bool isPositionIndependent() const;
1860b57cec5SDimitry Andric bool isTypeLegal(Type *Ty, MVT &VT);
1870b57cec5SDimitry Andric bool isLoadTypeLegal(Type *Ty, MVT &VT);
1880b57cec5SDimitry Andric bool ARMEmitCmp(const Value *Src1Value, const Value *Src2Value,
1898bcb0991SDimitry Andric bool isZExt);
1908bcb0991SDimitry Andric bool ARMEmitLoad(MVT VT, Register &ResultReg, Address &Addr,
191bdd1243dSDimitry Andric MaybeAlign Alignment = std::nullopt, bool isZExt = true,
1920b57cec5SDimitry Andric bool allocReg = true);
1930b57cec5SDimitry Andric bool ARMEmitStore(MVT VT, unsigned SrcReg, Address &Addr,
194bdd1243dSDimitry Andric MaybeAlign Alignment = std::nullopt);
1950b57cec5SDimitry Andric bool ARMComputeAddress(const Value *Obj, Address &Addr);
1960b57cec5SDimitry Andric void ARMSimplifyAddress(Address &Addr, MVT VT, bool useAM3);
1970b57cec5SDimitry Andric bool ARMIsMemCpySmall(uint64_t Len);
1980b57cec5SDimitry Andric bool ARMTryEmitSmallMemCpy(Address Dest, Address Src, uint64_t Len,
199bdd1243dSDimitry Andric MaybeAlign Alignment);
2000b57cec5SDimitry Andric unsigned ARMEmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt);
2010b57cec5SDimitry Andric unsigned ARMMaterializeFP(const ConstantFP *CFP, MVT VT);
2020b57cec5SDimitry Andric unsigned ARMMaterializeInt(const Constant *C, MVT VT);
2030b57cec5SDimitry Andric unsigned ARMMaterializeGV(const GlobalValue *GV, MVT VT);
2040b57cec5SDimitry Andric unsigned ARMMoveToFPReg(MVT VT, unsigned SrcReg);
2050b57cec5SDimitry Andric unsigned ARMMoveToIntReg(MVT VT, unsigned SrcReg);
2060b57cec5SDimitry Andric unsigned ARMSelectCallOp(bool UseReg);
2075ffd83dbSDimitry Andric unsigned ARMLowerPICELF(const GlobalValue *GV, MVT VT);
2080b57cec5SDimitry Andric
getTargetLowering()2090b57cec5SDimitry Andric const TargetLowering *getTargetLowering() { return &TLI; }
2100b57cec5SDimitry Andric
2110b57cec5SDimitry Andric // Call handling routines.
2120b57cec5SDimitry Andric
2130b57cec5SDimitry Andric CCAssignFn *CCAssignFnForCall(CallingConv::ID CC,
2140b57cec5SDimitry Andric bool Return,
2150b57cec5SDimitry Andric bool isVarArg);
2160b57cec5SDimitry Andric bool ProcessCallArgs(SmallVectorImpl<Value*> &Args,
2178bcb0991SDimitry Andric SmallVectorImpl<Register> &ArgRegs,
2180b57cec5SDimitry Andric SmallVectorImpl<MVT> &ArgVTs,
2190b57cec5SDimitry Andric SmallVectorImpl<ISD::ArgFlagsTy> &ArgFlags,
2208bcb0991SDimitry Andric SmallVectorImpl<Register> &RegArgs,
2210b57cec5SDimitry Andric CallingConv::ID CC,
2220b57cec5SDimitry Andric unsigned &NumBytes,
2230b57cec5SDimitry Andric bool isVarArg);
2240b57cec5SDimitry Andric unsigned getLibcallReg(const Twine &Name);
2258bcb0991SDimitry Andric bool FinishCall(MVT RetVT, SmallVectorImpl<Register> &UsedRegs,
2260b57cec5SDimitry Andric const Instruction *I, CallingConv::ID CC,
2270b57cec5SDimitry Andric unsigned &NumBytes, bool isVarArg);
2280b57cec5SDimitry Andric bool ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call);
2290b57cec5SDimitry Andric
2300b57cec5SDimitry Andric // OptionalDef handling routines.
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric bool isARMNEONPred(const MachineInstr *MI);
2330b57cec5SDimitry Andric bool DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR);
2340b57cec5SDimitry Andric const MachineInstrBuilder &AddOptionalDefs(const MachineInstrBuilder &MIB);
2350b57cec5SDimitry Andric void AddLoadStoreOperands(MVT VT, Address &Addr,
2360b57cec5SDimitry Andric const MachineInstrBuilder &MIB,
2370b57cec5SDimitry Andric MachineMemOperand::Flags Flags, bool useAM3);
2380b57cec5SDimitry Andric };
2390b57cec5SDimitry Andric
2400b57cec5SDimitry Andric } // end anonymous namespace
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric // DefinesOptionalPredicate - This is different from DefinesPredicate in that
2430b57cec5SDimitry Andric // we don't care about implicit defs here, just places we'll need to add a
2440b57cec5SDimitry Andric // default CCReg argument. Sets CPSR if we're setting CPSR instead of CCR.
DefinesOptionalPredicate(MachineInstr * MI,bool * CPSR)2450b57cec5SDimitry Andric bool ARMFastISel::DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR) {
2460b57cec5SDimitry Andric if (!MI->hasOptionalDef())
2470b57cec5SDimitry Andric return false;
2480b57cec5SDimitry Andric
2490b57cec5SDimitry Andric // Look to see if our OptionalDef is defining CPSR or CCR.
2500b57cec5SDimitry Andric for (const MachineOperand &MO : MI->operands()) {
2510b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef()) continue;
2520b57cec5SDimitry Andric if (MO.getReg() == ARM::CPSR)
2530b57cec5SDimitry Andric *CPSR = true;
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric return true;
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric
isARMNEONPred(const MachineInstr * MI)2580b57cec5SDimitry Andric bool ARMFastISel::isARMNEONPred(const MachineInstr *MI) {
2590b57cec5SDimitry Andric const MCInstrDesc &MCID = MI->getDesc();
2600b57cec5SDimitry Andric
2610b57cec5SDimitry Andric // If we're a thumb2 or not NEON function we'll be handled via isPredicable.
2620b57cec5SDimitry Andric if ((MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainNEON ||
2630b57cec5SDimitry Andric AFI->isThumb2Function())
2640b57cec5SDimitry Andric return MI->isPredicable();
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andric for (const MCOperandInfo &opInfo : MCID.operands())
2670b57cec5SDimitry Andric if (opInfo.isPredicate())
2680b57cec5SDimitry Andric return true;
2690b57cec5SDimitry Andric
2700b57cec5SDimitry Andric return false;
2710b57cec5SDimitry Andric }
2720b57cec5SDimitry Andric
2730b57cec5SDimitry Andric // If the machine is predicable go ahead and add the predicate operands, if
2740b57cec5SDimitry Andric // it needs default CC operands add those.
2750b57cec5SDimitry Andric // TODO: If we want to support thumb1 then we'll need to deal with optional
2760b57cec5SDimitry Andric // CPSR defs that need to be added before the remaining operands. See s_cc_out
2770b57cec5SDimitry Andric // for descriptions why.
2780b57cec5SDimitry Andric const MachineInstrBuilder &
AddOptionalDefs(const MachineInstrBuilder & MIB)2790b57cec5SDimitry Andric ARMFastISel::AddOptionalDefs(const MachineInstrBuilder &MIB) {
2800b57cec5SDimitry Andric MachineInstr *MI = &*MIB;
2810b57cec5SDimitry Andric
2820b57cec5SDimitry Andric // Do we use a predicate? or...
2830b57cec5SDimitry Andric // Are we NEON in ARM mode and have a predicate operand? If so, I know
2840b57cec5SDimitry Andric // we're not predicable but add it anyways.
2850b57cec5SDimitry Andric if (isARMNEONPred(MI))
2860b57cec5SDimitry Andric MIB.add(predOps(ARMCC::AL));
2870b57cec5SDimitry Andric
2880b57cec5SDimitry Andric // Do we optionally set a predicate? Preds is size > 0 iff the predicate
2890b57cec5SDimitry Andric // defines CPSR. All other OptionalDefines in ARM are the CCR register.
2900b57cec5SDimitry Andric bool CPSR = false;
2910b57cec5SDimitry Andric if (DefinesOptionalPredicate(MI, &CPSR))
2920b57cec5SDimitry Andric MIB.add(CPSR ? t1CondCodeOp() : condCodeOp());
2930b57cec5SDimitry Andric return MIB;
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric
fastEmitInst_r(unsigned MachineInstOpcode,const TargetRegisterClass * RC,unsigned Op0)2960b57cec5SDimitry Andric unsigned ARMFastISel::fastEmitInst_r(unsigned MachineInstOpcode,
2970b57cec5SDimitry Andric const TargetRegisterClass *RC,
298fe6060f1SDimitry Andric unsigned Op0) {
2998bcb0991SDimitry Andric Register ResultReg = createResultReg(RC);
3000b57cec5SDimitry Andric const MCInstrDesc &II = TII.get(MachineInstOpcode);
3010b57cec5SDimitry Andric
3020b57cec5SDimitry Andric // Make sure the input operand is sufficiently constrained to be legal
3030b57cec5SDimitry Andric // for this instruction.
3040b57cec5SDimitry Andric Op0 = constrainOperandRegClass(II, Op0, 1);
3050b57cec5SDimitry Andric if (II.getNumDefs() >= 1) {
306bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II,
307fe6060f1SDimitry Andric ResultReg).addReg(Op0));
3080b57cec5SDimitry Andric } else {
309bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)
310fe6060f1SDimitry Andric .addReg(Op0));
311bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3120b57cec5SDimitry Andric TII.get(TargetOpcode::COPY), ResultReg)
313bdd1243dSDimitry Andric .addReg(II.implicit_defs()[0]));
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric return ResultReg;
3160b57cec5SDimitry Andric }
3170b57cec5SDimitry Andric
fastEmitInst_rr(unsigned MachineInstOpcode,const TargetRegisterClass * RC,unsigned Op0,unsigned Op1)3180b57cec5SDimitry Andric unsigned ARMFastISel::fastEmitInst_rr(unsigned MachineInstOpcode,
3190b57cec5SDimitry Andric const TargetRegisterClass *RC,
320fe6060f1SDimitry Andric unsigned Op0, unsigned Op1) {
32104eeddc0SDimitry Andric Register ResultReg = createResultReg(RC);
3220b57cec5SDimitry Andric const MCInstrDesc &II = TII.get(MachineInstOpcode);
3230b57cec5SDimitry Andric
3240b57cec5SDimitry Andric // Make sure the input operands are sufficiently constrained to be legal
3250b57cec5SDimitry Andric // for this instruction.
3260b57cec5SDimitry Andric Op0 = constrainOperandRegClass(II, Op0, 1);
3270b57cec5SDimitry Andric Op1 = constrainOperandRegClass(II, Op1, 2);
3280b57cec5SDimitry Andric
3290b57cec5SDimitry Andric if (II.getNumDefs() >= 1) {
3300b57cec5SDimitry Andric AddOptionalDefs(
331bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)
332fe6060f1SDimitry Andric .addReg(Op0)
333fe6060f1SDimitry Andric .addReg(Op1));
3340b57cec5SDimitry Andric } else {
335bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)
336fe6060f1SDimitry Andric .addReg(Op0)
337fe6060f1SDimitry Andric .addReg(Op1));
338bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3390b57cec5SDimitry Andric TII.get(TargetOpcode::COPY), ResultReg)
340bdd1243dSDimitry Andric .addReg(II.implicit_defs()[0]));
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric return ResultReg;
3430b57cec5SDimitry Andric }
3440b57cec5SDimitry Andric
fastEmitInst_ri(unsigned MachineInstOpcode,const TargetRegisterClass * RC,unsigned Op0,uint64_t Imm)3450b57cec5SDimitry Andric unsigned ARMFastISel::fastEmitInst_ri(unsigned MachineInstOpcode,
3460b57cec5SDimitry Andric const TargetRegisterClass *RC,
347fe6060f1SDimitry Andric unsigned Op0, uint64_t Imm) {
34804eeddc0SDimitry Andric Register ResultReg = createResultReg(RC);
3490b57cec5SDimitry Andric const MCInstrDesc &II = TII.get(MachineInstOpcode);
3500b57cec5SDimitry Andric
3510b57cec5SDimitry Andric // Make sure the input operand is sufficiently constrained to be legal
3520b57cec5SDimitry Andric // for this instruction.
3530b57cec5SDimitry Andric Op0 = constrainOperandRegClass(II, Op0, 1);
3540b57cec5SDimitry Andric if (II.getNumDefs() >= 1) {
3550b57cec5SDimitry Andric AddOptionalDefs(
356bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)
357fe6060f1SDimitry Andric .addReg(Op0)
3580b57cec5SDimitry Andric .addImm(Imm));
3590b57cec5SDimitry Andric } else {
360bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)
361fe6060f1SDimitry Andric .addReg(Op0)
3620b57cec5SDimitry Andric .addImm(Imm));
363bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3640b57cec5SDimitry Andric TII.get(TargetOpcode::COPY), ResultReg)
365bdd1243dSDimitry Andric .addReg(II.implicit_defs()[0]));
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric return ResultReg;
3680b57cec5SDimitry Andric }
3690b57cec5SDimitry Andric
fastEmitInst_i(unsigned MachineInstOpcode,const TargetRegisterClass * RC,uint64_t Imm)3700b57cec5SDimitry Andric unsigned ARMFastISel::fastEmitInst_i(unsigned MachineInstOpcode,
3710b57cec5SDimitry Andric const TargetRegisterClass *RC,
3720b57cec5SDimitry Andric uint64_t Imm) {
37304eeddc0SDimitry Andric Register ResultReg = createResultReg(RC);
3740b57cec5SDimitry Andric const MCInstrDesc &II = TII.get(MachineInstOpcode);
3750b57cec5SDimitry Andric
3760b57cec5SDimitry Andric if (II.getNumDefs() >= 1) {
377bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II,
3780b57cec5SDimitry Andric ResultReg).addImm(Imm));
3790b57cec5SDimitry Andric } else {
380bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)
3810b57cec5SDimitry Andric .addImm(Imm));
382bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3830b57cec5SDimitry Andric TII.get(TargetOpcode::COPY), ResultReg)
384bdd1243dSDimitry Andric .addReg(II.implicit_defs()[0]));
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric return ResultReg;
3870b57cec5SDimitry Andric }
3880b57cec5SDimitry Andric
3890b57cec5SDimitry Andric // TODO: Don't worry about 64-bit now, but when this is fixed remove the
3900b57cec5SDimitry Andric // checks from the various callers.
ARMMoveToFPReg(MVT VT,unsigned SrcReg)3910b57cec5SDimitry Andric unsigned ARMFastISel::ARMMoveToFPReg(MVT VT, unsigned SrcReg) {
3920b57cec5SDimitry Andric if (VT == MVT::f64) return 0;
3930b57cec5SDimitry Andric
39404eeddc0SDimitry Andric Register MoveReg = createResultReg(TLI.getRegClassFor(VT));
395bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3960b57cec5SDimitry Andric TII.get(ARM::VMOVSR), MoveReg)
3970b57cec5SDimitry Andric .addReg(SrcReg));
3980b57cec5SDimitry Andric return MoveReg;
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric
ARMMoveToIntReg(MVT VT,unsigned SrcReg)4010b57cec5SDimitry Andric unsigned ARMFastISel::ARMMoveToIntReg(MVT VT, unsigned SrcReg) {
4020b57cec5SDimitry Andric if (VT == MVT::i64) return 0;
4030b57cec5SDimitry Andric
40404eeddc0SDimitry Andric Register MoveReg = createResultReg(TLI.getRegClassFor(VT));
405bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4060b57cec5SDimitry Andric TII.get(ARM::VMOVRS), MoveReg)
4070b57cec5SDimitry Andric .addReg(SrcReg));
4080b57cec5SDimitry Andric return MoveReg;
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric
4110b57cec5SDimitry Andric // For double width floating point we need to materialize two constants
4120b57cec5SDimitry Andric // (the high and the low) into integer registers then use a move to get
4130b57cec5SDimitry Andric // the combined constant into an FP reg.
ARMMaterializeFP(const ConstantFP * CFP,MVT VT)4140b57cec5SDimitry Andric unsigned ARMFastISel::ARMMaterializeFP(const ConstantFP *CFP, MVT VT) {
4150b57cec5SDimitry Andric const APFloat Val = CFP->getValueAPF();
4160b57cec5SDimitry Andric bool is64bit = VT == MVT::f64;
4170b57cec5SDimitry Andric
4180b57cec5SDimitry Andric // This checks to see if we can use VFP3 instructions to materialize
4190b57cec5SDimitry Andric // a constant, otherwise we have to go through the constant pool.
4200b57cec5SDimitry Andric if (TLI.isFPImmLegal(Val, VT)) {
4210b57cec5SDimitry Andric int Imm;
4220b57cec5SDimitry Andric unsigned Opc;
4230b57cec5SDimitry Andric if (is64bit) {
4240b57cec5SDimitry Andric Imm = ARM_AM::getFP64Imm(Val);
4250b57cec5SDimitry Andric Opc = ARM::FCONSTD;
4260b57cec5SDimitry Andric } else {
4270b57cec5SDimitry Andric Imm = ARM_AM::getFP32Imm(Val);
4280b57cec5SDimitry Andric Opc = ARM::FCONSTS;
4290b57cec5SDimitry Andric }
43004eeddc0SDimitry Andric Register DestReg = createResultReg(TLI.getRegClassFor(VT));
431bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4320b57cec5SDimitry Andric TII.get(Opc), DestReg).addImm(Imm));
4330b57cec5SDimitry Andric return DestReg;
4340b57cec5SDimitry Andric }
4350b57cec5SDimitry Andric
4360b57cec5SDimitry Andric // Require VFP2 for loading fp constants.
4370b57cec5SDimitry Andric if (!Subtarget->hasVFP2Base()) return false;
4380b57cec5SDimitry Andric
4390b57cec5SDimitry Andric // MachineConstantPool wants an explicit alignment.
4405ffd83dbSDimitry Andric Align Alignment = DL.getPrefTypeAlign(CFP->getType());
4415ffd83dbSDimitry Andric unsigned Idx = MCP.getConstantPoolIndex(cast<Constant>(CFP), Alignment);
44204eeddc0SDimitry Andric Register DestReg = createResultReg(TLI.getRegClassFor(VT));
4430b57cec5SDimitry Andric unsigned Opc = is64bit ? ARM::VLDRD : ARM::VLDRS;
4440b57cec5SDimitry Andric
4450b57cec5SDimitry Andric // The extra reg is for addrmode5.
4460b57cec5SDimitry Andric AddOptionalDefs(
447bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), DestReg)
4480b57cec5SDimitry Andric .addConstantPoolIndex(Idx)
4490b57cec5SDimitry Andric .addReg(0));
4500b57cec5SDimitry Andric return DestReg;
4510b57cec5SDimitry Andric }
4520b57cec5SDimitry Andric
ARMMaterializeInt(const Constant * C,MVT VT)4530b57cec5SDimitry Andric unsigned ARMFastISel::ARMMaterializeInt(const Constant *C, MVT VT) {
4540b57cec5SDimitry Andric if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1)
4550b57cec5SDimitry Andric return 0;
4560b57cec5SDimitry Andric
4570b57cec5SDimitry Andric // If we can do this in a single instruction without a constant pool entry
4580b57cec5SDimitry Andric // do so now.
4590b57cec5SDimitry Andric const ConstantInt *CI = cast<ConstantInt>(C);
4600b57cec5SDimitry Andric if (Subtarget->hasV6T2Ops() && isUInt<16>(CI->getZExtValue())) {
4610b57cec5SDimitry Andric unsigned Opc = isThumb2 ? ARM::t2MOVi16 : ARM::MOVi16;
4620b57cec5SDimitry Andric const TargetRegisterClass *RC = isThumb2 ? &ARM::rGPRRegClass :
4630b57cec5SDimitry Andric &ARM::GPRRegClass;
46404eeddc0SDimitry Andric Register ImmReg = createResultReg(RC);
465bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4660b57cec5SDimitry Andric TII.get(Opc), ImmReg)
4670b57cec5SDimitry Andric .addImm(CI->getZExtValue()));
4680b57cec5SDimitry Andric return ImmReg;
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric
4710b57cec5SDimitry Andric // Use MVN to emit negative constants.
4720b57cec5SDimitry Andric if (VT == MVT::i32 && Subtarget->hasV6T2Ops() && CI->isNegative()) {
4730b57cec5SDimitry Andric unsigned Imm = (unsigned)~(CI->getSExtValue());
4740b57cec5SDimitry Andric bool UseImm = isThumb2 ? (ARM_AM::getT2SOImmVal(Imm) != -1) :
4750b57cec5SDimitry Andric (ARM_AM::getSOImmVal(Imm) != -1);
4760b57cec5SDimitry Andric if (UseImm) {
4770b57cec5SDimitry Andric unsigned Opc = isThumb2 ? ARM::t2MVNi : ARM::MVNi;
4780b57cec5SDimitry Andric const TargetRegisterClass *RC = isThumb2 ? &ARM::rGPRRegClass :
4790b57cec5SDimitry Andric &ARM::GPRRegClass;
48004eeddc0SDimitry Andric Register ImmReg = createResultReg(RC);
481bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4820b57cec5SDimitry Andric TII.get(Opc), ImmReg)
4830b57cec5SDimitry Andric .addImm(Imm));
4840b57cec5SDimitry Andric return ImmReg;
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric }
4870b57cec5SDimitry Andric
4880b57cec5SDimitry Andric unsigned ResultReg = 0;
4890b57cec5SDimitry Andric if (Subtarget->useMovt())
4900b57cec5SDimitry Andric ResultReg = fastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue());
4910b57cec5SDimitry Andric
4920b57cec5SDimitry Andric if (ResultReg)
4930b57cec5SDimitry Andric return ResultReg;
4940b57cec5SDimitry Andric
4950b57cec5SDimitry Andric // Load from constant pool. For now 32-bit only.
4960b57cec5SDimitry Andric if (VT != MVT::i32)
4970b57cec5SDimitry Andric return 0;
4980b57cec5SDimitry Andric
4990b57cec5SDimitry Andric // MachineConstantPool wants an explicit alignment.
5005ffd83dbSDimitry Andric Align Alignment = DL.getPrefTypeAlign(C->getType());
5015ffd83dbSDimitry Andric unsigned Idx = MCP.getConstantPoolIndex(C, Alignment);
5020b57cec5SDimitry Andric ResultReg = createResultReg(TLI.getRegClassFor(VT));
5030b57cec5SDimitry Andric if (isThumb2)
504bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
5050b57cec5SDimitry Andric TII.get(ARM::t2LDRpci), ResultReg)
5060b57cec5SDimitry Andric .addConstantPoolIndex(Idx));
5070b57cec5SDimitry Andric else {
5080b57cec5SDimitry Andric // The extra immediate is for addrmode2.
5090b57cec5SDimitry Andric ResultReg = constrainOperandRegClass(TII.get(ARM::LDRcp), ResultReg, 0);
510bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
5110b57cec5SDimitry Andric TII.get(ARM::LDRcp), ResultReg)
5120b57cec5SDimitry Andric .addConstantPoolIndex(Idx)
5130b57cec5SDimitry Andric .addImm(0));
5140b57cec5SDimitry Andric }
5150b57cec5SDimitry Andric return ResultReg;
5160b57cec5SDimitry Andric }
5170b57cec5SDimitry Andric
isPositionIndependent() const5180b57cec5SDimitry Andric bool ARMFastISel::isPositionIndependent() const {
5190b57cec5SDimitry Andric return TLI.isPositionIndependent();
5200b57cec5SDimitry Andric }
5210b57cec5SDimitry Andric
ARMMaterializeGV(const GlobalValue * GV,MVT VT)5220b57cec5SDimitry Andric unsigned ARMFastISel::ARMMaterializeGV(const GlobalValue *GV, MVT VT) {
5230b57cec5SDimitry Andric // For now 32-bit only.
5240b57cec5SDimitry Andric if (VT != MVT::i32 || GV->isThreadLocal()) return 0;
5250b57cec5SDimitry Andric
5260b57cec5SDimitry Andric // ROPI/RWPI not currently supported.
5270b57cec5SDimitry Andric if (Subtarget->isROPI() || Subtarget->isRWPI())
5280b57cec5SDimitry Andric return 0;
5290b57cec5SDimitry Andric
5300b57cec5SDimitry Andric bool IsIndirect = Subtarget->isGVIndirectSymbol(GV);
5310b57cec5SDimitry Andric const TargetRegisterClass *RC = isThumb2 ? &ARM::rGPRRegClass
5320b57cec5SDimitry Andric : &ARM::GPRRegClass;
53304eeddc0SDimitry Andric Register DestReg = createResultReg(RC);
5340b57cec5SDimitry Andric
5350b57cec5SDimitry Andric // FastISel TLS support on non-MachO is broken, punt to SelectionDAG.
5360b57cec5SDimitry Andric const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
5370b57cec5SDimitry Andric bool IsThreadLocal = GVar && GVar->isThreadLocal();
5380b57cec5SDimitry Andric if (!Subtarget->isTargetMachO() && IsThreadLocal) return 0;
5390b57cec5SDimitry Andric
5400b57cec5SDimitry Andric bool IsPositionIndependent = isPositionIndependent();
5410b57cec5SDimitry Andric // Use movw+movt when possible, it avoids constant pool entries.
5420b57cec5SDimitry Andric // Non-darwin targets only support static movt relocations in FastISel.
5430b57cec5SDimitry Andric if (Subtarget->useMovt() &&
5440b57cec5SDimitry Andric (Subtarget->isTargetMachO() || !IsPositionIndependent)) {
5450b57cec5SDimitry Andric unsigned Opc;
5460b57cec5SDimitry Andric unsigned char TF = 0;
5470b57cec5SDimitry Andric if (Subtarget->isTargetMachO())
5480b57cec5SDimitry Andric TF = ARMII::MO_NONLAZY;
5490b57cec5SDimitry Andric
5500b57cec5SDimitry Andric if (IsPositionIndependent)
5510b57cec5SDimitry Andric Opc = isThumb2 ? ARM::t2MOV_ga_pcrel : ARM::MOV_ga_pcrel;
5520b57cec5SDimitry Andric else
5530b57cec5SDimitry Andric Opc = isThumb2 ? ARM::t2MOVi32imm : ARM::MOVi32imm;
554bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
5550b57cec5SDimitry Andric TII.get(Opc), DestReg).addGlobalAddress(GV, 0, TF));
5560b57cec5SDimitry Andric } else {
5570b57cec5SDimitry Andric // MachineConstantPool wants an explicit alignment.
5585ffd83dbSDimitry Andric Align Alignment = DL.getPrefTypeAlign(GV->getType());
5590b57cec5SDimitry Andric
5600b57cec5SDimitry Andric if (Subtarget->isTargetELF() && IsPositionIndependent)
5615ffd83dbSDimitry Andric return ARMLowerPICELF(GV, VT);
5620b57cec5SDimitry Andric
5630b57cec5SDimitry Andric // Grab index.
5640b57cec5SDimitry Andric unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
5650b57cec5SDimitry Andric unsigned Id = AFI->createPICLabelUId();
5660b57cec5SDimitry Andric ARMConstantPoolValue *CPV = ARMConstantPoolConstant::Create(GV, Id,
5670b57cec5SDimitry Andric ARMCP::CPValue,
5680b57cec5SDimitry Andric PCAdj);
5695ffd83dbSDimitry Andric unsigned Idx = MCP.getConstantPoolIndex(CPV, Alignment);
5700b57cec5SDimitry Andric
5710b57cec5SDimitry Andric // Load value.
5720b57cec5SDimitry Andric MachineInstrBuilder MIB;
5730b57cec5SDimitry Andric if (isThumb2) {
5740b57cec5SDimitry Andric unsigned Opc = IsPositionIndependent ? ARM::t2LDRpci_pic : ARM::t2LDRpci;
575bdd1243dSDimitry Andric MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc),
5760b57cec5SDimitry Andric DestReg).addConstantPoolIndex(Idx);
5770b57cec5SDimitry Andric if (IsPositionIndependent)
5780b57cec5SDimitry Andric MIB.addImm(Id);
5790b57cec5SDimitry Andric AddOptionalDefs(MIB);
5800b57cec5SDimitry Andric } else {
5810b57cec5SDimitry Andric // The extra immediate is for addrmode2.
5820b57cec5SDimitry Andric DestReg = constrainOperandRegClass(TII.get(ARM::LDRcp), DestReg, 0);
583bdd1243dSDimitry Andric MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
5840b57cec5SDimitry Andric TII.get(ARM::LDRcp), DestReg)
5850b57cec5SDimitry Andric .addConstantPoolIndex(Idx)
5860b57cec5SDimitry Andric .addImm(0);
5870b57cec5SDimitry Andric AddOptionalDefs(MIB);
5880b57cec5SDimitry Andric
5890b57cec5SDimitry Andric if (IsPositionIndependent) {
5900b57cec5SDimitry Andric unsigned Opc = IsIndirect ? ARM::PICLDR : ARM::PICADD;
59104eeddc0SDimitry Andric Register NewDestReg = createResultReg(TLI.getRegClassFor(VT));
5920b57cec5SDimitry Andric
5930b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
594bdd1243dSDimitry Andric MIMD, TII.get(Opc), NewDestReg)
5950b57cec5SDimitry Andric .addReg(DestReg)
5960b57cec5SDimitry Andric .addImm(Id);
5970b57cec5SDimitry Andric AddOptionalDefs(MIB);
5980b57cec5SDimitry Andric return NewDestReg;
5990b57cec5SDimitry Andric }
6000b57cec5SDimitry Andric }
6010b57cec5SDimitry Andric }
6020b57cec5SDimitry Andric
603e8d8bef9SDimitry Andric if ((Subtarget->isTargetELF() && Subtarget->isGVInGOT(GV)) ||
60481ad6265SDimitry Andric (Subtarget->isTargetMachO() && IsIndirect)) {
6050b57cec5SDimitry Andric MachineInstrBuilder MIB;
60604eeddc0SDimitry Andric Register NewDestReg = createResultReg(TLI.getRegClassFor(VT));
6070b57cec5SDimitry Andric if (isThumb2)
608bdd1243dSDimitry Andric MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
6090b57cec5SDimitry Andric TII.get(ARM::t2LDRi12), NewDestReg)
6100b57cec5SDimitry Andric .addReg(DestReg)
6110b57cec5SDimitry Andric .addImm(0);
6120b57cec5SDimitry Andric else
613bdd1243dSDimitry Andric MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
6140b57cec5SDimitry Andric TII.get(ARM::LDRi12), NewDestReg)
6150b57cec5SDimitry Andric .addReg(DestReg)
6160b57cec5SDimitry Andric .addImm(0);
6170b57cec5SDimitry Andric DestReg = NewDestReg;
6180b57cec5SDimitry Andric AddOptionalDefs(MIB);
6190b57cec5SDimitry Andric }
6200b57cec5SDimitry Andric
6210b57cec5SDimitry Andric return DestReg;
6220b57cec5SDimitry Andric }
6230b57cec5SDimitry Andric
fastMaterializeConstant(const Constant * C)6240b57cec5SDimitry Andric unsigned ARMFastISel::fastMaterializeConstant(const Constant *C) {
6250b57cec5SDimitry Andric EVT CEVT = TLI.getValueType(DL, C->getType(), true);
6260b57cec5SDimitry Andric
6270b57cec5SDimitry Andric // Only handle simple types.
6280b57cec5SDimitry Andric if (!CEVT.isSimple()) return 0;
6290b57cec5SDimitry Andric MVT VT = CEVT.getSimpleVT();
6300b57cec5SDimitry Andric
6310b57cec5SDimitry Andric if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
6320b57cec5SDimitry Andric return ARMMaterializeFP(CFP, VT);
6330b57cec5SDimitry Andric else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
6340b57cec5SDimitry Andric return ARMMaterializeGV(GV, VT);
6350b57cec5SDimitry Andric else if (isa<ConstantInt>(C))
6360b57cec5SDimitry Andric return ARMMaterializeInt(C, VT);
6370b57cec5SDimitry Andric
6380b57cec5SDimitry Andric return 0;
6390b57cec5SDimitry Andric }
6400b57cec5SDimitry Andric
6410b57cec5SDimitry Andric // TODO: unsigned ARMFastISel::TargetMaterializeFloatZero(const ConstantFP *CF);
6420b57cec5SDimitry Andric
fastMaterializeAlloca(const AllocaInst * AI)6430b57cec5SDimitry Andric unsigned ARMFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
6440b57cec5SDimitry Andric // Don't handle dynamic allocas.
6450b57cec5SDimitry Andric if (!FuncInfo.StaticAllocaMap.count(AI)) return 0;
6460b57cec5SDimitry Andric
6470b57cec5SDimitry Andric MVT VT;
6480b57cec5SDimitry Andric if (!isLoadTypeLegal(AI->getType(), VT)) return 0;
6490b57cec5SDimitry Andric
6500b57cec5SDimitry Andric DenseMap<const AllocaInst*, int>::iterator SI =
6510b57cec5SDimitry Andric FuncInfo.StaticAllocaMap.find(AI);
6520b57cec5SDimitry Andric
6530b57cec5SDimitry Andric // This will get lowered later into the correct offsets and registers
6540b57cec5SDimitry Andric // via rewriteXFrameIndex.
6550b57cec5SDimitry Andric if (SI != FuncInfo.StaticAllocaMap.end()) {
6560b57cec5SDimitry Andric unsigned Opc = isThumb2 ? ARM::t2ADDri : ARM::ADDri;
6570b57cec5SDimitry Andric const TargetRegisterClass* RC = TLI.getRegClassFor(VT);
65804eeddc0SDimitry Andric Register ResultReg = createResultReg(RC);
6590b57cec5SDimitry Andric ResultReg = constrainOperandRegClass(TII.get(Opc), ResultReg, 0);
6600b57cec5SDimitry Andric
661bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
6620b57cec5SDimitry Andric TII.get(Opc), ResultReg)
6630b57cec5SDimitry Andric .addFrameIndex(SI->second)
6640b57cec5SDimitry Andric .addImm(0));
6650b57cec5SDimitry Andric return ResultReg;
6660b57cec5SDimitry Andric }
6670b57cec5SDimitry Andric
6680b57cec5SDimitry Andric return 0;
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric
isTypeLegal(Type * Ty,MVT & VT)6710b57cec5SDimitry Andric bool ARMFastISel::isTypeLegal(Type *Ty, MVT &VT) {
6720b57cec5SDimitry Andric EVT evt = TLI.getValueType(DL, Ty, true);
6730b57cec5SDimitry Andric
6740b57cec5SDimitry Andric // Only handle simple types.
6750b57cec5SDimitry Andric if (evt == MVT::Other || !evt.isSimple()) return false;
6760b57cec5SDimitry Andric VT = evt.getSimpleVT();
6770b57cec5SDimitry Andric
6780b57cec5SDimitry Andric // Handle all legal types, i.e. a register that will directly hold this
6790b57cec5SDimitry Andric // value.
6800b57cec5SDimitry Andric return TLI.isTypeLegal(VT);
6810b57cec5SDimitry Andric }
6820b57cec5SDimitry Andric
isLoadTypeLegal(Type * Ty,MVT & VT)6830b57cec5SDimitry Andric bool ARMFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) {
6840b57cec5SDimitry Andric if (isTypeLegal(Ty, VT)) return true;
6850b57cec5SDimitry Andric
6860b57cec5SDimitry Andric // If this is a type than can be sign or zero-extended to a basic operation
6870b57cec5SDimitry Andric // go ahead and accept it now.
6880b57cec5SDimitry Andric if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)
6890b57cec5SDimitry Andric return true;
6900b57cec5SDimitry Andric
6910b57cec5SDimitry Andric return false;
6920b57cec5SDimitry Andric }
6930b57cec5SDimitry Andric
6940b57cec5SDimitry Andric // Computes the address to get to an object.
ARMComputeAddress(const Value * Obj,Address & Addr)6950b57cec5SDimitry Andric bool ARMFastISel::ARMComputeAddress(const Value *Obj, Address &Addr) {
6960b57cec5SDimitry Andric // Some boilerplate from the X86 FastISel.
6970b57cec5SDimitry Andric const User *U = nullptr;
6980b57cec5SDimitry Andric unsigned Opcode = Instruction::UserOp1;
6990b57cec5SDimitry Andric if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
7000b57cec5SDimitry Andric // Don't walk into other basic blocks unless the object is an alloca from
7010b57cec5SDimitry Andric // another block, otherwise it may not have a virtual register assigned.
7020b57cec5SDimitry Andric if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
7030b57cec5SDimitry Andric FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
7040b57cec5SDimitry Andric Opcode = I->getOpcode();
7050b57cec5SDimitry Andric U = I;
7060b57cec5SDimitry Andric }
7070b57cec5SDimitry Andric } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
7080b57cec5SDimitry Andric Opcode = C->getOpcode();
7090b57cec5SDimitry Andric U = C;
7100b57cec5SDimitry Andric }
7110b57cec5SDimitry Andric
7120b57cec5SDimitry Andric if (PointerType *Ty = dyn_cast<PointerType>(Obj->getType()))
7130b57cec5SDimitry Andric if (Ty->getAddressSpace() > 255)
7140b57cec5SDimitry Andric // Fast instruction selection doesn't support the special
7150b57cec5SDimitry Andric // address spaces.
7160b57cec5SDimitry Andric return false;
7170b57cec5SDimitry Andric
7180b57cec5SDimitry Andric switch (Opcode) {
7190b57cec5SDimitry Andric default:
7200b57cec5SDimitry Andric break;
7210b57cec5SDimitry Andric case Instruction::BitCast:
7220b57cec5SDimitry Andric // Look through bitcasts.
7230b57cec5SDimitry Andric return ARMComputeAddress(U->getOperand(0), Addr);
7240b57cec5SDimitry Andric case Instruction::IntToPtr:
7250b57cec5SDimitry Andric // Look past no-op inttoptrs.
7260b57cec5SDimitry Andric if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
7270b57cec5SDimitry Andric TLI.getPointerTy(DL))
7280b57cec5SDimitry Andric return ARMComputeAddress(U->getOperand(0), Addr);
7290b57cec5SDimitry Andric break;
7300b57cec5SDimitry Andric case Instruction::PtrToInt:
7310b57cec5SDimitry Andric // Look past no-op ptrtoints.
7320b57cec5SDimitry Andric if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
7330b57cec5SDimitry Andric return ARMComputeAddress(U->getOperand(0), Addr);
7340b57cec5SDimitry Andric break;
7350b57cec5SDimitry Andric case Instruction::GetElementPtr: {
7360b57cec5SDimitry Andric Address SavedAddr = Addr;
7370b57cec5SDimitry Andric int TmpOffset = Addr.Offset;
7380b57cec5SDimitry Andric
7390b57cec5SDimitry Andric // Iterate through the GEP folding the constants into offsets where
7400b57cec5SDimitry Andric // we can.
7410b57cec5SDimitry Andric gep_type_iterator GTI = gep_type_begin(U);
7420b57cec5SDimitry Andric for (User::const_op_iterator i = U->op_begin() + 1, e = U->op_end();
7430b57cec5SDimitry Andric i != e; ++i, ++GTI) {
7440b57cec5SDimitry Andric const Value *Op = *i;
7450b57cec5SDimitry Andric if (StructType *STy = GTI.getStructTypeOrNull()) {
7460b57cec5SDimitry Andric const StructLayout *SL = DL.getStructLayout(STy);
7470b57cec5SDimitry Andric unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
7480b57cec5SDimitry Andric TmpOffset += SL->getElementOffset(Idx);
7490b57cec5SDimitry Andric } else {
7501db9f3b2SDimitry Andric uint64_t S = GTI.getSequentialElementStride(DL);
7510b57cec5SDimitry Andric while (true) {
7520b57cec5SDimitry Andric if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
7530b57cec5SDimitry Andric // Constant-offset addressing.
7540b57cec5SDimitry Andric TmpOffset += CI->getSExtValue() * S;
7550b57cec5SDimitry Andric break;
7560b57cec5SDimitry Andric }
7570b57cec5SDimitry Andric if (canFoldAddIntoGEP(U, Op)) {
7580b57cec5SDimitry Andric // A compatible add with a constant operand. Fold the constant.
7590b57cec5SDimitry Andric ConstantInt *CI =
7600b57cec5SDimitry Andric cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
7610b57cec5SDimitry Andric TmpOffset += CI->getSExtValue() * S;
7620b57cec5SDimitry Andric // Iterate on the other operand.
7630b57cec5SDimitry Andric Op = cast<AddOperator>(Op)->getOperand(0);
7640b57cec5SDimitry Andric continue;
7650b57cec5SDimitry Andric }
7660b57cec5SDimitry Andric // Unsupported
7670b57cec5SDimitry Andric goto unsupported_gep;
7680b57cec5SDimitry Andric }
7690b57cec5SDimitry Andric }
7700b57cec5SDimitry Andric }
7710b57cec5SDimitry Andric
7720b57cec5SDimitry Andric // Try to grab the base operand now.
7730b57cec5SDimitry Andric Addr.Offset = TmpOffset;
7740b57cec5SDimitry Andric if (ARMComputeAddress(U->getOperand(0), Addr)) return true;
7750b57cec5SDimitry Andric
7760b57cec5SDimitry Andric // We failed, restore everything and try the other options.
7770b57cec5SDimitry Andric Addr = SavedAddr;
7780b57cec5SDimitry Andric
7790b57cec5SDimitry Andric unsupported_gep:
7800b57cec5SDimitry Andric break;
7810b57cec5SDimitry Andric }
7820b57cec5SDimitry Andric case Instruction::Alloca: {
7830b57cec5SDimitry Andric const AllocaInst *AI = cast<AllocaInst>(Obj);
7840b57cec5SDimitry Andric DenseMap<const AllocaInst*, int>::iterator SI =
7850b57cec5SDimitry Andric FuncInfo.StaticAllocaMap.find(AI);
7860b57cec5SDimitry Andric if (SI != FuncInfo.StaticAllocaMap.end()) {
7870b57cec5SDimitry Andric Addr.BaseType = Address::FrameIndexBase;
7880b57cec5SDimitry Andric Addr.Base.FI = SI->second;
7890b57cec5SDimitry Andric return true;
7900b57cec5SDimitry Andric }
7910b57cec5SDimitry Andric break;
7920b57cec5SDimitry Andric }
7930b57cec5SDimitry Andric }
7940b57cec5SDimitry Andric
7950b57cec5SDimitry Andric // Try to get this in a register if nothing else has worked.
7960b57cec5SDimitry Andric if (Addr.Base.Reg == 0) Addr.Base.Reg = getRegForValue(Obj);
7970b57cec5SDimitry Andric return Addr.Base.Reg != 0;
7980b57cec5SDimitry Andric }
7990b57cec5SDimitry Andric
ARMSimplifyAddress(Address & Addr,MVT VT,bool useAM3)8000b57cec5SDimitry Andric void ARMFastISel::ARMSimplifyAddress(Address &Addr, MVT VT, bool useAM3) {
8010b57cec5SDimitry Andric bool needsLowering = false;
8020b57cec5SDimitry Andric switch (VT.SimpleTy) {
8030b57cec5SDimitry Andric default: llvm_unreachable("Unhandled load/store type!");
8040b57cec5SDimitry Andric case MVT::i1:
8050b57cec5SDimitry Andric case MVT::i8:
8060b57cec5SDimitry Andric case MVT::i16:
8070b57cec5SDimitry Andric case MVT::i32:
8080b57cec5SDimitry Andric if (!useAM3) {
8090b57cec5SDimitry Andric // Integer loads/stores handle 12-bit offsets.
8100b57cec5SDimitry Andric needsLowering = ((Addr.Offset & 0xfff) != Addr.Offset);
8110b57cec5SDimitry Andric // Handle negative offsets.
8120b57cec5SDimitry Andric if (needsLowering && isThumb2)
8130b57cec5SDimitry Andric needsLowering = !(Subtarget->hasV6T2Ops() && Addr.Offset < 0 &&
8140b57cec5SDimitry Andric Addr.Offset > -256);
8150b57cec5SDimitry Andric } else {
8160b57cec5SDimitry Andric // ARM halfword load/stores and signed byte loads use +/-imm8 offsets.
8170b57cec5SDimitry Andric needsLowering = (Addr.Offset > 255 || Addr.Offset < -255);
8180b57cec5SDimitry Andric }
8190b57cec5SDimitry Andric break;
8200b57cec5SDimitry Andric case MVT::f32:
8210b57cec5SDimitry Andric case MVT::f64:
8220b57cec5SDimitry Andric // Floating point operands handle 8-bit offsets.
8230b57cec5SDimitry Andric needsLowering = ((Addr.Offset & 0xff) != Addr.Offset);
8240b57cec5SDimitry Andric break;
8250b57cec5SDimitry Andric }
8260b57cec5SDimitry Andric
8270b57cec5SDimitry Andric // If this is a stack pointer and the offset needs to be simplified then
8280b57cec5SDimitry Andric // put the alloca address into a register, set the base type back to
8290b57cec5SDimitry Andric // register and continue. This should almost never happen.
8300b57cec5SDimitry Andric if (needsLowering && Addr.BaseType == Address::FrameIndexBase) {
8310b57cec5SDimitry Andric const TargetRegisterClass *RC = isThumb2 ? &ARM::tGPRRegClass
8320b57cec5SDimitry Andric : &ARM::GPRRegClass;
83304eeddc0SDimitry Andric Register ResultReg = createResultReg(RC);
8340b57cec5SDimitry Andric unsigned Opc = isThumb2 ? ARM::t2ADDri : ARM::ADDri;
835bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
8360b57cec5SDimitry Andric TII.get(Opc), ResultReg)
8370b57cec5SDimitry Andric .addFrameIndex(Addr.Base.FI)
8380b57cec5SDimitry Andric .addImm(0));
8390b57cec5SDimitry Andric Addr.Base.Reg = ResultReg;
8400b57cec5SDimitry Andric Addr.BaseType = Address::RegBase;
8410b57cec5SDimitry Andric }
8420b57cec5SDimitry Andric
8430b57cec5SDimitry Andric // Since the offset is too large for the load/store instruction
8440b57cec5SDimitry Andric // get the reg+offset into a register.
8450b57cec5SDimitry Andric if (needsLowering) {
8460b57cec5SDimitry Andric Addr.Base.Reg = fastEmit_ri_(MVT::i32, ISD::ADD, Addr.Base.Reg,
847fe6060f1SDimitry Andric Addr.Offset, MVT::i32);
8480b57cec5SDimitry Andric Addr.Offset = 0;
8490b57cec5SDimitry Andric }
8500b57cec5SDimitry Andric }
8510b57cec5SDimitry Andric
AddLoadStoreOperands(MVT VT,Address & Addr,const MachineInstrBuilder & MIB,MachineMemOperand::Flags Flags,bool useAM3)8520b57cec5SDimitry Andric void ARMFastISel::AddLoadStoreOperands(MVT VT, Address &Addr,
8530b57cec5SDimitry Andric const MachineInstrBuilder &MIB,
8540b57cec5SDimitry Andric MachineMemOperand::Flags Flags,
8550b57cec5SDimitry Andric bool useAM3) {
8560b57cec5SDimitry Andric // addrmode5 output depends on the selection dag addressing dividing the
8570b57cec5SDimitry Andric // offset by 4 that it then later multiplies. Do this here as well.
8580b57cec5SDimitry Andric if (VT.SimpleTy == MVT::f32 || VT.SimpleTy == MVT::f64)
8590b57cec5SDimitry Andric Addr.Offset /= 4;
8600b57cec5SDimitry Andric
8610b57cec5SDimitry Andric // Frame base works a bit differently. Handle it separately.
8620b57cec5SDimitry Andric if (Addr.BaseType == Address::FrameIndexBase) {
8630b57cec5SDimitry Andric int FI = Addr.Base.FI;
8640b57cec5SDimitry Andric int Offset = Addr.Offset;
8650b57cec5SDimitry Andric MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
8660b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(*FuncInfo.MF, FI, Offset), Flags,
8675ffd83dbSDimitry Andric MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
8680b57cec5SDimitry Andric // Now add the rest of the operands.
8690b57cec5SDimitry Andric MIB.addFrameIndex(FI);
8700b57cec5SDimitry Andric
8710b57cec5SDimitry Andric // ARM halfword load/stores and signed byte loads need an additional
8720b57cec5SDimitry Andric // operand.
8730b57cec5SDimitry Andric if (useAM3) {
8740b57cec5SDimitry Andric int Imm = (Addr.Offset < 0) ? (0x100 | -Addr.Offset) : Addr.Offset;
8750b57cec5SDimitry Andric MIB.addReg(0);
8760b57cec5SDimitry Andric MIB.addImm(Imm);
8770b57cec5SDimitry Andric } else {
8780b57cec5SDimitry Andric MIB.addImm(Addr.Offset);
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric MIB.addMemOperand(MMO);
8810b57cec5SDimitry Andric } else {
8820b57cec5SDimitry Andric // Now add the rest of the operands.
8830b57cec5SDimitry Andric MIB.addReg(Addr.Base.Reg);
8840b57cec5SDimitry Andric
8850b57cec5SDimitry Andric // ARM halfword load/stores and signed byte loads need an additional
8860b57cec5SDimitry Andric // operand.
8870b57cec5SDimitry Andric if (useAM3) {
8880b57cec5SDimitry Andric int Imm = (Addr.Offset < 0) ? (0x100 | -Addr.Offset) : Addr.Offset;
8890b57cec5SDimitry Andric MIB.addReg(0);
8900b57cec5SDimitry Andric MIB.addImm(Imm);
8910b57cec5SDimitry Andric } else {
8920b57cec5SDimitry Andric MIB.addImm(Addr.Offset);
8930b57cec5SDimitry Andric }
8940b57cec5SDimitry Andric }
8950b57cec5SDimitry Andric AddOptionalDefs(MIB);
8960b57cec5SDimitry Andric }
8970b57cec5SDimitry Andric
ARMEmitLoad(MVT VT,Register & ResultReg,Address & Addr,MaybeAlign Alignment,bool isZExt,bool allocReg)8988bcb0991SDimitry Andric bool ARMFastISel::ARMEmitLoad(MVT VT, Register &ResultReg, Address &Addr,
89981ad6265SDimitry Andric MaybeAlign Alignment, bool isZExt,
90081ad6265SDimitry Andric bool allocReg) {
9010b57cec5SDimitry Andric unsigned Opc;
9020b57cec5SDimitry Andric bool useAM3 = false;
9030b57cec5SDimitry Andric bool needVMOV = false;
9040b57cec5SDimitry Andric const TargetRegisterClass *RC;
9050b57cec5SDimitry Andric switch (VT.SimpleTy) {
9060b57cec5SDimitry Andric // This is mostly going to be Neon/vector support.
9070b57cec5SDimitry Andric default: return false;
9080b57cec5SDimitry Andric case MVT::i1:
9090b57cec5SDimitry Andric case MVT::i8:
9100b57cec5SDimitry Andric if (isThumb2) {
9110b57cec5SDimitry Andric if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
9120b57cec5SDimitry Andric Opc = isZExt ? ARM::t2LDRBi8 : ARM::t2LDRSBi8;
9130b57cec5SDimitry Andric else
9140b57cec5SDimitry Andric Opc = isZExt ? ARM::t2LDRBi12 : ARM::t2LDRSBi12;
9150b57cec5SDimitry Andric } else {
9160b57cec5SDimitry Andric if (isZExt) {
9170b57cec5SDimitry Andric Opc = ARM::LDRBi12;
9180b57cec5SDimitry Andric } else {
9190b57cec5SDimitry Andric Opc = ARM::LDRSB;
9200b57cec5SDimitry Andric useAM3 = true;
9210b57cec5SDimitry Andric }
9220b57cec5SDimitry Andric }
9230b57cec5SDimitry Andric RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRnopcRegClass;
9240b57cec5SDimitry Andric break;
9250b57cec5SDimitry Andric case MVT::i16:
92681ad6265SDimitry Andric if (Alignment && *Alignment < Align(2) &&
92781ad6265SDimitry Andric !Subtarget->allowsUnalignedMem())
9280b57cec5SDimitry Andric return false;
9290b57cec5SDimitry Andric
9300b57cec5SDimitry Andric if (isThumb2) {
9310b57cec5SDimitry Andric if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
9320b57cec5SDimitry Andric Opc = isZExt ? ARM::t2LDRHi8 : ARM::t2LDRSHi8;
9330b57cec5SDimitry Andric else
9340b57cec5SDimitry Andric Opc = isZExt ? ARM::t2LDRHi12 : ARM::t2LDRSHi12;
9350b57cec5SDimitry Andric } else {
9360b57cec5SDimitry Andric Opc = isZExt ? ARM::LDRH : ARM::LDRSH;
9370b57cec5SDimitry Andric useAM3 = true;
9380b57cec5SDimitry Andric }
9390b57cec5SDimitry Andric RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRnopcRegClass;
9400b57cec5SDimitry Andric break;
9410b57cec5SDimitry Andric case MVT::i32:
94281ad6265SDimitry Andric if (Alignment && *Alignment < Align(4) &&
94381ad6265SDimitry Andric !Subtarget->allowsUnalignedMem())
9440b57cec5SDimitry Andric return false;
9450b57cec5SDimitry Andric
9460b57cec5SDimitry Andric if (isThumb2) {
9470b57cec5SDimitry Andric if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
9480b57cec5SDimitry Andric Opc = ARM::t2LDRi8;
9490b57cec5SDimitry Andric else
9500b57cec5SDimitry Andric Opc = ARM::t2LDRi12;
9510b57cec5SDimitry Andric } else {
9520b57cec5SDimitry Andric Opc = ARM::LDRi12;
9530b57cec5SDimitry Andric }
9540b57cec5SDimitry Andric RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRnopcRegClass;
9550b57cec5SDimitry Andric break;
9560b57cec5SDimitry Andric case MVT::f32:
9570b57cec5SDimitry Andric if (!Subtarget->hasVFP2Base()) return false;
9580b57cec5SDimitry Andric // Unaligned loads need special handling. Floats require word-alignment.
95981ad6265SDimitry Andric if (Alignment && *Alignment < Align(4)) {
9600b57cec5SDimitry Andric needVMOV = true;
9610b57cec5SDimitry Andric VT = MVT::i32;
9620b57cec5SDimitry Andric Opc = isThumb2 ? ARM::t2LDRi12 : ARM::LDRi12;
9630b57cec5SDimitry Andric RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRnopcRegClass;
9640b57cec5SDimitry Andric } else {
9650b57cec5SDimitry Andric Opc = ARM::VLDRS;
9660b57cec5SDimitry Andric RC = TLI.getRegClassFor(VT);
9670b57cec5SDimitry Andric }
9680b57cec5SDimitry Andric break;
9690b57cec5SDimitry Andric case MVT::f64:
9700b57cec5SDimitry Andric // Can load and store double precision even without FeatureFP64
9710b57cec5SDimitry Andric if (!Subtarget->hasVFP2Base()) return false;
9720b57cec5SDimitry Andric // FIXME: Unaligned loads need special handling. Doublewords require
9730b57cec5SDimitry Andric // word-alignment.
97481ad6265SDimitry Andric if (Alignment && *Alignment < Align(4))
9750b57cec5SDimitry Andric return false;
9760b57cec5SDimitry Andric
9770b57cec5SDimitry Andric Opc = ARM::VLDRD;
9780b57cec5SDimitry Andric RC = TLI.getRegClassFor(VT);
9790b57cec5SDimitry Andric break;
9800b57cec5SDimitry Andric }
9810b57cec5SDimitry Andric // Simplify this down to something we can handle.
9820b57cec5SDimitry Andric ARMSimplifyAddress(Addr, VT, useAM3);
9830b57cec5SDimitry Andric
9840b57cec5SDimitry Andric // Create the base instruction, then add the operands.
9850b57cec5SDimitry Andric if (allocReg)
9860b57cec5SDimitry Andric ResultReg = createResultReg(RC);
9870b57cec5SDimitry Andric assert(ResultReg > 255 && "Expected an allocated virtual register.");
988bdd1243dSDimitry Andric MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
9890b57cec5SDimitry Andric TII.get(Opc), ResultReg);
9900b57cec5SDimitry Andric AddLoadStoreOperands(VT, Addr, MIB, MachineMemOperand::MOLoad, useAM3);
9910b57cec5SDimitry Andric
9920b57cec5SDimitry Andric // If we had an unaligned load of a float we've converted it to an regular
9930b57cec5SDimitry Andric // load. Now we must move from the GRP to the FP register.
9940b57cec5SDimitry Andric if (needVMOV) {
99504eeddc0SDimitry Andric Register MoveReg = createResultReg(TLI.getRegClassFor(MVT::f32));
996bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
9970b57cec5SDimitry Andric TII.get(ARM::VMOVSR), MoveReg)
9980b57cec5SDimitry Andric .addReg(ResultReg));
9990b57cec5SDimitry Andric ResultReg = MoveReg;
10000b57cec5SDimitry Andric }
10010b57cec5SDimitry Andric return true;
10020b57cec5SDimitry Andric }
10030b57cec5SDimitry Andric
SelectLoad(const Instruction * I)10040b57cec5SDimitry Andric bool ARMFastISel::SelectLoad(const Instruction *I) {
10050b57cec5SDimitry Andric // Atomic loads need special handling.
10060b57cec5SDimitry Andric if (cast<LoadInst>(I)->isAtomic())
10070b57cec5SDimitry Andric return false;
10080b57cec5SDimitry Andric
10090b57cec5SDimitry Andric const Value *SV = I->getOperand(0);
10100b57cec5SDimitry Andric if (TLI.supportSwiftError()) {
10110b57cec5SDimitry Andric // Swifterror values can come from either a function parameter with
10120b57cec5SDimitry Andric // swifterror attribute or an alloca with swifterror attribute.
10130b57cec5SDimitry Andric if (const Argument *Arg = dyn_cast<Argument>(SV)) {
10140b57cec5SDimitry Andric if (Arg->hasSwiftErrorAttr())
10150b57cec5SDimitry Andric return false;
10160b57cec5SDimitry Andric }
10170b57cec5SDimitry Andric
10180b57cec5SDimitry Andric if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(SV)) {
10190b57cec5SDimitry Andric if (Alloca->isSwiftError())
10200b57cec5SDimitry Andric return false;
10210b57cec5SDimitry Andric }
10220b57cec5SDimitry Andric }
10230b57cec5SDimitry Andric
10240b57cec5SDimitry Andric // Verify we have a legal type before going any further.
10250b57cec5SDimitry Andric MVT VT;
10260b57cec5SDimitry Andric if (!isLoadTypeLegal(I->getType(), VT))
10270b57cec5SDimitry Andric return false;
10280b57cec5SDimitry Andric
10290b57cec5SDimitry Andric // See if we can handle this address.
10300b57cec5SDimitry Andric Address Addr;
10310b57cec5SDimitry Andric if (!ARMComputeAddress(I->getOperand(0), Addr)) return false;
10320b57cec5SDimitry Andric
10338bcb0991SDimitry Andric Register ResultReg;
103481ad6265SDimitry Andric if (!ARMEmitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlign()))
10350b57cec5SDimitry Andric return false;
10360b57cec5SDimitry Andric updateValueMap(I, ResultReg);
10370b57cec5SDimitry Andric return true;
10380b57cec5SDimitry Andric }
10390b57cec5SDimitry Andric
ARMEmitStore(MVT VT,unsigned SrcReg,Address & Addr,MaybeAlign Alignment)10400b57cec5SDimitry Andric bool ARMFastISel::ARMEmitStore(MVT VT, unsigned SrcReg, Address &Addr,
104181ad6265SDimitry Andric MaybeAlign Alignment) {
10420b57cec5SDimitry Andric unsigned StrOpc;
10430b57cec5SDimitry Andric bool useAM3 = false;
10440b57cec5SDimitry Andric switch (VT.SimpleTy) {
10450b57cec5SDimitry Andric // This is mostly going to be Neon/vector support.
10460b57cec5SDimitry Andric default: return false;
10470b57cec5SDimitry Andric case MVT::i1: {
104804eeddc0SDimitry Andric Register Res = createResultReg(isThumb2 ? &ARM::tGPRRegClass
10490b57cec5SDimitry Andric : &ARM::GPRRegClass);
10500b57cec5SDimitry Andric unsigned Opc = isThumb2 ? ARM::t2ANDri : ARM::ANDri;
10510b57cec5SDimitry Andric SrcReg = constrainOperandRegClass(TII.get(Opc), SrcReg, 1);
1052bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
10530b57cec5SDimitry Andric TII.get(Opc), Res)
10540b57cec5SDimitry Andric .addReg(SrcReg).addImm(1));
10550b57cec5SDimitry Andric SrcReg = Res;
1056bdd1243dSDimitry Andric [[fallthrough]];
10570b57cec5SDimitry Andric }
10580b57cec5SDimitry Andric case MVT::i8:
10590b57cec5SDimitry Andric if (isThumb2) {
10600b57cec5SDimitry Andric if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
10610b57cec5SDimitry Andric StrOpc = ARM::t2STRBi8;
10620b57cec5SDimitry Andric else
10630b57cec5SDimitry Andric StrOpc = ARM::t2STRBi12;
10640b57cec5SDimitry Andric } else {
10650b57cec5SDimitry Andric StrOpc = ARM::STRBi12;
10660b57cec5SDimitry Andric }
10670b57cec5SDimitry Andric break;
10680b57cec5SDimitry Andric case MVT::i16:
106981ad6265SDimitry Andric if (Alignment && *Alignment < Align(2) &&
107081ad6265SDimitry Andric !Subtarget->allowsUnalignedMem())
10710b57cec5SDimitry Andric return false;
10720b57cec5SDimitry Andric
10730b57cec5SDimitry Andric if (isThumb2) {
10740b57cec5SDimitry Andric if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
10750b57cec5SDimitry Andric StrOpc = ARM::t2STRHi8;
10760b57cec5SDimitry Andric else
10770b57cec5SDimitry Andric StrOpc = ARM::t2STRHi12;
10780b57cec5SDimitry Andric } else {
10790b57cec5SDimitry Andric StrOpc = ARM::STRH;
10800b57cec5SDimitry Andric useAM3 = true;
10810b57cec5SDimitry Andric }
10820b57cec5SDimitry Andric break;
10830b57cec5SDimitry Andric case MVT::i32:
108481ad6265SDimitry Andric if (Alignment && *Alignment < Align(4) &&
108581ad6265SDimitry Andric !Subtarget->allowsUnalignedMem())
10860b57cec5SDimitry Andric return false;
10870b57cec5SDimitry Andric
10880b57cec5SDimitry Andric if (isThumb2) {
10890b57cec5SDimitry Andric if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
10900b57cec5SDimitry Andric StrOpc = ARM::t2STRi8;
10910b57cec5SDimitry Andric else
10920b57cec5SDimitry Andric StrOpc = ARM::t2STRi12;
10930b57cec5SDimitry Andric } else {
10940b57cec5SDimitry Andric StrOpc = ARM::STRi12;
10950b57cec5SDimitry Andric }
10960b57cec5SDimitry Andric break;
10970b57cec5SDimitry Andric case MVT::f32:
10980b57cec5SDimitry Andric if (!Subtarget->hasVFP2Base()) return false;
10990b57cec5SDimitry Andric // Unaligned stores need special handling. Floats require word-alignment.
110081ad6265SDimitry Andric if (Alignment && *Alignment < Align(4)) {
110104eeddc0SDimitry Andric Register MoveReg = createResultReg(TLI.getRegClassFor(MVT::i32));
1102bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
11030b57cec5SDimitry Andric TII.get(ARM::VMOVRS), MoveReg)
11040b57cec5SDimitry Andric .addReg(SrcReg));
11050b57cec5SDimitry Andric SrcReg = MoveReg;
11060b57cec5SDimitry Andric VT = MVT::i32;
11070b57cec5SDimitry Andric StrOpc = isThumb2 ? ARM::t2STRi12 : ARM::STRi12;
11080b57cec5SDimitry Andric } else {
11090b57cec5SDimitry Andric StrOpc = ARM::VSTRS;
11100b57cec5SDimitry Andric }
11110b57cec5SDimitry Andric break;
11120b57cec5SDimitry Andric case MVT::f64:
11130b57cec5SDimitry Andric // Can load and store double precision even without FeatureFP64
11140b57cec5SDimitry Andric if (!Subtarget->hasVFP2Base()) return false;
11150b57cec5SDimitry Andric // FIXME: Unaligned stores need special handling. Doublewords require
11160b57cec5SDimitry Andric // word-alignment.
111781ad6265SDimitry Andric if (Alignment && *Alignment < Align(4))
11180b57cec5SDimitry Andric return false;
11190b57cec5SDimitry Andric
11200b57cec5SDimitry Andric StrOpc = ARM::VSTRD;
11210b57cec5SDimitry Andric break;
11220b57cec5SDimitry Andric }
11230b57cec5SDimitry Andric // Simplify this down to something we can handle.
11240b57cec5SDimitry Andric ARMSimplifyAddress(Addr, VT, useAM3);
11250b57cec5SDimitry Andric
11260b57cec5SDimitry Andric // Create the base instruction, then add the operands.
11270b57cec5SDimitry Andric SrcReg = constrainOperandRegClass(TII.get(StrOpc), SrcReg, 0);
1128bdd1243dSDimitry Andric MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
11290b57cec5SDimitry Andric TII.get(StrOpc))
11300b57cec5SDimitry Andric .addReg(SrcReg);
11310b57cec5SDimitry Andric AddLoadStoreOperands(VT, Addr, MIB, MachineMemOperand::MOStore, useAM3);
11320b57cec5SDimitry Andric return true;
11330b57cec5SDimitry Andric }
11340b57cec5SDimitry Andric
SelectStore(const Instruction * I)11350b57cec5SDimitry Andric bool ARMFastISel::SelectStore(const Instruction *I) {
11360b57cec5SDimitry Andric Value *Op0 = I->getOperand(0);
11370b57cec5SDimitry Andric unsigned SrcReg = 0;
11380b57cec5SDimitry Andric
11390b57cec5SDimitry Andric // Atomic stores need special handling.
11400b57cec5SDimitry Andric if (cast<StoreInst>(I)->isAtomic())
11410b57cec5SDimitry Andric return false;
11420b57cec5SDimitry Andric
11430b57cec5SDimitry Andric const Value *PtrV = I->getOperand(1);
11440b57cec5SDimitry Andric if (TLI.supportSwiftError()) {
11450b57cec5SDimitry Andric // Swifterror values can come from either a function parameter with
11460b57cec5SDimitry Andric // swifterror attribute or an alloca with swifterror attribute.
11470b57cec5SDimitry Andric if (const Argument *Arg = dyn_cast<Argument>(PtrV)) {
11480b57cec5SDimitry Andric if (Arg->hasSwiftErrorAttr())
11490b57cec5SDimitry Andric return false;
11500b57cec5SDimitry Andric }
11510b57cec5SDimitry Andric
11520b57cec5SDimitry Andric if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(PtrV)) {
11530b57cec5SDimitry Andric if (Alloca->isSwiftError())
11540b57cec5SDimitry Andric return false;
11550b57cec5SDimitry Andric }
11560b57cec5SDimitry Andric }
11570b57cec5SDimitry Andric
11580b57cec5SDimitry Andric // Verify we have a legal type before going any further.
11590b57cec5SDimitry Andric MVT VT;
11600b57cec5SDimitry Andric if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT))
11610b57cec5SDimitry Andric return false;
11620b57cec5SDimitry Andric
11630b57cec5SDimitry Andric // Get the value to be stored into a register.
11640b57cec5SDimitry Andric SrcReg = getRegForValue(Op0);
11650b57cec5SDimitry Andric if (SrcReg == 0) return false;
11660b57cec5SDimitry Andric
11670b57cec5SDimitry Andric // See if we can handle this address.
11680b57cec5SDimitry Andric Address Addr;
11690b57cec5SDimitry Andric if (!ARMComputeAddress(I->getOperand(1), Addr))
11700b57cec5SDimitry Andric return false;
11710b57cec5SDimitry Andric
117281ad6265SDimitry Andric if (!ARMEmitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlign()))
11730b57cec5SDimitry Andric return false;
11740b57cec5SDimitry Andric return true;
11750b57cec5SDimitry Andric }
11760b57cec5SDimitry Andric
getComparePred(CmpInst::Predicate Pred)11770b57cec5SDimitry Andric static ARMCC::CondCodes getComparePred(CmpInst::Predicate Pred) {
11780b57cec5SDimitry Andric switch (Pred) {
11790b57cec5SDimitry Andric // Needs two compares...
11800b57cec5SDimitry Andric case CmpInst::FCMP_ONE:
11810b57cec5SDimitry Andric case CmpInst::FCMP_UEQ:
11820b57cec5SDimitry Andric default:
11830b57cec5SDimitry Andric // AL is our "false" for now. The other two need more compares.
11840b57cec5SDimitry Andric return ARMCC::AL;
11850b57cec5SDimitry Andric case CmpInst::ICMP_EQ:
11860b57cec5SDimitry Andric case CmpInst::FCMP_OEQ:
11870b57cec5SDimitry Andric return ARMCC::EQ;
11880b57cec5SDimitry Andric case CmpInst::ICMP_SGT:
11890b57cec5SDimitry Andric case CmpInst::FCMP_OGT:
11900b57cec5SDimitry Andric return ARMCC::GT;
11910b57cec5SDimitry Andric case CmpInst::ICMP_SGE:
11920b57cec5SDimitry Andric case CmpInst::FCMP_OGE:
11930b57cec5SDimitry Andric return ARMCC::GE;
11940b57cec5SDimitry Andric case CmpInst::ICMP_UGT:
11950b57cec5SDimitry Andric case CmpInst::FCMP_UGT:
11960b57cec5SDimitry Andric return ARMCC::HI;
11970b57cec5SDimitry Andric case CmpInst::FCMP_OLT:
11980b57cec5SDimitry Andric return ARMCC::MI;
11990b57cec5SDimitry Andric case CmpInst::ICMP_ULE:
12000b57cec5SDimitry Andric case CmpInst::FCMP_OLE:
12010b57cec5SDimitry Andric return ARMCC::LS;
12020b57cec5SDimitry Andric case CmpInst::FCMP_ORD:
12030b57cec5SDimitry Andric return ARMCC::VC;
12040b57cec5SDimitry Andric case CmpInst::FCMP_UNO:
12050b57cec5SDimitry Andric return ARMCC::VS;
12060b57cec5SDimitry Andric case CmpInst::FCMP_UGE:
12070b57cec5SDimitry Andric return ARMCC::PL;
12080b57cec5SDimitry Andric case CmpInst::ICMP_SLT:
12090b57cec5SDimitry Andric case CmpInst::FCMP_ULT:
12100b57cec5SDimitry Andric return ARMCC::LT;
12110b57cec5SDimitry Andric case CmpInst::ICMP_SLE:
12120b57cec5SDimitry Andric case CmpInst::FCMP_ULE:
12130b57cec5SDimitry Andric return ARMCC::LE;
12140b57cec5SDimitry Andric case CmpInst::FCMP_UNE:
12150b57cec5SDimitry Andric case CmpInst::ICMP_NE:
12160b57cec5SDimitry Andric return ARMCC::NE;
12170b57cec5SDimitry Andric case CmpInst::ICMP_UGE:
12180b57cec5SDimitry Andric return ARMCC::HS;
12190b57cec5SDimitry Andric case CmpInst::ICMP_ULT:
12200b57cec5SDimitry Andric return ARMCC::LO;
12210b57cec5SDimitry Andric }
12220b57cec5SDimitry Andric }
12230b57cec5SDimitry Andric
SelectBranch(const Instruction * I)12240b57cec5SDimitry Andric bool ARMFastISel::SelectBranch(const Instruction *I) {
12250b57cec5SDimitry Andric const BranchInst *BI = cast<BranchInst>(I);
12260b57cec5SDimitry Andric MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)];
12270b57cec5SDimitry Andric MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];
12280b57cec5SDimitry Andric
12290b57cec5SDimitry Andric // Simple branch support.
12300b57cec5SDimitry Andric
12310b57cec5SDimitry Andric // If we can, avoid recomputing the compare - redoing it could lead to wonky
12320b57cec5SDimitry Andric // behavior.
12330b57cec5SDimitry Andric if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) {
12340b57cec5SDimitry Andric if (CI->hasOneUse() && (CI->getParent() == I->getParent())) {
12350b57cec5SDimitry Andric // Get the compare predicate.
12360b57cec5SDimitry Andric // Try to take advantage of fallthrough opportunities.
12370b57cec5SDimitry Andric CmpInst::Predicate Predicate = CI->getPredicate();
12380b57cec5SDimitry Andric if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
12390b57cec5SDimitry Andric std::swap(TBB, FBB);
12400b57cec5SDimitry Andric Predicate = CmpInst::getInversePredicate(Predicate);
12410b57cec5SDimitry Andric }
12420b57cec5SDimitry Andric
12430b57cec5SDimitry Andric ARMCC::CondCodes ARMPred = getComparePred(Predicate);
12440b57cec5SDimitry Andric
12450b57cec5SDimitry Andric // We may not handle every CC for now.
12460b57cec5SDimitry Andric if (ARMPred == ARMCC::AL) return false;
12470b57cec5SDimitry Andric
12480b57cec5SDimitry Andric // Emit the compare.
12498bcb0991SDimitry Andric if (!ARMEmitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned()))
12500b57cec5SDimitry Andric return false;
12510b57cec5SDimitry Andric
12520b57cec5SDimitry Andric unsigned BrOpc = isThumb2 ? ARM::t2Bcc : ARM::Bcc;
1253bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(BrOpc))
12540b57cec5SDimitry Andric .addMBB(TBB).addImm(ARMPred).addReg(ARM::CPSR);
12550b57cec5SDimitry Andric finishCondBranch(BI->getParent(), TBB, FBB);
12560b57cec5SDimitry Andric return true;
12570b57cec5SDimitry Andric }
12580b57cec5SDimitry Andric } else if (TruncInst *TI = dyn_cast<TruncInst>(BI->getCondition())) {
12590b57cec5SDimitry Andric MVT SourceVT;
12600b57cec5SDimitry Andric if (TI->hasOneUse() && TI->getParent() == I->getParent() &&
12610b57cec5SDimitry Andric (isLoadTypeLegal(TI->getOperand(0)->getType(), SourceVT))) {
12620b57cec5SDimitry Andric unsigned TstOpc = isThumb2 ? ARM::t2TSTri : ARM::TSTri;
126304eeddc0SDimitry Andric Register OpReg = getRegForValue(TI->getOperand(0));
12640b57cec5SDimitry Andric OpReg = constrainOperandRegClass(TII.get(TstOpc), OpReg, 0);
1265bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
12660b57cec5SDimitry Andric TII.get(TstOpc))
12670b57cec5SDimitry Andric .addReg(OpReg).addImm(1));
12680b57cec5SDimitry Andric
12690b57cec5SDimitry Andric unsigned CCMode = ARMCC::NE;
12700b57cec5SDimitry Andric if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
12710b57cec5SDimitry Andric std::swap(TBB, FBB);
12720b57cec5SDimitry Andric CCMode = ARMCC::EQ;
12730b57cec5SDimitry Andric }
12740b57cec5SDimitry Andric
12750b57cec5SDimitry Andric unsigned BrOpc = isThumb2 ? ARM::t2Bcc : ARM::Bcc;
1276bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(BrOpc))
12770b57cec5SDimitry Andric .addMBB(TBB).addImm(CCMode).addReg(ARM::CPSR);
12780b57cec5SDimitry Andric
12790b57cec5SDimitry Andric finishCondBranch(BI->getParent(), TBB, FBB);
12800b57cec5SDimitry Andric return true;
12810b57cec5SDimitry Andric }
12820b57cec5SDimitry Andric } else if (const ConstantInt *CI =
12830b57cec5SDimitry Andric dyn_cast<ConstantInt>(BI->getCondition())) {
12840b57cec5SDimitry Andric uint64_t Imm = CI->getZExtValue();
12850b57cec5SDimitry Andric MachineBasicBlock *Target = (Imm == 0) ? FBB : TBB;
1286bdd1243dSDimitry Andric fastEmitBranch(Target, MIMD.getDL());
12870b57cec5SDimitry Andric return true;
12880b57cec5SDimitry Andric }
12890b57cec5SDimitry Andric
129004eeddc0SDimitry Andric Register CmpReg = getRegForValue(BI->getCondition());
12910b57cec5SDimitry Andric if (CmpReg == 0) return false;
12920b57cec5SDimitry Andric
12930b57cec5SDimitry Andric // We've been divorced from our compare! Our block was split, and
12940b57cec5SDimitry Andric // now our compare lives in a predecessor block. We musn't
12950b57cec5SDimitry Andric // re-compare here, as the children of the compare aren't guaranteed
12960b57cec5SDimitry Andric // live across the block boundary (we *could* check for this).
12970b57cec5SDimitry Andric // Regardless, the compare has been done in the predecessor block,
12980b57cec5SDimitry Andric // and it left a value for us in a virtual register. Ergo, we test
12990b57cec5SDimitry Andric // the one-bit value left in the virtual register.
13000b57cec5SDimitry Andric unsigned TstOpc = isThumb2 ? ARM::t2TSTri : ARM::TSTri;
13010b57cec5SDimitry Andric CmpReg = constrainOperandRegClass(TII.get(TstOpc), CmpReg, 0);
13020b57cec5SDimitry Andric AddOptionalDefs(
1303bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(TstOpc))
13040b57cec5SDimitry Andric .addReg(CmpReg)
13050b57cec5SDimitry Andric .addImm(1));
13060b57cec5SDimitry Andric
13070b57cec5SDimitry Andric unsigned CCMode = ARMCC::NE;
13080b57cec5SDimitry Andric if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
13090b57cec5SDimitry Andric std::swap(TBB, FBB);
13100b57cec5SDimitry Andric CCMode = ARMCC::EQ;
13110b57cec5SDimitry Andric }
13120b57cec5SDimitry Andric
13130b57cec5SDimitry Andric unsigned BrOpc = isThumb2 ? ARM::t2Bcc : ARM::Bcc;
1314bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(BrOpc))
13150b57cec5SDimitry Andric .addMBB(TBB).addImm(CCMode).addReg(ARM::CPSR);
13160b57cec5SDimitry Andric finishCondBranch(BI->getParent(), TBB, FBB);
13170b57cec5SDimitry Andric return true;
13180b57cec5SDimitry Andric }
13190b57cec5SDimitry Andric
SelectIndirectBr(const Instruction * I)13200b57cec5SDimitry Andric bool ARMFastISel::SelectIndirectBr(const Instruction *I) {
132104eeddc0SDimitry Andric Register AddrReg = getRegForValue(I->getOperand(0));
13220b57cec5SDimitry Andric if (AddrReg == 0) return false;
13230b57cec5SDimitry Andric
13240b57cec5SDimitry Andric unsigned Opc = isThumb2 ? ARM::tBRIND : ARM::BX;
13250b57cec5SDimitry Andric assert(isThumb2 || Subtarget->hasV4TOps());
13260b57cec5SDimitry Andric
1327bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
13280b57cec5SDimitry Andric TII.get(Opc)).addReg(AddrReg));
13290b57cec5SDimitry Andric
13300b57cec5SDimitry Andric const IndirectBrInst *IB = cast<IndirectBrInst>(I);
13310b57cec5SDimitry Andric for (const BasicBlock *SuccBB : IB->successors())
13320b57cec5SDimitry Andric FuncInfo.MBB->addSuccessor(FuncInfo.MBBMap[SuccBB]);
13330b57cec5SDimitry Andric
13340b57cec5SDimitry Andric return true;
13350b57cec5SDimitry Andric }
13360b57cec5SDimitry Andric
ARMEmitCmp(const Value * Src1Value,const Value * Src2Value,bool isZExt)13370b57cec5SDimitry Andric bool ARMFastISel::ARMEmitCmp(const Value *Src1Value, const Value *Src2Value,
13388bcb0991SDimitry Andric bool isZExt) {
13390b57cec5SDimitry Andric Type *Ty = Src1Value->getType();
13400b57cec5SDimitry Andric EVT SrcEVT = TLI.getValueType(DL, Ty, true);
13410b57cec5SDimitry Andric if (!SrcEVT.isSimple()) return false;
13420b57cec5SDimitry Andric MVT SrcVT = SrcEVT.getSimpleVT();
13430b57cec5SDimitry Andric
13440b57cec5SDimitry Andric if (Ty->isFloatTy() && !Subtarget->hasVFP2Base())
13450b57cec5SDimitry Andric return false;
13460b57cec5SDimitry Andric
13470b57cec5SDimitry Andric if (Ty->isDoubleTy() && (!Subtarget->hasVFP2Base() || !Subtarget->hasFP64()))
13480b57cec5SDimitry Andric return false;
13490b57cec5SDimitry Andric
13500b57cec5SDimitry Andric // Check to see if the 2nd operand is a constant that we can encode directly
13510b57cec5SDimitry Andric // in the compare.
13520b57cec5SDimitry Andric int Imm = 0;
13530b57cec5SDimitry Andric bool UseImm = false;
13540b57cec5SDimitry Andric bool isNegativeImm = false;
13550b57cec5SDimitry Andric // FIXME: At -O0 we don't have anything that canonicalizes operand order.
13560b57cec5SDimitry Andric // Thus, Src1Value may be a ConstantInt, but we're missing it.
13570b57cec5SDimitry Andric if (const ConstantInt *ConstInt = dyn_cast<ConstantInt>(Src2Value)) {
13580b57cec5SDimitry Andric if (SrcVT == MVT::i32 || SrcVT == MVT::i16 || SrcVT == MVT::i8 ||
13590b57cec5SDimitry Andric SrcVT == MVT::i1) {
13600b57cec5SDimitry Andric const APInt &CIVal = ConstInt->getValue();
13610b57cec5SDimitry Andric Imm = (isZExt) ? (int)CIVal.getZExtValue() : (int)CIVal.getSExtValue();
13620b57cec5SDimitry Andric // For INT_MIN/LONG_MIN (i.e., 0x80000000) we need to use a cmp, rather
13630b57cec5SDimitry Andric // then a cmn, because there is no way to represent 2147483648 as a
13640b57cec5SDimitry Andric // signed 32-bit int.
13650b57cec5SDimitry Andric if (Imm < 0 && Imm != (int)0x80000000) {
13660b57cec5SDimitry Andric isNegativeImm = true;
13670b57cec5SDimitry Andric Imm = -Imm;
13680b57cec5SDimitry Andric }
13690b57cec5SDimitry Andric UseImm = isThumb2 ? (ARM_AM::getT2SOImmVal(Imm) != -1) :
13700b57cec5SDimitry Andric (ARM_AM::getSOImmVal(Imm) != -1);
13710b57cec5SDimitry Andric }
13720b57cec5SDimitry Andric } else if (const ConstantFP *ConstFP = dyn_cast<ConstantFP>(Src2Value)) {
13730b57cec5SDimitry Andric if (SrcVT == MVT::f32 || SrcVT == MVT::f64)
13740b57cec5SDimitry Andric if (ConstFP->isZero() && !ConstFP->isNegative())
13750b57cec5SDimitry Andric UseImm = true;
13760b57cec5SDimitry Andric }
13770b57cec5SDimitry Andric
13780b57cec5SDimitry Andric unsigned CmpOpc;
13790b57cec5SDimitry Andric bool isICmp = true;
13800b57cec5SDimitry Andric bool needsExt = false;
13810b57cec5SDimitry Andric switch (SrcVT.SimpleTy) {
13820b57cec5SDimitry Andric default: return false;
13830b57cec5SDimitry Andric // TODO: Verify compares.
13840b57cec5SDimitry Andric case MVT::f32:
13850b57cec5SDimitry Andric isICmp = false;
13860b57cec5SDimitry Andric CmpOpc = UseImm ? ARM::VCMPZS : ARM::VCMPS;
13870b57cec5SDimitry Andric break;
13880b57cec5SDimitry Andric case MVT::f64:
13890b57cec5SDimitry Andric isICmp = false;
13900b57cec5SDimitry Andric CmpOpc = UseImm ? ARM::VCMPZD : ARM::VCMPD;
13910b57cec5SDimitry Andric break;
13920b57cec5SDimitry Andric case MVT::i1:
13930b57cec5SDimitry Andric case MVT::i8:
13940b57cec5SDimitry Andric case MVT::i16:
13950b57cec5SDimitry Andric needsExt = true;
1396bdd1243dSDimitry Andric [[fallthrough]];
13970b57cec5SDimitry Andric case MVT::i32:
13980b57cec5SDimitry Andric if (isThumb2) {
13990b57cec5SDimitry Andric if (!UseImm)
14000b57cec5SDimitry Andric CmpOpc = ARM::t2CMPrr;
14010b57cec5SDimitry Andric else
14020b57cec5SDimitry Andric CmpOpc = isNegativeImm ? ARM::t2CMNri : ARM::t2CMPri;
14030b57cec5SDimitry Andric } else {
14040b57cec5SDimitry Andric if (!UseImm)
14050b57cec5SDimitry Andric CmpOpc = ARM::CMPrr;
14060b57cec5SDimitry Andric else
14070b57cec5SDimitry Andric CmpOpc = isNegativeImm ? ARM::CMNri : ARM::CMPri;
14080b57cec5SDimitry Andric }
14090b57cec5SDimitry Andric break;
14100b57cec5SDimitry Andric }
14110b57cec5SDimitry Andric
141204eeddc0SDimitry Andric Register SrcReg1 = getRegForValue(Src1Value);
14130b57cec5SDimitry Andric if (SrcReg1 == 0) return false;
14140b57cec5SDimitry Andric
14150b57cec5SDimitry Andric unsigned SrcReg2 = 0;
14160b57cec5SDimitry Andric if (!UseImm) {
14170b57cec5SDimitry Andric SrcReg2 = getRegForValue(Src2Value);
14180b57cec5SDimitry Andric if (SrcReg2 == 0) return false;
14190b57cec5SDimitry Andric }
14200b57cec5SDimitry Andric
14210b57cec5SDimitry Andric // We have i1, i8, or i16, we need to either zero extend or sign extend.
14220b57cec5SDimitry Andric if (needsExt) {
14230b57cec5SDimitry Andric SrcReg1 = ARMEmitIntExt(SrcVT, SrcReg1, MVT::i32, isZExt);
14240b57cec5SDimitry Andric if (SrcReg1 == 0) return false;
14250b57cec5SDimitry Andric if (!UseImm) {
14260b57cec5SDimitry Andric SrcReg2 = ARMEmitIntExt(SrcVT, SrcReg2, MVT::i32, isZExt);
14270b57cec5SDimitry Andric if (SrcReg2 == 0) return false;
14280b57cec5SDimitry Andric }
14290b57cec5SDimitry Andric }
14300b57cec5SDimitry Andric
14310b57cec5SDimitry Andric const MCInstrDesc &II = TII.get(CmpOpc);
14320b57cec5SDimitry Andric SrcReg1 = constrainOperandRegClass(II, SrcReg1, 0);
14330b57cec5SDimitry Andric if (!UseImm) {
14340b57cec5SDimitry Andric SrcReg2 = constrainOperandRegClass(II, SrcReg2, 1);
1435bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)
14360b57cec5SDimitry Andric .addReg(SrcReg1).addReg(SrcReg2));
14370b57cec5SDimitry Andric } else {
14380b57cec5SDimitry Andric MachineInstrBuilder MIB;
1439bdd1243dSDimitry Andric MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)
14400b57cec5SDimitry Andric .addReg(SrcReg1);
14410b57cec5SDimitry Andric
14420b57cec5SDimitry Andric // Only add immediate for icmp as the immediate for fcmp is an implicit 0.0.
14430b57cec5SDimitry Andric if (isICmp)
14440b57cec5SDimitry Andric MIB.addImm(Imm);
14450b57cec5SDimitry Andric AddOptionalDefs(MIB);
14460b57cec5SDimitry Andric }
14470b57cec5SDimitry Andric
14480b57cec5SDimitry Andric // For floating point we need to move the result to a comparison register
14490b57cec5SDimitry Andric // that we can then use for branches.
14500b57cec5SDimitry Andric if (Ty->isFloatTy() || Ty->isDoubleTy())
1451bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
14520b57cec5SDimitry Andric TII.get(ARM::FMSTAT)));
14530b57cec5SDimitry Andric return true;
14540b57cec5SDimitry Andric }
14550b57cec5SDimitry Andric
SelectCmp(const Instruction * I)14560b57cec5SDimitry Andric bool ARMFastISel::SelectCmp(const Instruction *I) {
14570b57cec5SDimitry Andric const CmpInst *CI = cast<CmpInst>(I);
14580b57cec5SDimitry Andric
14590b57cec5SDimitry Andric // Get the compare predicate.
14600b57cec5SDimitry Andric ARMCC::CondCodes ARMPred = getComparePred(CI->getPredicate());
14610b57cec5SDimitry Andric
14620b57cec5SDimitry Andric // We may not handle every CC for now.
14630b57cec5SDimitry Andric if (ARMPred == ARMCC::AL) return false;
14640b57cec5SDimitry Andric
14650b57cec5SDimitry Andric // Emit the compare.
14668bcb0991SDimitry Andric if (!ARMEmitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned()))
14670b57cec5SDimitry Andric return false;
14680b57cec5SDimitry Andric
14690b57cec5SDimitry Andric // Now set a register based on the comparison. Explicitly set the predicates
14700b57cec5SDimitry Andric // here.
14710b57cec5SDimitry Andric unsigned MovCCOpc = isThumb2 ? ARM::t2MOVCCi : ARM::MOVCCi;
14720b57cec5SDimitry Andric const TargetRegisterClass *RC = isThumb2 ? &ARM::rGPRRegClass
14730b57cec5SDimitry Andric : &ARM::GPRRegClass;
147404eeddc0SDimitry Andric Register DestReg = createResultReg(RC);
14750b57cec5SDimitry Andric Constant *Zero = ConstantInt::get(Type::getInt32Ty(*Context), 0);
14760b57cec5SDimitry Andric unsigned ZeroReg = fastMaterializeConstant(Zero);
14770b57cec5SDimitry Andric // ARMEmitCmp emits a FMSTAT when necessary, so it's always safe to use CPSR.
1478bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(MovCCOpc), DestReg)
14790b57cec5SDimitry Andric .addReg(ZeroReg).addImm(1)
14800b57cec5SDimitry Andric .addImm(ARMPred).addReg(ARM::CPSR);
14810b57cec5SDimitry Andric
14820b57cec5SDimitry Andric updateValueMap(I, DestReg);
14830b57cec5SDimitry Andric return true;
14840b57cec5SDimitry Andric }
14850b57cec5SDimitry Andric
SelectFPExt(const Instruction * I)14860b57cec5SDimitry Andric bool ARMFastISel::SelectFPExt(const Instruction *I) {
14870b57cec5SDimitry Andric // Make sure we have VFP and that we're extending float to double.
14880b57cec5SDimitry Andric if (!Subtarget->hasVFP2Base() || !Subtarget->hasFP64()) return false;
14890b57cec5SDimitry Andric
14900b57cec5SDimitry Andric Value *V = I->getOperand(0);
14910b57cec5SDimitry Andric if (!I->getType()->isDoubleTy() ||
14920b57cec5SDimitry Andric !V->getType()->isFloatTy()) return false;
14930b57cec5SDimitry Andric
149404eeddc0SDimitry Andric Register Op = getRegForValue(V);
14950b57cec5SDimitry Andric if (Op == 0) return false;
14960b57cec5SDimitry Andric
149704eeddc0SDimitry Andric Register Result = createResultReg(&ARM::DPRRegClass);
1498bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
14990b57cec5SDimitry Andric TII.get(ARM::VCVTDS), Result)
15000b57cec5SDimitry Andric .addReg(Op));
15010b57cec5SDimitry Andric updateValueMap(I, Result);
15020b57cec5SDimitry Andric return true;
15030b57cec5SDimitry Andric }
15040b57cec5SDimitry Andric
SelectFPTrunc(const Instruction * I)15050b57cec5SDimitry Andric bool ARMFastISel::SelectFPTrunc(const Instruction *I) {
15060b57cec5SDimitry Andric // Make sure we have VFP and that we're truncating double to float.
15070b57cec5SDimitry Andric if (!Subtarget->hasVFP2Base() || !Subtarget->hasFP64()) return false;
15080b57cec5SDimitry Andric
15090b57cec5SDimitry Andric Value *V = I->getOperand(0);
15100b57cec5SDimitry Andric if (!(I->getType()->isFloatTy() &&
15110b57cec5SDimitry Andric V->getType()->isDoubleTy())) return false;
15120b57cec5SDimitry Andric
151304eeddc0SDimitry Andric Register Op = getRegForValue(V);
15140b57cec5SDimitry Andric if (Op == 0) return false;
15150b57cec5SDimitry Andric
151604eeddc0SDimitry Andric Register Result = createResultReg(&ARM::SPRRegClass);
1517bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
15180b57cec5SDimitry Andric TII.get(ARM::VCVTSD), Result)
15190b57cec5SDimitry Andric .addReg(Op));
15200b57cec5SDimitry Andric updateValueMap(I, Result);
15210b57cec5SDimitry Andric return true;
15220b57cec5SDimitry Andric }
15230b57cec5SDimitry Andric
SelectIToFP(const Instruction * I,bool isSigned)15240b57cec5SDimitry Andric bool ARMFastISel::SelectIToFP(const Instruction *I, bool isSigned) {
15250b57cec5SDimitry Andric // Make sure we have VFP.
15260b57cec5SDimitry Andric if (!Subtarget->hasVFP2Base()) return false;
15270b57cec5SDimitry Andric
15280b57cec5SDimitry Andric MVT DstVT;
15290b57cec5SDimitry Andric Type *Ty = I->getType();
15300b57cec5SDimitry Andric if (!isTypeLegal(Ty, DstVT))
15310b57cec5SDimitry Andric return false;
15320b57cec5SDimitry Andric
15330b57cec5SDimitry Andric Value *Src = I->getOperand(0);
15340b57cec5SDimitry Andric EVT SrcEVT = TLI.getValueType(DL, Src->getType(), true);
15350b57cec5SDimitry Andric if (!SrcEVT.isSimple())
15360b57cec5SDimitry Andric return false;
15370b57cec5SDimitry Andric MVT SrcVT = SrcEVT.getSimpleVT();
15380b57cec5SDimitry Andric if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8)
15390b57cec5SDimitry Andric return false;
15400b57cec5SDimitry Andric
154104eeddc0SDimitry Andric Register SrcReg = getRegForValue(Src);
15420b57cec5SDimitry Andric if (SrcReg == 0) return false;
15430b57cec5SDimitry Andric
15440b57cec5SDimitry Andric // Handle sign-extension.
15450b57cec5SDimitry Andric if (SrcVT == MVT::i16 || SrcVT == MVT::i8) {
15460b57cec5SDimitry Andric SrcReg = ARMEmitIntExt(SrcVT, SrcReg, MVT::i32,
15470b57cec5SDimitry Andric /*isZExt*/!isSigned);
15480b57cec5SDimitry Andric if (SrcReg == 0) return false;
15490b57cec5SDimitry Andric }
15500b57cec5SDimitry Andric
15510b57cec5SDimitry Andric // The conversion routine works on fp-reg to fp-reg and the operand above
15520b57cec5SDimitry Andric // was an integer, move it to the fp registers if possible.
15530b57cec5SDimitry Andric unsigned FP = ARMMoveToFPReg(MVT::f32, SrcReg);
15540b57cec5SDimitry Andric if (FP == 0) return false;
15550b57cec5SDimitry Andric
15560b57cec5SDimitry Andric unsigned Opc;
15570b57cec5SDimitry Andric if (Ty->isFloatTy()) Opc = isSigned ? ARM::VSITOS : ARM::VUITOS;
15580b57cec5SDimitry Andric else if (Ty->isDoubleTy() && Subtarget->hasFP64())
15590b57cec5SDimitry Andric Opc = isSigned ? ARM::VSITOD : ARM::VUITOD;
15600b57cec5SDimitry Andric else return false;
15610b57cec5SDimitry Andric
156204eeddc0SDimitry Andric Register ResultReg = createResultReg(TLI.getRegClassFor(DstVT));
1563bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
15640b57cec5SDimitry Andric TII.get(Opc), ResultReg).addReg(FP));
15650b57cec5SDimitry Andric updateValueMap(I, ResultReg);
15660b57cec5SDimitry Andric return true;
15670b57cec5SDimitry Andric }
15680b57cec5SDimitry Andric
SelectFPToI(const Instruction * I,bool isSigned)15690b57cec5SDimitry Andric bool ARMFastISel::SelectFPToI(const Instruction *I, bool isSigned) {
15700b57cec5SDimitry Andric // Make sure we have VFP.
15710b57cec5SDimitry Andric if (!Subtarget->hasVFP2Base()) return false;
15720b57cec5SDimitry Andric
15730b57cec5SDimitry Andric MVT DstVT;
15740b57cec5SDimitry Andric Type *RetTy = I->getType();
15750b57cec5SDimitry Andric if (!isTypeLegal(RetTy, DstVT))
15760b57cec5SDimitry Andric return false;
15770b57cec5SDimitry Andric
157804eeddc0SDimitry Andric Register Op = getRegForValue(I->getOperand(0));
15790b57cec5SDimitry Andric if (Op == 0) return false;
15800b57cec5SDimitry Andric
15810b57cec5SDimitry Andric unsigned Opc;
15820b57cec5SDimitry Andric Type *OpTy = I->getOperand(0)->getType();
15830b57cec5SDimitry Andric if (OpTy->isFloatTy()) Opc = isSigned ? ARM::VTOSIZS : ARM::VTOUIZS;
15840b57cec5SDimitry Andric else if (OpTy->isDoubleTy() && Subtarget->hasFP64())
15850b57cec5SDimitry Andric Opc = isSigned ? ARM::VTOSIZD : ARM::VTOUIZD;
15860b57cec5SDimitry Andric else return false;
15870b57cec5SDimitry Andric
15880b57cec5SDimitry Andric // f64->s32/u32 or f32->s32/u32 both need an intermediate f32 reg.
158904eeddc0SDimitry Andric Register ResultReg = createResultReg(TLI.getRegClassFor(MVT::f32));
1590bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
15910b57cec5SDimitry Andric TII.get(Opc), ResultReg).addReg(Op));
15920b57cec5SDimitry Andric
15930b57cec5SDimitry Andric // This result needs to be in an integer register, but the conversion only
15940b57cec5SDimitry Andric // takes place in fp-regs.
15950b57cec5SDimitry Andric unsigned IntReg = ARMMoveToIntReg(DstVT, ResultReg);
15960b57cec5SDimitry Andric if (IntReg == 0) return false;
15970b57cec5SDimitry Andric
15980b57cec5SDimitry Andric updateValueMap(I, IntReg);
15990b57cec5SDimitry Andric return true;
16000b57cec5SDimitry Andric }
16010b57cec5SDimitry Andric
SelectSelect(const Instruction * I)16020b57cec5SDimitry Andric bool ARMFastISel::SelectSelect(const Instruction *I) {
16030b57cec5SDimitry Andric MVT VT;
16040b57cec5SDimitry Andric if (!isTypeLegal(I->getType(), VT))
16050b57cec5SDimitry Andric return false;
16060b57cec5SDimitry Andric
16070b57cec5SDimitry Andric // Things need to be register sized for register moves.
16080b57cec5SDimitry Andric if (VT != MVT::i32) return false;
16090b57cec5SDimitry Andric
161004eeddc0SDimitry Andric Register CondReg = getRegForValue(I->getOperand(0));
16110b57cec5SDimitry Andric if (CondReg == 0) return false;
161204eeddc0SDimitry Andric Register Op1Reg = getRegForValue(I->getOperand(1));
16130b57cec5SDimitry Andric if (Op1Reg == 0) return false;
16140b57cec5SDimitry Andric
16150b57cec5SDimitry Andric // Check to see if we can use an immediate in the conditional move.
16160b57cec5SDimitry Andric int Imm = 0;
16170b57cec5SDimitry Andric bool UseImm = false;
16180b57cec5SDimitry Andric bool isNegativeImm = false;
16190b57cec5SDimitry Andric if (const ConstantInt *ConstInt = dyn_cast<ConstantInt>(I->getOperand(2))) {
16200b57cec5SDimitry Andric assert(VT == MVT::i32 && "Expecting an i32.");
16210b57cec5SDimitry Andric Imm = (int)ConstInt->getValue().getZExtValue();
16220b57cec5SDimitry Andric if (Imm < 0) {
16230b57cec5SDimitry Andric isNegativeImm = true;
16240b57cec5SDimitry Andric Imm = ~Imm;
16250b57cec5SDimitry Andric }
16260b57cec5SDimitry Andric UseImm = isThumb2 ? (ARM_AM::getT2SOImmVal(Imm) != -1) :
16270b57cec5SDimitry Andric (ARM_AM::getSOImmVal(Imm) != -1);
16280b57cec5SDimitry Andric }
16290b57cec5SDimitry Andric
16300b57cec5SDimitry Andric unsigned Op2Reg = 0;
16310b57cec5SDimitry Andric if (!UseImm) {
16320b57cec5SDimitry Andric Op2Reg = getRegForValue(I->getOperand(2));
16330b57cec5SDimitry Andric if (Op2Reg == 0) return false;
16340b57cec5SDimitry Andric }
16350b57cec5SDimitry Andric
16360b57cec5SDimitry Andric unsigned TstOpc = isThumb2 ? ARM::t2TSTri : ARM::TSTri;
16370b57cec5SDimitry Andric CondReg = constrainOperandRegClass(TII.get(TstOpc), CondReg, 0);
16380b57cec5SDimitry Andric AddOptionalDefs(
1639bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(TstOpc))
16400b57cec5SDimitry Andric .addReg(CondReg)
16410b57cec5SDimitry Andric .addImm(1));
16420b57cec5SDimitry Andric
16430b57cec5SDimitry Andric unsigned MovCCOpc;
16440b57cec5SDimitry Andric const TargetRegisterClass *RC;
16450b57cec5SDimitry Andric if (!UseImm) {
16460b57cec5SDimitry Andric RC = isThumb2 ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
16470b57cec5SDimitry Andric MovCCOpc = isThumb2 ? ARM::t2MOVCCr : ARM::MOVCCr;
16480b57cec5SDimitry Andric } else {
16490b57cec5SDimitry Andric RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRRegClass;
16500b57cec5SDimitry Andric if (!isNegativeImm)
16510b57cec5SDimitry Andric MovCCOpc = isThumb2 ? ARM::t2MOVCCi : ARM::MOVCCi;
16520b57cec5SDimitry Andric else
16530b57cec5SDimitry Andric MovCCOpc = isThumb2 ? ARM::t2MVNCCi : ARM::MVNCCi;
16540b57cec5SDimitry Andric }
165504eeddc0SDimitry Andric Register ResultReg = createResultReg(RC);
16560b57cec5SDimitry Andric if (!UseImm) {
16570b57cec5SDimitry Andric Op2Reg = constrainOperandRegClass(TII.get(MovCCOpc), Op2Reg, 1);
16580b57cec5SDimitry Andric Op1Reg = constrainOperandRegClass(TII.get(MovCCOpc), Op1Reg, 2);
1659bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(MovCCOpc),
16600b57cec5SDimitry Andric ResultReg)
16610b57cec5SDimitry Andric .addReg(Op2Reg)
16620b57cec5SDimitry Andric .addReg(Op1Reg)
16630b57cec5SDimitry Andric .addImm(ARMCC::NE)
16640b57cec5SDimitry Andric .addReg(ARM::CPSR);
16650b57cec5SDimitry Andric } else {
16660b57cec5SDimitry Andric Op1Reg = constrainOperandRegClass(TII.get(MovCCOpc), Op1Reg, 1);
1667bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(MovCCOpc),
16680b57cec5SDimitry Andric ResultReg)
16690b57cec5SDimitry Andric .addReg(Op1Reg)
16700b57cec5SDimitry Andric .addImm(Imm)
16710b57cec5SDimitry Andric .addImm(ARMCC::EQ)
16720b57cec5SDimitry Andric .addReg(ARM::CPSR);
16730b57cec5SDimitry Andric }
16740b57cec5SDimitry Andric updateValueMap(I, ResultReg);
16750b57cec5SDimitry Andric return true;
16760b57cec5SDimitry Andric }
16770b57cec5SDimitry Andric
SelectDiv(const Instruction * I,bool isSigned)16780b57cec5SDimitry Andric bool ARMFastISel::SelectDiv(const Instruction *I, bool isSigned) {
16790b57cec5SDimitry Andric MVT VT;
16800b57cec5SDimitry Andric Type *Ty = I->getType();
16810b57cec5SDimitry Andric if (!isTypeLegal(Ty, VT))
16820b57cec5SDimitry Andric return false;
16830b57cec5SDimitry Andric
16840b57cec5SDimitry Andric // If we have integer div support we should have selected this automagically.
16850b57cec5SDimitry Andric // In case we have a real miss go ahead and return false and we'll pick
16860b57cec5SDimitry Andric // it up later.
16870b57cec5SDimitry Andric if (Subtarget->hasDivideInThumbMode())
16880b57cec5SDimitry Andric return false;
16890b57cec5SDimitry Andric
16900b57cec5SDimitry Andric // Otherwise emit a libcall.
16910b57cec5SDimitry Andric RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
16920b57cec5SDimitry Andric if (VT == MVT::i8)
16930b57cec5SDimitry Andric LC = isSigned ? RTLIB::SDIV_I8 : RTLIB::UDIV_I8;
16940b57cec5SDimitry Andric else if (VT == MVT::i16)
16950b57cec5SDimitry Andric LC = isSigned ? RTLIB::SDIV_I16 : RTLIB::UDIV_I16;
16960b57cec5SDimitry Andric else if (VT == MVT::i32)
16970b57cec5SDimitry Andric LC = isSigned ? RTLIB::SDIV_I32 : RTLIB::UDIV_I32;
16980b57cec5SDimitry Andric else if (VT == MVT::i64)
16990b57cec5SDimitry Andric LC = isSigned ? RTLIB::SDIV_I64 : RTLIB::UDIV_I64;
17000b57cec5SDimitry Andric else if (VT == MVT::i128)
17010b57cec5SDimitry Andric LC = isSigned ? RTLIB::SDIV_I128 : RTLIB::UDIV_I128;
17020b57cec5SDimitry Andric assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SDIV!");
17030b57cec5SDimitry Andric
17040b57cec5SDimitry Andric return ARMEmitLibcall(I, LC);
17050b57cec5SDimitry Andric }
17060b57cec5SDimitry Andric
SelectRem(const Instruction * I,bool isSigned)17070b57cec5SDimitry Andric bool ARMFastISel::SelectRem(const Instruction *I, bool isSigned) {
17080b57cec5SDimitry Andric MVT VT;
17090b57cec5SDimitry Andric Type *Ty = I->getType();
17100b57cec5SDimitry Andric if (!isTypeLegal(Ty, VT))
17110b57cec5SDimitry Andric return false;
17120b57cec5SDimitry Andric
17130b57cec5SDimitry Andric // Many ABIs do not provide a libcall for standalone remainder, so we need to
17140b57cec5SDimitry Andric // use divrem (see the RTABI 4.3.1). Since FastISel can't handle non-double
17150b57cec5SDimitry Andric // multi-reg returns, we'll have to bail out.
17160b57cec5SDimitry Andric if (!TLI.hasStandaloneRem(VT)) {
17170b57cec5SDimitry Andric return false;
17180b57cec5SDimitry Andric }
17190b57cec5SDimitry Andric
17200b57cec5SDimitry Andric RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
17210b57cec5SDimitry Andric if (VT == MVT::i8)
17220b57cec5SDimitry Andric LC = isSigned ? RTLIB::SREM_I8 : RTLIB::UREM_I8;
17230b57cec5SDimitry Andric else if (VT == MVT::i16)
17240b57cec5SDimitry Andric LC = isSigned ? RTLIB::SREM_I16 : RTLIB::UREM_I16;
17250b57cec5SDimitry Andric else if (VT == MVT::i32)
17260b57cec5SDimitry Andric LC = isSigned ? RTLIB::SREM_I32 : RTLIB::UREM_I32;
17270b57cec5SDimitry Andric else if (VT == MVT::i64)
17280b57cec5SDimitry Andric LC = isSigned ? RTLIB::SREM_I64 : RTLIB::UREM_I64;
17290b57cec5SDimitry Andric else if (VT == MVT::i128)
17300b57cec5SDimitry Andric LC = isSigned ? RTLIB::SREM_I128 : RTLIB::UREM_I128;
17310b57cec5SDimitry Andric assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SREM!");
17320b57cec5SDimitry Andric
17330b57cec5SDimitry Andric return ARMEmitLibcall(I, LC);
17340b57cec5SDimitry Andric }
17350b57cec5SDimitry Andric
SelectBinaryIntOp(const Instruction * I,unsigned ISDOpcode)17360b57cec5SDimitry Andric bool ARMFastISel::SelectBinaryIntOp(const Instruction *I, unsigned ISDOpcode) {
17370b57cec5SDimitry Andric EVT DestVT = TLI.getValueType(DL, I->getType(), true);
17380b57cec5SDimitry Andric
17390b57cec5SDimitry Andric // We can get here in the case when we have a binary operation on a non-legal
17400b57cec5SDimitry Andric // type and the target independent selector doesn't know how to handle it.
17410b57cec5SDimitry Andric if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1)
17420b57cec5SDimitry Andric return false;
17430b57cec5SDimitry Andric
17440b57cec5SDimitry Andric unsigned Opc;
17450b57cec5SDimitry Andric switch (ISDOpcode) {
17460b57cec5SDimitry Andric default: return false;
17470b57cec5SDimitry Andric case ISD::ADD:
17480b57cec5SDimitry Andric Opc = isThumb2 ? ARM::t2ADDrr : ARM::ADDrr;
17490b57cec5SDimitry Andric break;
17500b57cec5SDimitry Andric case ISD::OR:
17510b57cec5SDimitry Andric Opc = isThumb2 ? ARM::t2ORRrr : ARM::ORRrr;
17520b57cec5SDimitry Andric break;
17530b57cec5SDimitry Andric case ISD::SUB:
17540b57cec5SDimitry Andric Opc = isThumb2 ? ARM::t2SUBrr : ARM::SUBrr;
17550b57cec5SDimitry Andric break;
17560b57cec5SDimitry Andric }
17570b57cec5SDimitry Andric
175804eeddc0SDimitry Andric Register SrcReg1 = getRegForValue(I->getOperand(0));
17590b57cec5SDimitry Andric if (SrcReg1 == 0) return false;
17600b57cec5SDimitry Andric
17610b57cec5SDimitry Andric // TODO: Often the 2nd operand is an immediate, which can be encoded directly
17620b57cec5SDimitry Andric // in the instruction, rather then materializing the value in a register.
176304eeddc0SDimitry Andric Register SrcReg2 = getRegForValue(I->getOperand(1));
17640b57cec5SDimitry Andric if (SrcReg2 == 0) return false;
17650b57cec5SDimitry Andric
176604eeddc0SDimitry Andric Register ResultReg = createResultReg(&ARM::GPRnopcRegClass);
17670b57cec5SDimitry Andric SrcReg1 = constrainOperandRegClass(TII.get(Opc), SrcReg1, 1);
17680b57cec5SDimitry Andric SrcReg2 = constrainOperandRegClass(TII.get(Opc), SrcReg2, 2);
1769bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
17700b57cec5SDimitry Andric TII.get(Opc), ResultReg)
17710b57cec5SDimitry Andric .addReg(SrcReg1).addReg(SrcReg2));
17720b57cec5SDimitry Andric updateValueMap(I, ResultReg);
17730b57cec5SDimitry Andric return true;
17740b57cec5SDimitry Andric }
17750b57cec5SDimitry Andric
SelectBinaryFPOp(const Instruction * I,unsigned ISDOpcode)17760b57cec5SDimitry Andric bool ARMFastISel::SelectBinaryFPOp(const Instruction *I, unsigned ISDOpcode) {
17770b57cec5SDimitry Andric EVT FPVT = TLI.getValueType(DL, I->getType(), true);
17780b57cec5SDimitry Andric if (!FPVT.isSimple()) return false;
17790b57cec5SDimitry Andric MVT VT = FPVT.getSimpleVT();
17800b57cec5SDimitry Andric
17810b57cec5SDimitry Andric // FIXME: Support vector types where possible.
17820b57cec5SDimitry Andric if (VT.isVector())
17830b57cec5SDimitry Andric return false;
17840b57cec5SDimitry Andric
17850b57cec5SDimitry Andric // We can get here in the case when we want to use NEON for our fp
17860b57cec5SDimitry Andric // operations, but can't figure out how to. Just use the vfp instructions
17870b57cec5SDimitry Andric // if we have them.
17880b57cec5SDimitry Andric // FIXME: It'd be nice to use NEON instructions.
17890b57cec5SDimitry Andric Type *Ty = I->getType();
17900b57cec5SDimitry Andric if (Ty->isFloatTy() && !Subtarget->hasVFP2Base())
17910b57cec5SDimitry Andric return false;
17920b57cec5SDimitry Andric if (Ty->isDoubleTy() && (!Subtarget->hasVFP2Base() || !Subtarget->hasFP64()))
17930b57cec5SDimitry Andric return false;
17940b57cec5SDimitry Andric
17950b57cec5SDimitry Andric unsigned Opc;
17960b57cec5SDimitry Andric bool is64bit = VT == MVT::f64 || VT == MVT::i64;
17970b57cec5SDimitry Andric switch (ISDOpcode) {
17980b57cec5SDimitry Andric default: return false;
17990b57cec5SDimitry Andric case ISD::FADD:
18000b57cec5SDimitry Andric Opc = is64bit ? ARM::VADDD : ARM::VADDS;
18010b57cec5SDimitry Andric break;
18020b57cec5SDimitry Andric case ISD::FSUB:
18030b57cec5SDimitry Andric Opc = is64bit ? ARM::VSUBD : ARM::VSUBS;
18040b57cec5SDimitry Andric break;
18050b57cec5SDimitry Andric case ISD::FMUL:
18060b57cec5SDimitry Andric Opc = is64bit ? ARM::VMULD : ARM::VMULS;
18070b57cec5SDimitry Andric break;
18080b57cec5SDimitry Andric }
180904eeddc0SDimitry Andric Register Op1 = getRegForValue(I->getOperand(0));
18100b57cec5SDimitry Andric if (Op1 == 0) return false;
18110b57cec5SDimitry Andric
181204eeddc0SDimitry Andric Register Op2 = getRegForValue(I->getOperand(1));
18130b57cec5SDimitry Andric if (Op2 == 0) return false;
18140b57cec5SDimitry Andric
181504eeddc0SDimitry Andric Register ResultReg = createResultReg(TLI.getRegClassFor(VT.SimpleTy));
1816bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
18170b57cec5SDimitry Andric TII.get(Opc), ResultReg)
18180b57cec5SDimitry Andric .addReg(Op1).addReg(Op2));
18190b57cec5SDimitry Andric updateValueMap(I, ResultReg);
18200b57cec5SDimitry Andric return true;
18210b57cec5SDimitry Andric }
18220b57cec5SDimitry Andric
18230b57cec5SDimitry Andric // Call Handling Code
18240b57cec5SDimitry Andric
18250b57cec5SDimitry Andric // This is largely taken directly from CCAssignFnForNode
18260b57cec5SDimitry Andric // TODO: We may not support all of this.
CCAssignFnForCall(CallingConv::ID CC,bool Return,bool isVarArg)18270b57cec5SDimitry Andric CCAssignFn *ARMFastISel::CCAssignFnForCall(CallingConv::ID CC,
18280b57cec5SDimitry Andric bool Return,
18290b57cec5SDimitry Andric bool isVarArg) {
18300b57cec5SDimitry Andric switch (CC) {
18310b57cec5SDimitry Andric default:
18320b57cec5SDimitry Andric report_fatal_error("Unsupported calling convention");
18330b57cec5SDimitry Andric case CallingConv::Fast:
18340b57cec5SDimitry Andric if (Subtarget->hasVFP2Base() && !isVarArg) {
18350b57cec5SDimitry Andric if (!Subtarget->isAAPCS_ABI())
18360b57cec5SDimitry Andric return (Return ? RetFastCC_ARM_APCS : FastCC_ARM_APCS);
18370b57cec5SDimitry Andric // For AAPCS ABI targets, just use VFP variant of the calling convention.
18380b57cec5SDimitry Andric return (Return ? RetCC_ARM_AAPCS_VFP : CC_ARM_AAPCS_VFP);
18390b57cec5SDimitry Andric }
1840bdd1243dSDimitry Andric [[fallthrough]];
18410b57cec5SDimitry Andric case CallingConv::C:
18420b57cec5SDimitry Andric case CallingConv::CXX_FAST_TLS:
18430b57cec5SDimitry Andric // Use target triple & subtarget features to do actual dispatch.
18440b57cec5SDimitry Andric if (Subtarget->isAAPCS_ABI()) {
184506c3fb27SDimitry Andric if (Subtarget->hasFPRegs() &&
18460b57cec5SDimitry Andric TM.Options.FloatABIType == FloatABI::Hard && !isVarArg)
18470b57cec5SDimitry Andric return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP);
18480b57cec5SDimitry Andric else
18490b57cec5SDimitry Andric return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS);
18500b57cec5SDimitry Andric } else {
18510b57cec5SDimitry Andric return (Return ? RetCC_ARM_APCS: CC_ARM_APCS);
18520b57cec5SDimitry Andric }
18530b57cec5SDimitry Andric case CallingConv::ARM_AAPCS_VFP:
18540b57cec5SDimitry Andric case CallingConv::Swift:
1855fe6060f1SDimitry Andric case CallingConv::SwiftTail:
18560b57cec5SDimitry Andric if (!isVarArg)
18570b57cec5SDimitry Andric return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP);
18580b57cec5SDimitry Andric // Fall through to soft float variant, variadic functions don't
18590b57cec5SDimitry Andric // use hard floating point ABI.
1860bdd1243dSDimitry Andric [[fallthrough]];
18610b57cec5SDimitry Andric case CallingConv::ARM_AAPCS:
18620b57cec5SDimitry Andric return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS);
18630b57cec5SDimitry Andric case CallingConv::ARM_APCS:
18640b57cec5SDimitry Andric return (Return ? RetCC_ARM_APCS: CC_ARM_APCS);
18650b57cec5SDimitry Andric case CallingConv::GHC:
18660b57cec5SDimitry Andric if (Return)
18670b57cec5SDimitry Andric report_fatal_error("Can't return in GHC call convention");
18680b57cec5SDimitry Andric else
18690b57cec5SDimitry Andric return CC_ARM_APCS_GHC;
1870480093f4SDimitry Andric case CallingConv::CFGuard_Check:
1871480093f4SDimitry Andric return (Return ? RetCC_ARM_AAPCS : CC_ARM_Win32_CFGuard_Check);
18720b57cec5SDimitry Andric }
18730b57cec5SDimitry Andric }
18740b57cec5SDimitry Andric
ProcessCallArgs(SmallVectorImpl<Value * > & Args,SmallVectorImpl<Register> & ArgRegs,SmallVectorImpl<MVT> & ArgVTs,SmallVectorImpl<ISD::ArgFlagsTy> & ArgFlags,SmallVectorImpl<Register> & RegArgs,CallingConv::ID CC,unsigned & NumBytes,bool isVarArg)18750b57cec5SDimitry Andric bool ARMFastISel::ProcessCallArgs(SmallVectorImpl<Value*> &Args,
18768bcb0991SDimitry Andric SmallVectorImpl<Register> &ArgRegs,
18770b57cec5SDimitry Andric SmallVectorImpl<MVT> &ArgVTs,
18780b57cec5SDimitry Andric SmallVectorImpl<ISD::ArgFlagsTy> &ArgFlags,
18798bcb0991SDimitry Andric SmallVectorImpl<Register> &RegArgs,
18800b57cec5SDimitry Andric CallingConv::ID CC,
18810b57cec5SDimitry Andric unsigned &NumBytes,
18820b57cec5SDimitry Andric bool isVarArg) {
18830b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs;
18840b57cec5SDimitry Andric CCState CCInfo(CC, isVarArg, *FuncInfo.MF, ArgLocs, *Context);
18850b57cec5SDimitry Andric CCInfo.AnalyzeCallOperands(ArgVTs, ArgFlags,
18860b57cec5SDimitry Andric CCAssignFnForCall(CC, false, isVarArg));
18870b57cec5SDimitry Andric
18880b57cec5SDimitry Andric // Check that we can handle all of the arguments. If we can't, then bail out
18890b57cec5SDimitry Andric // now before we add code to the MBB.
18900b57cec5SDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
18910b57cec5SDimitry Andric CCValAssign &VA = ArgLocs[i];
18920b57cec5SDimitry Andric MVT ArgVT = ArgVTs[VA.getValNo()];
18930b57cec5SDimitry Andric
18940b57cec5SDimitry Andric // We don't handle NEON/vector parameters yet.
18950b57cec5SDimitry Andric if (ArgVT.isVector() || ArgVT.getSizeInBits() > 64)
18960b57cec5SDimitry Andric return false;
18970b57cec5SDimitry Andric
18980b57cec5SDimitry Andric // Now copy/store arg to correct locations.
18990b57cec5SDimitry Andric if (VA.isRegLoc() && !VA.needsCustom()) {
19000b57cec5SDimitry Andric continue;
19010b57cec5SDimitry Andric } else if (VA.needsCustom()) {
19020b57cec5SDimitry Andric // TODO: We need custom lowering for vector (v2f64) args.
19030b57cec5SDimitry Andric if (VA.getLocVT() != MVT::f64 ||
19040b57cec5SDimitry Andric // TODO: Only handle register args for now.
19050b57cec5SDimitry Andric !VA.isRegLoc() || !ArgLocs[++i].isRegLoc())
19060b57cec5SDimitry Andric return false;
19070b57cec5SDimitry Andric } else {
19080b57cec5SDimitry Andric switch (ArgVT.SimpleTy) {
19090b57cec5SDimitry Andric default:
19100b57cec5SDimitry Andric return false;
19110b57cec5SDimitry Andric case MVT::i1:
19120b57cec5SDimitry Andric case MVT::i8:
19130b57cec5SDimitry Andric case MVT::i16:
19140b57cec5SDimitry Andric case MVT::i32:
19150b57cec5SDimitry Andric break;
19160b57cec5SDimitry Andric case MVT::f32:
19170b57cec5SDimitry Andric if (!Subtarget->hasVFP2Base())
19180b57cec5SDimitry Andric return false;
19190b57cec5SDimitry Andric break;
19200b57cec5SDimitry Andric case MVT::f64:
19210b57cec5SDimitry Andric if (!Subtarget->hasVFP2Base())
19220b57cec5SDimitry Andric return false;
19230b57cec5SDimitry Andric break;
19240b57cec5SDimitry Andric }
19250b57cec5SDimitry Andric }
19260b57cec5SDimitry Andric }
19270b57cec5SDimitry Andric
19280b57cec5SDimitry Andric // At the point, we are able to handle the call's arguments in fast isel.
19290b57cec5SDimitry Andric
19300b57cec5SDimitry Andric // Get a count of how many bytes are to be pushed on the stack.
193106c3fb27SDimitry Andric NumBytes = CCInfo.getStackSize();
19320b57cec5SDimitry Andric
19330b57cec5SDimitry Andric // Issue CALLSEQ_START
19340b57cec5SDimitry Andric unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
1935bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
19360b57cec5SDimitry Andric TII.get(AdjStackDown))
19370b57cec5SDimitry Andric .addImm(NumBytes).addImm(0));
19380b57cec5SDimitry Andric
19390b57cec5SDimitry Andric // Process the args.
19400b57cec5SDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
19410b57cec5SDimitry Andric CCValAssign &VA = ArgLocs[i];
19420b57cec5SDimitry Andric const Value *ArgVal = Args[VA.getValNo()];
19438bcb0991SDimitry Andric Register Arg = ArgRegs[VA.getValNo()];
19440b57cec5SDimitry Andric MVT ArgVT = ArgVTs[VA.getValNo()];
19450b57cec5SDimitry Andric
19460b57cec5SDimitry Andric assert((!ArgVT.isVector() && ArgVT.getSizeInBits() <= 64) &&
19470b57cec5SDimitry Andric "We don't handle NEON/vector parameters yet.");
19480b57cec5SDimitry Andric
19490b57cec5SDimitry Andric // Handle arg promotion, etc.
19500b57cec5SDimitry Andric switch (VA.getLocInfo()) {
19510b57cec5SDimitry Andric case CCValAssign::Full: break;
19520b57cec5SDimitry Andric case CCValAssign::SExt: {
19530b57cec5SDimitry Andric MVT DestVT = VA.getLocVT();
19540b57cec5SDimitry Andric Arg = ARMEmitIntExt(ArgVT, Arg, DestVT, /*isZExt*/false);
19550b57cec5SDimitry Andric assert(Arg != 0 && "Failed to emit a sext");
19560b57cec5SDimitry Andric ArgVT = DestVT;
19570b57cec5SDimitry Andric break;
19580b57cec5SDimitry Andric }
19590b57cec5SDimitry Andric case CCValAssign::AExt:
19600b57cec5SDimitry Andric // Intentional fall-through. Handle AExt and ZExt.
19610b57cec5SDimitry Andric case CCValAssign::ZExt: {
19620b57cec5SDimitry Andric MVT DestVT = VA.getLocVT();
19630b57cec5SDimitry Andric Arg = ARMEmitIntExt(ArgVT, Arg, DestVT, /*isZExt*/true);
19640b57cec5SDimitry Andric assert(Arg != 0 && "Failed to emit a zext");
19650b57cec5SDimitry Andric ArgVT = DestVT;
19660b57cec5SDimitry Andric break;
19670b57cec5SDimitry Andric }
19680b57cec5SDimitry Andric case CCValAssign::BCvt: {
1969fe6060f1SDimitry Andric unsigned BC = fastEmit_r(ArgVT, VA.getLocVT(), ISD::BITCAST, Arg);
19700b57cec5SDimitry Andric assert(BC != 0 && "Failed to emit a bitcast!");
19710b57cec5SDimitry Andric Arg = BC;
19720b57cec5SDimitry Andric ArgVT = VA.getLocVT();
19730b57cec5SDimitry Andric break;
19740b57cec5SDimitry Andric }
19750b57cec5SDimitry Andric default: llvm_unreachable("Unknown arg promotion!");
19760b57cec5SDimitry Andric }
19770b57cec5SDimitry Andric
19780b57cec5SDimitry Andric // Now copy/store arg to correct locations.
19790b57cec5SDimitry Andric if (VA.isRegLoc() && !VA.needsCustom()) {
1980bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
19810b57cec5SDimitry Andric TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(Arg);
19820b57cec5SDimitry Andric RegArgs.push_back(VA.getLocReg());
19830b57cec5SDimitry Andric } else if (VA.needsCustom()) {
19840b57cec5SDimitry Andric // TODO: We need custom lowering for vector (v2f64) args.
19850b57cec5SDimitry Andric assert(VA.getLocVT() == MVT::f64 &&
19860b57cec5SDimitry Andric "Custom lowering for v2f64 args not available");
19870b57cec5SDimitry Andric
19880b57cec5SDimitry Andric // FIXME: ArgLocs[++i] may extend beyond ArgLocs.size()
19890b57cec5SDimitry Andric CCValAssign &NextVA = ArgLocs[++i];
19900b57cec5SDimitry Andric
19910b57cec5SDimitry Andric assert(VA.isRegLoc() && NextVA.isRegLoc() &&
19920b57cec5SDimitry Andric "We only handle register args!");
19930b57cec5SDimitry Andric
1994bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
19950b57cec5SDimitry Andric TII.get(ARM::VMOVRRD), VA.getLocReg())
19960b57cec5SDimitry Andric .addReg(NextVA.getLocReg(), RegState::Define)
19970b57cec5SDimitry Andric .addReg(Arg));
19980b57cec5SDimitry Andric RegArgs.push_back(VA.getLocReg());
19990b57cec5SDimitry Andric RegArgs.push_back(NextVA.getLocReg());
20000b57cec5SDimitry Andric } else {
20010b57cec5SDimitry Andric assert(VA.isMemLoc());
20020b57cec5SDimitry Andric // Need to store on the stack.
20030b57cec5SDimitry Andric
20040b57cec5SDimitry Andric // Don't emit stores for undef values.
20050b57cec5SDimitry Andric if (isa<UndefValue>(ArgVal))
20060b57cec5SDimitry Andric continue;
20070b57cec5SDimitry Andric
20080b57cec5SDimitry Andric Address Addr;
20090b57cec5SDimitry Andric Addr.BaseType = Address::RegBase;
20100b57cec5SDimitry Andric Addr.Base.Reg = ARM::SP;
20110b57cec5SDimitry Andric Addr.Offset = VA.getLocMemOffset();
20120b57cec5SDimitry Andric
20130b57cec5SDimitry Andric bool EmitRet = ARMEmitStore(ArgVT, Arg, Addr); (void)EmitRet;
20140b57cec5SDimitry Andric assert(EmitRet && "Could not emit a store for argument!");
20150b57cec5SDimitry Andric }
20160b57cec5SDimitry Andric }
20170b57cec5SDimitry Andric
20180b57cec5SDimitry Andric return true;
20190b57cec5SDimitry Andric }
20200b57cec5SDimitry Andric
FinishCall(MVT RetVT,SmallVectorImpl<Register> & UsedRegs,const Instruction * I,CallingConv::ID CC,unsigned & NumBytes,bool isVarArg)20218bcb0991SDimitry Andric bool ARMFastISel::FinishCall(MVT RetVT, SmallVectorImpl<Register> &UsedRegs,
20220b57cec5SDimitry Andric const Instruction *I, CallingConv::ID CC,
20230b57cec5SDimitry Andric unsigned &NumBytes, bool isVarArg) {
20240b57cec5SDimitry Andric // Issue CALLSEQ_END
20250b57cec5SDimitry Andric unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
2026bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
20270b57cec5SDimitry Andric TII.get(AdjStackUp))
202804eeddc0SDimitry Andric .addImm(NumBytes).addImm(-1ULL));
20290b57cec5SDimitry Andric
20300b57cec5SDimitry Andric // Now the return value.
20310b57cec5SDimitry Andric if (RetVT != MVT::isVoid) {
20320b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs;
20330b57cec5SDimitry Andric CCState CCInfo(CC, isVarArg, *FuncInfo.MF, RVLocs, *Context);
20340b57cec5SDimitry Andric CCInfo.AnalyzeCallResult(RetVT, CCAssignFnForCall(CC, true, isVarArg));
20350b57cec5SDimitry Andric
20360b57cec5SDimitry Andric // Copy all of the result registers out of their specified physreg.
20370b57cec5SDimitry Andric if (RVLocs.size() == 2 && RetVT == MVT::f64) {
20380b57cec5SDimitry Andric // For this move we copy into two registers and then move into the
20390b57cec5SDimitry Andric // double fp reg we want.
20400b57cec5SDimitry Andric MVT DestVT = RVLocs[0].getValVT();
20410b57cec5SDimitry Andric const TargetRegisterClass* DstRC = TLI.getRegClassFor(DestVT);
20428bcb0991SDimitry Andric Register ResultReg = createResultReg(DstRC);
2043bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
20440b57cec5SDimitry Andric TII.get(ARM::VMOVDRR), ResultReg)
20450b57cec5SDimitry Andric .addReg(RVLocs[0].getLocReg())
20460b57cec5SDimitry Andric .addReg(RVLocs[1].getLocReg()));
20470b57cec5SDimitry Andric
20480b57cec5SDimitry Andric UsedRegs.push_back(RVLocs[0].getLocReg());
20490b57cec5SDimitry Andric UsedRegs.push_back(RVLocs[1].getLocReg());
20500b57cec5SDimitry Andric
20510b57cec5SDimitry Andric // Finally update the result.
20520b57cec5SDimitry Andric updateValueMap(I, ResultReg);
20530b57cec5SDimitry Andric } else {
20540b57cec5SDimitry Andric assert(RVLocs.size() == 1 &&"Can't handle non-double multi-reg retvals!");
20550b57cec5SDimitry Andric MVT CopyVT = RVLocs[0].getValVT();
20560b57cec5SDimitry Andric
20570b57cec5SDimitry Andric // Special handling for extended integers.
20580b57cec5SDimitry Andric if (RetVT == MVT::i1 || RetVT == MVT::i8 || RetVT == MVT::i16)
20590b57cec5SDimitry Andric CopyVT = MVT::i32;
20600b57cec5SDimitry Andric
20610b57cec5SDimitry Andric const TargetRegisterClass* DstRC = TLI.getRegClassFor(CopyVT);
20620b57cec5SDimitry Andric
20638bcb0991SDimitry Andric Register ResultReg = createResultReg(DstRC);
2064bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
20650b57cec5SDimitry Andric TII.get(TargetOpcode::COPY),
20660b57cec5SDimitry Andric ResultReg).addReg(RVLocs[0].getLocReg());
20670b57cec5SDimitry Andric UsedRegs.push_back(RVLocs[0].getLocReg());
20680b57cec5SDimitry Andric
20690b57cec5SDimitry Andric // Finally update the result.
20700b57cec5SDimitry Andric updateValueMap(I, ResultReg);
20710b57cec5SDimitry Andric }
20720b57cec5SDimitry Andric }
20730b57cec5SDimitry Andric
20740b57cec5SDimitry Andric return true;
20750b57cec5SDimitry Andric }
20760b57cec5SDimitry Andric
SelectRet(const Instruction * I)20770b57cec5SDimitry Andric bool ARMFastISel::SelectRet(const Instruction *I) {
20780b57cec5SDimitry Andric const ReturnInst *Ret = cast<ReturnInst>(I);
20790b57cec5SDimitry Andric const Function &F = *I->getParent()->getParent();
20805ffd83dbSDimitry Andric const bool IsCmseNSEntry = F.hasFnAttribute("cmse_nonsecure_entry");
20810b57cec5SDimitry Andric
20820b57cec5SDimitry Andric if (!FuncInfo.CanLowerReturn)
20830b57cec5SDimitry Andric return false;
20840b57cec5SDimitry Andric
20850b57cec5SDimitry Andric if (TLI.supportSwiftError() &&
20860b57cec5SDimitry Andric F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
20870b57cec5SDimitry Andric return false;
20880b57cec5SDimitry Andric
20890b57cec5SDimitry Andric if (TLI.supportSplitCSR(FuncInfo.MF))
20900b57cec5SDimitry Andric return false;
20910b57cec5SDimitry Andric
20920b57cec5SDimitry Andric // Build a list of return value registers.
20930b57cec5SDimitry Andric SmallVector<unsigned, 4> RetRegs;
20940b57cec5SDimitry Andric
20950b57cec5SDimitry Andric CallingConv::ID CC = F.getCallingConv();
20960b57cec5SDimitry Andric if (Ret->getNumOperands() > 0) {
20970b57cec5SDimitry Andric SmallVector<ISD::OutputArg, 4> Outs;
20980b57cec5SDimitry Andric GetReturnInfo(CC, F.getReturnType(), F.getAttributes(), Outs, TLI, DL);
20990b57cec5SDimitry Andric
21000b57cec5SDimitry Andric // Analyze operands of the call, assigning locations to each operand.
21010b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ValLocs;
21020b57cec5SDimitry Andric CCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs, I->getContext());
21030b57cec5SDimitry Andric CCInfo.AnalyzeReturn(Outs, CCAssignFnForCall(CC, true /* is Ret */,
21040b57cec5SDimitry Andric F.isVarArg()));
21050b57cec5SDimitry Andric
21060b57cec5SDimitry Andric const Value *RV = Ret->getOperand(0);
210704eeddc0SDimitry Andric Register Reg = getRegForValue(RV);
21080b57cec5SDimitry Andric if (Reg == 0)
21090b57cec5SDimitry Andric return false;
21100b57cec5SDimitry Andric
21110b57cec5SDimitry Andric // Only handle a single return value for now.
21120b57cec5SDimitry Andric if (ValLocs.size() != 1)
21130b57cec5SDimitry Andric return false;
21140b57cec5SDimitry Andric
21150b57cec5SDimitry Andric CCValAssign &VA = ValLocs[0];
21160b57cec5SDimitry Andric
21170b57cec5SDimitry Andric // Don't bother handling odd stuff for now.
21180b57cec5SDimitry Andric if (VA.getLocInfo() != CCValAssign::Full)
21190b57cec5SDimitry Andric return false;
21200b57cec5SDimitry Andric // Only handle register returns for now.
21210b57cec5SDimitry Andric if (!VA.isRegLoc())
21220b57cec5SDimitry Andric return false;
21230b57cec5SDimitry Andric
21240b57cec5SDimitry Andric unsigned SrcReg = Reg + VA.getValNo();
21250b57cec5SDimitry Andric EVT RVEVT = TLI.getValueType(DL, RV->getType());
21260b57cec5SDimitry Andric if (!RVEVT.isSimple()) return false;
21270b57cec5SDimitry Andric MVT RVVT = RVEVT.getSimpleVT();
21280b57cec5SDimitry Andric MVT DestVT = VA.getValVT();
21290b57cec5SDimitry Andric // Special handling for extended integers.
21300b57cec5SDimitry Andric if (RVVT != DestVT) {
21310b57cec5SDimitry Andric if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
21320b57cec5SDimitry Andric return false;
21330b57cec5SDimitry Andric
21340b57cec5SDimitry Andric assert(DestVT == MVT::i32 && "ARM should always ext to i32");
21350b57cec5SDimitry Andric
21360b57cec5SDimitry Andric // Perform extension if flagged as either zext or sext. Otherwise, do
21370b57cec5SDimitry Andric // nothing.
21380b57cec5SDimitry Andric if (Outs[0].Flags.isZExt() || Outs[0].Flags.isSExt()) {
21390b57cec5SDimitry Andric SrcReg = ARMEmitIntExt(RVVT, SrcReg, DestVT, Outs[0].Flags.isZExt());
21400b57cec5SDimitry Andric if (SrcReg == 0) return false;
21410b57cec5SDimitry Andric }
21420b57cec5SDimitry Andric }
21430b57cec5SDimitry Andric
21440b57cec5SDimitry Andric // Make the copy.
21458bcb0991SDimitry Andric Register DstReg = VA.getLocReg();
21460b57cec5SDimitry Andric const TargetRegisterClass* SrcRC = MRI.getRegClass(SrcReg);
21470b57cec5SDimitry Andric // Avoid a cross-class copy. This is very unlikely.
21480b57cec5SDimitry Andric if (!SrcRC->contains(DstReg))
21490b57cec5SDimitry Andric return false;
2150bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
21510b57cec5SDimitry Andric TII.get(TargetOpcode::COPY), DstReg).addReg(SrcReg);
21520b57cec5SDimitry Andric
21530b57cec5SDimitry Andric // Add register to return instruction.
21540b57cec5SDimitry Andric RetRegs.push_back(VA.getLocReg());
21550b57cec5SDimitry Andric }
21560b57cec5SDimitry Andric
21575ffd83dbSDimitry Andric unsigned RetOpc;
21585ffd83dbSDimitry Andric if (IsCmseNSEntry)
21595ffd83dbSDimitry Andric if (isThumb2)
21605ffd83dbSDimitry Andric RetOpc = ARM::tBXNS_RET;
21615ffd83dbSDimitry Andric else
21625ffd83dbSDimitry Andric llvm_unreachable("CMSE not valid for non-Thumb targets");
21635ffd83dbSDimitry Andric else
21645ffd83dbSDimitry Andric RetOpc = Subtarget->getReturnOpcode();
21655ffd83dbSDimitry Andric
2166bdd1243dSDimitry Andric MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
21675ffd83dbSDimitry Andric TII.get(RetOpc));
21680b57cec5SDimitry Andric AddOptionalDefs(MIB);
21690b57cec5SDimitry Andric for (unsigned R : RetRegs)
21700b57cec5SDimitry Andric MIB.addReg(R, RegState::Implicit);
21710b57cec5SDimitry Andric return true;
21720b57cec5SDimitry Andric }
21730b57cec5SDimitry Andric
ARMSelectCallOp(bool UseReg)21740b57cec5SDimitry Andric unsigned ARMFastISel::ARMSelectCallOp(bool UseReg) {
21750b57cec5SDimitry Andric if (UseReg)
2176e8d8bef9SDimitry Andric return isThumb2 ? gettBLXrOpcode(*MF) : getBLXOpcode(*MF);
21770b57cec5SDimitry Andric else
21780b57cec5SDimitry Andric return isThumb2 ? ARM::tBL : ARM::BL;
21790b57cec5SDimitry Andric }
21800b57cec5SDimitry Andric
getLibcallReg(const Twine & Name)21810b57cec5SDimitry Andric unsigned ARMFastISel::getLibcallReg(const Twine &Name) {
21820b57cec5SDimitry Andric // Manually compute the global's type to avoid building it when unnecessary.
21835f757f3fSDimitry Andric Type *GVTy = PointerType::get(*Context, /*AS=*/0);
21840b57cec5SDimitry Andric EVT LCREVT = TLI.getValueType(DL, GVTy);
21850b57cec5SDimitry Andric if (!LCREVT.isSimple()) return 0;
21860b57cec5SDimitry Andric
2187fe6060f1SDimitry Andric GlobalValue *GV = M.getNamedGlobal(Name.str());
2188fe6060f1SDimitry Andric if (!GV)
2189fe6060f1SDimitry Andric GV = new GlobalVariable(M, Type::getInt32Ty(*Context), false,
2190fe6060f1SDimitry Andric GlobalValue::ExternalLinkage, nullptr, Name);
2191fe6060f1SDimitry Andric
21920b57cec5SDimitry Andric return ARMMaterializeGV(GV, LCREVT.getSimpleVT());
21930b57cec5SDimitry Andric }
21940b57cec5SDimitry Andric
21950b57cec5SDimitry Andric // A quick function that will emit a call for a named libcall in F with the
21960b57cec5SDimitry Andric // vector of passed arguments for the Instruction in I. We can assume that we
21970b57cec5SDimitry Andric // can emit a call for any libcall we can produce. This is an abridged version
21980b57cec5SDimitry Andric // of the full call infrastructure since we won't need to worry about things
21990b57cec5SDimitry Andric // like computed function pointers or strange arguments at call sites.
22000b57cec5SDimitry Andric // TODO: Try to unify this and the normal call bits for ARM, then try to unify
22010b57cec5SDimitry Andric // with X86.
ARMEmitLibcall(const Instruction * I,RTLIB::Libcall Call)22020b57cec5SDimitry Andric bool ARMFastISel::ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call) {
22030b57cec5SDimitry Andric CallingConv::ID CC = TLI.getLibcallCallingConv(Call);
22040b57cec5SDimitry Andric
22050b57cec5SDimitry Andric // Handle *simple* calls for now.
22060b57cec5SDimitry Andric Type *RetTy = I->getType();
22070b57cec5SDimitry Andric MVT RetVT;
22080b57cec5SDimitry Andric if (RetTy->isVoidTy())
22090b57cec5SDimitry Andric RetVT = MVT::isVoid;
22100b57cec5SDimitry Andric else if (!isTypeLegal(RetTy, RetVT))
22110b57cec5SDimitry Andric return false;
22120b57cec5SDimitry Andric
22130b57cec5SDimitry Andric // Can't handle non-double multi-reg retvals.
22140b57cec5SDimitry Andric if (RetVT != MVT::isVoid && RetVT != MVT::i32) {
22150b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs;
22160b57cec5SDimitry Andric CCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context);
22170b57cec5SDimitry Andric CCInfo.AnalyzeCallResult(RetVT, CCAssignFnForCall(CC, true, false));
22180b57cec5SDimitry Andric if (RVLocs.size() >= 2 && RetVT != MVT::f64)
22190b57cec5SDimitry Andric return false;
22200b57cec5SDimitry Andric }
22210b57cec5SDimitry Andric
22220b57cec5SDimitry Andric // Set up the argument vectors.
22230b57cec5SDimitry Andric SmallVector<Value*, 8> Args;
22248bcb0991SDimitry Andric SmallVector<Register, 8> ArgRegs;
22250b57cec5SDimitry Andric SmallVector<MVT, 8> ArgVTs;
22260b57cec5SDimitry Andric SmallVector<ISD::ArgFlagsTy, 8> ArgFlags;
22270b57cec5SDimitry Andric Args.reserve(I->getNumOperands());
22280b57cec5SDimitry Andric ArgRegs.reserve(I->getNumOperands());
22290b57cec5SDimitry Andric ArgVTs.reserve(I->getNumOperands());
22300b57cec5SDimitry Andric ArgFlags.reserve(I->getNumOperands());
22310b57cec5SDimitry Andric for (Value *Op : I->operands()) {
223204eeddc0SDimitry Andric Register Arg = getRegForValue(Op);
22330b57cec5SDimitry Andric if (Arg == 0) return false;
22340b57cec5SDimitry Andric
22350b57cec5SDimitry Andric Type *ArgTy = Op->getType();
22360b57cec5SDimitry Andric MVT ArgVT;
22370b57cec5SDimitry Andric if (!isTypeLegal(ArgTy, ArgVT)) return false;
22380b57cec5SDimitry Andric
22390b57cec5SDimitry Andric ISD::ArgFlagsTy Flags;
22405ffd83dbSDimitry Andric Flags.setOrigAlign(DL.getABITypeAlign(ArgTy));
22410b57cec5SDimitry Andric
22420b57cec5SDimitry Andric Args.push_back(Op);
22430b57cec5SDimitry Andric ArgRegs.push_back(Arg);
22440b57cec5SDimitry Andric ArgVTs.push_back(ArgVT);
22450b57cec5SDimitry Andric ArgFlags.push_back(Flags);
22460b57cec5SDimitry Andric }
22470b57cec5SDimitry Andric
22480b57cec5SDimitry Andric // Handle the arguments now that we've gotten them.
22498bcb0991SDimitry Andric SmallVector<Register, 4> RegArgs;
22500b57cec5SDimitry Andric unsigned NumBytes;
22510b57cec5SDimitry Andric if (!ProcessCallArgs(Args, ArgRegs, ArgVTs, ArgFlags,
22520b57cec5SDimitry Andric RegArgs, CC, NumBytes, false))
22530b57cec5SDimitry Andric return false;
22540b57cec5SDimitry Andric
22558bcb0991SDimitry Andric Register CalleeReg;
22560b57cec5SDimitry Andric if (Subtarget->genLongCalls()) {
22570b57cec5SDimitry Andric CalleeReg = getLibcallReg(TLI.getLibcallName(Call));
22580b57cec5SDimitry Andric if (CalleeReg == 0) return false;
22590b57cec5SDimitry Andric }
22600b57cec5SDimitry Andric
22610b57cec5SDimitry Andric // Issue the call.
22620b57cec5SDimitry Andric unsigned CallOpc = ARMSelectCallOp(Subtarget->genLongCalls());
22630b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
2264bdd1243dSDimitry Andric MIMD, TII.get(CallOpc));
22650b57cec5SDimitry Andric // BL / BLX don't take a predicate, but tBL / tBLX do.
22660b57cec5SDimitry Andric if (isThumb2)
22670b57cec5SDimitry Andric MIB.add(predOps(ARMCC::AL));
2268e8d8bef9SDimitry Andric if (Subtarget->genLongCalls()) {
2269e8d8bef9SDimitry Andric CalleeReg =
2270e8d8bef9SDimitry Andric constrainOperandRegClass(TII.get(CallOpc), CalleeReg, isThumb2 ? 2 : 0);
22710b57cec5SDimitry Andric MIB.addReg(CalleeReg);
2272e8d8bef9SDimitry Andric } else
22730b57cec5SDimitry Andric MIB.addExternalSymbol(TLI.getLibcallName(Call));
22740b57cec5SDimitry Andric
22750b57cec5SDimitry Andric // Add implicit physical register uses to the call.
22768bcb0991SDimitry Andric for (Register R : RegArgs)
22770b57cec5SDimitry Andric MIB.addReg(R, RegState::Implicit);
22780b57cec5SDimitry Andric
22790b57cec5SDimitry Andric // Add a register mask with the call-preserved registers.
22800b57cec5SDimitry Andric // Proper defs for return values will be added by setPhysRegsDeadExcept().
22810b57cec5SDimitry Andric MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC));
22820b57cec5SDimitry Andric
22830b57cec5SDimitry Andric // Finish off the call including any return values.
22848bcb0991SDimitry Andric SmallVector<Register, 4> UsedRegs;
22850b57cec5SDimitry Andric if (!FinishCall(RetVT, UsedRegs, I, CC, NumBytes, false)) return false;
22860b57cec5SDimitry Andric
22870b57cec5SDimitry Andric // Set all unused physreg defs as dead.
22880b57cec5SDimitry Andric static_cast<MachineInstr *>(MIB)->setPhysRegsDeadExcept(UsedRegs, TRI);
22890b57cec5SDimitry Andric
22900b57cec5SDimitry Andric return true;
22910b57cec5SDimitry Andric }
22920b57cec5SDimitry Andric
SelectCall(const Instruction * I,const char * IntrMemName=nullptr)22930b57cec5SDimitry Andric bool ARMFastISel::SelectCall(const Instruction *I,
22940b57cec5SDimitry Andric const char *IntrMemName = nullptr) {
22950b57cec5SDimitry Andric const CallInst *CI = cast<CallInst>(I);
22965ffd83dbSDimitry Andric const Value *Callee = CI->getCalledOperand();
22970b57cec5SDimitry Andric
22980b57cec5SDimitry Andric // Can't handle inline asm.
22990b57cec5SDimitry Andric if (isa<InlineAsm>(Callee)) return false;
23000b57cec5SDimitry Andric
23010b57cec5SDimitry Andric // Allow SelectionDAG isel to handle tail calls.
23020b57cec5SDimitry Andric if (CI->isTailCall()) return false;
23030b57cec5SDimitry Andric
23040b57cec5SDimitry Andric // Check the calling convention.
23055ffd83dbSDimitry Andric CallingConv::ID CC = CI->getCallingConv();
23060b57cec5SDimitry Andric
23070b57cec5SDimitry Andric // TODO: Avoid some calling conventions?
23080b57cec5SDimitry Andric
23095ffd83dbSDimitry Andric FunctionType *FTy = CI->getFunctionType();
23100b57cec5SDimitry Andric bool isVarArg = FTy->isVarArg();
23110b57cec5SDimitry Andric
23120b57cec5SDimitry Andric // Handle *simple* calls for now.
23130b57cec5SDimitry Andric Type *RetTy = I->getType();
23140b57cec5SDimitry Andric MVT RetVT;
23150b57cec5SDimitry Andric if (RetTy->isVoidTy())
23160b57cec5SDimitry Andric RetVT = MVT::isVoid;
23170b57cec5SDimitry Andric else if (!isTypeLegal(RetTy, RetVT) && RetVT != MVT::i16 &&
23180b57cec5SDimitry Andric RetVT != MVT::i8 && RetVT != MVT::i1)
23190b57cec5SDimitry Andric return false;
23200b57cec5SDimitry Andric
23210b57cec5SDimitry Andric // Can't handle non-double multi-reg retvals.
23220b57cec5SDimitry Andric if (RetVT != MVT::isVoid && RetVT != MVT::i1 && RetVT != MVT::i8 &&
23230b57cec5SDimitry Andric RetVT != MVT::i16 && RetVT != MVT::i32) {
23240b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs;
23250b57cec5SDimitry Andric CCState CCInfo(CC, isVarArg, *FuncInfo.MF, RVLocs, *Context);
23260b57cec5SDimitry Andric CCInfo.AnalyzeCallResult(RetVT, CCAssignFnForCall(CC, true, isVarArg));
23270b57cec5SDimitry Andric if (RVLocs.size() >= 2 && RetVT != MVT::f64)
23280b57cec5SDimitry Andric return false;
23290b57cec5SDimitry Andric }
23300b57cec5SDimitry Andric
23310b57cec5SDimitry Andric // Set up the argument vectors.
23320b57cec5SDimitry Andric SmallVector<Value*, 8> Args;
23338bcb0991SDimitry Andric SmallVector<Register, 8> ArgRegs;
23340b57cec5SDimitry Andric SmallVector<MVT, 8> ArgVTs;
23350b57cec5SDimitry Andric SmallVector<ISD::ArgFlagsTy, 8> ArgFlags;
23365ffd83dbSDimitry Andric unsigned arg_size = CI->arg_size();
23370b57cec5SDimitry Andric Args.reserve(arg_size);
23380b57cec5SDimitry Andric ArgRegs.reserve(arg_size);
23390b57cec5SDimitry Andric ArgVTs.reserve(arg_size);
23400b57cec5SDimitry Andric ArgFlags.reserve(arg_size);
23415ffd83dbSDimitry Andric for (auto ArgI = CI->arg_begin(), ArgE = CI->arg_end(); ArgI != ArgE; ++ArgI) {
23420b57cec5SDimitry Andric // If we're lowering a memory intrinsic instead of a regular call, skip the
23430b57cec5SDimitry Andric // last argument, which shouldn't be passed to the underlying function.
23445ffd83dbSDimitry Andric if (IntrMemName && ArgE - ArgI <= 1)
23450b57cec5SDimitry Andric break;
23460b57cec5SDimitry Andric
23470b57cec5SDimitry Andric ISD::ArgFlagsTy Flags;
23485ffd83dbSDimitry Andric unsigned ArgIdx = ArgI - CI->arg_begin();
23495ffd83dbSDimitry Andric if (CI->paramHasAttr(ArgIdx, Attribute::SExt))
23500b57cec5SDimitry Andric Flags.setSExt();
23515ffd83dbSDimitry Andric if (CI->paramHasAttr(ArgIdx, Attribute::ZExt))
23520b57cec5SDimitry Andric Flags.setZExt();
23530b57cec5SDimitry Andric
23540b57cec5SDimitry Andric // FIXME: Only handle *easy* calls for now.
23555ffd83dbSDimitry Andric if (CI->paramHasAttr(ArgIdx, Attribute::InReg) ||
23565ffd83dbSDimitry Andric CI->paramHasAttr(ArgIdx, Attribute::StructRet) ||
23575ffd83dbSDimitry Andric CI->paramHasAttr(ArgIdx, Attribute::SwiftSelf) ||
23585ffd83dbSDimitry Andric CI->paramHasAttr(ArgIdx, Attribute::SwiftError) ||
23595ffd83dbSDimitry Andric CI->paramHasAttr(ArgIdx, Attribute::Nest) ||
23605ffd83dbSDimitry Andric CI->paramHasAttr(ArgIdx, Attribute::ByVal))
23610b57cec5SDimitry Andric return false;
23620b57cec5SDimitry Andric
23635ffd83dbSDimitry Andric Type *ArgTy = (*ArgI)->getType();
23640b57cec5SDimitry Andric MVT ArgVT;
23650b57cec5SDimitry Andric if (!isTypeLegal(ArgTy, ArgVT) && ArgVT != MVT::i16 && ArgVT != MVT::i8 &&
23660b57cec5SDimitry Andric ArgVT != MVT::i1)
23670b57cec5SDimitry Andric return false;
23680b57cec5SDimitry Andric
23695ffd83dbSDimitry Andric Register Arg = getRegForValue(*ArgI);
23708bcb0991SDimitry Andric if (!Arg.isValid())
23710b57cec5SDimitry Andric return false;
23720b57cec5SDimitry Andric
23735ffd83dbSDimitry Andric Flags.setOrigAlign(DL.getABITypeAlign(ArgTy));
23740b57cec5SDimitry Andric
23755ffd83dbSDimitry Andric Args.push_back(*ArgI);
23760b57cec5SDimitry Andric ArgRegs.push_back(Arg);
23770b57cec5SDimitry Andric ArgVTs.push_back(ArgVT);
23780b57cec5SDimitry Andric ArgFlags.push_back(Flags);
23790b57cec5SDimitry Andric }
23800b57cec5SDimitry Andric
23810b57cec5SDimitry Andric // Handle the arguments now that we've gotten them.
23828bcb0991SDimitry Andric SmallVector<Register, 4> RegArgs;
23830b57cec5SDimitry Andric unsigned NumBytes;
23840b57cec5SDimitry Andric if (!ProcessCallArgs(Args, ArgRegs, ArgVTs, ArgFlags,
23850b57cec5SDimitry Andric RegArgs, CC, NumBytes, isVarArg))
23860b57cec5SDimitry Andric return false;
23870b57cec5SDimitry Andric
23880b57cec5SDimitry Andric bool UseReg = false;
23890b57cec5SDimitry Andric const GlobalValue *GV = dyn_cast<GlobalValue>(Callee);
23900b57cec5SDimitry Andric if (!GV || Subtarget->genLongCalls()) UseReg = true;
23910b57cec5SDimitry Andric
23928bcb0991SDimitry Andric Register CalleeReg;
23930b57cec5SDimitry Andric if (UseReg) {
23940b57cec5SDimitry Andric if (IntrMemName)
23950b57cec5SDimitry Andric CalleeReg = getLibcallReg(IntrMemName);
23960b57cec5SDimitry Andric else
23970b57cec5SDimitry Andric CalleeReg = getRegForValue(Callee);
23980b57cec5SDimitry Andric
23990b57cec5SDimitry Andric if (CalleeReg == 0) return false;
24000b57cec5SDimitry Andric }
24010b57cec5SDimitry Andric
24020b57cec5SDimitry Andric // Issue the call.
24030b57cec5SDimitry Andric unsigned CallOpc = ARMSelectCallOp(UseReg);
24040b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
2405bdd1243dSDimitry Andric MIMD, TII.get(CallOpc));
24060b57cec5SDimitry Andric
24070b57cec5SDimitry Andric // ARM calls don't take a predicate, but tBL / tBLX do.
24080b57cec5SDimitry Andric if(isThumb2)
24090b57cec5SDimitry Andric MIB.add(predOps(ARMCC::AL));
2410e8d8bef9SDimitry Andric if (UseReg) {
2411e8d8bef9SDimitry Andric CalleeReg =
2412e8d8bef9SDimitry Andric constrainOperandRegClass(TII.get(CallOpc), CalleeReg, isThumb2 ? 2 : 0);
24130b57cec5SDimitry Andric MIB.addReg(CalleeReg);
2414e8d8bef9SDimitry Andric } else if (!IntrMemName)
24150b57cec5SDimitry Andric MIB.addGlobalAddress(GV, 0, 0);
24160b57cec5SDimitry Andric else
24170b57cec5SDimitry Andric MIB.addExternalSymbol(IntrMemName, 0);
24180b57cec5SDimitry Andric
24190b57cec5SDimitry Andric // Add implicit physical register uses to the call.
24208bcb0991SDimitry Andric for (Register R : RegArgs)
24210b57cec5SDimitry Andric MIB.addReg(R, RegState::Implicit);
24220b57cec5SDimitry Andric
24230b57cec5SDimitry Andric // Add a register mask with the call-preserved registers.
24240b57cec5SDimitry Andric // Proper defs for return values will be added by setPhysRegsDeadExcept().
24250b57cec5SDimitry Andric MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC));
24260b57cec5SDimitry Andric
24270b57cec5SDimitry Andric // Finish off the call including any return values.
24288bcb0991SDimitry Andric SmallVector<Register, 4> UsedRegs;
24290b57cec5SDimitry Andric if (!FinishCall(RetVT, UsedRegs, I, CC, NumBytes, isVarArg))
24300b57cec5SDimitry Andric return false;
24310b57cec5SDimitry Andric
24320b57cec5SDimitry Andric // Set all unused physreg defs as dead.
24330b57cec5SDimitry Andric static_cast<MachineInstr *>(MIB)->setPhysRegsDeadExcept(UsedRegs, TRI);
24340b57cec5SDimitry Andric
24350b57cec5SDimitry Andric return true;
24360b57cec5SDimitry Andric }
24370b57cec5SDimitry Andric
ARMIsMemCpySmall(uint64_t Len)24380b57cec5SDimitry Andric bool ARMFastISel::ARMIsMemCpySmall(uint64_t Len) {
24390b57cec5SDimitry Andric return Len <= 16;
24400b57cec5SDimitry Andric }
24410b57cec5SDimitry Andric
ARMTryEmitSmallMemCpy(Address Dest,Address Src,uint64_t Len,MaybeAlign Alignment)2442bdd1243dSDimitry Andric bool ARMFastISel::ARMTryEmitSmallMemCpy(Address Dest, Address Src, uint64_t Len,
2443bdd1243dSDimitry Andric MaybeAlign Alignment) {
24440b57cec5SDimitry Andric // Make sure we don't bloat code by inlining very large memcpy's.
24450b57cec5SDimitry Andric if (!ARMIsMemCpySmall(Len))
24460b57cec5SDimitry Andric return false;
24470b57cec5SDimitry Andric
24480b57cec5SDimitry Andric while (Len) {
24490b57cec5SDimitry Andric MVT VT;
2450bdd1243dSDimitry Andric if (!Alignment || *Alignment >= 4) {
24510b57cec5SDimitry Andric if (Len >= 4)
24520b57cec5SDimitry Andric VT = MVT::i32;
24530b57cec5SDimitry Andric else if (Len >= 2)
24540b57cec5SDimitry Andric VT = MVT::i16;
24550b57cec5SDimitry Andric else {
24560b57cec5SDimitry Andric assert(Len == 1 && "Expected a length of 1!");
24570b57cec5SDimitry Andric VT = MVT::i8;
24580b57cec5SDimitry Andric }
24590b57cec5SDimitry Andric } else {
2460bdd1243dSDimitry Andric assert(Alignment && "Alignment is set in this branch");
24610b57cec5SDimitry Andric // Bound based on alignment.
2462bdd1243dSDimitry Andric if (Len >= 2 && *Alignment == 2)
24630b57cec5SDimitry Andric VT = MVT::i16;
24640b57cec5SDimitry Andric else {
24650b57cec5SDimitry Andric VT = MVT::i8;
24660b57cec5SDimitry Andric }
24670b57cec5SDimitry Andric }
24680b57cec5SDimitry Andric
24690b57cec5SDimitry Andric bool RV;
24708bcb0991SDimitry Andric Register ResultReg;
24710b57cec5SDimitry Andric RV = ARMEmitLoad(VT, ResultReg, Src);
24720b57cec5SDimitry Andric assert(RV && "Should be able to handle this load.");
24730b57cec5SDimitry Andric RV = ARMEmitStore(VT, ResultReg, Dest);
24740b57cec5SDimitry Andric assert(RV && "Should be able to handle this store.");
24750b57cec5SDimitry Andric (void)RV;
24760b57cec5SDimitry Andric
24770b57cec5SDimitry Andric unsigned Size = VT.getSizeInBits()/8;
24780b57cec5SDimitry Andric Len -= Size;
24790b57cec5SDimitry Andric Dest.Offset += Size;
24800b57cec5SDimitry Andric Src.Offset += Size;
24810b57cec5SDimitry Andric }
24820b57cec5SDimitry Andric
24830b57cec5SDimitry Andric return true;
24840b57cec5SDimitry Andric }
24850b57cec5SDimitry Andric
SelectIntrinsicCall(const IntrinsicInst & I)24860b57cec5SDimitry Andric bool ARMFastISel::SelectIntrinsicCall(const IntrinsicInst &I) {
24870b57cec5SDimitry Andric // FIXME: Handle more intrinsics.
24880b57cec5SDimitry Andric switch (I.getIntrinsicID()) {
24890b57cec5SDimitry Andric default: return false;
24900b57cec5SDimitry Andric case Intrinsic::frameaddress: {
24910b57cec5SDimitry Andric MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
24920b57cec5SDimitry Andric MFI.setFrameAddressIsTaken(true);
24930b57cec5SDimitry Andric
24940b57cec5SDimitry Andric unsigned LdrOpc = isThumb2 ? ARM::t2LDRi12 : ARM::LDRi12;
24950b57cec5SDimitry Andric const TargetRegisterClass *RC = isThumb2 ? &ARM::tGPRRegClass
24960b57cec5SDimitry Andric : &ARM::GPRRegClass;
24970b57cec5SDimitry Andric
24980b57cec5SDimitry Andric const ARMBaseRegisterInfo *RegInfo =
24990b57cec5SDimitry Andric static_cast<const ARMBaseRegisterInfo *>(Subtarget->getRegisterInfo());
25008bcb0991SDimitry Andric Register FramePtr = RegInfo->getFrameRegister(*(FuncInfo.MF));
25010b57cec5SDimitry Andric unsigned SrcReg = FramePtr;
25020b57cec5SDimitry Andric
25030b57cec5SDimitry Andric // Recursively load frame address
25040b57cec5SDimitry Andric // ldr r0 [fp]
25050b57cec5SDimitry Andric // ldr r0 [r0]
25060b57cec5SDimitry Andric // ldr r0 [r0]
25070b57cec5SDimitry Andric // ...
25080b57cec5SDimitry Andric unsigned DestReg;
25090b57cec5SDimitry Andric unsigned Depth = cast<ConstantInt>(I.getOperand(0))->getZExtValue();
25100b57cec5SDimitry Andric while (Depth--) {
25110b57cec5SDimitry Andric DestReg = createResultReg(RC);
2512bdd1243dSDimitry Andric AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
25130b57cec5SDimitry Andric TII.get(LdrOpc), DestReg)
25140b57cec5SDimitry Andric .addReg(SrcReg).addImm(0));
25150b57cec5SDimitry Andric SrcReg = DestReg;
25160b57cec5SDimitry Andric }
25170b57cec5SDimitry Andric updateValueMap(&I, SrcReg);
25180b57cec5SDimitry Andric return true;
25190b57cec5SDimitry Andric }
25200b57cec5SDimitry Andric case Intrinsic::memcpy:
25210b57cec5SDimitry Andric case Intrinsic::memmove: {
25220b57cec5SDimitry Andric const MemTransferInst &MTI = cast<MemTransferInst>(I);
25230b57cec5SDimitry Andric // Don't handle volatile.
25240b57cec5SDimitry Andric if (MTI.isVolatile())
25250b57cec5SDimitry Andric return false;
25260b57cec5SDimitry Andric
25270b57cec5SDimitry Andric // Disable inlining for memmove before calls to ComputeAddress. Otherwise,
25280b57cec5SDimitry Andric // we would emit dead code because we don't currently handle memmoves.
25290b57cec5SDimitry Andric bool isMemCpy = (I.getIntrinsicID() == Intrinsic::memcpy);
25300b57cec5SDimitry Andric if (isa<ConstantInt>(MTI.getLength()) && isMemCpy) {
25310b57cec5SDimitry Andric // Small memcpy's are common enough that we want to do them without a call
25320b57cec5SDimitry Andric // if possible.
25330b57cec5SDimitry Andric uint64_t Len = cast<ConstantInt>(MTI.getLength())->getZExtValue();
25340b57cec5SDimitry Andric if (ARMIsMemCpySmall(Len)) {
25350b57cec5SDimitry Andric Address Dest, Src;
25360b57cec5SDimitry Andric if (!ARMComputeAddress(MTI.getRawDest(), Dest) ||
25370b57cec5SDimitry Andric !ARMComputeAddress(MTI.getRawSource(), Src))
25380b57cec5SDimitry Andric return false;
2539bdd1243dSDimitry Andric MaybeAlign Alignment;
2540bdd1243dSDimitry Andric if (MTI.getDestAlign() || MTI.getSourceAlign())
2541bdd1243dSDimitry Andric Alignment = std::min(MTI.getDestAlign().valueOrOne(),
2542bdd1243dSDimitry Andric MTI.getSourceAlign().valueOrOne());
25430b57cec5SDimitry Andric if (ARMTryEmitSmallMemCpy(Dest, Src, Len, Alignment))
25440b57cec5SDimitry Andric return true;
25450b57cec5SDimitry Andric }
25460b57cec5SDimitry Andric }
25470b57cec5SDimitry Andric
25480b57cec5SDimitry Andric if (!MTI.getLength()->getType()->isIntegerTy(32))
25490b57cec5SDimitry Andric return false;
25500b57cec5SDimitry Andric
25510b57cec5SDimitry Andric if (MTI.getSourceAddressSpace() > 255 || MTI.getDestAddressSpace() > 255)
25520b57cec5SDimitry Andric return false;
25530b57cec5SDimitry Andric
25540b57cec5SDimitry Andric const char *IntrMemName = isa<MemCpyInst>(I) ? "memcpy" : "memmove";
25550b57cec5SDimitry Andric return SelectCall(&I, IntrMemName);
25560b57cec5SDimitry Andric }
25570b57cec5SDimitry Andric case Intrinsic::memset: {
25580b57cec5SDimitry Andric const MemSetInst &MSI = cast<MemSetInst>(I);
25590b57cec5SDimitry Andric // Don't handle volatile.
25600b57cec5SDimitry Andric if (MSI.isVolatile())
25610b57cec5SDimitry Andric return false;
25620b57cec5SDimitry Andric
25630b57cec5SDimitry Andric if (!MSI.getLength()->getType()->isIntegerTy(32))
25640b57cec5SDimitry Andric return false;
25650b57cec5SDimitry Andric
25660b57cec5SDimitry Andric if (MSI.getDestAddressSpace() > 255)
25670b57cec5SDimitry Andric return false;
25680b57cec5SDimitry Andric
25690b57cec5SDimitry Andric return SelectCall(&I, "memset");
25700b57cec5SDimitry Andric }
25710b57cec5SDimitry Andric case Intrinsic::trap: {
2572480093f4SDimitry Andric unsigned Opcode;
2573480093f4SDimitry Andric if (Subtarget->isThumb())
2574480093f4SDimitry Andric Opcode = ARM::tTRAP;
2575480093f4SDimitry Andric else
2576480093f4SDimitry Andric Opcode = Subtarget->useNaClTrap() ? ARM::TRAPNaCl : ARM::TRAP;
2577bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opcode));
25780b57cec5SDimitry Andric return true;
25790b57cec5SDimitry Andric }
25800b57cec5SDimitry Andric }
25810b57cec5SDimitry Andric }
25820b57cec5SDimitry Andric
SelectTrunc(const Instruction * I)25830b57cec5SDimitry Andric bool ARMFastISel::SelectTrunc(const Instruction *I) {
25840b57cec5SDimitry Andric // The high bits for a type smaller than the register size are assumed to be
25850b57cec5SDimitry Andric // undefined.
25860b57cec5SDimitry Andric Value *Op = I->getOperand(0);
25870b57cec5SDimitry Andric
25880b57cec5SDimitry Andric EVT SrcVT, DestVT;
25890b57cec5SDimitry Andric SrcVT = TLI.getValueType(DL, Op->getType(), true);
25900b57cec5SDimitry Andric DestVT = TLI.getValueType(DL, I->getType(), true);
25910b57cec5SDimitry Andric
25920b57cec5SDimitry Andric if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8)
25930b57cec5SDimitry Andric return false;
25940b57cec5SDimitry Andric if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1)
25950b57cec5SDimitry Andric return false;
25960b57cec5SDimitry Andric
259704eeddc0SDimitry Andric Register SrcReg = getRegForValue(Op);
25980b57cec5SDimitry Andric if (!SrcReg) return false;
25990b57cec5SDimitry Andric
26000b57cec5SDimitry Andric // Because the high bits are undefined, a truncate doesn't generate
26010b57cec5SDimitry Andric // any code.
26020b57cec5SDimitry Andric updateValueMap(I, SrcReg);
26030b57cec5SDimitry Andric return true;
26040b57cec5SDimitry Andric }
26050b57cec5SDimitry Andric
ARMEmitIntExt(MVT SrcVT,unsigned SrcReg,MVT DestVT,bool isZExt)26060b57cec5SDimitry Andric unsigned ARMFastISel::ARMEmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
26070b57cec5SDimitry Andric bool isZExt) {
26080b57cec5SDimitry Andric if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8)
26090b57cec5SDimitry Andric return 0;
26100b57cec5SDimitry Andric if (SrcVT != MVT::i16 && SrcVT != MVT::i8 && SrcVT != MVT::i1)
26110b57cec5SDimitry Andric return 0;
26120b57cec5SDimitry Andric
26130b57cec5SDimitry Andric // Table of which combinations can be emitted as a single instruction,
26140b57cec5SDimitry Andric // and which will require two.
26150b57cec5SDimitry Andric static const uint8_t isSingleInstrTbl[3][2][2][2] = {
26160b57cec5SDimitry Andric // ARM Thumb
26170b57cec5SDimitry Andric // !hasV6Ops hasV6Ops !hasV6Ops hasV6Ops
26180b57cec5SDimitry Andric // ext: s z s z s z s z
26190b57cec5SDimitry Andric /* 1 */ { { { 0, 1 }, { 0, 1 } }, { { 0, 0 }, { 0, 1 } } },
26200b57cec5SDimitry Andric /* 8 */ { { { 0, 1 }, { 1, 1 } }, { { 0, 0 }, { 1, 1 } } },
26210b57cec5SDimitry Andric /* 16 */ { { { 0, 0 }, { 1, 1 } }, { { 0, 0 }, { 1, 1 } } }
26220b57cec5SDimitry Andric };
26230b57cec5SDimitry Andric
26240b57cec5SDimitry Andric // Target registers for:
26250b57cec5SDimitry Andric // - For ARM can never be PC.
26260b57cec5SDimitry Andric // - For 16-bit Thumb are restricted to lower 8 registers.
26270b57cec5SDimitry Andric // - For 32-bit Thumb are restricted to non-SP and non-PC.
26280b57cec5SDimitry Andric static const TargetRegisterClass *RCTbl[2][2] = {
26290b57cec5SDimitry Andric // Instructions: Two Single
26300b57cec5SDimitry Andric /* ARM */ { &ARM::GPRnopcRegClass, &ARM::GPRnopcRegClass },
26310b57cec5SDimitry Andric /* Thumb */ { &ARM::tGPRRegClass, &ARM::rGPRRegClass }
26320b57cec5SDimitry Andric };
26330b57cec5SDimitry Andric
26340b57cec5SDimitry Andric // Table governing the instruction(s) to be emitted.
26350b57cec5SDimitry Andric static const struct InstructionTable {
26360b57cec5SDimitry Andric uint32_t Opc : 16;
26370b57cec5SDimitry Andric uint32_t hasS : 1; // Some instructions have an S bit, always set it to 0.
26380b57cec5SDimitry Andric uint32_t Shift : 7; // For shift operand addressing mode, used by MOVsi.
26390b57cec5SDimitry Andric uint32_t Imm : 8; // All instructions have either a shift or a mask.
26400b57cec5SDimitry Andric } IT[2][2][3][2] = {
26410b57cec5SDimitry Andric { // Two instructions (first is left shift, second is in this table).
26420b57cec5SDimitry Andric { // ARM Opc S Shift Imm
26430b57cec5SDimitry Andric /* 1 bit sext */ { { ARM::MOVsi , 1, ARM_AM::asr , 31 },
26440b57cec5SDimitry Andric /* 1 bit zext */ { ARM::MOVsi , 1, ARM_AM::lsr , 31 } },
26450b57cec5SDimitry Andric /* 8 bit sext */ { { ARM::MOVsi , 1, ARM_AM::asr , 24 },
26460b57cec5SDimitry Andric /* 8 bit zext */ { ARM::MOVsi , 1, ARM_AM::lsr , 24 } },
26470b57cec5SDimitry Andric /* 16 bit sext */ { { ARM::MOVsi , 1, ARM_AM::asr , 16 },
26480b57cec5SDimitry Andric /* 16 bit zext */ { ARM::MOVsi , 1, ARM_AM::lsr , 16 } }
26490b57cec5SDimitry Andric },
26500b57cec5SDimitry Andric { // Thumb Opc S Shift Imm
26510b57cec5SDimitry Andric /* 1 bit sext */ { { ARM::tASRri , 0, ARM_AM::no_shift, 31 },
26520b57cec5SDimitry Andric /* 1 bit zext */ { ARM::tLSRri , 0, ARM_AM::no_shift, 31 } },
26530b57cec5SDimitry Andric /* 8 bit sext */ { { ARM::tASRri , 0, ARM_AM::no_shift, 24 },
26540b57cec5SDimitry Andric /* 8 bit zext */ { ARM::tLSRri , 0, ARM_AM::no_shift, 24 } },
26550b57cec5SDimitry Andric /* 16 bit sext */ { { ARM::tASRri , 0, ARM_AM::no_shift, 16 },
26560b57cec5SDimitry Andric /* 16 bit zext */ { ARM::tLSRri , 0, ARM_AM::no_shift, 16 } }
26570b57cec5SDimitry Andric }
26580b57cec5SDimitry Andric },
26590b57cec5SDimitry Andric { // Single instruction.
26600b57cec5SDimitry Andric { // ARM Opc S Shift Imm
26610b57cec5SDimitry Andric /* 1 bit sext */ { { ARM::KILL , 0, ARM_AM::no_shift, 0 },
26620b57cec5SDimitry Andric /* 1 bit zext */ { ARM::ANDri , 1, ARM_AM::no_shift, 1 } },
26630b57cec5SDimitry Andric /* 8 bit sext */ { { ARM::SXTB , 0, ARM_AM::no_shift, 0 },
26640b57cec5SDimitry Andric /* 8 bit zext */ { ARM::ANDri , 1, ARM_AM::no_shift, 255 } },
26650b57cec5SDimitry Andric /* 16 bit sext */ { { ARM::SXTH , 0, ARM_AM::no_shift, 0 },
26660b57cec5SDimitry Andric /* 16 bit zext */ { ARM::UXTH , 0, ARM_AM::no_shift, 0 } }
26670b57cec5SDimitry Andric },
26680b57cec5SDimitry Andric { // Thumb Opc S Shift Imm
26690b57cec5SDimitry Andric /* 1 bit sext */ { { ARM::KILL , 0, ARM_AM::no_shift, 0 },
26700b57cec5SDimitry Andric /* 1 bit zext */ { ARM::t2ANDri, 1, ARM_AM::no_shift, 1 } },
26710b57cec5SDimitry Andric /* 8 bit sext */ { { ARM::t2SXTB , 0, ARM_AM::no_shift, 0 },
26720b57cec5SDimitry Andric /* 8 bit zext */ { ARM::t2ANDri, 1, ARM_AM::no_shift, 255 } },
26730b57cec5SDimitry Andric /* 16 bit sext */ { { ARM::t2SXTH , 0, ARM_AM::no_shift, 0 },
26740b57cec5SDimitry Andric /* 16 bit zext */ { ARM::t2UXTH , 0, ARM_AM::no_shift, 0 } }
26750b57cec5SDimitry Andric }
26760b57cec5SDimitry Andric }
26770b57cec5SDimitry Andric };
26780b57cec5SDimitry Andric
26790b57cec5SDimitry Andric unsigned SrcBits = SrcVT.getSizeInBits();
26800b57cec5SDimitry Andric unsigned DestBits = DestVT.getSizeInBits();
26810b57cec5SDimitry Andric (void) DestBits;
26820b57cec5SDimitry Andric assert((SrcBits < DestBits) && "can only extend to larger types");
26830b57cec5SDimitry Andric assert((DestBits == 32 || DestBits == 16 || DestBits == 8) &&
26840b57cec5SDimitry Andric "other sizes unimplemented");
26850b57cec5SDimitry Andric assert((SrcBits == 16 || SrcBits == 8 || SrcBits == 1) &&
26860b57cec5SDimitry Andric "other sizes unimplemented");
26870b57cec5SDimitry Andric
26880b57cec5SDimitry Andric bool hasV6Ops = Subtarget->hasV6Ops();
26890b57cec5SDimitry Andric unsigned Bitness = SrcBits / 8; // {1,8,16}=>{0,1,2}
26900b57cec5SDimitry Andric assert((Bitness < 3) && "sanity-check table bounds");
26910b57cec5SDimitry Andric
26920b57cec5SDimitry Andric bool isSingleInstr = isSingleInstrTbl[Bitness][isThumb2][hasV6Ops][isZExt];
26930b57cec5SDimitry Andric const TargetRegisterClass *RC = RCTbl[isThumb2][isSingleInstr];
26940b57cec5SDimitry Andric const InstructionTable *ITP = &IT[isSingleInstr][isThumb2][Bitness][isZExt];
26950b57cec5SDimitry Andric unsigned Opc = ITP->Opc;
26960b57cec5SDimitry Andric assert(ARM::KILL != Opc && "Invalid table entry");
26970b57cec5SDimitry Andric unsigned hasS = ITP->hasS;
26980b57cec5SDimitry Andric ARM_AM::ShiftOpc Shift = (ARM_AM::ShiftOpc) ITP->Shift;
26990b57cec5SDimitry Andric assert(((Shift == ARM_AM::no_shift) == (Opc != ARM::MOVsi)) &&
27000b57cec5SDimitry Andric "only MOVsi has shift operand addressing mode");
27010b57cec5SDimitry Andric unsigned Imm = ITP->Imm;
27020b57cec5SDimitry Andric
27030b57cec5SDimitry Andric // 16-bit Thumb instructions always set CPSR (unless they're in an IT block).
27040b57cec5SDimitry Andric bool setsCPSR = &ARM::tGPRRegClass == RC;
27050b57cec5SDimitry Andric unsigned LSLOpc = isThumb2 ? ARM::tLSLri : ARM::MOVsi;
27060b57cec5SDimitry Andric unsigned ResultReg;
27070b57cec5SDimitry Andric // MOVsi encodes shift and immediate in shift operand addressing mode.
27080b57cec5SDimitry Andric // The following condition has the same value when emitting two
27090b57cec5SDimitry Andric // instruction sequences: both are shifts.
27100b57cec5SDimitry Andric bool ImmIsSO = (Shift != ARM_AM::no_shift);
27110b57cec5SDimitry Andric
27120b57cec5SDimitry Andric // Either one or two instructions are emitted.
27130b57cec5SDimitry Andric // They're always of the form:
27140b57cec5SDimitry Andric // dst = in OP imm
27150b57cec5SDimitry Andric // CPSR is set only by 16-bit Thumb instructions.
27160b57cec5SDimitry Andric // Predicate, if any, is AL.
27170b57cec5SDimitry Andric // S bit, if available, is always 0.
27180b57cec5SDimitry Andric // When two are emitted the first's result will feed as the second's input,
27190b57cec5SDimitry Andric // that value is then dead.
27200b57cec5SDimitry Andric unsigned NumInstrsEmitted = isSingleInstr ? 1 : 2;
27210b57cec5SDimitry Andric for (unsigned Instr = 0; Instr != NumInstrsEmitted; ++Instr) {
27220b57cec5SDimitry Andric ResultReg = createResultReg(RC);
27230b57cec5SDimitry Andric bool isLsl = (0 == Instr) && !isSingleInstr;
27240b57cec5SDimitry Andric unsigned Opcode = isLsl ? LSLOpc : Opc;
27250b57cec5SDimitry Andric ARM_AM::ShiftOpc ShiftAM = isLsl ? ARM_AM::lsl : Shift;
27260b57cec5SDimitry Andric unsigned ImmEnc = ImmIsSO ? ARM_AM::getSORegOpc(ShiftAM, Imm) : Imm;
27270b57cec5SDimitry Andric bool isKill = 1 == Instr;
27280b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(
2729bdd1243dSDimitry Andric *FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opcode), ResultReg);
27300b57cec5SDimitry Andric if (setsCPSR)
27310b57cec5SDimitry Andric MIB.addReg(ARM::CPSR, RegState::Define);
27320b57cec5SDimitry Andric SrcReg = constrainOperandRegClass(TII.get(Opcode), SrcReg, 1 + setsCPSR);
27330b57cec5SDimitry Andric MIB.addReg(SrcReg, isKill * RegState::Kill)
27340b57cec5SDimitry Andric .addImm(ImmEnc)
27350b57cec5SDimitry Andric .add(predOps(ARMCC::AL));
27360b57cec5SDimitry Andric if (hasS)
27370b57cec5SDimitry Andric MIB.add(condCodeOp());
27380b57cec5SDimitry Andric // Second instruction consumes the first's result.
27390b57cec5SDimitry Andric SrcReg = ResultReg;
27400b57cec5SDimitry Andric }
27410b57cec5SDimitry Andric
27420b57cec5SDimitry Andric return ResultReg;
27430b57cec5SDimitry Andric }
27440b57cec5SDimitry Andric
SelectIntExt(const Instruction * I)27450b57cec5SDimitry Andric bool ARMFastISel::SelectIntExt(const Instruction *I) {
27460b57cec5SDimitry Andric // On ARM, in general, integer casts don't involve legal types; this code
27470b57cec5SDimitry Andric // handles promotable integers.
27480b57cec5SDimitry Andric Type *DestTy = I->getType();
27490b57cec5SDimitry Andric Value *Src = I->getOperand(0);
27500b57cec5SDimitry Andric Type *SrcTy = Src->getType();
27510b57cec5SDimitry Andric
27520b57cec5SDimitry Andric bool isZExt = isa<ZExtInst>(I);
275304eeddc0SDimitry Andric Register SrcReg = getRegForValue(Src);
27540b57cec5SDimitry Andric if (!SrcReg) return false;
27550b57cec5SDimitry Andric
27560b57cec5SDimitry Andric EVT SrcEVT, DestEVT;
27570b57cec5SDimitry Andric SrcEVT = TLI.getValueType(DL, SrcTy, true);
27580b57cec5SDimitry Andric DestEVT = TLI.getValueType(DL, DestTy, true);
27590b57cec5SDimitry Andric if (!SrcEVT.isSimple()) return false;
27600b57cec5SDimitry Andric if (!DestEVT.isSimple()) return false;
27610b57cec5SDimitry Andric
27620b57cec5SDimitry Andric MVT SrcVT = SrcEVT.getSimpleVT();
27630b57cec5SDimitry Andric MVT DestVT = DestEVT.getSimpleVT();
27640b57cec5SDimitry Andric unsigned ResultReg = ARMEmitIntExt(SrcVT, SrcReg, DestVT, isZExt);
27650b57cec5SDimitry Andric if (ResultReg == 0) return false;
27660b57cec5SDimitry Andric updateValueMap(I, ResultReg);
27670b57cec5SDimitry Andric return true;
27680b57cec5SDimitry Andric }
27690b57cec5SDimitry Andric
SelectShift(const Instruction * I,ARM_AM::ShiftOpc ShiftTy)27700b57cec5SDimitry Andric bool ARMFastISel::SelectShift(const Instruction *I,
27710b57cec5SDimitry Andric ARM_AM::ShiftOpc ShiftTy) {
27720b57cec5SDimitry Andric // We handle thumb2 mode by target independent selector
27730b57cec5SDimitry Andric // or SelectionDAG ISel.
27740b57cec5SDimitry Andric if (isThumb2)
27750b57cec5SDimitry Andric return false;
27760b57cec5SDimitry Andric
27770b57cec5SDimitry Andric // Only handle i32 now.
27780b57cec5SDimitry Andric EVT DestVT = TLI.getValueType(DL, I->getType(), true);
27790b57cec5SDimitry Andric if (DestVT != MVT::i32)
27800b57cec5SDimitry Andric return false;
27810b57cec5SDimitry Andric
27820b57cec5SDimitry Andric unsigned Opc = ARM::MOVsr;
27830b57cec5SDimitry Andric unsigned ShiftImm;
27840b57cec5SDimitry Andric Value *Src2Value = I->getOperand(1);
27850b57cec5SDimitry Andric if (const ConstantInt *CI = dyn_cast<ConstantInt>(Src2Value)) {
27860b57cec5SDimitry Andric ShiftImm = CI->getZExtValue();
27870b57cec5SDimitry Andric
27880b57cec5SDimitry Andric // Fall back to selection DAG isel if the shift amount
27890b57cec5SDimitry Andric // is zero or greater than the width of the value type.
27900b57cec5SDimitry Andric if (ShiftImm == 0 || ShiftImm >=32)
27910b57cec5SDimitry Andric return false;
27920b57cec5SDimitry Andric
27930b57cec5SDimitry Andric Opc = ARM::MOVsi;
27940b57cec5SDimitry Andric }
27950b57cec5SDimitry Andric
27960b57cec5SDimitry Andric Value *Src1Value = I->getOperand(0);
279704eeddc0SDimitry Andric Register Reg1 = getRegForValue(Src1Value);
27980b57cec5SDimitry Andric if (Reg1 == 0) return false;
27990b57cec5SDimitry Andric
28000b57cec5SDimitry Andric unsigned Reg2 = 0;
28010b57cec5SDimitry Andric if (Opc == ARM::MOVsr) {
28020b57cec5SDimitry Andric Reg2 = getRegForValue(Src2Value);
28030b57cec5SDimitry Andric if (Reg2 == 0) return false;
28040b57cec5SDimitry Andric }
28050b57cec5SDimitry Andric
280604eeddc0SDimitry Andric Register ResultReg = createResultReg(&ARM::GPRnopcRegClass);
28070b57cec5SDimitry Andric if(ResultReg == 0) return false;
28080b57cec5SDimitry Andric
2809bdd1243dSDimitry Andric MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
28100b57cec5SDimitry Andric TII.get(Opc), ResultReg)
28110b57cec5SDimitry Andric .addReg(Reg1);
28120b57cec5SDimitry Andric
28130b57cec5SDimitry Andric if (Opc == ARM::MOVsi)
28140b57cec5SDimitry Andric MIB.addImm(ARM_AM::getSORegOpc(ShiftTy, ShiftImm));
28150b57cec5SDimitry Andric else if (Opc == ARM::MOVsr) {
28160b57cec5SDimitry Andric MIB.addReg(Reg2);
28170b57cec5SDimitry Andric MIB.addImm(ARM_AM::getSORegOpc(ShiftTy, 0));
28180b57cec5SDimitry Andric }
28190b57cec5SDimitry Andric
28200b57cec5SDimitry Andric AddOptionalDefs(MIB);
28210b57cec5SDimitry Andric updateValueMap(I, ResultReg);
28220b57cec5SDimitry Andric return true;
28230b57cec5SDimitry Andric }
28240b57cec5SDimitry Andric
28250b57cec5SDimitry Andric // TODO: SoftFP support.
fastSelectInstruction(const Instruction * I)28260b57cec5SDimitry Andric bool ARMFastISel::fastSelectInstruction(const Instruction *I) {
28270b57cec5SDimitry Andric switch (I->getOpcode()) {
28280b57cec5SDimitry Andric case Instruction::Load:
28290b57cec5SDimitry Andric return SelectLoad(I);
28300b57cec5SDimitry Andric case Instruction::Store:
28310b57cec5SDimitry Andric return SelectStore(I);
28320b57cec5SDimitry Andric case Instruction::Br:
28330b57cec5SDimitry Andric return SelectBranch(I);
28340b57cec5SDimitry Andric case Instruction::IndirectBr:
28350b57cec5SDimitry Andric return SelectIndirectBr(I);
28360b57cec5SDimitry Andric case Instruction::ICmp:
28370b57cec5SDimitry Andric case Instruction::FCmp:
28380b57cec5SDimitry Andric return SelectCmp(I);
28390b57cec5SDimitry Andric case Instruction::FPExt:
28400b57cec5SDimitry Andric return SelectFPExt(I);
28410b57cec5SDimitry Andric case Instruction::FPTrunc:
28420b57cec5SDimitry Andric return SelectFPTrunc(I);
28430b57cec5SDimitry Andric case Instruction::SIToFP:
28440b57cec5SDimitry Andric return SelectIToFP(I, /*isSigned*/ true);
28450b57cec5SDimitry Andric case Instruction::UIToFP:
28460b57cec5SDimitry Andric return SelectIToFP(I, /*isSigned*/ false);
28470b57cec5SDimitry Andric case Instruction::FPToSI:
28480b57cec5SDimitry Andric return SelectFPToI(I, /*isSigned*/ true);
28490b57cec5SDimitry Andric case Instruction::FPToUI:
28500b57cec5SDimitry Andric return SelectFPToI(I, /*isSigned*/ false);
28510b57cec5SDimitry Andric case Instruction::Add:
28520b57cec5SDimitry Andric return SelectBinaryIntOp(I, ISD::ADD);
28530b57cec5SDimitry Andric case Instruction::Or:
28540b57cec5SDimitry Andric return SelectBinaryIntOp(I, ISD::OR);
28550b57cec5SDimitry Andric case Instruction::Sub:
28560b57cec5SDimitry Andric return SelectBinaryIntOp(I, ISD::SUB);
28570b57cec5SDimitry Andric case Instruction::FAdd:
28580b57cec5SDimitry Andric return SelectBinaryFPOp(I, ISD::FADD);
28590b57cec5SDimitry Andric case Instruction::FSub:
28600b57cec5SDimitry Andric return SelectBinaryFPOp(I, ISD::FSUB);
28610b57cec5SDimitry Andric case Instruction::FMul:
28620b57cec5SDimitry Andric return SelectBinaryFPOp(I, ISD::FMUL);
28630b57cec5SDimitry Andric case Instruction::SDiv:
28640b57cec5SDimitry Andric return SelectDiv(I, /*isSigned*/ true);
28650b57cec5SDimitry Andric case Instruction::UDiv:
28660b57cec5SDimitry Andric return SelectDiv(I, /*isSigned*/ false);
28670b57cec5SDimitry Andric case Instruction::SRem:
28680b57cec5SDimitry Andric return SelectRem(I, /*isSigned*/ true);
28690b57cec5SDimitry Andric case Instruction::URem:
28700b57cec5SDimitry Andric return SelectRem(I, /*isSigned*/ false);
28710b57cec5SDimitry Andric case Instruction::Call:
28720b57cec5SDimitry Andric if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I))
28730b57cec5SDimitry Andric return SelectIntrinsicCall(*II);
28740b57cec5SDimitry Andric return SelectCall(I);
28750b57cec5SDimitry Andric case Instruction::Select:
28760b57cec5SDimitry Andric return SelectSelect(I);
28770b57cec5SDimitry Andric case Instruction::Ret:
28780b57cec5SDimitry Andric return SelectRet(I);
28790b57cec5SDimitry Andric case Instruction::Trunc:
28800b57cec5SDimitry Andric return SelectTrunc(I);
28810b57cec5SDimitry Andric case Instruction::ZExt:
28820b57cec5SDimitry Andric case Instruction::SExt:
28830b57cec5SDimitry Andric return SelectIntExt(I);
28840b57cec5SDimitry Andric case Instruction::Shl:
28850b57cec5SDimitry Andric return SelectShift(I, ARM_AM::lsl);
28860b57cec5SDimitry Andric case Instruction::LShr:
28870b57cec5SDimitry Andric return SelectShift(I, ARM_AM::lsr);
28880b57cec5SDimitry Andric case Instruction::AShr:
28890b57cec5SDimitry Andric return SelectShift(I, ARM_AM::asr);
28900b57cec5SDimitry Andric default: break;
28910b57cec5SDimitry Andric }
28920b57cec5SDimitry Andric return false;
28930b57cec5SDimitry Andric }
28940b57cec5SDimitry Andric
28950b57cec5SDimitry Andric // This table describes sign- and zero-extend instructions which can be
28960b57cec5SDimitry Andric // folded into a preceding load. All of these extends have an immediate
28970b57cec5SDimitry Andric // (sometimes a mask and sometimes a shift) that's applied after
28980b57cec5SDimitry Andric // extension.
28990b57cec5SDimitry Andric static const struct FoldableLoadExtendsStruct {
29000b57cec5SDimitry Andric uint16_t Opc[2]; // ARM, Thumb.
29010b57cec5SDimitry Andric uint8_t ExpectedImm;
29020b57cec5SDimitry Andric uint8_t isZExt : 1;
29030b57cec5SDimitry Andric uint8_t ExpectedVT : 7;
29040b57cec5SDimitry Andric } FoldableLoadExtends[] = {
29050b57cec5SDimitry Andric { { ARM::SXTH, ARM::t2SXTH }, 0, 0, MVT::i16 },
29060b57cec5SDimitry Andric { { ARM::UXTH, ARM::t2UXTH }, 0, 1, MVT::i16 },
29070b57cec5SDimitry Andric { { ARM::ANDri, ARM::t2ANDri }, 255, 1, MVT::i8 },
29080b57cec5SDimitry Andric { { ARM::SXTB, ARM::t2SXTB }, 0, 0, MVT::i8 },
29090b57cec5SDimitry Andric { { ARM::UXTB, ARM::t2UXTB }, 0, 1, MVT::i8 }
29100b57cec5SDimitry Andric };
29110b57cec5SDimitry Andric
29120b57cec5SDimitry Andric /// The specified machine instr operand is a vreg, and that
29130b57cec5SDimitry Andric /// vreg is being provided by the specified load instruction. If possible,
29140b57cec5SDimitry Andric /// try to fold the load as an operand to the instruction, returning true if
29150b57cec5SDimitry Andric /// successful.
tryToFoldLoadIntoMI(MachineInstr * MI,unsigned OpNo,const LoadInst * LI)29160b57cec5SDimitry Andric bool ARMFastISel::tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
29170b57cec5SDimitry Andric const LoadInst *LI) {
29180b57cec5SDimitry Andric // Verify we have a legal type before going any further.
29190b57cec5SDimitry Andric MVT VT;
29200b57cec5SDimitry Andric if (!isLoadTypeLegal(LI->getType(), VT))
29210b57cec5SDimitry Andric return false;
29220b57cec5SDimitry Andric
29230b57cec5SDimitry Andric // Combine load followed by zero- or sign-extend.
29240b57cec5SDimitry Andric // ldrb r1, [r0] ldrb r1, [r0]
29250b57cec5SDimitry Andric // uxtb r2, r1 =>
29260b57cec5SDimitry Andric // mov r3, r2 mov r3, r1
29270b57cec5SDimitry Andric if (MI->getNumOperands() < 3 || !MI->getOperand(2).isImm())
29280b57cec5SDimitry Andric return false;
29290b57cec5SDimitry Andric const uint64_t Imm = MI->getOperand(2).getImm();
29300b57cec5SDimitry Andric
29310b57cec5SDimitry Andric bool Found = false;
29320b57cec5SDimitry Andric bool isZExt;
29330b57cec5SDimitry Andric for (const FoldableLoadExtendsStruct &FLE : FoldableLoadExtends) {
29340b57cec5SDimitry Andric if (FLE.Opc[isThumb2] == MI->getOpcode() &&
29350b57cec5SDimitry Andric (uint64_t)FLE.ExpectedImm == Imm &&
29360b57cec5SDimitry Andric MVT((MVT::SimpleValueType)FLE.ExpectedVT) == VT) {
29370b57cec5SDimitry Andric Found = true;
29380b57cec5SDimitry Andric isZExt = FLE.isZExt;
29390b57cec5SDimitry Andric }
29400b57cec5SDimitry Andric }
29410b57cec5SDimitry Andric if (!Found) return false;
29420b57cec5SDimitry Andric
29430b57cec5SDimitry Andric // See if we can handle this address.
29440b57cec5SDimitry Andric Address Addr;
29450b57cec5SDimitry Andric if (!ARMComputeAddress(LI->getOperand(0), Addr)) return false;
29460b57cec5SDimitry Andric
29478bcb0991SDimitry Andric Register ResultReg = MI->getOperand(0).getReg();
294881ad6265SDimitry Andric if (!ARMEmitLoad(VT, ResultReg, Addr, LI->getAlign(), isZExt, false))
29490b57cec5SDimitry Andric return false;
29500b57cec5SDimitry Andric MachineBasicBlock::iterator I(MI);
29510b57cec5SDimitry Andric removeDeadCode(I, std::next(I));
29520b57cec5SDimitry Andric return true;
29530b57cec5SDimitry Andric }
29540b57cec5SDimitry Andric
ARMLowerPICELF(const GlobalValue * GV,MVT VT)29555ffd83dbSDimitry Andric unsigned ARMFastISel::ARMLowerPICELF(const GlobalValue *GV, MVT VT) {
2956*0fca6ea1SDimitry Andric bool UseGOT_PREL = !GV->isDSOLocal();
29570b57cec5SDimitry Andric LLVMContext *Context = &MF->getFunction().getContext();
29580b57cec5SDimitry Andric unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
29590b57cec5SDimitry Andric unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
29600b57cec5SDimitry Andric ARMConstantPoolValue *CPV = ARMConstantPoolConstant::Create(
29610b57cec5SDimitry Andric GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj,
29620b57cec5SDimitry Andric UseGOT_PREL ? ARMCP::GOT_PREL : ARMCP::no_modifier,
29630b57cec5SDimitry Andric /*AddCurrentAddress=*/UseGOT_PREL);
29640b57cec5SDimitry Andric
29655ffd83dbSDimitry Andric Align ConstAlign =
29665f757f3fSDimitry Andric MF->getDataLayout().getPrefTypeAlign(PointerType::get(*Context, 0));
29670b57cec5SDimitry Andric unsigned Idx = MF->getConstantPool()->getConstantPoolIndex(CPV, ConstAlign);
29680b57cec5SDimitry Andric MachineMemOperand *CPMMO =
29690b57cec5SDimitry Andric MF->getMachineMemOperand(MachinePointerInfo::getConstantPool(*MF),
29705ffd83dbSDimitry Andric MachineMemOperand::MOLoad, 4, Align(4));
29710b57cec5SDimitry Andric
29728bcb0991SDimitry Andric Register TempReg = MF->getRegInfo().createVirtualRegister(&ARM::rGPRRegClass);
29730b57cec5SDimitry Andric unsigned Opc = isThumb2 ? ARM::t2LDRpci : ARM::LDRcp;
29740b57cec5SDimitry Andric MachineInstrBuilder MIB =
2975bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), TempReg)
29760b57cec5SDimitry Andric .addConstantPoolIndex(Idx)
29770b57cec5SDimitry Andric .addMemOperand(CPMMO);
29780b57cec5SDimitry Andric if (Opc == ARM::LDRcp)
29790b57cec5SDimitry Andric MIB.addImm(0);
29800b57cec5SDimitry Andric MIB.add(predOps(ARMCC::AL));
29810b57cec5SDimitry Andric
29820b57cec5SDimitry Andric // Fix the address by adding pc.
298304eeddc0SDimitry Andric Register DestReg = createResultReg(TLI.getRegClassFor(VT));
29840b57cec5SDimitry Andric Opc = Subtarget->isThumb() ? ARM::tPICADD : UseGOT_PREL ? ARM::PICLDR
29850b57cec5SDimitry Andric : ARM::PICADD;
29860b57cec5SDimitry Andric DestReg = constrainOperandRegClass(TII.get(Opc), DestReg, 0);
2987bdd1243dSDimitry Andric MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), DestReg)
29880b57cec5SDimitry Andric .addReg(TempReg)
29890b57cec5SDimitry Andric .addImm(ARMPCLabelIndex);
29900b57cec5SDimitry Andric
29910b57cec5SDimitry Andric if (!Subtarget->isThumb())
29920b57cec5SDimitry Andric MIB.add(predOps(ARMCC::AL));
29930b57cec5SDimitry Andric
29940b57cec5SDimitry Andric if (UseGOT_PREL && Subtarget->isThumb()) {
299504eeddc0SDimitry Andric Register NewDestReg = createResultReg(TLI.getRegClassFor(VT));
2996bdd1243dSDimitry Andric MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
29970b57cec5SDimitry Andric TII.get(ARM::t2LDRi12), NewDestReg)
29980b57cec5SDimitry Andric .addReg(DestReg)
29990b57cec5SDimitry Andric .addImm(0);
30000b57cec5SDimitry Andric DestReg = NewDestReg;
30010b57cec5SDimitry Andric AddOptionalDefs(MIB);
30020b57cec5SDimitry Andric }
30030b57cec5SDimitry Andric return DestReg;
30040b57cec5SDimitry Andric }
30050b57cec5SDimitry Andric
fastLowerArguments()30060b57cec5SDimitry Andric bool ARMFastISel::fastLowerArguments() {
30070b57cec5SDimitry Andric if (!FuncInfo.CanLowerReturn)
30080b57cec5SDimitry Andric return false;
30090b57cec5SDimitry Andric
30100b57cec5SDimitry Andric const Function *F = FuncInfo.Fn;
30110b57cec5SDimitry Andric if (F->isVarArg())
30120b57cec5SDimitry Andric return false;
30130b57cec5SDimitry Andric
30140b57cec5SDimitry Andric CallingConv::ID CC = F->getCallingConv();
30150b57cec5SDimitry Andric switch (CC) {
30160b57cec5SDimitry Andric default:
30170b57cec5SDimitry Andric return false;
30180b57cec5SDimitry Andric case CallingConv::Fast:
30190b57cec5SDimitry Andric case CallingConv::C:
30200b57cec5SDimitry Andric case CallingConv::ARM_AAPCS_VFP:
30210b57cec5SDimitry Andric case CallingConv::ARM_AAPCS:
30220b57cec5SDimitry Andric case CallingConv::ARM_APCS:
30230b57cec5SDimitry Andric case CallingConv::Swift:
3024fe6060f1SDimitry Andric case CallingConv::SwiftTail:
30250b57cec5SDimitry Andric break;
30260b57cec5SDimitry Andric }
30270b57cec5SDimitry Andric
30280b57cec5SDimitry Andric // Only handle simple cases. i.e. Up to 4 i8/i16/i32 scalar arguments
30290b57cec5SDimitry Andric // which are passed in r0 - r3.
30300b57cec5SDimitry Andric for (const Argument &Arg : F->args()) {
30310b57cec5SDimitry Andric if (Arg.getArgNo() >= 4)
30320b57cec5SDimitry Andric return false;
30330b57cec5SDimitry Andric
30340b57cec5SDimitry Andric if (Arg.hasAttribute(Attribute::InReg) ||
30350b57cec5SDimitry Andric Arg.hasAttribute(Attribute::StructRet) ||
30360b57cec5SDimitry Andric Arg.hasAttribute(Attribute::SwiftSelf) ||
30370b57cec5SDimitry Andric Arg.hasAttribute(Attribute::SwiftError) ||
30380b57cec5SDimitry Andric Arg.hasAttribute(Attribute::ByVal))
30390b57cec5SDimitry Andric return false;
30400b57cec5SDimitry Andric
30410b57cec5SDimitry Andric Type *ArgTy = Arg.getType();
30420b57cec5SDimitry Andric if (ArgTy->isStructTy() || ArgTy->isArrayTy() || ArgTy->isVectorTy())
30430b57cec5SDimitry Andric return false;
30440b57cec5SDimitry Andric
30450b57cec5SDimitry Andric EVT ArgVT = TLI.getValueType(DL, ArgTy);
30460b57cec5SDimitry Andric if (!ArgVT.isSimple()) return false;
30470b57cec5SDimitry Andric switch (ArgVT.getSimpleVT().SimpleTy) {
30480b57cec5SDimitry Andric case MVT::i8:
30490b57cec5SDimitry Andric case MVT::i16:
30500b57cec5SDimitry Andric case MVT::i32:
30510b57cec5SDimitry Andric break;
30520b57cec5SDimitry Andric default:
30530b57cec5SDimitry Andric return false;
30540b57cec5SDimitry Andric }
30550b57cec5SDimitry Andric }
30560b57cec5SDimitry Andric
30570b57cec5SDimitry Andric static const MCPhysReg GPRArgRegs[] = {
30580b57cec5SDimitry Andric ARM::R0, ARM::R1, ARM::R2, ARM::R3
30590b57cec5SDimitry Andric };
30600b57cec5SDimitry Andric
30610b57cec5SDimitry Andric const TargetRegisterClass *RC = &ARM::rGPRRegClass;
30620b57cec5SDimitry Andric for (const Argument &Arg : F->args()) {
30630b57cec5SDimitry Andric unsigned ArgNo = Arg.getArgNo();
30640b57cec5SDimitry Andric unsigned SrcReg = GPRArgRegs[ArgNo];
306504eeddc0SDimitry Andric Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
30660b57cec5SDimitry Andric // FIXME: Unfortunately it's necessary to emit a copy from the livein copy.
30670b57cec5SDimitry Andric // Without this, EmitLiveInCopies may eliminate the livein if its only
30680b57cec5SDimitry Andric // use is a bitcast (which isn't turned into an instruction).
306904eeddc0SDimitry Andric Register ResultReg = createResultReg(RC);
3070bdd1243dSDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
30710b57cec5SDimitry Andric TII.get(TargetOpcode::COPY),
30720b57cec5SDimitry Andric ResultReg).addReg(DstReg, getKillRegState(true));
30730b57cec5SDimitry Andric updateValueMap(&Arg, ResultReg);
30740b57cec5SDimitry Andric }
30750b57cec5SDimitry Andric
30760b57cec5SDimitry Andric return true;
30770b57cec5SDimitry Andric }
30780b57cec5SDimitry Andric
30790b57cec5SDimitry Andric namespace llvm {
30800b57cec5SDimitry Andric
createFastISel(FunctionLoweringInfo & funcInfo,const TargetLibraryInfo * libInfo)30810b57cec5SDimitry Andric FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo,
30820b57cec5SDimitry Andric const TargetLibraryInfo *libInfo) {
30830b57cec5SDimitry Andric if (funcInfo.MF->getSubtarget<ARMSubtarget>().useFastISel())
30840b57cec5SDimitry Andric return new ARMFastISel(funcInfo, libInfo);
30850b57cec5SDimitry Andric
30860b57cec5SDimitry Andric return nullptr;
30870b57cec5SDimitry Andric }
30880b57cec5SDimitry Andric
30890b57cec5SDimitry Andric } // end namespace llvm
3090