26 class MipsFastISel final :
public FastISel {
31 typedef enum { RegBase, FrameIndexBase } BaseKind;
46 Address() :
Kind(RegBase), Offset(0), GV(0) { Base.Reg = 0; }
47 void setKind(BaseKind K) {
Kind = K; }
48 BaseKind getKind()
const {
return Kind; }
49 bool isRegBase()
const {
return Kind == RegBase; }
50 bool isFIBase()
const {
return Kind == FrameIndexBase; }
51 void setReg(
unsigned Reg) {
52 assert(isRegBase() &&
"Invalid base register access!");
56 assert(isRegBase() &&
"Invalid base register access!");
59 void setFI(
unsigned FI) {
60 assert(isFIBase() &&
"Invalid base frame index access!");
63 unsigned getFI()
const {
64 assert(isFIBase() &&
"Invalid base frame index access!");
68 void setOffset(int64_t Offset_) { Offset = Offset_; }
69 int64_t
getOffset()
const {
return Offset; }
85 bool fastLowerCall(CallLoweringInfo &CLI)
override;
86 bool fastLowerIntrinsicCall(
const IntrinsicInst *II)
override;
89 bool UnsupportedFPMode;
103 bool selectFPToInt(
const Instruction *
I,
bool IsSigned);
108 bool selectDivRem(
const Instruction *
I,
unsigned ISDOpcode);
111 bool isTypeLegal(
Type *Ty,
MVT &VT);
112 bool isTypeSupported(
Type *Ty,
MVT &VT);
113 bool isLoadTypeLegal(
Type *Ty,
MVT &VT);
116 void simplifyAddress(
Address &Addr);
120 bool emitLoad(
MVT VT,
unsigned &ResultReg,
Address &Addr,
121 unsigned Alignment = 0);
122 bool emitStore(
MVT VT,
unsigned SrcReg,
Address Addr,
124 bool emitStore(
MVT VT,
unsigned SrcReg,
Address &Addr,
125 unsigned Alignment = 0);
126 unsigned emitIntExt(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
bool isZExt);
127 bool emitIntExt(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
unsigned DestReg,
130 bool emitIntZExt(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
unsigned DestReg);
132 bool emitIntSExt(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
unsigned DestReg);
133 bool emitIntSExt32r1(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
135 bool emitIntSExt32r2(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
138 unsigned getRegEnsuringSimpleIntegerWidening(
const Value *,
bool IsUnsigned);
140 unsigned emitLogicalOp(
unsigned ISDOpc,
MVT RetVT,
const Value *LHS,
147 unsigned materializeExternalCallSym(
MCSymbol *Syn);
150 return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc));
153 return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc),
157 unsigned MemReg, int64_t MemOffset) {
161 unsigned MemReg, int64_t MemOffset) {
162 return emitInst(Opc, DstReg).
addReg(MemReg).
addImm(MemOffset);
165 unsigned fastEmitInst_rr(
unsigned MachineInstOpcode,
167 unsigned Op0,
bool Op0IsKill,
168 unsigned Op1,
bool Op1IsKill);
174 unsigned Op0,
bool Op0IsKill, uint64_t imm1,
175 uint64_t imm2,
unsigned Op3,
bool Op3IsKill) {
184 bool finishCall(CallLoweringInfo &CLI,
MVT RetVT,
unsigned NumBytes);
190 :
FastISel(funcInfo, libInfo),
TM(funcInfo.MF->getTarget()),
192 TII(*Subtarget->getInstrInfo()), TLI(*Subtarget->getTargetLowering()) {
197 ((Subtarget->hasMips32r2() || Subtarget->hasMips32()) &&
198 (static_cast<const MipsTargetMachine &>(
TM).getABI().IsO32())));
199 UnsupportedFPMode = Subtarget->isFP64bit();
202 unsigned fastMaterializeAlloca(
const AllocaInst *AI)
override;
203 unsigned fastMaterializeConstant(
const Constant *
C)
override;
204 bool fastSelectInstruction(
const Instruction *
I)
override;
206 #include "MipsGenFastISel.inc"
226 #include "MipsGenCallingConv.inc"
232 unsigned MipsFastISel::emitLogicalOp(
unsigned ISDOpc,
MVT RetVT,
235 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS))
241 }
else if (ISDOpc ==
ISD::OR) {
248 unsigned LHSReg = getRegForValue(LHS);
249 unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
257 if (
const auto *C = dyn_cast<ConstantInt>(RHS))
258 RHSReg = materializeInt(C,
MVT::i32);
260 RHSReg = getRegForValue(RHS);
265 emitInst(Opc, ResultReg).addReg(LHSReg).addReg(RHSReg);
269 unsigned MipsFastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
270 if (!TargetSupported)
274 "Alloca should always return a pointer.");
277 FuncInfo.StaticAllocaMap.find(AI);
279 if (SI != FuncInfo.StaticAllocaMap.
end()) {
280 unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
281 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Mips::LEA_ADDiu),
283 .addFrameIndex(SI->second)
291 unsigned MipsFastISel::materializeInt(
const Constant *C,
MVT VT) {
299 unsigned MipsFastISel::materialize32BitInt(int64_t Imm,
301 unsigned ResultReg = createResultReg(RC);
304 unsigned Opc = Mips::ADDiu;
305 emitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm);
308 emitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm);
311 unsigned Lo = Imm & 0xFFFF;
312 unsigned Hi = (Imm >> 16) & 0xFFFF;
315 unsigned TmpReg = createResultReg(RC);
316 emitInst(Mips::LUi, TmpReg).addImm(Hi);
317 emitInst(Mips::ORi, ResultReg).addReg(TmpReg).addImm(Lo);
319 emitInst(Mips::LUi, ResultReg).addImm(Hi);
324 unsigned MipsFastISel::materializeFP(
const ConstantFP *CFP,
MVT VT) {
325 if (UnsupportedFPMode)
330 unsigned DestReg = createResultReg(RC);
331 unsigned TempReg = materialize32BitInt(Imm, &Mips::GPR32RegClass);
332 emitInst(Mips::MTC1, DestReg).addReg(TempReg);
336 unsigned DestReg = createResultReg(RC);
337 unsigned TempReg1 = materialize32BitInt(Imm >> 32, &Mips::GPR32RegClass);
339 materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass);
346 unsigned MipsFastISel::materializeGV(
const GlobalValue *GV,
MVT VT) {
351 unsigned DestReg = createResultReg(RC);
357 emitInst(Mips::LW, DestReg)
358 .addReg(MFI->getGlobalBaseReg())
362 unsigned TempReg = createResultReg(RC);
363 emitInst(Mips::ADDiu, TempReg)
371 unsigned MipsFastISel::materializeExternalCallSym(
MCSymbol *Sym) {
373 unsigned DestReg = createResultReg(RC);
374 emitInst(Mips::LW, DestReg)
375 .addReg(MFI->getGlobalBaseReg())
382 unsigned MipsFastISel::fastMaterializeConstant(
const Constant *C) {
383 if (!TargetSupported)
386 EVT CEVT = TLI.getValueType(DL, C->
getType(),
true);
393 if (
const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
394 return (UnsupportedFPMode) ? 0 : materializeFP(CFP, VT);
395 else if (
const GlobalValue *GV = dyn_cast<GlobalValue>(C))
396 return materializeGV(GV, VT);
397 else if (isa<ConstantInt>(C))
398 return materializeInt(C, VT);
403 bool MipsFastISel::computeAddress(
const Value *Obj,
Address &Addr) {
405 const User *U =
nullptr;
406 unsigned Opcode = Instruction::UserOp1;
407 if (
const Instruction *
I = dyn_cast<Instruction>(Obj)) {
410 if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
411 FuncInfo.MBBMap[
I->getParent()] == FuncInfo.MBB) {
412 Opcode =
I->getOpcode();
415 }
else if (
const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
416 Opcode = C->getOpcode();
422 case Instruction::BitCast: {
424 return computeAddress(U->
getOperand(0), Addr);
426 case Instruction::GetElementPtr: {
428 uint64_t TmpOffset = Addr.getOffset();
434 const Value *Op = *i;
435 if (
StructType *STy = dyn_cast<StructType>(*GTI)) {
437 unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
442 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
447 if (canFoldAddIntoGEP(U, Op)) {
450 cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
453 Op = cast<AddOperator>(Op)->getOperand(0);
457 goto unsupported_gep;
462 Addr.setOffset(TmpOffset);
470 case Instruction::Alloca: {
473 FuncInfo.StaticAllocaMap.
find(AI);
474 if (SI != FuncInfo.StaticAllocaMap.end()) {
475 Addr.setKind(Address::FrameIndexBase);
476 Addr.setFI(SI->second);
482 Addr.setReg(getRegForValue(Obj));
483 return Addr.getReg() != 0;
486 bool MipsFastISel::computeCallAddress(
const Value *V,
Address &Addr) {
487 const User *U =
nullptr;
488 unsigned Opcode = Instruction::UserOp1;
490 if (
const auto *
I = dyn_cast<Instruction>(V)) {
493 if (
I->getParent() == FuncInfo.MBB->getBasicBlock()) {
494 Opcode =
I->getOpcode();
497 }
else if (
const auto *C = dyn_cast<ConstantExpr>(V)) {
498 Opcode = C->getOpcode();
505 case Instruction::BitCast:
507 return computeCallAddress(U->
getOperand(0), Addr);
509 case Instruction::IntToPtr:
512 TLI.getPointerTy(DL))
513 return computeCallAddress(U->
getOperand(0), Addr);
515 case Instruction::PtrToInt:
517 if (TLI.getValueType(DL, U->
getType()) == TLI.getPointerTy(DL))
518 return computeCallAddress(U->
getOperand(0), Addr);
522 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
523 Addr.setGlobalValue(GV);
528 if (!Addr.getGlobalValue()) {
529 Addr.setReg(getRegForValue(V));
530 return Addr.getReg() != 0;
536 bool MipsFastISel::isTypeLegal(
Type *Ty,
MVT &VT) {
537 EVT evt = TLI.getValueType(DL, Ty,
true);
545 return TLI.isTypeLegal(VT);
548 bool MipsFastISel::isTypeSupported(
Type *Ty,
MVT &VT) {
552 if (isTypeLegal(Ty, VT))
563 bool MipsFastISel::isLoadTypeLegal(
Type *Ty,
MVT &VT) {
564 if (isTypeLegal(Ty, VT))
580 unsigned LeftReg = getRegEnsuringSimpleIntegerWidening(Left, IsUnsigned);
583 unsigned RightReg = getRegEnsuringSimpleIntegerWidening(Right, IsUnsigned);
592 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
593 emitInst(
Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg);
594 emitInst(Mips::SLTiu, ResultReg).addReg(TempReg).addImm(1);
598 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
599 emitInst(
Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg);
600 emitInst(Mips::SLTu, ResultReg).addReg(Mips::ZERO).addReg(TempReg);
604 emitInst(Mips::SLTu, ResultReg).addReg(RightReg).addReg(LeftReg);
608 emitInst(Mips::SLTu, ResultReg).addReg(LeftReg).addReg(RightReg);
612 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
613 emitInst(Mips::SLTu, TempReg).addReg(LeftReg).addReg(RightReg);
614 emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
618 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
619 emitInst(Mips::SLTu, TempReg).addReg(RightReg).addReg(LeftReg);
620 emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
624 emitInst(Mips::SLT, ResultReg).addReg(RightReg).addReg(LeftReg);
628 emitInst(Mips::SLT, ResultReg).addReg(LeftReg).addReg(RightReg);
632 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
633 emitInst(Mips::SLT, TempReg).addReg(LeftReg).addReg(RightReg);
634 emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
638 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
639 emitInst(Mips::SLT, TempReg).addReg(RightReg).addReg(LeftReg);
640 emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
649 if (UnsupportedFPMode)
653 if (!IsFloat && !IsDouble)
655 unsigned Opc, CondMovOpc;
658 Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32;
659 CondMovOpc = Mips::MOVT_I;
662 Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32;
663 CondMovOpc = Mips::MOVF_I;
666 Opc = IsFloat ? Mips::C_OLT_S : Mips::C_OLT_D32;
667 CondMovOpc = Mips::MOVT_I;
670 Opc = IsFloat ? Mips::C_OLE_S : Mips::C_OLE_D32;
671 CondMovOpc = Mips::MOVT_I;
674 Opc = IsFloat ? Mips::C_ULE_S : Mips::C_ULE_D32;
675 CondMovOpc = Mips::MOVF_I;
678 Opc = IsFloat ? Mips::C_ULT_S : Mips::C_ULT_D32;
679 CondMovOpc = Mips::MOVF_I;
684 unsigned RegWithZero = createResultReg(&Mips::GPR32RegClass);
685 unsigned RegWithOne = createResultReg(&Mips::GPR32RegClass);
686 emitInst(Mips::ADDiu, RegWithZero).addReg(Mips::ZERO).addImm(0);
687 emitInst(Mips::ADDiu, RegWithOne).addReg(Mips::ZERO).addImm(1);
688 emitInst(Opc).addReg(LeftReg).addReg(RightReg).addReg(
700 bool MipsFastISel::emitLoad(
MVT VT,
unsigned &ResultReg,
Address &Addr,
701 unsigned Alignment) {
708 ResultReg = createResultReg(&Mips::GPR32RegClass);
713 ResultReg = createResultReg(&Mips::GPR32RegClass);
718 ResultReg = createResultReg(&Mips::GPR32RegClass);
723 if (UnsupportedFPMode)
725 ResultReg = createResultReg(&Mips::FGR32RegClass);
730 if (UnsupportedFPMode)
732 ResultReg = createResultReg(&Mips::AFGR64RegClass);
739 if (Addr.isRegBase()) {
740 simplifyAddress(Addr);
741 emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset());
744 if (Addr.isFIBase()) {
745 unsigned FI = Addr.getFI();
747 unsigned Offset = Addr.getOffset();
752 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
761 bool MipsFastISel::emitStore(
MVT VT,
unsigned SrcReg,
Address &Addr,
762 unsigned Alignment) {
778 if (UnsupportedFPMode)
783 if (UnsupportedFPMode)
790 if (Addr.isRegBase()) {
791 simplifyAddress(Addr);
792 emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset());
795 if (Addr.isFIBase()) {
796 unsigned FI = Addr.getFI();
798 unsigned Offset = Addr.getOffset();
803 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc))
813 bool MipsFastISel::selectLogicalOp(
const Instruction *
I) {
815 if (!isTypeSupported(I->
getType(), VT))
836 updateValueMap(I, ResultReg);
840 bool MipsFastISel::selectLoad(
const Instruction *I) {
847 if (!isLoadTypeLegal(I->
getType(), VT))
856 if (!emitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment()))
858 updateValueMap(I, ResultReg);
862 bool MipsFastISel::selectStore(
const Instruction *I) {
876 SrcReg = getRegForValue(Op0);
885 if (!emitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment()))
894 bool MipsFastISel::selectBranch(
const Instruction *I) {
909 unsigned CondReg = createResultReg(&Mips::GPR32RegClass);
912 BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Mips::BGTZ))
915 fastEmitBranch(FBB, DbgLoc);
916 FuncInfo.MBB->addSuccessor(TBB);
922 bool MipsFastISel::selectCmp(
const Instruction *I) {
923 const CmpInst *CI = cast<CmpInst>(
I);
924 unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
927 updateValueMap(I, ResultReg);
932 bool MipsFastISel::selectFPExt(
const Instruction *I) {
933 if (UnsupportedFPMode)
936 EVT SrcVT = TLI.getValueType(DL, Src->
getType(),
true);
937 EVT DestVT = TLI.getValueType(DL, I->
getType(),
true);
948 unsigned DestReg = createResultReg(&Mips::AFGR64RegClass);
949 emitInst(Mips::CVT_D32_S, DestReg).addReg(SrcReg);
950 updateValueMap(I, DestReg);
954 bool MipsFastISel::selectSelect(
const Instruction *I) {
955 assert(isa<SelectInst>(I) &&
"Expected a select instruction.");
958 if (!isTypeSupported(I->
getType(), VT))
965 CondMovOpc = Mips::MOVN_I_I;
966 RC = &Mips::GPR32RegClass;
968 CondMovOpc = Mips::MOVN_I_S;
969 RC = &Mips::FGR32RegClass;
971 CondMovOpc = Mips::MOVN_I_D32;
972 RC = &Mips::AFGR64RegClass;
980 unsigned CondReg = getRegForValue(Cond);
982 if (!Src1Reg || !Src2Reg || !CondReg)
985 unsigned ZExtCondReg = createResultReg(&Mips::GPR32RegClass);
992 unsigned ResultReg = createResultReg(RC);
993 unsigned TempReg = createResultReg(RC);
995 if (!ResultReg || !TempReg)
999 emitInst(CondMovOpc, ResultReg)
1000 .addReg(Src1Reg).addReg(ZExtCondReg).addReg(TempReg);
1001 updateValueMap(I, ResultReg);
1006 bool MipsFastISel::selectFPTrunc(
const Instruction *I) {
1007 if (UnsupportedFPMode)
1010 EVT SrcVT = TLI.getValueType(DL, Src->
getType(),
true);
1011 EVT DestVT = TLI.getValueType(DL, I->
getType(),
true);
1016 unsigned SrcReg = getRegForValue(Src);
1020 unsigned DestReg = createResultReg(&Mips::FGR32RegClass);
1024 emitInst(Mips::CVT_S_D32, DestReg).addReg(SrcReg);
1025 updateValueMap(I, DestReg);
1030 bool MipsFastISel::selectFPToInt(
const Instruction *I,
bool IsSigned) {
1031 if (UnsupportedFPMode)
1038 if (!isTypeLegal(DstTy, DstVT))
1046 if (!isTypeLegal(SrcTy, SrcVT))
1052 unsigned SrcReg = getRegForValue(Src);
1058 unsigned DestReg = createResultReg(&Mips::GPR32RegClass);
1059 unsigned TempReg = createResultReg(&Mips::FGR32RegClass);
1063 Opc = Mips::TRUNC_W_S;
1065 Opc = Mips::TRUNC_W_D32;
1068 emitInst(Opc, TempReg).addReg(SrcReg);
1070 emitInst(Mips::MFC1, DestReg).addReg(TempReg);
1072 updateValueMap(I, DestReg);
1076 bool MipsFastISel::processCallArgs(CallLoweringInfo &CLI,
1078 unsigned &NumBytes) {
1081 CCState CCInfo(CC,
false, *FuncInfo.MF, ArgLocs, *Context);
1082 CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, CCAssignFnForCall(CC));
1084 NumBytes = CCInfo.getNextStackOffset();
1089 emitInst(Mips::ADJCALLSTACKDOWN).addImm(16);
1092 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
1104 }
else if (i == 1) {
1133 unsigned ArgReg = getRegForValue(ArgVal);
1145 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
false);
1153 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
true);
1164 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1176 assert(VA.
isMemLoc() &&
"Assuming store on stack.");
1178 if (isa<UndefValue>(ArgVal))
1188 unsigned BEAlign = 0;
1189 if (ArgSize < 8 && !Subtarget->isLittle())
1190 BEAlign = 8 - ArgSize;
1193 Addr.setKind(Address::RegBase);
1194 Addr.setReg(Mips::SP);
1197 unsigned Alignment =
DL.getABITypeAlignment(ArgVal->
getType());
1210 bool MipsFastISel::finishCall(CallLoweringInfo &CLI,
MVT RetVT,
1211 unsigned NumBytes) {
1213 emitInst(Mips::ADJCALLSTACKUP).addImm(16);
1216 CCState CCInfo(CC,
false, *FuncInfo.MF, RVLocs, *Context);
1217 CCInfo.AnalyzeCallResult(RetVT, RetCC_Mips);
1220 if (RVLocs.
size() != 1)
1223 MVT CopyVT = RVLocs[0].getValVT();
1228 unsigned ResultReg = createResultReg(TLI.getRegClassFor(CopyVT));
1231 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1233 ResultReg).addReg(RVLocs[0].getLocReg());
1234 CLI.InRegs.push_back(RVLocs[0].getLocReg());
1236 CLI.ResultReg = ResultReg;
1237 CLI.NumResultRegs = 1;
1242 bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) {
1243 if (!TargetSupported)
1247 bool IsTailCall = CLI.IsTailCall;
1248 bool IsVarArg = CLI.IsVarArg;
1249 const Value *Callee = CLI.Callee;
1266 if (CLI.RetTy->isVoidTy())
1268 else if (!isTypeSupported(CLI.RetTy, RetVT))
1271 for (
auto Flag : CLI.OutFlags)
1277 OutVTs.
reserve(CLI.OutVals.size());
1279 for (
auto *Val : CLI.OutVals) {
1281 if (!isTypeLegal(Val->getType(), VT) &&
1293 if (!computeCallAddress(Callee, Addr))
1298 if (!processCallArgs(CLI, OutVTs, NumBytes))
1301 if (!Addr.getGlobalValue())
1305 unsigned DestAddress;
1307 DestAddress = materializeExternalCallSym(Symbol);
1309 DestAddress = materializeGV(Addr.getGlobalValue(),
MVT::i32);
1312 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Mips::JALR),
1313 Mips::RA).addReg(Mips::T9);
1316 for (
auto Reg : CLI.OutRegs)
1321 MIB.
addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC));
1326 return finishCall(CLI, RetVT, NumBytes);
1329 bool MipsFastISel::fastLowerIntrinsicCall(
const IntrinsicInst *II) {
1330 if (!TargetSupported)
1336 case Intrinsic::bswap: {
1340 if (!isTypeSupported(RetTy, VT))
1343 unsigned SrcReg = getRegForValue(II->
getOperand(0));
1346 unsigned DestReg = createResultReg(&Mips::GPR32RegClass);
1350 if (Subtarget->hasMips32r2()) {
1351 emitInst(Mips::WSBH, DestReg).addReg(SrcReg);
1352 updateValueMap(II, DestReg);
1355 unsigned TempReg[3];
1356 for (
int i = 0; i < 3; i++) {
1357 TempReg[i] = createResultReg(&Mips::GPR32RegClass);
1358 if (TempReg[i] == 0)
1361 emitInst(Mips::SLL, TempReg[0]).addReg(SrcReg).addImm(8);
1362 emitInst(
Mips::SRL, TempReg[1]).addReg(SrcReg).addImm(8);
1363 emitInst(
Mips::OR, TempReg[2]).addReg(TempReg[0]).addReg(TempReg[1]);
1364 emitInst(Mips::ANDi, DestReg).addReg(TempReg[2]).addImm(0xFFFF);
1365 updateValueMap(II, DestReg);
1369 if (Subtarget->hasMips32r2()) {
1370 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
1371 emitInst(Mips::WSBH, TempReg).addReg(SrcReg);
1372 emitInst(
Mips::ROTR, DestReg).addReg(TempReg).addImm(16);
1373 updateValueMap(II, DestReg);
1376 unsigned TempReg[8];
1377 for (
int i = 0; i < 8; i++) {
1378 TempReg[i] = createResultReg(&Mips::GPR32RegClass);
1379 if (TempReg[i] == 0)
1383 emitInst(
Mips::SRL, TempReg[0]).addReg(SrcReg).addImm(8);
1384 emitInst(
Mips::SRL, TempReg[1]).addReg(SrcReg).addImm(24);
1385 emitInst(Mips::ANDi, TempReg[2]).addReg(TempReg[0]).addImm(0xFF00);
1386 emitInst(
Mips::OR, TempReg[3]).addReg(TempReg[1]).addReg(TempReg[2]);
1388 emitInst(Mips::ANDi, TempReg[4]).addReg(SrcReg).addImm(0xFF00);
1389 emitInst(Mips::SLL, TempReg[5]).addReg(TempReg[4]).addImm(8);
1391 emitInst(Mips::SLL, TempReg[6]).addReg(SrcReg).addImm(24);
1392 emitInst(
Mips::OR, TempReg[7]).addReg(TempReg[3]).addReg(TempReg[5]);
1393 emitInst(
Mips::OR, DestReg).addReg(TempReg[6]).addReg(TempReg[7]);
1394 updateValueMap(II, DestReg);
1400 case Intrinsic::memcpy:
1401 case Intrinsic::memmove: {
1402 const auto *MTI = cast<MemTransferInst>(II);
1404 if (MTI->isVolatile())
1406 if (!MTI->getLength()->getType()->isIntegerTy(32))
1408 const char *IntrMemName = isa<MemCpyInst>(II) ?
"memcpy" :
"memmove";
1411 case Intrinsic::memset: {
1412 const MemSetInst *MSI = cast<MemSetInst>(II);
1424 bool MipsFastISel::selectRet(
const Instruction *I) {
1428 if (!FuncInfo.CanLowerReturn)
1449 CCInfo.AnalyzeReturn(Outs, RetCC);
1452 if (ValLocs.size() != 1)
1467 unsigned Reg = getRegForValue(RV);
1471 unsigned SrcReg = Reg + VA.
getValNo();
1474 if (!MRI.getRegClass(SrcReg)->contains(DestReg))
1477 EVT RVEVT = TLI.getValueType(DL, RV->
getType());
1490 if (RVVT != DestVT) {
1494 if (Outs[0].
Flags.isZExt() || Outs[0].Flags.isSExt()) {
1495 bool IsZExt = Outs[0].Flags.isZExt();
1496 SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
1503 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1510 for (
unsigned i = 0, e = RetRegs.
size(); i != e; ++i)
1515 bool MipsFastISel::selectTrunc(
const Instruction *I) {
1521 SrcVT = TLI.getValueType(DL, Op->
getType(),
true);
1522 DestVT = TLI.getValueType(DL, I->
getType(),
true);
1529 unsigned SrcReg = getRegForValue(Op);
1535 updateValueMap(I, SrcReg);
1538 bool MipsFastISel::selectIntExt(
const Instruction *I) {
1543 bool isZExt = isa<ZExtInst>(
I);
1544 unsigned SrcReg = getRegForValue(Src);
1548 EVT SrcEVT, DestEVT;
1549 SrcEVT = TLI.getValueType(DL, SrcTy,
true);
1550 DestEVT = TLI.getValueType(DL, DestTy,
true);
1558 unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
1560 if (!emitIntExt(SrcVT, SrcReg, DestVT, ResultReg, isZExt))
1562 updateValueMap(I, ResultReg);
1565 bool MipsFastISel::emitIntSExt32r1(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
1578 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
1579 emitInst(Mips::SLL, TempReg).addReg(SrcReg).addImm(ShiftAmt);
1580 emitInst(
Mips::SRA, DestReg).addReg(TempReg).addImm(ShiftAmt);
1584 bool MipsFastISel::emitIntSExt32r2(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
1590 emitInst(Mips::SEB, DestReg).addReg(SrcReg);
1593 emitInst(Mips::SEH, DestReg).addReg(SrcReg);
1599 bool MipsFastISel::emitIntSExt(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
1603 if (Subtarget->hasMips32r2())
1604 return emitIntSExt32r2(SrcVT, SrcReg, DestVT, DestReg);
1605 return emitIntSExt32r1(SrcVT, SrcReg, DestVT, DestReg);
1608 bool MipsFastISel::emitIntZExt(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
1614 emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(1);
1617 emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xff);
1620 emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xffff);
1626 bool MipsFastISel::emitIntExt(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
1627 unsigned DestReg,
bool IsZExt) {
1636 return emitIntZExt(SrcVT, SrcReg, DestVT, DestReg);
1637 return emitIntSExt(SrcVT, SrcReg, DestVT, DestReg);
1640 unsigned MipsFastISel::emitIntExt(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
1642 unsigned DestReg = createResultReg(&Mips::GPR32RegClass);
1643 bool Success = emitIntExt(SrcVT, SrcReg, DestVT, DestReg, isZExt);
1644 return Success ? DestReg : 0;
1647 bool MipsFastISel::selectDivRem(
const Instruction *I,
unsigned ISDOpcode) {
1648 EVT DestEVT = TLI.getValueType(DL, I->
getType(),
true);
1657 switch (ISDOpcode) {
1670 unsigned Src0Reg = getRegForValue(I->
getOperand(0));
1671 unsigned Src1Reg = getRegForValue(I->
getOperand(1));
1672 if (!Src0Reg || !Src1Reg)
1675 emitInst(DivOpc).addReg(Src0Reg).addReg(Src1Reg);
1676 emitInst(Mips::TEQ).addReg(Src1Reg).addReg(Mips::ZERO).addImm(7);
1678 unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
1685 emitInst(MFOpc, ResultReg);
1687 updateValueMap(I, ResultReg);
1691 bool MipsFastISel::selectShift(
const Instruction *I) {
1694 if (!isTypeSupported(I->
getType(), RetVT))
1697 unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
1703 unsigned Op0Reg = getRegForValue(Op0);
1708 if (Opcode == Instruction::AShr || Opcode == Instruction::LShr) {
1709 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
1713 MVT Op0MVT = TLI.getValueType(DL, Op0->
getType(),
true).getSimpleVT();
1714 bool IsZExt = Opcode == Instruction::LShr;
1715 if (!emitIntExt(Op0MVT, Op0Reg,
MVT::i32, TempReg, IsZExt))
1721 if (
const auto *C = dyn_cast<ConstantInt>(I->
getOperand(1))) {
1722 uint64_t ShiftVal = C->getZExtValue();
1727 case Instruction::Shl:
1730 case Instruction::AShr:
1733 case Instruction::LShr:
1738 emitInst(Opcode, ResultReg).addReg(Op0Reg).addImm(ShiftVal);
1739 updateValueMap(I, ResultReg);
1743 unsigned Op1Reg = getRegForValue(I->
getOperand(1));
1750 case Instruction::Shl:
1751 Opcode = Mips::SLLV;
1753 case Instruction::AShr:
1754 Opcode = Mips::SRAV;
1756 case Instruction::LShr:
1757 Opcode = Mips::SRLV;
1761 emitInst(Opcode, ResultReg).addReg(Op0Reg).addReg(Op1Reg);
1762 updateValueMap(I, ResultReg);
1766 bool MipsFastISel::fastSelectInstruction(
const Instruction *I) {
1767 if (!TargetSupported)
1773 return selectLoad(I);
1775 return selectStore(I);
1776 case Instruction::SDiv:
1780 case Instruction::UDiv:
1784 case Instruction::SRem:
1788 case Instruction::URem:
1792 case Instruction::Shl:
1793 case Instruction::LShr:
1794 case Instruction::AShr:
1795 return selectShift(I);
1799 return selectLogicalOp(I);
1800 case Instruction::Br:
1801 return selectBranch(I);
1803 return selectRet(I);
1804 case Instruction::Trunc:
1805 return selectTrunc(I);
1806 case Instruction::ZExt:
1807 case Instruction::SExt:
1808 return selectIntExt(I);
1809 case Instruction::FPTrunc:
1810 return selectFPTrunc(I);
1811 case Instruction::FPExt:
1812 return selectFPExt(I);
1813 case Instruction::FPToSI:
1814 return selectFPToInt(I,
true);
1815 case Instruction::FPToUI:
1816 return selectFPToInt(I,
false);
1817 case Instruction::ICmp:
1818 case Instruction::FCmp:
1819 return selectCmp(I);
1821 return selectSelect(I);
1826 unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(
const Value *V,
1828 unsigned VReg = getRegForValue(V);
1831 MVT VMVT = TLI.getValueType(DL, V->
getType(),
true).getSimpleVT();
1833 unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
1834 if (!emitIntExt(VMVT, VReg,
MVT::i32, TempReg, IsUnsigned))
1841 void MipsFastISel::simplifyAddress(
Address &Addr) {
1844 materialize32BitInt(Addr.getOffset(), &Mips::GPR32RegClass);
1845 unsigned DestReg = createResultReg(&Mips::GPR32RegClass);
1846 emitInst(Mips::ADDu, DestReg).addReg(TempReg).addReg(Addr.getReg());
1847 Addr.setReg(DestReg);
1852 unsigned MipsFastISel::fastEmitInst_rr(
unsigned MachineInstOpcode,
1854 unsigned Op0,
bool Op0IsKill,
1855 unsigned Op1,
bool Op1IsKill) {
1863 unsigned ResultReg = createResultReg(RC);
1865 Op0 = constrainOperandRegClass(II, Op0, II.
getNumDefs());
1866 Op1 = constrainOperandRegClass(II, Op1, II.
getNumDefs() + 1);
1867 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
1882 return new MipsFastISel(funcInfo, libInfo);
ReturnInst - Return a value (possibly void), from a function.
void push_back(const T &Elt)
The memory access reads data.
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
Type * getIndexedType() const
This class is the base class for the comparison instructions.
The memory access writes data.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
uint64_t getZExtValue() const
Get zero extended value.
LocInfo getLocInfo() const
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Intrinsic::ID getIntrinsicID() const
getIntrinsicID - Return the intrinsic ID of this intrinsic.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
unsigned getNumOperands() const
Describe properties that are true of each instruction in the target description file.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change...
0 1 0 0 True if ordered and less than
unsigned getSizeInBits() const
bool isDoubleTy() const
isDoubleTy - Return true if this is 'double', a 64-bit IEEE fp type.
1 1 1 0 True if unordered or not equal
MemSetInst - This class wraps the llvm.memset intrinsic.
Type * getReturnType() const
const Function * getParent() const
Return the enclosing method, or null if none.
void reserve(size_type N)
static std::error_code getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
unsigned getValNo() const
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
static MachinePointerInfo getFixedStack(int FI, int64_t offset=0)
getFixedStack - Return a MachinePointerInfo record that refers to the the specified FrameIndex...
COPY - Target-independent register copy.
bool isVector() const
isVector - Return true if this is a vector value type.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
MachineMemOperand - A description of a memory reference used in the backend.
SelectInst - This class represents the LLVM 'select' instruction.
const HexagonInstrInfo * TII
StructType - Class to represent struct types.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
A Use represents the edge between a Value definition and its users.
bool hasInternalLinkage() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
unsigned getNumArgOperands() const
getNumArgOperands - Return the number of call arguments.
static SDValue emitCmp(SelectionDAG &DAG, SDLoc DL, Comparison &C)
Reg
All possible values of the reg field in the ModR/M byte.
0 1 0 1 True if ordered and less than or equal
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
static bool CC_MipsO32_FP32(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
unsigned getStoreSize() const
getStoreSize - Return the number of bytes overwritten by a store of the specified value type...
const MachineInstrBuilder & addImm(int64_t Val) const
addImm - Add a new immediate operand.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
unsigned getLocReg() const
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
ConstantExpr - a constant value that is initialized with an expression using other constant values...
void GetReturnInfo(Type *ReturnType, AttributeSet attr, SmallVectorImpl< ISD::OutputArg > &Outs, const TargetLowering &TLI, const DataLayout &DL)
Given an LLVM IR type and return type attributes, compute the return value EVTs and flags...
BasicBlock * getSuccessor(unsigned i) const
unsigned getKillRegState(bool B)
Flag
These should be considered private to the implementation of the MCInstrDesc class.
TargetInstrInfo - Interface to description of machine instruction set.
uint64_t getElementOffset(unsigned Idx) const
bool isInteger() const
isInteger - Return true if this is an integer, or a vector integer type.
MVT - Machine Value Type.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
BranchInst - Conditional or Unconditional Branch instruction.
bool isVectorTy() const
isVectorTy - True if this is an instance of VectorType.
This is an important base class in LLVM.
PointerType * getType() const
getType - Overload to return most specific pointer type
bool isVector() const
isVector - Return true if this is a vector value type.
const Value * getCondition() const
bool isFloatTy() const
isFloatTy - Return true if this is 'float', a 32-bit IEEE fp type.
APInt Or(const APInt &LHS, const APInt &RHS)
Bitwise OR function for APInt.
ConstantFP - Floating Point Values [float, double].
APInt Xor(const APInt &LHS, const APInt &RHS)
Bitwise XOR function for APInt.
#define LLVM_ATTRIBUTE_UNUSED
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Value * getOperand(unsigned i) const
Predicate getPredicate() const
Return the predicate for this instruction.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
BuildMI - Builder interface.
EVT - Extended Value Type.
LLVMContext & getContext() const
All values hold a context through their type.
static bool isAtomic(Instruction *I)
const Value * getTrueValue() const
0 0 1 0 True if ordered and greater than
CCState - This class holds information needed while lowering arguments and return values...
This is the shared class of boolean and integer constants.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Type * getType() const
All values are typed, get the type of this value.
Provides information about what library functions are available for the current target.
static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, ArrayRef< MCPhysReg > F64Regs)
CCValAssign - Represent assignment of one arg/retval to a location.
Value * getLength() const
unsigned fastEmitInst_rr(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill)
Emit a MachineInstr with two register operands and a result register in the given register class...
Function * getCalledFunction() const
getCalledFunction - Return the function called, or null if this is an indirect function invocation...
const MachineInstrBuilder & addFrameIndex(int Idx) const
static MachinePointerInfo getStack(int64_t Offset)
getStack - stack pointer relative access.
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(NoStrictAlign), cl::values(clEnumValN(StrictAlign,"aarch64-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"aarch64-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
static bool CC_Mips(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State) LLVM_ATTRIBUTE_UNUSED
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
AttributeSet getAttributes() const
Return the attribute list for this Function.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
bool isIntegerTy() const
isIntegerTy - True if this is an instance of IntegerType.
This file defines the FastISel class.
APInt bitcastToAPInt() const
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
APInt And(const APInt &LHS, const APInt &RHS)
Bitwise AND function for APInt.
Value * getCondition() const
Bitwise operators - logical and, logical or, logical xor.
unsigned greater or equal
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Fast - This calling convention attempts to make calls as fast as possible (e.g.
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
iterator find(const KeyT &Val)
MipsFunctionInfo - This class is derived from MachineFunction private Mips target-specific informatio...
bool isInt< 16 >(int64_t x)
bool hasLocalLinkage() const
const APFloat & getValueAPF() const
bool isUnsigned() const
Determine if this instruction is using an unsigned comparison.
const ARM::ArchExtKind Kind
bool isSimple() const
isSimple - Test if the given EVT is simple (as opposed to being extended).
0 0 0 1 True if ordered and equal
LLVM Value Representation.
unsigned getOpcode() const
getOpcode() returns a member of one of the enums like Instruction::Add.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0) const
bool isUInt< 16 >(uint64_t x)
Primary interface to the complete machine description for the target machine.
const Value * getFalseValue() const
unsigned getLocMemOffset() const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
0 0 1 1 True if ordered and greater than or equal
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
addReg - Add a new virtual register operand...
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
const BasicBlock * getParent() const
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
void convertToReg(unsigned RegNo)
MVT getSimpleVT() const
getSimpleVT - Return the SimpleValueType held in the specified simple EVT.
IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic functions.
AllocaInst - an instruction to allocate memory on the stack.
gep_type_iterator gep_type_begin(const User *GEP)
void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.