58#include "llvm/IR/IntrinsicsAArch64.h"
82class AArch64FastISel final :
public FastISel {
85 enum BaseKind { RegBase, FrameIndexBase };
88 BaseKind Kind = RegBase;
97 const GlobalValue *GV =
nullptr;
102 void setKind(BaseKind K) { Kind =
K; }
103 BaseKind getKind()
const {
return Kind; }
106 bool isRegBase()
const {
return Kind == RegBase; }
107 bool isFIBase()
const {
return Kind == FrameIndexBase; }
110 assert(isRegBase() &&
"Invalid base register access!");
115 assert(isRegBase() &&
"Invalid base register access!");
121 Register getOffsetReg()
const {
return OffsetReg; }
123 void setFI(
unsigned FI) {
124 assert(isFIBase() &&
"Invalid base frame index access!");
128 unsigned getFI()
const {
129 assert(isFIBase() &&
"Invalid base frame index access!");
133 void setOffset(int64_t O) { Offset =
O; }
135 void setShift(
unsigned S) { Shift = S; }
136 unsigned getShift() {
return Shift; }
138 void setGlobalValue(
const GlobalValue *
G) { GV =
G; }
139 const GlobalValue *getGlobalValue() {
return GV; }
144 const AArch64Subtarget *Subtarget;
145 LLVMContext *Context;
147 bool fastLowerArguments()
override;
148 bool fastLowerCall(CallLoweringInfo &CLI)
override;
149 bool fastLowerIntrinsicCall(
const IntrinsicInst *
II)
override;
153 bool selectAddSub(
const Instruction *
I);
154 bool selectLogicalOp(
const Instruction *
I);
155 bool selectLoad(
const Instruction *
I);
156 bool selectStore(
const Instruction *
I);
157 bool selectBranch(
const Instruction *
I);
158 bool selectIndirectBr(
const Instruction *
I);
159 bool selectCmp(
const Instruction *
I);
160 bool selectSelect(
const Instruction *
I);
161 bool selectFPExt(
const Instruction *
I);
162 bool selectFPTrunc(
const Instruction *
I);
163 bool selectFPToInt(
const Instruction *
I,
bool Signed);
164 bool selectIntToFP(
const Instruction *
I,
bool Signed);
165 bool selectRem(
const Instruction *
I,
unsigned ISDOpcode);
166 bool selectRet(
const Instruction *
I);
167 bool selectTrunc(
const Instruction *
I);
168 bool selectIntExt(
const Instruction *
I);
169 bool selectMul(
const Instruction *
I);
170 bool selectShift(
const Instruction *
I);
171 bool selectBitCast(
const Instruction *
I);
172 bool selectFRem(
const Instruction *
I);
173 bool selectSDiv(
const Instruction *
I);
174 bool selectGetElementPtr(
const Instruction *
I);
175 bool selectAtomicCmpXchg(
const AtomicCmpXchgInst *
I);
178 bool isTypeLegal(
Type *Ty, MVT &VT);
179 bool isTypeSupported(
Type *Ty, MVT &VT,
bool IsVectorAllowed =
false);
180 bool isValueAvailable(
const Value *V)
const;
181 bool computeAddress(
const Value *Obj, Address &Addr,
Type *Ty =
nullptr);
182 bool computeCallAddress(
const Value *V, Address &Addr);
183 bool simplifyAddress(Address &Addr, MVT VT);
184 void addLoadStoreOperands(Address &Addr,
const MachineInstrBuilder &MIB,
186 unsigned ScaleFactor, MachineMemOperand *MMO);
187 bool isMemCpySmall(uint64_t Len, MaybeAlign Alignment);
188 bool tryEmitSmallMemCpy(Address Dest, Address Src, uint64_t Len,
189 MaybeAlign Alignment);
192 bool optimizeIntExtLoad(
const Instruction *
I, MVT RetVT, MVT SrcVT);
193 bool optimizeSelect(
const SelectInst *SI);
198 const Value *
RHS,
bool SetFlags =
false,
199 bool WantResult =
true,
bool IsZExt =
false);
201 Register RHSReg,
bool SetFlags =
false,
202 bool WantResult =
true);
203 Register emitAddSub_ri(
bool UseAdd, MVT RetVT,
Register LHSReg, uint64_t Imm,
204 bool SetFlags =
false,
bool WantResult =
true);
207 uint64_t ShiftImm,
bool SetFlags =
false,
208 bool WantResult =
true);
211 uint64_t ShiftImm,
bool SetFlags =
false,
212 bool WantResult =
true);
215 bool emitCompareAndBranch(
const BranchInst *BI);
218 bool emitICmp_ri(MVT RetVT,
Register LHSReg, uint64_t Imm);
221 MachineMemOperand *MMO =
nullptr);
223 MachineMemOperand *MMO =
nullptr);
225 MachineMemOperand *MMO =
nullptr);
229 bool SetFlags =
false,
bool WantResult =
true,
230 bool IsZExt =
false);
233 bool SetFlags =
false,
bool WantResult =
true,
234 bool IsZExt =
false);
236 bool WantResult =
true);
239 bool WantResult =
true);
245 Register RHSReg, uint64_t ShiftImm);
258 bool IsZExt =
false);
260 Register materializeInt(
const ConstantInt *CI, MVT VT);
261 Register materializeFP(
const ConstantFP *CFP, MVT VT);
262 Register materializeGV(
const GlobalValue *GV);
266 CCAssignFn *CCAssignFnForCall(CallingConv::ID CC)
const;
267 bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs,
268 SmallVectorImpl<Type *> &OrigTys,
unsigned &NumBytes);
269 bool finishCall(CallLoweringInfo &CLI,
unsigned NumBytes);
273 Register fastMaterializeAlloca(
const AllocaInst *AI)
override;
274 Register fastMaterializeConstant(
const Constant *
C)
override;
275 Register fastMaterializeFloatZero(
const ConstantFP *CF)
override;
277 explicit AArch64FastISel(FunctionLoweringInfo &FuncInfo,
278 const TargetLibraryInfo *LibInfo,
279 const LibcallLoweringInfo *libcallLowering)
280 : FastISel(FuncInfo, LibInfo, libcallLowering,
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 }
2971 unsigned GPRIdx = 0;
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() &&
3186 if (MF->getFunction().getParent()->getRtLibUseGOT())
3196 for (
auto Flag : CLI.OutFlags)
3198 Flag.isSwiftSelf() ||
Flag.isSwiftAsync() ||
Flag.isSwiftError())
3204 OutVTs.
reserve(CLI.OutVals.size());
3206 for (
auto *Val : CLI.OutVals) {
3208 if (!isTypeLegal(Val->getType(), VT) &&
3209 !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16))
3221 if (Callee && !computeCallAddress(Callee, Addr))
3228 Addr.getGlobalValue()->hasExternalWeakLinkage())
3233 if (!processCallArgs(CLI, OutVTs, OrigTys, NumBytes))
3241 MachineInstrBuilder MIB;
3243 const MCInstrDesc &
II =
3245 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II);
3248 else if (Addr.getGlobalValue())
3250 else if (Addr.getReg()) {
3258 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
3259 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
3263 CallReg = createResultReg(&AArch64::GPR64RegClass);
3264 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3265 TII.get(AArch64::LDRXui), CallReg)
3269 }
else if (Addr.getGlobalValue())
3270 CallReg = materializeGV(Addr.getGlobalValue());
3271 else if (Addr.getReg())
3272 CallReg = Addr.getReg();
3279 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II).
addReg(CallReg);
3283 for (
auto Reg : CLI.OutRegs)
3293 return finishCall(CLI, NumBytes);
3296bool AArch64FastISel::isMemCpySmall(uint64_t Len, MaybeAlign Alignment) {
3298 return Len / Alignment->value() <= 4;
3303bool AArch64FastISel::tryEmitSmallMemCpy(
Address Dest,
Address Src,
3304 uint64_t Len, MaybeAlign Alignment) {
3306 if (!isMemCpySmall(Len, Alignment))
3309 int64_t UnscaledOffset = 0;
3315 if (!Alignment || *Alignment >= 8) {
3326 assert(Alignment &&
"Alignment is set in this branch");
3328 if (Len >= 4 && *Alignment == 4)
3330 else if (Len >= 2 && *Alignment == 2)
3346 UnscaledOffset +=
Size;
3349 Dest.setOffset(OrigDest.getOffset() + UnscaledOffset);
3350 Src.setOffset(OrigSrc.getOffset() + UnscaledOffset);
3359 const Instruction *
I,
3373 if (!isTypeLegal(RetTy, RetVT))
3376 if (RetVT != MVT::i32 && RetVT != MVT::i64)
3391 case Intrinsic::smul_with_overflow:
3393 if (
C->getValue() == 2)
3394 IID = Intrinsic::sadd_with_overflow;
3396 case Intrinsic::umul_with_overflow:
3398 if (
C->getValue() == 2)
3399 IID = Intrinsic::uadd_with_overflow;
3407 case Intrinsic::sadd_with_overflow:
3408 case Intrinsic::ssub_with_overflow:
3411 case Intrinsic::uadd_with_overflow:
3414 case Intrinsic::usub_with_overflow:
3417 case Intrinsic::smul_with_overflow:
3418 case Intrinsic::umul_with_overflow:
3424 if (!isValueAvailable(
II))
3430 for (
auto Itr = std::prev(Start); Itr != End; --Itr) {
3438 if (EVI->getAggregateOperand() !=
II)
3446bool AArch64FastISel::fastLowerIntrinsicCall(
const IntrinsicInst *
II) {
3448 switch (
II->getIntrinsicID()) {
3449 default:
return false;
3450 case Intrinsic::frameaddress: {
3451 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3456 Register SrcReg =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3457 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3467 DestReg = fastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,
3469 assert(DestReg &&
"Unexpected LDR instruction emission failure.");
3473 updateValueMap(
II, SrcReg);
3476 case Intrinsic::sponentry: {
3477 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3481 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
3482 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3483 TII.get(AArch64::ADDXri), ResultReg)
3488 updateValueMap(
II, ResultReg);
3491 case Intrinsic::memcpy:
3492 case Intrinsic::memmove: {
3495 if (MTI->isVolatile())
3500 bool IsMemCpy = (
II->getIntrinsicID() == Intrinsic::memcpy);
3505 MaybeAlign Alignment;
3506 if (MTI->getDestAlign() || MTI->getSourceAlign())
3507 Alignment = std::min(MTI->getDestAlign().valueOrOne(),
3508 MTI->getSourceAlign().valueOrOne());
3509 if (isMemCpySmall(Len, Alignment)) {
3511 if (!computeAddress(MTI->getRawDest(), Dest) ||
3512 !computeAddress(MTI->getRawSource(), Src))
3514 if (tryEmitSmallMemCpy(Dest, Src, Len, Alignment))
3519 if (!MTI->getLength()->getType()->isIntegerTy(64))
3522 if (MTI->getSourceAddressSpace() > 255 || MTI->getDestAddressSpace() > 255)
3528 return lowerCallTo(
II, IntrMemName,
II->arg_size() - 1);
3530 case Intrinsic::memset: {
3544 return lowerCallTo(
II,
"memset",
II->arg_size() - 1);
3546 case Intrinsic::sin:
3547 case Intrinsic::cos:
3548 case Intrinsic::tan:
3549 case Intrinsic::pow: {
3551 if (!isTypeLegal(
II->getType(), RetVT))
3554 if (RetVT != MVT::f32 && RetVT != MVT::f64)
3557 static const RTLIB::Libcall LibCallTable[4][2] = {
3558 {RTLIB::SIN_F32, RTLIB::SIN_F64},
3559 {RTLIB::COS_F32, RTLIB::COS_F64},
3560 {RTLIB::TAN_F32, RTLIB::TAN_F64},
3561 {RTLIB::POW_F32, RTLIB::POW_F64}};
3563 bool Is64Bit = RetVT == MVT::f64;
3564 switch (
II->getIntrinsicID()) {
3567 case Intrinsic::sin:
3568 LC = LibCallTable[0][Is64Bit];
3570 case Intrinsic::cos:
3571 LC = LibCallTable[1][Is64Bit];
3573 case Intrinsic::tan:
3574 LC = LibCallTable[2][Is64Bit];
3576 case Intrinsic::pow:
3577 LC = LibCallTable[3][Is64Bit];
3582 Args.reserve(
II->arg_size());
3585 for (
auto &Arg :
II->args())
3586 Args.emplace_back(Arg);
3588 CallLoweringInfo CLI;
3589 MCContext &Ctx = MF->getContext();
3591 RTLIB::LibcallImpl LCImpl = LibcallLowering->getLibcallImpl(LC);
3592 if (LCImpl == RTLIB::Unsupported)
3595 CallingConv::ID CC = LibcallLowering->getLibcallImplCallingConv(LCImpl);
3597 CLI.setCallee(
DL, Ctx, CC,
II->getType(), FuncName, std::move(Args));
3598 if (!lowerCallTo(CLI))
3600 updateValueMap(
II, CLI.ResultReg);
3603 case Intrinsic::fabs: {
3605 if (!isTypeLegal(
II->getType(), VT))
3613 Opc = AArch64::FABSSr;
3616 Opc = AArch64::FABSDr;
3619 Register SrcReg = getRegForValue(
II->getOperand(0));
3622 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3623 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
3625 updateValueMap(
II, ResultReg);
3628 case Intrinsic::trap:
3629 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3632 case Intrinsic::debugtrap:
3633 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3637 case Intrinsic::sqrt: {
3638 Type *RetTy =
II->getCalledFunction()->getReturnType();
3641 if (!isTypeLegal(RetTy, VT))
3644 Register Op0Reg = getRegForValue(
II->getOperand(0));
3652 updateValueMap(
II, ResultReg);
3655 case Intrinsic::sadd_with_overflow:
3656 case Intrinsic::uadd_with_overflow:
3657 case Intrinsic::ssub_with_overflow:
3658 case Intrinsic::usub_with_overflow:
3659 case Intrinsic::smul_with_overflow:
3660 case Intrinsic::umul_with_overflow: {
3664 Type *RetTy = Ty->getTypeAtIndex(0U);
3667 if (!isTypeLegal(RetTy, VT))
3670 if (VT != MVT::i32 && VT != MVT::i64)
3684 case Intrinsic::smul_with_overflow:
3686 if (
C->getValue() == 2) {
3687 IID = Intrinsic::sadd_with_overflow;
3691 case Intrinsic::umul_with_overflow:
3693 if (
C->getValue() == 2) {
3694 IID = Intrinsic::uadd_with_overflow;
3700 Register ResultReg1, ResultReg2, MulReg;
3704 case Intrinsic::sadd_with_overflow:
3705 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3708 case Intrinsic::uadd_with_overflow:
3709 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3712 case Intrinsic::ssub_with_overflow:
3713 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3716 case Intrinsic::usub_with_overflow:
3717 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3720 case Intrinsic::smul_with_overflow: {
3730 if (VT == MVT::i32) {
3731 MulReg = emitSMULL_rr(MVT::i64, LHSReg, RHSReg);
3733 fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3735 emitAddSub_rx(
false, MVT::i64, MulReg, MulSubReg,
3740 assert(VT == MVT::i64 &&
"Unexpected value type.");
3743 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3750 case Intrinsic::umul_with_overflow: {
3760 if (VT == MVT::i32) {
3761 MulReg = emitUMULL_rr(MVT::i64, LHSReg, RHSReg);
3763 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3764 TII.get(AArch64::ANDSXri), AArch64::XZR)
3767 MulReg = fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3769 assert(VT == MVT::i64 &&
"Unexpected value type.");
3772 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3774 emitSubs_rr(VT, AArch64::XZR, UMULHReg,
false);
3781 ResultReg1 = createResultReg(TLI.getRegClassFor(VT));
3782 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3783 TII.get(TargetOpcode::COPY), ResultReg1).
addReg(MulReg);
3789 ResultReg2 = fastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,
3790 AArch64::WZR, AArch64::WZR,
3791 getInvertedCondCode(CC));
3793 assert((ResultReg1 + 1) == ResultReg2 &&
3794 "Nonconsecutive result registers.");
3795 updateValueMap(
II, ResultReg1, 2);
3798 case Intrinsic::aarch64_crc32b:
3799 case Intrinsic::aarch64_crc32h:
3800 case Intrinsic::aarch64_crc32w:
3801 case Intrinsic::aarch64_crc32x:
3802 case Intrinsic::aarch64_crc32cb:
3803 case Intrinsic::aarch64_crc32ch:
3804 case Intrinsic::aarch64_crc32cw:
3805 case Intrinsic::aarch64_crc32cx: {
3806 if (!Subtarget->hasCRC())
3810 switch (
II->getIntrinsicID()) {
3813 case Intrinsic::aarch64_crc32b:
3814 Opc = AArch64::CRC32Brr;
3816 case Intrinsic::aarch64_crc32h:
3817 Opc = AArch64::CRC32Hrr;
3819 case Intrinsic::aarch64_crc32w:
3820 Opc = AArch64::CRC32Wrr;
3822 case Intrinsic::aarch64_crc32x:
3823 Opc = AArch64::CRC32Xrr;
3825 case Intrinsic::aarch64_crc32cb:
3826 Opc = AArch64::CRC32CBrr;
3828 case Intrinsic::aarch64_crc32ch:
3829 Opc = AArch64::CRC32CHrr;
3831 case Intrinsic::aarch64_crc32cw:
3832 Opc = AArch64::CRC32CWrr;
3834 case Intrinsic::aarch64_crc32cx:
3835 Opc = AArch64::CRC32CXrr;
3839 Register LHSReg = getRegForValue(
II->getArgOperand(0));
3840 Register RHSReg = getRegForValue(
II->getArgOperand(1));
3841 if (!LHSReg || !RHSReg)
3845 fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, LHSReg, RHSReg);
3846 updateValueMap(
II, ResultReg);
3853bool AArch64FastISel::selectRet(
const Instruction *
I) {
3855 const Function &
F = *
I->getParent()->getParent();
3857 if (!FuncInfo.CanLowerReturn)
3863 if (TLI.supportSwiftError() &&
3864 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
3867 if (TLI.supportSplitCSR(FuncInfo.MF))
3874 CallingConv::ID CC =
F.getCallingConv();
3880 CCState CCInfo(CC,
F.isVarArg(), *FuncInfo.MF, ValLocs,
I->getContext());
3884 if (ValLocs.
size() != 1)
3887 CCValAssign &VA = ValLocs[0];
3906 if (!
MRI.getRegClass(SrcReg)->contains(DestReg))
3909 EVT RVEVT = TLI.getValueType(
DL, RV->
getType());
3919 if (RVVT == MVT::f128)
3924 if (RVVT != DestVT) {
3925 if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
3928 if (!Outs[0].
Flags.isZExt() && !Outs[0].Flags.isSExt())
3931 bool IsZExt = Outs[0].Flags.isZExt();
3932 SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
3940 SrcReg = emitAnd_ri(MVT::i64, SrcReg, 0xffffffff);
3943 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3944 TII.get(TargetOpcode::COPY), DestReg).
addReg(SrcReg);
3950 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3951 TII.get(AArch64::RET_ReallyLR));
3957bool AArch64FastISel::selectTrunc(
const Instruction *
I) {
3958 Type *DestTy =
I->getType();
3960 Type *SrcTy =
Op->getType();
3962 EVT SrcEVT = TLI.getValueType(
DL, SrcTy,
true);
3963 EVT DestEVT = TLI.getValueType(
DL, DestTy,
true);
3972 if (SrcVT != MVT::i64 && SrcVT != MVT::i32 && SrcVT != MVT::i16 &&
3975 if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8 &&
3989 if (SrcVT == MVT::i64) {
4006 Register Reg32 = fastEmitInst_extractsubreg(MVT::i32, SrcReg,
4009 ResultReg = emitAnd_ri(MVT::i32, Reg32, Mask);
4010 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4012 ResultReg = createResultReg(&AArch64::GPR32RegClass);
4013 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4014 TII.get(TargetOpcode::COPY), ResultReg)
4018 updateValueMap(
I, ResultReg);
4022Register AArch64FastISel::emiti1Ext(
Register SrcReg, MVT DestVT,
bool IsZExt) {
4023 assert((DestVT == MVT::i8 || DestVT == MVT::i16 || DestVT == MVT::i32 ||
4024 DestVT == MVT::i64) &&
4025 "Unexpected value type.");
4027 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4031 Register ResultReg = emitAnd_ri(MVT::i32, SrcReg, 1);
4032 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4033 if (DestVT == MVT::i64) {
4036 Register Reg64 =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4037 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4038 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4041 .
addImm(AArch64::sub_32);
4046 if (DestVT == MVT::i64) {
4050 return fastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,
4065 Opc = AArch64::MADDWrrr; ZReg = AArch64::WZR;
break;
4067 Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR;
break;
4070 const TargetRegisterClass *RC =
4071 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4072 return fastEmitInst_rrr(
Opc, RC, Op0, Op1, ZReg);
4076 if (RetVT != MVT::i64)
4079 return fastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,
4080 Op0, Op1, AArch64::XZR);
4084 if (RetVT != MVT::i64)
4087 return fastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,
4088 Op0, Op1, AArch64::XZR);
4094 bool NeedTrunc =
false;
4099 case MVT::i8:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4100 case MVT::i16:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4101 case MVT::i32:
Opc = AArch64::LSLVWr;
break;
4102 case MVT::i64:
Opc = AArch64::LSLVXr;
break;
4105 const TargetRegisterClass *RC =
4106 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4108 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4110 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4112 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4117 uint64_t Shift,
bool IsZExt) {
4119 "Unexpected source/return type pair.");
4120 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4121 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4122 "Unexpected source value type.");
4123 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4124 RetVT == MVT::i64) &&
"Unexpected return value type.");
4126 bool Is64Bit = (RetVT == MVT::i64);
4127 unsigned RegSize = Is64Bit ? 64 : 32;
4130 const TargetRegisterClass *RC =
4131 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4135 if (RetVT == SrcVT) {
4136 Register ResultReg = createResultReg(RC);
4137 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4138 TII.get(TargetOpcode::COPY), ResultReg)
4142 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4146 if (Shift >= DstBits)
4174 unsigned ImmR =
RegSize - Shift;
4176 unsigned ImmS = std::min<unsigned>(SrcBits - 1, DstBits - 1 - Shift);
4177 static const unsigned OpcTable[2][2] = {
4178 {AArch64::SBFMWri, AArch64::SBFMXri},
4179 {AArch64::UBFMWri, AArch64::UBFMXri}
4181 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4182 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4184 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4185 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4188 .
addImm(AArch64::sub_32);
4191 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4197 bool NeedTrunc =
false;
4202 case MVT::i8:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4203 case MVT::i16:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4204 case MVT::i32:
Opc = AArch64::LSRVWr;
break;
4205 case MVT::i64:
Opc = AArch64::LSRVXr;
break;
4208 const TargetRegisterClass *RC =
4209 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4211 Op0Reg = emitAnd_ri(MVT::i32, Op0Reg, Mask);
4212 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4214 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4216 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4221 uint64_t Shift,
bool IsZExt) {
4223 "Unexpected source/return type pair.");
4224 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4225 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4226 "Unexpected source value type.");
4227 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4228 RetVT == MVT::i64) &&
"Unexpected return value type.");
4230 bool Is64Bit = (RetVT == MVT::i64);
4231 unsigned RegSize = Is64Bit ? 64 : 32;
4234 const TargetRegisterClass *RC =
4235 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4239 if (RetVT == SrcVT) {
4240 Register ResultReg = createResultReg(RC);
4241 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4242 TII.get(TargetOpcode::COPY), ResultReg)
4246 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4250 if (Shift >= DstBits)
4278 if (Shift >= SrcBits && IsZExt)
4279 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4284 Op0 = emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4292 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4293 unsigned ImmS = SrcBits - 1;
4294 static const unsigned OpcTable[2][2] = {
4295 {AArch64::SBFMWri, AArch64::SBFMXri},
4296 {AArch64::UBFMWri, AArch64::UBFMXri}
4298 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4299 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4301 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4302 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4305 .
addImm(AArch64::sub_32);
4308 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4314 bool NeedTrunc =
false;
4319 case MVT::i8:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4320 case MVT::i16:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4321 case MVT::i32:
Opc = AArch64::ASRVWr;
break;
4322 case MVT::i64:
Opc = AArch64::ASRVXr;
break;
4325 const TargetRegisterClass *RC =
4326 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4328 Op0Reg = emitIntExt(RetVT, Op0Reg, MVT::i32,
false);
4329 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4331 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4333 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4338 uint64_t Shift,
bool IsZExt) {
4340 "Unexpected source/return type pair.");
4341 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4342 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4343 "Unexpected source value type.");
4344 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4345 RetVT == MVT::i64) &&
"Unexpected return value type.");
4347 bool Is64Bit = (RetVT == MVT::i64);
4348 unsigned RegSize = Is64Bit ? 64 : 32;
4351 const TargetRegisterClass *RC =
4352 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4356 if (RetVT == SrcVT) {
4357 Register ResultReg = createResultReg(RC);
4358 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4359 TII.get(TargetOpcode::COPY), ResultReg)
4363 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4367 if (Shift >= DstBits)
4395 if (Shift >= SrcBits && IsZExt)
4396 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4398 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4399 unsigned ImmS = SrcBits - 1;
4400 static const unsigned OpcTable[2][2] = {
4401 {AArch64::SBFMWri, AArch64::SBFMXri},
4402 {AArch64::UBFMWri, AArch64::UBFMXri}
4404 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4405 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4407 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4408 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4411 .
addImm(AArch64::sub_32);
4414 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4417Register AArch64FastISel::emitIntExt(MVT SrcVT,
Register SrcReg, MVT DestVT,
4419 assert(DestVT != MVT::i1 &&
"ZeroExt/SignExt an i1?");
4425 if (((DestVT != MVT::i8) && (DestVT != MVT::i16) &&
4426 (DestVT != MVT::i32) && (DestVT != MVT::i64)) ||
4427 ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) &&
4428 (SrcVT != MVT::i16) && (SrcVT != MVT::i32)))
4438 return emiti1Ext(SrcReg, DestVT, IsZExt);
4440 if (DestVT == MVT::i64)
4441 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4443 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4447 if (DestVT == MVT::i64)
4448 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4450 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4454 assert(DestVT == MVT::i64 &&
"IntExt i32 to i32?!?");
4455 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4461 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4463 else if (DestVT == MVT::i64) {
4464 Register Src64 =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4465 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4466 TII.get(AArch64::SUBREG_TO_REG), Src64)
4469 .
addImm(AArch64::sub_32);
4473 const TargetRegisterClass *RC =
4474 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4475 return fastEmitInst_rii(
Opc, RC, SrcReg, 0, Imm);
4482 case AArch64::LDURBBi:
4483 case AArch64::LDURHHi:
4484 case AArch64::LDURWi:
4485 case AArch64::LDRBBui:
4486 case AArch64::LDRHHui:
4487 case AArch64::LDRWui:
4488 case AArch64::LDRBBroX:
4489 case AArch64::LDRHHroX:
4490 case AArch64::LDRWroX:
4491 case AArch64::LDRBBroW:
4492 case AArch64::LDRHHroW:
4493 case AArch64::LDRWroW:
4502 case AArch64::LDURSBWi:
4503 case AArch64::LDURSHWi:
4504 case AArch64::LDURSBXi:
4505 case AArch64::LDURSHXi:
4506 case AArch64::LDURSWi:
4507 case AArch64::LDRSBWui:
4508 case AArch64::LDRSHWui:
4509 case AArch64::LDRSBXui:
4510 case AArch64::LDRSHXui:
4511 case AArch64::LDRSWui:
4512 case AArch64::LDRSBWroX:
4513 case AArch64::LDRSHWroX:
4514 case AArch64::LDRSBXroX:
4515 case AArch64::LDRSHXroX:
4516 case AArch64::LDRSWroX:
4517 case AArch64::LDRSBWroW:
4518 case AArch64::LDRSHWroW:
4519 case AArch64::LDRSBXroW:
4520 case AArch64::LDRSHXroW:
4521 case AArch64::LDRSWroW:
4526bool AArch64FastISel::optimizeIntExtLoad(
const Instruction *
I, MVT RetVT,
4529 if (!LI || !LI->hasOneUse())
4537 MachineInstr *
MI =
MRI.getUniqueVRegDef(
Reg);
4544 const auto *LoadMI =
MI;
4545 if (LoadMI->getOpcode() == TargetOpcode::COPY &&
4546 LoadMI->getOperand(1).getSubReg() == AArch64::sub_32) {
4547 Register LoadReg =
MI->getOperand(1).getReg();
4548 LoadMI =
MRI.getUniqueVRegDef(LoadReg);
4549 assert(LoadMI &&
"Expected valid instruction");
4555 if (RetVT != MVT::i64 || SrcVT > MVT::i32) {
4556 updateValueMap(
I,
Reg);
4561 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
4562 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4563 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4566 .
addImm(AArch64::sub_32);
4569 assert((
MI->getOpcode() == TargetOpcode::COPY &&
4570 MI->getOperand(1).getSubReg() == AArch64::sub_32) &&
4571 "Expected copy instruction");
4572 Reg =
MI->getOperand(1).getReg();
4574 removeDeadCode(
I, std::next(
I));
4576 updateValueMap(
I,
Reg);
4580bool AArch64FastISel::selectIntExt(
const Instruction *
I) {
4582 "Unexpected integer extend instruction.");
4585 if (!isTypeSupported(
I->getType(), RetVT))
4588 if (!isTypeSupported(
I->getOperand(0)->getType(), SrcVT))
4592 if (optimizeIntExtLoad(
I, RetVT, SrcVT))
4595 Register SrcReg = getRegForValue(
I->getOperand(0));
4602 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr())) {
4603 if (RetVT == MVT::i64 && SrcVT != MVT::i64) {
4604 Register ResultReg = createResultReg(&AArch64::GPR64RegClass);
4605 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4606 TII.get(AArch64::SUBREG_TO_REG), ResultReg)
4609 .
addImm(AArch64::sub_32);
4613 updateValueMap(
I, SrcReg);
4618 Register ResultReg = emitIntExt(SrcVT, SrcReg, RetVT, IsZExt);
4622 updateValueMap(
I, ResultReg);
4626bool AArch64FastISel::selectRem(
const Instruction *
I,
unsigned ISDOpcode) {
4627 EVT DestEVT = TLI.getValueType(
DL,
I->getType(),
true);
4632 if (DestVT != MVT::i64 && DestVT != MVT::i32)
4636 bool Is64bit = (DestVT == MVT::i64);
4637 switch (ISDOpcode) {
4641 DivOpc = Is64bit ? AArch64::SDIVXr : AArch64::SDIVWr;
4644 DivOpc = Is64bit ? AArch64::UDIVXr : AArch64::UDIVWr;
4647 unsigned MSubOpc = Is64bit ? AArch64::MSUBXrrr : AArch64::MSUBWrrr;
4648 Register Src0Reg = getRegForValue(
I->getOperand(0));
4652 Register Src1Reg = getRegForValue(
I->getOperand(1));
4656 const TargetRegisterClass *RC =
4657 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4658 Register QuotReg = fastEmitInst_rr(DivOpc, RC, Src0Reg, Src1Reg);
4659 assert(QuotReg &&
"Unexpected DIV instruction emission failure.");
4662 Register ResultReg = fastEmitInst_rrr(MSubOpc, RC, QuotReg, Src1Reg, Src0Reg);
4663 updateValueMap(
I, ResultReg);
4667bool AArch64FastISel::selectMul(
const Instruction *
I) {
4669 if (!isTypeSupported(
I->getType(), VT,
true))
4675 const Value *Src0 =
I->getOperand(0);
4676 const Value *Src1 =
I->getOperand(1);
4678 if (
C->getValue().isPowerOf2())
4683 if (
C->getValue().isPowerOf2()) {
4684 uint64_t ShiftVal =
C->getValue().logBase2();
4690 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), VT)) {
4693 Src0 = ZExt->getOperand(0);
4699 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), VT)) {
4702 Src0 = SExt->getOperand(0);
4707 Register Src0Reg = getRegForValue(Src0);
4711 Register ResultReg = emitLSL_ri(VT, SrcVT, Src0Reg, ShiftVal, IsZExt);
4714 updateValueMap(
I, ResultReg);
4719 Register Src0Reg = getRegForValue(
I->getOperand(0));
4723 Register Src1Reg = getRegForValue(
I->getOperand(1));
4727 Register ResultReg = emitMul_rr(VT, Src0Reg, Src1Reg);
4732 updateValueMap(
I, ResultReg);
4736bool AArch64FastISel::selectShift(
const Instruction *
I) {
4738 if (!isTypeSupported(
I->getType(), RetVT,
true))
4742 return selectOperator(
I,
I->getOpcode());
4746 uint64_t ShiftVal =
C->getZExtValue();
4748 bool IsZExt =
I->getOpcode() != Instruction::AShr;
4749 const Value *Op0 =
I->getOperand(0);
4753 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), TmpVT)) {
4756 Op0 = ZExt->getOperand(0);
4762 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), TmpVT)) {
4765 Op0 = SExt->getOperand(0);
4770 Register Op0Reg = getRegForValue(Op0);
4774 switch (
I->getOpcode()) {
4776 case Instruction::Shl:
4777 ResultReg = emitLSL_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4779 case Instruction::AShr:
4780 ResultReg = emitASR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4782 case Instruction::LShr:
4783 ResultReg = emitLSR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4789 updateValueMap(
I, ResultReg);
4793 Register Op0Reg = getRegForValue(
I->getOperand(0));
4797 Register Op1Reg = getRegForValue(
I->getOperand(1));
4802 switch (
I->getOpcode()) {
4804 case Instruction::Shl:
4805 ResultReg = emitLSL_rr(RetVT, Op0Reg, Op1Reg);
4807 case Instruction::AShr:
4808 ResultReg = emitASR_rr(RetVT, Op0Reg, Op1Reg);
4810 case Instruction::LShr:
4811 ResultReg = emitLSR_rr(RetVT, Op0Reg, Op1Reg);
4818 updateValueMap(
I, ResultReg);
4822bool AArch64FastISel::selectBitCast(
const Instruction *
I) {
4825 if (!isTypeLegal(
I->getOperand(0)->getType(), SrcVT))
4827 if (!isTypeLegal(
I->getType(), RetVT))
4831 if (RetVT == MVT::f32 && SrcVT == MVT::i32)
4832 Opc = AArch64::FMOVWSr;
4833 else if (RetVT == MVT::f64 && SrcVT == MVT::i64)
4834 Opc = AArch64::FMOVXDr;
4835 else if (RetVT == MVT::i32 && SrcVT == MVT::f32)
4836 Opc = AArch64::FMOVSWr;
4837 else if (RetVT == MVT::i64 && SrcVT == MVT::f64)
4838 Opc = AArch64::FMOVDXr;
4842 const TargetRegisterClass *RC =
nullptr;
4845 case MVT::i32: RC = &AArch64::GPR32RegClass;
break;
4846 case MVT::i64: RC = &AArch64::GPR64RegClass;
break;
4847 case MVT::f32: RC = &AArch64::FPR32RegClass;
break;
4848 case MVT::f64: RC = &AArch64::FPR64RegClass;
break;
4850 Register Op0Reg = getRegForValue(
I->getOperand(0));
4854 Register ResultReg = fastEmitInst_r(
Opc, RC, Op0Reg);
4858 updateValueMap(
I, ResultReg);
4862bool AArch64FastISel::selectFRem(
const Instruction *
I) {
4864 if (!isTypeLegal(
I->getType(), RetVT))
4867 RTLIB::LibcallImpl LCImpl =
4869 if (LCImpl == RTLIB::Unsupported)
4873 Args.reserve(
I->getNumOperands());
4876 for (
auto &Arg :
I->operands())
4877 Args.emplace_back(Arg);
4879 CallLoweringInfo CLI;
4880 MCContext &Ctx = MF->getContext();
4881 CallingConv::ID CC = LibcallLowering->getLibcallImplCallingConv(LCImpl);
4884 CLI.setCallee(
DL, Ctx, CC,
I->getType(), FuncName, std::move(Args));
4885 if (!lowerCallTo(CLI))
4887 updateValueMap(
I, CLI.ResultReg);
4891bool AArch64FastISel::selectSDiv(
const Instruction *
I) {
4893 if (!isTypeLegal(
I->getType(), VT))
4900 if ((VT != MVT::i32 && VT != MVT::i64) || !
C ||
4901 !(
C.isPowerOf2() ||
C.isNegatedPowerOf2()))
4904 unsigned Lg2 =
C.countr_zero();
4905 Register Src0Reg = getRegForValue(
I->getOperand(0));
4910 Register ResultReg = emitASR_ri(VT, VT, Src0Reg, Lg2);
4913 updateValueMap(
I, ResultReg);
4917 int64_t Pow2MinusOne = (1ULL << Lg2) - 1;
4918 Register AddReg = emitAdd_ri_(VT, Src0Reg, Pow2MinusOne);
4923 if (!emitICmp_ri(VT, Src0Reg, 0))
4927 const TargetRegisterClass *RC;
4928 if (VT == MVT::i64) {
4929 SelectOpc = AArch64::CSELXr;
4930 RC = &AArch64::GPR64RegClass;
4932 SelectOpc = AArch64::CSELWr;
4933 RC = &AArch64::GPR32RegClass;
4935 Register SelectReg = fastEmitInst_rri(SelectOpc, RC, AddReg, Src0Reg,
4942 Register ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
4945 ResultReg = emitAddSub_rs(
false, VT, ZeroReg, SelectReg,
4948 ResultReg = emitASR_ri(VT, VT, SelectReg, Lg2);
4953 updateValueMap(
I, ResultReg);
4960Register AArch64FastISel::getRegForGEPIndex(
const Value *Idx) {
4961 Register IdxN = getRegForValue(Idx);
4967 MVT PtrVT = TLI.getPointerTy(
DL);
4969 if (IdxVT.
bitsLT(PtrVT)) {
4970 IdxN = emitIntExt(IdxVT.
getSimpleVT(), IdxN, PtrVT,
false);
4971 }
else if (IdxVT.
bitsGT(PtrVT))
4972 llvm_unreachable(
"AArch64 FastISel doesn't support types larger than i64");
4980bool AArch64FastISel::selectGetElementPtr(
const Instruction *
I) {
4984 Register N = getRegForValue(
I->getOperand(0));
4990 uint64_t TotalOffs = 0;
4991 MVT VT = TLI.getPointerTy(
DL);
4994 const Value *Idx = GTI.getOperand();
4995 if (
auto *StTy = GTI.getStructTypeOrNull()) {
4999 TotalOffs +=
DL.getStructLayout(StTy)->getElementOffset(
Field);
5006 TotalOffs += GTI.getSequentialElementStride(
DL) *
5011 N = emitAdd_ri_(VT,
N, TotalOffs);
5018 uint64_t ElementSize = GTI.getSequentialElementStride(
DL);
5019 Register IdxN = getRegForGEPIndex(Idx);
5023 if (ElementSize != 1) {
5027 IdxN = emitMul_rr(VT, IdxN,
C);
5037 N = emitAdd_ri_(VT,
N, TotalOffs);
5041 updateValueMap(
I,
N);
5045bool AArch64FastISel::selectAtomicCmpXchg(
const AtomicCmpXchgInst *
I) {
5046 assert(TM.getOptLevel() == CodeGenOptLevel::None &&
5047 "cmpxchg survived AtomicExpand at optlevel > -O0");
5050 Type *RetTy = RetPairTy->getTypeAtIndex(0U);
5051 assert(RetPairTy->getTypeAtIndex(1U)->isIntegerTy(1) &&
5052 "cmpxchg has a non-i1 status result");
5055 if (!isTypeLegal(RetTy, VT))
5058 const TargetRegisterClass *ResRC;
5059 unsigned Opc, CmpOpc;
5062 if (VT == MVT::i32) {
5063 Opc = AArch64::CMP_SWAP_32;
5064 CmpOpc = AArch64::SUBSWrs;
5065 ResRC = &AArch64::GPR32RegClass;
5066 }
else if (VT == MVT::i64) {
5067 Opc = AArch64::CMP_SWAP_64;
5068 CmpOpc = AArch64::SUBSXrs;
5069 ResRC = &AArch64::GPR64RegClass;
5074 const MCInstrDesc &
II =
TII.get(
Opc);
5076 Register AddrReg = getRegForValue(
I->getPointerOperand());
5077 Register DesiredReg = getRegForValue(
I->getCompareOperand());
5078 Register NewReg = getRegForValue(
I->getNewValOperand());
5080 if (!AddrReg || !DesiredReg || !NewReg)
5087 const Register ResultReg1 = createResultReg(ResRC);
5088 const Register ResultReg2 = createResultReg(&AArch64::GPR32RegClass);
5089 const Register ScratchReg = createResultReg(&AArch64::GPR32RegClass);
5092 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
5099 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CmpOpc))
5100 .
addDef(VT == MVT::i32 ? AArch64::WZR : AArch64::XZR)
5105 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr))
5111 assert((ResultReg1 + 1) == ResultReg2 &&
"Nonconsecutive result registers.");
5112 updateValueMap(
I, ResultReg1, 2);
5116bool AArch64FastISel::fastSelectInstruction(
const Instruction *
I) {
5117 if (TLI.fallBackToDAGISel(*
I))
5119 switch (
I->getOpcode()) {
5122 case Instruction::Add:
5123 case Instruction::Sub:
5124 return selectAddSub(
I);
5125 case Instruction::Mul:
5126 return selectMul(
I);
5127 case Instruction::SDiv:
5128 return selectSDiv(
I);
5129 case Instruction::SRem:
5133 case Instruction::URem:
5137 case Instruction::Shl:
5138 case Instruction::LShr:
5139 case Instruction::AShr:
5140 return selectShift(
I);
5141 case Instruction::And:
5142 case Instruction::Or:
5143 case Instruction::Xor:
5144 return selectLogicalOp(
I);
5145 case Instruction::Br:
5146 return selectBranch(
I);
5147 case Instruction::IndirectBr:
5148 return selectIndirectBr(
I);
5149 case Instruction::BitCast:
5151 return selectBitCast(
I);
5153 case Instruction::FPToSI:
5155 return selectFPToInt(
I,
true);
5157 case Instruction::FPToUI:
5158 return selectFPToInt(
I,
false);
5159 case Instruction::ZExt:
5160 case Instruction::SExt:
5161 return selectIntExt(
I);
5162 case Instruction::Trunc:
5164 return selectTrunc(
I);
5166 case Instruction::FPExt:
5167 return selectFPExt(
I);
5168 case Instruction::FPTrunc:
5169 return selectFPTrunc(
I);
5170 case Instruction::SIToFP:
5172 return selectIntToFP(
I,
true);
5174 case Instruction::UIToFP:
5175 return selectIntToFP(
I,
false);
5176 case Instruction::Load:
5177 return selectLoad(
I);
5178 case Instruction::Store:
5179 return selectStore(
I);
5180 case Instruction::FCmp:
5181 case Instruction::ICmp:
5182 return selectCmp(
I);
5183 case Instruction::Select:
5184 return selectSelect(
I);
5185 case Instruction::Ret:
5186 return selectRet(
I);
5187 case Instruction::FRem:
5188 return selectFRem(
I);
5189 case Instruction::GetElementPtr:
5190 return selectGetElementPtr(
I);
5191 case Instruction::AtomicCmpXchg:
5196 return selectOperator(
I,
I->getOpcode());
5210 return new AArch64FastISel(FuncInfo, LibInfo, LibcallLowering);
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 MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
uint64_t IntrinsicInst * II
This file defines ARC utility functions which are used by various parts of the compiler.
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.
Tracks which library functions to use for a particular subtarget.
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
unsigned getNumOperands() 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, const LibcallLoweringInfo *libcallLowering)
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.
LLVM_ABI Libcall getREM(EVT VT)
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ User
could "use" a pointer
bool hasAttachedCallOpBundle(const CallBase *CB)
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 unsigned getKillRegState(bool B)
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)
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.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.