123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084 |
- //===- ARMFastISel.cpp - ARM FastISel implementation ----------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file defines the ARM-specific support for the FastISel class. Some
- // of the target-specific code is generated by tablegen in the file
- // ARMGenFastISel.inc, which is #included here.
- //
- //===----------------------------------------------------------------------===//
- #include "ARM.h"
- #include "ARMBaseInstrInfo.h"
- #include "ARMBaseRegisterInfo.h"
- #include "ARMCallingConv.h"
- #include "ARMConstantPoolValue.h"
- #include "ARMISelLowering.h"
- #include "ARMMachineFunctionInfo.h"
- #include "ARMSubtarget.h"
- #include "MCTargetDesc/ARMAddressingModes.h"
- #include "MCTargetDesc/ARMBaseInfo.h"
- #include "Utils/ARMBaseInfo.h"
- #include "llvm/ADT/APFloat.h"
- #include "llvm/ADT/APInt.h"
- #include "llvm/ADT/DenseMap.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/CodeGen/CallingConvLower.h"
- #include "llvm/CodeGen/FastISel.h"
- #include "llvm/CodeGen/FunctionLoweringInfo.h"
- #include "llvm/CodeGen/ISDOpcodes.h"
- #include "llvm/CodeGen/MachineBasicBlock.h"
- #include "llvm/CodeGen/MachineConstantPool.h"
- #include "llvm/CodeGen/MachineFrameInfo.h"
- #include "llvm/CodeGen/MachineFunction.h"
- #include "llvm/CodeGen/MachineInstr.h"
- #include "llvm/CodeGen/MachineInstrBuilder.h"
- #include "llvm/CodeGen/MachineMemOperand.h"
- #include "llvm/CodeGen/MachineOperand.h"
- #include "llvm/CodeGen/MachineRegisterInfo.h"
- #include "llvm/CodeGen/RuntimeLibcalls.h"
- #include "llvm/CodeGen/TargetInstrInfo.h"
- #include "llvm/CodeGen/TargetLowering.h"
- #include "llvm/CodeGen/TargetOpcodes.h"
- #include "llvm/CodeGen/TargetRegisterInfo.h"
- #include "llvm/CodeGen/ValueTypes.h"
- #include "llvm/IR/Argument.h"
- #include "llvm/IR/Attributes.h"
- #include "llvm/IR/CallingConv.h"
- #include "llvm/IR/Constant.h"
- #include "llvm/IR/Constants.h"
- #include "llvm/IR/DataLayout.h"
- #include "llvm/IR/DerivedTypes.h"
- #include "llvm/IR/Function.h"
- #include "llvm/IR/GetElementPtrTypeIterator.h"
- #include "llvm/IR/GlobalValue.h"
- #include "llvm/IR/GlobalVariable.h"
- #include "llvm/IR/InstrTypes.h"
- #include "llvm/IR/Instruction.h"
- #include "llvm/IR/Instructions.h"
- #include "llvm/IR/IntrinsicInst.h"
- #include "llvm/IR/Intrinsics.h"
- #include "llvm/IR/Module.h"
- #include "llvm/IR/Operator.h"
- #include "llvm/IR/Type.h"
- #include "llvm/IR/User.h"
- #include "llvm/IR/Value.h"
- #include "llvm/MC/MCInstrDesc.h"
- #include "llvm/MC/MCRegisterInfo.h"
- #include "llvm/Support/Casting.h"
- #include "llvm/Support/Compiler.h"
- #include "llvm/Support/ErrorHandling.h"
- #include "llvm/Support/MachineValueType.h"
- #include "llvm/Support/MathExtras.h"
- #include "llvm/Target/TargetMachine.h"
- #include "llvm/Target/TargetOptions.h"
- #include <cassert>
- #include <cstdint>
- #include <utility>
- using namespace llvm;
- namespace {
- // All possible address modes, plus some.
- struct Address {
- enum {
- RegBase,
- FrameIndexBase
- } BaseType = RegBase;
- union {
- unsigned Reg;
- int FI;
- } Base;
- int Offset = 0;
- // Innocuous defaults for our address.
- Address() {
- Base.Reg = 0;
- }
- };
- class ARMFastISel final : public FastISel {
- /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
- /// make the right decision when generating code for different targets.
- const ARMSubtarget *Subtarget;
- Module &M;
- const TargetMachine &TM;
- const TargetInstrInfo &TII;
- const TargetLowering &TLI;
- ARMFunctionInfo *AFI;
- // Convenience variables to avoid some queries.
- bool isThumb2;
- LLVMContext *Context;
- public:
- explicit ARMFastISel(FunctionLoweringInfo &funcInfo,
- const TargetLibraryInfo *libInfo)
- : FastISel(funcInfo, libInfo),
- Subtarget(
- &static_cast<const ARMSubtarget &>(funcInfo.MF->getSubtarget())),
- M(const_cast<Module &>(*funcInfo.Fn->getParent())),
- TM(funcInfo.MF->getTarget()), TII(*Subtarget->getInstrInfo()),
- TLI(*Subtarget->getTargetLowering()) {
- AFI = funcInfo.MF->getInfo<ARMFunctionInfo>();
- isThumb2 = AFI->isThumbFunction();
- Context = &funcInfo.Fn->getContext();
- }
- private:
- // Code from FastISel.cpp.
- unsigned fastEmitInst_r(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC, unsigned Op0);
- unsigned fastEmitInst_rr(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC,
- unsigned Op0, unsigned Op1);
- unsigned fastEmitInst_ri(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC,
- unsigned Op0, uint64_t Imm);
- unsigned fastEmitInst_i(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC,
- uint64_t Imm);
- // Backend specific FastISel code.
- bool fastSelectInstruction(const Instruction *I) override;
- unsigned fastMaterializeConstant(const Constant *C) override;
- unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
- bool tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
- const LoadInst *LI) override;
- bool fastLowerArguments() override;
- #include "ARMGenFastISel.inc"
- // Instruction selection routines.
- bool SelectLoad(const Instruction *I);
- bool SelectStore(const Instruction *I);
- bool SelectBranch(const Instruction *I);
- bool SelectIndirectBr(const Instruction *I);
- bool SelectCmp(const Instruction *I);
- bool SelectFPExt(const Instruction *I);
- bool SelectFPTrunc(const Instruction *I);
- bool SelectBinaryIntOp(const Instruction *I, unsigned ISDOpcode);
- bool SelectBinaryFPOp(const Instruction *I, unsigned ISDOpcode);
- bool SelectIToFP(const Instruction *I, bool isSigned);
- bool SelectFPToI(const Instruction *I, bool isSigned);
- bool SelectDiv(const Instruction *I, bool isSigned);
- bool SelectRem(const Instruction *I, bool isSigned);
- bool SelectCall(const Instruction *I, const char *IntrMemName);
- bool SelectIntrinsicCall(const IntrinsicInst &I);
- bool SelectSelect(const Instruction *I);
- bool SelectRet(const Instruction *I);
- bool SelectTrunc(const Instruction *I);
- bool SelectIntExt(const Instruction *I);
- bool SelectShift(const Instruction *I, ARM_AM::ShiftOpc ShiftTy);
- // Utility routines.
- bool isPositionIndependent() const;
- bool isTypeLegal(Type *Ty, MVT &VT);
- bool isLoadTypeLegal(Type *Ty, MVT &VT);
- bool ARMEmitCmp(const Value *Src1Value, const Value *Src2Value,
- bool isZExt);
- bool ARMEmitLoad(MVT VT, Register &ResultReg, Address &Addr,
- unsigned Alignment = 0, bool isZExt = true,
- bool allocReg = true);
- bool ARMEmitStore(MVT VT, unsigned SrcReg, Address &Addr,
- unsigned Alignment = 0);
- bool ARMComputeAddress(const Value *Obj, Address &Addr);
- void ARMSimplifyAddress(Address &Addr, MVT VT, bool useAM3);
- bool ARMIsMemCpySmall(uint64_t Len);
- bool ARMTryEmitSmallMemCpy(Address Dest, Address Src, uint64_t Len,
- unsigned Alignment);
- unsigned ARMEmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt);
- unsigned ARMMaterializeFP(const ConstantFP *CFP, MVT VT);
- unsigned ARMMaterializeInt(const Constant *C, MVT VT);
- unsigned ARMMaterializeGV(const GlobalValue *GV, MVT VT);
- unsigned ARMMoveToFPReg(MVT VT, unsigned SrcReg);
- unsigned ARMMoveToIntReg(MVT VT, unsigned SrcReg);
- unsigned ARMSelectCallOp(bool UseReg);
- unsigned ARMLowerPICELF(const GlobalValue *GV, MVT VT);
- const TargetLowering *getTargetLowering() { return &TLI; }
- // Call handling routines.
- CCAssignFn *CCAssignFnForCall(CallingConv::ID CC,
- bool Return,
- bool isVarArg);
- bool ProcessCallArgs(SmallVectorImpl<Value*> &Args,
- SmallVectorImpl<Register> &ArgRegs,
- SmallVectorImpl<MVT> &ArgVTs,
- SmallVectorImpl<ISD::ArgFlagsTy> &ArgFlags,
- SmallVectorImpl<Register> &RegArgs,
- CallingConv::ID CC,
- unsigned &NumBytes,
- bool isVarArg);
- unsigned getLibcallReg(const Twine &Name);
- bool FinishCall(MVT RetVT, SmallVectorImpl<Register> &UsedRegs,
- const Instruction *I, CallingConv::ID CC,
- unsigned &NumBytes, bool isVarArg);
- bool ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call);
- // OptionalDef handling routines.
- bool isARMNEONPred(const MachineInstr *MI);
- bool DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR);
- const MachineInstrBuilder &AddOptionalDefs(const MachineInstrBuilder &MIB);
- void AddLoadStoreOperands(MVT VT, Address &Addr,
- const MachineInstrBuilder &MIB,
- MachineMemOperand::Flags Flags, bool useAM3);
- };
- } // end anonymous namespace
- // DefinesOptionalPredicate - This is different from DefinesPredicate in that
- // we don't care about implicit defs here, just places we'll need to add a
- // default CCReg argument. Sets CPSR if we're setting CPSR instead of CCR.
- bool ARMFastISel::DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR) {
- if (!MI->hasOptionalDef())
- return false;
- // Look to see if our OptionalDef is defining CPSR or CCR.
- for (const MachineOperand &MO : MI->operands()) {
- if (!MO.isReg() || !MO.isDef()) continue;
- if (MO.getReg() == ARM::CPSR)
- *CPSR = true;
- }
- return true;
- }
- bool ARMFastISel::isARMNEONPred(const MachineInstr *MI) {
- const MCInstrDesc &MCID = MI->getDesc();
- // If we're a thumb2 or not NEON function we'll be handled via isPredicable.
- if ((MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainNEON ||
- AFI->isThumb2Function())
- return MI->isPredicable();
- for (const MCOperandInfo &opInfo : MCID.operands())
- if (opInfo.isPredicate())
- return true;
- return false;
- }
- // If the machine is predicable go ahead and add the predicate operands, if
- // it needs default CC operands add those.
- // TODO: If we want to support thumb1 then we'll need to deal with optional
- // CPSR defs that need to be added before the remaining operands. See s_cc_out
- // for descriptions why.
- const MachineInstrBuilder &
- ARMFastISel::AddOptionalDefs(const MachineInstrBuilder &MIB) {
- MachineInstr *MI = &*MIB;
- // Do we use a predicate? or...
- // Are we NEON in ARM mode and have a predicate operand? If so, I know
- // we're not predicable but add it anyways.
- if (isARMNEONPred(MI))
- MIB.add(predOps(ARMCC::AL));
- // Do we optionally set a predicate? Preds is size > 0 iff the predicate
- // defines CPSR. All other OptionalDefines in ARM are the CCR register.
- bool CPSR = false;
- if (DefinesOptionalPredicate(MI, &CPSR))
- MIB.add(CPSR ? t1CondCodeOp() : condCodeOp());
- return MIB;
- }
- unsigned ARMFastISel::fastEmitInst_r(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC,
- unsigned Op0) {
- Register ResultReg = createResultReg(RC);
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- // Make sure the input operand is sufficiently constrained to be legal
- // for this instruction.
- Op0 = constrainOperandRegClass(II, Op0, 1);
- if (II.getNumDefs() >= 1) {
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II,
- ResultReg).addReg(Op0));
- } else {
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addReg(Op0));
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg)
- .addReg(II.ImplicitDefs[0]));
- }
- return ResultReg;
- }
- unsigned ARMFastISel::fastEmitInst_rr(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC,
- unsigned Op0, unsigned Op1) {
- Register ResultReg = createResultReg(RC);
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- // Make sure the input operands are sufficiently constrained to be legal
- // for this instruction.
- Op0 = constrainOperandRegClass(II, Op0, 1);
- Op1 = constrainOperandRegClass(II, Op1, 2);
- if (II.getNumDefs() >= 1) {
- AddOptionalDefs(
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
- .addReg(Op0)
- .addReg(Op1));
- } else {
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addReg(Op0)
- .addReg(Op1));
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg)
- .addReg(II.ImplicitDefs[0]));
- }
- return ResultReg;
- }
- unsigned ARMFastISel::fastEmitInst_ri(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC,
- unsigned Op0, uint64_t Imm) {
- Register ResultReg = createResultReg(RC);
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- // Make sure the input operand is sufficiently constrained to be legal
- // for this instruction.
- Op0 = constrainOperandRegClass(II, Op0, 1);
- if (II.getNumDefs() >= 1) {
- AddOptionalDefs(
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
- .addReg(Op0)
- .addImm(Imm));
- } else {
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addReg(Op0)
- .addImm(Imm));
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg)
- .addReg(II.ImplicitDefs[0]));
- }
- return ResultReg;
- }
- unsigned ARMFastISel::fastEmitInst_i(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC,
- uint64_t Imm) {
- Register ResultReg = createResultReg(RC);
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- if (II.getNumDefs() >= 1) {
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II,
- ResultReg).addImm(Imm));
- } else {
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addImm(Imm));
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg)
- .addReg(II.ImplicitDefs[0]));
- }
- return ResultReg;
- }
- // TODO: Don't worry about 64-bit now, but when this is fixed remove the
- // checks from the various callers.
- unsigned ARMFastISel::ARMMoveToFPReg(MVT VT, unsigned SrcReg) {
- if (VT == MVT::f64) return 0;
- Register MoveReg = createResultReg(TLI.getRegClassFor(VT));
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::VMOVSR), MoveReg)
- .addReg(SrcReg));
- return MoveReg;
- }
- unsigned ARMFastISel::ARMMoveToIntReg(MVT VT, unsigned SrcReg) {
- if (VT == MVT::i64) return 0;
- Register MoveReg = createResultReg(TLI.getRegClassFor(VT));
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::VMOVRS), MoveReg)
- .addReg(SrcReg));
- return MoveReg;
- }
- // For double width floating point we need to materialize two constants
- // (the high and the low) into integer registers then use a move to get
- // the combined constant into an FP reg.
- unsigned ARMFastISel::ARMMaterializeFP(const ConstantFP *CFP, MVT VT) {
- const APFloat Val = CFP->getValueAPF();
- bool is64bit = VT == MVT::f64;
- // This checks to see if we can use VFP3 instructions to materialize
- // a constant, otherwise we have to go through the constant pool.
- if (TLI.isFPImmLegal(Val, VT)) {
- int Imm;
- unsigned Opc;
- if (is64bit) {
- Imm = ARM_AM::getFP64Imm(Val);
- Opc = ARM::FCONSTD;
- } else {
- Imm = ARM_AM::getFP32Imm(Val);
- Opc = ARM::FCONSTS;
- }
- Register DestReg = createResultReg(TLI.getRegClassFor(VT));
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(Opc), DestReg).addImm(Imm));
- return DestReg;
- }
- // Require VFP2 for loading fp constants.
- if (!Subtarget->hasVFP2Base()) return false;
- // MachineConstantPool wants an explicit alignment.
- Align Alignment = DL.getPrefTypeAlign(CFP->getType());
- unsigned Idx = MCP.getConstantPoolIndex(cast<Constant>(CFP), Alignment);
- Register DestReg = createResultReg(TLI.getRegClassFor(VT));
- unsigned Opc = is64bit ? ARM::VLDRD : ARM::VLDRS;
- // The extra reg is for addrmode5.
- AddOptionalDefs(
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), DestReg)
- .addConstantPoolIndex(Idx)
- .addReg(0));
- return DestReg;
- }
- unsigned ARMFastISel::ARMMaterializeInt(const Constant *C, MVT VT) {
- if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1)
- return 0;
- // If we can do this in a single instruction without a constant pool entry
- // do so now.
- const ConstantInt *CI = cast<ConstantInt>(C);
- if (Subtarget->hasV6T2Ops() && isUInt<16>(CI->getZExtValue())) {
- unsigned Opc = isThumb2 ? ARM::t2MOVi16 : ARM::MOVi16;
- const TargetRegisterClass *RC = isThumb2 ? &ARM::rGPRRegClass :
- &ARM::GPRRegClass;
- Register ImmReg = createResultReg(RC);
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(Opc), ImmReg)
- .addImm(CI->getZExtValue()));
- return ImmReg;
- }
- // Use MVN to emit negative constants.
- if (VT == MVT::i32 && Subtarget->hasV6T2Ops() && CI->isNegative()) {
- unsigned Imm = (unsigned)~(CI->getSExtValue());
- bool UseImm = isThumb2 ? (ARM_AM::getT2SOImmVal(Imm) != -1) :
- (ARM_AM::getSOImmVal(Imm) != -1);
- if (UseImm) {
- unsigned Opc = isThumb2 ? ARM::t2MVNi : ARM::MVNi;
- const TargetRegisterClass *RC = isThumb2 ? &ARM::rGPRRegClass :
- &ARM::GPRRegClass;
- Register ImmReg = createResultReg(RC);
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(Opc), ImmReg)
- .addImm(Imm));
- return ImmReg;
- }
- }
- unsigned ResultReg = 0;
- if (Subtarget->useMovt())
- ResultReg = fastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue());
- if (ResultReg)
- return ResultReg;
- // Load from constant pool. For now 32-bit only.
- if (VT != MVT::i32)
- return 0;
- // MachineConstantPool wants an explicit alignment.
- Align Alignment = DL.getPrefTypeAlign(C->getType());
- unsigned Idx = MCP.getConstantPoolIndex(C, Alignment);
- ResultReg = createResultReg(TLI.getRegClassFor(VT));
- if (isThumb2)
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::t2LDRpci), ResultReg)
- .addConstantPoolIndex(Idx));
- else {
- // The extra immediate is for addrmode2.
- ResultReg = constrainOperandRegClass(TII.get(ARM::LDRcp), ResultReg, 0);
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::LDRcp), ResultReg)
- .addConstantPoolIndex(Idx)
- .addImm(0));
- }
- return ResultReg;
- }
- bool ARMFastISel::isPositionIndependent() const {
- return TLI.isPositionIndependent();
- }
- unsigned ARMFastISel::ARMMaterializeGV(const GlobalValue *GV, MVT VT) {
- // For now 32-bit only.
- if (VT != MVT::i32 || GV->isThreadLocal()) return 0;
- // ROPI/RWPI not currently supported.
- if (Subtarget->isROPI() || Subtarget->isRWPI())
- return 0;
- bool IsIndirect = Subtarget->isGVIndirectSymbol(GV);
- const TargetRegisterClass *RC = isThumb2 ? &ARM::rGPRRegClass
- : &ARM::GPRRegClass;
- Register DestReg = createResultReg(RC);
- // FastISel TLS support on non-MachO is broken, punt to SelectionDAG.
- const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
- bool IsThreadLocal = GVar && GVar->isThreadLocal();
- if (!Subtarget->isTargetMachO() && IsThreadLocal) return 0;
- bool IsPositionIndependent = isPositionIndependent();
- // Use movw+movt when possible, it avoids constant pool entries.
- // Non-darwin targets only support static movt relocations in FastISel.
- if (Subtarget->useMovt() &&
- (Subtarget->isTargetMachO() || !IsPositionIndependent)) {
- unsigned Opc;
- unsigned char TF = 0;
- if (Subtarget->isTargetMachO())
- TF = ARMII::MO_NONLAZY;
- if (IsPositionIndependent)
- Opc = isThumb2 ? ARM::t2MOV_ga_pcrel : ARM::MOV_ga_pcrel;
- else
- Opc = isThumb2 ? ARM::t2MOVi32imm : ARM::MOVi32imm;
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(Opc), DestReg).addGlobalAddress(GV, 0, TF));
- } else {
- // MachineConstantPool wants an explicit alignment.
- Align Alignment = DL.getPrefTypeAlign(GV->getType());
- if (Subtarget->isTargetELF() && IsPositionIndependent)
- return ARMLowerPICELF(GV, VT);
- // Grab index.
- unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
- unsigned Id = AFI->createPICLabelUId();
- ARMConstantPoolValue *CPV = ARMConstantPoolConstant::Create(GV, Id,
- ARMCP::CPValue,
- PCAdj);
- unsigned Idx = MCP.getConstantPoolIndex(CPV, Alignment);
- // Load value.
- MachineInstrBuilder MIB;
- if (isThumb2) {
- unsigned Opc = IsPositionIndependent ? ARM::t2LDRpci_pic : ARM::t2LDRpci;
- MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
- DestReg).addConstantPoolIndex(Idx);
- if (IsPositionIndependent)
- MIB.addImm(Id);
- AddOptionalDefs(MIB);
- } else {
- // The extra immediate is for addrmode2.
- DestReg = constrainOperandRegClass(TII.get(ARM::LDRcp), DestReg, 0);
- MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::LDRcp), DestReg)
- .addConstantPoolIndex(Idx)
- .addImm(0);
- AddOptionalDefs(MIB);
- if (IsPositionIndependent) {
- unsigned Opc = IsIndirect ? ARM::PICLDR : ARM::PICADD;
- Register NewDestReg = createResultReg(TLI.getRegClassFor(VT));
- MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
- DbgLoc, TII.get(Opc), NewDestReg)
- .addReg(DestReg)
- .addImm(Id);
- AddOptionalDefs(MIB);
- return NewDestReg;
- }
- }
- }
- if ((Subtarget->isTargetELF() && Subtarget->isGVInGOT(GV)) ||
- (Subtarget->isTargetMachO() && IsIndirect) ||
- Subtarget->genLongCalls()) {
- MachineInstrBuilder MIB;
- Register NewDestReg = createResultReg(TLI.getRegClassFor(VT));
- if (isThumb2)
- MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::t2LDRi12), NewDestReg)
- .addReg(DestReg)
- .addImm(0);
- else
- MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::LDRi12), NewDestReg)
- .addReg(DestReg)
- .addImm(0);
- DestReg = NewDestReg;
- AddOptionalDefs(MIB);
- }
- return DestReg;
- }
- unsigned ARMFastISel::fastMaterializeConstant(const Constant *C) {
- EVT CEVT = TLI.getValueType(DL, C->getType(), true);
- // Only handle simple types.
- if (!CEVT.isSimple()) return 0;
- MVT VT = CEVT.getSimpleVT();
- if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
- return ARMMaterializeFP(CFP, VT);
- else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
- return ARMMaterializeGV(GV, VT);
- else if (isa<ConstantInt>(C))
- return ARMMaterializeInt(C, VT);
- return 0;
- }
- // TODO: unsigned ARMFastISel::TargetMaterializeFloatZero(const ConstantFP *CF);
- unsigned ARMFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
- // Don't handle dynamic allocas.
- if (!FuncInfo.StaticAllocaMap.count(AI)) return 0;
- MVT VT;
- if (!isLoadTypeLegal(AI->getType(), VT)) return 0;
- DenseMap<const AllocaInst*, int>::iterator SI =
- FuncInfo.StaticAllocaMap.find(AI);
- // This will get lowered later into the correct offsets and registers
- // via rewriteXFrameIndex.
- if (SI != FuncInfo.StaticAllocaMap.end()) {
- unsigned Opc = isThumb2 ? ARM::t2ADDri : ARM::ADDri;
- const TargetRegisterClass* RC = TLI.getRegClassFor(VT);
- Register ResultReg = createResultReg(RC);
- ResultReg = constrainOperandRegClass(TII.get(Opc), ResultReg, 0);
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(Opc), ResultReg)
- .addFrameIndex(SI->second)
- .addImm(0));
- return ResultReg;
- }
- return 0;
- }
- bool ARMFastISel::isTypeLegal(Type *Ty, MVT &VT) {
- EVT evt = TLI.getValueType(DL, Ty, true);
- // Only handle simple types.
- if (evt == MVT::Other || !evt.isSimple()) return false;
- VT = evt.getSimpleVT();
- // Handle all legal types, i.e. a register that will directly hold this
- // value.
- return TLI.isTypeLegal(VT);
- }
- bool ARMFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) {
- if (isTypeLegal(Ty, VT)) return true;
- // If this is a type than can be sign or zero-extended to a basic operation
- // go ahead and accept it now.
- if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)
- return true;
- return false;
- }
- // Computes the address to get to an object.
- bool ARMFastISel::ARMComputeAddress(const Value *Obj, Address &Addr) {
- // Some boilerplate from the X86 FastISel.
- const User *U = nullptr;
- unsigned Opcode = Instruction::UserOp1;
- if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
- // Don't walk into other basic blocks unless the object is an alloca from
- // another block, otherwise it may not have a virtual register assigned.
- if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
- FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
- Opcode = I->getOpcode();
- U = I;
- }
- } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
- Opcode = C->getOpcode();
- U = C;
- }
- if (PointerType *Ty = dyn_cast<PointerType>(Obj->getType()))
- if (Ty->getAddressSpace() > 255)
- // Fast instruction selection doesn't support the special
- // address spaces.
- return false;
- switch (Opcode) {
- default:
- break;
- case Instruction::BitCast:
- // Look through bitcasts.
- return ARMComputeAddress(U->getOperand(0), Addr);
- case Instruction::IntToPtr:
- // Look past no-op inttoptrs.
- if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
- TLI.getPointerTy(DL))
- return ARMComputeAddress(U->getOperand(0), Addr);
- break;
- case Instruction::PtrToInt:
- // Look past no-op ptrtoints.
- if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
- return ARMComputeAddress(U->getOperand(0), Addr);
- break;
- case Instruction::GetElementPtr: {
- Address SavedAddr = Addr;
- int TmpOffset = Addr.Offset;
- // Iterate through the GEP folding the constants into offsets where
- // we can.
- gep_type_iterator GTI = gep_type_begin(U);
- for (User::const_op_iterator i = U->op_begin() + 1, e = U->op_end();
- i != e; ++i, ++GTI) {
- const Value *Op = *i;
- if (StructType *STy = GTI.getStructTypeOrNull()) {
- const StructLayout *SL = DL.getStructLayout(STy);
- unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
- TmpOffset += SL->getElementOffset(Idx);
- } else {
- uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
- while (true) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
- // Constant-offset addressing.
- TmpOffset += CI->getSExtValue() * S;
- break;
- }
- if (canFoldAddIntoGEP(U, Op)) {
- // A compatible add with a constant operand. Fold the constant.
- ConstantInt *CI =
- cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
- TmpOffset += CI->getSExtValue() * S;
- // Iterate on the other operand.
- Op = cast<AddOperator>(Op)->getOperand(0);
- continue;
- }
- // Unsupported
- goto unsupported_gep;
- }
- }
- }
- // Try to grab the base operand now.
- Addr.Offset = TmpOffset;
- if (ARMComputeAddress(U->getOperand(0), Addr)) return true;
- // We failed, restore everything and try the other options.
- Addr = SavedAddr;
- unsupported_gep:
- break;
- }
- case Instruction::Alloca: {
- const AllocaInst *AI = cast<AllocaInst>(Obj);
- DenseMap<const AllocaInst*, int>::iterator SI =
- FuncInfo.StaticAllocaMap.find(AI);
- if (SI != FuncInfo.StaticAllocaMap.end()) {
- Addr.BaseType = Address::FrameIndexBase;
- Addr.Base.FI = SI->second;
- return true;
- }
- break;
- }
- }
- // Try to get this in a register if nothing else has worked.
- if (Addr.Base.Reg == 0) Addr.Base.Reg = getRegForValue(Obj);
- return Addr.Base.Reg != 0;
- }
- void ARMFastISel::ARMSimplifyAddress(Address &Addr, MVT VT, bool useAM3) {
- bool needsLowering = false;
- switch (VT.SimpleTy) {
- default: llvm_unreachable("Unhandled load/store type!");
- case MVT::i1:
- case MVT::i8:
- case MVT::i16:
- case MVT::i32:
- if (!useAM3) {
- // Integer loads/stores handle 12-bit offsets.
- needsLowering = ((Addr.Offset & 0xfff) != Addr.Offset);
- // Handle negative offsets.
- if (needsLowering && isThumb2)
- needsLowering = !(Subtarget->hasV6T2Ops() && Addr.Offset < 0 &&
- Addr.Offset > -256);
- } else {
- // ARM halfword load/stores and signed byte loads use +/-imm8 offsets.
- needsLowering = (Addr.Offset > 255 || Addr.Offset < -255);
- }
- break;
- case MVT::f32:
- case MVT::f64:
- // Floating point operands handle 8-bit offsets.
- needsLowering = ((Addr.Offset & 0xff) != Addr.Offset);
- break;
- }
- // If this is a stack pointer and the offset needs to be simplified then
- // put the alloca address into a register, set the base type back to
- // register and continue. This should almost never happen.
- if (needsLowering && Addr.BaseType == Address::FrameIndexBase) {
- const TargetRegisterClass *RC = isThumb2 ? &ARM::tGPRRegClass
- : &ARM::GPRRegClass;
- Register ResultReg = createResultReg(RC);
- unsigned Opc = isThumb2 ? ARM::t2ADDri : ARM::ADDri;
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(Opc), ResultReg)
- .addFrameIndex(Addr.Base.FI)
- .addImm(0));
- Addr.Base.Reg = ResultReg;
- Addr.BaseType = Address::RegBase;
- }
- // Since the offset is too large for the load/store instruction
- // get the reg+offset into a register.
- if (needsLowering) {
- Addr.Base.Reg = fastEmit_ri_(MVT::i32, ISD::ADD, Addr.Base.Reg,
- Addr.Offset, MVT::i32);
- Addr.Offset = 0;
- }
- }
- void ARMFastISel::AddLoadStoreOperands(MVT VT, Address &Addr,
- const MachineInstrBuilder &MIB,
- MachineMemOperand::Flags Flags,
- bool useAM3) {
- // addrmode5 output depends on the selection dag addressing dividing the
- // offset by 4 that it then later multiplies. Do this here as well.
- if (VT.SimpleTy == MVT::f32 || VT.SimpleTy == MVT::f64)
- Addr.Offset /= 4;
- // Frame base works a bit differently. Handle it separately.
- if (Addr.BaseType == Address::FrameIndexBase) {
- int FI = Addr.Base.FI;
- int Offset = Addr.Offset;
- MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
- MachinePointerInfo::getFixedStack(*FuncInfo.MF, FI, Offset), Flags,
- MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
- // Now add the rest of the operands.
- MIB.addFrameIndex(FI);
- // ARM halfword load/stores and signed byte loads need an additional
- // operand.
- if (useAM3) {
- int Imm = (Addr.Offset < 0) ? (0x100 | -Addr.Offset) : Addr.Offset;
- MIB.addReg(0);
- MIB.addImm(Imm);
- } else {
- MIB.addImm(Addr.Offset);
- }
- MIB.addMemOperand(MMO);
- } else {
- // Now add the rest of the operands.
- MIB.addReg(Addr.Base.Reg);
- // ARM halfword load/stores and signed byte loads need an additional
- // operand.
- if (useAM3) {
- int Imm = (Addr.Offset < 0) ? (0x100 | -Addr.Offset) : Addr.Offset;
- MIB.addReg(0);
- MIB.addImm(Imm);
- } else {
- MIB.addImm(Addr.Offset);
- }
- }
- AddOptionalDefs(MIB);
- }
- bool ARMFastISel::ARMEmitLoad(MVT VT, Register &ResultReg, Address &Addr,
- unsigned Alignment, bool isZExt, bool allocReg) {
- unsigned Opc;
- bool useAM3 = false;
- bool needVMOV = false;
- const TargetRegisterClass *RC;
- switch (VT.SimpleTy) {
- // This is mostly going to be Neon/vector support.
- default: return false;
- case MVT::i1:
- case MVT::i8:
- if (isThumb2) {
- if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
- Opc = isZExt ? ARM::t2LDRBi8 : ARM::t2LDRSBi8;
- else
- Opc = isZExt ? ARM::t2LDRBi12 : ARM::t2LDRSBi12;
- } else {
- if (isZExt) {
- Opc = ARM::LDRBi12;
- } else {
- Opc = ARM::LDRSB;
- useAM3 = true;
- }
- }
- RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRnopcRegClass;
- break;
- case MVT::i16:
- if (Alignment && Alignment < 2 && !Subtarget->allowsUnalignedMem())
- return false;
- if (isThumb2) {
- if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
- Opc = isZExt ? ARM::t2LDRHi8 : ARM::t2LDRSHi8;
- else
- Opc = isZExt ? ARM::t2LDRHi12 : ARM::t2LDRSHi12;
- } else {
- Opc = isZExt ? ARM::LDRH : ARM::LDRSH;
- useAM3 = true;
- }
- RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRnopcRegClass;
- break;
- case MVT::i32:
- if (Alignment && Alignment < 4 && !Subtarget->allowsUnalignedMem())
- return false;
- if (isThumb2) {
- if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
- Opc = ARM::t2LDRi8;
- else
- Opc = ARM::t2LDRi12;
- } else {
- Opc = ARM::LDRi12;
- }
- RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRnopcRegClass;
- break;
- case MVT::f32:
- if (!Subtarget->hasVFP2Base()) return false;
- // Unaligned loads need special handling. Floats require word-alignment.
- if (Alignment && Alignment < 4) {
- needVMOV = true;
- VT = MVT::i32;
- Opc = isThumb2 ? ARM::t2LDRi12 : ARM::LDRi12;
- RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRnopcRegClass;
- } else {
- Opc = ARM::VLDRS;
- RC = TLI.getRegClassFor(VT);
- }
- break;
- case MVT::f64:
- // Can load and store double precision even without FeatureFP64
- if (!Subtarget->hasVFP2Base()) return false;
- // FIXME: Unaligned loads need special handling. Doublewords require
- // word-alignment.
- if (Alignment && Alignment < 4)
- return false;
- Opc = ARM::VLDRD;
- RC = TLI.getRegClassFor(VT);
- break;
- }
- // Simplify this down to something we can handle.
- ARMSimplifyAddress(Addr, VT, useAM3);
- // Create the base instruction, then add the operands.
- if (allocReg)
- ResultReg = createResultReg(RC);
- assert(ResultReg > 255 && "Expected an allocated virtual register.");
- MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(Opc), ResultReg);
- AddLoadStoreOperands(VT, Addr, MIB, MachineMemOperand::MOLoad, useAM3);
- // If we had an unaligned load of a float we've converted it to an regular
- // load. Now we must move from the GRP to the FP register.
- if (needVMOV) {
- Register MoveReg = createResultReg(TLI.getRegClassFor(MVT::f32));
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::VMOVSR), MoveReg)
- .addReg(ResultReg));
- ResultReg = MoveReg;
- }
- return true;
- }
- bool ARMFastISel::SelectLoad(const Instruction *I) {
- // Atomic loads need special handling.
- if (cast<LoadInst>(I)->isAtomic())
- return false;
- const Value *SV = I->getOperand(0);
- if (TLI.supportSwiftError()) {
- // Swifterror values can come from either a function parameter with
- // swifterror attribute or an alloca with swifterror attribute.
- if (const Argument *Arg = dyn_cast<Argument>(SV)) {
- if (Arg->hasSwiftErrorAttr())
- return false;
- }
- if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(SV)) {
- if (Alloca->isSwiftError())
- return false;
- }
- }
- // Verify we have a legal type before going any further.
- MVT VT;
- if (!isLoadTypeLegal(I->getType(), VT))
- return false;
- // See if we can handle this address.
- Address Addr;
- if (!ARMComputeAddress(I->getOperand(0), Addr)) return false;
- Register ResultReg;
- if (!ARMEmitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment()))
- return false;
- updateValueMap(I, ResultReg);
- return true;
- }
- bool ARMFastISel::ARMEmitStore(MVT VT, unsigned SrcReg, Address &Addr,
- unsigned Alignment) {
- unsigned StrOpc;
- bool useAM3 = false;
- switch (VT.SimpleTy) {
- // This is mostly going to be Neon/vector support.
- default: return false;
- case MVT::i1: {
- Register Res = createResultReg(isThumb2 ? &ARM::tGPRRegClass
- : &ARM::GPRRegClass);
- unsigned Opc = isThumb2 ? ARM::t2ANDri : ARM::ANDri;
- SrcReg = constrainOperandRegClass(TII.get(Opc), SrcReg, 1);
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(Opc), Res)
- .addReg(SrcReg).addImm(1));
- SrcReg = Res;
- LLVM_FALLTHROUGH;
- }
- case MVT::i8:
- if (isThumb2) {
- if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
- StrOpc = ARM::t2STRBi8;
- else
- StrOpc = ARM::t2STRBi12;
- } else {
- StrOpc = ARM::STRBi12;
- }
- break;
- case MVT::i16:
- if (Alignment && Alignment < 2 && !Subtarget->allowsUnalignedMem())
- return false;
- if (isThumb2) {
- if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
- StrOpc = ARM::t2STRHi8;
- else
- StrOpc = ARM::t2STRHi12;
- } else {
- StrOpc = ARM::STRH;
- useAM3 = true;
- }
- break;
- case MVT::i32:
- if (Alignment && Alignment < 4 && !Subtarget->allowsUnalignedMem())
- return false;
- if (isThumb2) {
- if (Addr.Offset < 0 && Addr.Offset > -256 && Subtarget->hasV6T2Ops())
- StrOpc = ARM::t2STRi8;
- else
- StrOpc = ARM::t2STRi12;
- } else {
- StrOpc = ARM::STRi12;
- }
- break;
- case MVT::f32:
- if (!Subtarget->hasVFP2Base()) return false;
- // Unaligned stores need special handling. Floats require word-alignment.
- if (Alignment && Alignment < 4) {
- Register MoveReg = createResultReg(TLI.getRegClassFor(MVT::i32));
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::VMOVRS), MoveReg)
- .addReg(SrcReg));
- SrcReg = MoveReg;
- VT = MVT::i32;
- StrOpc = isThumb2 ? ARM::t2STRi12 : ARM::STRi12;
- } else {
- StrOpc = ARM::VSTRS;
- }
- break;
- case MVT::f64:
- // Can load and store double precision even without FeatureFP64
- if (!Subtarget->hasVFP2Base()) return false;
- // FIXME: Unaligned stores need special handling. Doublewords require
- // word-alignment.
- if (Alignment && Alignment < 4)
- return false;
- StrOpc = ARM::VSTRD;
- break;
- }
- // Simplify this down to something we can handle.
- ARMSimplifyAddress(Addr, VT, useAM3);
- // Create the base instruction, then add the operands.
- SrcReg = constrainOperandRegClass(TII.get(StrOpc), SrcReg, 0);
- MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(StrOpc))
- .addReg(SrcReg);
- AddLoadStoreOperands(VT, Addr, MIB, MachineMemOperand::MOStore, useAM3);
- return true;
- }
- bool ARMFastISel::SelectStore(const Instruction *I) {
- Value *Op0 = I->getOperand(0);
- unsigned SrcReg = 0;
- // Atomic stores need special handling.
- if (cast<StoreInst>(I)->isAtomic())
- return false;
- const Value *PtrV = I->getOperand(1);
- if (TLI.supportSwiftError()) {
- // Swifterror values can come from either a function parameter with
- // swifterror attribute or an alloca with swifterror attribute.
- if (const Argument *Arg = dyn_cast<Argument>(PtrV)) {
- if (Arg->hasSwiftErrorAttr())
- return false;
- }
- if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(PtrV)) {
- if (Alloca->isSwiftError())
- return false;
- }
- }
- // Verify we have a legal type before going any further.
- MVT VT;
- if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT))
- return false;
- // Get the value to be stored into a register.
- SrcReg = getRegForValue(Op0);
- if (SrcReg == 0) return false;
- // See if we can handle this address.
- Address Addr;
- if (!ARMComputeAddress(I->getOperand(1), Addr))
- return false;
- if (!ARMEmitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment()))
- return false;
- return true;
- }
- static ARMCC::CondCodes getComparePred(CmpInst::Predicate Pred) {
- switch (Pred) {
- // Needs two compares...
- case CmpInst::FCMP_ONE:
- case CmpInst::FCMP_UEQ:
- default:
- // AL is our "false" for now. The other two need more compares.
- return ARMCC::AL;
- case CmpInst::ICMP_EQ:
- case CmpInst::FCMP_OEQ:
- return ARMCC::EQ;
- case CmpInst::ICMP_SGT:
- case CmpInst::FCMP_OGT:
- return ARMCC::GT;
- case CmpInst::ICMP_SGE:
- case CmpInst::FCMP_OGE:
- return ARMCC::GE;
- case CmpInst::ICMP_UGT:
- case CmpInst::FCMP_UGT:
- return ARMCC::HI;
- case CmpInst::FCMP_OLT:
- return ARMCC::MI;
- case CmpInst::ICMP_ULE:
- case CmpInst::FCMP_OLE:
- return ARMCC::LS;
- case CmpInst::FCMP_ORD:
- return ARMCC::VC;
- case CmpInst::FCMP_UNO:
- return ARMCC::VS;
- case CmpInst::FCMP_UGE:
- return ARMCC::PL;
- case CmpInst::ICMP_SLT:
- case CmpInst::FCMP_ULT:
- return ARMCC::LT;
- case CmpInst::ICMP_SLE:
- case CmpInst::FCMP_ULE:
- return ARMCC::LE;
- case CmpInst::FCMP_UNE:
- case CmpInst::ICMP_NE:
- return ARMCC::NE;
- case CmpInst::ICMP_UGE:
- return ARMCC::HS;
- case CmpInst::ICMP_ULT:
- return ARMCC::LO;
- }
- }
- bool ARMFastISel::SelectBranch(const Instruction *I) {
- const BranchInst *BI = cast<BranchInst>(I);
- MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)];
- MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];
- // Simple branch support.
- // If we can, avoid recomputing the compare - redoing it could lead to wonky
- // behavior.
- if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) {
- if (CI->hasOneUse() && (CI->getParent() == I->getParent())) {
- // Get the compare predicate.
- // Try to take advantage of fallthrough opportunities.
- CmpInst::Predicate Predicate = CI->getPredicate();
- if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
- std::swap(TBB, FBB);
- Predicate = CmpInst::getInversePredicate(Predicate);
- }
- ARMCC::CondCodes ARMPred = getComparePred(Predicate);
- // We may not handle every CC for now.
- if (ARMPred == ARMCC::AL) return false;
- // Emit the compare.
- if (!ARMEmitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned()))
- return false;
- unsigned BrOpc = isThumb2 ? ARM::t2Bcc : ARM::Bcc;
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(BrOpc))
- .addMBB(TBB).addImm(ARMPred).addReg(ARM::CPSR);
- finishCondBranch(BI->getParent(), TBB, FBB);
- return true;
- }
- } else if (TruncInst *TI = dyn_cast<TruncInst>(BI->getCondition())) {
- MVT SourceVT;
- if (TI->hasOneUse() && TI->getParent() == I->getParent() &&
- (isLoadTypeLegal(TI->getOperand(0)->getType(), SourceVT))) {
- unsigned TstOpc = isThumb2 ? ARM::t2TSTri : ARM::TSTri;
- Register OpReg = getRegForValue(TI->getOperand(0));
- OpReg = constrainOperandRegClass(TII.get(TstOpc), OpReg, 0);
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TstOpc))
- .addReg(OpReg).addImm(1));
- unsigned CCMode = ARMCC::NE;
- if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
- std::swap(TBB, FBB);
- CCMode = ARMCC::EQ;
- }
- unsigned BrOpc = isThumb2 ? ARM::t2Bcc : ARM::Bcc;
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(BrOpc))
- .addMBB(TBB).addImm(CCMode).addReg(ARM::CPSR);
- finishCondBranch(BI->getParent(), TBB, FBB);
- return true;
- }
- } else if (const ConstantInt *CI =
- dyn_cast<ConstantInt>(BI->getCondition())) {
- uint64_t Imm = CI->getZExtValue();
- MachineBasicBlock *Target = (Imm == 0) ? FBB : TBB;
- fastEmitBranch(Target, DbgLoc);
- return true;
- }
- Register CmpReg = getRegForValue(BI->getCondition());
- if (CmpReg == 0) return false;
- // We've been divorced from our compare! Our block was split, and
- // now our compare lives in a predecessor block. We musn't
- // re-compare here, as the children of the compare aren't guaranteed
- // live across the block boundary (we *could* check for this).
- // Regardless, the compare has been done in the predecessor block,
- // and it left a value for us in a virtual register. Ergo, we test
- // the one-bit value left in the virtual register.
- unsigned TstOpc = isThumb2 ? ARM::t2TSTri : ARM::TSTri;
- CmpReg = constrainOperandRegClass(TII.get(TstOpc), CmpReg, 0);
- AddOptionalDefs(
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TstOpc))
- .addReg(CmpReg)
- .addImm(1));
- unsigned CCMode = ARMCC::NE;
- if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
- std::swap(TBB, FBB);
- CCMode = ARMCC::EQ;
- }
- unsigned BrOpc = isThumb2 ? ARM::t2Bcc : ARM::Bcc;
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(BrOpc))
- .addMBB(TBB).addImm(CCMode).addReg(ARM::CPSR);
- finishCondBranch(BI->getParent(), TBB, FBB);
- return true;
- }
- bool ARMFastISel::SelectIndirectBr(const Instruction *I) {
- Register AddrReg = getRegForValue(I->getOperand(0));
- if (AddrReg == 0) return false;
- unsigned Opc = isThumb2 ? ARM::tBRIND : ARM::BX;
- assert(isThumb2 || Subtarget->hasV4TOps());
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(Opc)).addReg(AddrReg));
- const IndirectBrInst *IB = cast<IndirectBrInst>(I);
- for (const BasicBlock *SuccBB : IB->successors())
- FuncInfo.MBB->addSuccessor(FuncInfo.MBBMap[SuccBB]);
- return true;
- }
- bool ARMFastISel::ARMEmitCmp(const Value *Src1Value, const Value *Src2Value,
- bool isZExt) {
- Type *Ty = Src1Value->getType();
- EVT SrcEVT = TLI.getValueType(DL, Ty, true);
- if (!SrcEVT.isSimple()) return false;
- MVT SrcVT = SrcEVT.getSimpleVT();
- if (Ty->isFloatTy() && !Subtarget->hasVFP2Base())
- return false;
- if (Ty->isDoubleTy() && (!Subtarget->hasVFP2Base() || !Subtarget->hasFP64()))
- return false;
- // Check to see if the 2nd operand is a constant that we can encode directly
- // in the compare.
- int Imm = 0;
- bool UseImm = false;
- bool isNegativeImm = false;
- // FIXME: At -O0 we don't have anything that canonicalizes operand order.
- // Thus, Src1Value may be a ConstantInt, but we're missing it.
- if (const ConstantInt *ConstInt = dyn_cast<ConstantInt>(Src2Value)) {
- if (SrcVT == MVT::i32 || SrcVT == MVT::i16 || SrcVT == MVT::i8 ||
- SrcVT == MVT::i1) {
- const APInt &CIVal = ConstInt->getValue();
- Imm = (isZExt) ? (int)CIVal.getZExtValue() : (int)CIVal.getSExtValue();
- // For INT_MIN/LONG_MIN (i.e., 0x80000000) we need to use a cmp, rather
- // then a cmn, because there is no way to represent 2147483648 as a
- // signed 32-bit int.
- if (Imm < 0 && Imm != (int)0x80000000) {
- isNegativeImm = true;
- Imm = -Imm;
- }
- UseImm = isThumb2 ? (ARM_AM::getT2SOImmVal(Imm) != -1) :
- (ARM_AM::getSOImmVal(Imm) != -1);
- }
- } else if (const ConstantFP *ConstFP = dyn_cast<ConstantFP>(Src2Value)) {
- if (SrcVT == MVT::f32 || SrcVT == MVT::f64)
- if (ConstFP->isZero() && !ConstFP->isNegative())
- UseImm = true;
- }
- unsigned CmpOpc;
- bool isICmp = true;
- bool needsExt = false;
- switch (SrcVT.SimpleTy) {
- default: return false;
- // TODO: Verify compares.
- case MVT::f32:
- isICmp = false;
- CmpOpc = UseImm ? ARM::VCMPZS : ARM::VCMPS;
- break;
- case MVT::f64:
- isICmp = false;
- CmpOpc = UseImm ? ARM::VCMPZD : ARM::VCMPD;
- break;
- case MVT::i1:
- case MVT::i8:
- case MVT::i16:
- needsExt = true;
- LLVM_FALLTHROUGH;
- case MVT::i32:
- if (isThumb2) {
- if (!UseImm)
- CmpOpc = ARM::t2CMPrr;
- else
- CmpOpc = isNegativeImm ? ARM::t2CMNri : ARM::t2CMPri;
- } else {
- if (!UseImm)
- CmpOpc = ARM::CMPrr;
- else
- CmpOpc = isNegativeImm ? ARM::CMNri : ARM::CMPri;
- }
- break;
- }
- Register SrcReg1 = getRegForValue(Src1Value);
- if (SrcReg1 == 0) return false;
- unsigned SrcReg2 = 0;
- if (!UseImm) {
- SrcReg2 = getRegForValue(Src2Value);
- if (SrcReg2 == 0) return false;
- }
- // We have i1, i8, or i16, we need to either zero extend or sign extend.
- if (needsExt) {
- SrcReg1 = ARMEmitIntExt(SrcVT, SrcReg1, MVT::i32, isZExt);
- if (SrcReg1 == 0) return false;
- if (!UseImm) {
- SrcReg2 = ARMEmitIntExt(SrcVT, SrcReg2, MVT::i32, isZExt);
- if (SrcReg2 == 0) return false;
- }
- }
- const MCInstrDesc &II = TII.get(CmpOpc);
- SrcReg1 = constrainOperandRegClass(II, SrcReg1, 0);
- if (!UseImm) {
- SrcReg2 = constrainOperandRegClass(II, SrcReg2, 1);
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addReg(SrcReg1).addReg(SrcReg2));
- } else {
- MachineInstrBuilder MIB;
- MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addReg(SrcReg1);
- // Only add immediate for icmp as the immediate for fcmp is an implicit 0.0.
- if (isICmp)
- MIB.addImm(Imm);
- AddOptionalDefs(MIB);
- }
- // For floating point we need to move the result to a comparison register
- // that we can then use for branches.
- if (Ty->isFloatTy() || Ty->isDoubleTy())
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::FMSTAT)));
- return true;
- }
- bool ARMFastISel::SelectCmp(const Instruction *I) {
- const CmpInst *CI = cast<CmpInst>(I);
- // Get the compare predicate.
- ARMCC::CondCodes ARMPred = getComparePred(CI->getPredicate());
- // We may not handle every CC for now.
- if (ARMPred == ARMCC::AL) return false;
- // Emit the compare.
- if (!ARMEmitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned()))
- return false;
- // Now set a register based on the comparison. Explicitly set the predicates
- // here.
- unsigned MovCCOpc = isThumb2 ? ARM::t2MOVCCi : ARM::MOVCCi;
- const TargetRegisterClass *RC = isThumb2 ? &ARM::rGPRRegClass
- : &ARM::GPRRegClass;
- Register DestReg = createResultReg(RC);
- Constant *Zero = ConstantInt::get(Type::getInt32Ty(*Context), 0);
- unsigned ZeroReg = fastMaterializeConstant(Zero);
- // ARMEmitCmp emits a FMSTAT when necessary, so it's always safe to use CPSR.
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(MovCCOpc), DestReg)
- .addReg(ZeroReg).addImm(1)
- .addImm(ARMPred).addReg(ARM::CPSR);
- updateValueMap(I, DestReg);
- return true;
- }
- bool ARMFastISel::SelectFPExt(const Instruction *I) {
- // Make sure we have VFP and that we're extending float to double.
- if (!Subtarget->hasVFP2Base() || !Subtarget->hasFP64()) return false;
- Value *V = I->getOperand(0);
- if (!I->getType()->isDoubleTy() ||
- !V->getType()->isFloatTy()) return false;
- Register Op = getRegForValue(V);
- if (Op == 0) return false;
- Register Result = createResultReg(&ARM::DPRRegClass);
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::VCVTDS), Result)
- .addReg(Op));
- updateValueMap(I, Result);
- return true;
- }
- bool ARMFastISel::SelectFPTrunc(const Instruction *I) {
- // Make sure we have VFP and that we're truncating double to float.
- if (!Subtarget->hasVFP2Base() || !Subtarget->hasFP64()) return false;
- Value *V = I->getOperand(0);
- if (!(I->getType()->isFloatTy() &&
- V->getType()->isDoubleTy())) return false;
- Register Op = getRegForValue(V);
- if (Op == 0) return false;
- Register Result = createResultReg(&ARM::SPRRegClass);
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::VCVTSD), Result)
- .addReg(Op));
- updateValueMap(I, Result);
- return true;
- }
- bool ARMFastISel::SelectIToFP(const Instruction *I, bool isSigned) {
- // Make sure we have VFP.
- if (!Subtarget->hasVFP2Base()) return false;
- MVT DstVT;
- Type *Ty = I->getType();
- if (!isTypeLegal(Ty, DstVT))
- return false;
- Value *Src = I->getOperand(0);
- EVT SrcEVT = TLI.getValueType(DL, Src->getType(), true);
- if (!SrcEVT.isSimple())
- return false;
- MVT SrcVT = SrcEVT.getSimpleVT();
- if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8)
- return false;
- Register SrcReg = getRegForValue(Src);
- if (SrcReg == 0) return false;
- // Handle sign-extension.
- if (SrcVT == MVT::i16 || SrcVT == MVT::i8) {
- SrcReg = ARMEmitIntExt(SrcVT, SrcReg, MVT::i32,
- /*isZExt*/!isSigned);
- if (SrcReg == 0) return false;
- }
- // The conversion routine works on fp-reg to fp-reg and the operand above
- // was an integer, move it to the fp registers if possible.
- unsigned FP = ARMMoveToFPReg(MVT::f32, SrcReg);
- if (FP == 0) return false;
- unsigned Opc;
- if (Ty->isFloatTy()) Opc = isSigned ? ARM::VSITOS : ARM::VUITOS;
- else if (Ty->isDoubleTy() && Subtarget->hasFP64())
- Opc = isSigned ? ARM::VSITOD : ARM::VUITOD;
- else return false;
- Register ResultReg = createResultReg(TLI.getRegClassFor(DstVT));
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(Opc), ResultReg).addReg(FP));
- updateValueMap(I, ResultReg);
- return true;
- }
- bool ARMFastISel::SelectFPToI(const Instruction *I, bool isSigned) {
- // Make sure we have VFP.
- if (!Subtarget->hasVFP2Base()) return false;
- MVT DstVT;
- Type *RetTy = I->getType();
- if (!isTypeLegal(RetTy, DstVT))
- return false;
- Register Op = getRegForValue(I->getOperand(0));
- if (Op == 0) return false;
- unsigned Opc;
- Type *OpTy = I->getOperand(0)->getType();
- if (OpTy->isFloatTy()) Opc = isSigned ? ARM::VTOSIZS : ARM::VTOUIZS;
- else if (OpTy->isDoubleTy() && Subtarget->hasFP64())
- Opc = isSigned ? ARM::VTOSIZD : ARM::VTOUIZD;
- else return false;
- // f64->s32/u32 or f32->s32/u32 both need an intermediate f32 reg.
- Register ResultReg = createResultReg(TLI.getRegClassFor(MVT::f32));
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(Opc), ResultReg).addReg(Op));
- // This result needs to be in an integer register, but the conversion only
- // takes place in fp-regs.
- unsigned IntReg = ARMMoveToIntReg(DstVT, ResultReg);
- if (IntReg == 0) return false;
- updateValueMap(I, IntReg);
- return true;
- }
- bool ARMFastISel::SelectSelect(const Instruction *I) {
- MVT VT;
- if (!isTypeLegal(I->getType(), VT))
- return false;
- // Things need to be register sized for register moves.
- if (VT != MVT::i32) return false;
- Register CondReg = getRegForValue(I->getOperand(0));
- if (CondReg == 0) return false;
- Register Op1Reg = getRegForValue(I->getOperand(1));
- if (Op1Reg == 0) return false;
- // Check to see if we can use an immediate in the conditional move.
- int Imm = 0;
- bool UseImm = false;
- bool isNegativeImm = false;
- if (const ConstantInt *ConstInt = dyn_cast<ConstantInt>(I->getOperand(2))) {
- assert(VT == MVT::i32 && "Expecting an i32.");
- Imm = (int)ConstInt->getValue().getZExtValue();
- if (Imm < 0) {
- isNegativeImm = true;
- Imm = ~Imm;
- }
- UseImm = isThumb2 ? (ARM_AM::getT2SOImmVal(Imm) != -1) :
- (ARM_AM::getSOImmVal(Imm) != -1);
- }
- unsigned Op2Reg = 0;
- if (!UseImm) {
- Op2Reg = getRegForValue(I->getOperand(2));
- if (Op2Reg == 0) return false;
- }
- unsigned TstOpc = isThumb2 ? ARM::t2TSTri : ARM::TSTri;
- CondReg = constrainOperandRegClass(TII.get(TstOpc), CondReg, 0);
- AddOptionalDefs(
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TstOpc))
- .addReg(CondReg)
- .addImm(1));
- unsigned MovCCOpc;
- const TargetRegisterClass *RC;
- if (!UseImm) {
- RC = isThumb2 ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
- MovCCOpc = isThumb2 ? ARM::t2MOVCCr : ARM::MOVCCr;
- } else {
- RC = isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRRegClass;
- if (!isNegativeImm)
- MovCCOpc = isThumb2 ? ARM::t2MOVCCi : ARM::MOVCCi;
- else
- MovCCOpc = isThumb2 ? ARM::t2MVNCCi : ARM::MVNCCi;
- }
- Register ResultReg = createResultReg(RC);
- if (!UseImm) {
- Op2Reg = constrainOperandRegClass(TII.get(MovCCOpc), Op2Reg, 1);
- Op1Reg = constrainOperandRegClass(TII.get(MovCCOpc), Op1Reg, 2);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(MovCCOpc),
- ResultReg)
- .addReg(Op2Reg)
- .addReg(Op1Reg)
- .addImm(ARMCC::NE)
- .addReg(ARM::CPSR);
- } else {
- Op1Reg = constrainOperandRegClass(TII.get(MovCCOpc), Op1Reg, 1);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(MovCCOpc),
- ResultReg)
- .addReg(Op1Reg)
- .addImm(Imm)
- .addImm(ARMCC::EQ)
- .addReg(ARM::CPSR);
- }
- updateValueMap(I, ResultReg);
- return true;
- }
- bool ARMFastISel::SelectDiv(const Instruction *I, bool isSigned) {
- MVT VT;
- Type *Ty = I->getType();
- if (!isTypeLegal(Ty, VT))
- return false;
- // If we have integer div support we should have selected this automagically.
- // In case we have a real miss go ahead and return false and we'll pick
- // it up later.
- if (Subtarget->hasDivideInThumbMode())
- return false;
- // Otherwise emit a libcall.
- RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
- if (VT == MVT::i8)
- LC = isSigned ? RTLIB::SDIV_I8 : RTLIB::UDIV_I8;
- else if (VT == MVT::i16)
- LC = isSigned ? RTLIB::SDIV_I16 : RTLIB::UDIV_I16;
- else if (VT == MVT::i32)
- LC = isSigned ? RTLIB::SDIV_I32 : RTLIB::UDIV_I32;
- else if (VT == MVT::i64)
- LC = isSigned ? RTLIB::SDIV_I64 : RTLIB::UDIV_I64;
- else if (VT == MVT::i128)
- LC = isSigned ? RTLIB::SDIV_I128 : RTLIB::UDIV_I128;
- assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SDIV!");
- return ARMEmitLibcall(I, LC);
- }
- bool ARMFastISel::SelectRem(const Instruction *I, bool isSigned) {
- MVT VT;
- Type *Ty = I->getType();
- if (!isTypeLegal(Ty, VT))
- return false;
- // Many ABIs do not provide a libcall for standalone remainder, so we need to
- // use divrem (see the RTABI 4.3.1). Since FastISel can't handle non-double
- // multi-reg returns, we'll have to bail out.
- if (!TLI.hasStandaloneRem(VT)) {
- return false;
- }
- RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
- if (VT == MVT::i8)
- LC = isSigned ? RTLIB::SREM_I8 : RTLIB::UREM_I8;
- else if (VT == MVT::i16)
- LC = isSigned ? RTLIB::SREM_I16 : RTLIB::UREM_I16;
- else if (VT == MVT::i32)
- LC = isSigned ? RTLIB::SREM_I32 : RTLIB::UREM_I32;
- else if (VT == MVT::i64)
- LC = isSigned ? RTLIB::SREM_I64 : RTLIB::UREM_I64;
- else if (VT == MVT::i128)
- LC = isSigned ? RTLIB::SREM_I128 : RTLIB::UREM_I128;
- assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SREM!");
- return ARMEmitLibcall(I, LC);
- }
- bool ARMFastISel::SelectBinaryIntOp(const Instruction *I, unsigned ISDOpcode) {
- EVT DestVT = TLI.getValueType(DL, I->getType(), true);
- // We can get here in the case when we have a binary operation on a non-legal
- // type and the target independent selector doesn't know how to handle it.
- if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1)
- return false;
- unsigned Opc;
- switch (ISDOpcode) {
- default: return false;
- case ISD::ADD:
- Opc = isThumb2 ? ARM::t2ADDrr : ARM::ADDrr;
- break;
- case ISD::OR:
- Opc = isThumb2 ? ARM::t2ORRrr : ARM::ORRrr;
- break;
- case ISD::SUB:
- Opc = isThumb2 ? ARM::t2SUBrr : ARM::SUBrr;
- break;
- }
- Register SrcReg1 = getRegForValue(I->getOperand(0));
- if (SrcReg1 == 0) return false;
- // TODO: Often the 2nd operand is an immediate, which can be encoded directly
- // in the instruction, rather then materializing the value in a register.
- Register SrcReg2 = getRegForValue(I->getOperand(1));
- if (SrcReg2 == 0) return false;
- Register ResultReg = createResultReg(&ARM::GPRnopcRegClass);
- SrcReg1 = constrainOperandRegClass(TII.get(Opc), SrcReg1, 1);
- SrcReg2 = constrainOperandRegClass(TII.get(Opc), SrcReg2, 2);
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(Opc), ResultReg)
- .addReg(SrcReg1).addReg(SrcReg2));
- updateValueMap(I, ResultReg);
- return true;
- }
- bool ARMFastISel::SelectBinaryFPOp(const Instruction *I, unsigned ISDOpcode) {
- EVT FPVT = TLI.getValueType(DL, I->getType(), true);
- if (!FPVT.isSimple()) return false;
- MVT VT = FPVT.getSimpleVT();
- // FIXME: Support vector types where possible.
- if (VT.isVector())
- return false;
- // We can get here in the case when we want to use NEON for our fp
- // operations, but can't figure out how to. Just use the vfp instructions
- // if we have them.
- // FIXME: It'd be nice to use NEON instructions.
- Type *Ty = I->getType();
- if (Ty->isFloatTy() && !Subtarget->hasVFP2Base())
- return false;
- if (Ty->isDoubleTy() && (!Subtarget->hasVFP2Base() || !Subtarget->hasFP64()))
- return false;
- unsigned Opc;
- bool is64bit = VT == MVT::f64 || VT == MVT::i64;
- switch (ISDOpcode) {
- default: return false;
- case ISD::FADD:
- Opc = is64bit ? ARM::VADDD : ARM::VADDS;
- break;
- case ISD::FSUB:
- Opc = is64bit ? ARM::VSUBD : ARM::VSUBS;
- break;
- case ISD::FMUL:
- Opc = is64bit ? ARM::VMULD : ARM::VMULS;
- break;
- }
- Register Op1 = getRegForValue(I->getOperand(0));
- if (Op1 == 0) return false;
- Register Op2 = getRegForValue(I->getOperand(1));
- if (Op2 == 0) return false;
- Register ResultReg = createResultReg(TLI.getRegClassFor(VT.SimpleTy));
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(Opc), ResultReg)
- .addReg(Op1).addReg(Op2));
- updateValueMap(I, ResultReg);
- return true;
- }
- // Call Handling Code
- // This is largely taken directly from CCAssignFnForNode
- // TODO: We may not support all of this.
- CCAssignFn *ARMFastISel::CCAssignFnForCall(CallingConv::ID CC,
- bool Return,
- bool isVarArg) {
- switch (CC) {
- default:
- report_fatal_error("Unsupported calling convention");
- case CallingConv::Fast:
- if (Subtarget->hasVFP2Base() && !isVarArg) {
- if (!Subtarget->isAAPCS_ABI())
- return (Return ? RetFastCC_ARM_APCS : FastCC_ARM_APCS);
- // For AAPCS ABI targets, just use VFP variant of the calling convention.
- return (Return ? RetCC_ARM_AAPCS_VFP : CC_ARM_AAPCS_VFP);
- }
- LLVM_FALLTHROUGH;
- case CallingConv::C:
- case CallingConv::CXX_FAST_TLS:
- // Use target triple & subtarget features to do actual dispatch.
- if (Subtarget->isAAPCS_ABI()) {
- if (Subtarget->hasVFP2Base() &&
- TM.Options.FloatABIType == FloatABI::Hard && !isVarArg)
- return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP);
- else
- return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS);
- } else {
- return (Return ? RetCC_ARM_APCS: CC_ARM_APCS);
- }
- case CallingConv::ARM_AAPCS_VFP:
- case CallingConv::Swift:
- case CallingConv::SwiftTail:
- if (!isVarArg)
- return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP);
- // Fall through to soft float variant, variadic functions don't
- // use hard floating point ABI.
- LLVM_FALLTHROUGH;
- case CallingConv::ARM_AAPCS:
- return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS);
- case CallingConv::ARM_APCS:
- return (Return ? RetCC_ARM_APCS: CC_ARM_APCS);
- case CallingConv::GHC:
- if (Return)
- report_fatal_error("Can't return in GHC call convention");
- else
- return CC_ARM_APCS_GHC;
- case CallingConv::CFGuard_Check:
- return (Return ? RetCC_ARM_AAPCS : CC_ARM_Win32_CFGuard_Check);
- }
- }
- bool ARMFastISel::ProcessCallArgs(SmallVectorImpl<Value*> &Args,
- SmallVectorImpl<Register> &ArgRegs,
- SmallVectorImpl<MVT> &ArgVTs,
- SmallVectorImpl<ISD::ArgFlagsTy> &ArgFlags,
- SmallVectorImpl<Register> &RegArgs,
- CallingConv::ID CC,
- unsigned &NumBytes,
- bool isVarArg) {
- SmallVector<CCValAssign, 16> ArgLocs;
- CCState CCInfo(CC, isVarArg, *FuncInfo.MF, ArgLocs, *Context);
- CCInfo.AnalyzeCallOperands(ArgVTs, ArgFlags,
- CCAssignFnForCall(CC, false, isVarArg));
- // Check that we can handle all of the arguments. If we can't, then bail out
- // now before we add code to the MBB.
- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
- CCValAssign &VA = ArgLocs[i];
- MVT ArgVT = ArgVTs[VA.getValNo()];
- // We don't handle NEON/vector parameters yet.
- if (ArgVT.isVector() || ArgVT.getSizeInBits() > 64)
- return false;
- // Now copy/store arg to correct locations.
- if (VA.isRegLoc() && !VA.needsCustom()) {
- continue;
- } else if (VA.needsCustom()) {
- // TODO: We need custom lowering for vector (v2f64) args.
- if (VA.getLocVT() != MVT::f64 ||
- // TODO: Only handle register args for now.
- !VA.isRegLoc() || !ArgLocs[++i].isRegLoc())
- return false;
- } else {
- switch (ArgVT.SimpleTy) {
- default:
- return false;
- case MVT::i1:
- case MVT::i8:
- case MVT::i16:
- case MVT::i32:
- break;
- case MVT::f32:
- if (!Subtarget->hasVFP2Base())
- return false;
- break;
- case MVT::f64:
- if (!Subtarget->hasVFP2Base())
- return false;
- break;
- }
- }
- }
- // At the point, we are able to handle the call's arguments in fast isel.
- // Get a count of how many bytes are to be pushed on the stack.
- NumBytes = CCInfo.getNextStackOffset();
- // Issue CALLSEQ_START
- unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(AdjStackDown))
- .addImm(NumBytes).addImm(0));
- // Process the args.
- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
- CCValAssign &VA = ArgLocs[i];
- const Value *ArgVal = Args[VA.getValNo()];
- Register Arg = ArgRegs[VA.getValNo()];
- MVT ArgVT = ArgVTs[VA.getValNo()];
- assert((!ArgVT.isVector() && ArgVT.getSizeInBits() <= 64) &&
- "We don't handle NEON/vector parameters yet.");
- // Handle arg promotion, etc.
- switch (VA.getLocInfo()) {
- case CCValAssign::Full: break;
- case CCValAssign::SExt: {
- MVT DestVT = VA.getLocVT();
- Arg = ARMEmitIntExt(ArgVT, Arg, DestVT, /*isZExt*/false);
- assert(Arg != 0 && "Failed to emit a sext");
- ArgVT = DestVT;
- break;
- }
- case CCValAssign::AExt:
- // Intentional fall-through. Handle AExt and ZExt.
- case CCValAssign::ZExt: {
- MVT DestVT = VA.getLocVT();
- Arg = ARMEmitIntExt(ArgVT, Arg, DestVT, /*isZExt*/true);
- assert(Arg != 0 && "Failed to emit a zext");
- ArgVT = DestVT;
- break;
- }
- case CCValAssign::BCvt: {
- unsigned BC = fastEmit_r(ArgVT, VA.getLocVT(), ISD::BITCAST, Arg);
- assert(BC != 0 && "Failed to emit a bitcast!");
- Arg = BC;
- ArgVT = VA.getLocVT();
- break;
- }
- default: llvm_unreachable("Unknown arg promotion!");
- }
- // Now copy/store arg to correct locations.
- if (VA.isRegLoc() && !VA.needsCustom()) {
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(Arg);
- RegArgs.push_back(VA.getLocReg());
- } else if (VA.needsCustom()) {
- // TODO: We need custom lowering for vector (v2f64) args.
- assert(VA.getLocVT() == MVT::f64 &&
- "Custom lowering for v2f64 args not available");
- // FIXME: ArgLocs[++i] may extend beyond ArgLocs.size()
- CCValAssign &NextVA = ArgLocs[++i];
- assert(VA.isRegLoc() && NextVA.isRegLoc() &&
- "We only handle register args!");
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::VMOVRRD), VA.getLocReg())
- .addReg(NextVA.getLocReg(), RegState::Define)
- .addReg(Arg));
- RegArgs.push_back(VA.getLocReg());
- RegArgs.push_back(NextVA.getLocReg());
- } else {
- assert(VA.isMemLoc());
- // Need to store on the stack.
- // Don't emit stores for undef values.
- if (isa<UndefValue>(ArgVal))
- continue;
- Address Addr;
- Addr.BaseType = Address::RegBase;
- Addr.Base.Reg = ARM::SP;
- Addr.Offset = VA.getLocMemOffset();
- bool EmitRet = ARMEmitStore(ArgVT, Arg, Addr); (void)EmitRet;
- assert(EmitRet && "Could not emit a store for argument!");
- }
- }
- return true;
- }
- bool ARMFastISel::FinishCall(MVT RetVT, SmallVectorImpl<Register> &UsedRegs,
- const Instruction *I, CallingConv::ID CC,
- unsigned &NumBytes, bool isVarArg) {
- // Issue CALLSEQ_END
- unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(AdjStackUp))
- .addImm(NumBytes).addImm(-1ULL));
- // Now the return value.
- if (RetVT != MVT::isVoid) {
- SmallVector<CCValAssign, 16> RVLocs;
- CCState CCInfo(CC, isVarArg, *FuncInfo.MF, RVLocs, *Context);
- CCInfo.AnalyzeCallResult(RetVT, CCAssignFnForCall(CC, true, isVarArg));
- // Copy all of the result registers out of their specified physreg.
- if (RVLocs.size() == 2 && RetVT == MVT::f64) {
- // For this move we copy into two registers and then move into the
- // double fp reg we want.
- MVT DestVT = RVLocs[0].getValVT();
- const TargetRegisterClass* DstRC = TLI.getRegClassFor(DestVT);
- Register ResultReg = createResultReg(DstRC);
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::VMOVDRR), ResultReg)
- .addReg(RVLocs[0].getLocReg())
- .addReg(RVLocs[1].getLocReg()));
- UsedRegs.push_back(RVLocs[0].getLocReg());
- UsedRegs.push_back(RVLocs[1].getLocReg());
- // Finally update the result.
- updateValueMap(I, ResultReg);
- } else {
- assert(RVLocs.size() == 1 &&"Can't handle non-double multi-reg retvals!");
- MVT CopyVT = RVLocs[0].getValVT();
- // Special handling for extended integers.
- if (RetVT == MVT::i1 || RetVT == MVT::i8 || RetVT == MVT::i16)
- CopyVT = MVT::i32;
- const TargetRegisterClass* DstRC = TLI.getRegClassFor(CopyVT);
- Register ResultReg = createResultReg(DstRC);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY),
- ResultReg).addReg(RVLocs[0].getLocReg());
- UsedRegs.push_back(RVLocs[0].getLocReg());
- // Finally update the result.
- updateValueMap(I, ResultReg);
- }
- }
- return true;
- }
- bool ARMFastISel::SelectRet(const Instruction *I) {
- const ReturnInst *Ret = cast<ReturnInst>(I);
- const Function &F = *I->getParent()->getParent();
- const bool IsCmseNSEntry = F.hasFnAttribute("cmse_nonsecure_entry");
- if (!FuncInfo.CanLowerReturn)
- return false;
- if (TLI.supportSwiftError() &&
- F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
- return false;
- if (TLI.supportSplitCSR(FuncInfo.MF))
- return false;
- // Build a list of return value registers.
- SmallVector<unsigned, 4> RetRegs;
- CallingConv::ID CC = F.getCallingConv();
- if (Ret->getNumOperands() > 0) {
- SmallVector<ISD::OutputArg, 4> Outs;
- GetReturnInfo(CC, F.getReturnType(), F.getAttributes(), Outs, TLI, DL);
- // Analyze operands of the call, assigning locations to each operand.
- SmallVector<CCValAssign, 16> ValLocs;
- CCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs, I->getContext());
- CCInfo.AnalyzeReturn(Outs, CCAssignFnForCall(CC, true /* is Ret */,
- F.isVarArg()));
- const Value *RV = Ret->getOperand(0);
- Register Reg = getRegForValue(RV);
- if (Reg == 0)
- return false;
- // Only handle a single return value for now.
- if (ValLocs.size() != 1)
- return false;
- CCValAssign &VA = ValLocs[0];
- // Don't bother handling odd stuff for now.
- if (VA.getLocInfo() != CCValAssign::Full)
- return false;
- // Only handle register returns for now.
- if (!VA.isRegLoc())
- return false;
- unsigned SrcReg = Reg + VA.getValNo();
- EVT RVEVT = TLI.getValueType(DL, RV->getType());
- if (!RVEVT.isSimple()) return false;
- MVT RVVT = RVEVT.getSimpleVT();
- MVT DestVT = VA.getValVT();
- // Special handling for extended integers.
- if (RVVT != DestVT) {
- if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
- return false;
- assert(DestVT == MVT::i32 && "ARM should always ext to i32");
- // Perform extension if flagged as either zext or sext. Otherwise, do
- // nothing.
- if (Outs[0].Flags.isZExt() || Outs[0].Flags.isSExt()) {
- SrcReg = ARMEmitIntExt(RVVT, SrcReg, DestVT, Outs[0].Flags.isZExt());
- if (SrcReg == 0) return false;
- }
- }
- // Make the copy.
- Register DstReg = VA.getLocReg();
- const TargetRegisterClass* SrcRC = MRI.getRegClass(SrcReg);
- // Avoid a cross-class copy. This is very unlikely.
- if (!SrcRC->contains(DstReg))
- return false;
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), DstReg).addReg(SrcReg);
- // Add register to return instruction.
- RetRegs.push_back(VA.getLocReg());
- }
- unsigned RetOpc;
- if (IsCmseNSEntry)
- if (isThumb2)
- RetOpc = ARM::tBXNS_RET;
- else
- llvm_unreachable("CMSE not valid for non-Thumb targets");
- else
- RetOpc = Subtarget->getReturnOpcode();
- MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(RetOpc));
- AddOptionalDefs(MIB);
- for (unsigned R : RetRegs)
- MIB.addReg(R, RegState::Implicit);
- return true;
- }
- unsigned ARMFastISel::ARMSelectCallOp(bool UseReg) {
- if (UseReg)
- return isThumb2 ? gettBLXrOpcode(*MF) : getBLXOpcode(*MF);
- else
- return isThumb2 ? ARM::tBL : ARM::BL;
- }
- unsigned ARMFastISel::getLibcallReg(const Twine &Name) {
- // Manually compute the global's type to avoid building it when unnecessary.
- Type *GVTy = Type::getInt32PtrTy(*Context, /*AS=*/0);
- EVT LCREVT = TLI.getValueType(DL, GVTy);
- if (!LCREVT.isSimple()) return 0;
- GlobalValue *GV = M.getNamedGlobal(Name.str());
- if (!GV)
- GV = new GlobalVariable(M, Type::getInt32Ty(*Context), false,
- GlobalValue::ExternalLinkage, nullptr, Name);
- return ARMMaterializeGV(GV, LCREVT.getSimpleVT());
- }
- // A quick function that will emit a call for a named libcall in F with the
- // vector of passed arguments for the Instruction in I. We can assume that we
- // can emit a call for any libcall we can produce. This is an abridged version
- // of the full call infrastructure since we won't need to worry about things
- // like computed function pointers or strange arguments at call sites.
- // TODO: Try to unify this and the normal call bits for ARM, then try to unify
- // with X86.
- bool ARMFastISel::ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call) {
- CallingConv::ID CC = TLI.getLibcallCallingConv(Call);
- // Handle *simple* calls for now.
- Type *RetTy = I->getType();
- MVT RetVT;
- if (RetTy->isVoidTy())
- RetVT = MVT::isVoid;
- else if (!isTypeLegal(RetTy, RetVT))
- return false;
- // Can't handle non-double multi-reg retvals.
- if (RetVT != MVT::isVoid && RetVT != MVT::i32) {
- SmallVector<CCValAssign, 16> RVLocs;
- CCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context);
- CCInfo.AnalyzeCallResult(RetVT, CCAssignFnForCall(CC, true, false));
- if (RVLocs.size() >= 2 && RetVT != MVT::f64)
- return false;
- }
- // Set up the argument vectors.
- SmallVector<Value*, 8> Args;
- SmallVector<Register, 8> ArgRegs;
- SmallVector<MVT, 8> ArgVTs;
- SmallVector<ISD::ArgFlagsTy, 8> ArgFlags;
- Args.reserve(I->getNumOperands());
- ArgRegs.reserve(I->getNumOperands());
- ArgVTs.reserve(I->getNumOperands());
- ArgFlags.reserve(I->getNumOperands());
- for (Value *Op : I->operands()) {
- Register Arg = getRegForValue(Op);
- if (Arg == 0) return false;
- Type *ArgTy = Op->getType();
- MVT ArgVT;
- if (!isTypeLegal(ArgTy, ArgVT)) return false;
- ISD::ArgFlagsTy Flags;
- Flags.setOrigAlign(DL.getABITypeAlign(ArgTy));
- Args.push_back(Op);
- ArgRegs.push_back(Arg);
- ArgVTs.push_back(ArgVT);
- ArgFlags.push_back(Flags);
- }
- // Handle the arguments now that we've gotten them.
- SmallVector<Register, 4> RegArgs;
- unsigned NumBytes;
- if (!ProcessCallArgs(Args, ArgRegs, ArgVTs, ArgFlags,
- RegArgs, CC, NumBytes, false))
- return false;
- Register CalleeReg;
- if (Subtarget->genLongCalls()) {
- CalleeReg = getLibcallReg(TLI.getLibcallName(Call));
- if (CalleeReg == 0) return false;
- }
- // Issue the call.
- unsigned CallOpc = ARMSelectCallOp(Subtarget->genLongCalls());
- MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
- DbgLoc, TII.get(CallOpc));
- // BL / BLX don't take a predicate, but tBL / tBLX do.
- if (isThumb2)
- MIB.add(predOps(ARMCC::AL));
- if (Subtarget->genLongCalls()) {
- CalleeReg =
- constrainOperandRegClass(TII.get(CallOpc), CalleeReg, isThumb2 ? 2 : 0);
- MIB.addReg(CalleeReg);
- } else
- MIB.addExternalSymbol(TLI.getLibcallName(Call));
- // Add implicit physical register uses to the call.
- for (Register R : RegArgs)
- MIB.addReg(R, RegState::Implicit);
- // Add a register mask with the call-preserved registers.
- // Proper defs for return values will be added by setPhysRegsDeadExcept().
- MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC));
- // Finish off the call including any return values.
- SmallVector<Register, 4> UsedRegs;
- if (!FinishCall(RetVT, UsedRegs, I, CC, NumBytes, false)) return false;
- // Set all unused physreg defs as dead.
- static_cast<MachineInstr *>(MIB)->setPhysRegsDeadExcept(UsedRegs, TRI);
- return true;
- }
- bool ARMFastISel::SelectCall(const Instruction *I,
- const char *IntrMemName = nullptr) {
- const CallInst *CI = cast<CallInst>(I);
- const Value *Callee = CI->getCalledOperand();
- // Can't handle inline asm.
- if (isa<InlineAsm>(Callee)) return false;
- // Allow SelectionDAG isel to handle tail calls.
- if (CI->isTailCall()) return false;
- // Check the calling convention.
- CallingConv::ID CC = CI->getCallingConv();
- // TODO: Avoid some calling conventions?
- FunctionType *FTy = CI->getFunctionType();
- bool isVarArg = FTy->isVarArg();
- // Handle *simple* calls for now.
- Type *RetTy = I->getType();
- MVT RetVT;
- if (RetTy->isVoidTy())
- RetVT = MVT::isVoid;
- else if (!isTypeLegal(RetTy, RetVT) && RetVT != MVT::i16 &&
- RetVT != MVT::i8 && RetVT != MVT::i1)
- return false;
- // Can't handle non-double multi-reg retvals.
- if (RetVT != MVT::isVoid && RetVT != MVT::i1 && RetVT != MVT::i8 &&
- RetVT != MVT::i16 && RetVT != MVT::i32) {
- SmallVector<CCValAssign, 16> RVLocs;
- CCState CCInfo(CC, isVarArg, *FuncInfo.MF, RVLocs, *Context);
- CCInfo.AnalyzeCallResult(RetVT, CCAssignFnForCall(CC, true, isVarArg));
- if (RVLocs.size() >= 2 && RetVT != MVT::f64)
- return false;
- }
- // Set up the argument vectors.
- SmallVector<Value*, 8> Args;
- SmallVector<Register, 8> ArgRegs;
- SmallVector<MVT, 8> ArgVTs;
- SmallVector<ISD::ArgFlagsTy, 8> ArgFlags;
- unsigned arg_size = CI->arg_size();
- Args.reserve(arg_size);
- ArgRegs.reserve(arg_size);
- ArgVTs.reserve(arg_size);
- ArgFlags.reserve(arg_size);
- for (auto ArgI = CI->arg_begin(), ArgE = CI->arg_end(); ArgI != ArgE; ++ArgI) {
- // If we're lowering a memory intrinsic instead of a regular call, skip the
- // last argument, which shouldn't be passed to the underlying function.
- if (IntrMemName && ArgE - ArgI <= 1)
- break;
- ISD::ArgFlagsTy Flags;
- unsigned ArgIdx = ArgI - CI->arg_begin();
- if (CI->paramHasAttr(ArgIdx, Attribute::SExt))
- Flags.setSExt();
- if (CI->paramHasAttr(ArgIdx, Attribute::ZExt))
- Flags.setZExt();
- // FIXME: Only handle *easy* calls for now.
- if (CI->paramHasAttr(ArgIdx, Attribute::InReg) ||
- CI->paramHasAttr(ArgIdx, Attribute::StructRet) ||
- CI->paramHasAttr(ArgIdx, Attribute::SwiftSelf) ||
- CI->paramHasAttr(ArgIdx, Attribute::SwiftError) ||
- CI->paramHasAttr(ArgIdx, Attribute::Nest) ||
- CI->paramHasAttr(ArgIdx, Attribute::ByVal))
- return false;
- Type *ArgTy = (*ArgI)->getType();
- MVT ArgVT;
- if (!isTypeLegal(ArgTy, ArgVT) && ArgVT != MVT::i16 && ArgVT != MVT::i8 &&
- ArgVT != MVT::i1)
- return false;
- Register Arg = getRegForValue(*ArgI);
- if (!Arg.isValid())
- return false;
- Flags.setOrigAlign(DL.getABITypeAlign(ArgTy));
- Args.push_back(*ArgI);
- ArgRegs.push_back(Arg);
- ArgVTs.push_back(ArgVT);
- ArgFlags.push_back(Flags);
- }
- // Handle the arguments now that we've gotten them.
- SmallVector<Register, 4> RegArgs;
- unsigned NumBytes;
- if (!ProcessCallArgs(Args, ArgRegs, ArgVTs, ArgFlags,
- RegArgs, CC, NumBytes, isVarArg))
- return false;
- bool UseReg = false;
- const GlobalValue *GV = dyn_cast<GlobalValue>(Callee);
- if (!GV || Subtarget->genLongCalls()) UseReg = true;
- Register CalleeReg;
- if (UseReg) {
- if (IntrMemName)
- CalleeReg = getLibcallReg(IntrMemName);
- else
- CalleeReg = getRegForValue(Callee);
- if (CalleeReg == 0) return false;
- }
- // Issue the call.
- unsigned CallOpc = ARMSelectCallOp(UseReg);
- MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
- DbgLoc, TII.get(CallOpc));
- // ARM calls don't take a predicate, but tBL / tBLX do.
- if(isThumb2)
- MIB.add(predOps(ARMCC::AL));
- if (UseReg) {
- CalleeReg =
- constrainOperandRegClass(TII.get(CallOpc), CalleeReg, isThumb2 ? 2 : 0);
- MIB.addReg(CalleeReg);
- } else if (!IntrMemName)
- MIB.addGlobalAddress(GV, 0, 0);
- else
- MIB.addExternalSymbol(IntrMemName, 0);
- // Add implicit physical register uses to the call.
- for (Register R : RegArgs)
- MIB.addReg(R, RegState::Implicit);
- // Add a register mask with the call-preserved registers.
- // Proper defs for return values will be added by setPhysRegsDeadExcept().
- MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC));
- // Finish off the call including any return values.
- SmallVector<Register, 4> UsedRegs;
- if (!FinishCall(RetVT, UsedRegs, I, CC, NumBytes, isVarArg))
- return false;
- // Set all unused physreg defs as dead.
- static_cast<MachineInstr *>(MIB)->setPhysRegsDeadExcept(UsedRegs, TRI);
- return true;
- }
- bool ARMFastISel::ARMIsMemCpySmall(uint64_t Len) {
- return Len <= 16;
- }
- bool ARMFastISel::ARMTryEmitSmallMemCpy(Address Dest, Address Src,
- uint64_t Len, unsigned Alignment) {
- // Make sure we don't bloat code by inlining very large memcpy's.
- if (!ARMIsMemCpySmall(Len))
- return false;
- while (Len) {
- MVT VT;
- if (!Alignment || Alignment >= 4) {
- if (Len >= 4)
- VT = MVT::i32;
- else if (Len >= 2)
- VT = MVT::i16;
- else {
- assert(Len == 1 && "Expected a length of 1!");
- VT = MVT::i8;
- }
- } else {
- // Bound based on alignment.
- if (Len >= 2 && Alignment == 2)
- VT = MVT::i16;
- else {
- VT = MVT::i8;
- }
- }
- bool RV;
- Register ResultReg;
- RV = ARMEmitLoad(VT, ResultReg, Src);
- assert(RV && "Should be able to handle this load.");
- RV = ARMEmitStore(VT, ResultReg, Dest);
- assert(RV && "Should be able to handle this store.");
- (void)RV;
- unsigned Size = VT.getSizeInBits()/8;
- Len -= Size;
- Dest.Offset += Size;
- Src.Offset += Size;
- }
- return true;
- }
- bool ARMFastISel::SelectIntrinsicCall(const IntrinsicInst &I) {
- // FIXME: Handle more intrinsics.
- switch (I.getIntrinsicID()) {
- default: return false;
- case Intrinsic::frameaddress: {
- MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
- MFI.setFrameAddressIsTaken(true);
- unsigned LdrOpc = isThumb2 ? ARM::t2LDRi12 : ARM::LDRi12;
- const TargetRegisterClass *RC = isThumb2 ? &ARM::tGPRRegClass
- : &ARM::GPRRegClass;
- const ARMBaseRegisterInfo *RegInfo =
- static_cast<const ARMBaseRegisterInfo *>(Subtarget->getRegisterInfo());
- Register FramePtr = RegInfo->getFrameRegister(*(FuncInfo.MF));
- unsigned SrcReg = FramePtr;
- // Recursively load frame address
- // ldr r0 [fp]
- // ldr r0 [r0]
- // ldr r0 [r0]
- // ...
- unsigned DestReg;
- unsigned Depth = cast<ConstantInt>(I.getOperand(0))->getZExtValue();
- while (Depth--) {
- DestReg = createResultReg(RC);
- AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(LdrOpc), DestReg)
- .addReg(SrcReg).addImm(0));
- SrcReg = DestReg;
- }
- updateValueMap(&I, SrcReg);
- return true;
- }
- case Intrinsic::memcpy:
- case Intrinsic::memmove: {
- const MemTransferInst &MTI = cast<MemTransferInst>(I);
- // Don't handle volatile.
- if (MTI.isVolatile())
- return false;
- // Disable inlining for memmove before calls to ComputeAddress. Otherwise,
- // we would emit dead code because we don't currently handle memmoves.
- bool isMemCpy = (I.getIntrinsicID() == Intrinsic::memcpy);
- if (isa<ConstantInt>(MTI.getLength()) && isMemCpy) {
- // Small memcpy's are common enough that we want to do them without a call
- // if possible.
- uint64_t Len = cast<ConstantInt>(MTI.getLength())->getZExtValue();
- if (ARMIsMemCpySmall(Len)) {
- Address Dest, Src;
- if (!ARMComputeAddress(MTI.getRawDest(), Dest) ||
- !ARMComputeAddress(MTI.getRawSource(), Src))
- return false;
- unsigned Alignment = MinAlign(MTI.getDestAlignment(),
- MTI.getSourceAlignment());
- if (ARMTryEmitSmallMemCpy(Dest, Src, Len, Alignment))
- return true;
- }
- }
- if (!MTI.getLength()->getType()->isIntegerTy(32))
- return false;
- if (MTI.getSourceAddressSpace() > 255 || MTI.getDestAddressSpace() > 255)
- return false;
- const char *IntrMemName = isa<MemCpyInst>(I) ? "memcpy" : "memmove";
- return SelectCall(&I, IntrMemName);
- }
- case Intrinsic::memset: {
- const MemSetInst &MSI = cast<MemSetInst>(I);
- // Don't handle volatile.
- if (MSI.isVolatile())
- return false;
- if (!MSI.getLength()->getType()->isIntegerTy(32))
- return false;
- if (MSI.getDestAddressSpace() > 255)
- return false;
- return SelectCall(&I, "memset");
- }
- case Intrinsic::trap: {
- unsigned Opcode;
- if (Subtarget->isThumb())
- Opcode = ARM::tTRAP;
- else
- Opcode = Subtarget->useNaClTrap() ? ARM::TRAPNaCl : ARM::TRAP;
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opcode));
- return true;
- }
- }
- }
- bool ARMFastISel::SelectTrunc(const Instruction *I) {
- // The high bits for a type smaller than the register size are assumed to be
- // undefined.
- Value *Op = I->getOperand(0);
- EVT SrcVT, DestVT;
- SrcVT = TLI.getValueType(DL, Op->getType(), true);
- DestVT = TLI.getValueType(DL, I->getType(), true);
- if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8)
- return false;
- if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1)
- return false;
- Register SrcReg = getRegForValue(Op);
- if (!SrcReg) return false;
- // Because the high bits are undefined, a truncate doesn't generate
- // any code.
- updateValueMap(I, SrcReg);
- return true;
- }
- unsigned ARMFastISel::ARMEmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
- bool isZExt) {
- if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8)
- return 0;
- if (SrcVT != MVT::i16 && SrcVT != MVT::i8 && SrcVT != MVT::i1)
- return 0;
- // Table of which combinations can be emitted as a single instruction,
- // and which will require two.
- static const uint8_t isSingleInstrTbl[3][2][2][2] = {
- // ARM Thumb
- // !hasV6Ops hasV6Ops !hasV6Ops hasV6Ops
- // ext: s z s z s z s z
- /* 1 */ { { { 0, 1 }, { 0, 1 } }, { { 0, 0 }, { 0, 1 } } },
- /* 8 */ { { { 0, 1 }, { 1, 1 } }, { { 0, 0 }, { 1, 1 } } },
- /* 16 */ { { { 0, 0 }, { 1, 1 } }, { { 0, 0 }, { 1, 1 } } }
- };
- // Target registers for:
- // - For ARM can never be PC.
- // - For 16-bit Thumb are restricted to lower 8 registers.
- // - For 32-bit Thumb are restricted to non-SP and non-PC.
- static const TargetRegisterClass *RCTbl[2][2] = {
- // Instructions: Two Single
- /* ARM */ { &ARM::GPRnopcRegClass, &ARM::GPRnopcRegClass },
- /* Thumb */ { &ARM::tGPRRegClass, &ARM::rGPRRegClass }
- };
- // Table governing the instruction(s) to be emitted.
- static const struct InstructionTable {
- uint32_t Opc : 16;
- uint32_t hasS : 1; // Some instructions have an S bit, always set it to 0.
- uint32_t Shift : 7; // For shift operand addressing mode, used by MOVsi.
- uint32_t Imm : 8; // All instructions have either a shift or a mask.
- } IT[2][2][3][2] = {
- { // Two instructions (first is left shift, second is in this table).
- { // ARM Opc S Shift Imm
- /* 1 bit sext */ { { ARM::MOVsi , 1, ARM_AM::asr , 31 },
- /* 1 bit zext */ { ARM::MOVsi , 1, ARM_AM::lsr , 31 } },
- /* 8 bit sext */ { { ARM::MOVsi , 1, ARM_AM::asr , 24 },
- /* 8 bit zext */ { ARM::MOVsi , 1, ARM_AM::lsr , 24 } },
- /* 16 bit sext */ { { ARM::MOVsi , 1, ARM_AM::asr , 16 },
- /* 16 bit zext */ { ARM::MOVsi , 1, ARM_AM::lsr , 16 } }
- },
- { // Thumb Opc S Shift Imm
- /* 1 bit sext */ { { ARM::tASRri , 0, ARM_AM::no_shift, 31 },
- /* 1 bit zext */ { ARM::tLSRri , 0, ARM_AM::no_shift, 31 } },
- /* 8 bit sext */ { { ARM::tASRri , 0, ARM_AM::no_shift, 24 },
- /* 8 bit zext */ { ARM::tLSRri , 0, ARM_AM::no_shift, 24 } },
- /* 16 bit sext */ { { ARM::tASRri , 0, ARM_AM::no_shift, 16 },
- /* 16 bit zext */ { ARM::tLSRri , 0, ARM_AM::no_shift, 16 } }
- }
- },
- { // Single instruction.
- { // ARM Opc S Shift Imm
- /* 1 bit sext */ { { ARM::KILL , 0, ARM_AM::no_shift, 0 },
- /* 1 bit zext */ { ARM::ANDri , 1, ARM_AM::no_shift, 1 } },
- /* 8 bit sext */ { { ARM::SXTB , 0, ARM_AM::no_shift, 0 },
- /* 8 bit zext */ { ARM::ANDri , 1, ARM_AM::no_shift, 255 } },
- /* 16 bit sext */ { { ARM::SXTH , 0, ARM_AM::no_shift, 0 },
- /* 16 bit zext */ { ARM::UXTH , 0, ARM_AM::no_shift, 0 } }
- },
- { // Thumb Opc S Shift Imm
- /* 1 bit sext */ { { ARM::KILL , 0, ARM_AM::no_shift, 0 },
- /* 1 bit zext */ { ARM::t2ANDri, 1, ARM_AM::no_shift, 1 } },
- /* 8 bit sext */ { { ARM::t2SXTB , 0, ARM_AM::no_shift, 0 },
- /* 8 bit zext */ { ARM::t2ANDri, 1, ARM_AM::no_shift, 255 } },
- /* 16 bit sext */ { { ARM::t2SXTH , 0, ARM_AM::no_shift, 0 },
- /* 16 bit zext */ { ARM::t2UXTH , 0, ARM_AM::no_shift, 0 } }
- }
- }
- };
- unsigned SrcBits = SrcVT.getSizeInBits();
- unsigned DestBits = DestVT.getSizeInBits();
- (void) DestBits;
- assert((SrcBits < DestBits) && "can only extend to larger types");
- assert((DestBits == 32 || DestBits == 16 || DestBits == 8) &&
- "other sizes unimplemented");
- assert((SrcBits == 16 || SrcBits == 8 || SrcBits == 1) &&
- "other sizes unimplemented");
- bool hasV6Ops = Subtarget->hasV6Ops();
- unsigned Bitness = SrcBits / 8; // {1,8,16}=>{0,1,2}
- assert((Bitness < 3) && "sanity-check table bounds");
- bool isSingleInstr = isSingleInstrTbl[Bitness][isThumb2][hasV6Ops][isZExt];
- const TargetRegisterClass *RC = RCTbl[isThumb2][isSingleInstr];
- const InstructionTable *ITP = &IT[isSingleInstr][isThumb2][Bitness][isZExt];
- unsigned Opc = ITP->Opc;
- assert(ARM::KILL != Opc && "Invalid table entry");
- unsigned hasS = ITP->hasS;
- ARM_AM::ShiftOpc Shift = (ARM_AM::ShiftOpc) ITP->Shift;
- assert(((Shift == ARM_AM::no_shift) == (Opc != ARM::MOVsi)) &&
- "only MOVsi has shift operand addressing mode");
- unsigned Imm = ITP->Imm;
- // 16-bit Thumb instructions always set CPSR (unless they're in an IT block).
- bool setsCPSR = &ARM::tGPRRegClass == RC;
- unsigned LSLOpc = isThumb2 ? ARM::tLSLri : ARM::MOVsi;
- unsigned ResultReg;
- // MOVsi encodes shift and immediate in shift operand addressing mode.
- // The following condition has the same value when emitting two
- // instruction sequences: both are shifts.
- bool ImmIsSO = (Shift != ARM_AM::no_shift);
- // Either one or two instructions are emitted.
- // They're always of the form:
- // dst = in OP imm
- // CPSR is set only by 16-bit Thumb instructions.
- // Predicate, if any, is AL.
- // S bit, if available, is always 0.
- // When two are emitted the first's result will feed as the second's input,
- // that value is then dead.
- unsigned NumInstrsEmitted = isSingleInstr ? 1 : 2;
- for (unsigned Instr = 0; Instr != NumInstrsEmitted; ++Instr) {
- ResultReg = createResultReg(RC);
- bool isLsl = (0 == Instr) && !isSingleInstr;
- unsigned Opcode = isLsl ? LSLOpc : Opc;
- ARM_AM::ShiftOpc ShiftAM = isLsl ? ARM_AM::lsl : Shift;
- unsigned ImmEnc = ImmIsSO ? ARM_AM::getSORegOpc(ShiftAM, Imm) : Imm;
- bool isKill = 1 == Instr;
- MachineInstrBuilder MIB = BuildMI(
- *FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opcode), ResultReg);
- if (setsCPSR)
- MIB.addReg(ARM::CPSR, RegState::Define);
- SrcReg = constrainOperandRegClass(TII.get(Opcode), SrcReg, 1 + setsCPSR);
- MIB.addReg(SrcReg, isKill * RegState::Kill)
- .addImm(ImmEnc)
- .add(predOps(ARMCC::AL));
- if (hasS)
- MIB.add(condCodeOp());
- // Second instruction consumes the first's result.
- SrcReg = ResultReg;
- }
- return ResultReg;
- }
- bool ARMFastISel::SelectIntExt(const Instruction *I) {
- // On ARM, in general, integer casts don't involve legal types; this code
- // handles promotable integers.
- Type *DestTy = I->getType();
- Value *Src = I->getOperand(0);
- Type *SrcTy = Src->getType();
- bool isZExt = isa<ZExtInst>(I);
- Register SrcReg = getRegForValue(Src);
- if (!SrcReg) return false;
- EVT SrcEVT, DestEVT;
- SrcEVT = TLI.getValueType(DL, SrcTy, true);
- DestEVT = TLI.getValueType(DL, DestTy, true);
- if (!SrcEVT.isSimple()) return false;
- if (!DestEVT.isSimple()) return false;
- MVT SrcVT = SrcEVT.getSimpleVT();
- MVT DestVT = DestEVT.getSimpleVT();
- unsigned ResultReg = ARMEmitIntExt(SrcVT, SrcReg, DestVT, isZExt);
- if (ResultReg == 0) return false;
- updateValueMap(I, ResultReg);
- return true;
- }
- bool ARMFastISel::SelectShift(const Instruction *I,
- ARM_AM::ShiftOpc ShiftTy) {
- // We handle thumb2 mode by target independent selector
- // or SelectionDAG ISel.
- if (isThumb2)
- return false;
- // Only handle i32 now.
- EVT DestVT = TLI.getValueType(DL, I->getType(), true);
- if (DestVT != MVT::i32)
- return false;
- unsigned Opc = ARM::MOVsr;
- unsigned ShiftImm;
- Value *Src2Value = I->getOperand(1);
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(Src2Value)) {
- ShiftImm = CI->getZExtValue();
- // Fall back to selection DAG isel if the shift amount
- // is zero or greater than the width of the value type.
- if (ShiftImm == 0 || ShiftImm >=32)
- return false;
- Opc = ARM::MOVsi;
- }
- Value *Src1Value = I->getOperand(0);
- Register Reg1 = getRegForValue(Src1Value);
- if (Reg1 == 0) return false;
- unsigned Reg2 = 0;
- if (Opc == ARM::MOVsr) {
- Reg2 = getRegForValue(Src2Value);
- if (Reg2 == 0) return false;
- }
- Register ResultReg = createResultReg(&ARM::GPRnopcRegClass);
- if(ResultReg == 0) return false;
- MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(Opc), ResultReg)
- .addReg(Reg1);
- if (Opc == ARM::MOVsi)
- MIB.addImm(ARM_AM::getSORegOpc(ShiftTy, ShiftImm));
- else if (Opc == ARM::MOVsr) {
- MIB.addReg(Reg2);
- MIB.addImm(ARM_AM::getSORegOpc(ShiftTy, 0));
- }
- AddOptionalDefs(MIB);
- updateValueMap(I, ResultReg);
- return true;
- }
- // TODO: SoftFP support.
- bool ARMFastISel::fastSelectInstruction(const Instruction *I) {
- switch (I->getOpcode()) {
- case Instruction::Load:
- return SelectLoad(I);
- case Instruction::Store:
- return SelectStore(I);
- case Instruction::Br:
- return SelectBranch(I);
- case Instruction::IndirectBr:
- return SelectIndirectBr(I);
- case Instruction::ICmp:
- case Instruction::FCmp:
- return SelectCmp(I);
- case Instruction::FPExt:
- return SelectFPExt(I);
- case Instruction::FPTrunc:
- return SelectFPTrunc(I);
- case Instruction::SIToFP:
- return SelectIToFP(I, /*isSigned*/ true);
- case Instruction::UIToFP:
- return SelectIToFP(I, /*isSigned*/ false);
- case Instruction::FPToSI:
- return SelectFPToI(I, /*isSigned*/ true);
- case Instruction::FPToUI:
- return SelectFPToI(I, /*isSigned*/ false);
- case Instruction::Add:
- return SelectBinaryIntOp(I, ISD::ADD);
- case Instruction::Or:
- return SelectBinaryIntOp(I, ISD::OR);
- case Instruction::Sub:
- return SelectBinaryIntOp(I, ISD::SUB);
- case Instruction::FAdd:
- return SelectBinaryFPOp(I, ISD::FADD);
- case Instruction::FSub:
- return SelectBinaryFPOp(I, ISD::FSUB);
- case Instruction::FMul:
- return SelectBinaryFPOp(I, ISD::FMUL);
- case Instruction::SDiv:
- return SelectDiv(I, /*isSigned*/ true);
- case Instruction::UDiv:
- return SelectDiv(I, /*isSigned*/ false);
- case Instruction::SRem:
- return SelectRem(I, /*isSigned*/ true);
- case Instruction::URem:
- return SelectRem(I, /*isSigned*/ false);
- case Instruction::Call:
- if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I))
- return SelectIntrinsicCall(*II);
- return SelectCall(I);
- case Instruction::Select:
- return SelectSelect(I);
- case Instruction::Ret:
- return SelectRet(I);
- case Instruction::Trunc:
- return SelectTrunc(I);
- case Instruction::ZExt:
- case Instruction::SExt:
- return SelectIntExt(I);
- case Instruction::Shl:
- return SelectShift(I, ARM_AM::lsl);
- case Instruction::LShr:
- return SelectShift(I, ARM_AM::lsr);
- case Instruction::AShr:
- return SelectShift(I, ARM_AM::asr);
- default: break;
- }
- return false;
- }
- // This table describes sign- and zero-extend instructions which can be
- // folded into a preceding load. All of these extends have an immediate
- // (sometimes a mask and sometimes a shift) that's applied after
- // extension.
- static const struct FoldableLoadExtendsStruct {
- uint16_t Opc[2]; // ARM, Thumb.
- uint8_t ExpectedImm;
- uint8_t isZExt : 1;
- uint8_t ExpectedVT : 7;
- } FoldableLoadExtends[] = {
- { { ARM::SXTH, ARM::t2SXTH }, 0, 0, MVT::i16 },
- { { ARM::UXTH, ARM::t2UXTH }, 0, 1, MVT::i16 },
- { { ARM::ANDri, ARM::t2ANDri }, 255, 1, MVT::i8 },
- { { ARM::SXTB, ARM::t2SXTB }, 0, 0, MVT::i8 },
- { { ARM::UXTB, ARM::t2UXTB }, 0, 1, MVT::i8 }
- };
- /// The specified machine instr operand is a vreg, and that
- /// vreg is being provided by the specified load instruction. If possible,
- /// try to fold the load as an operand to the instruction, returning true if
- /// successful.
- bool ARMFastISel::tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
- const LoadInst *LI) {
- // Verify we have a legal type before going any further.
- MVT VT;
- if (!isLoadTypeLegal(LI->getType(), VT))
- return false;
- // Combine load followed by zero- or sign-extend.
- // ldrb r1, [r0] ldrb r1, [r0]
- // uxtb r2, r1 =>
- // mov r3, r2 mov r3, r1
- if (MI->getNumOperands() < 3 || !MI->getOperand(2).isImm())
- return false;
- const uint64_t Imm = MI->getOperand(2).getImm();
- bool Found = false;
- bool isZExt;
- for (const FoldableLoadExtendsStruct &FLE : FoldableLoadExtends) {
- if (FLE.Opc[isThumb2] == MI->getOpcode() &&
- (uint64_t)FLE.ExpectedImm == Imm &&
- MVT((MVT::SimpleValueType)FLE.ExpectedVT) == VT) {
- Found = true;
- isZExt = FLE.isZExt;
- }
- }
- if (!Found) return false;
- // See if we can handle this address.
- Address Addr;
- if (!ARMComputeAddress(LI->getOperand(0), Addr)) return false;
- Register ResultReg = MI->getOperand(0).getReg();
- if (!ARMEmitLoad(VT, ResultReg, Addr, LI->getAlignment(), isZExt, false))
- return false;
- MachineBasicBlock::iterator I(MI);
- removeDeadCode(I, std::next(I));
- return true;
- }
- unsigned ARMFastISel::ARMLowerPICELF(const GlobalValue *GV, MVT VT) {
- bool UseGOT_PREL = !TM.shouldAssumeDSOLocal(*GV->getParent(), GV);
- LLVMContext *Context = &MF->getFunction().getContext();
- unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
- unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
- ARMConstantPoolValue *CPV = ARMConstantPoolConstant::Create(
- GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj,
- UseGOT_PREL ? ARMCP::GOT_PREL : ARMCP::no_modifier,
- /*AddCurrentAddress=*/UseGOT_PREL);
- Align ConstAlign =
- MF->getDataLayout().getPrefTypeAlign(Type::getInt32PtrTy(*Context));
- unsigned Idx = MF->getConstantPool()->getConstantPoolIndex(CPV, ConstAlign);
- MachineMemOperand *CPMMO =
- MF->getMachineMemOperand(MachinePointerInfo::getConstantPool(*MF),
- MachineMemOperand::MOLoad, 4, Align(4));
- Register TempReg = MF->getRegInfo().createVirtualRegister(&ARM::rGPRRegClass);
- unsigned Opc = isThumb2 ? ARM::t2LDRpci : ARM::LDRcp;
- MachineInstrBuilder MIB =
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), TempReg)
- .addConstantPoolIndex(Idx)
- .addMemOperand(CPMMO);
- if (Opc == ARM::LDRcp)
- MIB.addImm(0);
- MIB.add(predOps(ARMCC::AL));
- // Fix the address by adding pc.
- Register DestReg = createResultReg(TLI.getRegClassFor(VT));
- Opc = Subtarget->isThumb() ? ARM::tPICADD : UseGOT_PREL ? ARM::PICLDR
- : ARM::PICADD;
- DestReg = constrainOperandRegClass(TII.get(Opc), DestReg, 0);
- MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), DestReg)
- .addReg(TempReg)
- .addImm(ARMPCLabelIndex);
- if (!Subtarget->isThumb())
- MIB.add(predOps(ARMCC::AL));
- if (UseGOT_PREL && Subtarget->isThumb()) {
- Register NewDestReg = createResultReg(TLI.getRegClassFor(VT));
- MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(ARM::t2LDRi12), NewDestReg)
- .addReg(DestReg)
- .addImm(0);
- DestReg = NewDestReg;
- AddOptionalDefs(MIB);
- }
- return DestReg;
- }
- bool ARMFastISel::fastLowerArguments() {
- if (!FuncInfo.CanLowerReturn)
- return false;
- const Function *F = FuncInfo.Fn;
- if (F->isVarArg())
- return false;
- CallingConv::ID CC = F->getCallingConv();
- switch (CC) {
- default:
- return false;
- case CallingConv::Fast:
- case CallingConv::C:
- case CallingConv::ARM_AAPCS_VFP:
- case CallingConv::ARM_AAPCS:
- case CallingConv::ARM_APCS:
- case CallingConv::Swift:
- case CallingConv::SwiftTail:
- break;
- }
- // Only handle simple cases. i.e. Up to 4 i8/i16/i32 scalar arguments
- // which are passed in r0 - r3.
- for (const Argument &Arg : F->args()) {
- if (Arg.getArgNo() >= 4)
- return false;
- if (Arg.hasAttribute(Attribute::InReg) ||
- Arg.hasAttribute(Attribute::StructRet) ||
- Arg.hasAttribute(Attribute::SwiftSelf) ||
- Arg.hasAttribute(Attribute::SwiftError) ||
- Arg.hasAttribute(Attribute::ByVal))
- return false;
- Type *ArgTy = Arg.getType();
- if (ArgTy->isStructTy() || ArgTy->isArrayTy() || ArgTy->isVectorTy())
- return false;
- EVT ArgVT = TLI.getValueType(DL, ArgTy);
- if (!ArgVT.isSimple()) return false;
- switch (ArgVT.getSimpleVT().SimpleTy) {
- case MVT::i8:
- case MVT::i16:
- case MVT::i32:
- break;
- default:
- return false;
- }
- }
- static const MCPhysReg GPRArgRegs[] = {
- ARM::R0, ARM::R1, ARM::R2, ARM::R3
- };
- const TargetRegisterClass *RC = &ARM::rGPRRegClass;
- for (const Argument &Arg : F->args()) {
- unsigned ArgNo = Arg.getArgNo();
- unsigned SrcReg = GPRArgRegs[ArgNo];
- Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
- // FIXME: Unfortunately it's necessary to emit a copy from the livein copy.
- // Without this, EmitLiveInCopies may eliminate the livein if its only
- // use is a bitcast (which isn't turned into an instruction).
- Register ResultReg = createResultReg(RC);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY),
- ResultReg).addReg(DstReg, getKillRegState(true));
- updateValueMap(&Arg, ResultReg);
- }
- return true;
- }
- namespace llvm {
- FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo,
- const TargetLibraryInfo *libInfo) {
- if (funcInfo.MF->getSubtarget<ARMSubtarget>().useFastISel())
- return new ARMFastISel(funcInfo, libInfo);
- return nullptr;
- }
- } // end namespace llvm
|