57#include "llvm/IR/IntrinsicsAArch64.h"
81class AArch64FastISel final :
public FastISel {
84 using BaseKind =
enum {
90 BaseKind Kind = RegBase;
99 const GlobalValue *GV =
nullptr;
104 void setKind(BaseKind K) { Kind =
K; }
105 BaseKind getKind()
const {
return Kind; }
108 bool isRegBase()
const {
return Kind == RegBase; }
109 bool isFIBase()
const {
return Kind == FrameIndexBase; }
112 assert(isRegBase() &&
"Invalid base register access!");
117 assert(isRegBase() &&
"Invalid base register access!");
123 Register getOffsetReg()
const {
return OffsetReg; }
125 void setFI(
unsigned FI) {
126 assert(isFIBase() &&
"Invalid base frame index access!");
130 unsigned getFI()
const {
131 assert(isFIBase() &&
"Invalid base frame index access!");
135 void setOffset(int64_t O) { Offset =
O; }
137 void setShift(
unsigned S) { Shift = S; }
138 unsigned getShift() {
return Shift; }
140 void setGlobalValue(
const GlobalValue *
G) { GV =
G; }
141 const GlobalValue *getGlobalValue() {
return GV; }
146 const AArch64Subtarget *Subtarget;
147 LLVMContext *Context;
149 bool fastLowerArguments()
override;
150 bool fastLowerCall(CallLoweringInfo &CLI)
override;
151 bool fastLowerIntrinsicCall(
const IntrinsicInst *
II)
override;
155 bool selectAddSub(
const Instruction *
I);
156 bool selectLogicalOp(
const Instruction *
I);
157 bool selectLoad(
const Instruction *
I);
158 bool selectStore(
const Instruction *
I);
159 bool selectBranch(
const Instruction *
I);
160 bool selectIndirectBr(
const Instruction *
I);
161 bool selectCmp(
const Instruction *
I);
162 bool selectSelect(
const Instruction *
I);
163 bool selectFPExt(
const Instruction *
I);
164 bool selectFPTrunc(
const Instruction *
I);
165 bool selectFPToInt(
const Instruction *
I,
bool Signed);
166 bool selectIntToFP(
const Instruction *
I,
bool Signed);
167 bool selectRem(
const Instruction *
I,
unsigned ISDOpcode);
168 bool selectRet(
const Instruction *
I);
169 bool selectTrunc(
const Instruction *
I);
170 bool selectIntExt(
const Instruction *
I);
171 bool selectMul(
const Instruction *
I);
172 bool selectShift(
const Instruction *
I);
173 bool selectBitCast(
const Instruction *
I);
174 bool selectFRem(
const Instruction *
I);
175 bool selectSDiv(
const Instruction *
I);
176 bool selectGetElementPtr(
const Instruction *
I);
177 bool selectAtomicCmpXchg(
const AtomicCmpXchgInst *
I);
180 bool isTypeLegal(
Type *Ty, MVT &VT);
181 bool isTypeSupported(
Type *Ty, MVT &VT,
bool IsVectorAllowed =
false);
182 bool isValueAvailable(
const Value *V)
const;
183 bool computeAddress(
const Value *Obj, Address &Addr,
Type *Ty =
nullptr);
184 bool computeCallAddress(
const Value *V, Address &Addr);
185 bool simplifyAddress(Address &Addr, MVT VT);
186 void addLoadStoreOperands(Address &Addr,
const MachineInstrBuilder &MIB,
188 unsigned ScaleFactor, MachineMemOperand *MMO);
189 bool isMemCpySmall(uint64_t Len, MaybeAlign Alignment);
190 bool tryEmitSmallMemCpy(Address Dest, Address Src, uint64_t Len,
191 MaybeAlign Alignment);
194 bool optimizeIntExtLoad(
const Instruction *
I, MVT RetVT, MVT SrcVT);
195 bool optimizeSelect(
const SelectInst *SI);
200 const Value *
RHS,
bool SetFlags =
false,
201 bool WantResult =
true,
bool IsZExt =
false);
203 Register RHSReg,
bool SetFlags =
false,
204 bool WantResult =
true);
205 Register emitAddSub_ri(
bool UseAdd, MVT RetVT,
Register LHSReg, uint64_t Imm,
206 bool SetFlags =
false,
bool WantResult =
true);
209 uint64_t ShiftImm,
bool SetFlags =
false,
210 bool WantResult =
true);
213 uint64_t ShiftImm,
bool SetFlags =
false,
214 bool WantResult =
true);
217 bool emitCompareAndBranch(
const BranchInst *BI);
220 bool emitICmp_ri(MVT RetVT,
Register LHSReg, uint64_t Imm);
223 MachineMemOperand *MMO =
nullptr);
225 MachineMemOperand *MMO =
nullptr);
227 MachineMemOperand *MMO =
nullptr);
231 bool SetFlags =
false,
bool WantResult =
true,
232 bool IsZExt =
false);
235 bool SetFlags =
false,
bool WantResult =
true,
236 bool IsZExt =
false);
238 bool WantResult =
true);
241 bool WantResult =
true);
247 Register RHSReg, uint64_t ShiftImm);
260 bool IsZExt =
false);
262 Register materializeInt(
const ConstantInt *CI, MVT VT);
263 Register materializeFP(
const ConstantFP *CFP, MVT VT);
264 Register materializeGV(
const GlobalValue *GV);
268 CCAssignFn *CCAssignFnForCall(CallingConv::ID CC)
const;
269 bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs,
270 SmallVectorImpl<Type *> &OrigTys,
unsigned &NumBytes);
271 bool finishCall(CallLoweringInfo &CLI,
unsigned NumBytes);
275 Register fastMaterializeAlloca(
const AllocaInst *AI)
override;
276 Register fastMaterializeConstant(
const Constant *
C)
override;
277 Register fastMaterializeFloatZero(
const ConstantFP *CF)
override;
279 explicit AArch64FastISel(FunctionLoweringInfo &FuncInfo,
280 const TargetLibraryInfo *LibInfo)
281 : FastISel(FuncInfo, LibInfo,
true) {
286 bool fastSelectInstruction(
const Instruction *
I)
override;
288#include "AArch64GenFastISel.inc"
296 "Unexpected integer extend instruction.");
297 assert(!
I->getType()->isVectorTy() &&
I->getType()->isIntegerTy() &&
298 "Unexpected value type.");
306 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr()))
333 if (CC == CallingConv::GHC)
335 if (CC == CallingConv::CFGuard_Check)
344Register AArch64FastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
346 "Alloca should always return a pointer.");
349 auto SI = FuncInfo.StaticAllocaMap.find(AI);
350 if (SI == FuncInfo.StaticAllocaMap.end())
353 if (SI != FuncInfo.StaticAllocaMap.end()) {
354 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
355 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
366Register AArch64FastISel::materializeInt(
const ConstantInt *CI, MVT VT) {
374 const TargetRegisterClass *RC = (VT == MVT::i64) ? &AArch64::GPR64RegClass
375 : &AArch64::GPR32RegClass;
376 unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
377 Register ResultReg = createResultReg(RC);
378 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
383Register AArch64FastISel::materializeFP(
const ConstantFP *CFP, MVT VT) {
387 return fastMaterializeFloatZero(CFP);
389 if (VT != MVT::f32 && VT != MVT::f64)
393 bool Is64Bit = (VT == MVT::f64);
399 unsigned Opc = Is64Bit ? AArch64::FMOVDi : AArch64::FMOVSi;
400 return fastEmitInst_i(
Opc, TLI.getRegClassFor(VT), Imm);
405 unsigned Opc1 = Is64Bit ? AArch64::MOVi64imm : AArch64::MOVi32imm;
406 const TargetRegisterClass *RC = Is64Bit ?
407 &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
409 Register TmpReg = createResultReg(RC);
410 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc1), TmpReg)
411 .addImm(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
413 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
414 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
415 TII.get(TargetOpcode::COPY), ResultReg)
416 .addReg(TmpReg, getKillRegState(true));
423 Align Alignment =
DL.getPrefTypeAlign(CFP->
getType());
425 unsigned CPI = MCP.getConstantPoolIndex(
cast<Constant>(CFP), Alignment);
426 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
427 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
430 unsigned Opc = Is64Bit ? AArch64::LDRDui : AArch64::LDRSui;
431 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
432 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
438Register AArch64FastISel::materializeGV(
const GlobalValue *GV) {
448 if (FuncInfo.MF->getInfo<AArch64FunctionInfo>()->hasELFSignedGOT())
453 EVT DestEVT = TLI.getValueType(
DL, GV->
getType(),
true);
457 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
462 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
468 ResultReg = createResultReg(&AArch64::GPR32RegClass);
469 LdrOpc = AArch64::LDRWui;
471 ResultReg = createResultReg(&AArch64::GPR64RegClass);
472 LdrOpc = AArch64::LDRXui;
474 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(LdrOpc),
484 Register Result64 = createResultReg(&AArch64::GPR64RegClass);
485 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
486 TII.get(TargetOpcode::SUBREG_TO_REG))
494 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
512 Register DstReg = createResultReg(&AArch64::GPR64commonRegClass);
513 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::MOVKXi),
522 ResultReg = createResultReg(&AArch64::GPR64spRegClass);
523 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
533Register AArch64FastISel::fastMaterializeConstant(
const Constant *
C) {
534 EVT CEVT = TLI.getValueType(
DL,
C->getType(),
true);
543 assert(VT == MVT::i64 &&
"Expected 64-bit pointers");
544 return materializeInt(ConstantInt::get(Type::getInt64Ty(*
Context), 0), VT);
548 return materializeInt(CI, VT);
550 return materializeFP(CFP, VT);
552 return materializeGV(GV);
557Register AArch64FastISel::fastMaterializeFloatZero(
const ConstantFP *CFP) {
559 "Floating-point constant is not a positive zero.");
561 if (!isTypeLegal(CFP->
getType(), VT))
564 if (VT != MVT::f32 && VT != MVT::f64)
567 bool Is64Bit = (VT == MVT::f64);
568 unsigned ZReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
569 unsigned Opc = Is64Bit ? AArch64::FMOVXDr : AArch64::FMOVWSr;
570 return fastEmitInst_r(
Opc, TLI.getRegClassFor(VT), ZReg);
577 if (
C->getValue().isPowerOf2())
580 if (
C->getValue().isPowerOf2())
587bool AArch64FastISel::computeAddress(
const Value *Obj,
Address &Addr,
Type *Ty)
589 const User *
U =
nullptr;
590 unsigned Opcode = Instruction::UserOp1;
594 if (FuncInfo.StaticAllocaMap.count(
static_cast<const AllocaInst *
>(Obj)) ||
595 FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
596 Opcode =
I->getOpcode();
600 Opcode =
C->getOpcode();
605 if (Ty->getAddressSpace() > 255)
613 case Instruction::BitCast:
615 return computeAddress(
U->getOperand(0), Addr, Ty);
617 case Instruction::IntToPtr:
619 if (TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
620 TLI.getPointerTy(
DL))
621 return computeAddress(
U->getOperand(0), Addr, Ty);
624 case Instruction::PtrToInt:
626 if (TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
627 return computeAddress(
U->getOperand(0), Addr, Ty);
630 case Instruction::GetElementPtr: {
632 uint64_t TmpOffset = Addr.getOffset();
638 const Value *
Op = GTI.getOperand();
639 if (StructType *STy = GTI.getStructTypeOrNull()) {
640 const StructLayout *SL =
DL.getStructLayout(STy);
644 uint64_t S = GTI.getSequentialElementStride(
DL);
651 if (canFoldAddIntoGEP(U,
Op)) {
661 goto unsupported_gep;
667 Addr.setOffset(TmpOffset);
668 if (computeAddress(
U->getOperand(0), Addr, Ty))
677 case Instruction::Alloca: {
679 DenseMap<const AllocaInst *, int>::iterator
SI =
680 FuncInfo.StaticAllocaMap.find(AI);
681 if (SI != FuncInfo.StaticAllocaMap.end()) {
682 Addr.setKind(Address::FrameIndexBase);
683 Addr.setFI(
SI->second);
688 case Instruction::Add: {
698 return computeAddress(
LHS, Addr, Ty);
702 if (computeAddress(
LHS, Addr, Ty) && computeAddress(
RHS, Addr, Ty))
708 case Instruction::Sub: {
715 return computeAddress(
LHS, Addr, Ty);
719 case Instruction::Shl: {
720 if (Addr.getOffsetReg())
728 if (Val < 1 || Val > 3)
731 uint64_t NumBytes = 0;
733 uint64_t NumBits =
DL.getTypeSizeInBits(Ty);
734 NumBytes = NumBits / 8;
739 if (NumBytes != (1ULL << Val))
745 const Value *Src =
U->getOperand(0);
747 if (FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
751 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
753 Src = ZE->getOperand(0);
757 SE->getOperand(0)->getType()->isIntegerTy(32)) {
759 Src = SE->getOperand(0);
766 if (AI->
getOpcode() == Instruction::And) {
771 if (
C->getValue() == 0xffffffff)
775 if (
C->getValue() == 0xffffffff) {
780 Reg = fastEmitInst_extractsubreg(MVT::i32,
Reg, AArch64::sub_32);
781 Addr.setOffsetReg(
Reg);
789 Addr.setOffsetReg(
Reg);
792 case Instruction::Mul: {
793 if (Addr.getOffsetReg())
804 if (
C->getValue().isPowerOf2())
809 unsigned Val =
C->getValue().logBase2();
810 if (Val < 1 || Val > 3)
813 uint64_t NumBytes = 0;
815 uint64_t NumBits =
DL.getTypeSizeInBits(Ty);
816 NumBytes = NumBits / 8;
821 if (NumBytes != (1ULL << Val))
829 if (FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
833 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
835 Src = ZE->getOperand(0);
839 SE->getOperand(0)->getType()->isIntegerTy(32)) {
841 Src = SE->getOperand(0);
850 Addr.setOffsetReg(
Reg);
853 case Instruction::And: {
854 if (Addr.getOffsetReg())
857 if (!Ty ||
DL.getTypeSizeInBits(Ty) != 8)
864 if (
C->getValue() == 0xffffffff)
868 if (
C->getValue() == 0xffffffff) {
876 Reg = fastEmitInst_extractsubreg(MVT::i32,
Reg, AArch64::sub_32);
877 Addr.setOffsetReg(
Reg);
882 case Instruction::SExt:
883 case Instruction::ZExt: {
884 if (!Addr.getReg() || Addr.getOffsetReg())
887 const Value *Src =
nullptr;
890 if (!
isIntExtFree(ZE) && ZE->getOperand(0)->getType()->isIntegerTy(32)) {
892 Src = ZE->getOperand(0);
895 if (!
isIntExtFree(SE) && SE->getOperand(0)->getType()->isIntegerTy(32)) {
897 Src = SE->getOperand(0);
908 Addr.setOffsetReg(
Reg);
913 if (Addr.isRegBase() && !Addr.getReg()) {
921 if (!Addr.getOffsetReg()) {
925 Addr.setOffsetReg(
Reg);
932bool AArch64FastISel::computeCallAddress(
const Value *V,
Address &Addr) {
933 const User *
U =
nullptr;
934 unsigned Opcode = Instruction::UserOp1;
938 Opcode =
I->getOpcode();
940 InMBB =
I->getParent() == FuncInfo.MBB->getBasicBlock();
942 Opcode =
C->getOpcode();
948 case Instruction::BitCast:
951 return computeCallAddress(
U->getOperand(0), Addr);
953 case Instruction::IntToPtr:
956 TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
957 TLI.getPointerTy(
DL))
958 return computeCallAddress(
U->getOperand(0), Addr);
960 case Instruction::PtrToInt:
962 if (InMBB && TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
963 return computeCallAddress(
U->getOperand(0), Addr);
968 Addr.setGlobalValue(GV);
973 if (!Addr.getGlobalValue()) {
974 Addr.setReg(getRegForValue(V));
975 return Addr.getReg().isValid();
981bool AArch64FastISel::isTypeLegal(
Type *Ty, MVT &VT) {
982 EVT evt = TLI.getValueType(
DL, Ty,
true);
988 if (evt == MVT::Other || !evt.
isSimple())
998 return TLI.isTypeLegal(VT);
1005bool AArch64FastISel::isTypeSupported(
Type *Ty, MVT &VT,
bool IsVectorAllowed) {
1009 if (isTypeLegal(Ty, VT))
1014 if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)
1020bool AArch64FastISel::isValueAvailable(
const Value *V)
const {
1025 return FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB;
1028bool AArch64FastISel::simplifyAddress(
Address &Addr, MVT VT) {
1036 bool ImmediateOffsetNeedsLowering =
false;
1037 bool RegisterOffsetNeedsLowering =
false;
1038 int64_t
Offset = Addr.getOffset();
1040 ImmediateOffsetNeedsLowering =
true;
1041 else if (
Offset > 0 && !(
Offset & (ScaleFactor - 1)) &&
1043 ImmediateOffsetNeedsLowering =
true;
1048 if (!ImmediateOffsetNeedsLowering && Addr.getOffset() && Addr.getOffsetReg())
1049 RegisterOffsetNeedsLowering =
true;
1052 if (Addr.isRegBase() && Addr.getOffsetReg() && !Addr.getReg())
1053 RegisterOffsetNeedsLowering =
true;
1058 if ((ImmediateOffsetNeedsLowering || Addr.getOffsetReg()) && Addr.isFIBase())
1060 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
1061 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
1066 Addr.setKind(Address::RegBase);
1067 Addr.setReg(ResultReg);
1070 if (RegisterOffsetNeedsLowering) {
1072 if (Addr.getReg()) {
1075 ResultReg = emitAddSub_rx(
true, MVT::i64, Addr.getReg(),
1076 Addr.getOffsetReg(), Addr.getExtendType(),
1079 ResultReg = emitAddSub_rs(
true, MVT::i64, Addr.getReg(),
1084 ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1085 Addr.getShift(),
true);
1087 ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1088 Addr.getShift(),
false);
1090 ResultReg = emitLSL_ri(MVT::i64, MVT::i64, Addr.getOffsetReg(),
1096 Addr.setReg(ResultReg);
1097 Addr.setOffsetReg(0);
1104 if (ImmediateOffsetNeedsLowering) {
1108 ResultReg = emitAdd_ri_(MVT::i64, Addr.getReg(),
Offset);
1114 Addr.setReg(ResultReg);
1120void AArch64FastISel::addLoadStoreOperands(
Address &Addr,
1121 const MachineInstrBuilder &MIB,
1123 unsigned ScaleFactor,
1124 MachineMemOperand *MMO) {
1125 int64_t
Offset = Addr.getOffset() / ScaleFactor;
1127 if (Addr.isFIBase()) {
1128 int FI = Addr.getFI();
1131 MMO = FuncInfo.MF->getMachineMemOperand(
1133 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
1137 assert(Addr.isRegBase() &&
"Unexpected address kind.");
1144 if (Addr.getOffsetReg()) {
1145 assert(Addr.getOffset() == 0 &&
"Unexpected offset");
1148 MIB.
addReg(Addr.getReg());
1149 MIB.
addReg(Addr.getOffsetReg());
1151 MIB.
addImm(Addr.getShift() != 0);
1160Register AArch64FastISel::emitAddSub(
bool UseAdd, MVT RetVT,
const Value *
LHS,
1162 bool WantResult,
bool IsZExt) {
1164 bool NeedExtend =
false;
1199 if (
SI->getOpcode() == Instruction::Shl ||
1200 SI->getOpcode() == Instruction::LShr ||
1201 SI->getOpcode() == Instruction::AShr )
1209 LHSReg = emitIntExt(SrcVT, LHSReg, RetVT, IsZExt);
1213 uint64_t
Imm = IsZExt ?
C->getZExtValue() :
C->getSExtValue();
1214 if (
C->isNegative())
1215 ResultReg = emitAddSub_ri(!UseAdd, RetVT, LHSReg, -Imm, SetFlags,
1218 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, Imm, SetFlags,
1221 if (
C->isNullValue())
1222 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, 0, SetFlags, WantResult);
1229 isValueAvailable(
RHS)) {
1233 return emitAddSub_rx(UseAdd, RetVT, LHSReg, RHSReg, ExtendType, 0,
1234 SetFlags, WantResult);
1244 if (
C->getValue().isPowerOf2())
1249 Register RHSReg = getRegForValue(MulLHS);
1252 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg,
AArch64_AM::LSL,
1253 ShiftVal, SetFlags, WantResult);
1264 switch (
SI->getOpcode()) {
1270 uint64_t ShiftVal =
C->getZExtValue();
1272 Register RHSReg = getRegForValue(
SI->getOperand(0));
1275 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg, ShiftType,
1276 ShiftVal, SetFlags, WantResult);
1289 RHSReg = emitIntExt(SrcVT, RHSReg, RetVT, IsZExt);
1291 return emitAddSub_rr(UseAdd, RetVT, LHSReg, RHSReg, SetFlags, WantResult);
1294Register AArch64FastISel::emitAddSub_rr(
bool UseAdd, MVT RetVT,
Register LHSReg,
1297 assert(LHSReg && RHSReg &&
"Invalid register number.");
1299 if (LHSReg == AArch64::SP || LHSReg == AArch64::WSP ||
1300 RHSReg == AArch64::SP || RHSReg == AArch64::WSP)
1303 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1306 static const unsigned OpcTable[2][2][2] = {
1307 { { AArch64::SUBWrr, AArch64::SUBXrr },
1308 { AArch64::ADDWrr, AArch64::ADDXrr } },
1309 { { AArch64::SUBSWrr, AArch64::SUBSXrr },
1310 { AArch64::ADDSWrr, AArch64::ADDSXrr } }
1312 bool Is64Bit = RetVT == MVT::i64;
1313 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1314 const TargetRegisterClass *RC =
1315 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1318 ResultReg = createResultReg(RC);
1320 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1322 const MCInstrDesc &
II =
TII.get(
Opc);
1325 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1331Register AArch64FastISel::emitAddSub_ri(
bool UseAdd, MVT RetVT,
Register LHSReg,
1332 uint64_t Imm,
bool SetFlags,
1334 assert(LHSReg &&
"Invalid register number.");
1336 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1342 else if ((Imm & 0xfff000) == Imm) {
1348 static const unsigned OpcTable[2][2][2] = {
1349 { { AArch64::SUBWri, AArch64::SUBXri },
1350 { AArch64::ADDWri, AArch64::ADDXri } },
1351 { { AArch64::SUBSWri, AArch64::SUBSXri },
1352 { AArch64::ADDSWri, AArch64::ADDSXri } }
1354 bool Is64Bit = RetVT == MVT::i64;
1355 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1356 const TargetRegisterClass *RC;
1358 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1360 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1363 ResultReg = createResultReg(RC);
1365 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1367 const MCInstrDesc &
II =
TII.get(
Opc);
1369 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1376Register AArch64FastISel::emitAddSub_rs(
bool UseAdd, MVT RetVT,
Register LHSReg,
1379 uint64_t ShiftImm,
bool SetFlags,
1381 assert(LHSReg && RHSReg &&
"Invalid register number.");
1382 assert(LHSReg != AArch64::SP && LHSReg != AArch64::WSP &&
1383 RHSReg != AArch64::SP && RHSReg != AArch64::WSP);
1385 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1392 static const unsigned OpcTable[2][2][2] = {
1393 { { AArch64::SUBWrs, AArch64::SUBXrs },
1394 { AArch64::ADDWrs, AArch64::ADDXrs } },
1395 { { AArch64::SUBSWrs, AArch64::SUBSXrs },
1396 { AArch64::ADDSWrs, AArch64::ADDSXrs } }
1398 bool Is64Bit = RetVT == MVT::i64;
1399 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1400 const TargetRegisterClass *RC =
1401 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1404 ResultReg = createResultReg(RC);
1406 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1408 const MCInstrDesc &
II =
TII.get(
Opc);
1411 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1414 .
addImm(getShifterImm(ShiftType, ShiftImm));
1418Register AArch64FastISel::emitAddSub_rx(
bool UseAdd, MVT RetVT,
Register LHSReg,
1421 uint64_t ShiftImm,
bool SetFlags,
1423 assert(LHSReg && RHSReg &&
"Invalid register number.");
1424 assert(LHSReg != AArch64::XZR && LHSReg != AArch64::WZR &&
1425 RHSReg != AArch64::XZR && RHSReg != AArch64::WZR);
1427 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1433 static const unsigned OpcTable[2][2][2] = {
1434 { { AArch64::SUBWrx, AArch64::SUBXrx },
1435 { AArch64::ADDWrx, AArch64::ADDXrx } },
1436 { { AArch64::SUBSWrx, AArch64::SUBSXrx },
1437 { AArch64::ADDSWrx, AArch64::ADDSXrx } }
1439 bool Is64Bit = RetVT == MVT::i64;
1440 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1441 const TargetRegisterClass *RC =
nullptr;
1443 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1445 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1448 ResultReg = createResultReg(RC);
1450 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1452 const MCInstrDesc &
II =
TII.get(
Opc);
1455 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1458 .
addImm(getArithExtendImm(ExtType, ShiftImm));
1462bool AArch64FastISel::emitCmp(
const Value *
LHS,
const Value *
RHS,
bool IsZExt) {
1464 EVT EVT = TLI.getValueType(
DL, Ty,
true);
1477 return emitICmp(VT,
LHS,
RHS, IsZExt);
1480 return emitFCmp(VT,
LHS,
RHS);
1484bool AArch64FastISel::emitICmp(MVT RetVT,
const Value *
LHS,
const Value *
RHS,
1486 return emitSub(RetVT,
LHS,
RHS,
true,
false,
1491bool AArch64FastISel::emitICmp_ri(MVT RetVT,
Register LHSReg, uint64_t Imm) {
1492 return emitAddSub_ri(
false, RetVT, LHSReg, Imm,
1497bool AArch64FastISel::emitFCmp(MVT RetVT,
const Value *
LHS,
const Value *
RHS) {
1498 if (RetVT != MVT::f32 && RetVT != MVT::f64)
1503 bool UseImm =
false;
1513 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDri : AArch64::FCMPSri;
1514 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1523 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDrr : AArch64::FCMPSrr;
1524 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1531 bool SetFlags,
bool WantResult,
bool IsZExt) {
1532 return emitAddSub(
true, RetVT,
LHS,
RHS, SetFlags, WantResult,
1544 ResultReg = emitAddSub_ri(
false, VT, Op0, -Imm);
1546 ResultReg = emitAddSub_ri(
true, VT, Op0, Imm);
1555 ResultReg = emitAddSub_rr(
true, VT, Op0, CReg);
1560 bool SetFlags,
bool WantResult,
bool IsZExt) {
1561 return emitAddSub(
false, RetVT,
LHS,
RHS, SetFlags, WantResult,
1566 Register RHSReg,
bool WantResult) {
1567 return emitAddSub_rr(
false, RetVT, LHSReg, RHSReg,
1574 uint64_t ShiftImm,
bool WantResult) {
1575 return emitAddSub_rs(
false, RetVT, LHSReg, RHSReg, ShiftType,
1576 ShiftImm,
true, WantResult);
1579Register AArch64FastISel::emitLogicalOp(
unsigned ISDOpc, MVT RetVT,
1602 uint64_t
Imm =
C->getZExtValue();
1603 ResultReg = emitLogicalOp_ri(ISDOpc, RetVT, LHSReg, Imm);
1615 if (
C->getValue().isPowerOf2())
1621 Register RHSReg = getRegForValue(MulLHS);
1624 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);
1634 uint64_t ShiftVal =
C->getZExtValue();
1635 Register RHSReg = getRegForValue(
SI->getOperand(0));
1638 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);
1648 MVT VT = std::max(MVT::i32, RetVT.
SimpleTy);
1649 ResultReg = fastEmit_rr(VT, VT, ISDOpc, LHSReg, RHSReg);
1650 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1651 uint64_t
Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1652 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1657Register AArch64FastISel::emitLogicalOp_ri(
unsigned ISDOpc, MVT RetVT,
1660 "ISD nodes are not consecutive!");
1661 static const unsigned OpcTable[3][2] = {
1662 { AArch64::ANDWri, AArch64::ANDXri },
1663 { AArch64::ORRWri, AArch64::ORRXri },
1664 { AArch64::EORWri, AArch64::EORXri }
1666 const TargetRegisterClass *RC;
1677 Opc = OpcTable[Idx][0];
1678 RC = &AArch64::GPR32spRegClass;
1684 RC = &AArch64::GPR64spRegClass;
1693 fastEmitInst_ri(
Opc, RC, LHSReg,
1695 if (RetVT >= MVT::i8 && RetVT <= MVT::i16 && ISDOpc !=
ISD::AND) {
1696 uint64_t
Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1697 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1702Register AArch64FastISel::emitLogicalOp_rs(
unsigned ISDOpc, MVT RetVT,
1704 uint64_t ShiftImm) {
1706 "ISD nodes are not consecutive!");
1707 static const unsigned OpcTable[3][2] = {
1708 { AArch64::ANDWrs, AArch64::ANDXrs },
1709 { AArch64::ORRWrs, AArch64::ORRXrs },
1710 { AArch64::EORWrs, AArch64::EORXrs }
1717 const TargetRegisterClass *RC;
1727 RC = &AArch64::GPR32RegClass;
1731 RC = &AArch64::GPR64RegClass;
1735 fastEmitInst_rri(
Opc, RC, LHSReg, RHSReg,
1737 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1738 uint64_t
Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1739 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1744Register AArch64FastISel::emitAnd_ri(MVT RetVT,
Register LHSReg, uint64_t Imm) {
1745 return emitLogicalOp_ri(
ISD::AND, RetVT, LHSReg, Imm);
1749 bool WantZExt, MachineMemOperand *MMO) {
1750 if (!TLI.allowsMisalignedMemoryAccesses(VT))
1754 if (!simplifyAddress(Addr, VT))
1763 bool UseScaled =
true;
1764 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
1769 static const unsigned GPOpcTable[2][8][4] = {
1771 { { AArch64::LDURSBWi, AArch64::LDURSHWi, AArch64::LDURWi,
1773 { AArch64::LDURSBXi, AArch64::LDURSHXi, AArch64::LDURSWi,
1775 { AArch64::LDRSBWui, AArch64::LDRSHWui, AArch64::LDRWui,
1777 { AArch64::LDRSBXui, AArch64::LDRSHXui, AArch64::LDRSWui,
1779 { AArch64::LDRSBWroX, AArch64::LDRSHWroX, AArch64::LDRWroX,
1781 { AArch64::LDRSBXroX, AArch64::LDRSHXroX, AArch64::LDRSWroX,
1783 { AArch64::LDRSBWroW, AArch64::LDRSHWroW, AArch64::LDRWroW,
1785 { AArch64::LDRSBXroW, AArch64::LDRSHXroW, AArch64::LDRSWroW,
1789 { { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1791 { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1793 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1795 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1797 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1799 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1801 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1803 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1808 static const unsigned FPOpcTable[4][2] = {
1809 { AArch64::LDURSi, AArch64::LDURDi },
1810 { AArch64::LDRSui, AArch64::LDRDui },
1811 { AArch64::LDRSroX, AArch64::LDRDroX },
1812 { AArch64::LDRSroW, AArch64::LDRDroW }
1816 const TargetRegisterClass *RC;
1817 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
1818 Addr.getOffsetReg();
1819 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
1824 bool IsRet64Bit = RetVT == MVT::i64;
1830 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][0];
1831 RC = (IsRet64Bit && !WantZExt) ?
1832 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1835 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][1];
1836 RC = (IsRet64Bit && !WantZExt) ?
1837 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1840 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][2];
1841 RC = (IsRet64Bit && !WantZExt) ?
1842 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1845 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][3];
1846 RC = &AArch64::GPR64RegClass;
1849 Opc = FPOpcTable[Idx][0];
1850 RC = &AArch64::FPR32RegClass;
1853 Opc = FPOpcTable[Idx][1];
1854 RC = &AArch64::FPR64RegClass;
1859 Register ResultReg = createResultReg(RC);
1860 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1861 TII.get(
Opc), ResultReg);
1865 if (VT == MVT::i1) {
1866 Register ANDReg = emitAnd_ri(MVT::i32, ResultReg, 1);
1867 assert(ANDReg &&
"Unexpected AND instruction emission failure.");
1873 if (WantZExt && RetVT == MVT::i64 && VT <= MVT::i32) {
1874 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
1875 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1876 TII.get(AArch64::SUBREG_TO_REG), Reg64)
1879 .
addImm(AArch64::sub_32);
1885bool AArch64FastISel::selectAddSub(
const Instruction *
I) {
1887 if (!isTypeSupported(
I->getType(), VT,
true))
1891 return selectOperator(
I,
I->getOpcode());
1894 switch (
I->getOpcode()) {
1897 case Instruction::Add:
1898 ResultReg = emitAdd(VT,
I->getOperand(0),
I->getOperand(1));
1900 case Instruction::Sub:
1901 ResultReg = emitSub(VT,
I->getOperand(0),
I->getOperand(1));
1907 updateValueMap(
I, ResultReg);
1911bool AArch64FastISel::selectLogicalOp(
const Instruction *
I) {
1913 if (!isTypeSupported(
I->getType(), VT,
true))
1917 return selectOperator(
I,
I->getOpcode());
1920 switch (
I->getOpcode()) {
1923 case Instruction::And:
1924 ResultReg = emitLogicalOp(
ISD::AND, VT,
I->getOperand(0),
I->getOperand(1));
1926 case Instruction::Or:
1927 ResultReg = emitLogicalOp(
ISD::OR, VT,
I->getOperand(0),
I->getOperand(1));
1929 case Instruction::Xor:
1930 ResultReg = emitLogicalOp(
ISD::XOR, VT,
I->getOperand(0),
I->getOperand(1));
1936 updateValueMap(
I, ResultReg);
1940bool AArch64FastISel::selectLoad(
const Instruction *
I) {
1945 if (!isTypeSupported(
I->getType(), VT,
true) ||
1949 const Value *SV =
I->getOperand(0);
1950 if (TLI.supportSwiftError()) {
1954 if (Arg->hasSwiftErrorAttr())
1959 if (Alloca->isSwiftError())
1966 if (!computeAddress(
I->getOperand(0), Addr,
I->getType()))
1970 bool WantZExt =
true;
1972 const Value *IntExtVal =
nullptr;
1973 if (
I->hasOneUse()) {
1975 if (isTypeSupported(ZE->getType(), RetVT))
1980 if (isTypeSupported(SE->getType(), RetVT))
1989 emitLoad(VT, RetVT, Addr, WantZExt, createMachineMemOperandFor(
I));
2010 auto *
MI =
MRI.getUniqueVRegDef(
Reg);
2012 if (RetVT == MVT::i64 && VT <= MVT::i32) {
2016 ResultReg = std::prev(
I)->getOperand(0).getReg();
2017 removeDeadCode(
I, std::next(
I));
2019 ResultReg = fastEmitInst_extractsubreg(MVT::i32, ResultReg,
2022 updateValueMap(
I, ResultReg);
2031 for (
auto &Opnd :
MI->uses()) {
2033 Reg = Opnd.getReg();
2038 removeDeadCode(
I, std::next(
I));
2043 updateValueMap(IntExtVal, ResultReg);
2047 updateValueMap(
I, ResultReg);
2051bool AArch64FastISel::emitStoreRelease(MVT VT,
Register SrcReg,
2053 MachineMemOperand *MMO) {
2056 default:
return false;
2057 case MVT::i8:
Opc = AArch64::STLRB;
break;
2058 case MVT::i16:
Opc = AArch64::STLRH;
break;
2059 case MVT::i32:
Opc = AArch64::STLRW;
break;
2060 case MVT::i64:
Opc = AArch64::STLRX;
break;
2063 const MCInstrDesc &
II =
TII.get(
Opc);
2066 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2074 MachineMemOperand *MMO) {
2075 if (!TLI.allowsMisalignedMemoryAccesses(VT))
2079 if (!simplifyAddress(Addr, VT))
2088 bool UseScaled =
true;
2089 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
2094 static const unsigned OpcTable[4][6] = {
2095 { AArch64::STURBBi, AArch64::STURHHi, AArch64::STURWi, AArch64::STURXi,
2096 AArch64::STURSi, AArch64::STURDi },
2097 { AArch64::STRBBui, AArch64::STRHHui, AArch64::STRWui, AArch64::STRXui,
2098 AArch64::STRSui, AArch64::STRDui },
2099 { AArch64::STRBBroX, AArch64::STRHHroX, AArch64::STRWroX, AArch64::STRXroX,
2100 AArch64::STRSroX, AArch64::STRDroX },
2101 { AArch64::STRBBroW, AArch64::STRHHroW, AArch64::STRWroW, AArch64::STRXroW,
2102 AArch64::STRSroW, AArch64::STRDroW }
2106 bool VTIsi1 =
false;
2107 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
2108 Addr.getOffsetReg();
2109 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
2116 case MVT::i1: VTIsi1 =
true; [[fallthrough]];
2117 case MVT::i8:
Opc = OpcTable[Idx][0];
break;
2118 case MVT::i16:
Opc = OpcTable[Idx][1];
break;
2119 case MVT::i32:
Opc = OpcTable[Idx][2];
break;
2120 case MVT::i64:
Opc = OpcTable[Idx][3];
break;
2121 case MVT::f32:
Opc = OpcTable[Idx][4];
break;
2122 case MVT::f64:
Opc = OpcTable[Idx][5];
break;
2126 if (VTIsi1 && SrcReg != AArch64::WZR) {
2127 Register ANDReg = emitAnd_ri(MVT::i32, SrcReg, 1);
2128 assert(ANDReg &&
"Unexpected AND instruction emission failure.");
2132 const MCInstrDesc &
II =
TII.get(
Opc);
2134 MachineInstrBuilder MIB =
2141bool AArch64FastISel::selectStore(
const Instruction *
I) {
2143 const Value *Op0 =
I->getOperand(0);
2147 if (!isTypeSupported(Op0->
getType(), VT,
true))
2150 const Value *PtrV =
I->getOperand(1);
2151 if (TLI.supportSwiftError()) {
2155 if (Arg->hasSwiftErrorAttr())
2160 if (Alloca->isSwiftError())
2170 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2172 if (CF->isZero() && !CF->isNegative()) {
2174 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2179 SrcReg = getRegForValue(Op0);
2187 if (
SI->isAtomic()) {
2192 Register AddrReg = getRegForValue(PtrV);
2195 return emitStoreRelease(VT, SrcReg, AddrReg,
2196 createMachineMemOperandFor(
I));
2202 if (!computeAddress(PtrV, Addr, Op0->
getType()))
2205 if (!
emitStore(VT, SrcReg, Addr, createMachineMemOperandFor(
I)))
2257bool AArch64FastISel::emitCompareAndBranch(
const BranchInst *BI) {
2261 if (FuncInfo.MF->getFunction().hasFnAttribute(
2262 Attribute::SpeculativeLoadHardening))
2281 MachineBasicBlock *FBB = FuncInfo.getMBB(BI->
getSuccessor(1));
2284 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2291 switch (Predicate) {
2303 if (AI->
getOpcode() == Instruction::And && isValueAvailable(AI)) {
2308 if (
C->getValue().isPowerOf2())
2312 if (
C->getValue().isPowerOf2()) {
2313 TestBit =
C->getValue().logBase2();
2344 static const unsigned OpcTable[2][2][2] = {
2345 { {AArch64::CBZW, AArch64::CBZX },
2346 {AArch64::CBNZW, AArch64::CBNZX} },
2347 { {AArch64::TBZW, AArch64::TBZX },
2348 {AArch64::TBNZW, AArch64::TBNZX} }
2351 bool IsBitTest = TestBit != -1;
2352 bool Is64Bit = BW == 64;
2353 if (TestBit < 32 && TestBit >= 0)
2356 unsigned Opc = OpcTable[IsBitTest][IsCmpNE][Is64Bit];
2357 const MCInstrDesc &
II =
TII.get(
Opc);
2363 if (BW == 64 && !Is64Bit)
2364 SrcReg = fastEmitInst_extractsubreg(MVT::i32, SrcReg, AArch64::sub_32);
2366 if ((BW < 32) && !IsBitTest)
2367 SrcReg = emitIntExt(VT, SrcReg, MVT::i32,
true);
2371 MachineInstrBuilder MIB =
2372 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
2382bool AArch64FastISel::selectBranch(
const Instruction *
I) {
2385 MachineBasicBlock *MSucc = FuncInfo.getMBB(BI->
getSuccessor(0));
2391 MachineBasicBlock *FBB = FuncInfo.getMBB(BI->
getSuccessor(1));
2394 if (CI->
hasOneUse() && isValueAvailable(CI)) {
2397 switch (Predicate) {
2401 fastEmitBranch(FBB, MIMD.getDL());
2404 fastEmitBranch(
TBB, MIMD.getDL());
2409 if (emitCompareAndBranch(BI))
2413 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2426 switch (Predicate) {
2442 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2448 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2456 uint64_t
Imm = CI->getZExtValue();
2458 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::B))
2463 auto BranchProbability = FuncInfo.BPI->getEdgeProbability(
2465 FuncInfo.MBB->addSuccessor(Target, BranchProbability);
2467 FuncInfo.MBB->addSuccessorWithoutProb(Target);
2479 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2493 unsigned Opcode = AArch64::TBNZW;
2494 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2496 Opcode = AArch64::TBZW;
2499 const MCInstrDesc &
II =
TII.get(Opcode);
2502 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2503 .
addReg(ConstrainedCondReg)
2511bool AArch64FastISel::selectIndirectBr(
const Instruction *
I) {
2518 if (FuncInfo.MF->getFunction().hasFnAttribute(
"ptrauth-indirect-gotos"))
2522 const MCInstrDesc &
II =
TII.get(AArch64::BR);
2528 FuncInfo.MBB->addSuccessor(FuncInfo.getMBB(Succ));
2533bool AArch64FastISel::selectCmp(
const Instruction *
I) {
2543 switch (Predicate) {
2547 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2548 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2549 TII.get(TargetOpcode::COPY), ResultReg)
2553 ResultReg = fastEmit_i(MVT::i32, MVT::i32,
ISD::Constant, 1);
2558 updateValueMap(
I, ResultReg);
2566 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2570 static unsigned CondCodeTable[2][2] = {
2575 switch (Predicate) {
2587 Register TmpReg1 = createResultReg(&AArch64::GPR32RegClass);
2588 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2593 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2599 updateValueMap(
I, ResultReg);
2607 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2613 updateValueMap(
I, ResultReg);
2619bool AArch64FastISel::optimizeSelect(
const SelectInst *SI) {
2620 if (!
SI->getType()->isIntegerTy(1))
2623 const Value *Src1Val, *Src2Val;
2625 bool NeedExtraOp =
false;
2628 Src1Val =
SI->getCondition();
2629 Src2Val =
SI->getFalseValue();
2630 Opc = AArch64::ORRWrr;
2633 Src1Val =
SI->getFalseValue();
2634 Src2Val =
SI->getCondition();
2635 Opc = AArch64::BICWrr;
2639 Src1Val =
SI->getCondition();
2640 Src2Val =
SI->getTrueValue();
2641 Opc = AArch64::ORRWrr;
2645 Src1Val =
SI->getCondition();
2646 Src2Val =
SI->getTrueValue();
2647 Opc = AArch64::ANDWrr;
2654 Register Src1Reg = getRegForValue(Src1Val);
2658 Register Src2Reg = getRegForValue(Src2Val);
2663 Src1Reg = emitLogicalOp_ri(
ISD::XOR, MVT::i32, Src1Reg, 1);
2665 Register ResultReg = fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, Src1Reg,
2667 updateValueMap(SI, ResultReg);
2671bool AArch64FastISel::selectSelect(
const Instruction *
I) {
2674 if (!isTypeSupported(
I->getType(), VT))
2678 const TargetRegisterClass *RC;
2686 Opc = AArch64::CSELWr;
2687 RC = &AArch64::GPR32RegClass;
2690 Opc = AArch64::CSELXr;
2691 RC = &AArch64::GPR64RegClass;
2694 Opc = AArch64::FCSELSrrr;
2695 RC = &AArch64::FPR32RegClass;
2698 Opc = AArch64::FCSELDrrr;
2699 RC = &AArch64::FPR64RegClass;
2708 if (optimizeSelect(SI))
2712 if (foldXALUIntrinsic(CC,
I,
Cond)) {
2718 isValueAvailable(
Cond)) {
2722 const Value *FoldSelect =
nullptr;
2723 switch (Predicate) {
2727 FoldSelect =
SI->getFalseValue();
2730 FoldSelect =
SI->getTrueValue();
2735 Register SrcReg = getRegForValue(FoldSelect);
2739 updateValueMap(
I, SrcReg);
2749 switch (Predicate) {
2767 const MCInstrDesc &
II =
TII.get(AArch64::ANDSWri);
2771 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II,
2777 Register Src1Reg = getRegForValue(
SI->getTrueValue());
2778 Register Src2Reg = getRegForValue(
SI->getFalseValue());
2780 if (!Src1Reg || !Src2Reg)
2784 Src2Reg = fastEmitInst_rri(
Opc, RC, Src1Reg, Src2Reg, ExtraCC);
2786 Register ResultReg = fastEmitInst_rri(
Opc, RC, Src1Reg, Src2Reg, CC);
2787 updateValueMap(
I, ResultReg);
2791bool AArch64FastISel::selectFPExt(
const Instruction *
I) {
2793 if (!
I->getType()->isDoubleTy() || !
V->getType()->isFloatTy())
2800 Register ResultReg = createResultReg(&AArch64::FPR64RegClass);
2801 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTDSr),
2803 updateValueMap(
I, ResultReg);
2807bool AArch64FastISel::selectFPTrunc(
const Instruction *
I) {
2809 if (!
I->getType()->isFloatTy() || !
V->getType()->isDoubleTy())
2816 Register ResultReg = createResultReg(&AArch64::FPR32RegClass);
2817 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTSDr),
2819 updateValueMap(
I, ResultReg);
2824bool AArch64FastISel::selectFPToInt(
const Instruction *
I,
bool Signed) {
2826 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2829 Register SrcReg = getRegForValue(
I->getOperand(0));
2833 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2834 if (SrcVT == MVT::f128 || SrcVT == MVT::f16 || SrcVT == MVT::bf16)
2838 if (SrcVT == MVT::f64) {
2840 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWDr : AArch64::FCVTZSUXDr;
2842 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWDr : AArch64::FCVTZUUXDr;
2845 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWSr : AArch64::FCVTZSUXSr;
2847 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWSr : AArch64::FCVTZUUXSr;
2849 Register ResultReg = createResultReg(
2850 DestVT == MVT::i32 ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass);
2851 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
2853 updateValueMap(
I, ResultReg);
2857bool AArch64FastISel::selectIntToFP(
const Instruction *
I,
bool Signed) {
2859 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2862 if (DestVT == MVT::f16 || DestVT == MVT::bf16)
2865 assert((DestVT == MVT::f32 || DestVT == MVT::f64) &&
2866 "Unexpected value type.");
2868 Register SrcReg = getRegForValue(
I->getOperand(0));
2872 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2875 if (SrcVT == MVT::i16 || SrcVT == MVT::i8 || SrcVT == MVT::i1) {
2883 if (SrcVT == MVT::i64) {
2885 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUXSri : AArch64::SCVTFUXDri;
2887 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUXSri : AArch64::UCVTFUXDri;
2890 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUWSri : AArch64::SCVTFUWDri;
2892 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUWSri : AArch64::UCVTFUWDri;
2895 Register ResultReg = fastEmitInst_r(
Opc, TLI.getRegClassFor(DestVT), SrcReg);
2896 updateValueMap(
I, ResultReg);
2900bool AArch64FastISel::fastLowerArguments() {
2901 if (!FuncInfo.CanLowerReturn)
2908 CallingConv::ID CC =
F->getCallingConv();
2909 if (CC != CallingConv::C && CC != CallingConv::Swift)
2916 unsigned GPRCnt = 0;
2917 unsigned FPRCnt = 0;
2918 for (
auto const &Arg :
F->args()) {
2919 if (Arg.hasAttribute(Attribute::ByVal) ||
2920 Arg.hasAttribute(Attribute::InReg) ||
2921 Arg.hasAttribute(Attribute::StructRet) ||
2922 Arg.hasAttribute(Attribute::SwiftSelf) ||
2923 Arg.hasAttribute(Attribute::SwiftAsync) ||
2924 Arg.hasAttribute(Attribute::SwiftError) ||
2925 Arg.hasAttribute(Attribute::Nest))
2928 Type *ArgTy = Arg.getType();
2932 EVT ArgVT = TLI.getValueType(
DL, ArgTy);
2944 if (VT >= MVT::i1 && VT <= MVT::i64)
2946 else if ((VT >= MVT::f16 && VT <= MVT::f64) || VT.
is64BitVector() ||
2952 if (GPRCnt > 8 || FPRCnt > 8)
2957 { AArch64::W0, AArch64::W1, AArch64::W2, AArch64::W3, AArch64::W4,
2958 AArch64::W5, AArch64::W6, AArch64::W7 },
2959 { AArch64::X0, AArch64::X1, AArch64::X2, AArch64::X3, AArch64::X4,
2960 AArch64::X5, AArch64::X6, AArch64::X7 },
2961 { AArch64::H0, AArch64::H1, AArch64::H2, AArch64::H3, AArch64::H4,
2962 AArch64::H5, AArch64::H6, AArch64::H7 },
2963 { AArch64::S0, AArch64::S1, AArch64::S2, AArch64::S3, AArch64::S4,
2964 AArch64::S5, AArch64::S6, AArch64::S7 },
2965 { AArch64::D0, AArch64::D1, AArch64::D2, AArch64::D3, AArch64::D4,
2966 AArch64::D5, AArch64::D6, AArch64::D7 },
2967 { AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,
2968 AArch64::Q5, AArch64::Q6, AArch64::Q7 }
2972 unsigned FPRIdx = 0;
2973 for (
auto const &Arg :
F->args()) {
2974 MVT VT = TLI.getSimpleValueType(
DL, Arg.getType());
2976 const TargetRegisterClass *RC;
2977 if (VT >= MVT::i1 && VT <= MVT::i32) {
2979 RC = &AArch64::GPR32RegClass;
2981 }
else if (VT == MVT::i64) {
2983 RC = &AArch64::GPR64RegClass;
2984 }
else if (VT == MVT::f16 || VT == MVT::bf16) {
2986 RC = &AArch64::FPR16RegClass;
2987 }
else if (VT == MVT::f32) {
2989 RC = &AArch64::FPR32RegClass;
2992 RC = &AArch64::FPR64RegClass;
2995 RC = &AArch64::FPR128RegClass;
2999 Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
3003 Register ResultReg = createResultReg(RC);
3004 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3005 TII.get(TargetOpcode::COPY), ResultReg)
3007 updateValueMap(&Arg, ResultReg);
3012bool AArch64FastISel::processCallArgs(CallLoweringInfo &CLI,
3013 SmallVectorImpl<MVT> &OutVTs,
3014 SmallVectorImpl<Type *> &OrigTys,
3015 unsigned &NumBytes) {
3016 CallingConv::ID CC = CLI.CallConv;
3018 CCState CCInfo(CC,
false, *FuncInfo.MF, ArgLocs, *
Context);
3019 CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, OrigTys,
3020 CCAssignFnForCall(CC));
3023 NumBytes = CCInfo.getStackSize();
3026 unsigned AdjStackDown =
TII.getCallFrameSetupOpcode();
3027 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackDown))
3031 for (CCValAssign &VA : ArgLocs) {
3032 const Value *ArgVal = CLI.OutVals[VA.getValNo()];
3033 MVT ArgVT = OutVTs[VA.getValNo()];
3035 Register ArgReg = getRegForValue(ArgVal);
3040 switch (VA.getLocInfo()) {
3044 MVT DestVT = VA.getLocVT();
3046 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
false);
3054 MVT DestVT = VA.getLocVT();
3056 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
true);
3066 if (VA.isRegLoc() && !VA.needsCustom()) {
3067 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3068 TII.get(TargetOpcode::COPY), VA.getLocReg()).
addReg(ArgReg);
3069 CLI.OutRegs.push_back(VA.getLocReg());
3070 }
else if (VA.needsCustom()) {
3074 assert(VA.isMemLoc() &&
"Assuming store on stack.");
3083 unsigned BEAlign = 0;
3084 if (ArgSize < 8 && !Subtarget->isLittleEndian())
3085 BEAlign = 8 - ArgSize;
3088 Addr.setKind(Address::RegBase);
3089 Addr.setReg(AArch64::SP);
3090 Addr.setOffset(VA.getLocMemOffset() + BEAlign);
3093 MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
3097 if (!
emitStore(ArgVT, ArgReg, Addr, MMO))
3104bool AArch64FastISel::finishCall(CallLoweringInfo &CLI,
unsigned NumBytes) {
3105 CallingConv::ID CC = CLI.CallConv;
3108 unsigned AdjStackUp =
TII.getCallFrameDestroyOpcode();
3109 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackUp))
3114 CCState CCInfo(CC,
false, *FuncInfo.MF, RVLocs, *
Context);
3115 CCInfo.AnalyzeCallResult(CLI.Ins, CCAssignFnForCall(CC));
3117 Register ResultReg = FuncInfo.CreateRegs(CLI.RetTy);
3118 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
3119 CCValAssign &VA = RVLocs[i];
3128 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
3134 CLI.ResultReg = ResultReg;
3135 CLI.NumResultRegs = RVLocs.
size();
3140bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
3141 CallingConv::ID CC = CLI.CallConv;
3142 bool IsTailCall = CLI.IsTailCall;
3143 bool IsVarArg = CLI.IsVarArg;
3147 if (!Callee && !Symbol)
3152 if (CLI.CB && CLI.CB->hasFnAttr(Attribute::ReturnsTwice) &&
3153 !Subtarget->noBTIAtReturnTwice() &&
3154 MF->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement())
3158 if (CLI.CB && CLI.CB->isIndirectCall() &&
3182 if (MF->getFunction().getParent()->getRtLibUseGOT())
3192 for (
auto Flag : CLI.OutFlags)
3194 Flag.isSwiftSelf() ||
Flag.isSwiftAsync() ||
Flag.isSwiftError())
3200 OutVTs.
reserve(CLI.OutVals.size());
3202 for (
auto *Val : CLI.OutVals) {
3204 if (!isTypeLegal(Val->getType(), VT) &&
3205 !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16))
3217 if (Callee && !computeCallAddress(Callee, Addr))
3224 Addr.getGlobalValue()->hasExternalWeakLinkage())
3229 if (!processCallArgs(CLI, OutVTs, OrigTys, NumBytes))
3237 MachineInstrBuilder MIB;
3239 const MCInstrDesc &
II =
3241 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II);
3244 else if (Addr.getGlobalValue())
3246 else if (Addr.getReg()) {
3254 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
3255 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
3259 CallReg = createResultReg(&AArch64::GPR64RegClass);
3260 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3261 TII.get(AArch64::LDRXui), CallReg)
3265 }
else if (Addr.getGlobalValue())
3266 CallReg = materializeGV(Addr.getGlobalValue());
3267 else if (Addr.getReg())
3268 CallReg = Addr.getReg();
3275 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II).
addReg(CallReg);
3279 for (
auto Reg : CLI.OutRegs)
3289 return finishCall(CLI, NumBytes);
3292bool AArch64FastISel::isMemCpySmall(uint64_t Len, MaybeAlign Alignment) {
3294 return Len / Alignment->value() <= 4;
3299bool AArch64FastISel::tryEmitSmallMemCpy(
Address Dest,
Address Src,
3300 uint64_t Len, MaybeAlign Alignment) {
3302 if (!isMemCpySmall(Len, Alignment))
3305 int64_t UnscaledOffset = 0;
3311 if (!Alignment || *Alignment >= 8) {
3322 assert(Alignment &&
"Alignment is set in this branch");
3324 if (Len >= 4 && *Alignment == 4)
3326 else if (Len >= 2 && *Alignment == 2)
3342 UnscaledOffset +=
Size;
3345 Dest.setOffset(OrigDest.getOffset() + UnscaledOffset);
3346 Src.setOffset(OrigSrc.getOffset() + UnscaledOffset);
3355 const Instruction *
I,
3369 if (!isTypeLegal(RetTy, RetVT))
3372 if (RetVT != MVT::i32 && RetVT != MVT::i64)
3387 case Intrinsic::smul_with_overflow:
3389 if (
C->getValue() == 2)
3390 IID = Intrinsic::sadd_with_overflow;
3392 case Intrinsic::umul_with_overflow:
3394 if (
C->getValue() == 2)
3395 IID = Intrinsic::uadd_with_overflow;
3403 case Intrinsic::sadd_with_overflow:
3404 case Intrinsic::ssub_with_overflow:
3407 case Intrinsic::uadd_with_overflow:
3410 case Intrinsic::usub_with_overflow:
3413 case Intrinsic::smul_with_overflow:
3414 case Intrinsic::umul_with_overflow:
3420 if (!isValueAvailable(
II))
3426 for (
auto Itr = std::prev(Start); Itr != End; --Itr) {
3434 if (EVI->getAggregateOperand() !=
II)
3442bool AArch64FastISel::fastLowerIntrinsicCall(
const IntrinsicInst *
II) {
3444 switch (
II->getIntrinsicID()) {
3445 default:
return false;
3446 case Intrinsic::frameaddress: {
3447 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3452 Register SrcReg =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3453 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3463 DestReg = fastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,
3465 assert(DestReg &&
"Unexpected LDR instruction emission failure.");
3469 updateValueMap(
II, SrcReg);
3472 case Intrinsic::sponentry: {
3473 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3477 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
3478 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3479 TII.get(AArch64::ADDXri), ResultReg)
3484 updateValueMap(
II, ResultReg);
3487 case Intrinsic::memcpy:
3488 case Intrinsic::memmove: {
3491 if (MTI->isVolatile())
3496 bool IsMemCpy = (
II->getIntrinsicID() == Intrinsic::memcpy);
3501 MaybeAlign Alignment;
3502 if (MTI->getDestAlign() || MTI->getSourceAlign())
3503 Alignment = std::min(MTI->getDestAlign().valueOrOne(),
3504 MTI->getSourceAlign().valueOrOne());
3505 if (isMemCpySmall(Len, Alignment)) {
3507 if (!computeAddress(MTI->getRawDest(), Dest) ||
3508 !computeAddress(MTI->getRawSource(), Src))
3510 if (tryEmitSmallMemCpy(Dest, Src, Len, Alignment))
3515 if (!MTI->getLength()->getType()->isIntegerTy(64))
3518 if (MTI->getSourceAddressSpace() > 255 || MTI->getDestAddressSpace() > 255)
3524 return lowerCallTo(
II, IntrMemName,
II->arg_size() - 1);
3526 case Intrinsic::memset: {
3540 return lowerCallTo(
II,
"memset",
II->arg_size() - 1);
3542 case Intrinsic::sin:
3543 case Intrinsic::cos:
3544 case Intrinsic::tan:
3545 case Intrinsic::pow: {
3547 if (!isTypeLegal(
II->getType(), RetVT))
3550 if (RetVT != MVT::f32 && RetVT != MVT::f64)
3553 static const RTLIB::Libcall LibCallTable[4][2] = {
3554 {RTLIB::SIN_F32, RTLIB::SIN_F64},
3555 {RTLIB::COS_F32, RTLIB::COS_F64},
3556 {RTLIB::TAN_F32, RTLIB::TAN_F64},
3557 {RTLIB::POW_F32, RTLIB::POW_F64}};
3559 bool Is64Bit = RetVT == MVT::f64;
3560 switch (
II->getIntrinsicID()) {
3563 case Intrinsic::sin:
3564 LC = LibCallTable[0][Is64Bit];
3566 case Intrinsic::cos:
3567 LC = LibCallTable[1][Is64Bit];
3569 case Intrinsic::tan:
3570 LC = LibCallTable[2][Is64Bit];
3572 case Intrinsic::pow:
3573 LC = LibCallTable[3][Is64Bit];
3578 Args.reserve(
II->arg_size());
3581 for (
auto &Arg :
II->args())
3582 Args.emplace_back(Arg);
3584 CallLoweringInfo CLI;
3585 MCContext &Ctx = MF->getContext();
3586 CLI.setCallee(
DL, Ctx, TLI.getLibcallCallingConv(LC),
II->getType(),
3587 TLI.getLibcallName(LC), std::move(Args));
3588 if (!lowerCallTo(CLI))
3590 updateValueMap(
II, CLI.ResultReg);
3593 case Intrinsic::fabs: {
3595 if (!isTypeLegal(
II->getType(), VT))
3603 Opc = AArch64::FABSSr;
3606 Opc = AArch64::FABSDr;
3609 Register SrcReg = getRegForValue(
II->getOperand(0));
3612 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3613 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
3615 updateValueMap(
II, ResultReg);
3618 case Intrinsic::trap:
3619 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3622 case Intrinsic::debugtrap:
3623 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3627 case Intrinsic::sqrt: {
3628 Type *RetTy =
II->getCalledFunction()->getReturnType();
3631 if (!isTypeLegal(RetTy, VT))
3634 Register Op0Reg = getRegForValue(
II->getOperand(0));
3638 Register ResultReg = fastEmit_r(VT, VT, ISD::FSQRT, Op0Reg);
3642 updateValueMap(
II, ResultReg);
3645 case Intrinsic::sadd_with_overflow:
3646 case Intrinsic::uadd_with_overflow:
3647 case Intrinsic::ssub_with_overflow:
3648 case Intrinsic::usub_with_overflow:
3649 case Intrinsic::smul_with_overflow:
3650 case Intrinsic::umul_with_overflow: {
3654 Type *RetTy = Ty->getTypeAtIndex(0U);
3657 if (!isTypeLegal(RetTy, VT))
3660 if (VT != MVT::i32 && VT != MVT::i64)
3674 case Intrinsic::smul_with_overflow:
3676 if (
C->getValue() == 2) {
3677 IID = Intrinsic::sadd_with_overflow;
3681 case Intrinsic::umul_with_overflow:
3683 if (
C->getValue() == 2) {
3684 IID = Intrinsic::uadd_with_overflow;
3690 Register ResultReg1, ResultReg2, MulReg;
3694 case Intrinsic::sadd_with_overflow:
3695 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3698 case Intrinsic::uadd_with_overflow:
3699 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3702 case Intrinsic::ssub_with_overflow:
3703 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3706 case Intrinsic::usub_with_overflow:
3707 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3710 case Intrinsic::smul_with_overflow: {
3720 if (VT == MVT::i32) {
3721 MulReg = emitSMULL_rr(MVT::i64, LHSReg, RHSReg);
3723 fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3725 emitAddSub_rx(
false, MVT::i64, MulReg, MulSubReg,
3730 assert(VT == MVT::i64 &&
"Unexpected value type.");
3733 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3740 case Intrinsic::umul_with_overflow: {
3750 if (VT == MVT::i32) {
3751 MulReg = emitUMULL_rr(MVT::i64, LHSReg, RHSReg);
3753 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3754 TII.get(AArch64::ANDSXri), AArch64::XZR)
3757 MulReg = fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3759 assert(VT == MVT::i64 &&
"Unexpected value type.");
3762 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3764 emitSubs_rr(VT, AArch64::XZR, UMULHReg,
false);
3771 ResultReg1 = createResultReg(TLI.getRegClassFor(VT));
3772 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3773 TII.get(TargetOpcode::COPY), ResultReg1).
addReg(MulReg);
3779 ResultReg2 = fastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,
3780 AArch64::WZR, AArch64::WZR,
3781 getInvertedCondCode(CC));
3783 assert((ResultReg1 + 1) == ResultReg2 &&
3784 "Nonconsecutive result registers.");
3785 updateValueMap(
II, ResultReg1, 2);
3788 case Intrinsic::aarch64_crc32b:
3789 case Intrinsic::aarch64_crc32h:
3790 case Intrinsic::aarch64_crc32w:
3791 case Intrinsic::aarch64_crc32x:
3792 case Intrinsic::aarch64_crc32cb:
3793 case Intrinsic::aarch64_crc32ch:
3794 case Intrinsic::aarch64_crc32cw:
3795 case Intrinsic::aarch64_crc32cx: {
3796 if (!Subtarget->hasCRC())
3800 switch (
II->getIntrinsicID()) {
3803 case Intrinsic::aarch64_crc32b:
3804 Opc = AArch64::CRC32Brr;
3806 case Intrinsic::aarch64_crc32h:
3807 Opc = AArch64::CRC32Hrr;
3809 case Intrinsic::aarch64_crc32w:
3810 Opc = AArch64::CRC32Wrr;
3812 case Intrinsic::aarch64_crc32x:
3813 Opc = AArch64::CRC32Xrr;
3815 case Intrinsic::aarch64_crc32cb:
3816 Opc = AArch64::CRC32CBrr;
3818 case Intrinsic::aarch64_crc32ch:
3819 Opc = AArch64::CRC32CHrr;
3821 case Intrinsic::aarch64_crc32cw:
3822 Opc = AArch64::CRC32CWrr;
3824 case Intrinsic::aarch64_crc32cx:
3825 Opc = AArch64::CRC32CXrr;
3829 Register LHSReg = getRegForValue(
II->getArgOperand(0));
3830 Register RHSReg = getRegForValue(
II->getArgOperand(1));
3831 if (!LHSReg || !RHSReg)
3835 fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, LHSReg, RHSReg);
3836 updateValueMap(
II, ResultReg);
3843bool AArch64FastISel::selectRet(
const Instruction *
I) {
3845 const Function &
F = *
I->getParent()->getParent();
3847 if (!FuncInfo.CanLowerReturn)
3853 if (TLI.supportSwiftError() &&
3854 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
3857 if (TLI.supportSplitCSR(FuncInfo.MF))
3863 if (
Ret->getNumOperands() > 0) {
3864 CallingConv::ID CC =
F.getCallingConv();
3870 CCState CCInfo(CC,
F.isVarArg(), *FuncInfo.MF, ValLocs,
I->getContext());
3874 if (ValLocs.
size() != 1)
3877 CCValAssign &VA = ValLocs[0];
3878 const Value *RV =
Ret->getOperand(0);
3896 if (!
MRI.getRegClass(SrcReg)->contains(DestReg))
3899 EVT RVEVT = TLI.getValueType(
DL, RV->
getType());
3909 if (RVVT == MVT::f128)
3914 if (RVVT != DestVT) {
3915 if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
3918 if (!Outs[0].
Flags.isZExt() && !Outs[0].Flags.isSExt())
3921 bool IsZExt = Outs[0].Flags.isZExt();
3922 SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
3930 SrcReg = emitAnd_ri(MVT::i64, SrcReg, 0xffffffff);
3933 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3934 TII.get(TargetOpcode::COPY), DestReg).
addReg(SrcReg);
3940 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3941 TII.get(AArch64::RET_ReallyLR));
3947bool AArch64FastISel::selectTrunc(
const Instruction *
I) {
3948 Type *DestTy =
I->getType();
3950 Type *SrcTy =
Op->getType();
3952 EVT SrcEVT = TLI.getValueType(
DL, SrcTy,
true);
3953 EVT DestEVT = TLI.getValueType(
DL, DestTy,
true);
3962 if (SrcVT != MVT::i64 && SrcVT != MVT::i32 && SrcVT != MVT::i16 &&
3965 if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8 &&
3979 if (SrcVT == MVT::i64) {
3996 Register Reg32 = fastEmitInst_extractsubreg(MVT::i32, SrcReg,
3999 ResultReg = emitAnd_ri(MVT::i32, Reg32, Mask);
4000 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4002 ResultReg = createResultReg(&AArch64::GPR32RegClass);
4003 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4004 TII.get(TargetOpcode::COPY), ResultReg)
4008 updateValueMap(
I, ResultReg);
4012Register AArch64FastISel::emiti1Ext(
Register SrcReg, MVT DestVT,
bool IsZExt) {
4013 assert((DestVT == MVT::i8 || DestVT == MVT::i16 || DestVT == MVT::i32 ||
4014 DestVT == MVT::i64) &&
4015 "Unexpected value type.");
4017 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4021 Register ResultReg = emitAnd_ri(MVT::i32, SrcReg, 1);
4022 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4023 if (DestVT == MVT::i64) {
4026 Register Reg64 =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4027 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4028 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4031 .
addImm(AArch64::sub_32);
4036 if (DestVT == MVT::i64) {
4040 return fastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,
4055 Opc = AArch64::MADDWrrr; ZReg = AArch64::WZR;
break;
4057 Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR;
break;
4060 const TargetRegisterClass *RC =
4061 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4062 return fastEmitInst_rrr(
Opc, RC, Op0, Op1, ZReg);
4066 if (RetVT != MVT::i64)
4069 return fastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,
4070 Op0, Op1, AArch64::XZR);
4074 if (RetVT != MVT::i64)
4077 return fastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,
4078 Op0, Op1, AArch64::XZR);
4084 bool NeedTrunc =
false;
4089 case MVT::i8:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4090 case MVT::i16:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4091 case MVT::i32:
Opc = AArch64::LSLVWr;
break;
4092 case MVT::i64:
Opc = AArch64::LSLVXr;
break;
4095 const TargetRegisterClass *RC =
4096 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4098 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4100 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4102 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4107 uint64_t Shift,
bool IsZExt) {
4109 "Unexpected source/return type pair.");
4110 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4111 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4112 "Unexpected source value type.");
4113 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4114 RetVT == MVT::i64) &&
"Unexpected return value type.");
4116 bool Is64Bit = (RetVT == MVT::i64);
4117 unsigned RegSize = Is64Bit ? 64 : 32;
4120 const TargetRegisterClass *RC =
4121 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4125 if (RetVT == SrcVT) {
4126 Register ResultReg = createResultReg(RC);
4127 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4128 TII.get(TargetOpcode::COPY), ResultReg)
4132 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4136 if (Shift >= DstBits)
4164 unsigned ImmR =
RegSize - Shift;
4166 unsigned ImmS = std::min<unsigned>(SrcBits - 1, DstBits - 1 - Shift);
4167 static const unsigned OpcTable[2][2] = {
4168 {AArch64::SBFMWri, AArch64::SBFMXri},
4169 {AArch64::UBFMWri, AArch64::UBFMXri}
4171 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4172 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4174 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4175 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4178 .
addImm(AArch64::sub_32);
4181 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4187 bool NeedTrunc =
false;
4192 case MVT::i8:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4193 case MVT::i16:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4194 case MVT::i32:
Opc = AArch64::LSRVWr;
break;
4195 case MVT::i64:
Opc = AArch64::LSRVXr;
break;
4198 const TargetRegisterClass *RC =
4199 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4201 Op0Reg = emitAnd_ri(MVT::i32, Op0Reg, Mask);
4202 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4204 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4206 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4211 uint64_t Shift,
bool IsZExt) {
4213 "Unexpected source/return type pair.");
4214 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4215 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4216 "Unexpected source value type.");
4217 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4218 RetVT == MVT::i64) &&
"Unexpected return value type.");
4220 bool Is64Bit = (RetVT == MVT::i64);
4221 unsigned RegSize = Is64Bit ? 64 : 32;
4224 const TargetRegisterClass *RC =
4225 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4229 if (RetVT == SrcVT) {
4230 Register ResultReg = createResultReg(RC);
4231 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4232 TII.get(TargetOpcode::COPY), ResultReg)
4236 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4240 if (Shift >= DstBits)
4268 if (Shift >= SrcBits && IsZExt)
4269 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4274 Op0 = emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4282 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4283 unsigned ImmS = SrcBits - 1;
4284 static const unsigned OpcTable[2][2] = {
4285 {AArch64::SBFMWri, AArch64::SBFMXri},
4286 {AArch64::UBFMWri, AArch64::UBFMXri}
4288 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4289 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4291 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4292 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4295 .
addImm(AArch64::sub_32);
4298 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4304 bool NeedTrunc =
false;
4309 case MVT::i8:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4310 case MVT::i16:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4311 case MVT::i32:
Opc = AArch64::ASRVWr;
break;
4312 case MVT::i64:
Opc = AArch64::ASRVXr;
break;
4315 const TargetRegisterClass *RC =
4316 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4318 Op0Reg = emitIntExt(RetVT, Op0Reg, MVT::i32,
false);
4319 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4321 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4323 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4328 uint64_t Shift,
bool IsZExt) {
4330 "Unexpected source/return type pair.");
4331 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4332 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4333 "Unexpected source value type.");
4334 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4335 RetVT == MVT::i64) &&
"Unexpected return value type.");
4337 bool Is64Bit = (RetVT == MVT::i64);
4338 unsigned RegSize = Is64Bit ? 64 : 32;
4341 const TargetRegisterClass *RC =
4342 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4346 if (RetVT == SrcVT) {
4347 Register ResultReg = createResultReg(RC);
4348 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4349 TII.get(TargetOpcode::COPY), ResultReg)
4353 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4357 if (Shift >= DstBits)
4385 if (Shift >= SrcBits && IsZExt)
4386 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4388 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4389 unsigned ImmS = SrcBits - 1;
4390 static const unsigned OpcTable[2][2] = {
4391 {AArch64::SBFMWri, AArch64::SBFMXri},
4392 {AArch64::UBFMWri, AArch64::UBFMXri}
4394 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4395 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4397 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4398 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4401 .
addImm(AArch64::sub_32);
4404 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4407Register AArch64FastISel::emitIntExt(MVT SrcVT,
Register SrcReg, MVT DestVT,
4409 assert(DestVT != MVT::i1 &&
"ZeroExt/SignExt an i1?");
4415 if (((DestVT != MVT::i8) && (DestVT != MVT::i16) &&
4416 (DestVT != MVT::i32) && (DestVT != MVT::i64)) ||
4417 ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) &&
4418 (SrcVT != MVT::i16) && (SrcVT != MVT::i32)))
4428 return emiti1Ext(SrcReg, DestVT, IsZExt);
4430 if (DestVT == MVT::i64)
4431 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4433 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4437 if (DestVT == MVT::i64)
4438 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4440 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4444 assert(DestVT == MVT::i64 &&
"IntExt i32 to i32?!?");
4445 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4451 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4453 else if (DestVT == MVT::i64) {
4454 Register Src64 =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4455 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4456 TII.get(AArch64::SUBREG_TO_REG), Src64)
4459 .
addImm(AArch64::sub_32);
4463 const TargetRegisterClass *RC =
4464 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4465 return fastEmitInst_rii(
Opc, RC, SrcReg, 0, Imm);
4472 case AArch64::LDURBBi:
4473 case AArch64::LDURHHi:
4474 case AArch64::LDURWi:
4475 case AArch64::LDRBBui:
4476 case AArch64::LDRHHui:
4477 case AArch64::LDRWui:
4478 case AArch64::LDRBBroX:
4479 case AArch64::LDRHHroX:
4480 case AArch64::LDRWroX:
4481 case AArch64::LDRBBroW:
4482 case AArch64::LDRHHroW:
4483 case AArch64::LDRWroW:
4492 case AArch64::LDURSBWi:
4493 case AArch64::LDURSHWi:
4494 case AArch64::LDURSBXi:
4495 case AArch64::LDURSHXi:
4496 case AArch64::LDURSWi:
4497 case AArch64::LDRSBWui:
4498 case AArch64::LDRSHWui:
4499 case AArch64::LDRSBXui:
4500 case AArch64::LDRSHXui:
4501 case AArch64::LDRSWui:
4502 case AArch64::LDRSBWroX:
4503 case AArch64::LDRSHWroX:
4504 case AArch64::LDRSBXroX:
4505 case AArch64::LDRSHXroX:
4506 case AArch64::LDRSWroX:
4507 case AArch64::LDRSBWroW:
4508 case AArch64::LDRSHWroW:
4509 case AArch64::LDRSBXroW:
4510 case AArch64::LDRSHXroW:
4511 case AArch64::LDRSWroW:
4516bool AArch64FastISel::optimizeIntExtLoad(
const Instruction *
I, MVT RetVT,
4519 if (!LI || !LI->hasOneUse())
4527 MachineInstr *
MI =
MRI.getUniqueVRegDef(
Reg);
4534 const auto *LoadMI =
MI;
4535 if (LoadMI->getOpcode() == TargetOpcode::COPY &&
4536 LoadMI->getOperand(1).getSubReg() == AArch64::sub_32) {
4537 Register LoadReg =
MI->getOperand(1).getReg();
4538 LoadMI =
MRI.getUniqueVRegDef(LoadReg);
4539 assert(LoadMI &&
"Expected valid instruction");
4545 if (RetVT != MVT::i64 || SrcVT > MVT::i32) {
4546 updateValueMap(
I,
Reg);
4551 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
4552 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4553 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4556 .
addImm(AArch64::sub_32);
4559 assert((
MI->getOpcode() == TargetOpcode::COPY &&
4560 MI->getOperand(1).getSubReg() == AArch64::sub_32) &&
4561 "Expected copy instruction");
4562 Reg =
MI->getOperand(1).getReg();
4564 removeDeadCode(
I, std::next(
I));
4566 updateValueMap(
I,
Reg);
4570bool AArch64FastISel::selectIntExt(
const Instruction *
I) {
4572 "Unexpected integer extend instruction.");
4575 if (!isTypeSupported(
I->getType(), RetVT))
4578 if (!isTypeSupported(
I->getOperand(0)->getType(), SrcVT))
4582 if (optimizeIntExtLoad(
I, RetVT, SrcVT))
4585 Register SrcReg = getRegForValue(
I->getOperand(0));
4592 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr())) {
4593 if (RetVT == MVT::i64 && SrcVT != MVT::i64) {
4594 Register ResultReg = createResultReg(&AArch64::GPR64RegClass);
4595 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4596 TII.get(AArch64::SUBREG_TO_REG), ResultReg)
4599 .
addImm(AArch64::sub_32);
4603 updateValueMap(
I, SrcReg);
4608 Register ResultReg = emitIntExt(SrcVT, SrcReg, RetVT, IsZExt);
4612 updateValueMap(
I, ResultReg);
4616bool AArch64FastISel::selectRem(
const Instruction *
I,
unsigned ISDOpcode) {
4617 EVT DestEVT = TLI.getValueType(
DL,
I->getType(),
true);
4622 if (DestVT != MVT::i64 && DestVT != MVT::i32)
4626 bool Is64bit = (DestVT == MVT::i64);
4627 switch (ISDOpcode) {
4631 DivOpc = Is64bit ? AArch64::SDIVXr : AArch64::SDIVWr;
4634 DivOpc = Is64bit ? AArch64::UDIVXr : AArch64::UDIVWr;
4637 unsigned MSubOpc = Is64bit ? AArch64::MSUBXrrr : AArch64::MSUBWrrr;
4638 Register Src0Reg = getRegForValue(
I->getOperand(0));
4642 Register Src1Reg = getRegForValue(
I->getOperand(1));
4646 const TargetRegisterClass *RC =
4647 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4648 Register QuotReg = fastEmitInst_rr(DivOpc, RC, Src0Reg, Src1Reg);
4649 assert(QuotReg &&
"Unexpected DIV instruction emission failure.");
4652 Register ResultReg = fastEmitInst_rrr(MSubOpc, RC, QuotReg, Src1Reg, Src0Reg);
4653 updateValueMap(
I, ResultReg);
4657bool AArch64FastISel::selectMul(
const Instruction *
I) {
4659 if (!isTypeSupported(
I->getType(), VT,
true))
4665 const Value *Src0 =
I->getOperand(0);
4666 const Value *Src1 =
I->getOperand(1);
4668 if (
C->getValue().isPowerOf2())
4673 if (
C->getValue().isPowerOf2()) {
4674 uint64_t ShiftVal =
C->getValue().logBase2();
4680 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), VT)) {
4683 Src0 = ZExt->getOperand(0);
4689 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), VT)) {
4692 Src0 = SExt->getOperand(0);
4697 Register Src0Reg = getRegForValue(Src0);
4701 Register ResultReg = emitLSL_ri(VT, SrcVT, Src0Reg, ShiftVal, IsZExt);
4704 updateValueMap(
I, ResultReg);
4709 Register Src0Reg = getRegForValue(
I->getOperand(0));
4713 Register Src1Reg = getRegForValue(
I->getOperand(1));
4717 Register ResultReg = emitMul_rr(VT, Src0Reg, Src1Reg);
4722 updateValueMap(
I, ResultReg);
4726bool AArch64FastISel::selectShift(
const Instruction *
I) {
4728 if (!isTypeSupported(
I->getType(), RetVT,
true))
4732 return selectOperator(
I,
I->getOpcode());
4736 uint64_t ShiftVal =
C->getZExtValue();
4738 bool IsZExt =
I->getOpcode() != Instruction::AShr;
4739 const Value *Op0 =
I->getOperand(0);
4743 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), TmpVT)) {
4746 Op0 = ZExt->getOperand(0);
4752 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), TmpVT)) {
4755 Op0 = SExt->getOperand(0);
4760 Register Op0Reg = getRegForValue(Op0);
4764 switch (
I->getOpcode()) {
4766 case Instruction::Shl:
4767 ResultReg = emitLSL_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4769 case Instruction::AShr:
4770 ResultReg = emitASR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4772 case Instruction::LShr:
4773 ResultReg = emitLSR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4779 updateValueMap(
I, ResultReg);
4783 Register Op0Reg = getRegForValue(
I->getOperand(0));
4787 Register Op1Reg = getRegForValue(
I->getOperand(1));
4792 switch (
I->getOpcode()) {
4794 case Instruction::Shl:
4795 ResultReg = emitLSL_rr(RetVT, Op0Reg, Op1Reg);
4797 case Instruction::AShr:
4798 ResultReg = emitASR_rr(RetVT, Op0Reg, Op1Reg);
4800 case Instruction::LShr:
4801 ResultReg = emitLSR_rr(RetVT, Op0Reg, Op1Reg);
4808 updateValueMap(
I, ResultReg);
4812bool AArch64FastISel::selectBitCast(
const Instruction *
I) {
4815 if (!isTypeLegal(
I->getOperand(0)->getType(), SrcVT))
4817 if (!isTypeLegal(
I->getType(), RetVT))
4821 if (RetVT == MVT::f32 && SrcVT == MVT::i32)
4822 Opc = AArch64::FMOVWSr;
4823 else if (RetVT == MVT::f64 && SrcVT == MVT::i64)
4824 Opc = AArch64::FMOVXDr;
4825 else if (RetVT == MVT::i32 && SrcVT == MVT::f32)
4826 Opc = AArch64::FMOVSWr;
4827 else if (RetVT == MVT::i64 && SrcVT == MVT::f64)
4828 Opc = AArch64::FMOVDXr;
4832 const TargetRegisterClass *RC =
nullptr;
4835 case MVT::i32: RC = &AArch64::GPR32RegClass;
break;
4836 case MVT::i64: RC = &AArch64::GPR64RegClass;
break;
4837 case MVT::f32: RC = &AArch64::FPR32RegClass;
break;
4838 case MVT::f64: RC = &AArch64::FPR64RegClass;
break;
4840 Register Op0Reg = getRegForValue(
I->getOperand(0));
4844 Register ResultReg = fastEmitInst_r(
Opc, RC, Op0Reg);
4848 updateValueMap(
I, ResultReg);
4852bool AArch64FastISel::selectFRem(
const Instruction *
I) {
4854 if (!isTypeLegal(
I->getType(), RetVT))
4862 LC = RTLIB::REM_F32;
4865 LC = RTLIB::REM_F64;
4870 Args.reserve(
I->getNumOperands());
4873 for (
auto &Arg :
I->operands())
4874 Args.emplace_back(Arg);
4876 CallLoweringInfo CLI;
4877 MCContext &Ctx = MF->getContext();
4878 CLI.setCallee(
DL, Ctx, TLI.getLibcallCallingConv(LC),
I->getType(),
4879 TLI.getLibcallName(LC), std::move(Args));
4880 if (!lowerCallTo(CLI))
4882 updateValueMap(
I, CLI.ResultReg);
4886bool AArch64FastISel::selectSDiv(
const Instruction *
I) {
4888 if (!isTypeLegal(
I->getType(), VT))
4895 if ((VT != MVT::i32 && VT != MVT::i64) || !
C ||
4896 !(
C.isPowerOf2() ||
C.isNegatedPowerOf2()))
4899 unsigned Lg2 =
C.countr_zero();
4900 Register Src0Reg = getRegForValue(
I->getOperand(0));
4905 Register ResultReg = emitASR_ri(VT, VT, Src0Reg, Lg2);
4908 updateValueMap(
I, ResultReg);
4912 int64_t Pow2MinusOne = (1ULL << Lg2) - 1;
4913 Register AddReg = emitAdd_ri_(VT, Src0Reg, Pow2MinusOne);
4918 if (!emitICmp_ri(VT, Src0Reg, 0))
4922 const TargetRegisterClass *RC;
4923 if (VT == MVT::i64) {
4924 SelectOpc = AArch64::CSELXr;
4925 RC = &AArch64::GPR64RegClass;
4927 SelectOpc = AArch64::CSELWr;
4928 RC = &AArch64::GPR32RegClass;
4930 Register SelectReg = fastEmitInst_rri(SelectOpc, RC, AddReg, Src0Reg,
4937 Register ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
4940 ResultReg = emitAddSub_rs(
false, VT, ZeroReg, SelectReg,
4943 ResultReg = emitASR_ri(VT, VT, SelectReg, Lg2);
4948 updateValueMap(
I, ResultReg);
4955Register AArch64FastISel::getRegForGEPIndex(
const Value *Idx) {
4956 Register IdxN = getRegForValue(Idx);
4962 MVT PtrVT = TLI.getPointerTy(
DL);
4964 if (IdxVT.
bitsLT(PtrVT)) {
4965 IdxN = emitIntExt(IdxVT.
getSimpleVT(), IdxN, PtrVT,
false);
4966 }
else if (IdxVT.
bitsGT(PtrVT))
4967 llvm_unreachable(
"AArch64 FastISel doesn't support types larger than i64");
4975bool AArch64FastISel::selectGetElementPtr(
const Instruction *
I) {
4979 Register N = getRegForValue(
I->getOperand(0));
4985 uint64_t TotalOffs = 0;
4986 MVT VT = TLI.getPointerTy(
DL);
4989 const Value *Idx = GTI.getOperand();
4990 if (
auto *StTy = GTI.getStructTypeOrNull()) {
4994 TotalOffs +=
DL.getStructLayout(StTy)->getElementOffset(
Field);
5001 TotalOffs += GTI.getSequentialElementStride(
DL) *
5006 N = emitAdd_ri_(VT,
N, TotalOffs);
5013 uint64_t ElementSize = GTI.getSequentialElementStride(
DL);
5014 Register IdxN = getRegForGEPIndex(Idx);
5018 if (ElementSize != 1) {
5022 IdxN = emitMul_rr(VT, IdxN,
C);
5032 N = emitAdd_ri_(VT,
N, TotalOffs);
5036 updateValueMap(
I,
N);
5040bool AArch64FastISel::selectAtomicCmpXchg(
const AtomicCmpXchgInst *
I) {
5041 assert(
TM.getOptLevel() == CodeGenOptLevel::None &&
5042 "cmpxchg survived AtomicExpand at optlevel > -O0");
5045 Type *RetTy = RetPairTy->getTypeAtIndex(0U);
5046 assert(RetPairTy->getTypeAtIndex(1U)->isIntegerTy(1) &&
5047 "cmpxchg has a non-i1 status result");
5050 if (!isTypeLegal(RetTy, VT))
5053 const TargetRegisterClass *ResRC;
5054 unsigned Opc, CmpOpc;
5057 if (VT == MVT::i32) {
5058 Opc = AArch64::CMP_SWAP_32;
5059 CmpOpc = AArch64::SUBSWrs;
5060 ResRC = &AArch64::GPR32RegClass;
5061 }
else if (VT == MVT::i64) {
5062 Opc = AArch64::CMP_SWAP_64;
5063 CmpOpc = AArch64::SUBSXrs;
5064 ResRC = &AArch64::GPR64RegClass;
5069 const MCInstrDesc &
II =
TII.get(
Opc);
5071 Register AddrReg = getRegForValue(
I->getPointerOperand());
5072 Register DesiredReg = getRegForValue(
I->getCompareOperand());
5073 Register NewReg = getRegForValue(
I->getNewValOperand());
5075 if (!AddrReg || !DesiredReg || !NewReg)
5082 const Register ResultReg1 = createResultReg(ResRC);
5083 const Register ResultReg2 = createResultReg(&AArch64::GPR32RegClass);
5084 const Register ScratchReg = createResultReg(&AArch64::GPR32RegClass);
5087 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
5094 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CmpOpc))
5095 .
addDef(VT == MVT::i32 ? AArch64::WZR : AArch64::XZR)
5100 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr))
5106 assert((ResultReg1 + 1) == ResultReg2 &&
"Nonconsecutive result registers.");
5107 updateValueMap(
I, ResultReg1, 2);
5111bool AArch64FastISel::fastSelectInstruction(
const Instruction *
I) {
5112 if (TLI.fallBackToDAGISel(*
I))
5114 switch (
I->getOpcode()) {
5117 case Instruction::Add:
5118 case Instruction::Sub:
5119 return selectAddSub(
I);
5120 case Instruction::Mul:
5121 return selectMul(
I);
5122 case Instruction::SDiv:
5123 return selectSDiv(
I);
5124 case Instruction::SRem:
5128 case Instruction::URem:
5132 case Instruction::Shl:
5133 case Instruction::LShr:
5134 case Instruction::AShr:
5135 return selectShift(
I);
5136 case Instruction::And:
5137 case Instruction::Or:
5138 case Instruction::Xor:
5139 return selectLogicalOp(
I);
5140 case Instruction::Br:
5141 return selectBranch(
I);
5142 case Instruction::IndirectBr:
5143 return selectIndirectBr(
I);
5144 case Instruction::BitCast:
5146 return selectBitCast(
I);
5148 case Instruction::FPToSI:
5150 return selectFPToInt(
I,
true);
5152 case Instruction::FPToUI:
5153 return selectFPToInt(
I,
false);
5154 case Instruction::ZExt:
5155 case Instruction::SExt:
5156 return selectIntExt(
I);
5157 case Instruction::Trunc:
5159 return selectTrunc(
I);
5161 case Instruction::FPExt:
5162 return selectFPExt(
I);
5163 case Instruction::FPTrunc:
5164 return selectFPTrunc(
I);
5165 case Instruction::SIToFP:
5167 return selectIntToFP(
I,
true);
5169 case Instruction::UIToFP:
5170 return selectIntToFP(
I,
false);
5171 case Instruction::Load:
5172 return selectLoad(
I);
5173 case Instruction::Store:
5174 return selectStore(
I);
5175 case Instruction::FCmp:
5176 case Instruction::ICmp:
5177 return selectCmp(
I);
5178 case Instruction::Select:
5179 return selectSelect(
I);
5180 case Instruction::Ret:
5181 return selectRet(
I);
5182 case Instruction::FRem:
5183 return selectFRem(
I);
5184 case Instruction::GetElementPtr:
5185 return selectGetElementPtr(
I);
5186 case Instruction::AtomicCmpXchg:
5191 return selectOperator(
I,
I->getOpcode());
5204 return new AArch64FastISel(FuncInfo, LibInfo);
unsigned const MachineRegisterInfo * MRI
static bool isIntExtFree(const Instruction *I)
Check if the sign-/zero-extend will be a noop.
static bool isSExtLoad(const MachineInstr *LI)
static AArch64CC::CondCode getCompareCC(CmpInst::Predicate Pred)
static bool isMulPowOf2(const Value *I)
Check if the multiply is by a power-of-2 constant.
static unsigned getImplicitScaleFactor(MVT VT)
Determine the implicit scale factor that is applied by a memory operation for a given value type.
static bool isZExtLoad(const MachineInstr *LI)
static unsigned selectBinaryOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
Select the AArch64 opcode for the basic binary operation GenericOpc (such as G_OR or G_SDIV),...
static void emitLoad(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2, int Offset, bool IsPostDec)
Emit a load-pair instruction for frame-destroy.
static void emitStore(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2, int Offset, bool IsPreDec)
Emit a store-pair instruction for frame-setup.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
This file defines the FastISel class.
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
uint64_t IntrinsicInst * II
OptimizedStructLayoutField Field
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
SI Pre allocate WWM Registers
This file defines the SmallVector class.
static SDValue emitCmp(SelectionDAG &DAG, const SDLoc &DL, Comparison &C)
static const unsigned FramePtr
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
bool isAnyArgRegReserved(const MachineFunction &MF) const
void emitReservedArgRegCallError(const MachineFunction &MF) const
Register getFrameRegister(const MachineFunction &MF) const override
bool isTargetWindows() const
const AArch64RegisterInfo * getRegisterInfo() const override
bool useSmallAddressing() const
bool isTargetDarwin() const
bool isTargetILP32() const
bool isTargetMachO() const
unsigned ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const
ClassifyGlobalReference - Find the target operand flags that describe how a global value should be re...
bool isLittleEndian() const
bool isWindowsArm64EC() const
bool hasCustomCallingConv() const
PointerType * getType() const
Overload to return most specific pointer type.
InstListType::const_iterator const_iterator
BasicBlock * getSuccessor(unsigned i) const
bool isUnconditional() const
Value * getCondition() const
Register getLocReg() const
LocInfo getLocInfo() const
unsigned getValNo() const
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
const APFloat & getValueAPF() const
bool isNegative() const
Return true if the sign bit is set.
bool isZero() const
Return true if the value is positive or negative zero.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
LLVM_ABI bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
constexpr bool isVector() const
One or more elements.
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
bool selectBitCast(const User *I)
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
PointerType * getType() const
Global values are always pointers.
iterator_range< succ_op_iterator > successors()
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
bool isVector() const
Return true if this is a vector value type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
bool isValid() const
Return true if this is a valid simple valuetype.
static MVT getIntegerVT(unsigned BitWidth)
bool is64BitVector() const
Return true if this is a 64-bit vector type.
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
void setFrameAddressIsTaken(bool T)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Flags
Flags values. These may be or'd together.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
Value * getLength() const
unsigned getDestAddressSpace() const
constexpr unsigned id() const
SMEAttrs is a utility class to parse the SME ACLE attributes on functions.
bool hasStreamingCompatibleInterface() const
bool hasAgnosticZAInterface() const
bool hasStreamingInterfaceOrBody() const
void reserve(size_type N)
void push_back(const T &Elt)
TypeSize getElementOffset(unsigned Idx) const
Provides information about what library functions are available for the current target.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isArrayTy() const
True if this is an instance of ArrayType.
bool isPointerTy() const
True if this is an instance of PointerType.
bool isStructTy() const
True if this is an instance of StructType.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_PREL
MO_PREL - Indicates that the bits of the symbol operand represented by MO_G0 etc are PC relative.
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ ADD
Simple integer binary arithmetic operators.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ User
could "use" a pointer
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
LLVM_ABI void GetReturnInfo(CallingConv::ID CC, Type *ReturnType, AttributeList 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,...
bool CC_AArch64_Win64PCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_AArch64_DarwinPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
unsigned getBLRCallOpcode(const MachineFunction &MF)
Return opcode to be used for indirect calls.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
gep_type_iterator gep_type_end(const User *GEP)
bool isReleaseOrStronger(AtomicOrdering AO)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
bool CC_AArch64_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
generic_gep_type_iterator<> gep_type_iterator
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
AtomicOrdering
Atomic ordering for LLVM's memory model.
bool CC_AArch64_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
unsigned getKillRegState(bool B)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
bool RetCC_AArch64_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
gep_type_iterator gep_type_begin(const User *GEP)
bool CC_AArch64_Win64_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
ElementCount getVectorElementCount() const
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool isVector() const
Return true if this is a vector value type.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.