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);
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);
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);
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) {
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, TII.get(TargetOpcode::COPY),
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))
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)
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)
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()) {
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];
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,
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];
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,
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];
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,
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];
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,
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,
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);
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) {
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 }
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) {
1696 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1701Register AArch64FastISel::emitLogicalOp_rs(
unsigned ISDOpc, MVT RetVT,
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 }
1726 RC = &AArch64::GPR32RegClass;
1730 RC = &AArch64::GPR64RegClass;
1734 fastEmitInst_rri(
Opc, RC, LHSReg, RHSReg,
1736 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1738 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
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 }
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));
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));
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))
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))
2451 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::B))
2456 auto BranchProbability = FuncInfo.BPI->getEdgeProbability(
2458 FuncInfo.MBB->addSuccessor(Target, BranchProbability);
2460 FuncInfo.MBB->addSuccessorWithoutProb(Target);
2472 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2487 if (FuncInfo.MF->getFunction().hasFnAttribute(
2488 Attribute::SpeculativeLoadHardening))
2491 unsigned Opcode = AArch64::TBNZW;
2492 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2494 Opcode = AArch64::TBZW;
2497 const MCInstrDesc &
II =
TII.get(Opcode);
2500 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2501 .
addReg(ConstrainedCondReg)
2509bool AArch64FastISel::selectIndirectBr(
const Instruction *
I) {
2516 if (FuncInfo.MF->getFunction().hasFnAttribute(
"ptrauth-indirect-gotos"))
2520 const MCInstrDesc &
II =
TII.get(AArch64::BR);
2526 FuncInfo.MBB->addSuccessor(FuncInfo.getMBB(Succ));
2531bool AArch64FastISel::selectCmp(
const Instruction *
I) {
2541 switch (Predicate) {
2545 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2546 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2547 TII.get(TargetOpcode::COPY), ResultReg)
2551 ResultReg = fastEmit_i(MVT::i32, MVT::i32,
ISD::Constant, 1);
2556 updateValueMap(
I, ResultReg);
2564 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2568 static unsigned CondCodeTable[2][2] = {
2573 switch (Predicate) {
2585 Register TmpReg1 = createResultReg(&AArch64::GPR32RegClass);
2586 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2591 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2597 updateValueMap(
I, ResultReg);
2605 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2611 updateValueMap(
I, ResultReg);
2617bool AArch64FastISel::optimizeSelect(
const SelectInst *SI) {
2618 if (!
SI->getType()->isIntegerTy(1))
2621 const Value *Src1Val, *Src2Val;
2623 bool NeedExtraOp =
false;
2626 Src1Val =
SI->getCondition();
2627 Src2Val =
SI->getFalseValue();
2628 Opc = AArch64::ORRWrr;
2631 Src1Val =
SI->getFalseValue();
2632 Src2Val =
SI->getCondition();
2633 Opc = AArch64::BICWrr;
2637 Src1Val =
SI->getCondition();
2638 Src2Val =
SI->getTrueValue();
2639 Opc = AArch64::ORRWrr;
2643 Src1Val =
SI->getCondition();
2644 Src2Val =
SI->getTrueValue();
2645 Opc = AArch64::ANDWrr;
2652 Register Src1Reg = getRegForValue(Src1Val);
2656 Register Src2Reg = getRegForValue(Src2Val);
2661 Src1Reg = emitLogicalOp_ri(
ISD::XOR, MVT::i32, Src1Reg, 1);
2663 Register ResultReg = fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, Src1Reg,
2665 updateValueMap(SI, ResultReg);
2669bool AArch64FastISel::selectSelect(
const Instruction *
I) {
2672 if (!isTypeSupported(
I->getType(), VT))
2684 Opc = AArch64::CSELWr;
2685 RC = &AArch64::GPR32RegClass;
2688 Opc = AArch64::CSELXr;
2689 RC = &AArch64::GPR64RegClass;
2692 Opc = AArch64::FCSELSrrr;
2693 RC = &AArch64::FPR32RegClass;
2696 Opc = AArch64::FCSELDrrr;
2697 RC = &AArch64::FPR64RegClass;
2706 if (optimizeSelect(SI))
2710 if (foldXALUIntrinsic(
CC,
I,
Cond)) {
2716 isValueAvailable(
Cond)) {
2720 const Value *FoldSelect =
nullptr;
2721 switch (Predicate) {
2725 FoldSelect =
SI->getFalseValue();
2728 FoldSelect =
SI->getTrueValue();
2733 Register SrcReg = getRegForValue(FoldSelect);
2737 updateValueMap(
I, SrcReg);
2747 switch (Predicate) {
2765 const MCInstrDesc &
II =
TII.get(AArch64::ANDSWri);
2769 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II,
2775 Register Src1Reg = getRegForValue(
SI->getTrueValue());
2776 Register Src2Reg = getRegForValue(
SI->getFalseValue());
2778 if (!Src1Reg || !Src2Reg)
2782 Src2Reg = fastEmitInst_rri(
Opc, RC, Src1Reg, Src2Reg, ExtraCC);
2784 Register ResultReg = fastEmitInst_rri(
Opc, RC, Src1Reg, Src2Reg,
CC);
2785 updateValueMap(
I, ResultReg);
2789bool AArch64FastISel::selectFPExt(
const Instruction *
I) {
2791 if (!
I->getType()->isDoubleTy() || !
V->getType()->isFloatTy())
2798 Register ResultReg = createResultReg(&AArch64::FPR64RegClass);
2799 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTDSr),
2801 updateValueMap(
I, ResultReg);
2805bool AArch64FastISel::selectFPTrunc(
const Instruction *
I) {
2807 if (!
I->getType()->isFloatTy() || !
V->getType()->isDoubleTy())
2814 Register ResultReg = createResultReg(&AArch64::FPR32RegClass);
2815 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTSDr),
2817 updateValueMap(
I, ResultReg);
2822bool AArch64FastISel::selectFPToInt(
const Instruction *
I,
bool Signed) {
2824 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2827 Register SrcReg = getRegForValue(
I->getOperand(0));
2831 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2832 if (SrcVT == MVT::f128 || SrcVT == MVT::f16 || SrcVT == MVT::bf16)
2836 if (SrcVT == MVT::f64) {
2838 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWDr : AArch64::FCVTZSUXDr;
2840 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWDr : AArch64::FCVTZUUXDr;
2843 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWSr : AArch64::FCVTZSUXSr;
2845 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWSr : AArch64::FCVTZUUXSr;
2847 Register ResultReg = createResultReg(
2848 DestVT == MVT::i32 ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass);
2849 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
2851 updateValueMap(
I, ResultReg);
2855bool AArch64FastISel::selectIntToFP(
const Instruction *
I,
bool Signed) {
2857 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2860 if (DestVT == MVT::f16 || DestVT == MVT::bf16)
2863 assert((DestVT == MVT::f32 || DestVT == MVT::f64) &&
2864 "Unexpected value type.");
2866 Register SrcReg = getRegForValue(
I->getOperand(0));
2870 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2873 if (SrcVT == MVT::i16 || SrcVT == MVT::i8 || SrcVT == MVT::i1) {
2881 if (SrcVT == MVT::i64) {
2883 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUXSri : AArch64::SCVTFUXDri;
2885 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUXSri : AArch64::UCVTFUXDri;
2888 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUWSri : AArch64::SCVTFUWDri;
2890 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUWSri : AArch64::UCVTFUWDri;
2893 Register ResultReg = fastEmitInst_r(
Opc, TLI.getRegClassFor(DestVT), SrcReg);
2894 updateValueMap(
I, ResultReg);
2898bool AArch64FastISel::fastLowerArguments() {
2899 if (!FuncInfo.CanLowerReturn)
2906 CallingConv::ID
CC =
F->getCallingConv();
2907 if (
CC != CallingConv::C &&
CC != CallingConv::Swift)
2914 unsigned GPRCnt = 0;
2915 unsigned FPRCnt = 0;
2916 for (
auto const &Arg :
F->args()) {
2917 if (Arg.hasAttribute(Attribute::ByVal) ||
2918 Arg.hasAttribute(Attribute::InReg) ||
2919 Arg.hasAttribute(Attribute::StructRet) ||
2920 Arg.hasAttribute(Attribute::SwiftSelf) ||
2921 Arg.hasAttribute(Attribute::SwiftAsync) ||
2922 Arg.hasAttribute(Attribute::SwiftError) ||
2923 Arg.hasAttribute(Attribute::Nest))
2926 Type *ArgTy = Arg.getType();
2930 EVT ArgVT = TLI.getValueType(
DL, ArgTy);
2942 if (VT >= MVT::i1 && VT <= MVT::i64)
2944 else if ((VT >= MVT::f16 && VT <= MVT::f64) || VT.
is64BitVector() ||
2950 if (GPRCnt > 8 || FPRCnt > 8)
2955 { AArch64::W0, AArch64::W1, AArch64::W2, AArch64::W3, AArch64::W4,
2956 AArch64::W5, AArch64::W6, AArch64::W7 },
2957 { AArch64::X0, AArch64::X1, AArch64::X2, AArch64::X3, AArch64::X4,
2958 AArch64::X5, AArch64::X6, AArch64::X7 },
2959 { AArch64::H0, AArch64::H1, AArch64::H2, AArch64::H3, AArch64::H4,
2960 AArch64::H5, AArch64::H6, AArch64::H7 },
2961 { AArch64::S0, AArch64::S1, AArch64::S2, AArch64::S3, AArch64::S4,
2962 AArch64::S5, AArch64::S6, AArch64::S7 },
2963 { AArch64::D0, AArch64::D1, AArch64::D2, AArch64::D3, AArch64::D4,
2964 AArch64::D5, AArch64::D6, AArch64::D7 },
2965 { AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,
2966 AArch64::Q5, AArch64::Q6, AArch64::Q7 }
2969 unsigned GPRIdx = 0;
2970 unsigned FPRIdx = 0;
2971 for (
auto const &Arg :
F->args()) {
2972 MVT VT = TLI.getSimpleValueType(
DL, Arg.getType());
2975 if (VT >= MVT::i1 && VT <= MVT::i32) {
2977 RC = &AArch64::GPR32RegClass;
2979 }
else if (VT == MVT::i64) {
2981 RC = &AArch64::GPR64RegClass;
2982 }
else if (VT == MVT::f16 || VT == MVT::bf16) {
2984 RC = &AArch64::FPR16RegClass;
2985 }
else if (VT == MVT::f32) {
2987 RC = &AArch64::FPR32RegClass;
2990 RC = &AArch64::FPR64RegClass;
2993 RC = &AArch64::FPR128RegClass;
2997 Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
3001 Register ResultReg = createResultReg(RC);
3002 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
3005 updateValueMap(&Arg, ResultReg);
3010bool AArch64FastISel::processCallArgs(CallLoweringInfo &CLI,
3011 SmallVectorImpl<MVT> &OutVTs,
3012 SmallVectorImpl<Type *> &OrigTys,
3013 unsigned &NumBytes) {
3014 CallingConv::ID
CC = CLI.CallConv;
3016 CCState CCInfo(
CC,
false, *FuncInfo.MF, ArgLocs, *
Context);
3017 CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, OrigTys,
3018 CCAssignFnForCall(
CC));
3021 NumBytes = CCInfo.getStackSize();
3024 unsigned AdjStackDown =
TII.getCallFrameSetupOpcode();
3025 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackDown))
3029 for (CCValAssign &VA : ArgLocs) {
3030 const Value *ArgVal = CLI.OutVals[VA.getValNo()];
3031 MVT ArgVT = OutVTs[VA.getValNo()];
3033 Register ArgReg = getRegForValue(ArgVal);
3038 switch (VA.getLocInfo()) {
3042 MVT DestVT = VA.getLocVT();
3044 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
false);
3052 MVT DestVT = VA.getLocVT();
3054 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
true);
3064 if (VA.isRegLoc() && !VA.needsCustom()) {
3065 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3066 TII.get(TargetOpcode::COPY), VA.getLocReg()).
addReg(ArgReg);
3067 CLI.OutRegs.push_back(VA.getLocReg());
3068 }
else if (VA.needsCustom()) {
3072 assert(VA.isMemLoc() &&
"Assuming store on stack.");
3081 unsigned BEAlign = 0;
3082 if (ArgSize < 8 && !Subtarget->isLittleEndian())
3083 BEAlign = 8 - ArgSize;
3086 Addr.setKind(Address::RegBase);
3087 Addr.setReg(AArch64::SP);
3088 Addr.setOffset(VA.getLocMemOffset() + BEAlign);
3091 MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
3095 if (!
emitStore(ArgVT, ArgReg, Addr, MMO))
3102bool AArch64FastISel::finishCall(CallLoweringInfo &CLI,
unsigned NumBytes) {
3103 CallingConv::ID
CC = CLI.CallConv;
3106 unsigned AdjStackUp =
TII.getCallFrameDestroyOpcode();
3107 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackUp))
3112 CCState CCInfo(
CC,
false, *FuncInfo.MF, RVLocs, *
Context);
3113 CCInfo.AnalyzeCallResult(CLI.Ins, CCAssignFnForCall(
CC));
3115 Register ResultReg = FuncInfo.CreateRegs(CLI.RetTy);
3116 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
3117 CCValAssign &VA = RVLocs[i];
3126 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
3132 CLI.ResultReg = ResultReg;
3133 CLI.NumResultRegs = RVLocs.
size();
3138bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
3139 CallingConv::ID
CC = CLI.CallConv;
3140 bool IsTailCall = CLI.IsTailCall;
3141 bool IsVarArg = CLI.IsVarArg;
3145 if (!Callee && !Symbol)
3150 if (CLI.CB && CLI.CB->hasFnAttr(Attribute::ReturnsTwice) &&
3151 !Subtarget->noBTIAtReturnTwice() &&
3152 MF->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement())
3156 if (CLI.CB && CLI.CB->isIndirectCall() &&
3168 (
CC == CallingConv::Tail ||
CC == CallingConv::SwiftTail ||
3169 (
CC == CallingConv::Fast && TM.Options.GuaranteedTailCallOpt)))
3188 if (MF->getFunction().getParent()->getRtLibUseGOT())
3198 for (
auto Flag : CLI.OutFlags)
3200 Flag.isSwiftSelf() ||
Flag.isSwiftAsync() ||
Flag.isSwiftError())
3206 OutVTs.
reserve(CLI.OutVals.size());
3208 for (
auto *Val : CLI.OutVals) {
3210 if (!isTypeLegal(Val->getType(), VT) &&
3211 !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16))
3223 if (Callee && !computeCallAddress(Callee, Addr))
3230 Addr.getGlobalValue()->hasExternalWeakLinkage())
3235 if (!processCallArgs(CLI, OutVTs, OrigTys, NumBytes))
3243 MachineInstrBuilder MIB;
3245 const MCInstrDesc &
II =
3247 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II);
3250 else if (Addr.getGlobalValue())
3252 else if (Addr.getReg()) {
3260 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
3261 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
3265 CallReg = createResultReg(&AArch64::GPR64RegClass);
3266 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3267 TII.get(AArch64::LDRXui), CallReg)
3271 }
else if (Addr.getGlobalValue())
3272 CallReg = materializeGV(Addr.getGlobalValue());
3273 else if (Addr.getReg())
3274 CallReg = Addr.getReg();
3281 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II).
addReg(CallReg);
3285 for (
auto Reg : CLI.OutRegs)
3295 return finishCall(CLI, NumBytes);
3298bool AArch64FastISel::isMemCpySmall(
uint64_t Len, MaybeAlign Alignment) {
3305bool AArch64FastISel::tryEmitSmallMemCpy(
Address Dest,
Address Src,
3306 uint64_t Len, MaybeAlign Alignment) {
3308 if (!isMemCpySmall(Len, Alignment))
3311 int64_t UnscaledOffset = 0;
3317 if (!Alignment || *Alignment >= 8) {
3328 assert(Alignment &&
"Alignment is set in this branch");
3330 if (Len >= 4 && *Alignment == 4)
3332 else if (Len >= 2 && *Alignment == 2)
3348 UnscaledOffset +=
Size;
3351 Dest.setOffset(OrigDest.getOffset() + UnscaledOffset);
3352 Src.setOffset(OrigSrc.getOffset() + UnscaledOffset);
3361 const Instruction *
I,
3375 if (!isTypeLegal(RetTy, RetVT))
3378 if (RetVT != MVT::i32 && RetVT != MVT::i64)
3393 case Intrinsic::smul_with_overflow:
3395 if (
C->getValue() == 2)
3396 IID = Intrinsic::sadd_with_overflow;
3398 case Intrinsic::umul_with_overflow:
3400 if (
C->getValue() == 2)
3401 IID = Intrinsic::uadd_with_overflow;
3409 case Intrinsic::sadd_with_overflow:
3410 case Intrinsic::ssub_with_overflow:
3413 case Intrinsic::uadd_with_overflow:
3416 case Intrinsic::usub_with_overflow:
3419 case Intrinsic::smul_with_overflow:
3420 case Intrinsic::umul_with_overflow:
3426 if (!isValueAvailable(
II))
3432 for (
auto Itr = std::prev(Start); Itr !=
End; --Itr) {
3440 if (EVI->getAggregateOperand() !=
II)
3448bool AArch64FastISel::fastLowerIntrinsicCall(
const IntrinsicInst *
II) {
3450 switch (
II->getIntrinsicID()) {
3451 default:
return false;
3452 case Intrinsic::frameaddress: {
3453 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3459 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3469 DestReg = fastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,
3471 assert(DestReg &&
"Unexpected LDR instruction emission failure.");
3475 updateValueMap(
II, SrcReg);
3478 case Intrinsic::sponentry: {
3479 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3483 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
3484 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3485 TII.get(AArch64::ADDXri), ResultReg)
3490 updateValueMap(
II, ResultReg);
3493 case Intrinsic::memcpy:
3494 case Intrinsic::memmove: {
3497 if (MTI->isVolatile())
3502 bool IsMemCpy = (
II->getIntrinsicID() == Intrinsic::memcpy);
3508 if (MTI->getDestAlign() || MTI->getSourceAlign())
3509 Alignment = std::min(MTI->getDestAlign().valueOrOne(),
3510 MTI->getSourceAlign().valueOrOne());
3511 if (isMemCpySmall(Len, Alignment)) {
3513 if (!computeAddress(MTI->getRawDest(), Dest) ||
3514 !computeAddress(MTI->getRawSource(), Src))
3516 if (tryEmitSmallMemCpy(Dest, Src, Len, Alignment))
3521 if (!MTI->getLength()->getType()->isIntegerTy(64))
3524 if (MTI->getSourceAddressSpace() > 255 || MTI->getDestAddressSpace() > 255)
3530 return lowerCallTo(
II, IntrMemName,
II->arg_size() - 1);
3532 case Intrinsic::memset: {
3546 return lowerCallTo(
II,
"memset",
II->arg_size() - 1);
3548 case Intrinsic::sin:
3549 case Intrinsic::cos:
3550 case Intrinsic::tan:
3551 case Intrinsic::pow: {
3553 if (!isTypeLegal(
II->getType(), RetVT))
3556 if (RetVT != MVT::f32 && RetVT != MVT::f64)
3559 static const RTLIB::Libcall LibCallTable[4][2] = {
3560 {RTLIB::SIN_F32, RTLIB::SIN_F64},
3561 {RTLIB::COS_F32, RTLIB::COS_F64},
3562 {RTLIB::TAN_F32, RTLIB::TAN_F64},
3563 {RTLIB::POW_F32, RTLIB::POW_F64}};
3565 bool Is64Bit = RetVT == MVT::f64;
3566 switch (
II->getIntrinsicID()) {
3569 case Intrinsic::sin:
3570 LC = LibCallTable[0][Is64Bit];
3572 case Intrinsic::cos:
3573 LC = LibCallTable[1][Is64Bit];
3575 case Intrinsic::tan:
3576 LC = LibCallTable[2][Is64Bit];
3578 case Intrinsic::pow:
3579 LC = LibCallTable[3][Is64Bit];
3584 Args.reserve(
II->arg_size());
3587 for (
auto &Arg :
II->args())
3588 Args.emplace_back(Arg);
3590 CallLoweringInfo CLI;
3591 MCContext &Ctx = MF->getContext();
3593 RTLIB::LibcallImpl LCImpl = LibcallLowering->getLibcallImpl(LC);
3594 if (LCImpl == RTLIB::Unsupported)
3597 CallingConv::ID
CC = LibcallLowering->getLibcallImplCallingConv(LCImpl);
3599 CLI.setCallee(
DL, Ctx,
CC,
II->getType(), FuncName, std::move(Args));
3600 if (!lowerCallTo(CLI))
3602 updateValueMap(
II, CLI.ResultReg);
3605 case Intrinsic::fabs: {
3607 if (!isTypeLegal(
II->getType(), VT))
3615 Opc = AArch64::FABSSr;
3618 Opc = AArch64::FABSDr;
3621 Register SrcReg = getRegForValue(
II->getOperand(0));
3624 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3625 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
3627 updateValueMap(
II, ResultReg);
3630 case Intrinsic::trap:
3631 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3634 case Intrinsic::debugtrap:
3635 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3639 case Intrinsic::sqrt: {
3640 Type *RetTy =
II->getCalledFunction()->getReturnType();
3643 if (!isTypeLegal(RetTy, VT))
3646 Register Op0Reg = getRegForValue(
II->getOperand(0));
3654 updateValueMap(
II, ResultReg);
3657 case Intrinsic::sadd_with_overflow:
3658 case Intrinsic::uadd_with_overflow:
3659 case Intrinsic::ssub_with_overflow:
3660 case Intrinsic::usub_with_overflow:
3661 case Intrinsic::smul_with_overflow:
3662 case Intrinsic::umul_with_overflow: {
3666 Type *RetTy = Ty->getTypeAtIndex(0U);
3669 if (!isTypeLegal(RetTy, VT))
3672 if (VT != MVT::i32 && VT != MVT::i64)
3686 case Intrinsic::smul_with_overflow:
3688 if (
C->getValue() == 2) {
3689 IID = Intrinsic::sadd_with_overflow;
3693 case Intrinsic::umul_with_overflow:
3695 if (
C->getValue() == 2) {
3696 IID = Intrinsic::uadd_with_overflow;
3702 Register ResultReg1, ResultReg2, MulReg;
3706 case Intrinsic::sadd_with_overflow:
3707 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3710 case Intrinsic::uadd_with_overflow:
3711 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3714 case Intrinsic::ssub_with_overflow:
3715 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3718 case Intrinsic::usub_with_overflow:
3719 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3722 case Intrinsic::smul_with_overflow: {
3732 if (VT == MVT::i32) {
3733 MulReg = emitSMULL_rr(MVT::i64, LHSReg, RHSReg);
3735 fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3737 emitAddSub_rx(
false, MVT::i64, MulReg, MulSubReg,
3742 assert(VT == MVT::i64 &&
"Unexpected value type.");
3745 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3752 case Intrinsic::umul_with_overflow: {
3762 if (VT == MVT::i32) {
3763 MulReg = emitUMULL_rr(MVT::i64, LHSReg, RHSReg);
3765 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3766 TII.get(AArch64::ANDSXri), AArch64::XZR)
3769 MulReg = fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3771 assert(VT == MVT::i64 &&
"Unexpected value type.");
3774 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3776 emitSubs_rr(VT, AArch64::XZR, UMULHReg,
false);
3783 ResultReg1 = createResultReg(TLI.getRegClassFor(VT));
3784 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3785 TII.get(TargetOpcode::COPY), ResultReg1).
addReg(MulReg);
3791 ResultReg2 = fastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,
3792 AArch64::WZR, AArch64::WZR,
3793 getInvertedCondCode(
CC));
3795 assert((ResultReg1 + 1) == ResultReg2 &&
3796 "Nonconsecutive result registers.");
3797 updateValueMap(
II, ResultReg1, 2);
3800 case Intrinsic::aarch64_crc32b:
3801 case Intrinsic::aarch64_crc32h:
3802 case Intrinsic::aarch64_crc32w:
3803 case Intrinsic::aarch64_crc32x:
3804 case Intrinsic::aarch64_crc32cb:
3805 case Intrinsic::aarch64_crc32ch:
3806 case Intrinsic::aarch64_crc32cw:
3807 case Intrinsic::aarch64_crc32cx: {
3808 if (!Subtarget->hasCRC())
3812 switch (
II->getIntrinsicID()) {
3815 case Intrinsic::aarch64_crc32b:
3816 Opc = AArch64::CRC32Brr;
3818 case Intrinsic::aarch64_crc32h:
3819 Opc = AArch64::CRC32Hrr;
3821 case Intrinsic::aarch64_crc32w:
3822 Opc = AArch64::CRC32Wrr;
3824 case Intrinsic::aarch64_crc32x:
3825 Opc = AArch64::CRC32Xrr;
3827 case Intrinsic::aarch64_crc32cb:
3828 Opc = AArch64::CRC32CBrr;
3830 case Intrinsic::aarch64_crc32ch:
3831 Opc = AArch64::CRC32CHrr;
3833 case Intrinsic::aarch64_crc32cw:
3834 Opc = AArch64::CRC32CWrr;
3836 case Intrinsic::aarch64_crc32cx:
3837 Opc = AArch64::CRC32CXrr;
3841 Register LHSReg = getRegForValue(
II->getArgOperand(0));
3842 Register RHSReg = getRegForValue(
II->getArgOperand(1));
3843 if (!LHSReg || !RHSReg)
3847 fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, LHSReg, RHSReg);
3848 updateValueMap(
II, ResultReg);
3855bool AArch64FastISel::selectRet(
const Instruction *
I) {
3857 const Function &
F = *
I->getParent()->getParent();
3859 if (!FuncInfo.CanLowerReturn)
3862 if (FuncInfo.MF->getInfo<AArch64FunctionInfo>()->getSRetReturnReg())
3868 if (TLI.supportSwiftError() &&
3869 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
3872 if (TLI.supportSplitCSR(FuncInfo.MF))
3879 CallingConv::ID
CC =
F.getCallingConv();
3885 CCState CCInfo(
CC,
F.isVarArg(), *FuncInfo.MF, ValLocs,
I->getContext());
3889 if (ValLocs.
size() != 1)
3892 CCValAssign &VA = ValLocs[0];
3914 EVT RVEVT = TLI.getValueType(
DL, RV->
getType());
3924 if (RVVT == MVT::f128)
3929 if (RVVT != DestVT) {
3930 if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
3933 if (!Outs[0].
Flags.isZExt() && !Outs[0].Flags.isSExt())
3936 bool IsZExt = Outs[0].Flags.isZExt();
3937 SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
3945 SrcReg = emitAnd_ri(MVT::i64, SrcReg, 0xffffffff);
3948 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3949 TII.get(TargetOpcode::COPY), DestReg).
addReg(SrcReg);
3955 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3956 TII.get(AArch64::RET_ReallyLR));
3958 MIB.
addReg(RetReg, RegState::Implicit);
3962bool AArch64FastISel::selectTrunc(
const Instruction *
I) {
3963 Type *DestTy =
I->getType();
3965 Type *SrcTy =
Op->getType();
3967 EVT SrcEVT = TLI.getValueType(
DL, SrcTy,
true);
3968 EVT DestEVT = TLI.getValueType(
DL, DestTy,
true);
3977 if (SrcVT != MVT::i64 && SrcVT != MVT::i32 && SrcVT != MVT::i16 &&
3980 if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8 &&
3994 if (SrcVT == MVT::i64) {
4011 Register Reg32 = fastEmitInst_extractsubreg(MVT::i32, SrcReg,
4014 ResultReg = emitAnd_ri(MVT::i32, Reg32, Mask);
4015 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4017 ResultReg = createResultReg(&AArch64::GPR32RegClass);
4018 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4019 TII.get(TargetOpcode::COPY), ResultReg)
4023 updateValueMap(
I, ResultReg);
4027Register AArch64FastISel::emiti1Ext(
Register SrcReg, MVT DestVT,
bool IsZExt) {
4028 assert((DestVT == MVT::i8 || DestVT == MVT::i16 || DestVT == MVT::i32 ||
4029 DestVT == MVT::i64) &&
4030 "Unexpected value type.");
4032 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4036 Register ResultReg = emitAnd_ri(MVT::i32, SrcReg, 1);
4037 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4038 if (DestVT == MVT::i64) {
4042 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4043 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4045 .
addImm(AArch64::sub_32);
4050 if (DestVT == MVT::i64) {
4054 return fastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,
4069 Opc = AArch64::MADDWrrr; ZReg = AArch64::WZR;
break;
4071 Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR;
break;
4075 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4076 return fastEmitInst_rrr(
Opc, RC, Op0, Op1, ZReg);
4080 if (RetVT != MVT::i64)
4083 return fastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,
4084 Op0, Op1, AArch64::XZR);
4088 if (RetVT != MVT::i64)
4091 return fastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,
4092 Op0, Op1, AArch64::XZR);
4098 bool NeedTrunc =
false;
4103 case MVT::i8:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4104 case MVT::i16:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4105 case MVT::i32:
Opc = AArch64::LSLVWr;
break;
4106 case MVT::i64:
Opc = AArch64::LSLVXr;
break;
4110 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4112 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4114 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4116 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4123 "Unexpected source/return type pair.");
4124 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4125 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4126 "Unexpected source value type.");
4127 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4128 RetVT == MVT::i64) &&
"Unexpected return value type.");
4130 bool Is64Bit = (RetVT == MVT::i64);
4131 unsigned RegSize = Is64Bit ? 64 : 32;
4135 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4139 if (RetVT == SrcVT) {
4140 Register ResultReg = createResultReg(RC);
4141 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4142 TII.get(TargetOpcode::COPY), ResultReg)
4146 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4150 if (Shift >= DstBits)
4178 unsigned ImmR =
RegSize - Shift;
4180 unsigned ImmS = std::min<unsigned>(SrcBits - 1, DstBits - 1 - Shift);
4181 static const unsigned OpcTable[2][2] = {
4182 {AArch64::SBFMWri, AArch64::SBFMXri},
4183 {AArch64::UBFMWri, AArch64::UBFMXri}
4185 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4186 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4188 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4189 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4191 .
addImm(AArch64::sub_32);
4194 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4200 bool NeedTrunc =
false;
4205 case MVT::i8:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4206 case MVT::i16:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4207 case MVT::i32:
Opc = AArch64::LSRVWr;
break;
4208 case MVT::i64:
Opc = AArch64::LSRVXr;
break;
4212 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4214 Op0Reg = emitAnd_ri(MVT::i32, Op0Reg, Mask);
4215 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4217 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4219 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4226 "Unexpected source/return type pair.");
4227 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4228 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4229 "Unexpected source value type.");
4230 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4231 RetVT == MVT::i64) &&
"Unexpected return value type.");
4233 bool Is64Bit = (RetVT == MVT::i64);
4234 unsigned RegSize = Is64Bit ? 64 : 32;
4238 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4242 if (RetVT == SrcVT) {
4243 Register ResultReg = createResultReg(RC);
4244 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4245 TII.get(TargetOpcode::COPY), ResultReg)
4249 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4253 if (Shift >= DstBits)
4281 if (Shift >= SrcBits && IsZExt)
4282 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4287 Op0 = emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4295 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4296 unsigned ImmS = SrcBits - 1;
4297 static const unsigned OpcTable[2][2] = {
4298 {AArch64::SBFMWri, AArch64::SBFMXri},
4299 {AArch64::UBFMWri, AArch64::UBFMXri}
4301 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4302 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4304 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4305 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4307 .
addImm(AArch64::sub_32);
4310 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4316 bool NeedTrunc =
false;
4321 case MVT::i8:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4322 case MVT::i16:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4323 case MVT::i32:
Opc = AArch64::ASRVWr;
break;
4324 case MVT::i64:
Opc = AArch64::ASRVXr;
break;
4328 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4330 Op0Reg = emitIntExt(RetVT, Op0Reg, MVT::i32,
false);
4331 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4333 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4335 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4342 "Unexpected source/return type pair.");
4343 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4344 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4345 "Unexpected source value type.");
4346 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4347 RetVT == MVT::i64) &&
"Unexpected return value type.");
4349 bool Is64Bit = (RetVT == MVT::i64);
4350 unsigned RegSize = Is64Bit ? 64 : 32;
4354 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4358 if (RetVT == SrcVT) {
4359 Register ResultReg = createResultReg(RC);
4360 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4361 TII.get(TargetOpcode::COPY), ResultReg)
4365 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4369 if (Shift >= DstBits)
4397 if (Shift >= SrcBits && IsZExt)
4398 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4400 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4401 unsigned ImmS = SrcBits - 1;
4402 static const unsigned OpcTable[2][2] = {
4403 {AArch64::SBFMWri, AArch64::SBFMXri},
4404 {AArch64::UBFMWri, AArch64::UBFMXri}
4406 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4407 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4409 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4410 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4412 .
addImm(AArch64::sub_32);
4415 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4418Register AArch64FastISel::emitIntExt(MVT SrcVT,
Register SrcReg, MVT DestVT,
4420 assert(DestVT != MVT::i1 &&
"ZeroExt/SignExt an i1?");
4426 if (((DestVT != MVT::i8) && (DestVT != MVT::i16) &&
4427 (DestVT != MVT::i32) && (DestVT != MVT::i64)) ||
4428 ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) &&
4429 (SrcVT != MVT::i16) && (SrcVT != MVT::i32)))
4439 return emiti1Ext(SrcReg, DestVT, IsZExt);
4441 if (DestVT == MVT::i64)
4442 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4444 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4448 if (DestVT == MVT::i64)
4449 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4451 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4455 assert(DestVT == MVT::i64 &&
"IntExt i32 to i32?!?");
4456 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4462 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4464 else if (DestVT == MVT::i64) {
4466 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4467 TII.get(AArch64::SUBREG_TO_REG), Src64)
4469 .
addImm(AArch64::sub_32);
4474 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4475 return fastEmitInst_rii(
Opc, RC, SrcReg, 0,
Imm);
4478bool AArch64FastISel::optimizeIntExtLoad(
const Instruction *
I, MVT RetVT,
4481 if (!LI || !LI->hasOneUse())
4496 const auto *LoadMI =
MI;
4497 if (LoadMI->getOpcode() == TargetOpcode::COPY &&
4498 LoadMI->getOperand(1).getSubReg() == AArch64::sub_32) {
4499 Register LoadReg =
MI->getOperand(1).getReg();
4501 assert(LoadMI &&
"Expected valid instruction");
4508 if (RetVT != MVT::i64 || SrcVT > MVT::i32) {
4509 updateValueMap(
I,
Reg);
4514 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
4515 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4516 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4518 .
addImm(AArch64::sub_32);
4521 assert((
MI->getOpcode() == TargetOpcode::COPY &&
4522 MI->getOperand(1).getSubReg() == AArch64::sub_32) &&
4523 "Expected copy instruction");
4524 Reg =
MI->getOperand(1).getReg();
4526 removeDeadCode(
I, std::next(
I));
4528 updateValueMap(
I,
Reg);
4532bool AArch64FastISel::selectIntExt(
const Instruction *
I) {
4534 "Unexpected integer extend instruction.");
4537 if (!isTypeSupported(
I->getType(), RetVT))
4540 if (!isTypeSupported(
I->getOperand(0)->getType(), SrcVT))
4544 if (optimizeIntExtLoad(
I, RetVT, SrcVT))
4547 Register SrcReg = getRegForValue(
I->getOperand(0));
4554 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr())) {
4555 if (RetVT == MVT::i64 && SrcVT != MVT::i64) {
4556 Register ResultReg = createResultReg(&AArch64::GPR64RegClass);
4557 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4558 TII.get(AArch64::SUBREG_TO_REG), ResultReg)
4560 .
addImm(AArch64::sub_32);
4564 updateValueMap(
I, SrcReg);
4569 Register ResultReg = emitIntExt(SrcVT, SrcReg, RetVT, IsZExt);
4573 updateValueMap(
I, ResultReg);
4577bool AArch64FastISel::selectRem(
const Instruction *
I,
unsigned ISDOpcode) {
4578 EVT DestEVT = TLI.getValueType(
DL,
I->getType(),
true);
4583 if (DestVT != MVT::i64 && DestVT != MVT::i32)
4587 bool Is64bit = (DestVT == MVT::i64);
4588 switch (ISDOpcode) {
4592 DivOpc = Is64bit ? AArch64::SDIVXr : AArch64::SDIVWr;
4595 DivOpc = Is64bit ? AArch64::UDIVXr : AArch64::UDIVWr;
4598 unsigned MSubOpc = Is64bit ? AArch64::MSUBXrrr : AArch64::MSUBWrrr;
4599 Register Src0Reg = getRegForValue(
I->getOperand(0));
4603 Register Src1Reg = getRegForValue(
I->getOperand(1));
4608 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4609 Register QuotReg = fastEmitInst_rr(DivOpc, RC, Src0Reg, Src1Reg);
4610 assert(QuotReg &&
"Unexpected DIV instruction emission failure.");
4613 Register ResultReg = fastEmitInst_rrr(MSubOpc, RC, QuotReg, Src1Reg, Src0Reg);
4614 updateValueMap(
I, ResultReg);
4618bool AArch64FastISel::selectMul(
const Instruction *
I) {
4620 if (!isTypeSupported(
I->getType(), VT,
true))
4629 if (
C->getValue().isPowerOf2())
4634 if (
C->getValue().isPowerOf2()) {
4635 uint64_t ShiftVal =
C->getValue().logBase2();
4641 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), VT)) {
4644 Src0 = ZExt->getOperand(0);
4650 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), VT)) {
4653 Src0 = SExt->getOperand(0);
4658 Register Src0Reg = getRegForValue(Src0);
4662 Register ResultReg = emitLSL_ri(VT, SrcVT, Src0Reg, ShiftVal, IsZExt);
4665 updateValueMap(
I, ResultReg);
4670 Register Src0Reg = getRegForValue(
I->getOperand(0));
4674 Register Src1Reg = getRegForValue(
I->getOperand(1));
4678 Register ResultReg = emitMul_rr(VT, Src0Reg, Src1Reg);
4683 updateValueMap(
I, ResultReg);
4687bool AArch64FastISel::selectShift(
const Instruction *
I) {
4689 if (!isTypeSupported(
I->getType(), RetVT,
true))
4693 return selectOperator(
I,
I->getOpcode());
4699 bool IsZExt =
I->getOpcode() != Instruction::AShr;
4700 const Value *Op0 =
I->getOperand(0);
4704 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), TmpVT)) {
4707 Op0 = ZExt->getOperand(0);
4713 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), TmpVT)) {
4716 Op0 = SExt->getOperand(0);
4721 Register Op0Reg = getRegForValue(Op0);
4725 switch (
I->getOpcode()) {
4727 case Instruction::Shl:
4728 ResultReg = emitLSL_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4730 case Instruction::AShr:
4731 ResultReg = emitASR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4733 case Instruction::LShr:
4734 ResultReg = emitLSR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4740 updateValueMap(
I, ResultReg);
4744 Register Op0Reg = getRegForValue(
I->getOperand(0));
4748 Register Op1Reg = getRegForValue(
I->getOperand(1));
4753 switch (
I->getOpcode()) {
4755 case Instruction::Shl:
4756 ResultReg = emitLSL_rr(RetVT, Op0Reg, Op1Reg);
4758 case Instruction::AShr:
4759 ResultReg = emitASR_rr(RetVT, Op0Reg, Op1Reg);
4761 case Instruction::LShr:
4762 ResultReg = emitLSR_rr(RetVT, Op0Reg, Op1Reg);
4769 updateValueMap(
I, ResultReg);
4773bool AArch64FastISel::selectBitCast(
const Instruction *
I) {
4776 if (!isTypeLegal(
I->getOperand(0)->getType(), SrcVT))
4778 if (!isTypeLegal(
I->getType(), RetVT))
4782 if (RetVT == MVT::f32 && SrcVT == MVT::i32)
4783 Opc = AArch64::FMOVWSr;
4784 else if (RetVT == MVT::f64 && SrcVT == MVT::i64)
4785 Opc = AArch64::FMOVXDr;
4786 else if (RetVT == MVT::i32 && SrcVT == MVT::f32)
4787 Opc = AArch64::FMOVSWr;
4788 else if (RetVT == MVT::i64 && SrcVT == MVT::f64)
4789 Opc = AArch64::FMOVDXr;
4796 case MVT::i32: RC = &AArch64::GPR32RegClass;
break;
4797 case MVT::i64: RC = &AArch64::GPR64RegClass;
break;
4798 case MVT::f32: RC = &AArch64::FPR32RegClass;
break;
4799 case MVT::f64: RC = &AArch64::FPR64RegClass;
break;
4801 Register Op0Reg = getRegForValue(
I->getOperand(0));
4805 Register ResultReg = fastEmitInst_r(
Opc, RC, Op0Reg);
4809 updateValueMap(
I, ResultReg);
4813bool AArch64FastISel::selectFRem(
const Instruction *
I) {
4815 if (!isTypeLegal(
I->getType(), RetVT))
4818 RTLIB::LibcallImpl LCImpl =
4819 LibcallLowering->getLibcallImpl(RTLIB::getREM(RetVT));
4820 if (LCImpl == RTLIB::Unsupported)
4824 Args.reserve(
I->getNumOperands());
4827 for (
auto &Arg :
I->operands())
4828 Args.emplace_back(Arg);
4830 CallLoweringInfo CLI;
4831 MCContext &Ctx = MF->getContext();
4832 CallingConv::ID
CC = LibcallLowering->getLibcallImplCallingConv(LCImpl);
4835 CLI.setCallee(
DL, Ctx,
CC,
I->getType(), FuncName, std::move(Args));
4836 if (!lowerCallTo(CLI))
4838 updateValueMap(
I, CLI.ResultReg);
4842bool AArch64FastISel::selectSDiv(
const Instruction *
I) {
4844 if (!isTypeLegal(
I->getType(), VT))
4851 if ((VT != MVT::i32 && VT != MVT::i64) || !
C ||
4852 !(
C.isPowerOf2() ||
C.isNegatedPowerOf2()))
4855 unsigned Lg2 =
C.countr_zero();
4856 Register Src0Reg = getRegForValue(
I->getOperand(0));
4861 Register ResultReg = emitASR_ri(VT, VT, Src0Reg, Lg2);
4864 updateValueMap(
I, ResultReg);
4868 int64_t Pow2MinusOne = (1ULL << Lg2) - 1;
4869 Register AddReg = emitAdd_ri_(VT, Src0Reg, Pow2MinusOne);
4874 if (!emitICmp_ri(VT, Src0Reg, 0))
4879 if (VT == MVT::i64) {
4880 SelectOpc = AArch64::CSELXr;
4881 RC = &AArch64::GPR64RegClass;
4883 SelectOpc = AArch64::CSELWr;
4884 RC = &AArch64::GPR32RegClass;
4886 Register SelectReg = fastEmitInst_rri(SelectOpc, RC, AddReg, Src0Reg,
4893 Register ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
4896 ResultReg = emitAddSub_rs(
false, VT, ZeroReg, SelectReg,
4899 ResultReg = emitASR_ri(VT, VT, SelectReg, Lg2);
4904 updateValueMap(
I, ResultReg);
4911Register AArch64FastISel::getRegForGEPIndex(
const Value *Idx) {
4912 Register IdxN = getRegForValue(Idx);
4918 MVT PtrVT = TLI.getPointerTy(
DL);
4920 if (IdxVT.
bitsLT(PtrVT)) {
4921 IdxN = emitIntExt(IdxVT.
getSimpleVT(), IdxN, PtrVT,
false);
4922 }
else if (IdxVT.
bitsGT(PtrVT))
4923 llvm_unreachable(
"AArch64 FastISel doesn't support types larger than i64");
4931bool AArch64FastISel::selectGetElementPtr(
const Instruction *
I) {
4935 Register N = getRegForValue(
I->getOperand(0));
4942 MVT VT = TLI.getPointerTy(
DL);
4945 const Value *
Idx = GTI.getOperand();
4946 if (
auto *StTy = GTI.getStructTypeOrNull()) {
4950 TotalOffs +=
DL.getStructLayout(StTy)->getElementOffset(
Field);
4957 TotalOffs += GTI.getSequentialElementStride(
DL) *
4962 N = emitAdd_ri_(VT,
N, TotalOffs);
4969 uint64_t ElementSize = GTI.getSequentialElementStride(
DL);
4970 Register IdxN = getRegForGEPIndex(Idx);
4974 if (ElementSize != 1) {
4978 IdxN = emitMul_rr(VT, IdxN,
C);
4988 N = emitAdd_ri_(VT,
N, TotalOffs);
4992 updateValueMap(
I,
N);
4996bool AArch64FastISel::selectAtomicCmpXchg(
const AtomicCmpXchgInst *
I) {
4997 assert(TM.getOptLevel() == CodeGenOptLevel::None &&
4998 "cmpxchg survived AtomicExpand at optlevel > -O0");
5001 Type *RetTy = RetPairTy->getTypeAtIndex(0U);
5002 assert(RetPairTy->getTypeAtIndex(1U)->isIntegerTy(1) &&
5003 "cmpxchg has a non-i1 status result");
5006 if (!isTypeLegal(RetTy, VT))
5010 unsigned Opc, CmpOpc;
5013 if (VT == MVT::i32) {
5014 Opc = AArch64::CMP_SWAP_32;
5015 CmpOpc = AArch64::SUBSWrs;
5016 ResRC = &AArch64::GPR32RegClass;
5017 }
else if (VT == MVT::i64) {
5018 Opc = AArch64::CMP_SWAP_64;
5019 CmpOpc = AArch64::SUBSXrs;
5020 ResRC = &AArch64::GPR64RegClass;
5025 const MCInstrDesc &
II =
TII.get(
Opc);
5027 Register AddrReg = getRegForValue(
I->getPointerOperand());
5028 Register DesiredReg = getRegForValue(
I->getCompareOperand());
5029 Register NewReg = getRegForValue(
I->getNewValOperand());
5031 if (!AddrReg || !DesiredReg || !NewReg)
5038 const Register ResultReg1 = createResultReg(ResRC);
5039 const Register ResultReg2 = createResultReg(&AArch64::GPR32RegClass);
5040 const Register ScratchReg = createResultReg(&AArch64::GPR32RegClass);
5043 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
5050 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CmpOpc))
5051 .
addDef(VT == MVT::i32 ? AArch64::WZR : AArch64::XZR)
5056 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr))
5062 assert((ResultReg1 + 1) == ResultReg2 &&
"Nonconsecutive result registers.");
5063 updateValueMap(
I, ResultReg1, 2);
5067bool AArch64FastISel::fastSelectInstruction(
const Instruction *
I) {
5068 if (TLI.fallBackToDAGISel(*
I))
5070 switch (
I->getOpcode()) {
5073 case Instruction::Add:
5074 case Instruction::Sub:
5075 return selectAddSub(
I);
5076 case Instruction::Mul:
5077 return selectMul(
I);
5078 case Instruction::SDiv:
5079 return selectSDiv(
I);
5080 case Instruction::SRem:
5084 case Instruction::URem:
5088 case Instruction::Shl:
5089 case Instruction::LShr:
5090 case Instruction::AShr:
5091 return selectShift(
I);
5092 case Instruction::And:
5093 case Instruction::Or:
5094 case Instruction::Xor:
5095 return selectLogicalOp(
I);
5096 case Instruction::CondBr:
5097 return selectBranch(
I);
5098 case Instruction::IndirectBr:
5099 return selectIndirectBr(
I);
5100 case Instruction::BitCast:
5102 return selectBitCast(
I);
5104 case Instruction::FPToSI:
5106 return selectFPToInt(
I,
true);
5108 case Instruction::FPToUI:
5109 return selectFPToInt(
I,
false);
5110 case Instruction::ZExt:
5111 case Instruction::SExt:
5112 return selectIntExt(
I);
5113 case Instruction::Trunc:
5115 return selectTrunc(
I);
5117 case Instruction::FPExt:
5118 return selectFPExt(
I);
5119 case Instruction::FPTrunc:
5120 return selectFPTrunc(
I);
5121 case Instruction::SIToFP:
5123 return selectIntToFP(
I,
true);
5125 case Instruction::UIToFP:
5126 return selectIntToFP(
I,
false);
5127 case Instruction::Load:
5128 return selectLoad(
I);
5129 case Instruction::Store:
5130 return selectStore(
I);
5131 case Instruction::FCmp:
5132 case Instruction::ICmp:
5133 return selectCmp(
I);
5134 case Instruction::Select:
5135 return selectSelect(
I);
5136 case Instruction::Ret:
5137 return selectRet(
I);
5138 case Instruction::FRem:
5139 return selectFRem(
I);
5140 case Instruction::GetElementPtr:
5141 return selectGetElementPtr(
I);
5142 case Instruction::AtomicCmpXchg:
5147 return selectOperator(
I,
I->getOpcode());
5161 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, appropriate for the register ban...
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!")
AMDGPU Reserve WWM Registers
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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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.
static constexpr Value * getValue(Ty &ValueOrUse)
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
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
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 isTargetWindowsOrUEFI() const
UEFI follows the Windows ARM64 ABI and produces PE/COFF images, so most of the Windows specific ABI h...
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...
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 or function.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
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.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
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 isSized() const
Return true if it makes sense to take the size of this type.
bool isStructTy() const
True if this is an instance of StructType.
bool isIntegerTy() const
True if this is an instance of IntegerType.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_PREL
MO_PREL - Indicates that the bits of the symbol operand represented by MO_G0 etc are PC relative.
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering)
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ 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.
@ User
could "use" a pointer
This is an optimization pass for GlobalISel generic memory operations.
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)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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)
@ End
Run the machine verifier once, at the end of the pipeline.
bool CC_AArch64_Win64_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
MCRegisterClass TargetRegisterClass
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.