57#include "llvm/IR/IntrinsicsAArch64.h"
81class AArch64FastISel final :
public FastISel {
84 enum BaseKind { RegBase, FrameIndexBase };
87 BaseKind Kind = RegBase;
96 const GlobalValue *GV =
nullptr;
101 void setKind(BaseKind K) { Kind =
K; }
102 BaseKind getKind()
const {
return Kind; }
105 bool isRegBase()
const {
return Kind == RegBase; }
106 bool isFIBase()
const {
return Kind == FrameIndexBase; }
109 assert(isRegBase() &&
"Invalid base register access!");
114 assert(isRegBase() &&
"Invalid base register access!");
120 Register getOffsetReg()
const {
return OffsetReg; }
122 void setFI(
unsigned FI) {
123 assert(isFIBase() &&
"Invalid base frame index access!");
127 unsigned getFI()
const {
128 assert(isFIBase() &&
"Invalid base frame index access!");
132 void setOffset(int64_t O) { Offset =
O; }
134 void setShift(
unsigned S) { Shift = S; }
135 unsigned getShift() {
return Shift; }
137 void setGlobalValue(
const GlobalValue *
G) { GV =
G; }
138 const GlobalValue *getGlobalValue() {
return GV; }
143 const AArch64Subtarget *Subtarget;
144 LLVMContext *Context;
146 bool fastLowerArguments()
override;
147 bool fastLowerCall(CallLoweringInfo &CLI)
override;
148 bool fastLowerIntrinsicCall(
const IntrinsicInst *
II)
override;
152 bool selectAddSub(
const Instruction *
I);
153 bool selectLogicalOp(
const Instruction *
I);
154 bool selectLoad(
const Instruction *
I);
155 bool selectStore(
const Instruction *
I);
156 bool selectBranch(
const Instruction *
I);
157 bool selectIndirectBr(
const Instruction *
I);
158 bool selectCmp(
const Instruction *
I);
159 bool selectSelect(
const Instruction *
I);
160 bool selectFPExt(
const Instruction *
I);
161 bool selectFPTrunc(
const Instruction *
I);
162 bool selectFPToInt(
const Instruction *
I,
bool Signed);
163 bool selectIntToFP(
const Instruction *
I,
bool Signed);
164 bool selectRem(
const Instruction *
I,
unsigned ISDOpcode);
165 bool selectRet(
const Instruction *
I);
166 bool selectTrunc(
const Instruction *
I);
167 bool selectIntExt(
const Instruction *
I);
168 bool selectMul(
const Instruction *
I);
169 bool selectShift(
const Instruction *
I);
170 bool selectBitCast(
const Instruction *
I);
171 bool selectFRem(
const Instruction *
I);
172 bool selectSDiv(
const Instruction *
I);
173 bool selectGetElementPtr(
const Instruction *
I);
174 bool selectAtomicCmpXchg(
const AtomicCmpXchgInst *
I);
177 bool isTypeLegal(
Type *Ty, MVT &VT);
178 bool isTypeSupported(
Type *Ty, MVT &VT,
bool IsVectorAllowed =
false);
179 bool isValueAvailable(
const Value *V)
const;
180 bool computeAddress(
const Value *Obj, Address &Addr,
Type *Ty =
nullptr);
181 bool computeCallAddress(
const Value *V, Address &Addr);
182 bool simplifyAddress(Address &Addr, MVT VT);
183 void addLoadStoreOperands(Address &Addr,
const MachineInstrBuilder &MIB,
185 unsigned ScaleFactor, MachineMemOperand *MMO);
186 bool isMemCpySmall(uint64_t Len, MaybeAlign Alignment);
187 bool tryEmitSmallMemCpy(Address Dest, Address Src, uint64_t Len,
188 MaybeAlign Alignment);
191 bool optimizeIntExtLoad(
const Instruction *
I, MVT RetVT, MVT SrcVT);
192 bool optimizeSelect(
const SelectInst *SI);
197 const Value *
RHS,
bool SetFlags =
false,
198 bool WantResult =
true,
bool IsZExt =
false);
200 Register RHSReg,
bool SetFlags =
false,
201 bool WantResult =
true);
202 Register emitAddSub_ri(
bool UseAdd, MVT RetVT,
Register LHSReg, uint64_t Imm,
203 bool SetFlags =
false,
bool WantResult =
true);
206 uint64_t ShiftImm,
bool SetFlags =
false,
207 bool WantResult =
true);
210 uint64_t ShiftImm,
bool SetFlags =
false,
211 bool WantResult =
true);
214 bool emitCompareAndBranch(
const CondBrInst *BI);
217 bool emitICmp_ri(MVT RetVT,
Register LHSReg, uint64_t Imm);
220 MachineMemOperand *MMO =
nullptr);
222 MachineMemOperand *MMO =
nullptr);
224 MachineMemOperand *MMO =
nullptr);
228 bool SetFlags =
false,
bool WantResult =
true,
229 bool IsZExt =
false);
232 bool SetFlags =
false,
bool WantResult =
true,
233 bool IsZExt =
false);
235 bool WantResult =
true);
238 bool WantResult =
true);
244 Register RHSReg, uint64_t ShiftImm);
257 bool IsZExt =
false);
259 Register materializeInt(
const ConstantInt *CI, MVT VT);
260 Register materializeFP(
const ConstantFP *CFP, MVT VT);
261 Register materializeGV(
const GlobalValue *GV);
265 CCAssignFn *CCAssignFnForCall(CallingConv::ID CC)
const;
266 bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs,
267 SmallVectorImpl<Type *> &OrigTys,
unsigned &NumBytes);
268 bool finishCall(CallLoweringInfo &CLI,
unsigned NumBytes);
272 Register fastMaterializeAlloca(
const AllocaInst *AI)
override;
273 Register fastMaterializeConstant(
const Constant *
C)
override;
274 Register fastMaterializeFloatZero(
const ConstantFP *CF)
override;
276 explicit AArch64FastISel(FunctionLoweringInfo &FuncInfo,
277 const TargetLibraryInfo *LibInfo,
278 const LibcallLoweringInfo *libcallLowering)
279 : FastISel(FuncInfo, LibInfo, libcallLowering,
285 bool fastSelectInstruction(
const Instruction *
I)
override;
287#include "AArch64GenFastISel.inc"
295 "Unexpected integer extend instruction.");
296 assert(!
I->getType()->isVectorTy() &&
I->getType()->isIntegerTy() &&
297 "Unexpected value type.");
305 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr()))
332 if (CC == CallingConv::GHC)
334 if (CC == CallingConv::CFGuard_Check)
343Register AArch64FastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
345 "Alloca should always return a pointer.");
348 auto SI = FuncInfo.StaticAllocaMap.find(AI);
349 if (SI == FuncInfo.StaticAllocaMap.end())
352 if (SI != FuncInfo.StaticAllocaMap.end()) {
353 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
354 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
365Register AArch64FastISel::materializeInt(
const ConstantInt *CI, MVT VT) {
373 const TargetRegisterClass *RC = (VT == MVT::i64) ? &AArch64::GPR64RegClass
374 : &AArch64::GPR32RegClass;
375 unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
376 Register ResultReg = createResultReg(RC);
377 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
382Register AArch64FastISel::materializeFP(
const ConstantFP *CFP, MVT VT) {
386 return fastMaterializeFloatZero(CFP);
388 if (VT != MVT::f32 && VT != MVT::f64)
392 bool Is64Bit = (VT == MVT::f64);
398 unsigned Opc = Is64Bit ? AArch64::FMOVDi : AArch64::FMOVSi;
399 return fastEmitInst_i(
Opc, TLI.getRegClassFor(VT), Imm);
404 unsigned Opc1 = Is64Bit ? AArch64::MOVi64imm : AArch64::MOVi32imm;
405 const TargetRegisterClass *RC = Is64Bit ?
406 &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
408 Register TmpReg = createResultReg(RC);
409 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc1), TmpReg)
410 .addImm(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
412 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
413 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
414 TII.get(TargetOpcode::COPY), ResultReg)
415 .addReg(TmpReg, getKillRegState(true));
422 Align Alignment =
DL.getPrefTypeAlign(CFP->
getType());
424 unsigned CPI = MCP.getConstantPoolIndex(
cast<Constant>(CFP), Alignment);
425 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
426 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
429 unsigned Opc = Is64Bit ? AArch64::LDRDui : AArch64::LDRSui;
430 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
431 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
437Register AArch64FastISel::materializeGV(
const GlobalValue *GV) {
447 if (FuncInfo.MF->getInfo<AArch64FunctionInfo>()->hasELFSignedGOT())
452 EVT DestEVT = TLI.getValueType(
DL, GV->
getType(),
true);
456 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
461 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
467 ResultReg = createResultReg(&AArch64::GPR32RegClass);
468 LdrOpc = AArch64::LDRWui;
470 ResultReg = createResultReg(&AArch64::GPR64RegClass);
471 LdrOpc = AArch64::LDRXui;
473 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(LdrOpc),
483 Register Result64 = createResultReg(&AArch64::GPR64RegClass);
484 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
485 TII.get(TargetOpcode::SUBREG_TO_REG))
487 .
addReg(ResultReg, RegState::Kill)
492 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
510 Register DstReg = createResultReg(&AArch64::GPR64commonRegClass);
511 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::MOVKXi),
520 ResultReg = createResultReg(&AArch64::GPR64spRegClass);
521 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
531Register AArch64FastISel::fastMaterializeConstant(
const Constant *
C) {
532 EVT CEVT = TLI.getValueType(
DL,
C->getType(),
true);
541 if (
C->getType()->isVectorTy())
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 auto SI = FuncInfo.StaticAllocaMap.find(AI);
680 if (SI != FuncInfo.StaticAllocaMap.end()) {
681 Addr.setKind(Address::FrameIndexBase);
682 Addr.setFI(
SI->second);
687 case Instruction::Add: {
697 return computeAddress(
LHS, Addr, Ty);
701 if (computeAddress(
LHS, Addr, Ty) && computeAddress(
RHS, Addr, Ty))
707 case Instruction::Sub: {
714 return computeAddress(
LHS, Addr, Ty);
718 case Instruction::Shl: {
719 if (Addr.getOffsetReg())
727 if (Val < 1 || Val > 3)
730 uint64_t NumBytes = 0;
732 uint64_t NumBits =
DL.getTypeSizeInBits(Ty);
733 NumBytes = NumBits / 8;
738 if (NumBytes != (1ULL << Val))
744 const Value *Src =
U->getOperand(0);
746 if (FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
750 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
752 Src = ZE->getOperand(0);
756 SE->getOperand(0)->getType()->isIntegerTy(32)) {
758 Src = SE->getOperand(0);
765 if (AI->
getOpcode() == Instruction::And) {
770 if (
C->getValue() == 0xffffffff)
774 if (
C->getValue() == 0xffffffff) {
779 Reg = fastEmitInst_extractsubreg(MVT::i32,
Reg, AArch64::sub_32);
780 Addr.setOffsetReg(
Reg);
788 Addr.setOffsetReg(
Reg);
791 case Instruction::Mul: {
792 if (Addr.getOffsetReg())
803 if (
C->getValue().isPowerOf2())
808 unsigned Val =
C->getValue().logBase2();
809 if (Val < 1 || Val > 3)
812 uint64_t NumBytes = 0;
814 uint64_t NumBits =
DL.getTypeSizeInBits(Ty);
815 NumBytes = NumBits / 8;
820 if (NumBytes != (1ULL << Val))
828 if (FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
832 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
834 Src = ZE->getOperand(0);
838 SE->getOperand(0)->getType()->isIntegerTy(32)) {
840 Src = SE->getOperand(0);
849 Addr.setOffsetReg(
Reg);
852 case Instruction::And: {
853 if (Addr.getOffsetReg())
856 if (!Ty ||
DL.getTypeSizeInBits(Ty) != 8)
863 if (
C->getValue() == 0xffffffff)
867 if (
C->getValue() == 0xffffffff) {
875 Reg = fastEmitInst_extractsubreg(MVT::i32,
Reg, AArch64::sub_32);
876 Addr.setOffsetReg(
Reg);
881 case Instruction::SExt:
882 case Instruction::ZExt: {
883 if (!Addr.getReg() || Addr.getOffsetReg())
886 const Value *Src =
nullptr;
889 if (!
isIntExtFree(ZE) && ZE->getOperand(0)->getType()->isIntegerTy(32)) {
891 Src = ZE->getOperand(0);
894 if (!
isIntExtFree(SE) && SE->getOperand(0)->getType()->isIntegerTy(32)) {
896 Src = SE->getOperand(0);
907 Addr.setOffsetReg(
Reg);
912 if (Addr.isRegBase() && !Addr.getReg()) {
920 if (!Addr.getOffsetReg()) {
924 Addr.setOffsetReg(
Reg);
931bool AArch64FastISel::computeCallAddress(
const Value *V,
Address &Addr) {
932 const User *
U =
nullptr;
933 unsigned Opcode = Instruction::UserOp1;
937 Opcode =
I->getOpcode();
939 InMBB =
I->getParent() == FuncInfo.MBB->getBasicBlock();
941 Opcode =
C->getOpcode();
947 case Instruction::BitCast:
950 return computeCallAddress(
U->getOperand(0), Addr);
952 case Instruction::IntToPtr:
955 TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
956 TLI.getPointerTy(
DL))
957 return computeCallAddress(
U->getOperand(0), Addr);
959 case Instruction::PtrToInt:
961 if (InMBB && TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
962 return computeCallAddress(
U->getOperand(0), Addr);
967 Addr.setGlobalValue(GV);
972 if (!Addr.getGlobalValue()) {
973 Addr.setReg(getRegForValue(V));
974 return Addr.getReg().isValid();
980bool AArch64FastISel::isTypeLegal(
Type *Ty, MVT &VT) {
981 EVT evt = TLI.getValueType(
DL, Ty,
true);
987 if (evt == MVT::Other || !evt.
isSimple())
997 return TLI.isTypeLegal(VT);
1004bool AArch64FastISel::isTypeSupported(
Type *Ty, MVT &VT,
bool IsVectorAllowed) {
1008 if (isTypeLegal(Ty, VT))
1013 if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)
1019bool AArch64FastISel::isValueAvailable(
const Value *V)
const {
1024 return FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB;
1027bool AArch64FastISel::simplifyAddress(
Address &Addr, MVT VT) {
1035 bool ImmediateOffsetNeedsLowering =
false;
1036 bool RegisterOffsetNeedsLowering =
false;
1037 int64_t
Offset = Addr.getOffset();
1039 ImmediateOffsetNeedsLowering =
true;
1040 else if (
Offset > 0 && !(
Offset & (ScaleFactor - 1)) &&
1042 ImmediateOffsetNeedsLowering =
true;
1047 if (!ImmediateOffsetNeedsLowering && Addr.getOffset() && Addr.getOffsetReg())
1048 RegisterOffsetNeedsLowering =
true;
1051 if (Addr.isRegBase() && Addr.getOffsetReg() && !Addr.getReg())
1052 RegisterOffsetNeedsLowering =
true;
1057 if ((ImmediateOffsetNeedsLowering || Addr.getOffsetReg()) && Addr.isFIBase())
1059 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
1060 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
1065 Addr.setKind(Address::RegBase);
1066 Addr.setReg(ResultReg);
1069 if (RegisterOffsetNeedsLowering) {
1071 if (Addr.getReg()) {
1074 ResultReg = emitAddSub_rx(
true, MVT::i64, Addr.getReg(),
1075 Addr.getOffsetReg(), Addr.getExtendType(),
1078 ResultReg = emitAddSub_rs(
true, MVT::i64, Addr.getReg(),
1083 ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1084 Addr.getShift(),
true);
1086 ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1087 Addr.getShift(),
false);
1089 ResultReg = emitLSL_ri(MVT::i64, MVT::i64, Addr.getOffsetReg(),
1095 Addr.setReg(ResultReg);
1096 Addr.setOffsetReg(0);
1103 if (ImmediateOffsetNeedsLowering) {
1107 ResultReg = emitAdd_ri_(MVT::i64, Addr.getReg(),
Offset);
1113 Addr.setReg(ResultReg);
1119void AArch64FastISel::addLoadStoreOperands(
Address &Addr,
1120 const MachineInstrBuilder &MIB,
1122 unsigned ScaleFactor,
1123 MachineMemOperand *MMO) {
1124 int64_t
Offset = Addr.getOffset() / ScaleFactor;
1126 if (Addr.isFIBase()) {
1127 int FI = Addr.getFI();
1130 MMO = FuncInfo.MF->getMachineMemOperand(
1132 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
1136 assert(Addr.isRegBase() &&
"Unexpected address kind.");
1143 if (Addr.getOffsetReg()) {
1144 assert(Addr.getOffset() == 0 &&
"Unexpected offset");
1147 MIB.
addReg(Addr.getReg());
1148 MIB.
addReg(Addr.getOffsetReg());
1150 MIB.
addImm(Addr.getShift() != 0);
1159Register AArch64FastISel::emitAddSub(
bool UseAdd, MVT RetVT,
const Value *
LHS,
1161 bool WantResult,
bool IsZExt) {
1163 bool NeedExtend =
false;
1198 if (
SI->getOpcode() == Instruction::Shl ||
1199 SI->getOpcode() == Instruction::LShr ||
1200 SI->getOpcode() == Instruction::AShr )
1208 LHSReg = emitIntExt(SrcVT, LHSReg, RetVT, IsZExt);
1212 uint64_t
Imm = IsZExt ?
C->getZExtValue() :
C->getSExtValue();
1213 if (
C->isNegative())
1214 ResultReg = emitAddSub_ri(!UseAdd, RetVT, LHSReg, -Imm, SetFlags,
1217 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, Imm, SetFlags,
1220 if (
C->isNullValue())
1221 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, 0, SetFlags, WantResult);
1228 isValueAvailable(
RHS)) {
1232 return emitAddSub_rx(UseAdd, RetVT, LHSReg, RHSReg, ExtendType, 0,
1233 SetFlags, WantResult);
1243 if (
C->getValue().isPowerOf2())
1248 Register RHSReg = getRegForValue(MulLHS);
1251 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg,
AArch64_AM::LSL,
1252 ShiftVal, SetFlags, WantResult);
1263 switch (
SI->getOpcode()) {
1269 uint64_t ShiftVal =
C->getZExtValue();
1271 Register RHSReg = getRegForValue(
SI->getOperand(0));
1274 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg, ShiftType,
1275 ShiftVal, SetFlags, WantResult);
1288 RHSReg = emitIntExt(SrcVT, RHSReg, RetVT, IsZExt);
1290 return emitAddSub_rr(UseAdd, RetVT, LHSReg, RHSReg, SetFlags, WantResult);
1293Register AArch64FastISel::emitAddSub_rr(
bool UseAdd, MVT RetVT,
Register LHSReg,
1296 assert(LHSReg && RHSReg &&
"Invalid register number.");
1298 if (LHSReg == AArch64::SP || LHSReg == AArch64::WSP ||
1299 RHSReg == AArch64::SP || RHSReg == AArch64::WSP)
1302 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1305 static const unsigned OpcTable[2][2][2] = {
1306 { { AArch64::SUBWrr, AArch64::SUBXrr },
1307 { AArch64::ADDWrr, AArch64::ADDXrr } },
1308 { { AArch64::SUBSWrr, AArch64::SUBSXrr },
1309 { AArch64::ADDSWrr, AArch64::ADDSXrr } }
1311 bool Is64Bit = RetVT == MVT::i64;
1312 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1313 const TargetRegisterClass *RC =
1314 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1317 ResultReg = createResultReg(RC);
1319 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1321 const MCInstrDesc &
II =
TII.get(
Opc);
1324 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1330Register AArch64FastISel::emitAddSub_ri(
bool UseAdd, MVT RetVT,
Register LHSReg,
1331 uint64_t Imm,
bool SetFlags,
1333 assert(LHSReg &&
"Invalid register number.");
1335 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1341 else if ((Imm & 0xfff000) == Imm) {
1347 static const unsigned OpcTable[2][2][2] = {
1348 { { AArch64::SUBWri, AArch64::SUBXri },
1349 { AArch64::ADDWri, AArch64::ADDXri } },
1350 { { AArch64::SUBSWri, AArch64::SUBSXri },
1351 { AArch64::ADDSWri, AArch64::ADDSXri } }
1353 bool Is64Bit = RetVT == MVT::i64;
1354 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1355 const TargetRegisterClass *RC;
1357 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1359 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1362 ResultReg = createResultReg(RC);
1364 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1366 const MCInstrDesc &
II =
TII.get(
Opc);
1368 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1375Register AArch64FastISel::emitAddSub_rs(
bool UseAdd, MVT RetVT,
Register LHSReg,
1378 uint64_t ShiftImm,
bool SetFlags,
1380 assert(LHSReg && RHSReg &&
"Invalid register number.");
1381 assert(LHSReg != AArch64::SP && LHSReg != AArch64::WSP &&
1382 RHSReg != AArch64::SP && RHSReg != AArch64::WSP);
1384 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1391 static const unsigned OpcTable[2][2][2] = {
1392 { { AArch64::SUBWrs, AArch64::SUBXrs },
1393 { AArch64::ADDWrs, AArch64::ADDXrs } },
1394 { { AArch64::SUBSWrs, AArch64::SUBSXrs },
1395 { AArch64::ADDSWrs, AArch64::ADDSXrs } }
1397 bool Is64Bit = RetVT == MVT::i64;
1398 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1399 const TargetRegisterClass *RC =
1400 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1403 ResultReg = createResultReg(RC);
1405 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1407 const MCInstrDesc &
II =
TII.get(
Opc);
1410 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1413 .
addImm(getShifterImm(ShiftType, ShiftImm));
1417Register AArch64FastISel::emitAddSub_rx(
bool UseAdd, MVT RetVT,
Register LHSReg,
1420 uint64_t ShiftImm,
bool SetFlags,
1422 assert(LHSReg && RHSReg &&
"Invalid register number.");
1423 assert(LHSReg != AArch64::XZR && LHSReg != AArch64::WZR &&
1424 RHSReg != AArch64::XZR && RHSReg != AArch64::WZR);
1426 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1432 static const unsigned OpcTable[2][2][2] = {
1433 { { AArch64::SUBWrx, AArch64::SUBXrx },
1434 { AArch64::ADDWrx, AArch64::ADDXrx } },
1435 { { AArch64::SUBSWrx, AArch64::SUBSXrx },
1436 { AArch64::ADDSWrx, AArch64::ADDSXrx } }
1438 bool Is64Bit = RetVT == MVT::i64;
1439 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1440 const TargetRegisterClass *RC =
nullptr;
1442 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1444 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1447 ResultReg = createResultReg(RC);
1449 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1451 const MCInstrDesc &
II =
TII.get(
Opc);
1454 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1457 .
addImm(getArithExtendImm(ExtType, ShiftImm));
1461bool AArch64FastISel::emitCmp(
const Value *
LHS,
const Value *
RHS,
bool IsZExt) {
1463 EVT EVT = TLI.getValueType(
DL, Ty,
true);
1476 return emitICmp(VT,
LHS,
RHS, IsZExt);
1479 return emitFCmp(VT,
LHS,
RHS);
1483bool AArch64FastISel::emitICmp(MVT RetVT,
const Value *
LHS,
const Value *
RHS,
1485 return emitSub(RetVT,
LHS,
RHS,
true,
false,
1490bool AArch64FastISel::emitICmp_ri(MVT RetVT,
Register LHSReg, uint64_t Imm) {
1491 return emitAddSub_ri(
false, RetVT, LHSReg, Imm,
1496bool AArch64FastISel::emitFCmp(MVT RetVT,
const Value *
LHS,
const Value *
RHS) {
1497 if (RetVT != MVT::f32 && RetVT != MVT::f64)
1502 bool UseImm =
false;
1512 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDri : AArch64::FCMPSri;
1513 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1522 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDrr : AArch64::FCMPSrr;
1523 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1530 bool SetFlags,
bool WantResult,
bool IsZExt) {
1531 return emitAddSub(
true, RetVT,
LHS,
RHS, SetFlags, WantResult,
1543 ResultReg = emitAddSub_ri(
false, VT, Op0, -Imm);
1545 ResultReg = emitAddSub_ri(
true, VT, Op0, Imm);
1554 ResultReg = emitAddSub_rr(
true, VT, Op0, CReg);
1559 bool SetFlags,
bool WantResult,
bool IsZExt) {
1560 return emitAddSub(
false, RetVT,
LHS,
RHS, SetFlags, WantResult,
1565 Register RHSReg,
bool WantResult) {
1566 return emitAddSub_rr(
false, RetVT, LHSReg, RHSReg,
1573 uint64_t ShiftImm,
bool WantResult) {
1574 return emitAddSub_rs(
false, RetVT, LHSReg, RHSReg, ShiftType,
1575 ShiftImm,
true, WantResult);
1578Register AArch64FastISel::emitLogicalOp(
unsigned ISDOpc, MVT RetVT,
1601 uint64_t
Imm =
C->getZExtValue();
1602 ResultReg = emitLogicalOp_ri(ISDOpc, RetVT, LHSReg, Imm);
1614 if (
C->getValue().isPowerOf2())
1620 Register RHSReg = getRegForValue(MulLHS);
1623 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);
1633 uint64_t ShiftVal =
C->getZExtValue();
1634 Register RHSReg = getRegForValue(
SI->getOperand(0));
1637 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);
1647 MVT VT = std::max(MVT::i32, RetVT.
SimpleTy);
1648 ResultReg = fastEmit_rr(VT, VT, ISDOpc, LHSReg, RHSReg);
1649 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1650 uint64_t
Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1651 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1656Register AArch64FastISel::emitLogicalOp_ri(
unsigned ISDOpc, MVT RetVT,
1659 "ISD nodes are not consecutive!");
1660 static const unsigned OpcTable[3][2] = {
1661 { AArch64::ANDWri, AArch64::ANDXri },
1662 { AArch64::ORRWri, AArch64::ORRXri },
1663 { AArch64::EORWri, AArch64::EORXri }
1665 const TargetRegisterClass *RC;
1676 Opc = OpcTable[Idx][0];
1677 RC = &AArch64::GPR32spRegClass;
1683 RC = &AArch64::GPR64spRegClass;
1692 fastEmitInst_ri(
Opc, RC, LHSReg,
1694 if (RetVT >= MVT::i8 && RetVT <= MVT::i16 && ISDOpc !=
ISD::AND) {
1695 uint64_t
Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1696 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1701Register AArch64FastISel::emitLogicalOp_rs(
unsigned ISDOpc, MVT RetVT,
1703 uint64_t ShiftImm) {
1705 "ISD nodes are not consecutive!");
1706 static const unsigned OpcTable[3][2] = {
1707 { AArch64::ANDWrs, AArch64::ANDXrs },
1708 { AArch64::ORRWrs, AArch64::ORRXrs },
1709 { AArch64::EORWrs, AArch64::EORXrs }
1716 const TargetRegisterClass *RC;
1726 RC = &AArch64::GPR32RegClass;
1730 RC = &AArch64::GPR64RegClass;
1734 fastEmitInst_rri(
Opc, RC, LHSReg, RHSReg,
1736 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1737 uint64_t
Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1738 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1743Register AArch64FastISel::emitAnd_ri(MVT RetVT,
Register LHSReg, uint64_t Imm) {
1744 return emitLogicalOp_ri(
ISD::AND, RetVT, LHSReg, Imm);
1748 bool WantZExt, MachineMemOperand *MMO) {
1749 if (!TLI.allowsMisalignedMemoryAccesses(VT))
1753 if (!simplifyAddress(Addr, VT))
1762 bool UseScaled =
true;
1763 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
1768 static const unsigned GPOpcTable[2][8][4] = {
1770 { { AArch64::LDURSBWi, AArch64::LDURSHWi, AArch64::LDURWi,
1772 { AArch64::LDURSBXi, AArch64::LDURSHXi, AArch64::LDURSWi,
1774 { AArch64::LDRSBWui, AArch64::LDRSHWui, AArch64::LDRWui,
1776 { AArch64::LDRSBXui, AArch64::LDRSHXui, AArch64::LDRSWui,
1778 { AArch64::LDRSBWroX, AArch64::LDRSHWroX, AArch64::LDRWroX,
1780 { AArch64::LDRSBXroX, AArch64::LDRSHXroX, AArch64::LDRSWroX,
1782 { AArch64::LDRSBWroW, AArch64::LDRSHWroW, AArch64::LDRWroW,
1784 { AArch64::LDRSBXroW, AArch64::LDRSHXroW, AArch64::LDRSWroW,
1788 { { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1790 { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1792 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1794 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1796 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1798 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1800 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1802 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1807 static const unsigned FPOpcTable[4][2] = {
1808 { AArch64::LDURSi, AArch64::LDURDi },
1809 { AArch64::LDRSui, AArch64::LDRDui },
1810 { AArch64::LDRSroX, AArch64::LDRDroX },
1811 { AArch64::LDRSroW, AArch64::LDRDroW }
1815 const TargetRegisterClass *RC;
1816 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
1817 Addr.getOffsetReg();
1818 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
1823 bool IsRet64Bit = RetVT == MVT::i64;
1829 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][0];
1830 RC = (IsRet64Bit && !WantZExt) ?
1831 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1834 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][1];
1835 RC = (IsRet64Bit && !WantZExt) ?
1836 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1839 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][2];
1840 RC = (IsRet64Bit && !WantZExt) ?
1841 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1844 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][3];
1845 RC = &AArch64::GPR64RegClass;
1848 Opc = FPOpcTable[Idx][0];
1849 RC = &AArch64::FPR32RegClass;
1852 Opc = FPOpcTable[Idx][1];
1853 RC = &AArch64::FPR64RegClass;
1858 Register ResultReg = createResultReg(RC);
1859 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1860 TII.get(
Opc), ResultReg);
1864 if (VT == MVT::i1) {
1865 Register ANDReg = emitAnd_ri(MVT::i32, ResultReg, 1);
1866 assert(ANDReg &&
"Unexpected AND instruction emission failure.");
1872 if (WantZExt && RetVT == MVT::i64 && VT <= MVT::i32) {
1873 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
1874 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1875 TII.get(AArch64::SUBREG_TO_REG), Reg64)
1877 .
addImm(AArch64::sub_32);
1883bool AArch64FastISel::selectAddSub(
const Instruction *
I) {
1885 if (!isTypeSupported(
I->getType(), VT,
true))
1889 return selectOperator(
I,
I->getOpcode());
1892 switch (
I->getOpcode()) {
1895 case Instruction::Add:
1896 ResultReg = emitAdd(VT,
I->getOperand(0),
I->getOperand(1));
1898 case Instruction::Sub:
1899 ResultReg = emitSub(VT,
I->getOperand(0),
I->getOperand(1));
1905 updateValueMap(
I, ResultReg);
1909bool AArch64FastISel::selectLogicalOp(
const Instruction *
I) {
1911 if (!isTypeSupported(
I->getType(), VT,
true))
1915 return selectOperator(
I,
I->getOpcode());
1918 switch (
I->getOpcode()) {
1921 case Instruction::And:
1922 ResultReg = emitLogicalOp(
ISD::AND, VT,
I->getOperand(0),
I->getOperand(1));
1924 case Instruction::Or:
1925 ResultReg = emitLogicalOp(
ISD::OR, VT,
I->getOperand(0),
I->getOperand(1));
1927 case Instruction::Xor:
1928 ResultReg = emitLogicalOp(
ISD::XOR, VT,
I->getOperand(0),
I->getOperand(1));
1934 updateValueMap(
I, ResultReg);
1938bool AArch64FastISel::selectLoad(
const Instruction *
I) {
1943 if (!isTypeSupported(
I->getType(), VT,
true) ||
1947 const Value *SV =
I->getOperand(0);
1948 if (TLI.supportSwiftError()) {
1952 if (Arg->hasSwiftErrorAttr())
1957 if (Alloca->isSwiftError())
1964 if (!computeAddress(
I->getOperand(0), Addr,
I->getType()))
1968 bool WantZExt =
true;
1970 const Value *IntExtVal =
nullptr;
1971 if (
I->hasOneUse()) {
1973 if (isTypeSupported(ZE->getType(), RetVT))
1978 if (isTypeSupported(SE->getType(), RetVT))
1987 emitLoad(VT, RetVT, Addr, WantZExt, createMachineMemOperandFor(
I));
2008 auto *
MI = MRI.getUniqueVRegDef(
Reg);
2010 if (RetVT == MVT::i64 && VT <= MVT::i32) {
2014 ResultReg = std::prev(
I)->getOperand(0).getReg();
2015 removeDeadCode(
I, std::next(
I));
2017 ResultReg = fastEmitInst_extractsubreg(MVT::i32, ResultReg,
2020 updateValueMap(
I, ResultReg);
2029 for (
auto &Opnd :
MI->uses()) {
2031 Reg = Opnd.getReg();
2036 removeDeadCode(
I, std::next(
I));
2039 MI = MRI.getUniqueVRegDef(
Reg);
2041 updateValueMap(IntExtVal, ResultReg);
2045 updateValueMap(
I, ResultReg);
2049bool AArch64FastISel::emitStoreRelease(MVT VT,
Register SrcReg,
2051 MachineMemOperand *MMO) {
2054 default:
return false;
2055 case MVT::i8:
Opc = AArch64::STLRB;
break;
2056 case MVT::i16:
Opc = AArch64::STLRH;
break;
2057 case MVT::i32:
Opc = AArch64::STLRW;
break;
2058 case MVT::i64:
Opc = AArch64::STLRX;
break;
2061 const MCInstrDesc &
II =
TII.get(
Opc);
2064 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2072 MachineMemOperand *MMO) {
2073 if (!TLI.allowsMisalignedMemoryAccesses(VT))
2077 if (!simplifyAddress(Addr, VT))
2086 bool UseScaled =
true;
2087 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
2092 static const unsigned OpcTable[4][6] = {
2093 { AArch64::STURBBi, AArch64::STURHHi, AArch64::STURWi, AArch64::STURXi,
2094 AArch64::STURSi, AArch64::STURDi },
2095 { AArch64::STRBBui, AArch64::STRHHui, AArch64::STRWui, AArch64::STRXui,
2096 AArch64::STRSui, AArch64::STRDui },
2097 { AArch64::STRBBroX, AArch64::STRHHroX, AArch64::STRWroX, AArch64::STRXroX,
2098 AArch64::STRSroX, AArch64::STRDroX },
2099 { AArch64::STRBBroW, AArch64::STRHHroW, AArch64::STRWroW, AArch64::STRXroW,
2100 AArch64::STRSroW, AArch64::STRDroW }
2104 bool VTIsi1 =
false;
2105 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
2106 Addr.getOffsetReg();
2107 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
2114 case MVT::i1: VTIsi1 =
true; [[fallthrough]];
2115 case MVT::i8:
Opc = OpcTable[Idx][0];
break;
2116 case MVT::i16:
Opc = OpcTable[Idx][1];
break;
2117 case MVT::i32:
Opc = OpcTable[Idx][2];
break;
2118 case MVT::i64:
Opc = OpcTable[Idx][3];
break;
2119 case MVT::f32:
Opc = OpcTable[Idx][4];
break;
2120 case MVT::f64:
Opc = OpcTable[Idx][5];
break;
2124 if (VTIsi1 && SrcReg != AArch64::WZR) {
2125 Register ANDReg = emitAnd_ri(MVT::i32, SrcReg, 1);
2126 assert(ANDReg &&
"Unexpected AND instruction emission failure.");
2130 const MCInstrDesc &
II =
TII.get(
Opc);
2132 MachineInstrBuilder MIB =
2139bool AArch64FastISel::selectStore(
const Instruction *
I) {
2141 const Value *Op0 =
I->getOperand(0);
2145 if (!isTypeSupported(Op0->
getType(), VT,
true))
2148 const Value *PtrV =
I->getOperand(1);
2149 if (TLI.supportSwiftError()) {
2153 if (Arg->hasSwiftErrorAttr())
2158 if (Alloca->isSwiftError())
2168 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2170 if (CF->isZero() && !CF->isNegative()) {
2172 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2177 SrcReg = getRegForValue(Op0);
2185 if (
SI->isAtomic()) {
2190 Register AddrReg = getRegForValue(PtrV);
2193 return emitStoreRelease(VT, SrcReg, AddrReg,
2194 createMachineMemOperandFor(
I));
2200 if (!computeAddress(PtrV, Addr, Op0->
getType()))
2203 if (!
emitStore(VT, SrcReg, Addr, createMachineMemOperandFor(
I)))
2255bool AArch64FastISel::emitCompareAndBranch(
const CondBrInst *BI) {
2259 if (FuncInfo.MF->getFunction().hasFnAttribute(
2260 Attribute::SpeculativeLoadHardening))
2279 MachineBasicBlock *FBB = FuncInfo.getMBB(BI->
getSuccessor(1));
2282 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2289 switch (Predicate) {
2301 if (AI->
getOpcode() == Instruction::And && isValueAvailable(AI)) {
2306 if (
C->getValue().isPowerOf2())
2310 if (
C->getValue().isPowerOf2()) {
2311 TestBit =
C->getValue().logBase2();
2342 static const unsigned OpcTable[2][2][2] = {
2343 { {AArch64::CBZW, AArch64::CBZX },
2344 {AArch64::CBNZW, AArch64::CBNZX} },
2345 { {AArch64::TBZW, AArch64::TBZX },
2346 {AArch64::TBNZW, AArch64::TBNZX} }
2349 bool IsBitTest = TestBit != -1;
2350 bool Is64Bit = BW == 64;
2351 if (TestBit < 32 && TestBit >= 0)
2354 unsigned Opc = OpcTable[IsBitTest][IsCmpNE][Is64Bit];
2355 const MCInstrDesc &
II =
TII.get(
Opc);
2361 if (BW == 64 && !Is64Bit)
2362 SrcReg = fastEmitInst_extractsubreg(MVT::i32, SrcReg, AArch64::sub_32);
2364 if ((BW < 32) && !IsBitTest)
2365 SrcReg = emitIntExt(VT, SrcReg, MVT::i32,
true);
2369 MachineInstrBuilder MIB =
2370 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
2376 finishCondBranch(BI->getParent(),
TBB, FBB);
2380bool AArch64FastISel::selectBranch(
const Instruction *
I) {
2384 MachineBasicBlock *FBB = FuncInfo.getMBB(BI->
getSuccessor(1));
2387 if (CI->
hasOneUse() && isValueAvailable(CI)) {
2390 switch (Predicate) {
2394 fastEmitBranch(FBB, MIMD.getDL());
2397 fastEmitBranch(
TBB, MIMD.getDL());
2402 if (emitCompareAndBranch(BI))
2406 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2419 switch (Predicate) {
2435 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2441 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2445 finishCondBranch(BI->getParent(),
TBB, FBB);
2449 uint64_t
Imm = CI->getZExtValue();
2451 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::B))
2456 auto BranchProbability = FuncInfo.BPI->getEdgeProbability(
2457 BI->getParent(),
Target->getBasicBlock());
2458 FuncInfo.MBB->addSuccessor(Target, BranchProbability);
2460 FuncInfo.MBB->addSuccessorWithoutProb(Target);
2472 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2476 finishCondBranch(BI->getParent(),
TBB, FBB);
2486 unsigned Opcode = AArch64::TBNZW;
2487 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2489 Opcode = AArch64::TBZW;
2492 const MCInstrDesc &
II =
TII.get(Opcode);
2495 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2496 .
addReg(ConstrainedCondReg)
2500 finishCondBranch(BI->getParent(),
TBB, FBB);
2504bool AArch64FastISel::selectIndirectBr(
const Instruction *
I) {
2511 if (FuncInfo.MF->getFunction().hasFnAttribute(
"ptrauth-indirect-gotos"))
2515 const MCInstrDesc &
II =
TII.get(AArch64::BR);
2521 FuncInfo.MBB->addSuccessor(FuncInfo.getMBB(Succ));
2526bool AArch64FastISel::selectCmp(
const Instruction *
I) {
2536 switch (Predicate) {
2540 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2541 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2542 TII.get(TargetOpcode::COPY), ResultReg)
2546 ResultReg = fastEmit_i(MVT::i32, MVT::i32,
ISD::Constant, 1);
2551 updateValueMap(
I, ResultReg);
2559 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2563 static unsigned CondCodeTable[2][2] = {
2568 switch (Predicate) {
2580 Register TmpReg1 = createResultReg(&AArch64::GPR32RegClass);
2581 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2586 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2592 updateValueMap(
I, ResultReg);
2600 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2606 updateValueMap(
I, ResultReg);
2612bool AArch64FastISel::optimizeSelect(
const SelectInst *SI) {
2613 if (!
SI->getType()->isIntegerTy(1))
2616 const Value *Src1Val, *Src2Val;
2618 bool NeedExtraOp =
false;
2621 Src1Val =
SI->getCondition();
2622 Src2Val =
SI->getFalseValue();
2623 Opc = AArch64::ORRWrr;
2626 Src1Val =
SI->getFalseValue();
2627 Src2Val =
SI->getCondition();
2628 Opc = AArch64::BICWrr;
2632 Src1Val =
SI->getCondition();
2633 Src2Val =
SI->getTrueValue();
2634 Opc = AArch64::ORRWrr;
2638 Src1Val =
SI->getCondition();
2639 Src2Val =
SI->getTrueValue();
2640 Opc = AArch64::ANDWrr;
2647 Register Src1Reg = getRegForValue(Src1Val);
2651 Register Src2Reg = getRegForValue(Src2Val);
2656 Src1Reg = emitLogicalOp_ri(
ISD::XOR, MVT::i32, Src1Reg, 1);
2658 Register ResultReg = fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, Src1Reg,
2660 updateValueMap(SI, ResultReg);
2664bool AArch64FastISel::selectSelect(
const Instruction *
I) {
2667 if (!isTypeSupported(
I->getType(), VT))
2671 const TargetRegisterClass *RC;
2679 Opc = AArch64::CSELWr;
2680 RC = &AArch64::GPR32RegClass;
2683 Opc = AArch64::CSELXr;
2684 RC = &AArch64::GPR64RegClass;
2687 Opc = AArch64::FCSELSrrr;
2688 RC = &AArch64::FPR32RegClass;
2691 Opc = AArch64::FCSELDrrr;
2692 RC = &AArch64::FPR64RegClass;
2701 if (optimizeSelect(SI))
2705 if (foldXALUIntrinsic(CC,
I,
Cond)) {
2711 isValueAvailable(
Cond)) {
2715 const Value *FoldSelect =
nullptr;
2716 switch (Predicate) {
2720 FoldSelect =
SI->getFalseValue();
2723 FoldSelect =
SI->getTrueValue();
2728 Register SrcReg = getRegForValue(FoldSelect);
2732 updateValueMap(
I, SrcReg);
2742 switch (Predicate) {
2760 const MCInstrDesc &
II =
TII.get(AArch64::ANDSWri);
2764 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II,
2770 Register Src1Reg = getRegForValue(
SI->getTrueValue());
2771 Register Src2Reg = getRegForValue(
SI->getFalseValue());
2773 if (!Src1Reg || !Src2Reg)
2777 Src2Reg = fastEmitInst_rri(
Opc, RC, Src1Reg, Src2Reg, ExtraCC);
2779 Register ResultReg = fastEmitInst_rri(
Opc, RC, Src1Reg, Src2Reg, CC);
2780 updateValueMap(
I, ResultReg);
2784bool AArch64FastISel::selectFPExt(
const Instruction *
I) {
2786 if (!
I->getType()->isDoubleTy() || !
V->getType()->isFloatTy())
2793 Register ResultReg = createResultReg(&AArch64::FPR64RegClass);
2794 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTDSr),
2796 updateValueMap(
I, ResultReg);
2800bool AArch64FastISel::selectFPTrunc(
const Instruction *
I) {
2802 if (!
I->getType()->isFloatTy() || !
V->getType()->isDoubleTy())
2809 Register ResultReg = createResultReg(&AArch64::FPR32RegClass);
2810 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTSDr),
2812 updateValueMap(
I, ResultReg);
2817bool AArch64FastISel::selectFPToInt(
const Instruction *
I,
bool Signed) {
2819 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2822 Register SrcReg = getRegForValue(
I->getOperand(0));
2826 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2827 if (SrcVT == MVT::f128 || SrcVT == MVT::f16 || SrcVT == MVT::bf16)
2831 if (SrcVT == MVT::f64) {
2833 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWDr : AArch64::FCVTZSUXDr;
2835 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWDr : AArch64::FCVTZUUXDr;
2838 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWSr : AArch64::FCVTZSUXSr;
2840 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWSr : AArch64::FCVTZUUXSr;
2842 Register ResultReg = createResultReg(
2843 DestVT == MVT::i32 ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass);
2844 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
2846 updateValueMap(
I, ResultReg);
2850bool AArch64FastISel::selectIntToFP(
const Instruction *
I,
bool Signed) {
2852 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2855 if (DestVT == MVT::f16 || DestVT == MVT::bf16)
2858 assert((DestVT == MVT::f32 || DestVT == MVT::f64) &&
2859 "Unexpected value type.");
2861 Register SrcReg = getRegForValue(
I->getOperand(0));
2865 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2868 if (SrcVT == MVT::i16 || SrcVT == MVT::i8 || SrcVT == MVT::i1) {
2876 if (SrcVT == MVT::i64) {
2878 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUXSri : AArch64::SCVTFUXDri;
2880 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUXSri : AArch64::UCVTFUXDri;
2883 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUWSri : AArch64::SCVTFUWDri;
2885 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUWSri : AArch64::UCVTFUWDri;
2888 Register ResultReg = fastEmitInst_r(
Opc, TLI.getRegClassFor(DestVT), SrcReg);
2889 updateValueMap(
I, ResultReg);
2893bool AArch64FastISel::fastLowerArguments() {
2894 if (!FuncInfo.CanLowerReturn)
2901 CallingConv::ID CC =
F->getCallingConv();
2902 if (CC != CallingConv::C && CC != CallingConv::Swift)
2909 unsigned GPRCnt = 0;
2910 unsigned FPRCnt = 0;
2911 for (
auto const &Arg :
F->args()) {
2912 if (Arg.hasAttribute(Attribute::ByVal) ||
2913 Arg.hasAttribute(Attribute::InReg) ||
2914 Arg.hasAttribute(Attribute::StructRet) ||
2915 Arg.hasAttribute(Attribute::SwiftSelf) ||
2916 Arg.hasAttribute(Attribute::SwiftAsync) ||
2917 Arg.hasAttribute(Attribute::SwiftError) ||
2918 Arg.hasAttribute(Attribute::Nest))
2921 Type *ArgTy = Arg.getType();
2925 EVT ArgVT = TLI.getValueType(
DL, ArgTy);
2937 if (VT >= MVT::i1 && VT <= MVT::i64)
2939 else if ((VT >= MVT::f16 && VT <= MVT::f64) || VT.
is64BitVector() ||
2945 if (GPRCnt > 8 || FPRCnt > 8)
2950 { AArch64::W0, AArch64::W1, AArch64::W2, AArch64::W3, AArch64::W4,
2951 AArch64::W5, AArch64::W6, AArch64::W7 },
2952 { AArch64::X0, AArch64::X1, AArch64::X2, AArch64::X3, AArch64::X4,
2953 AArch64::X5, AArch64::X6, AArch64::X7 },
2954 { AArch64::H0, AArch64::H1, AArch64::H2, AArch64::H3, AArch64::H4,
2955 AArch64::H5, AArch64::H6, AArch64::H7 },
2956 { AArch64::S0, AArch64::S1, AArch64::S2, AArch64::S3, AArch64::S4,
2957 AArch64::S5, AArch64::S6, AArch64::S7 },
2958 { AArch64::D0, AArch64::D1, AArch64::D2, AArch64::D3, AArch64::D4,
2959 AArch64::D5, AArch64::D6, AArch64::D7 },
2960 { AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,
2961 AArch64::Q5, AArch64::Q6, AArch64::Q7 }
2964 unsigned GPRIdx = 0;
2965 unsigned FPRIdx = 0;
2966 for (
auto const &Arg :
F->args()) {
2967 MVT VT = TLI.getSimpleValueType(
DL, Arg.getType());
2969 const TargetRegisterClass *RC;
2970 if (VT >= MVT::i1 && VT <= MVT::i32) {
2972 RC = &AArch64::GPR32RegClass;
2974 }
else if (VT == MVT::i64) {
2976 RC = &AArch64::GPR64RegClass;
2977 }
else if (VT == MVT::f16 || VT == MVT::bf16) {
2979 RC = &AArch64::FPR16RegClass;
2980 }
else if (VT == MVT::f32) {
2982 RC = &AArch64::FPR32RegClass;
2985 RC = &AArch64::FPR64RegClass;
2988 RC = &AArch64::FPR128RegClass;
2992 Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
2996 Register ResultReg = createResultReg(RC);
2997 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2998 TII.get(TargetOpcode::COPY), ResultReg)
3000 updateValueMap(&Arg, ResultReg);
3005bool AArch64FastISel::processCallArgs(CallLoweringInfo &CLI,
3006 SmallVectorImpl<MVT> &OutVTs,
3007 SmallVectorImpl<Type *> &OrigTys,
3008 unsigned &NumBytes) {
3009 CallingConv::ID CC = CLI.CallConv;
3011 CCState CCInfo(CC,
false, *FuncInfo.MF, ArgLocs, *
Context);
3012 CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, OrigTys,
3013 CCAssignFnForCall(CC));
3016 NumBytes = CCInfo.getStackSize();
3019 unsigned AdjStackDown =
TII.getCallFrameSetupOpcode();
3020 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackDown))
3024 for (CCValAssign &VA : ArgLocs) {
3025 const Value *ArgVal = CLI.OutVals[VA.getValNo()];
3026 MVT ArgVT = OutVTs[VA.getValNo()];
3028 Register ArgReg = getRegForValue(ArgVal);
3033 switch (VA.getLocInfo()) {
3037 MVT DestVT = VA.getLocVT();
3039 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
false);
3047 MVT DestVT = VA.getLocVT();
3049 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
true);
3059 if (VA.isRegLoc() && !VA.needsCustom()) {
3060 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3061 TII.get(TargetOpcode::COPY), VA.getLocReg()).
addReg(ArgReg);
3062 CLI.OutRegs.push_back(VA.getLocReg());
3063 }
else if (VA.needsCustom()) {
3067 assert(VA.isMemLoc() &&
"Assuming store on stack.");
3076 unsigned BEAlign = 0;
3077 if (ArgSize < 8 && !Subtarget->isLittleEndian())
3078 BEAlign = 8 - ArgSize;
3081 Addr.setKind(Address::RegBase);
3082 Addr.setReg(AArch64::SP);
3083 Addr.setOffset(VA.getLocMemOffset() + BEAlign);
3086 MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
3090 if (!
emitStore(ArgVT, ArgReg, Addr, MMO))
3097bool AArch64FastISel::finishCall(CallLoweringInfo &CLI,
unsigned NumBytes) {
3098 CallingConv::ID CC = CLI.CallConv;
3101 unsigned AdjStackUp =
TII.getCallFrameDestroyOpcode();
3102 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackUp))
3107 CCState CCInfo(CC,
false, *FuncInfo.MF, RVLocs, *
Context);
3108 CCInfo.AnalyzeCallResult(CLI.Ins, CCAssignFnForCall(CC));
3110 Register ResultReg = FuncInfo.CreateRegs(CLI.RetTy);
3111 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
3112 CCValAssign &VA = RVLocs[i];
3121 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
3127 CLI.ResultReg = ResultReg;
3128 CLI.NumResultRegs = RVLocs.
size();
3133bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
3134 CallingConv::ID CC = CLI.CallConv;
3135 bool IsTailCall = CLI.IsTailCall;
3136 bool IsVarArg = CLI.IsVarArg;
3140 if (!Callee && !Symbol)
3145 if (CLI.CB && CLI.CB->hasFnAttr(Attribute::ReturnsTwice) &&
3146 !Subtarget->noBTIAtReturnTwice() &&
3147 MF->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement())
3151 if (CLI.CB && CLI.CB->isIndirectCall() &&
3175 if (MF->getFunction().getParent()->getRtLibUseGOT())
3185 for (
auto Flag : CLI.OutFlags)
3187 Flag.isSwiftSelf() ||
Flag.isSwiftAsync() ||
Flag.isSwiftError())
3193 OutVTs.
reserve(CLI.OutVals.size());
3195 for (
auto *Val : CLI.OutVals) {
3197 if (!isTypeLegal(Val->getType(), VT) &&
3198 !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16))
3210 if (Callee && !computeCallAddress(Callee, Addr))
3217 Addr.getGlobalValue()->hasExternalWeakLinkage())
3222 if (!processCallArgs(CLI, OutVTs, OrigTys, NumBytes))
3230 MachineInstrBuilder MIB;
3232 const MCInstrDesc &
II =
3234 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II);
3237 else if (Addr.getGlobalValue())
3239 else if (Addr.getReg()) {
3247 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
3248 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
3252 CallReg = createResultReg(&AArch64::GPR64RegClass);
3253 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3254 TII.get(AArch64::LDRXui), CallReg)
3258 }
else if (Addr.getGlobalValue())
3259 CallReg = materializeGV(Addr.getGlobalValue());
3260 else if (Addr.getReg())
3261 CallReg = Addr.getReg();
3268 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II).
addReg(CallReg);
3272 for (
auto Reg : CLI.OutRegs)
3282 return finishCall(CLI, NumBytes);
3285bool AArch64FastISel::isMemCpySmall(uint64_t Len, MaybeAlign Alignment) {
3287 return Len / Alignment->value() <= 4;
3292bool AArch64FastISel::tryEmitSmallMemCpy(
Address Dest,
Address Src,
3293 uint64_t Len, MaybeAlign Alignment) {
3295 if (!isMemCpySmall(Len, Alignment))
3298 int64_t UnscaledOffset = 0;
3304 if (!Alignment || *Alignment >= 8) {
3315 assert(Alignment &&
"Alignment is set in this branch");
3317 if (Len >= 4 && *Alignment == 4)
3319 else if (Len >= 2 && *Alignment == 2)
3335 UnscaledOffset +=
Size;
3338 Dest.setOffset(OrigDest.getOffset() + UnscaledOffset);
3339 Src.setOffset(OrigSrc.getOffset() + UnscaledOffset);
3348 const Instruction *
I,
3362 if (!isTypeLegal(RetTy, RetVT))
3365 if (RetVT != MVT::i32 && RetVT != MVT::i64)
3380 case Intrinsic::smul_with_overflow:
3382 if (
C->getValue() == 2)
3383 IID = Intrinsic::sadd_with_overflow;
3385 case Intrinsic::umul_with_overflow:
3387 if (
C->getValue() == 2)
3388 IID = Intrinsic::uadd_with_overflow;
3396 case Intrinsic::sadd_with_overflow:
3397 case Intrinsic::ssub_with_overflow:
3400 case Intrinsic::uadd_with_overflow:
3403 case Intrinsic::usub_with_overflow:
3406 case Intrinsic::smul_with_overflow:
3407 case Intrinsic::umul_with_overflow:
3413 if (!isValueAvailable(
II))
3419 for (
auto Itr = std::prev(Start); Itr != End; --Itr) {
3427 if (EVI->getAggregateOperand() !=
II)
3435bool AArch64FastISel::fastLowerIntrinsicCall(
const IntrinsicInst *
II) {
3437 switch (
II->getIntrinsicID()) {
3438 default:
return false;
3439 case Intrinsic::frameaddress: {
3440 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3445 Register SrcReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3446 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3456 DestReg = fastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,
3458 assert(DestReg &&
"Unexpected LDR instruction emission failure.");
3462 updateValueMap(
II, SrcReg);
3465 case Intrinsic::sponentry: {
3466 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3470 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
3471 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3472 TII.get(AArch64::ADDXri), ResultReg)
3477 updateValueMap(
II, ResultReg);
3480 case Intrinsic::memcpy:
3481 case Intrinsic::memmove: {
3484 if (MTI->isVolatile())
3489 bool IsMemCpy = (
II->getIntrinsicID() == Intrinsic::memcpy);
3494 MaybeAlign Alignment;
3495 if (MTI->getDestAlign() || MTI->getSourceAlign())
3496 Alignment = std::min(MTI->getDestAlign().valueOrOne(),
3497 MTI->getSourceAlign().valueOrOne());
3498 if (isMemCpySmall(Len, Alignment)) {
3500 if (!computeAddress(MTI->getRawDest(), Dest) ||
3501 !computeAddress(MTI->getRawSource(), Src))
3503 if (tryEmitSmallMemCpy(Dest, Src, Len, Alignment))
3508 if (!MTI->getLength()->getType()->isIntegerTy(64))
3511 if (MTI->getSourceAddressSpace() > 255 || MTI->getDestAddressSpace() > 255)
3517 return lowerCallTo(
II, IntrMemName,
II->arg_size() - 1);
3519 case Intrinsic::memset: {
3533 return lowerCallTo(
II,
"memset",
II->arg_size() - 1);
3535 case Intrinsic::sin:
3536 case Intrinsic::cos:
3537 case Intrinsic::tan:
3538 case Intrinsic::pow: {
3540 if (!isTypeLegal(
II->getType(), RetVT))
3543 if (RetVT != MVT::f32 && RetVT != MVT::f64)
3546 static const RTLIB::Libcall LibCallTable[4][2] = {
3547 {RTLIB::SIN_F32, RTLIB::SIN_F64},
3548 {RTLIB::COS_F32, RTLIB::COS_F64},
3549 {RTLIB::TAN_F32, RTLIB::TAN_F64},
3550 {RTLIB::POW_F32, RTLIB::POW_F64}};
3552 bool Is64Bit = RetVT == MVT::f64;
3553 switch (
II->getIntrinsicID()) {
3556 case Intrinsic::sin:
3557 LC = LibCallTable[0][Is64Bit];
3559 case Intrinsic::cos:
3560 LC = LibCallTable[1][Is64Bit];
3562 case Intrinsic::tan:
3563 LC = LibCallTable[2][Is64Bit];
3565 case Intrinsic::pow:
3566 LC = LibCallTable[3][Is64Bit];
3571 Args.reserve(
II->arg_size());
3574 for (
auto &Arg :
II->args())
3575 Args.emplace_back(Arg);
3577 CallLoweringInfo CLI;
3578 MCContext &Ctx = MF->getContext();
3580 RTLIB::LibcallImpl LCImpl = LibcallLowering->getLibcallImpl(LC);
3581 if (LCImpl == RTLIB::Unsupported)
3584 CallingConv::ID CC = LibcallLowering->getLibcallImplCallingConv(LCImpl);
3586 CLI.setCallee(
DL, Ctx, CC,
II->getType(), FuncName, std::move(Args));
3587 if (!lowerCallTo(CLI))
3589 updateValueMap(
II, CLI.ResultReg);
3592 case Intrinsic::fabs: {
3594 if (!isTypeLegal(
II->getType(), VT))
3602 Opc = AArch64::FABSSr;
3605 Opc = AArch64::FABSDr;
3608 Register SrcReg = getRegForValue(
II->getOperand(0));
3611 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3612 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
3614 updateValueMap(
II, ResultReg);
3617 case Intrinsic::trap:
3618 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3621 case Intrinsic::debugtrap:
3622 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3626 case Intrinsic::sqrt: {
3627 Type *RetTy =
II->getCalledFunction()->getReturnType();
3630 if (!isTypeLegal(RetTy, VT))
3633 Register Op0Reg = getRegForValue(
II->getOperand(0));
3641 updateValueMap(
II, ResultReg);
3644 case Intrinsic::sadd_with_overflow:
3645 case Intrinsic::uadd_with_overflow:
3646 case Intrinsic::ssub_with_overflow:
3647 case Intrinsic::usub_with_overflow:
3648 case Intrinsic::smul_with_overflow:
3649 case Intrinsic::umul_with_overflow: {
3653 Type *RetTy = Ty->getTypeAtIndex(0U);
3656 if (!isTypeLegal(RetTy, VT))
3659 if (VT != MVT::i32 && VT != MVT::i64)
3673 case Intrinsic::smul_with_overflow:
3675 if (
C->getValue() == 2) {
3676 IID = Intrinsic::sadd_with_overflow;
3680 case Intrinsic::umul_with_overflow:
3682 if (
C->getValue() == 2) {
3683 IID = Intrinsic::uadd_with_overflow;
3689 Register ResultReg1, ResultReg2, MulReg;
3693 case Intrinsic::sadd_with_overflow:
3694 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3697 case Intrinsic::uadd_with_overflow:
3698 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3701 case Intrinsic::ssub_with_overflow:
3702 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3705 case Intrinsic::usub_with_overflow:
3706 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3709 case Intrinsic::smul_with_overflow: {
3719 if (VT == MVT::i32) {
3720 MulReg = emitSMULL_rr(MVT::i64, LHSReg, RHSReg);
3722 fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3724 emitAddSub_rx(
false, MVT::i64, MulReg, MulSubReg,
3729 assert(VT == MVT::i64 &&
"Unexpected value type.");
3732 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3739 case Intrinsic::umul_with_overflow: {
3749 if (VT == MVT::i32) {
3750 MulReg = emitUMULL_rr(MVT::i64, LHSReg, RHSReg);
3752 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3753 TII.get(AArch64::ANDSXri), AArch64::XZR)
3756 MulReg = fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3758 assert(VT == MVT::i64 &&
"Unexpected value type.");
3761 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3763 emitSubs_rr(VT, AArch64::XZR, UMULHReg,
false);
3770 ResultReg1 = createResultReg(TLI.getRegClassFor(VT));
3771 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3772 TII.get(TargetOpcode::COPY), ResultReg1).
addReg(MulReg);
3778 ResultReg2 = fastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,
3779 AArch64::WZR, AArch64::WZR,
3780 getInvertedCondCode(CC));
3782 assert((ResultReg1 + 1) == ResultReg2 &&
3783 "Nonconsecutive result registers.");
3784 updateValueMap(
II, ResultReg1, 2);
3787 case Intrinsic::aarch64_crc32b:
3788 case Intrinsic::aarch64_crc32h:
3789 case Intrinsic::aarch64_crc32w:
3790 case Intrinsic::aarch64_crc32x:
3791 case Intrinsic::aarch64_crc32cb:
3792 case Intrinsic::aarch64_crc32ch:
3793 case Intrinsic::aarch64_crc32cw:
3794 case Intrinsic::aarch64_crc32cx: {
3795 if (!Subtarget->hasCRC())
3799 switch (
II->getIntrinsicID()) {
3802 case Intrinsic::aarch64_crc32b:
3803 Opc = AArch64::CRC32Brr;
3805 case Intrinsic::aarch64_crc32h:
3806 Opc = AArch64::CRC32Hrr;
3808 case Intrinsic::aarch64_crc32w:
3809 Opc = AArch64::CRC32Wrr;
3811 case Intrinsic::aarch64_crc32x:
3812 Opc = AArch64::CRC32Xrr;
3814 case Intrinsic::aarch64_crc32cb:
3815 Opc = AArch64::CRC32CBrr;
3817 case Intrinsic::aarch64_crc32ch:
3818 Opc = AArch64::CRC32CHrr;
3820 case Intrinsic::aarch64_crc32cw:
3821 Opc = AArch64::CRC32CWrr;
3823 case Intrinsic::aarch64_crc32cx:
3824 Opc = AArch64::CRC32CXrr;
3828 Register LHSReg = getRegForValue(
II->getArgOperand(0));
3829 Register RHSReg = getRegForValue(
II->getArgOperand(1));
3830 if (!LHSReg || !RHSReg)
3834 fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, LHSReg, RHSReg);
3835 updateValueMap(
II, ResultReg);
3842bool AArch64FastISel::selectRet(
const Instruction *
I) {
3844 const Function &
F = *
I->getParent()->getParent();
3846 if (!FuncInfo.CanLowerReturn)
3852 if (TLI.supportSwiftError() &&
3853 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
3856 if (TLI.supportSplitCSR(FuncInfo.MF))
3863 CallingConv::ID CC =
F.getCallingConv();
3869 CCState CCInfo(CC,
F.isVarArg(), *FuncInfo.MF, ValLocs,
I->getContext());
3873 if (ValLocs.
size() != 1)
3876 CCValAssign &VA = ValLocs[0];
3895 if (!MRI.getRegClass(SrcReg)->contains(DestReg))
3898 EVT RVEVT = TLI.getValueType(
DL, RV->
getType());
3908 if (RVVT == MVT::f128)
3913 if (RVVT != DestVT) {
3914 if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
3917 if (!Outs[0].
Flags.isZExt() && !Outs[0].Flags.isSExt())
3920 bool IsZExt = Outs[0].Flags.isZExt();
3921 SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
3929 SrcReg = emitAnd_ri(MVT::i64, SrcReg, 0xffffffff);
3932 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3933 TII.get(TargetOpcode::COPY), DestReg).
addReg(SrcReg);
3939 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3940 TII.get(AArch64::RET_ReallyLR));
3942 MIB.
addReg(RetReg, RegState::Implicit);
3946bool AArch64FastISel::selectTrunc(
const Instruction *
I) {
3947 Type *DestTy =
I->getType();
3949 Type *SrcTy =
Op->getType();
3951 EVT SrcEVT = TLI.getValueType(
DL, SrcTy,
true);
3952 EVT DestEVT = TLI.getValueType(
DL, DestTy,
true);
3961 if (SrcVT != MVT::i64 && SrcVT != MVT::i32 && SrcVT != MVT::i16 &&
3964 if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8 &&
3978 if (SrcVT == MVT::i64) {
3995 Register Reg32 = fastEmitInst_extractsubreg(MVT::i32, SrcReg,
3998 ResultReg = emitAnd_ri(MVT::i32, Reg32, Mask);
3999 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4001 ResultReg = createResultReg(&AArch64::GPR32RegClass);
4002 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4003 TII.get(TargetOpcode::COPY), ResultReg)
4007 updateValueMap(
I, ResultReg);
4011Register AArch64FastISel::emiti1Ext(
Register SrcReg, MVT DestVT,
bool IsZExt) {
4012 assert((DestVT == MVT::i8 || DestVT == MVT::i16 || DestVT == MVT::i32 ||
4013 DestVT == MVT::i64) &&
4014 "Unexpected value type.");
4016 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4020 Register ResultReg = emitAnd_ri(MVT::i32, SrcReg, 1);
4021 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4022 if (DestVT == MVT::i64) {
4025 Register Reg64 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4026 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4027 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4029 .
addImm(AArch64::sub_32);
4034 if (DestVT == MVT::i64) {
4038 return fastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,
4053 Opc = AArch64::MADDWrrr; ZReg = AArch64::WZR;
break;
4055 Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR;
break;
4058 const TargetRegisterClass *RC =
4059 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4060 return fastEmitInst_rrr(
Opc, RC, Op0, Op1, ZReg);
4064 if (RetVT != MVT::i64)
4067 return fastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,
4068 Op0, Op1, AArch64::XZR);
4072 if (RetVT != MVT::i64)
4075 return fastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,
4076 Op0, Op1, AArch64::XZR);
4082 bool NeedTrunc =
false;
4087 case MVT::i8:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4088 case MVT::i16:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4089 case MVT::i32:
Opc = AArch64::LSLVWr;
break;
4090 case MVT::i64:
Opc = AArch64::LSLVXr;
break;
4093 const TargetRegisterClass *RC =
4094 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4096 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4098 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4100 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4105 uint64_t Shift,
bool IsZExt) {
4107 "Unexpected source/return type pair.");
4108 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4109 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4110 "Unexpected source value type.");
4111 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4112 RetVT == MVT::i64) &&
"Unexpected return value type.");
4114 bool Is64Bit = (RetVT == MVT::i64);
4115 unsigned RegSize = Is64Bit ? 64 : 32;
4118 const TargetRegisterClass *RC =
4119 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4123 if (RetVT == SrcVT) {
4124 Register ResultReg = createResultReg(RC);
4125 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4126 TII.get(TargetOpcode::COPY), ResultReg)
4130 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4134 if (Shift >= DstBits)
4162 unsigned ImmR =
RegSize - Shift;
4164 unsigned ImmS = std::min<unsigned>(SrcBits - 1, DstBits - 1 - Shift);
4165 static const unsigned OpcTable[2][2] = {
4166 {AArch64::SBFMWri, AArch64::SBFMXri},
4167 {AArch64::UBFMWri, AArch64::UBFMXri}
4169 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4170 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4171 Register TmpReg = MRI.createVirtualRegister(RC);
4172 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4173 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4175 .
addImm(AArch64::sub_32);
4178 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4184 bool NeedTrunc =
false;
4189 case MVT::i8:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4190 case MVT::i16:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4191 case MVT::i32:
Opc = AArch64::LSRVWr;
break;
4192 case MVT::i64:
Opc = AArch64::LSRVXr;
break;
4195 const TargetRegisterClass *RC =
4196 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4198 Op0Reg = emitAnd_ri(MVT::i32, Op0Reg, Mask);
4199 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4201 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4203 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4208 uint64_t Shift,
bool IsZExt) {
4210 "Unexpected source/return type pair.");
4211 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4212 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4213 "Unexpected source value type.");
4214 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4215 RetVT == MVT::i64) &&
"Unexpected return value type.");
4217 bool Is64Bit = (RetVT == MVT::i64);
4218 unsigned RegSize = Is64Bit ? 64 : 32;
4221 const TargetRegisterClass *RC =
4222 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4226 if (RetVT == SrcVT) {
4227 Register ResultReg = createResultReg(RC);
4228 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4229 TII.get(TargetOpcode::COPY), ResultReg)
4233 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4237 if (Shift >= DstBits)
4265 if (Shift >= SrcBits && IsZExt)
4266 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4271 Op0 = emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4279 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4280 unsigned ImmS = SrcBits - 1;
4281 static const unsigned OpcTable[2][2] = {
4282 {AArch64::SBFMWri, AArch64::SBFMXri},
4283 {AArch64::UBFMWri, AArch64::UBFMXri}
4285 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4286 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4287 Register TmpReg = MRI.createVirtualRegister(RC);
4288 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4289 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4291 .
addImm(AArch64::sub_32);
4294 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4300 bool NeedTrunc =
false;
4305 case MVT::i8:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4306 case MVT::i16:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4307 case MVT::i32:
Opc = AArch64::ASRVWr;
break;
4308 case MVT::i64:
Opc = AArch64::ASRVXr;
break;
4311 const TargetRegisterClass *RC =
4312 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4314 Op0Reg = emitIntExt(RetVT, Op0Reg, MVT::i32,
false);
4315 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4317 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4319 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4324 uint64_t Shift,
bool IsZExt) {
4326 "Unexpected source/return type pair.");
4327 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4328 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4329 "Unexpected source value type.");
4330 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4331 RetVT == MVT::i64) &&
"Unexpected return value type.");
4333 bool Is64Bit = (RetVT == MVT::i64);
4334 unsigned RegSize = Is64Bit ? 64 : 32;
4337 const TargetRegisterClass *RC =
4338 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4342 if (RetVT == SrcVT) {
4343 Register ResultReg = createResultReg(RC);
4344 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4345 TII.get(TargetOpcode::COPY), ResultReg)
4349 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4353 if (Shift >= DstBits)
4381 if (Shift >= SrcBits && IsZExt)
4382 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4384 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4385 unsigned ImmS = SrcBits - 1;
4386 static const unsigned OpcTable[2][2] = {
4387 {AArch64::SBFMWri, AArch64::SBFMXri},
4388 {AArch64::UBFMWri, AArch64::UBFMXri}
4390 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4391 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4392 Register TmpReg = MRI.createVirtualRegister(RC);
4393 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4394 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4396 .
addImm(AArch64::sub_32);
4399 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4402Register AArch64FastISel::emitIntExt(MVT SrcVT,
Register SrcReg, MVT DestVT,
4404 assert(DestVT != MVT::i1 &&
"ZeroExt/SignExt an i1?");
4410 if (((DestVT != MVT::i8) && (DestVT != MVT::i16) &&
4411 (DestVT != MVT::i32) && (DestVT != MVT::i64)) ||
4412 ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) &&
4413 (SrcVT != MVT::i16) && (SrcVT != MVT::i32)))
4423 return emiti1Ext(SrcReg, DestVT, IsZExt);
4425 if (DestVT == MVT::i64)
4426 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4428 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4432 if (DestVT == MVT::i64)
4433 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4435 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4439 assert(DestVT == MVT::i64 &&
"IntExt i32 to i32?!?");
4440 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4446 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4448 else if (DestVT == MVT::i64) {
4449 Register Src64 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4450 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4451 TII.get(AArch64::SUBREG_TO_REG), Src64)
4453 .
addImm(AArch64::sub_32);
4457 const TargetRegisterClass *RC =
4458 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4459 return fastEmitInst_rii(
Opc, RC, SrcReg, 0, Imm);
4462bool AArch64FastISel::optimizeIntExtLoad(
const Instruction *
I, MVT RetVT,
4465 if (!LI || !LI->hasOneUse())
4473 MachineInstr *
MI = MRI.getUniqueVRegDef(
Reg);
4480 const auto *LoadMI =
MI;
4481 if (LoadMI->getOpcode() == TargetOpcode::COPY &&
4482 LoadMI->getOperand(1).getSubReg() == AArch64::sub_32) {
4483 Register LoadReg =
MI->getOperand(1).getReg();
4484 LoadMI = MRI.getUniqueVRegDef(LoadReg);
4485 assert(LoadMI &&
"Expected valid instruction");
4492 if (RetVT != MVT::i64 || SrcVT > MVT::i32) {
4493 updateValueMap(
I,
Reg);
4498 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
4499 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4500 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4502 .
addImm(AArch64::sub_32);
4505 assert((
MI->getOpcode() == TargetOpcode::COPY &&
4506 MI->getOperand(1).getSubReg() == AArch64::sub_32) &&
4507 "Expected copy instruction");
4508 Reg =
MI->getOperand(1).getReg();
4510 removeDeadCode(
I, std::next(
I));
4512 updateValueMap(
I,
Reg);
4516bool AArch64FastISel::selectIntExt(
const Instruction *
I) {
4518 "Unexpected integer extend instruction.");
4521 if (!isTypeSupported(
I->getType(), RetVT))
4524 if (!isTypeSupported(
I->getOperand(0)->getType(), SrcVT))
4528 if (optimizeIntExtLoad(
I, RetVT, SrcVT))
4531 Register SrcReg = getRegForValue(
I->getOperand(0));
4538 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr())) {
4539 if (RetVT == MVT::i64 && SrcVT != MVT::i64) {
4540 Register ResultReg = createResultReg(&AArch64::GPR64RegClass);
4541 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4542 TII.get(AArch64::SUBREG_TO_REG), ResultReg)
4544 .
addImm(AArch64::sub_32);
4548 updateValueMap(
I, SrcReg);
4553 Register ResultReg = emitIntExt(SrcVT, SrcReg, RetVT, IsZExt);
4557 updateValueMap(
I, ResultReg);
4561bool AArch64FastISel::selectRem(
const Instruction *
I,
unsigned ISDOpcode) {
4562 EVT DestEVT = TLI.getValueType(
DL,
I->getType(),
true);
4567 if (DestVT != MVT::i64 && DestVT != MVT::i32)
4571 bool Is64bit = (DestVT == MVT::i64);
4572 switch (ISDOpcode) {
4576 DivOpc = Is64bit ? AArch64::SDIVXr : AArch64::SDIVWr;
4579 DivOpc = Is64bit ? AArch64::UDIVXr : AArch64::UDIVWr;
4582 unsigned MSubOpc = Is64bit ? AArch64::MSUBXrrr : AArch64::MSUBWrrr;
4583 Register Src0Reg = getRegForValue(
I->getOperand(0));
4587 Register Src1Reg = getRegForValue(
I->getOperand(1));
4591 const TargetRegisterClass *RC =
4592 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4593 Register QuotReg = fastEmitInst_rr(DivOpc, RC, Src0Reg, Src1Reg);
4594 assert(QuotReg &&
"Unexpected DIV instruction emission failure.");
4597 Register ResultReg = fastEmitInst_rrr(MSubOpc, RC, QuotReg, Src1Reg, Src0Reg);
4598 updateValueMap(
I, ResultReg);
4602bool AArch64FastISel::selectMul(
const Instruction *
I) {
4604 if (!isTypeSupported(
I->getType(), VT,
true))
4610 const Value *Src0 =
I->getOperand(0);
4611 const Value *Src1 =
I->getOperand(1);
4613 if (
C->getValue().isPowerOf2())
4618 if (
C->getValue().isPowerOf2()) {
4619 uint64_t ShiftVal =
C->getValue().logBase2();
4625 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), VT)) {
4628 Src0 = ZExt->getOperand(0);
4634 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), VT)) {
4637 Src0 = SExt->getOperand(0);
4642 Register Src0Reg = getRegForValue(Src0);
4646 Register ResultReg = emitLSL_ri(VT, SrcVT, Src0Reg, ShiftVal, IsZExt);
4649 updateValueMap(
I, ResultReg);
4654 Register Src0Reg = getRegForValue(
I->getOperand(0));
4658 Register Src1Reg = getRegForValue(
I->getOperand(1));
4662 Register ResultReg = emitMul_rr(VT, Src0Reg, Src1Reg);
4667 updateValueMap(
I, ResultReg);
4671bool AArch64FastISel::selectShift(
const Instruction *
I) {
4673 if (!isTypeSupported(
I->getType(), RetVT,
true))
4677 return selectOperator(
I,
I->getOpcode());
4681 uint64_t ShiftVal =
C->getZExtValue();
4683 bool IsZExt =
I->getOpcode() != Instruction::AShr;
4684 const Value *Op0 =
I->getOperand(0);
4688 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), TmpVT)) {
4691 Op0 = ZExt->getOperand(0);
4697 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), TmpVT)) {
4700 Op0 = SExt->getOperand(0);
4705 Register Op0Reg = getRegForValue(Op0);
4709 switch (
I->getOpcode()) {
4711 case Instruction::Shl:
4712 ResultReg = emitLSL_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4714 case Instruction::AShr:
4715 ResultReg = emitASR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4717 case Instruction::LShr:
4718 ResultReg = emitLSR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4724 updateValueMap(
I, ResultReg);
4728 Register Op0Reg = getRegForValue(
I->getOperand(0));
4732 Register Op1Reg = getRegForValue(
I->getOperand(1));
4737 switch (
I->getOpcode()) {
4739 case Instruction::Shl:
4740 ResultReg = emitLSL_rr(RetVT, Op0Reg, Op1Reg);
4742 case Instruction::AShr:
4743 ResultReg = emitASR_rr(RetVT, Op0Reg, Op1Reg);
4745 case Instruction::LShr:
4746 ResultReg = emitLSR_rr(RetVT, Op0Reg, Op1Reg);
4753 updateValueMap(
I, ResultReg);
4757bool AArch64FastISel::selectBitCast(
const Instruction *
I) {
4760 if (!isTypeLegal(
I->getOperand(0)->getType(), SrcVT))
4762 if (!isTypeLegal(
I->getType(), RetVT))
4766 if (RetVT == MVT::f32 && SrcVT == MVT::i32)
4767 Opc = AArch64::FMOVWSr;
4768 else if (RetVT == MVT::f64 && SrcVT == MVT::i64)
4769 Opc = AArch64::FMOVXDr;
4770 else if (RetVT == MVT::i32 && SrcVT == MVT::f32)
4771 Opc = AArch64::FMOVSWr;
4772 else if (RetVT == MVT::i64 && SrcVT == MVT::f64)
4773 Opc = AArch64::FMOVDXr;
4777 const TargetRegisterClass *RC =
nullptr;
4780 case MVT::i32: RC = &AArch64::GPR32RegClass;
break;
4781 case MVT::i64: RC = &AArch64::GPR64RegClass;
break;
4782 case MVT::f32: RC = &AArch64::FPR32RegClass;
break;
4783 case MVT::f64: RC = &AArch64::FPR64RegClass;
break;
4785 Register Op0Reg = getRegForValue(
I->getOperand(0));
4789 Register ResultReg = fastEmitInst_r(
Opc, RC, Op0Reg);
4793 updateValueMap(
I, ResultReg);
4797bool AArch64FastISel::selectFRem(
const Instruction *
I) {
4799 if (!isTypeLegal(
I->getType(), RetVT))
4802 RTLIB::LibcallImpl LCImpl =
4804 if (LCImpl == RTLIB::Unsupported)
4808 Args.reserve(
I->getNumOperands());
4811 for (
auto &Arg :
I->operands())
4812 Args.emplace_back(Arg);
4814 CallLoweringInfo CLI;
4815 MCContext &Ctx = MF->getContext();
4816 CallingConv::ID CC = LibcallLowering->getLibcallImplCallingConv(LCImpl);
4819 CLI.setCallee(
DL, Ctx, CC,
I->getType(), FuncName, std::move(Args));
4820 if (!lowerCallTo(CLI))
4822 updateValueMap(
I, CLI.ResultReg);
4826bool AArch64FastISel::selectSDiv(
const Instruction *
I) {
4828 if (!isTypeLegal(
I->getType(), VT))
4835 if ((VT != MVT::i32 && VT != MVT::i64) || !
C ||
4836 !(
C.isPowerOf2() ||
C.isNegatedPowerOf2()))
4839 unsigned Lg2 =
C.countr_zero();
4840 Register Src0Reg = getRegForValue(
I->getOperand(0));
4845 Register ResultReg = emitASR_ri(VT, VT, Src0Reg, Lg2);
4848 updateValueMap(
I, ResultReg);
4852 int64_t Pow2MinusOne = (1ULL << Lg2) - 1;
4853 Register AddReg = emitAdd_ri_(VT, Src0Reg, Pow2MinusOne);
4858 if (!emitICmp_ri(VT, Src0Reg, 0))
4862 const TargetRegisterClass *RC;
4863 if (VT == MVT::i64) {
4864 SelectOpc = AArch64::CSELXr;
4865 RC = &AArch64::GPR64RegClass;
4867 SelectOpc = AArch64::CSELWr;
4868 RC = &AArch64::GPR32RegClass;
4870 Register SelectReg = fastEmitInst_rri(SelectOpc, RC, AddReg, Src0Reg,
4877 Register ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
4880 ResultReg = emitAddSub_rs(
false, VT, ZeroReg, SelectReg,
4883 ResultReg = emitASR_ri(VT, VT, SelectReg, Lg2);
4888 updateValueMap(
I, ResultReg);
4895Register AArch64FastISel::getRegForGEPIndex(
const Value *Idx) {
4896 Register IdxN = getRegForValue(Idx);
4902 MVT PtrVT = TLI.getPointerTy(
DL);
4904 if (IdxVT.
bitsLT(PtrVT)) {
4905 IdxN = emitIntExt(IdxVT.
getSimpleVT(), IdxN, PtrVT,
false);
4906 }
else if (IdxVT.
bitsGT(PtrVT))
4907 llvm_unreachable(
"AArch64 FastISel doesn't support types larger than i64");
4915bool AArch64FastISel::selectGetElementPtr(
const Instruction *
I) {
4919 Register N = getRegForValue(
I->getOperand(0));
4925 uint64_t TotalOffs = 0;
4926 MVT VT = TLI.getPointerTy(
DL);
4929 const Value *Idx = GTI.getOperand();
4930 if (
auto *StTy = GTI.getStructTypeOrNull()) {
4934 TotalOffs +=
DL.getStructLayout(StTy)->getElementOffset(
Field);
4941 TotalOffs += GTI.getSequentialElementStride(
DL) *
4946 N = emitAdd_ri_(VT,
N, TotalOffs);
4953 uint64_t ElementSize = GTI.getSequentialElementStride(
DL);
4954 Register IdxN = getRegForGEPIndex(Idx);
4958 if (ElementSize != 1) {
4962 IdxN = emitMul_rr(VT, IdxN,
C);
4972 N = emitAdd_ri_(VT,
N, TotalOffs);
4976 updateValueMap(
I,
N);
4980bool AArch64FastISel::selectAtomicCmpXchg(
const AtomicCmpXchgInst *
I) {
4981 assert(TM.getOptLevel() == CodeGenOptLevel::None &&
4982 "cmpxchg survived AtomicExpand at optlevel > -O0");
4985 Type *RetTy = RetPairTy->getTypeAtIndex(0U);
4986 assert(RetPairTy->getTypeAtIndex(1U)->isIntegerTy(1) &&
4987 "cmpxchg has a non-i1 status result");
4990 if (!isTypeLegal(RetTy, VT))
4993 const TargetRegisterClass *ResRC;
4994 unsigned Opc, CmpOpc;
4997 if (VT == MVT::i32) {
4998 Opc = AArch64::CMP_SWAP_32;
4999 CmpOpc = AArch64::SUBSWrs;
5000 ResRC = &AArch64::GPR32RegClass;
5001 }
else if (VT == MVT::i64) {
5002 Opc = AArch64::CMP_SWAP_64;
5003 CmpOpc = AArch64::SUBSXrs;
5004 ResRC = &AArch64::GPR64RegClass;
5009 const MCInstrDesc &
II =
TII.get(
Opc);
5011 Register AddrReg = getRegForValue(
I->getPointerOperand());
5012 Register DesiredReg = getRegForValue(
I->getCompareOperand());
5013 Register NewReg = getRegForValue(
I->getNewValOperand());
5015 if (!AddrReg || !DesiredReg || !NewReg)
5022 const Register ResultReg1 = createResultReg(ResRC);
5023 const Register ResultReg2 = createResultReg(&AArch64::GPR32RegClass);
5024 const Register ScratchReg = createResultReg(&AArch64::GPR32RegClass);
5027 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
5034 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CmpOpc))
5035 .
addDef(VT == MVT::i32 ? AArch64::WZR : AArch64::XZR)
5040 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr))
5046 assert((ResultReg1 + 1) == ResultReg2 &&
"Nonconsecutive result registers.");
5047 updateValueMap(
I, ResultReg1, 2);
5051bool AArch64FastISel::fastSelectInstruction(
const Instruction *
I) {
5052 if (TLI.fallBackToDAGISel(*
I))
5054 switch (
I->getOpcode()) {
5057 case Instruction::Add:
5058 case Instruction::Sub:
5059 return selectAddSub(
I);
5060 case Instruction::Mul:
5061 return selectMul(
I);
5062 case Instruction::SDiv:
5063 return selectSDiv(
I);
5064 case Instruction::SRem:
5068 case Instruction::URem:
5072 case Instruction::Shl:
5073 case Instruction::LShr:
5074 case Instruction::AShr:
5075 return selectShift(
I);
5076 case Instruction::And:
5077 case Instruction::Or:
5078 case Instruction::Xor:
5079 return selectLogicalOp(
I);
5080 case Instruction::CondBr:
5081 return selectBranch(
I);
5082 case Instruction::IndirectBr:
5083 return selectIndirectBr(
I);
5084 case Instruction::BitCast:
5086 return selectBitCast(
I);
5088 case Instruction::FPToSI:
5090 return selectFPToInt(
I,
true);
5092 case Instruction::FPToUI:
5093 return selectFPToInt(
I,
false);
5094 case Instruction::ZExt:
5095 case Instruction::SExt:
5096 return selectIntExt(
I);
5097 case Instruction::Trunc:
5099 return selectTrunc(
I);
5101 case Instruction::FPExt:
5102 return selectFPExt(
I);
5103 case Instruction::FPTrunc:
5104 return selectFPTrunc(
I);
5105 case Instruction::SIToFP:
5107 return selectIntToFP(
I,
true);
5109 case Instruction::UIToFP:
5110 return selectIntToFP(
I,
false);
5111 case Instruction::Load:
5112 return selectLoad(
I);
5113 case Instruction::Store:
5114 return selectStore(
I);
5115 case Instruction::FCmp:
5116 case Instruction::ICmp:
5117 return selectCmp(
I);
5118 case Instruction::Select:
5119 return selectSelect(
I);
5120 case Instruction::Ret:
5121 return selectRet(
I);
5122 case Instruction::FRem:
5123 return selectFRem(
I);
5124 case Instruction::GetElementPtr:
5125 return selectGetElementPtr(
I);
5126 case Instruction::AtomicCmpXchg:
5131 return selectOperator(
I,
I->getOpcode());
5145 return new AArch64FastISel(FuncInfo, LibInfo, LibcallLowering);
static bool isIntExtFree(const Instruction *I)
Check if the sign-/zero-extend will be a noop.
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 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
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...
static bool isZExtLoad(const MachineInstr &MI)
Returns whether the instruction is a zero-extending load.
static bool isSExtLoad(const MachineInstr &MI)
Returns whether the instruction is a sign-extending load.
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
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,...
Value * getCondition() const
BasicBlock * getSuccessor(unsigned i) const
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_iterator > successors()
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 & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
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 & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
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.
#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)
@ User
could "use" a pointer
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
LLVM_ABI void GetReturnInfo(CallingConv::ID CC, Type *ReturnType, AttributeList attr, SmallVectorImpl< ISD::OutputArg > &Outs, const TargetLowering &TLI, const DataLayout &DL)
Given an LLVM IR type and return type attributes, compute the return value EVTs and flags,...
bool CC_AArch64_Win64PCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
constexpr RegState getKillRegState(bool B)
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.