123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226 |
- //===-- FastISel.cpp - Implementation of the FastISel class ---------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This file contains the implementation of the FastISel class.
- //
- // "Fast" instruction selection is designed to emit very poor code quickly.
- // Also, it is not designed to be able to do much lowering, so most illegal
- // types (e.g. i64 on 32-bit targets) and operations are not supported. It is
- // also not intended to be able to do much optimization, except in a few cases
- // where doing optimizations reduces overall compile time. For example, folding
- // constants into immediate fields is often done, because it's cheap and it
- // reduces the number of instructions later phases have to examine.
- //
- // "Fast" instruction selection is able to fail gracefully and transfer
- // control to the SelectionDAG selector for operations that it doesn't
- // support. In many cases, this allows us to avoid duplicating a lot of
- // the complicated lowering logic that SelectionDAG currently has.
- //
- // The intended use for "fast" instruction selection is "-O0" mode
- // compilation, where the quality of the generated code is irrelevant when
- // weighed against the speed at which the code can be generated. Also,
- // at -O0, the LLVM optimizers are not running, and this makes the
- // compile time of codegen a much higher portion of the overall compile
- // time. Despite its limitations, "fast" instruction selection is able to
- // handle enough code on its own to provide noticeable overall speedups
- // in -O0 compiles.
- //
- // Basic operations are supported in a target-independent way, by reading
- // the same instruction descriptions that the SelectionDAG selector reads,
- // and identifying simple arithmetic operations that can be directly selected
- // from simple operators. More complicated operations currently require
- // target-specific code.
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/CodeGen/Analysis.h"
- #include "llvm/ADT/Optional.h"
- #include "llvm/ADT/Statistic.h"
- #include "llvm/Analysis/BranchProbabilityInfo.h"
- #include "llvm/Analysis/Loads.h"
- #include "llvm/Analysis/TargetLibraryInfo.h"
- #include "llvm/CodeGen/Analysis.h"
- #include "llvm/CodeGen/FastISel.h"
- #include "llvm/CodeGen/FunctionLoweringInfo.h"
- #include "llvm/CodeGen/MachineFrameInfo.h"
- #include "llvm/CodeGen/MachineInstrBuilder.h"
- #include "llvm/CodeGen/MachineModuleInfo.h"
- #include "llvm/CodeGen/MachineRegisterInfo.h"
- #include "llvm/CodeGen/StackMaps.h"
- #include "llvm/IR/DataLayout.h"
- #include "llvm/IR/DebugInfo.h"
- #include "llvm/IR/Function.h"
- #include "llvm/IR/GlobalVariable.h"
- #include "llvm/IR/Instructions.h"
- #include "llvm/IR/IntrinsicInst.h"
- #include "llvm/IR/Mangler.h"
- #include "llvm/IR/Operator.h"
- #include "llvm/Support/Debug.h"
- #include "llvm/Support/ErrorHandling.h"
- #include "llvm/Support/raw_ostream.h"
- #include "llvm/Target/TargetInstrInfo.h"
- #include "llvm/Target/TargetLowering.h"
- #include "llvm/Target/TargetMachine.h"
- #include "llvm/Target/TargetSubtargetInfo.h"
- using namespace llvm;
- #define DEBUG_TYPE "isel"
- STATISTIC(NumFastIselSuccessIndependent, "Number of insts selected by "
- "target-independent selector");
- STATISTIC(NumFastIselSuccessTarget, "Number of insts selected by "
- "target-specific selector");
- STATISTIC(NumFastIselDead, "Number of dead insts removed on failure");
- void FastISel::ArgListEntry::setAttributes(ImmutableCallSite *CS,
- unsigned AttrIdx) {
- IsSExt = CS->paramHasAttr(AttrIdx, Attribute::SExt);
- IsZExt = CS->paramHasAttr(AttrIdx, Attribute::ZExt);
- IsInReg = CS->paramHasAttr(AttrIdx, Attribute::InReg);
- IsSRet = CS->paramHasAttr(AttrIdx, Attribute::StructRet);
- IsNest = CS->paramHasAttr(AttrIdx, Attribute::Nest);
- IsByVal = CS->paramHasAttr(AttrIdx, Attribute::ByVal);
- IsInAlloca = CS->paramHasAttr(AttrIdx, Attribute::InAlloca);
- IsReturned = CS->paramHasAttr(AttrIdx, Attribute::Returned);
- Alignment = CS->getParamAlignment(AttrIdx);
- }
- /// Set the current block to which generated machine instructions will be
- /// appended, and clear the local CSE map.
- void FastISel::startNewBlock() {
- LocalValueMap.clear();
- // Instructions are appended to FuncInfo.MBB. If the basic block already
- // contains labels or copies, use the last instruction as the last local
- // value.
- EmitStartPt = nullptr;
- if (!FuncInfo.MBB->empty())
- EmitStartPt = &FuncInfo.MBB->back();
- LastLocalValue = EmitStartPt;
- }
- bool FastISel::lowerArguments() {
- if (!FuncInfo.CanLowerReturn)
- // Fallback to SDISel argument lowering code to deal with sret pointer
- // parameter.
- return false;
- if (!fastLowerArguments())
- return false;
- // Enter arguments into ValueMap for uses in non-entry BBs.
- for (Function::const_arg_iterator I = FuncInfo.Fn->arg_begin(),
- E = FuncInfo.Fn->arg_end();
- I != E; ++I) {
- DenseMap<const Value *, unsigned>::iterator VI = LocalValueMap.find(I);
- assert(VI != LocalValueMap.end() && "Missed an argument?");
- FuncInfo.ValueMap[I] = VI->second;
- }
- return true;
- }
- void FastISel::flushLocalValueMap() {
- LocalValueMap.clear();
- LastLocalValue = EmitStartPt;
- recomputeInsertPt();
- SavedInsertPt = FuncInfo.InsertPt;
- }
- bool FastISel::hasTrivialKill(const Value *V) {
- // Don't consider constants or arguments to have trivial kills.
- const Instruction *I = dyn_cast<Instruction>(V);
- if (!I)
- return false;
- // No-op casts are trivially coalesced by fast-isel.
- if (const auto *Cast = dyn_cast<CastInst>(I))
- if (Cast->isNoopCast(DL.getIntPtrType(Cast->getContext())) &&
- !hasTrivialKill(Cast->getOperand(0)))
- return false;
- // Even the value might have only one use in the LLVM IR, it is possible that
- // FastISel might fold the use into another instruction and now there is more
- // than one use at the Machine Instruction level.
- unsigned Reg = lookUpRegForValue(V);
- if (Reg && !MRI.use_empty(Reg))
- return false;
- // GEPs with all zero indices are trivially coalesced by fast-isel.
- if (const auto *GEP = dyn_cast<GetElementPtrInst>(I))
- if (GEP->hasAllZeroIndices() && !hasTrivialKill(GEP->getOperand(0)))
- return false;
- // Only instructions with a single use in the same basic block are considered
- // to have trivial kills.
- return I->hasOneUse() &&
- !(I->getOpcode() == Instruction::BitCast ||
- I->getOpcode() == Instruction::PtrToInt ||
- I->getOpcode() == Instruction::IntToPtr) &&
- cast<Instruction>(*I->user_begin())->getParent() == I->getParent();
- }
- unsigned FastISel::getRegForValue(const Value *V) {
- EVT RealVT = TLI.getValueType(DL, V->getType(), /*AllowUnknown=*/true);
- // Don't handle non-simple values in FastISel.
- if (!RealVT.isSimple())
- return 0;
- // Ignore illegal types. We must do this before looking up the value
- // in ValueMap because Arguments are given virtual registers regardless
- // of whether FastISel can handle them.
- MVT VT = RealVT.getSimpleVT();
- if (!TLI.isTypeLegal(VT)) {
- // Handle integer promotions, though, because they're common and easy.
- if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)
- VT = TLI.getTypeToTransformTo(V->getContext(), VT).getSimpleVT();
- else
- return 0;
- }
- // Look up the value to see if we already have a register for it.
- unsigned Reg = lookUpRegForValue(V);
- if (Reg)
- return Reg;
- // In bottom-up mode, just create the virtual register which will be used
- // to hold the value. It will be materialized later.
- if (isa<Instruction>(V) &&
- (!isa<AllocaInst>(V) ||
- !FuncInfo.StaticAllocaMap.count(cast<AllocaInst>(V))))
- return FuncInfo.InitializeRegForValue(V);
- SavePoint SaveInsertPt = enterLocalValueArea();
- // Materialize the value in a register. Emit any instructions in the
- // local value area.
- Reg = materializeRegForValue(V, VT);
- leaveLocalValueArea(SaveInsertPt);
- return Reg;
- }
- unsigned FastISel::materializeConstant(const Value *V, MVT VT) {
- unsigned Reg = 0;
- if (const auto *CI = dyn_cast<ConstantInt>(V)) {
- if (CI->getValue().getActiveBits() <= 64)
- Reg = fastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue());
- } else if (isa<AllocaInst>(V))
- Reg = fastMaterializeAlloca(cast<AllocaInst>(V));
- else if (isa<ConstantPointerNull>(V))
- // Translate this as an integer zero so that it can be
- // local-CSE'd with actual integer zeros.
- Reg = getRegForValue(
- Constant::getNullValue(DL.getIntPtrType(V->getContext())));
- else if (const auto *CF = dyn_cast<ConstantFP>(V)) {
- if (CF->isNullValue())
- Reg = fastMaterializeFloatZero(CF);
- else
- // Try to emit the constant directly.
- Reg = fastEmit_f(VT, VT, ISD::ConstantFP, CF);
- if (!Reg) {
- // Try to emit the constant by using an integer constant with a cast.
- const APFloat &Flt = CF->getValueAPF();
- EVT IntVT = TLI.getPointerTy(DL);
- uint64_t x[2];
- uint32_t IntBitWidth = IntVT.getSizeInBits();
- bool isExact;
- (void)Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true,
- APFloat::rmTowardZero, &isExact);
- if (isExact) {
- APInt IntVal(IntBitWidth, x);
- unsigned IntegerReg =
- getRegForValue(ConstantInt::get(V->getContext(), IntVal));
- if (IntegerReg != 0)
- Reg = fastEmit_r(IntVT.getSimpleVT(), VT, ISD::SINT_TO_FP, IntegerReg,
- /*Kill=*/false);
- }
- }
- } else if (const auto *Op = dyn_cast<Operator>(V)) {
- if (!selectOperator(Op, Op->getOpcode()))
- if (!isa<Instruction>(Op) ||
- !fastSelectInstruction(cast<Instruction>(Op)))
- return 0;
- Reg = lookUpRegForValue(Op);
- } else if (isa<UndefValue>(V)) {
- Reg = createResultReg(TLI.getRegClassFor(VT));
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::IMPLICIT_DEF), Reg);
- }
- return Reg;
- }
- /// Helper for getRegForValue. This function is called when the value isn't
- /// already available in a register and must be materialized with new
- /// instructions.
- unsigned FastISel::materializeRegForValue(const Value *V, MVT VT) {
- unsigned Reg = 0;
- // Give the target-specific code a try first.
- if (isa<Constant>(V))
- Reg = fastMaterializeConstant(cast<Constant>(V));
- // If target-specific code couldn't or didn't want to handle the value, then
- // give target-independent code a try.
- if (!Reg)
- Reg = materializeConstant(V, VT);
- // Don't cache constant materializations in the general ValueMap.
- // To do so would require tracking what uses they dominate.
- if (Reg) {
- LocalValueMap[V] = Reg;
- LastLocalValue = MRI.getVRegDef(Reg);
- }
- return Reg;
- }
- unsigned FastISel::lookUpRegForValue(const Value *V) {
- // Look up the value to see if we already have a register for it. We
- // cache values defined by Instructions across blocks, and other values
- // only locally. This is because Instructions already have the SSA
- // def-dominates-use requirement enforced.
- DenseMap<const Value *, unsigned>::iterator I = FuncInfo.ValueMap.find(V);
- if (I != FuncInfo.ValueMap.end())
- return I->second;
- return LocalValueMap[V];
- }
- void FastISel::updateValueMap(const Value *I, unsigned Reg, unsigned NumRegs) {
- if (!isa<Instruction>(I)) {
- LocalValueMap[I] = Reg;
- return;
- }
- unsigned &AssignedReg = FuncInfo.ValueMap[I];
- if (AssignedReg == 0)
- // Use the new register.
- AssignedReg = Reg;
- else if (Reg != AssignedReg) {
- // Arrange for uses of AssignedReg to be replaced by uses of Reg.
- for (unsigned i = 0; i < NumRegs; i++)
- FuncInfo.RegFixups[AssignedReg + i] = Reg + i;
- AssignedReg = Reg;
- }
- }
- std::pair<unsigned, bool> FastISel::getRegForGEPIndex(const Value *Idx) {
- unsigned IdxN = getRegForValue(Idx);
- if (IdxN == 0)
- // Unhandled operand. Halt "fast" selection and bail.
- return std::pair<unsigned, bool>(0, false);
- bool IdxNIsKill = hasTrivialKill(Idx);
- // If the index is smaller or larger than intptr_t, truncate or extend it.
- MVT PtrVT = TLI.getPointerTy(DL);
- EVT IdxVT = EVT::getEVT(Idx->getType(), /*HandleUnknown=*/false);
- if (IdxVT.bitsLT(PtrVT)) {
- IdxN = fastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::SIGN_EXTEND, IdxN,
- IdxNIsKill);
- IdxNIsKill = true;
- } else if (IdxVT.bitsGT(PtrVT)) {
- IdxN =
- fastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::TRUNCATE, IdxN, IdxNIsKill);
- IdxNIsKill = true;
- }
- return std::pair<unsigned, bool>(IdxN, IdxNIsKill);
- }
- void FastISel::recomputeInsertPt() {
- if (getLastLocalValue()) {
- FuncInfo.InsertPt = getLastLocalValue();
- FuncInfo.MBB = FuncInfo.InsertPt->getParent();
- ++FuncInfo.InsertPt;
- } else
- FuncInfo.InsertPt = FuncInfo.MBB->getFirstNonPHI();
- // Now skip past any EH_LABELs, which must remain at the beginning.
- while (FuncInfo.InsertPt != FuncInfo.MBB->end() &&
- FuncInfo.InsertPt->getOpcode() == TargetOpcode::EH_LABEL)
- ++FuncInfo.InsertPt;
- }
- void FastISel::removeDeadCode(MachineBasicBlock::iterator I,
- MachineBasicBlock::iterator E) {
- assert(I && E && std::distance(I, E) > 0 && "Invalid iterator!");
- while (I != E) {
- MachineInstr *Dead = &*I;
- ++I;
- Dead->eraseFromParent();
- ++NumFastIselDead;
- }
- recomputeInsertPt();
- }
- FastISel::SavePoint FastISel::enterLocalValueArea() {
- MachineBasicBlock::iterator OldInsertPt = FuncInfo.InsertPt;
- DebugLoc OldDL = DbgLoc;
- recomputeInsertPt();
- DbgLoc = DebugLoc();
- SavePoint SP = {OldInsertPt, OldDL};
- return SP;
- }
- void FastISel::leaveLocalValueArea(SavePoint OldInsertPt) {
- if (FuncInfo.InsertPt != FuncInfo.MBB->begin())
- LastLocalValue = std::prev(FuncInfo.InsertPt);
- // Restore the previous insert position.
- FuncInfo.InsertPt = OldInsertPt.InsertPt;
- DbgLoc = OldInsertPt.DL;
- }
- bool FastISel::selectBinaryOp(const User *I, unsigned ISDOpcode) {
- EVT VT = EVT::getEVT(I->getType(), /*HandleUnknown=*/true);
- if (VT == MVT::Other || !VT.isSimple())
- // Unhandled type. Halt "fast" selection and bail.
- return false;
- // We only handle legal types. For example, on x86-32 the instruction
- // selector contains all of the 64-bit instructions from x86-64,
- // under the assumption that i64 won't be used if the target doesn't
- // support it.
- if (!TLI.isTypeLegal(VT)) {
- // MVT::i1 is special. Allow AND, OR, or XOR because they
- // don't require additional zeroing, which makes them easy.
- if (VT == MVT::i1 && (ISDOpcode == ISD::AND || ISDOpcode == ISD::OR ||
- ISDOpcode == ISD::XOR))
- VT = TLI.getTypeToTransformTo(I->getContext(), VT);
- else
- return false;
- }
- // Check if the first operand is a constant, and handle it as "ri". At -O0,
- // we don't have anything that canonicalizes operand order.
- if (const auto *CI = dyn_cast<ConstantInt>(I->getOperand(0)))
- if (isa<Instruction>(I) && cast<Instruction>(I)->isCommutative()) {
- unsigned Op1 = getRegForValue(I->getOperand(1));
- if (!Op1)
- return false;
- bool Op1IsKill = hasTrivialKill(I->getOperand(1));
- unsigned ResultReg =
- fastEmit_ri_(VT.getSimpleVT(), ISDOpcode, Op1, Op1IsKill,
- CI->getZExtValue(), VT.getSimpleVT());
- if (!ResultReg)
- return false;
- // We successfully emitted code for the given LLVM Instruction.
- updateValueMap(I, ResultReg);
- return true;
- }
- unsigned Op0 = getRegForValue(I->getOperand(0));
- if (!Op0) // Unhandled operand. Halt "fast" selection and bail.
- return false;
- bool Op0IsKill = hasTrivialKill(I->getOperand(0));
- // Check if the second operand is a constant and handle it appropriately.
- if (const auto *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
- uint64_t Imm = CI->getSExtValue();
- // Transform "sdiv exact X, 8" -> "sra X, 3".
- if (ISDOpcode == ISD::SDIV && isa<BinaryOperator>(I) &&
- cast<BinaryOperator>(I)->isExact() && isPowerOf2_64(Imm)) {
- Imm = Log2_64(Imm);
- ISDOpcode = ISD::SRA;
- }
- // Transform "urem x, pow2" -> "and x, pow2-1".
- if (ISDOpcode == ISD::UREM && isa<BinaryOperator>(I) &&
- isPowerOf2_64(Imm)) {
- --Imm;
- ISDOpcode = ISD::AND;
- }
- unsigned ResultReg = fastEmit_ri_(VT.getSimpleVT(), ISDOpcode, Op0,
- Op0IsKill, Imm, VT.getSimpleVT());
- if (!ResultReg)
- return false;
- // We successfully emitted code for the given LLVM Instruction.
- updateValueMap(I, ResultReg);
- return true;
- }
- // Check if the second operand is a constant float.
- if (const auto *CF = dyn_cast<ConstantFP>(I->getOperand(1))) {
- unsigned ResultReg = fastEmit_rf(VT.getSimpleVT(), VT.getSimpleVT(),
- ISDOpcode, Op0, Op0IsKill, CF);
- if (ResultReg) {
- // We successfully emitted code for the given LLVM Instruction.
- updateValueMap(I, ResultReg);
- return true;
- }
- }
- unsigned Op1 = getRegForValue(I->getOperand(1));
- if (!Op1) // Unhandled operand. Halt "fast" selection and bail.
- return false;
- bool Op1IsKill = hasTrivialKill(I->getOperand(1));
- // Now we have both operands in registers. Emit the instruction.
- unsigned ResultReg = fastEmit_rr(VT.getSimpleVT(), VT.getSimpleVT(),
- ISDOpcode, Op0, Op0IsKill, Op1, Op1IsKill);
- if (!ResultReg)
- // Target-specific code wasn't able to find a machine opcode for
- // the given ISD opcode and type. Halt "fast" selection and bail.
- return false;
- // We successfully emitted code for the given LLVM Instruction.
- updateValueMap(I, ResultReg);
- return true;
- }
- bool FastISel::selectGetElementPtr(const User *I) {
- unsigned N = getRegForValue(I->getOperand(0));
- if (!N) // Unhandled operand. Halt "fast" selection and bail.
- return false;
- bool NIsKill = hasTrivialKill(I->getOperand(0));
- // Keep a running tab of the total offset to coalesce multiple N = N + Offset
- // into a single N = N + TotalOffset.
- uint64_t TotalOffs = 0;
- // FIXME: What's a good SWAG number for MaxOffs?
- uint64_t MaxOffs = 2048;
- Type *Ty = I->getOperand(0)->getType();
- MVT VT = TLI.getPointerTy(DL);
- for (GetElementPtrInst::const_op_iterator OI = I->op_begin() + 1,
- E = I->op_end();
- OI != E; ++OI) {
- const Value *Idx = *OI;
- if (auto *StTy = dyn_cast<StructType>(Ty)) {
- uint64_t Field = cast<ConstantInt>(Idx)->getZExtValue();
- if (Field) {
- // N = N + Offset
- TotalOffs += DL.getStructLayout(StTy)->getElementOffset(Field);
- if (TotalOffs >= MaxOffs) {
- N = fastEmit_ri_(VT, ISD::ADD, N, NIsKill, TotalOffs, VT);
- if (!N) // Unhandled operand. Halt "fast" selection and bail.
- return false;
- NIsKill = true;
- TotalOffs = 0;
- }
- }
- Ty = StTy->getElementType(Field);
- } else {
- Ty = cast<SequentialType>(Ty)->getElementType();
- // If this is a constant subscript, handle it quickly.
- if (const auto *CI = dyn_cast<ConstantInt>(Idx)) {
- if (CI->isZero())
- continue;
- // N = N + Offset
- uint64_t IdxN = CI->getValue().sextOrTrunc(64).getSExtValue();
- TotalOffs += DL.getTypeAllocSize(Ty) * IdxN;
- if (TotalOffs >= MaxOffs) {
- N = fastEmit_ri_(VT, ISD::ADD, N, NIsKill, TotalOffs, VT);
- if (!N) // Unhandled operand. Halt "fast" selection and bail.
- return false;
- NIsKill = true;
- TotalOffs = 0;
- }
- continue;
- }
- if (TotalOffs) {
- N = fastEmit_ri_(VT, ISD::ADD, N, NIsKill, TotalOffs, VT);
- if (!N) // Unhandled operand. Halt "fast" selection and bail.
- return false;
- NIsKill = true;
- TotalOffs = 0;
- }
- // N = N + Idx * ElementSize;
- uint64_t ElementSize = DL.getTypeAllocSize(Ty);
- std::pair<unsigned, bool> Pair = getRegForGEPIndex(Idx);
- unsigned IdxN = Pair.first;
- bool IdxNIsKill = Pair.second;
- if (!IdxN) // Unhandled operand. Halt "fast" selection and bail.
- return false;
- if (ElementSize != 1) {
- IdxN = fastEmit_ri_(VT, ISD::MUL, IdxN, IdxNIsKill, ElementSize, VT);
- if (!IdxN) // Unhandled operand. Halt "fast" selection and bail.
- return false;
- IdxNIsKill = true;
- }
- N = fastEmit_rr(VT, VT, ISD::ADD, N, NIsKill, IdxN, IdxNIsKill);
- if (!N) // Unhandled operand. Halt "fast" selection and bail.
- return false;
- }
- }
- if (TotalOffs) {
- N = fastEmit_ri_(VT, ISD::ADD, N, NIsKill, TotalOffs, VT);
- if (!N) // Unhandled operand. Halt "fast" selection and bail.
- return false;
- }
- // We successfully emitted code for the given LLVM Instruction.
- updateValueMap(I, N);
- return true;
- }
- bool FastISel::addStackMapLiveVars(SmallVectorImpl<MachineOperand> &Ops,
- const CallInst *CI, unsigned StartIdx) {
- for (unsigned i = StartIdx, e = CI->getNumArgOperands(); i != e; ++i) {
- Value *Val = CI->getArgOperand(i);
- // Check for constants and encode them with a StackMaps::ConstantOp prefix.
- if (const auto *C = dyn_cast<ConstantInt>(Val)) {
- Ops.push_back(MachineOperand::CreateImm(StackMaps::ConstantOp));
- Ops.push_back(MachineOperand::CreateImm(C->getSExtValue()));
- } else if (isa<ConstantPointerNull>(Val)) {
- Ops.push_back(MachineOperand::CreateImm(StackMaps::ConstantOp));
- Ops.push_back(MachineOperand::CreateImm(0));
- } else if (auto *AI = dyn_cast<AllocaInst>(Val)) {
- // Values coming from a stack location also require a sepcial encoding,
- // but that is added later on by the target specific frame index
- // elimination implementation.
- auto SI = FuncInfo.StaticAllocaMap.find(AI);
- if (SI != FuncInfo.StaticAllocaMap.end())
- Ops.push_back(MachineOperand::CreateFI(SI->second));
- else
- return false;
- } else {
- unsigned Reg = getRegForValue(Val);
- if (!Reg)
- return false;
- Ops.push_back(MachineOperand::CreateReg(Reg, /*IsDef=*/false));
- }
- }
- return true;
- }
- bool FastISel::selectStackmap(const CallInst *I) {
- // void @llvm.experimental.stackmap(i64 <id>, i32 <numShadowBytes>,
- // [live variables...])
- assert(I->getCalledFunction()->getReturnType()->isVoidTy() &&
- "Stackmap cannot return a value.");
- // The stackmap intrinsic only records the live variables (the arguments
- // passed to it) and emits NOPS (if requested). Unlike the patchpoint
- // intrinsic, this won't be lowered to a function call. This means we don't
- // have to worry about calling conventions and target-specific lowering code.
- // Instead we perform the call lowering right here.
- //
- // CALLSEQ_START(0)
- // STACKMAP(id, nbytes, ...)
- // CALLSEQ_END(0, 0)
- //
- SmallVector<MachineOperand, 32> Ops;
- // Add the <id> and <numBytes> constants.
- assert(isa<ConstantInt>(I->getOperand(PatchPointOpers::IDPos)) &&
- "Expected a constant integer.");
- const auto *ID = cast<ConstantInt>(I->getOperand(PatchPointOpers::IDPos));
- Ops.push_back(MachineOperand::CreateImm(ID->getZExtValue()));
- assert(isa<ConstantInt>(I->getOperand(PatchPointOpers::NBytesPos)) &&
- "Expected a constant integer.");
- const auto *NumBytes =
- cast<ConstantInt>(I->getOperand(PatchPointOpers::NBytesPos));
- Ops.push_back(MachineOperand::CreateImm(NumBytes->getZExtValue()));
- // Push live variables for the stack map (skipping the first two arguments
- // <id> and <numBytes>).
- if (!addStackMapLiveVars(Ops, I, 2))
- return false;
- // We are not adding any register mask info here, because the stackmap doesn't
- // clobber anything.
- // Add scratch registers as implicit def and early clobber.
- CallingConv::ID CC = I->getCallingConv();
- const MCPhysReg *ScratchRegs = TLI.getScratchRegisters(CC);
- for (unsigned i = 0; ScratchRegs[i]; ++i)
- Ops.push_back(MachineOperand::CreateReg(
- ScratchRegs[i], /*IsDef=*/true, /*IsImp=*/true, /*IsKill=*/false,
- /*IsDead=*/false, /*IsUndef=*/false, /*IsEarlyClobber=*/true));
- // Issue CALLSEQ_START
- unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AdjStackDown))
- .addImm(0);
- // Issue STACKMAP.
- MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::STACKMAP));
- for (auto const &MO : Ops)
- MIB.addOperand(MO);
- // Issue CALLSEQ_END
- unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AdjStackUp))
- .addImm(0)
- .addImm(0);
- // Inform the Frame Information that we have a stackmap in this function.
- FuncInfo.MF->getFrameInfo()->setHasStackMap();
- return true;
- }
- /// \brief Lower an argument list according to the target calling convention.
- ///
- /// This is a helper for lowering intrinsics that follow a target calling
- /// convention or require stack pointer adjustment. Only a subset of the
- /// intrinsic's operands need to participate in the calling convention.
- bool FastISel::lowerCallOperands(const CallInst *CI, unsigned ArgIdx,
- unsigned NumArgs, const Value *Callee,
- bool ForceRetVoidTy, CallLoweringInfo &CLI) {
- ArgListTy Args;
- Args.reserve(NumArgs);
- // Populate the argument list.
- // Attributes for args start at offset 1, after the return attribute.
- ImmutableCallSite CS(CI);
- for (unsigned ArgI = ArgIdx, ArgE = ArgIdx + NumArgs, AttrI = ArgIdx + 1;
- ArgI != ArgE; ++ArgI) {
- Value *V = CI->getOperand(ArgI);
- assert(!V->getType()->isEmptyTy() && "Empty type passed to intrinsic.");
- ArgListEntry Entry;
- Entry.Val = V;
- Entry.Ty = V->getType();
- Entry.setAttributes(&CS, AttrI);
- Args.push_back(Entry);
- }
- Type *RetTy = ForceRetVoidTy ? Type::getVoidTy(CI->getType()->getContext())
- : CI->getType();
- CLI.setCallee(CI->getCallingConv(), RetTy, Callee, std::move(Args), NumArgs);
- return lowerCallTo(CLI);
- }
- FastISel::CallLoweringInfo &FastISel::CallLoweringInfo::setCallee(
- const DataLayout &DL, MCContext &Ctx, CallingConv::ID CC, Type *ResultTy,
- const char *Target, ArgListTy &&ArgsList, unsigned FixedArgs) {
- SmallString<32> MangledName;
- Mangler::getNameWithPrefix(MangledName, Target, DL);
- MCSymbol *Sym = Ctx.getOrCreateSymbol(MangledName);
- return setCallee(CC, ResultTy, Sym, std::move(ArgsList), FixedArgs);
- }
- bool FastISel::selectPatchpoint(const CallInst *I) {
- // void|i64 @llvm.experimental.patchpoint.void|i64(i64 <id>,
- // i32 <numBytes>,
- // i8* <target>,
- // i32 <numArgs>,
- // [Args...],
- // [live variables...])
- CallingConv::ID CC = I->getCallingConv();
- bool IsAnyRegCC = CC == CallingConv::AnyReg;
- bool HasDef = !I->getType()->isVoidTy();
- Value *Callee = I->getOperand(PatchPointOpers::TargetPos)->stripPointerCasts();
- // Get the real number of arguments participating in the call <numArgs>
- assert(isa<ConstantInt>(I->getOperand(PatchPointOpers::NArgPos)) &&
- "Expected a constant integer.");
- const auto *NumArgsVal =
- cast<ConstantInt>(I->getOperand(PatchPointOpers::NArgPos));
- unsigned NumArgs = NumArgsVal->getZExtValue();
- // Skip the four meta args: <id>, <numNopBytes>, <target>, <numArgs>
- // This includes all meta-operands up to but not including CC.
- unsigned NumMetaOpers = PatchPointOpers::CCPos;
- assert(I->getNumArgOperands() >= NumMetaOpers + NumArgs &&
- "Not enough arguments provided to the patchpoint intrinsic");
- // For AnyRegCC the arguments are lowered later on manually.
- unsigned NumCallArgs = IsAnyRegCC ? 0 : NumArgs;
- CallLoweringInfo CLI;
- CLI.setIsPatchPoint();
- if (!lowerCallOperands(I, NumMetaOpers, NumCallArgs, Callee, IsAnyRegCC, CLI))
- return false;
- assert(CLI.Call && "No call instruction specified.");
- SmallVector<MachineOperand, 32> Ops;
- // Add an explicit result reg if we use the anyreg calling convention.
- if (IsAnyRegCC && HasDef) {
- assert(CLI.NumResultRegs == 0 && "Unexpected result register.");
- CLI.ResultReg = createResultReg(TLI.getRegClassFor(MVT::i64));
- CLI.NumResultRegs = 1;
- Ops.push_back(MachineOperand::CreateReg(CLI.ResultReg, /*IsDef=*/true));
- }
- // Add the <id> and <numBytes> constants.
- assert(isa<ConstantInt>(I->getOperand(PatchPointOpers::IDPos)) &&
- "Expected a constant integer.");
- const auto *ID = cast<ConstantInt>(I->getOperand(PatchPointOpers::IDPos));
- Ops.push_back(MachineOperand::CreateImm(ID->getZExtValue()));
- assert(isa<ConstantInt>(I->getOperand(PatchPointOpers::NBytesPos)) &&
- "Expected a constant integer.");
- const auto *NumBytes =
- cast<ConstantInt>(I->getOperand(PatchPointOpers::NBytesPos));
- Ops.push_back(MachineOperand::CreateImm(NumBytes->getZExtValue()));
- // Add the call target.
- if (const auto *C = dyn_cast<IntToPtrInst>(Callee)) {
- uint64_t CalleeConstAddr =
- cast<ConstantInt>(C->getOperand(0))->getZExtValue();
- Ops.push_back(MachineOperand::CreateImm(CalleeConstAddr));
- } else if (const auto *C = dyn_cast<ConstantExpr>(Callee)) {
- if (C->getOpcode() == Instruction::IntToPtr) {
- uint64_t CalleeConstAddr =
- cast<ConstantInt>(C->getOperand(0))->getZExtValue();
- Ops.push_back(MachineOperand::CreateImm(CalleeConstAddr));
- } else
- llvm_unreachable("Unsupported ConstantExpr.");
- } else if (const auto *GV = dyn_cast<GlobalValue>(Callee)) {
- Ops.push_back(MachineOperand::CreateGA(GV, 0));
- } else if (isa<ConstantPointerNull>(Callee))
- Ops.push_back(MachineOperand::CreateImm(0));
- else
- llvm_unreachable("Unsupported callee address.");
- // Adjust <numArgs> to account for any arguments that have been passed on
- // the stack instead.
- unsigned NumCallRegArgs = IsAnyRegCC ? NumArgs : CLI.OutRegs.size();
- Ops.push_back(MachineOperand::CreateImm(NumCallRegArgs));
- // Add the calling convention
- Ops.push_back(MachineOperand::CreateImm((unsigned)CC));
- // Add the arguments we omitted previously. The register allocator should
- // place these in any free register.
- if (IsAnyRegCC) {
- for (unsigned i = NumMetaOpers, e = NumMetaOpers + NumArgs; i != e; ++i) {
- unsigned Reg = getRegForValue(I->getArgOperand(i));
- if (!Reg)
- return false;
- Ops.push_back(MachineOperand::CreateReg(Reg, /*IsDef=*/false));
- }
- }
- // Push the arguments from the call instruction.
- for (auto Reg : CLI.OutRegs)
- Ops.push_back(MachineOperand::CreateReg(Reg, /*IsDef=*/false));
- // Push live variables for the stack map.
- if (!addStackMapLiveVars(Ops, I, NumMetaOpers + NumArgs))
- return false;
- // Push the register mask info.
- Ops.push_back(MachineOperand::CreateRegMask(
- TRI.getCallPreservedMask(*FuncInfo.MF, CC)));
- // Add scratch registers as implicit def and early clobber.
- const MCPhysReg *ScratchRegs = TLI.getScratchRegisters(CC);
- for (unsigned i = 0; ScratchRegs[i]; ++i)
- Ops.push_back(MachineOperand::CreateReg(
- ScratchRegs[i], /*IsDef=*/true, /*IsImp=*/true, /*IsKill=*/false,
- /*IsDead=*/false, /*IsUndef=*/false, /*IsEarlyClobber=*/true));
- // Add implicit defs (return values).
- for (auto Reg : CLI.InRegs)
- Ops.push_back(MachineOperand::CreateReg(Reg, /*IsDef=*/true,
- /*IsImpl=*/true));
- // Insert the patchpoint instruction before the call generated by the target.
- MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, CLI.Call, DbgLoc,
- TII.get(TargetOpcode::PATCHPOINT));
- for (auto &MO : Ops)
- MIB.addOperand(MO);
- MIB->setPhysRegsDeadExcept(CLI.InRegs, TRI);
- // Delete the original call instruction.
- CLI.Call->eraseFromParent();
- // Inform the Frame Information that we have a patchpoint in this function.
- FuncInfo.MF->getFrameInfo()->setHasPatchPoint();
- if (CLI.NumResultRegs)
- updateValueMap(I, CLI.ResultReg, CLI.NumResultRegs);
- return true;
- }
- /// Returns an AttributeSet representing the attributes applied to the return
- /// value of the given call.
- static AttributeSet getReturnAttrs(FastISel::CallLoweringInfo &CLI) {
- SmallVector<Attribute::AttrKind, 2> Attrs;
- if (CLI.RetSExt)
- Attrs.push_back(Attribute::SExt);
- if (CLI.RetZExt)
- Attrs.push_back(Attribute::ZExt);
- if (CLI.IsInReg)
- Attrs.push_back(Attribute::InReg);
- return AttributeSet::get(CLI.RetTy->getContext(), AttributeSet::ReturnIndex,
- Attrs);
- }
- bool FastISel::lowerCallTo(const CallInst *CI, const char *SymName,
- unsigned NumArgs) {
- MCContext &Ctx = MF->getContext();
- SmallString<32> MangledName;
- Mangler::getNameWithPrefix(MangledName, SymName, DL);
- MCSymbol *Sym = Ctx.getOrCreateSymbol(MangledName);
- return lowerCallTo(CI, Sym, NumArgs);
- }
- bool FastISel::lowerCallTo(const CallInst *CI, MCSymbol *Symbol,
- unsigned NumArgs) {
- ImmutableCallSite CS(CI);
- PointerType *PT = cast<PointerType>(CS.getCalledValue()->getType());
- FunctionType *FTy = cast<FunctionType>(PT->getElementType());
- Type *RetTy = FTy->getReturnType();
- ArgListTy Args;
- Args.reserve(NumArgs);
- // Populate the argument list.
- // Attributes for args start at offset 1, after the return attribute.
- for (unsigned ArgI = 0; ArgI != NumArgs; ++ArgI) {
- Value *V = CI->getOperand(ArgI);
- assert(!V->getType()->isEmptyTy() && "Empty type passed to intrinsic.");
- ArgListEntry Entry;
- Entry.Val = V;
- Entry.Ty = V->getType();
- Entry.setAttributes(&CS, ArgI + 1);
- Args.push_back(Entry);
- }
- CallLoweringInfo CLI;
- CLI.setCallee(RetTy, FTy, Symbol, std::move(Args), CS, NumArgs);
- return lowerCallTo(CLI);
- }
- bool FastISel::lowerCallTo(CallLoweringInfo &CLI) {
- // Handle the incoming return values from the call.
- CLI.clearIns();
- SmallVector<EVT, 4> RetTys;
- ComputeValueVTs(TLI, DL, CLI.RetTy, RetTys);
- SmallVector<ISD::OutputArg, 4> Outs;
- GetReturnInfo(CLI.RetTy, getReturnAttrs(CLI), Outs, TLI, DL);
- bool CanLowerReturn = TLI.CanLowerReturn(
- CLI.CallConv, *FuncInfo.MF, CLI.IsVarArg, Outs, CLI.RetTy->getContext());
- // FIXME: sret demotion isn't supported yet - bail out.
- if (!CanLowerReturn)
- return false;
- for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
- EVT VT = RetTys[I];
- MVT RegisterVT = TLI.getRegisterType(CLI.RetTy->getContext(), VT);
- unsigned NumRegs = TLI.getNumRegisters(CLI.RetTy->getContext(), VT);
- for (unsigned i = 0; i != NumRegs; ++i) {
- ISD::InputArg MyFlags;
- MyFlags.VT = RegisterVT;
- MyFlags.ArgVT = VT;
- MyFlags.Used = CLI.IsReturnValueUsed;
- if (CLI.RetSExt)
- MyFlags.Flags.setSExt();
- if (CLI.RetZExt)
- MyFlags.Flags.setZExt();
- if (CLI.IsInReg)
- MyFlags.Flags.setInReg();
- CLI.Ins.push_back(MyFlags);
- }
- }
- // Handle all of the outgoing arguments.
- CLI.clearOuts();
- for (auto &Arg : CLI.getArgs()) {
- Type *FinalType = Arg.Ty;
- if (Arg.IsByVal)
- FinalType = cast<PointerType>(Arg.Ty)->getElementType();
- bool NeedsRegBlock = TLI.functionArgumentNeedsConsecutiveRegisters(
- FinalType, CLI.CallConv, CLI.IsVarArg);
- ISD::ArgFlagsTy Flags;
- if (Arg.IsZExt)
- Flags.setZExt();
- if (Arg.IsSExt)
- Flags.setSExt();
- if (Arg.IsInReg)
- Flags.setInReg();
- if (Arg.IsSRet)
- Flags.setSRet();
- if (Arg.IsByVal)
- Flags.setByVal();
- if (Arg.IsInAlloca) {
- Flags.setInAlloca();
- // Set the byval flag for CCAssignFn callbacks that don't know about
- // inalloca. This way we can know how many bytes we should've allocated
- // and how many bytes a callee cleanup function will pop. If we port
- // inalloca to more targets, we'll have to add custom inalloca handling in
- // the various CC lowering callbacks.
- Flags.setByVal();
- }
- if (Arg.IsByVal || Arg.IsInAlloca) {
- PointerType *Ty = cast<PointerType>(Arg.Ty);
- Type *ElementTy = Ty->getElementType();
- unsigned FrameSize = DL.getTypeAllocSize(ElementTy);
- // For ByVal, alignment should come from FE. BE will guess if this info is
- // not there, but there are cases it cannot get right.
- unsigned FrameAlign = Arg.Alignment;
- if (!FrameAlign)
- FrameAlign = TLI.getByValTypeAlignment(ElementTy, DL);
- Flags.setByValSize(FrameSize);
- Flags.setByValAlign(FrameAlign);
- }
- if (Arg.IsNest)
- Flags.setNest();
- if (NeedsRegBlock)
- Flags.setInConsecutiveRegs();
- unsigned OriginalAlignment = DL.getABITypeAlignment(Arg.Ty);
- Flags.setOrigAlign(OriginalAlignment);
- CLI.OutVals.push_back(Arg.Val);
- CLI.OutFlags.push_back(Flags);
- }
- if (!fastLowerCall(CLI))
- return false;
- // Set all unused physreg defs as dead.
- assert(CLI.Call && "No call instruction specified.");
- CLI.Call->setPhysRegsDeadExcept(CLI.InRegs, TRI);
- if (CLI.NumResultRegs && CLI.CS)
- updateValueMap(CLI.CS->getInstruction(), CLI.ResultReg, CLI.NumResultRegs);
- return true;
- }
- bool FastISel::lowerCall(const CallInst *CI) {
- ImmutableCallSite CS(CI);
- PointerType *PT = cast<PointerType>(CS.getCalledValue()->getType());
- FunctionType *FuncTy = cast<FunctionType>(PT->getElementType());
- Type *RetTy = FuncTy->getReturnType();
- ArgListTy Args;
- ArgListEntry Entry;
- Args.reserve(CS.arg_size());
- for (ImmutableCallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end();
- i != e; ++i) {
- Value *V = *i;
- // Skip empty types
- if (V->getType()->isEmptyTy())
- continue;
- Entry.Val = V;
- Entry.Ty = V->getType();
- // Skip the first return-type Attribute to get to params.
- Entry.setAttributes(&CS, i - CS.arg_begin() + 1);
- Args.push_back(Entry);
- }
- // Check if target-independent constraints permit a tail call here.
- // Target-dependent constraints are checked within fastLowerCall.
- bool IsTailCall = CI->isTailCall();
- if (IsTailCall && !isInTailCallPosition(CS, TM))
- IsTailCall = false;
- CallLoweringInfo CLI;
- CLI.setCallee(RetTy, FuncTy, CI->getCalledValue(), std::move(Args), CS)
- .setTailCall(IsTailCall);
- return lowerCallTo(CLI);
- }
- bool FastISel::selectCall(const User *I) {
- const CallInst *Call = cast<CallInst>(I);
- // Handle simple inline asms.
- if (const InlineAsm *IA = dyn_cast<InlineAsm>(Call->getCalledValue())) {
- // If the inline asm has side effects, then make sure that no local value
- // lives across by flushing the local value map.
- if (IA->hasSideEffects())
- flushLocalValueMap();
- // Don't attempt to handle constraints.
- if (!IA->getConstraintString().empty())
- return false;
- unsigned ExtraInfo = 0;
- if (IA->hasSideEffects())
- ExtraInfo |= InlineAsm::Extra_HasSideEffects;
- if (IA->isAlignStack())
- ExtraInfo |= InlineAsm::Extra_IsAlignStack;
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::INLINEASM))
- .addExternalSymbol(IA->getAsmString().c_str())
- .addImm(ExtraInfo);
- return true;
- }
- MachineModuleInfo &MMI = FuncInfo.MF->getMMI();
- ComputeUsesVAFloatArgument(*Call, &MMI);
- // Handle intrinsic function calls.
- if (const auto *II = dyn_cast<IntrinsicInst>(Call))
- return selectIntrinsicCall(II);
- // Usually, it does not make sense to initialize a value,
- // make an unrelated function call and use the value, because
- // it tends to be spilled on the stack. So, we move the pointer
- // to the last local value to the beginning of the block, so that
- // all the values which have already been materialized,
- // appear after the call. It also makes sense to skip intrinsics
- // since they tend to be inlined.
- flushLocalValueMap();
- return lowerCall(Call);
- }
- bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) {
- switch (II->getIntrinsicID()) {
- default:
- break;
- // At -O0 we don't care about the lifetime intrinsics.
- case Intrinsic::lifetime_start:
- case Intrinsic::lifetime_end:
- // The donothing intrinsic does, well, nothing.
- case Intrinsic::donothing:
- return true;
- case Intrinsic::eh_actions: {
- unsigned ResultReg = getRegForValue(UndefValue::get(II->getType()));
- if (!ResultReg)
- return false;
- updateValueMap(II, ResultReg);
- return true;
- }
- case Intrinsic::dbg_declare: {
- const DbgDeclareInst *DI = cast<DbgDeclareInst>(II);
- assert(DI->getVariable() && "Missing variable");
- if (!FuncInfo.MF->getMMI().hasDebugInfo()) {
- DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n");
- return true;
- }
- const Value *Address = DI->getAddress();
- if (!Address || isa<UndefValue>(Address)) {
- DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n");
- return true;
- }
- unsigned Offset = 0;
- Optional<MachineOperand> Op;
- if (const auto *Arg = dyn_cast<Argument>(Address))
- // Some arguments' frame index is recorded during argument lowering.
- Offset = FuncInfo.getArgumentFrameIndex(Arg);
- if (Offset)
- Op = MachineOperand::CreateFI(Offset);
- if (!Op)
- if (unsigned Reg = lookUpRegForValue(Address))
- Op = MachineOperand::CreateReg(Reg, false);
- // If we have a VLA that has a "use" in a metadata node that's then used
- // here but it has no other uses, then we have a problem. E.g.,
- //
- // int foo (const int *x) {
- // char a[*x];
- // return 0;
- // }
- //
- // If we assign 'a' a vreg and fast isel later on has to use the selection
- // DAG isel, it will want to copy the value to the vreg. However, there are
- // no uses, which goes counter to what selection DAG isel expects.
- if (!Op && !Address->use_empty() && isa<Instruction>(Address) &&
- (!isa<AllocaInst>(Address) ||
- !FuncInfo.StaticAllocaMap.count(cast<AllocaInst>(Address))))
- Op = MachineOperand::CreateReg(FuncInfo.InitializeRegForValue(Address),
- false);
- if (Op) {
- assert(DI->getVariable()->isValidLocationForIntrinsic(DbgLoc) &&
- "Expected inlined-at fields to agree");
- if (Op->isReg()) {
- Op->setIsDebug(true);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::DBG_VALUE), false, Op->getReg(), 0,
- DI->getVariable(), DI->getExpression());
- } else
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::DBG_VALUE))
- .addOperand(*Op)
- .addImm(0)
- .addMetadata(DI->getVariable())
- .addMetadata(DI->getExpression());
- } else {
- // We can't yet handle anything else here because it would require
- // generating code, thus altering codegen because of debug info.
- DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n");
- }
- return true;
- }
- case Intrinsic::dbg_value: {
- // This form of DBG_VALUE is target-independent.
- const DbgValueInst *DI = cast<DbgValueInst>(II);
- const MCInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE);
- const Value *V = DI->getValue();
- assert(DI->getVariable()->isValidLocationForIntrinsic(DbgLoc) &&
- "Expected inlined-at fields to agree");
- if (!V) {
- // Currently the optimizer can produce this; insert an undef to
- // help debugging. Probably the optimizer should not do this.
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addReg(0U)
- .addImm(DI->getOffset())
- .addMetadata(DI->getVariable())
- .addMetadata(DI->getExpression());
- } else if (const auto *CI = dyn_cast<ConstantInt>(V)) {
- if (CI->getBitWidth() > 64)
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addCImm(CI)
- .addImm(DI->getOffset())
- .addMetadata(DI->getVariable())
- .addMetadata(DI->getExpression());
- else
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addImm(CI->getZExtValue())
- .addImm(DI->getOffset())
- .addMetadata(DI->getVariable())
- .addMetadata(DI->getExpression());
- } else if (const auto *CF = dyn_cast<ConstantFP>(V)) {
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addFPImm(CF)
- .addImm(DI->getOffset())
- .addMetadata(DI->getVariable())
- .addMetadata(DI->getExpression());
- } else if (unsigned Reg = lookUpRegForValue(V)) {
- // FIXME: This does not handle register-indirect values at offset 0.
- bool IsIndirect = DI->getOffset() != 0;
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, IsIndirect, Reg,
- DI->getOffset(), DI->getVariable(), DI->getExpression());
- } else {
- // We can't yet handle anything else here because it would require
- // generating code, thus altering codegen because of debug info.
- DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n");
- }
- return true;
- }
- case Intrinsic::objectsize: {
- ConstantInt *CI = cast<ConstantInt>(II->getArgOperand(1));
- unsigned long long Res = CI->isZero() ? -1ULL : 0;
- Constant *ResCI = ConstantInt::get(II->getType(), Res);
- unsigned ResultReg = getRegForValue(ResCI);
- if (!ResultReg)
- return false;
- updateValueMap(II, ResultReg);
- return true;
- }
- case Intrinsic::expect: {
- unsigned ResultReg = getRegForValue(II->getArgOperand(0));
- if (!ResultReg)
- return false;
- updateValueMap(II, ResultReg);
- return true;
- }
- case Intrinsic::experimental_stackmap:
- return selectStackmap(II);
- case Intrinsic::experimental_patchpoint_void:
- case Intrinsic::experimental_patchpoint_i64:
- return selectPatchpoint(II);
- }
- return fastLowerIntrinsicCall(II);
- }
- bool FastISel::selectCast(const User *I, unsigned Opcode) {
- EVT SrcVT = TLI.getValueType(DL, I->getOperand(0)->getType());
- EVT DstVT = TLI.getValueType(DL, I->getType());
- if (SrcVT == MVT::Other || !SrcVT.isSimple() || DstVT == MVT::Other ||
- !DstVT.isSimple())
- // Unhandled type. Halt "fast" selection and bail.
- return false;
- // Check if the destination type is legal.
- if (!TLI.isTypeLegal(DstVT))
- return false;
- // Check if the source operand is legal.
- if (!TLI.isTypeLegal(SrcVT))
- return false;
- unsigned InputReg = getRegForValue(I->getOperand(0));
- if (!InputReg)
- // Unhandled operand. Halt "fast" selection and bail.
- return false;
- bool InputRegIsKill = hasTrivialKill(I->getOperand(0));
- unsigned ResultReg = fastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(),
- Opcode, InputReg, InputRegIsKill);
- if (!ResultReg)
- return false;
- updateValueMap(I, ResultReg);
- return true;
- }
- bool FastISel::selectBitCast(const User *I) {
- // If the bitcast doesn't change the type, just use the operand value.
- if (I->getType() == I->getOperand(0)->getType()) {
- unsigned Reg = getRegForValue(I->getOperand(0));
- if (!Reg)
- return false;
- updateValueMap(I, Reg);
- return true;
- }
- // Bitcasts of other values become reg-reg copies or BITCAST operators.
- EVT SrcEVT = TLI.getValueType(DL, I->getOperand(0)->getType());
- EVT DstEVT = TLI.getValueType(DL, I->getType());
- if (SrcEVT == MVT::Other || DstEVT == MVT::Other ||
- !TLI.isTypeLegal(SrcEVT) || !TLI.isTypeLegal(DstEVT))
- // Unhandled type. Halt "fast" selection and bail.
- return false;
- MVT SrcVT = SrcEVT.getSimpleVT();
- MVT DstVT = DstEVT.getSimpleVT();
- unsigned Op0 = getRegForValue(I->getOperand(0));
- if (!Op0) // Unhandled operand. Halt "fast" selection and bail.
- return false;
- bool Op0IsKill = hasTrivialKill(I->getOperand(0));
- // First, try to perform the bitcast by inserting a reg-reg copy.
- unsigned ResultReg = 0;
- if (SrcVT == DstVT) {
- const TargetRegisterClass *SrcClass = TLI.getRegClassFor(SrcVT);
- const TargetRegisterClass *DstClass = TLI.getRegClassFor(DstVT);
- // Don't attempt a cross-class copy. It will likely fail.
- if (SrcClass == DstClass) {
- ResultReg = createResultReg(DstClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg).addReg(Op0);
- }
- }
- // If the reg-reg copy failed, select a BITCAST opcode.
- if (!ResultReg)
- ResultReg = fastEmit_r(SrcVT, DstVT, ISD::BITCAST, Op0, Op0IsKill);
- if (!ResultReg)
- return false;
- updateValueMap(I, ResultReg);
- return true;
- }
- bool FastISel::selectInstruction(const Instruction *I) {
- // Just before the terminator instruction, insert instructions to
- // feed PHI nodes in successor blocks.
- if (isa<TerminatorInst>(I))
- if (!handlePHINodesInSuccessorBlocks(I->getParent()))
- return false;
- DbgLoc = I->getDebugLoc();
- SavedInsertPt = FuncInfo.InsertPt;
- if (const auto *Call = dyn_cast<CallInst>(I)) {
- const Function *F = Call->getCalledFunction();
- LibFunc::Func Func;
- // As a special case, don't handle calls to builtin library functions that
- // may be translated directly to target instructions.
- if (F && !F->hasLocalLinkage() && F->hasName() &&
- LibInfo->getLibFunc(F->getName(), Func) &&
- LibInfo->hasOptimizedCodeGen(Func))
- return false;
- // Don't handle Intrinsic::trap if a trap funciton is specified.
- if (F && F->getIntrinsicID() == Intrinsic::trap &&
- Call->hasFnAttr("trap-func-name"))
- return false;
- }
- // First, try doing target-independent selection.
- if (!SkipTargetIndependentISel) {
- if (selectOperator(I, I->getOpcode())) {
- ++NumFastIselSuccessIndependent;
- DbgLoc = DebugLoc();
- return true;
- }
- // Remove dead code.
- recomputeInsertPt();
- if (SavedInsertPt != FuncInfo.InsertPt)
- removeDeadCode(FuncInfo.InsertPt, SavedInsertPt);
- SavedInsertPt = FuncInfo.InsertPt;
- }
- // Next, try calling the target to attempt to handle the instruction.
- if (fastSelectInstruction(I)) {
- ++NumFastIselSuccessTarget;
- DbgLoc = DebugLoc();
- return true;
- }
- // Remove dead code.
- recomputeInsertPt();
- if (SavedInsertPt != FuncInfo.InsertPt)
- removeDeadCode(FuncInfo.InsertPt, SavedInsertPt);
- DbgLoc = DebugLoc();
- // Undo phi node updates, because they will be added again by SelectionDAG.
- if (isa<TerminatorInst>(I))
- FuncInfo.PHINodesToUpdate.resize(FuncInfo.OrigNumPHINodesToUpdate);
- return false;
- }
- /// Emit an unconditional branch to the given block, unless it is the immediate
- /// (fall-through) successor, and update the CFG.
- void FastISel::fastEmitBranch(MachineBasicBlock *MSucc, DebugLoc DbgLoc) {
- if (FuncInfo.MBB->getBasicBlock()->size() > 1 &&
- FuncInfo.MBB->isLayoutSuccessor(MSucc)) {
- // For more accurate line information if this is the only instruction
- // in the block then emit it, otherwise we have the unconditional
- // fall-through case, which needs no instructions.
- } else {
- // The unconditional branch case.
- TII.InsertBranch(*FuncInfo.MBB, MSucc, nullptr,
- SmallVector<MachineOperand, 0>(), DbgLoc);
- }
- uint32_t BranchWeight = 0;
- if (FuncInfo.BPI)
- BranchWeight = FuncInfo.BPI->getEdgeWeight(FuncInfo.MBB->getBasicBlock(),
- MSucc->getBasicBlock());
- FuncInfo.MBB->addSuccessor(MSucc, BranchWeight);
- }
- /// Emit an FNeg operation.
- bool FastISel::selectFNeg(const User *I) {
- unsigned OpReg = getRegForValue(BinaryOperator::getFNegArgument(I));
- if (!OpReg)
- return false;
- bool OpRegIsKill = hasTrivialKill(I);
- // If the target has ISD::FNEG, use it.
- EVT VT = TLI.getValueType(DL, I->getType());
- unsigned ResultReg = fastEmit_r(VT.getSimpleVT(), VT.getSimpleVT(), ISD::FNEG,
- OpReg, OpRegIsKill);
- if (ResultReg) {
- updateValueMap(I, ResultReg);
- return true;
- }
- // Bitcast the value to integer, twiddle the sign bit with xor,
- // and then bitcast it back to floating-point.
- if (VT.getSizeInBits() > 64)
- return false;
- EVT IntVT = EVT::getIntegerVT(I->getContext(), VT.getSizeInBits());
- if (!TLI.isTypeLegal(IntVT))
- return false;
- unsigned IntReg = fastEmit_r(VT.getSimpleVT(), IntVT.getSimpleVT(),
- ISD::BITCAST, OpReg, OpRegIsKill);
- if (!IntReg)
- return false;
- unsigned IntResultReg = fastEmit_ri_(
- IntVT.getSimpleVT(), ISD::XOR, IntReg, /*IsKill=*/true,
- UINT64_C(1) << (VT.getSizeInBits() - 1), IntVT.getSimpleVT());
- if (!IntResultReg)
- return false;
- ResultReg = fastEmit_r(IntVT.getSimpleVT(), VT.getSimpleVT(), ISD::BITCAST,
- IntResultReg, /*IsKill=*/true);
- if (!ResultReg)
- return false;
- updateValueMap(I, ResultReg);
- return true;
- }
- bool FastISel::selectExtractValue(const User *U) {
- const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(U);
- if (!EVI)
- return false;
- // Make sure we only try to handle extracts with a legal result. But also
- // allow i1 because it's easy.
- EVT RealVT = TLI.getValueType(DL, EVI->getType(), /*AllowUnknown=*/true);
- if (!RealVT.isSimple())
- return false;
- MVT VT = RealVT.getSimpleVT();
- if (!TLI.isTypeLegal(VT) && VT != MVT::i1)
- return false;
- const Value *Op0 = EVI->getOperand(0);
- Type *AggTy = Op0->getType();
- // Get the base result register.
- unsigned ResultReg;
- DenseMap<const Value *, unsigned>::iterator I = FuncInfo.ValueMap.find(Op0);
- if (I != FuncInfo.ValueMap.end())
- ResultReg = I->second;
- else if (isa<Instruction>(Op0))
- ResultReg = FuncInfo.InitializeRegForValue(Op0);
- else
- return false; // fast-isel can't handle aggregate constants at the moment
- // Get the actual result register, which is an offset from the base register.
- unsigned VTIndex = ComputeLinearIndex(AggTy, EVI->getIndices());
- SmallVector<EVT, 4> AggValueVTs;
- ComputeValueVTs(TLI, DL, AggTy, AggValueVTs);
- for (unsigned i = 0; i < VTIndex; i++)
- ResultReg += TLI.getNumRegisters(FuncInfo.Fn->getContext(), AggValueVTs[i]);
- updateValueMap(EVI, ResultReg);
- return true;
- }
- bool FastISel::selectOperator(const User *I, unsigned Opcode) {
- switch (Opcode) {
- case Instruction::Add:
- return selectBinaryOp(I, ISD::ADD);
- case Instruction::FAdd:
- return selectBinaryOp(I, ISD::FADD);
- case Instruction::Sub:
- return selectBinaryOp(I, ISD::SUB);
- case Instruction::FSub:
- // FNeg is currently represented in LLVM IR as a special case of FSub.
- if (BinaryOperator::isFNeg(I))
- return selectFNeg(I);
- return selectBinaryOp(I, ISD::FSUB);
- case Instruction::Mul:
- return selectBinaryOp(I, ISD::MUL);
- case Instruction::FMul:
- return selectBinaryOp(I, ISD::FMUL);
- case Instruction::SDiv:
- return selectBinaryOp(I, ISD::SDIV);
- case Instruction::UDiv:
- return selectBinaryOp(I, ISD::UDIV);
- case Instruction::FDiv:
- return selectBinaryOp(I, ISD::FDIV);
- case Instruction::SRem:
- return selectBinaryOp(I, ISD::SREM);
- case Instruction::URem:
- return selectBinaryOp(I, ISD::UREM);
- case Instruction::FRem:
- return selectBinaryOp(I, ISD::FREM);
- case Instruction::Shl:
- return selectBinaryOp(I, ISD::SHL);
- case Instruction::LShr:
- return selectBinaryOp(I, ISD::SRL);
- case Instruction::AShr:
- return selectBinaryOp(I, ISD::SRA);
- case Instruction::And:
- return selectBinaryOp(I, ISD::AND);
- case Instruction::Or:
- return selectBinaryOp(I, ISD::OR);
- case Instruction::Xor:
- return selectBinaryOp(I, ISD::XOR);
- case Instruction::GetElementPtr:
- return selectGetElementPtr(I);
- case Instruction::Br: {
- const BranchInst *BI = cast<BranchInst>(I);
- if (BI->isUnconditional()) {
- const BasicBlock *LLVMSucc = BI->getSuccessor(0);
- MachineBasicBlock *MSucc = FuncInfo.MBBMap[LLVMSucc];
- fastEmitBranch(MSucc, BI->getDebugLoc());
- return true;
- }
- // Conditional branches are not handed yet.
- // Halt "fast" selection and bail.
- return false;
- }
- case Instruction::Unreachable:
- if (TM.Options.TrapUnreachable)
- return fastEmit_(MVT::Other, MVT::Other, ISD::TRAP) != 0;
- else
- return true;
- case Instruction::Alloca:
- // FunctionLowering has the static-sized case covered.
- if (FuncInfo.StaticAllocaMap.count(cast<AllocaInst>(I)))
- return true;
- // Dynamic-sized alloca is not handled yet.
- return false;
- case Instruction::Call:
- return selectCall(I);
- case Instruction::BitCast:
- return selectBitCast(I);
- case Instruction::FPToSI:
- return selectCast(I, ISD::FP_TO_SINT);
- case Instruction::ZExt:
- return selectCast(I, ISD::ZERO_EXTEND);
- case Instruction::SExt:
- return selectCast(I, ISD::SIGN_EXTEND);
- case Instruction::Trunc:
- return selectCast(I, ISD::TRUNCATE);
- case Instruction::SIToFP:
- return selectCast(I, ISD::SINT_TO_FP);
- case Instruction::IntToPtr: // Deliberate fall-through.
- case Instruction::PtrToInt: {
- EVT SrcVT = TLI.getValueType(DL, I->getOperand(0)->getType());
- EVT DstVT = TLI.getValueType(DL, I->getType());
- if (DstVT.bitsGT(SrcVT))
- return selectCast(I, ISD::ZERO_EXTEND);
- if (DstVT.bitsLT(SrcVT))
- return selectCast(I, ISD::TRUNCATE);
- unsigned Reg = getRegForValue(I->getOperand(0));
- if (!Reg)
- return false;
- updateValueMap(I, Reg);
- return true;
- }
- case Instruction::ExtractValue:
- return selectExtractValue(I);
- case Instruction::PHI:
- llvm_unreachable("FastISel shouldn't visit PHI nodes!");
- default:
- // Unhandled instruction. Halt "fast" selection and bail.
- return false;
- }
- }
- FastISel::FastISel(FunctionLoweringInfo &FuncInfo,
- const TargetLibraryInfo *LibInfo,
- bool SkipTargetIndependentISel)
- : FuncInfo(FuncInfo), MF(FuncInfo.MF), MRI(FuncInfo.MF->getRegInfo()),
- MFI(*FuncInfo.MF->getFrameInfo()), MCP(*FuncInfo.MF->getConstantPool()),
- TM(FuncInfo.MF->getTarget()), DL(MF->getDataLayout()),
- TII(*MF->getSubtarget().getInstrInfo()),
- TLI(*MF->getSubtarget().getTargetLowering()),
- TRI(*MF->getSubtarget().getRegisterInfo()), LibInfo(LibInfo),
- SkipTargetIndependentISel(SkipTargetIndependentISel) {}
- FastISel::~FastISel() {}
- bool FastISel::fastLowerArguments() { return false; }
- bool FastISel::fastLowerCall(CallLoweringInfo & /*CLI*/) { return false; }
- bool FastISel::fastLowerIntrinsicCall(const IntrinsicInst * /*II*/) {
- return false;
- }
- unsigned FastISel::fastEmit_(MVT, MVT, unsigned) { return 0; }
- unsigned FastISel::fastEmit_r(MVT, MVT, unsigned, unsigned /*Op0*/,
- bool /*Op0IsKill*/) {
- return 0;
- }
- unsigned FastISel::fastEmit_rr(MVT, MVT, unsigned, unsigned /*Op0*/,
- bool /*Op0IsKill*/, unsigned /*Op1*/,
- bool /*Op1IsKill*/) {
- return 0;
- }
- unsigned FastISel::fastEmit_i(MVT, MVT, unsigned, uint64_t /*Imm*/) {
- return 0;
- }
- unsigned FastISel::fastEmit_f(MVT, MVT, unsigned,
- const ConstantFP * /*FPImm*/) {
- return 0;
- }
- unsigned FastISel::fastEmit_ri(MVT, MVT, unsigned, unsigned /*Op0*/,
- bool /*Op0IsKill*/, uint64_t /*Imm*/) {
- return 0;
- }
- unsigned FastISel::fastEmit_rf(MVT, MVT, unsigned, unsigned /*Op0*/,
- bool /*Op0IsKill*/,
- const ConstantFP * /*FPImm*/) {
- return 0;
- }
- unsigned FastISel::fastEmit_rri(MVT, MVT, unsigned, unsigned /*Op0*/,
- bool /*Op0IsKill*/, unsigned /*Op1*/,
- bool /*Op1IsKill*/, uint64_t /*Imm*/) {
- return 0;
- }
- /// This method is a wrapper of fastEmit_ri. It first tries to emit an
- /// instruction with an immediate operand using fastEmit_ri.
- /// If that fails, it materializes the immediate into a register and try
- /// fastEmit_rr instead.
- unsigned FastISel::fastEmit_ri_(MVT VT, unsigned Opcode, unsigned Op0,
- bool Op0IsKill, uint64_t Imm, MVT ImmType) {
- // If this is a multiply by a power of two, emit this as a shift left.
- if (Opcode == ISD::MUL && isPowerOf2_64(Imm)) {
- Opcode = ISD::SHL;
- Imm = Log2_64(Imm);
- } else if (Opcode == ISD::UDIV && isPowerOf2_64(Imm)) {
- // div x, 8 -> srl x, 3
- Opcode = ISD::SRL;
- Imm = Log2_64(Imm);
- }
- // Horrible hack (to be removed), check to make sure shift amounts are
- // in-range.
- if ((Opcode == ISD::SHL || Opcode == ISD::SRA || Opcode == ISD::SRL) &&
- Imm >= VT.getSizeInBits())
- return 0;
- // First check if immediate type is legal. If not, we can't use the ri form.
- unsigned ResultReg = fastEmit_ri(VT, VT, Opcode, Op0, Op0IsKill, Imm);
- if (ResultReg)
- return ResultReg;
- unsigned MaterialReg = fastEmit_i(ImmType, ImmType, ISD::Constant, Imm);
- bool IsImmKill = true;
- if (!MaterialReg) {
- // This is a bit ugly/slow, but failing here means falling out of
- // fast-isel, which would be very slow.
- IntegerType *ITy =
- IntegerType::get(FuncInfo.Fn->getContext(), VT.getSizeInBits());
- MaterialReg = getRegForValue(ConstantInt::get(ITy, Imm));
- if (!MaterialReg)
- return 0;
- // FIXME: If the materialized register here has no uses yet then this
- // will be the first use and we should be able to mark it as killed.
- // However, the local value area for materialising constant expressions
- // grows down, not up, which means that any constant expressions we generate
- // later which also use 'Imm' could be after this instruction and therefore
- // after this kill.
- IsImmKill = false;
- }
- return fastEmit_rr(VT, VT, Opcode, Op0, Op0IsKill, MaterialReg, IsImmKill);
- }
- unsigned FastISel::createResultReg(const TargetRegisterClass *RC) {
- return MRI.createVirtualRegister(RC);
- }
- unsigned FastISel::constrainOperandRegClass(const MCInstrDesc &II, unsigned Op,
- unsigned OpNum) {
- if (TargetRegisterInfo::isVirtualRegister(Op)) {
- const TargetRegisterClass *RegClass =
- TII.getRegClass(II, OpNum, &TRI, *FuncInfo.MF);
- if (!MRI.constrainRegClass(Op, RegClass)) {
- // If it's not legal to COPY between the register classes, something
- // has gone very wrong before we got here.
- unsigned NewOp = createResultReg(RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), NewOp).addReg(Op);
- return NewOp;
- }
- }
- return Op;
- }
- unsigned FastISel::fastEmitInst_(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC) {
- unsigned ResultReg = createResultReg(RC);
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg);
- return ResultReg;
- }
- unsigned FastISel::fastEmitInst_r(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC, unsigned Op0,
- bool Op0IsKill) {
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- unsigned ResultReg = createResultReg(RC);
- Op0 = constrainOperandRegClass(II, Op0, II.getNumDefs());
- if (II.getNumDefs() >= 1)
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
- .addReg(Op0, getKillRegState(Op0IsKill));
- else {
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addReg(Op0, getKillRegState(Op0IsKill));
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg).addReg(II.ImplicitDefs[0]);
- }
- return ResultReg;
- }
- unsigned FastISel::fastEmitInst_rr(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC, unsigned Op0,
- bool Op0IsKill, unsigned Op1,
- bool Op1IsKill) {
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- unsigned ResultReg = createResultReg(RC);
- Op0 = constrainOperandRegClass(II, Op0, II.getNumDefs());
- Op1 = constrainOperandRegClass(II, Op1, II.getNumDefs() + 1);
- if (II.getNumDefs() >= 1)
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
- .addReg(Op0, getKillRegState(Op0IsKill))
- .addReg(Op1, getKillRegState(Op1IsKill));
- else {
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addReg(Op0, getKillRegState(Op0IsKill))
- .addReg(Op1, getKillRegState(Op1IsKill));
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg).addReg(II.ImplicitDefs[0]);
- }
- return ResultReg;
- }
- unsigned FastISel::fastEmitInst_rrr(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC, unsigned Op0,
- bool Op0IsKill, unsigned Op1,
- bool Op1IsKill, unsigned Op2,
- bool Op2IsKill) {
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- unsigned ResultReg = createResultReg(RC);
- Op0 = constrainOperandRegClass(II, Op0, II.getNumDefs());
- Op1 = constrainOperandRegClass(II, Op1, II.getNumDefs() + 1);
- Op2 = constrainOperandRegClass(II, Op2, II.getNumDefs() + 2);
- if (II.getNumDefs() >= 1)
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
- .addReg(Op0, getKillRegState(Op0IsKill))
- .addReg(Op1, getKillRegState(Op1IsKill))
- .addReg(Op2, getKillRegState(Op2IsKill));
- else {
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addReg(Op0, getKillRegState(Op0IsKill))
- .addReg(Op1, getKillRegState(Op1IsKill))
- .addReg(Op2, getKillRegState(Op2IsKill));
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg).addReg(II.ImplicitDefs[0]);
- }
- return ResultReg;
- }
- unsigned FastISel::fastEmitInst_ri(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC, unsigned Op0,
- bool Op0IsKill, uint64_t Imm) {
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- unsigned ResultReg = createResultReg(RC);
- Op0 = constrainOperandRegClass(II, Op0, II.getNumDefs());
- if (II.getNumDefs() >= 1)
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
- .addReg(Op0, getKillRegState(Op0IsKill))
- .addImm(Imm);
- else {
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addReg(Op0, getKillRegState(Op0IsKill))
- .addImm(Imm);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg).addReg(II.ImplicitDefs[0]);
- }
- return ResultReg;
- }
- unsigned FastISel::fastEmitInst_rii(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC, unsigned Op0,
- bool Op0IsKill, uint64_t Imm1,
- uint64_t Imm2) {
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- unsigned ResultReg = createResultReg(RC);
- Op0 = constrainOperandRegClass(II, Op0, II.getNumDefs());
- if (II.getNumDefs() >= 1)
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
- .addReg(Op0, getKillRegState(Op0IsKill))
- .addImm(Imm1)
- .addImm(Imm2);
- else {
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addReg(Op0, getKillRegState(Op0IsKill))
- .addImm(Imm1)
- .addImm(Imm2);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg).addReg(II.ImplicitDefs[0]);
- }
- return ResultReg;
- }
- unsigned FastISel::fastEmitInst_rf(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC, unsigned Op0,
- bool Op0IsKill, const ConstantFP *FPImm) {
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- unsigned ResultReg = createResultReg(RC);
- Op0 = constrainOperandRegClass(II, Op0, II.getNumDefs());
- if (II.getNumDefs() >= 1)
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
- .addReg(Op0, getKillRegState(Op0IsKill))
- .addFPImm(FPImm);
- else {
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addReg(Op0, getKillRegState(Op0IsKill))
- .addFPImm(FPImm);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg).addReg(II.ImplicitDefs[0]);
- }
- return ResultReg;
- }
- unsigned FastISel::fastEmitInst_rri(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC, unsigned Op0,
- bool Op0IsKill, unsigned Op1,
- bool Op1IsKill, uint64_t Imm) {
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- unsigned ResultReg = createResultReg(RC);
- Op0 = constrainOperandRegClass(II, Op0, II.getNumDefs());
- Op1 = constrainOperandRegClass(II, Op1, II.getNumDefs() + 1);
- if (II.getNumDefs() >= 1)
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
- .addReg(Op0, getKillRegState(Op0IsKill))
- .addReg(Op1, getKillRegState(Op1IsKill))
- .addImm(Imm);
- else {
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addReg(Op0, getKillRegState(Op0IsKill))
- .addReg(Op1, getKillRegState(Op1IsKill))
- .addImm(Imm);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg).addReg(II.ImplicitDefs[0]);
- }
- return ResultReg;
- }
- unsigned FastISel::fastEmitInst_rrii(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC,
- unsigned Op0, bool Op0IsKill, unsigned Op1,
- bool Op1IsKill, uint64_t Imm1,
- uint64_t Imm2) {
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- unsigned ResultReg = createResultReg(RC);
- Op0 = constrainOperandRegClass(II, Op0, II.getNumDefs());
- Op1 = constrainOperandRegClass(II, Op1, II.getNumDefs() + 1);
- if (II.getNumDefs() >= 1)
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
- .addReg(Op0, getKillRegState(Op0IsKill))
- .addReg(Op1, getKillRegState(Op1IsKill))
- .addImm(Imm1)
- .addImm(Imm2);
- else {
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
- .addReg(Op0, getKillRegState(Op0IsKill))
- .addReg(Op1, getKillRegState(Op1IsKill))
- .addImm(Imm1)
- .addImm(Imm2);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg).addReg(II.ImplicitDefs[0]);
- }
- return ResultReg;
- }
- unsigned FastISel::fastEmitInst_i(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC, uint64_t Imm) {
- unsigned ResultReg = createResultReg(RC);
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- if (II.getNumDefs() >= 1)
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
- .addImm(Imm);
- else {
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II).addImm(Imm);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg).addReg(II.ImplicitDefs[0]);
- }
- return ResultReg;
- }
- unsigned FastISel::fastEmitInst_ii(unsigned MachineInstOpcode,
- const TargetRegisterClass *RC, uint64_t Imm1,
- uint64_t Imm2) {
- unsigned ResultReg = createResultReg(RC);
- const MCInstrDesc &II = TII.get(MachineInstOpcode);
- if (II.getNumDefs() >= 1)
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
- .addImm(Imm1)
- .addImm(Imm2);
- else {
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II).addImm(Imm1)
- .addImm(Imm2);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
- TII.get(TargetOpcode::COPY), ResultReg).addReg(II.ImplicitDefs[0]);
- }
- return ResultReg;
- }
- unsigned FastISel::fastEmitInst_extractsubreg(MVT RetVT, unsigned Op0,
- bool Op0IsKill, uint32_t Idx) {
- unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT));
- assert(TargetRegisterInfo::isVirtualRegister(Op0) &&
- "Cannot yet extract from physregs");
- const TargetRegisterClass *RC = MRI.getRegClass(Op0);
- MRI.constrainRegClass(Op0, TRI.getSubClassWithSubReg(RC, Idx));
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TargetOpcode::COPY),
- ResultReg).addReg(Op0, getKillRegState(Op0IsKill), Idx);
- return ResultReg;
- }
- /// Emit MachineInstrs to compute the value of Op with all but the least
- /// significant bit set to zero.
- unsigned FastISel::fastEmitZExtFromI1(MVT VT, unsigned Op0, bool Op0IsKill) {
- return fastEmit_ri(VT, VT, ISD::AND, Op0, Op0IsKill, 1);
- }
- /// HandlePHINodesInSuccessorBlocks - Handle PHI nodes in successor blocks.
- /// Emit code to ensure constants are copied into registers when needed.
- /// Remember the virtual registers that need to be added to the Machine PHI
- /// nodes as input. We cannot just directly add them, because expansion
- /// might result in multiple MBB's for one BB. As such, the start of the
- /// BB might correspond to a different MBB than the end.
- bool FastISel::handlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {
- const TerminatorInst *TI = LLVMBB->getTerminator();
- SmallPtrSet<MachineBasicBlock *, 4> SuccsHandled;
- FuncInfo.OrigNumPHINodesToUpdate = FuncInfo.PHINodesToUpdate.size();
- // Check successor nodes' PHI nodes that expect a constant to be available
- // from this block.
- for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) {
- const BasicBlock *SuccBB = TI->getSuccessor(succ);
- if (!isa<PHINode>(SuccBB->begin()))
- continue;
- MachineBasicBlock *SuccMBB = FuncInfo.MBBMap[SuccBB];
- // If this terminator has multiple identical successors (common for
- // switches), only handle each succ once.
- if (!SuccsHandled.insert(SuccMBB).second)
- continue;
- MachineBasicBlock::iterator MBBI = SuccMBB->begin();
- // At this point we know that there is a 1-1 correspondence between LLVM PHI
- // nodes and Machine PHI nodes, but the incoming operands have not been
- // emitted yet.
- for (BasicBlock::const_iterator I = SuccBB->begin();
- const auto *PN = dyn_cast<PHINode>(I); ++I) {
- // Ignore dead phi's.
- if (PN->use_empty())
- continue;
- // Only handle legal types. Two interesting things to note here. First,
- // by bailing out early, we may leave behind some dead instructions,
- // since SelectionDAG's HandlePHINodesInSuccessorBlocks will insert its
- // own moves. Second, this check is necessary because FastISel doesn't
- // use CreateRegs to create registers, so it always creates
- // exactly one register for each non-void instruction.
- EVT VT = TLI.getValueType(DL, PN->getType(), /*AllowUnknown=*/true);
- if (VT == MVT::Other || !TLI.isTypeLegal(VT)) {
- // Handle integer promotions, though, because they're common and easy.
- if (!(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)) {
- FuncInfo.PHINodesToUpdate.resize(FuncInfo.OrigNumPHINodesToUpdate);
- return false;
- }
- }
- const Value *PHIOp = PN->getIncomingValueForBlock(LLVMBB);
- // Set the DebugLoc for the copy. Prefer the location of the operand
- // if there is one; use the location of the PHI otherwise.
- DbgLoc = PN->getDebugLoc();
- if (const auto *Inst = dyn_cast<Instruction>(PHIOp))
- DbgLoc = Inst->getDebugLoc();
- unsigned Reg = getRegForValue(PHIOp);
- if (!Reg) {
- FuncInfo.PHINodesToUpdate.resize(FuncInfo.OrigNumPHINodesToUpdate);
- return false;
- }
- FuncInfo.PHINodesToUpdate.push_back(std::make_pair(MBBI++, Reg));
- DbgLoc = DebugLoc();
- }
- }
- return true;
- }
- bool FastISel::tryToFoldLoad(const LoadInst *LI, const Instruction *FoldInst) {
- assert(LI->hasOneUse() &&
- "tryToFoldLoad expected a LoadInst with a single use");
- // We know that the load has a single use, but don't know what it is. If it
- // isn't one of the folded instructions, then we can't succeed here. Handle
- // this by scanning the single-use users of the load until we get to FoldInst.
- unsigned MaxUsers = 6; // Don't scan down huge single-use chains of instrs.
- const Instruction *TheUser = LI->user_back();
- while (TheUser != FoldInst && // Scan up until we find FoldInst.
- // Stay in the right block.
- TheUser->getParent() == FoldInst->getParent() &&
- --MaxUsers) { // Don't scan too far.
- // If there are multiple or no uses of this instruction, then bail out.
- if (!TheUser->hasOneUse())
- return false;
- TheUser = TheUser->user_back();
- }
- // If we didn't find the fold instruction, then we failed to collapse the
- // sequence.
- if (TheUser != FoldInst)
- return false;
- // Don't try to fold volatile loads. Target has to deal with alignment
- // constraints.
- if (LI->isVolatile())
- return false;
- // Figure out which vreg this is going into. If there is no assigned vreg yet
- // then there actually was no reference to it. Perhaps the load is referenced
- // by a dead instruction.
- unsigned LoadReg = getRegForValue(LI);
- if (!LoadReg)
- return false;
- // We can't fold if this vreg has no uses or more than one use. Multiple uses
- // may mean that the instruction got lowered to multiple MIs, or the use of
- // the loaded value ended up being multiple operands of the result.
- if (!MRI.hasOneUse(LoadReg))
- return false;
- MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(LoadReg);
- MachineInstr *User = RI->getParent();
- // Set the insertion point properly. Folding the load can cause generation of
- // other random instructions (like sign extends) for addressing modes; make
- // sure they get inserted in a logical place before the new instruction.
- FuncInfo.InsertPt = User;
- FuncInfo.MBB = User->getParent();
- // Ask the target to try folding the load.
- return tryToFoldLoadIntoMI(User, RI.getOperandNo(), LI);
- }
- bool FastISel::canFoldAddIntoGEP(const User *GEP, const Value *Add) {
- // Must be an add.
- if (!isa<AddOperator>(Add))
- return false;
- // Type size needs to match.
- if (DL.getTypeSizeInBits(GEP->getType()) !=
- DL.getTypeSizeInBits(Add->getType()))
- return false;
- // Must be in the same basic block.
- if (isa<Instruction>(Add) &&
- FuncInfo.MBBMap[cast<Instruction>(Add)->getParent()] != FuncInfo.MBB)
- return false;
- // Must have a constant operand.
- return isa<ConstantInt>(cast<AddOperator>(Add)->getOperand(1));
- }
- MachineMemOperand *
- FastISel::createMachineMemOperandFor(const Instruction *I) const {
- const Value *Ptr;
- Type *ValTy;
- unsigned Alignment;
- unsigned Flags;
- bool IsVolatile;
- if (const auto *LI = dyn_cast<LoadInst>(I)) {
- Alignment = LI->getAlignment();
- IsVolatile = LI->isVolatile();
- Flags = MachineMemOperand::MOLoad;
- Ptr = LI->getPointerOperand();
- ValTy = LI->getType();
- } else if (const auto *SI = dyn_cast<StoreInst>(I)) {
- Alignment = SI->getAlignment();
- IsVolatile = SI->isVolatile();
- Flags = MachineMemOperand::MOStore;
- Ptr = SI->getPointerOperand();
- ValTy = SI->getValueOperand()->getType();
- } else
- return nullptr;
- bool IsNonTemporal = I->getMetadata(LLVMContext::MD_nontemporal) != nullptr;
- bool IsInvariant = I->getMetadata(LLVMContext::MD_invariant_load) != nullptr;
- const MDNode *Ranges = I->getMetadata(LLVMContext::MD_range);
- AAMDNodes AAInfo;
- I->getAAMetadata(AAInfo);
- if (Alignment == 0) // Ensure that codegen never sees alignment 0.
- Alignment = DL.getABITypeAlignment(ValTy);
- unsigned Size = DL.getTypeStoreSize(ValTy);
- if (IsVolatile)
- Flags |= MachineMemOperand::MOVolatile;
- if (IsNonTemporal)
- Flags |= MachineMemOperand::MONonTemporal;
- if (IsInvariant)
- Flags |= MachineMemOperand::MOInvariant;
- return FuncInfo.MF->getMachineMemOperand(MachinePointerInfo(Ptr), Flags, Size,
- Alignment, AAInfo, Ranges);
- }
- CmpInst::Predicate FastISel::optimizeCmpPredicate(const CmpInst *CI) const {
- // If both operands are the same, then try to optimize or fold the cmp.
- CmpInst::Predicate Predicate = CI->getPredicate();
- if (CI->getOperand(0) != CI->getOperand(1))
- return Predicate;
- switch (Predicate) {
- default: llvm_unreachable("Invalid predicate!");
- case CmpInst::FCMP_FALSE: Predicate = CmpInst::FCMP_FALSE; break;
- case CmpInst::FCMP_OEQ: Predicate = CmpInst::FCMP_ORD; break;
- case CmpInst::FCMP_OGT: Predicate = CmpInst::FCMP_FALSE; break;
- case CmpInst::FCMP_OGE: Predicate = CmpInst::FCMP_ORD; break;
- case CmpInst::FCMP_OLT: Predicate = CmpInst::FCMP_FALSE; break;
- case CmpInst::FCMP_OLE: Predicate = CmpInst::FCMP_ORD; break;
- case CmpInst::FCMP_ONE: Predicate = CmpInst::FCMP_FALSE; break;
- case CmpInst::FCMP_ORD: Predicate = CmpInst::FCMP_ORD; break;
- case CmpInst::FCMP_UNO: Predicate = CmpInst::FCMP_UNO; break;
- case CmpInst::FCMP_UEQ: Predicate = CmpInst::FCMP_TRUE; break;
- case CmpInst::FCMP_UGT: Predicate = CmpInst::FCMP_UNO; break;
- case CmpInst::FCMP_UGE: Predicate = CmpInst::FCMP_TRUE; break;
- case CmpInst::FCMP_ULT: Predicate = CmpInst::FCMP_UNO; break;
- case CmpInst::FCMP_ULE: Predicate = CmpInst::FCMP_TRUE; break;
- case CmpInst::FCMP_UNE: Predicate = CmpInst::FCMP_UNO; break;
- case CmpInst::FCMP_TRUE: Predicate = CmpInst::FCMP_TRUE; break;
- case CmpInst::ICMP_EQ: Predicate = CmpInst::FCMP_TRUE; break;
- case CmpInst::ICMP_NE: Predicate = CmpInst::FCMP_FALSE; break;
- case CmpInst::ICMP_UGT: Predicate = CmpInst::FCMP_FALSE; break;
- case CmpInst::ICMP_UGE: Predicate = CmpInst::FCMP_TRUE; break;
- case CmpInst::ICMP_ULT: Predicate = CmpInst::FCMP_FALSE; break;
- case CmpInst::ICMP_ULE: Predicate = CmpInst::FCMP_TRUE; break;
- case CmpInst::ICMP_SGT: Predicate = CmpInst::FCMP_FALSE; break;
- case CmpInst::ICMP_SGE: Predicate = CmpInst::FCMP_TRUE; break;
- case CmpInst::ICMP_SLT: Predicate = CmpInst::FCMP_FALSE; break;
- case CmpInst::ICMP_SLE: Predicate = CmpInst::FCMP_TRUE; break;
- }
- return Predicate;
- }
|