57#include "llvm/IR/IntrinsicsAArch64.h"
81class AArch64FastISel final :
public FastISel {
84 enum BaseKind { RegBase, FrameIndexBase };
87 BaseKind Kind = RegBase;
96 const GlobalValue *GV =
nullptr;
101 void setKind(BaseKind K) { Kind =
K; }
102 BaseKind getKind()
const {
return Kind; }
105 bool isRegBase()
const {
return Kind == RegBase; }
106 bool isFIBase()
const {
return Kind == FrameIndexBase; }
109 assert(isRegBase() &&
"Invalid base register access!");
114 assert(isRegBase() &&
"Invalid base register access!");
120 Register getOffsetReg()
const {
return OffsetReg; }
122 void setFI(
unsigned FI) {
123 assert(isFIBase() &&
"Invalid base frame index access!");
127 unsigned getFI()
const {
128 assert(isFIBase() &&
"Invalid base frame index access!");
132 void setOffset(int64_t O) { Offset =
O; }
134 void setShift(
unsigned S) { Shift = S; }
135 unsigned getShift() {
return Shift; }
137 void setGlobalValue(
const GlobalValue *
G) { GV =
G; }
138 const GlobalValue *getGlobalValue() {
return GV; }
143 const AArch64Subtarget *Subtarget;
144 LLVMContext *Context;
146 bool fastLowerArguments()
override;
147 bool fastLowerCall(CallLoweringInfo &CLI)
override;
148 bool fastLowerIntrinsicCall(
const IntrinsicInst *
II)
override;
152 bool selectAddSub(
const Instruction *
I);
153 bool selectLogicalOp(
const Instruction *
I);
154 bool selectLoad(
const Instruction *
I);
155 bool selectStore(
const Instruction *
I);
156 bool selectBranch(
const Instruction *
I);
157 bool selectIndirectBr(
const Instruction *
I);
158 bool selectCmp(
const Instruction *
I);
159 bool selectSelect(
const Instruction *
I);
160 bool selectFPExt(
const Instruction *
I);
161 bool selectFPTrunc(
const Instruction *
I);
162 bool selectFPToInt(
const Instruction *
I,
bool Signed);
163 bool selectIntToFP(
const Instruction *
I,
bool Signed);
164 bool selectRem(
const Instruction *
I,
unsigned ISDOpcode);
165 bool selectRet(
const Instruction *
I);
166 bool selectTrunc(
const Instruction *
I);
167 bool selectIntExt(
const Instruction *
I);
168 bool selectMul(
const Instruction *
I);
169 bool selectShift(
const Instruction *
I);
170 bool selectBitCast(
const Instruction *
I);
171 bool selectFRem(
const Instruction *
I);
172 bool selectSDiv(
const Instruction *
I);
173 bool selectGetElementPtr(
const Instruction *
I);
174 bool selectAtomicCmpXchg(
const AtomicCmpXchgInst *
I);
177 bool isTypeLegal(
Type *Ty, MVT &VT);
178 bool isTypeSupported(
Type *Ty, MVT &VT,
bool IsVectorAllowed =
false);
179 bool isValueAvailable(
const Value *V)
const;
180 bool computeAddress(
const Value *Obj, Address &Addr,
Type *Ty =
nullptr);
181 bool computeCallAddress(
const Value *V, Address &Addr);
182 bool simplifyAddress(Address &Addr, MVT VT);
183 void addLoadStoreOperands(Address &Addr,
const MachineInstrBuilder &MIB,
185 unsigned ScaleFactor, MachineMemOperand *MMO);
186 bool isMemCpySmall(uint64_t Len, MaybeAlign Alignment);
187 bool tryEmitSmallMemCpy(Address Dest, Address Src, uint64_t Len,
188 MaybeAlign Alignment);
191 bool optimizeIntExtLoad(
const Instruction *
I, MVT RetVT, MVT SrcVT);
192 bool optimizeSelect(
const SelectInst *SI);
197 const Value *
RHS,
bool SetFlags =
false,
198 bool WantResult =
true,
bool IsZExt =
false);
200 Register RHSReg,
bool SetFlags =
false,
201 bool WantResult =
true);
202 Register emitAddSub_ri(
bool UseAdd, MVT RetVT,
Register LHSReg, uint64_t Imm,
203 bool SetFlags =
false,
bool WantResult =
true);
206 uint64_t ShiftImm,
bool SetFlags =
false,
207 bool WantResult =
true);
210 uint64_t ShiftImm,
bool SetFlags =
false,
211 bool WantResult =
true);
214 bool emitCompareAndBranch(
const BranchInst *BI);
217 bool emitICmp_ri(MVT RetVT,
Register LHSReg, uint64_t Imm);
220 MachineMemOperand *MMO =
nullptr);
222 MachineMemOperand *MMO =
nullptr);
224 MachineMemOperand *MMO =
nullptr);
228 bool SetFlags =
false,
bool WantResult =
true,
229 bool IsZExt =
false);
232 bool SetFlags =
false,
bool WantResult =
true,
233 bool IsZExt =
false);
235 bool WantResult =
true);
238 bool WantResult =
true);
244 Register RHSReg, uint64_t ShiftImm);
257 bool IsZExt =
false);
259 Register materializeInt(
const ConstantInt *CI, MVT VT);
260 Register materializeFP(
const ConstantFP *CFP, MVT VT);
261 Register materializeGV(
const GlobalValue *GV);
265 CCAssignFn *CCAssignFnForCall(CallingConv::ID CC)
const;
266 bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs,
267 SmallVectorImpl<Type *> &OrigTys,
unsigned &NumBytes);
268 bool finishCall(CallLoweringInfo &CLI,
unsigned NumBytes);
272 Register fastMaterializeAlloca(
const AllocaInst *AI)
override;
273 Register fastMaterializeConstant(
const Constant *
C)
override;
274 Register fastMaterializeFloatZero(
const ConstantFP *CF)
override;
276 explicit AArch64FastISel(FunctionLoweringInfo &FuncInfo,
277 const TargetLibraryInfo *LibInfo,
278 const LibcallLoweringInfo *libcallLowering)
279 : FastISel(FuncInfo, LibInfo, libcallLowering,
285 bool fastSelectInstruction(
const Instruction *
I)
override;
287#include "AArch64GenFastISel.inc"
295 "Unexpected integer extend instruction.");
296 assert(!
I->getType()->isVectorTy() &&
I->getType()->isIntegerTy() &&
297 "Unexpected value type.");
305 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr()))
332 if (CC == CallingConv::GHC)
334 if (CC == CallingConv::CFGuard_Check)
343Register AArch64FastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
345 "Alloca should always return a pointer.");
348 auto SI = FuncInfo.StaticAllocaMap.find(AI);
349 if (SI == FuncInfo.StaticAllocaMap.end())
352 if (SI != FuncInfo.StaticAllocaMap.end()) {
353 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
354 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
365Register AArch64FastISel::materializeInt(
const ConstantInt *CI, MVT VT) {
373 const TargetRegisterClass *RC = (VT == MVT::i64) ? &AArch64::GPR64RegClass
374 : &AArch64::GPR32RegClass;
375 unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
376 Register ResultReg = createResultReg(RC);
377 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
382Register AArch64FastISel::materializeFP(
const ConstantFP *CFP, MVT VT) {
386 return fastMaterializeFloatZero(CFP);
388 if (VT != MVT::f32 && VT != MVT::f64)
392 bool Is64Bit = (VT == MVT::f64);
398 unsigned Opc = Is64Bit ? AArch64::FMOVDi : AArch64::FMOVSi;
399 return fastEmitInst_i(
Opc, TLI.getRegClassFor(VT), Imm);
404 unsigned Opc1 = Is64Bit ? AArch64::MOVi64imm : AArch64::MOVi32imm;
405 const TargetRegisterClass *RC = Is64Bit ?
406 &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
408 Register TmpReg = createResultReg(RC);
409 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc1), TmpReg)
410 .addImm(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
412 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
413 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
414 TII.get(TargetOpcode::COPY), ResultReg)
415 .addReg(TmpReg, getKillRegState(true));
422 Align Alignment =
DL.getPrefTypeAlign(CFP->
getType());
424 unsigned CPI = MCP.getConstantPoolIndex(
cast<Constant>(CFP), Alignment);
425 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
426 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
429 unsigned Opc = Is64Bit ? AArch64::LDRDui : AArch64::LDRSui;
430 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
431 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
437Register AArch64FastISel::materializeGV(
const GlobalValue *GV) {
447 if (FuncInfo.MF->getInfo<AArch64FunctionInfo>()->hasELFSignedGOT())
452 EVT DestEVT = TLI.getValueType(
DL, GV->
getType(),
true);
456 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
461 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
467 ResultReg = createResultReg(&AArch64::GPR32RegClass);
468 LdrOpc = AArch64::LDRWui;
470 ResultReg = createResultReg(&AArch64::GPR64RegClass);
471 LdrOpc = AArch64::LDRXui;
473 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(LdrOpc),
483 Register Result64 = createResultReg(&AArch64::GPR64RegClass);
484 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
485 TII.get(TargetOpcode::SUBREG_TO_REG))
493 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
511 Register DstReg = createResultReg(&AArch64::GPR64commonRegClass);
512 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::MOVKXi),
521 ResultReg = createResultReg(&AArch64::GPR64spRegClass);
522 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
532Register AArch64FastISel::fastMaterializeConstant(
const Constant *
C) {
533 EVT CEVT = TLI.getValueType(
DL,
C->getType(),
true);
542 assert(VT == MVT::i64 &&
"Expected 64-bit pointers");
543 return materializeInt(ConstantInt::get(Type::getInt64Ty(*
Context), 0), VT);
547 return materializeInt(CI, VT);
549 return materializeFP(CFP, VT);
551 return materializeGV(GV);
556Register AArch64FastISel::fastMaterializeFloatZero(
const ConstantFP *CFP) {
558 "Floating-point constant is not a positive zero.");
560 if (!isTypeLegal(CFP->
getType(), VT))
563 if (VT != MVT::f32 && VT != MVT::f64)
566 bool Is64Bit = (VT == MVT::f64);
567 unsigned ZReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
568 unsigned Opc = Is64Bit ? AArch64::FMOVXDr : AArch64::FMOVWSr;
569 return fastEmitInst_r(
Opc, TLI.getRegClassFor(VT), ZReg);
576 if (
C->getValue().isPowerOf2())
579 if (
C->getValue().isPowerOf2())
586bool AArch64FastISel::computeAddress(
const Value *Obj,
Address &Addr,
Type *Ty)
588 const User *
U =
nullptr;
589 unsigned Opcode = Instruction::UserOp1;
593 if (FuncInfo.StaticAllocaMap.count(
static_cast<const AllocaInst *
>(Obj)) ||
594 FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
595 Opcode =
I->getOpcode();
599 Opcode =
C->getOpcode();
604 if (Ty->getAddressSpace() > 255)
612 case Instruction::BitCast:
614 return computeAddress(
U->getOperand(0), Addr, Ty);
616 case Instruction::IntToPtr:
618 if (TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
619 TLI.getPointerTy(
DL))
620 return computeAddress(
U->getOperand(0), Addr, Ty);
623 case Instruction::PtrToInt:
625 if (TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
626 return computeAddress(
U->getOperand(0), Addr, Ty);
629 case Instruction::GetElementPtr: {
631 uint64_t TmpOffset = Addr.getOffset();
637 const Value *
Op = GTI.getOperand();
638 if (StructType *STy = GTI.getStructTypeOrNull()) {
639 const StructLayout *SL =
DL.getStructLayout(STy);
643 uint64_t S = GTI.getSequentialElementStride(
DL);
650 if (canFoldAddIntoGEP(U,
Op)) {
660 goto unsupported_gep;
666 Addr.setOffset(TmpOffset);
667 if (computeAddress(
U->getOperand(0), Addr, Ty))
676 case Instruction::Alloca: {
678 DenseMap<const AllocaInst *, int>::iterator
SI =
679 FuncInfo.StaticAllocaMap.find(AI);
680 if (SI != FuncInfo.StaticAllocaMap.end()) {
681 Addr.setKind(Address::FrameIndexBase);
682 Addr.setFI(
SI->second);
687 case Instruction::Add: {
697 return computeAddress(
LHS, Addr, Ty);
701 if (computeAddress(
LHS, Addr, Ty) && computeAddress(
RHS, Addr, Ty))
707 case Instruction::Sub: {
714 return computeAddress(
LHS, Addr, Ty);
718 case Instruction::Shl: {
719 if (Addr.getOffsetReg())
727 if (Val < 1 || Val > 3)
730 uint64_t NumBytes = 0;
732 uint64_t NumBits =
DL.getTypeSizeInBits(Ty);
733 NumBytes = NumBits / 8;
738 if (NumBytes != (1ULL << Val))
744 const Value *Src =
U->getOperand(0);
746 if (FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
750 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
752 Src = ZE->getOperand(0);
756 SE->getOperand(0)->getType()->isIntegerTy(32)) {
758 Src = SE->getOperand(0);
765 if (AI->
getOpcode() == Instruction::And) {
770 if (
C->getValue() == 0xffffffff)
774 if (
C->getValue() == 0xffffffff) {
779 Reg = fastEmitInst_extractsubreg(MVT::i32,
Reg, AArch64::sub_32);
780 Addr.setOffsetReg(
Reg);
788 Addr.setOffsetReg(
Reg);
791 case Instruction::Mul: {
792 if (Addr.getOffsetReg())
803 if (
C->getValue().isPowerOf2())
808 unsigned Val =
C->getValue().logBase2();
809 if (Val < 1 || Val > 3)
812 uint64_t NumBytes = 0;
814 uint64_t NumBits =
DL.getTypeSizeInBits(Ty);
815 NumBytes = NumBits / 8;
820 if (NumBytes != (1ULL << Val))
828 if (FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
832 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
834 Src = ZE->getOperand(0);
838 SE->getOperand(0)->getType()->isIntegerTy(32)) {
840 Src = SE->getOperand(0);
849 Addr.setOffsetReg(
Reg);
852 case Instruction::And: {
853 if (Addr.getOffsetReg())
856 if (!Ty ||
DL.getTypeSizeInBits(Ty) != 8)
863 if (
C->getValue() == 0xffffffff)
867 if (
C->getValue() == 0xffffffff) {
875 Reg = fastEmitInst_extractsubreg(MVT::i32,
Reg, AArch64::sub_32);
876 Addr.setOffsetReg(
Reg);
881 case Instruction::SExt:
882 case Instruction::ZExt: {
883 if (!Addr.getReg() || Addr.getOffsetReg())
886 const Value *Src =
nullptr;
889 if (!
isIntExtFree(ZE) && ZE->getOperand(0)->getType()->isIntegerTy(32)) {
891 Src = ZE->getOperand(0);
894 if (!
isIntExtFree(SE) && SE->getOperand(0)->getType()->isIntegerTy(32)) {
896 Src = SE->getOperand(0);
907 Addr.setOffsetReg(
Reg);
912 if (Addr.isRegBase() && !Addr.getReg()) {
920 if (!Addr.getOffsetReg()) {
924 Addr.setOffsetReg(
Reg);
931bool AArch64FastISel::computeCallAddress(
const Value *V,
Address &Addr) {
932 const User *
U =
nullptr;
933 unsigned Opcode = Instruction::UserOp1;
937 Opcode =
I->getOpcode();
939 InMBB =
I->getParent() == FuncInfo.MBB->getBasicBlock();
941 Opcode =
C->getOpcode();
947 case Instruction::BitCast:
950 return computeCallAddress(
U->getOperand(0), Addr);
952 case Instruction::IntToPtr:
955 TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
956 TLI.getPointerTy(
DL))
957 return computeCallAddress(
U->getOperand(0), Addr);
959 case Instruction::PtrToInt:
961 if (InMBB && TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
962 return computeCallAddress(
U->getOperand(0), Addr);
967 Addr.setGlobalValue(GV);
972 if (!Addr.getGlobalValue()) {
973 Addr.setReg(getRegForValue(V));
974 return Addr.getReg().isValid();
980bool AArch64FastISel::isTypeLegal(
Type *Ty, MVT &VT) {
981 EVT evt = TLI.getValueType(
DL, Ty,
true);
987 if (evt == MVT::Other || !evt.
isSimple())
997 return TLI.isTypeLegal(VT);
1004bool AArch64FastISel::isTypeSupported(
Type *Ty, MVT &VT,
bool IsVectorAllowed) {
1008 if (isTypeLegal(Ty, VT))
1013 if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)
1019bool AArch64FastISel::isValueAvailable(
const Value *V)
const {
1024 return FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB;
1027bool AArch64FastISel::simplifyAddress(
Address &Addr, MVT VT) {
1035 bool ImmediateOffsetNeedsLowering =
false;
1036 bool RegisterOffsetNeedsLowering =
false;
1037 int64_t
Offset = Addr.getOffset();
1039 ImmediateOffsetNeedsLowering =
true;
1040 else if (
Offset > 0 && !(
Offset & (ScaleFactor - 1)) &&
1042 ImmediateOffsetNeedsLowering =
true;
1047 if (!ImmediateOffsetNeedsLowering && Addr.getOffset() && Addr.getOffsetReg())
1048 RegisterOffsetNeedsLowering =
true;
1051 if (Addr.isRegBase() && Addr.getOffsetReg() && !Addr.getReg())
1052 RegisterOffsetNeedsLowering =
true;
1057 if ((ImmediateOffsetNeedsLowering || Addr.getOffsetReg()) && Addr.isFIBase())
1059 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
1060 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
1065 Addr.setKind(Address::RegBase);
1066 Addr.setReg(ResultReg);
1069 if (RegisterOffsetNeedsLowering) {
1071 if (Addr.getReg()) {
1074 ResultReg = emitAddSub_rx(
true, MVT::i64, Addr.getReg(),
1075 Addr.getOffsetReg(), Addr.getExtendType(),
1078 ResultReg = emitAddSub_rs(
true, MVT::i64, Addr.getReg(),
1083 ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1084 Addr.getShift(),
true);
1086 ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1087 Addr.getShift(),
false);
1089 ResultReg = emitLSL_ri(MVT::i64, MVT::i64, Addr.getOffsetReg(),
1095 Addr.setReg(ResultReg);
1096 Addr.setOffsetReg(0);
1103 if (ImmediateOffsetNeedsLowering) {
1107 ResultReg = emitAdd_ri_(MVT::i64, Addr.getReg(),
Offset);
1113 Addr.setReg(ResultReg);
1119void AArch64FastISel::addLoadStoreOperands(
Address &Addr,
1120 const MachineInstrBuilder &MIB,
1122 unsigned ScaleFactor,
1123 MachineMemOperand *MMO) {
1124 int64_t
Offset = Addr.getOffset() / ScaleFactor;
1126 if (Addr.isFIBase()) {
1127 int FI = Addr.getFI();
1130 MMO = FuncInfo.MF->getMachineMemOperand(
1132 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
1136 assert(Addr.isRegBase() &&
"Unexpected address kind.");
1143 if (Addr.getOffsetReg()) {
1144 assert(Addr.getOffset() == 0 &&
"Unexpected offset");
1147 MIB.
addReg(Addr.getReg());
1148 MIB.
addReg(Addr.getOffsetReg());
1150 MIB.
addImm(Addr.getShift() != 0);
1159Register AArch64FastISel::emitAddSub(
bool UseAdd, MVT RetVT,
const Value *
LHS,
1161 bool WantResult,
bool IsZExt) {
1163 bool NeedExtend =
false;
1198 if (
SI->getOpcode() == Instruction::Shl ||
1199 SI->getOpcode() == Instruction::LShr ||
1200 SI->getOpcode() == Instruction::AShr )
1208 LHSReg = emitIntExt(SrcVT, LHSReg, RetVT, IsZExt);
1212 uint64_t
Imm = IsZExt ?
C->getZExtValue() :
C->getSExtValue();
1213 if (
C->isNegative())
1214 ResultReg = emitAddSub_ri(!UseAdd, RetVT, LHSReg, -Imm, SetFlags,
1217 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, Imm, SetFlags,
1220 if (
C->isNullValue())
1221 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, 0, SetFlags, WantResult);
1228 isValueAvailable(
RHS)) {
1232 return emitAddSub_rx(UseAdd, RetVT, LHSReg, RHSReg, ExtendType, 0,
1233 SetFlags, WantResult);
1243 if (
C->getValue().isPowerOf2())
1248 Register RHSReg = getRegForValue(MulLHS);
1251 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg,
AArch64_AM::LSL,
1252 ShiftVal, SetFlags, WantResult);
1263 switch (
SI->getOpcode()) {
1269 uint64_t ShiftVal =
C->getZExtValue();
1271 Register RHSReg = getRegForValue(
SI->getOperand(0));
1274 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg, ShiftType,
1275 ShiftVal, SetFlags, WantResult);
1288 RHSReg = emitIntExt(SrcVT, RHSReg, RetVT, IsZExt);
1290 return emitAddSub_rr(UseAdd, RetVT, LHSReg, RHSReg, SetFlags, WantResult);
1293Register AArch64FastISel::emitAddSub_rr(
bool UseAdd, MVT RetVT,
Register LHSReg,
1296 assert(LHSReg && RHSReg &&
"Invalid register number.");
1298 if (LHSReg == AArch64::SP || LHSReg == AArch64::WSP ||
1299 RHSReg == AArch64::SP || RHSReg == AArch64::WSP)
1302 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1305 static const unsigned OpcTable[2][2][2] = {
1306 { { AArch64::SUBWrr, AArch64::SUBXrr },
1307 { AArch64::ADDWrr, AArch64::ADDXrr } },
1308 { { AArch64::SUBSWrr, AArch64::SUBSXrr },
1309 { AArch64::ADDSWrr, AArch64::ADDSXrr } }
1311 bool Is64Bit = RetVT == MVT::i64;
1312 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1313 const TargetRegisterClass *RC =
1314 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1317 ResultReg = createResultReg(RC);
1319 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1321 const MCInstrDesc &
II =
TII.get(
Opc);
1324 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1330Register AArch64FastISel::emitAddSub_ri(
bool UseAdd, MVT RetVT,
Register LHSReg,
1331 uint64_t Imm,
bool SetFlags,
1333 assert(LHSReg &&
"Invalid register number.");
1335 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1341 else if ((Imm & 0xfff000) == Imm) {
1347 static const unsigned OpcTable[2][2][2] = {
1348 { { AArch64::SUBWri, AArch64::SUBXri },
1349 { AArch64::ADDWri, AArch64::ADDXri } },
1350 { { AArch64::SUBSWri, AArch64::SUBSXri },
1351 { AArch64::ADDSWri, AArch64::ADDSXri } }
1353 bool Is64Bit = RetVT == MVT::i64;
1354 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1355 const TargetRegisterClass *RC;
1357 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1359 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1362 ResultReg = createResultReg(RC);
1364 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1366 const MCInstrDesc &
II =
TII.get(
Opc);
1368 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1375Register AArch64FastISel::emitAddSub_rs(
bool UseAdd, MVT RetVT,
Register LHSReg,
1378 uint64_t ShiftImm,
bool SetFlags,
1380 assert(LHSReg && RHSReg &&
"Invalid register number.");
1381 assert(LHSReg != AArch64::SP && LHSReg != AArch64::WSP &&
1382 RHSReg != AArch64::SP && RHSReg != AArch64::WSP);
1384 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1391 static const unsigned OpcTable[2][2][2] = {
1392 { { AArch64::SUBWrs, AArch64::SUBXrs },
1393 { AArch64::ADDWrs, AArch64::ADDXrs } },
1394 { { AArch64::SUBSWrs, AArch64::SUBSXrs },
1395 { AArch64::ADDSWrs, AArch64::ADDSXrs } }
1397 bool Is64Bit = RetVT == MVT::i64;
1398 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1399 const TargetRegisterClass *RC =
1400 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1403 ResultReg = createResultReg(RC);
1405 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1407 const MCInstrDesc &
II =
TII.get(
Opc);
1410 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1413 .
addImm(getShifterImm(ShiftType, ShiftImm));
1417Register AArch64FastISel::emitAddSub_rx(
bool UseAdd, MVT RetVT,
Register LHSReg,
1420 uint64_t ShiftImm,
bool SetFlags,
1422 assert(LHSReg && RHSReg &&
"Invalid register number.");
1423 assert(LHSReg != AArch64::XZR && LHSReg != AArch64::WZR &&
1424 RHSReg != AArch64::XZR && RHSReg != AArch64::WZR);
1426 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1432 static const unsigned OpcTable[2][2][2] = {
1433 { { AArch64::SUBWrx, AArch64::SUBXrx },
1434 { AArch64::ADDWrx, AArch64::ADDXrx } },
1435 { { AArch64::SUBSWrx, AArch64::SUBSXrx },
1436 { AArch64::ADDSWrx, AArch64::ADDSXrx } }
1438 bool Is64Bit = RetVT == MVT::i64;
1439 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1440 const TargetRegisterClass *RC =
nullptr;
1442 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1444 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1447 ResultReg = createResultReg(RC);
1449 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1451 const MCInstrDesc &
II =
TII.get(
Opc);
1454 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1457 .
addImm(getArithExtendImm(ExtType, ShiftImm));
1461bool AArch64FastISel::emitCmp(
const Value *
LHS,
const Value *
RHS,
bool IsZExt) {
1463 EVT EVT = TLI.getValueType(
DL, Ty,
true);
1476 return emitICmp(VT,
LHS,
RHS, IsZExt);
1479 return emitFCmp(VT,
LHS,
RHS);
1483bool AArch64FastISel::emitICmp(MVT RetVT,
const Value *
LHS,
const Value *
RHS,
1485 return emitSub(RetVT,
LHS,
RHS,
true,
false,
1490bool AArch64FastISel::emitICmp_ri(MVT RetVT,
Register LHSReg, uint64_t Imm) {
1491 return emitAddSub_ri(
false, RetVT, LHSReg, Imm,
1496bool AArch64FastISel::emitFCmp(MVT RetVT,
const Value *
LHS,
const Value *
RHS) {
1497 if (RetVT != MVT::f32 && RetVT != MVT::f64)
1502 bool UseImm =
false;
1512 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDri : AArch64::FCMPSri;
1513 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1522 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDrr : AArch64::FCMPSrr;
1523 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1530 bool SetFlags,
bool WantResult,
bool IsZExt) {
1531 return emitAddSub(
true, RetVT,
LHS,
RHS, SetFlags, WantResult,
1543 ResultReg = emitAddSub_ri(
false, VT, Op0, -Imm);
1545 ResultReg = emitAddSub_ri(
true, VT, Op0, Imm);
1554 ResultReg = emitAddSub_rr(
true, VT, Op0, CReg);
1559 bool SetFlags,
bool WantResult,
bool IsZExt) {
1560 return emitAddSub(
false, RetVT,
LHS,
RHS, SetFlags, WantResult,
1565 Register RHSReg,
bool WantResult) {
1566 return emitAddSub_rr(
false, RetVT, LHSReg, RHSReg,
1573 uint64_t ShiftImm,
bool WantResult) {
1574 return emitAddSub_rs(
false, RetVT, LHSReg, RHSReg, ShiftType,
1575 ShiftImm,
true, WantResult);
1578Register AArch64FastISel::emitLogicalOp(
unsigned ISDOpc, MVT RetVT,
1601 uint64_t
Imm =
C->getZExtValue();
1602 ResultReg = emitLogicalOp_ri(ISDOpc, RetVT, LHSReg, Imm);
1614 if (
C->getValue().isPowerOf2())
1620 Register RHSReg = getRegForValue(MulLHS);
1623 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);
1633 uint64_t ShiftVal =
C->getZExtValue();
1634 Register RHSReg = getRegForValue(
SI->getOperand(0));
1637 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);
1647 MVT VT = std::max(MVT::i32, RetVT.
SimpleTy);
1648 ResultReg = fastEmit_rr(VT, VT, ISDOpc, LHSReg, RHSReg);
1649 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1650 uint64_t
Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1651 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1656Register AArch64FastISel::emitLogicalOp_ri(
unsigned ISDOpc, MVT RetVT,
1659 "ISD nodes are not consecutive!");
1660 static const unsigned OpcTable[3][2] = {
1661 { AArch64::ANDWri, AArch64::ANDXri },
1662 { AArch64::ORRWri, AArch64::ORRXri },
1663 { AArch64::EORWri, AArch64::EORXri }
1665 const TargetRegisterClass *RC;
1676 Opc = OpcTable[Idx][0];
1677 RC = &AArch64::GPR32spRegClass;
1683 RC = &AArch64::GPR64spRegClass;
1692 fastEmitInst_ri(
Opc, RC, LHSReg,
1694 if (RetVT >= MVT::i8 && RetVT <= MVT::i16 && ISDOpc !=
ISD::AND) {
1695 uint64_t
Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1696 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1701Register AArch64FastISel::emitLogicalOp_rs(
unsigned ISDOpc, MVT RetVT,
1703 uint64_t ShiftImm) {
1705 "ISD nodes are not consecutive!");
1706 static const unsigned OpcTable[3][2] = {
1707 { AArch64::ANDWrs, AArch64::ANDXrs },
1708 { AArch64::ORRWrs, AArch64::ORRXrs },
1709 { AArch64::EORWrs, AArch64::EORXrs }
1716 const TargetRegisterClass *RC;
1726 RC = &AArch64::GPR32RegClass;
1730 RC = &AArch64::GPR64RegClass;
1734 fastEmitInst_rri(
Opc, RC, LHSReg, RHSReg,
1736 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1737 uint64_t
Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1738 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1743Register AArch64FastISel::emitAnd_ri(MVT RetVT,
Register LHSReg, uint64_t Imm) {
1744 return emitLogicalOp_ri(
ISD::AND, RetVT, LHSReg, Imm);
1748 bool WantZExt, MachineMemOperand *MMO) {
1749 if (!TLI.allowsMisalignedMemoryAccesses(VT))
1753 if (!simplifyAddress(Addr, VT))
1762 bool UseScaled =
true;
1763 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
1768 static const unsigned GPOpcTable[2][8][4] = {
1770 { { AArch64::LDURSBWi, AArch64::LDURSHWi, AArch64::LDURWi,
1772 { AArch64::LDURSBXi, AArch64::LDURSHXi, AArch64::LDURSWi,
1774 { AArch64::LDRSBWui, AArch64::LDRSHWui, AArch64::LDRWui,
1776 { AArch64::LDRSBXui, AArch64::LDRSHXui, AArch64::LDRSWui,
1778 { AArch64::LDRSBWroX, AArch64::LDRSHWroX, AArch64::LDRWroX,
1780 { AArch64::LDRSBXroX, AArch64::LDRSHXroX, AArch64::LDRSWroX,
1782 { AArch64::LDRSBWroW, AArch64::LDRSHWroW, AArch64::LDRWroW,
1784 { AArch64::LDRSBXroW, AArch64::LDRSHXroW, AArch64::LDRSWroW,
1788 { { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1790 { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1792 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1794 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1796 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1798 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1800 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1802 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1807 static const unsigned FPOpcTable[4][2] = {
1808 { AArch64::LDURSi, AArch64::LDURDi },
1809 { AArch64::LDRSui, AArch64::LDRDui },
1810 { AArch64::LDRSroX, AArch64::LDRDroX },
1811 { AArch64::LDRSroW, AArch64::LDRDroW }
1815 const TargetRegisterClass *RC;
1816 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
1817 Addr.getOffsetReg();
1818 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
1823 bool IsRet64Bit = RetVT == MVT::i64;
1829 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][0];
1830 RC = (IsRet64Bit && !WantZExt) ?
1831 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1834 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][1];
1835 RC = (IsRet64Bit && !WantZExt) ?
1836 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1839 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][2];
1840 RC = (IsRet64Bit && !WantZExt) ?
1841 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1844 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][3];
1845 RC = &AArch64::GPR64RegClass;
1848 Opc = FPOpcTable[Idx][0];
1849 RC = &AArch64::FPR32RegClass;
1852 Opc = FPOpcTable[Idx][1];
1853 RC = &AArch64::FPR64RegClass;
1858 Register ResultReg = createResultReg(RC);
1859 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1860 TII.get(
Opc), ResultReg);
1864 if (VT == MVT::i1) {
1865 Register ANDReg = emitAnd_ri(MVT::i32, ResultReg, 1);
1866 assert(ANDReg &&
"Unexpected AND instruction emission failure.");
1872 if (WantZExt && RetVT == MVT::i64 && VT <= MVT::i32) {
1873 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
1874 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1875 TII.get(AArch64::SUBREG_TO_REG), Reg64)
1878 .
addImm(AArch64::sub_32);
1884bool AArch64FastISel::selectAddSub(
const Instruction *
I) {
1886 if (!isTypeSupported(
I->getType(), VT,
true))
1890 return selectOperator(
I,
I->getOpcode());
1893 switch (
I->getOpcode()) {
1896 case Instruction::Add:
1897 ResultReg = emitAdd(VT,
I->getOperand(0),
I->getOperand(1));
1899 case Instruction::Sub:
1900 ResultReg = emitSub(VT,
I->getOperand(0),
I->getOperand(1));
1906 updateValueMap(
I, ResultReg);
1910bool AArch64FastISel::selectLogicalOp(
const Instruction *
I) {
1912 if (!isTypeSupported(
I->getType(), VT,
true))
1916 return selectOperator(
I,
I->getOpcode());
1919 switch (
I->getOpcode()) {
1922 case Instruction::And:
1923 ResultReg = emitLogicalOp(
ISD::AND, VT,
I->getOperand(0),
I->getOperand(1));
1925 case Instruction::Or:
1926 ResultReg = emitLogicalOp(
ISD::OR, VT,
I->getOperand(0),
I->getOperand(1));
1928 case Instruction::Xor:
1929 ResultReg = emitLogicalOp(
ISD::XOR, VT,
I->getOperand(0),
I->getOperand(1));
1935 updateValueMap(
I, ResultReg);
1939bool AArch64FastISel::selectLoad(
const Instruction *
I) {
1944 if (!isTypeSupported(
I->getType(), VT,
true) ||
1948 const Value *SV =
I->getOperand(0);
1949 if (TLI.supportSwiftError()) {
1953 if (Arg->hasSwiftErrorAttr())
1958 if (Alloca->isSwiftError())
1965 if (!computeAddress(
I->getOperand(0), Addr,
I->getType()))
1969 bool WantZExt =
true;
1971 const Value *IntExtVal =
nullptr;
1972 if (
I->hasOneUse()) {
1974 if (isTypeSupported(ZE->getType(), RetVT))
1979 if (isTypeSupported(SE->getType(), RetVT))
1988 emitLoad(VT, RetVT, Addr, WantZExt, createMachineMemOperandFor(
I));
2009 auto *
MI =
MRI.getUniqueVRegDef(
Reg);
2011 if (RetVT == MVT::i64 && VT <= MVT::i32) {
2015 ResultReg = std::prev(
I)->getOperand(0).getReg();
2016 removeDeadCode(
I, std::next(
I));
2018 ResultReg = fastEmitInst_extractsubreg(MVT::i32, ResultReg,
2021 updateValueMap(
I, ResultReg);
2030 for (
auto &Opnd :
MI->uses()) {
2032 Reg = Opnd.getReg();
2037 removeDeadCode(
I, std::next(
I));
2042 updateValueMap(IntExtVal, ResultReg);
2046 updateValueMap(
I, ResultReg);
2050bool AArch64FastISel::emitStoreRelease(MVT VT,
Register SrcReg,
2052 MachineMemOperand *MMO) {
2055 default:
return false;
2056 case MVT::i8:
Opc = AArch64::STLRB;
break;
2057 case MVT::i16:
Opc = AArch64::STLRH;
break;
2058 case MVT::i32:
Opc = AArch64::STLRW;
break;
2059 case MVT::i64:
Opc = AArch64::STLRX;
break;
2062 const MCInstrDesc &
II =
TII.get(
Opc);
2065 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2073 MachineMemOperand *MMO) {
2074 if (!TLI.allowsMisalignedMemoryAccesses(VT))
2078 if (!simplifyAddress(Addr, VT))
2087 bool UseScaled =
true;
2088 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
2093 static const unsigned OpcTable[4][6] = {
2094 { AArch64::STURBBi, AArch64::STURHHi, AArch64::STURWi, AArch64::STURXi,
2095 AArch64::STURSi, AArch64::STURDi },
2096 { AArch64::STRBBui, AArch64::STRHHui, AArch64::STRWui, AArch64::STRXui,
2097 AArch64::STRSui, AArch64::STRDui },
2098 { AArch64::STRBBroX, AArch64::STRHHroX, AArch64::STRWroX, AArch64::STRXroX,
2099 AArch64::STRSroX, AArch64::STRDroX },
2100 { AArch64::STRBBroW, AArch64::STRHHroW, AArch64::STRWroW, AArch64::STRXroW,
2101 AArch64::STRSroW, AArch64::STRDroW }
2105 bool VTIsi1 =
false;
2106 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
2107 Addr.getOffsetReg();
2108 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
2115 case MVT::i1: VTIsi1 =
true; [[fallthrough]];
2116 case MVT::i8:
Opc = OpcTable[Idx][0];
break;
2117 case MVT::i16:
Opc = OpcTable[Idx][1];
break;
2118 case MVT::i32:
Opc = OpcTable[Idx][2];
break;
2119 case MVT::i64:
Opc = OpcTable[Idx][3];
break;
2120 case MVT::f32:
Opc = OpcTable[Idx][4];
break;
2121 case MVT::f64:
Opc = OpcTable[Idx][5];
break;
2125 if (VTIsi1 && SrcReg != AArch64::WZR) {
2126 Register ANDReg = emitAnd_ri(MVT::i32, SrcReg, 1);
2127 assert(ANDReg &&
"Unexpected AND instruction emission failure.");
2131 const MCInstrDesc &
II =
TII.get(
Opc);
2133 MachineInstrBuilder MIB =
2140bool AArch64FastISel::selectStore(
const Instruction *
I) {
2142 const Value *Op0 =
I->getOperand(0);
2146 if (!isTypeSupported(Op0->
getType(), VT,
true))
2149 const Value *PtrV =
I->getOperand(1);
2150 if (TLI.supportSwiftError()) {
2154 if (Arg->hasSwiftErrorAttr())
2159 if (Alloca->isSwiftError())
2169 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2171 if (CF->isZero() && !CF->isNegative()) {
2173 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2178 SrcReg = getRegForValue(Op0);
2186 if (
SI->isAtomic()) {
2191 Register AddrReg = getRegForValue(PtrV);
2194 return emitStoreRelease(VT, SrcReg, AddrReg,
2195 createMachineMemOperandFor(
I));
2201 if (!computeAddress(PtrV, Addr, Op0->
getType()))
2204 if (!
emitStore(VT, SrcReg, Addr, createMachineMemOperandFor(
I)))
2256bool AArch64FastISel::emitCompareAndBranch(
const BranchInst *BI) {
2260 if (FuncInfo.MF->getFunction().hasFnAttribute(
2261 Attribute::SpeculativeLoadHardening))
2280 MachineBasicBlock *FBB = FuncInfo.getMBB(BI->
getSuccessor(1));
2283 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2290 switch (Predicate) {
2302 if (AI->
getOpcode() == Instruction::And && isValueAvailable(AI)) {
2307 if (
C->getValue().isPowerOf2())
2311 if (
C->getValue().isPowerOf2()) {
2312 TestBit =
C->getValue().logBase2();
2343 static const unsigned OpcTable[2][2][2] = {
2344 { {AArch64::CBZW, AArch64::CBZX },
2345 {AArch64::CBNZW, AArch64::CBNZX} },
2346 { {AArch64::TBZW, AArch64::TBZX },
2347 {AArch64::TBNZW, AArch64::TBNZX} }
2350 bool IsBitTest = TestBit != -1;
2351 bool Is64Bit = BW == 64;
2352 if (TestBit < 32 && TestBit >= 0)
2355 unsigned Opc = OpcTable[IsBitTest][IsCmpNE][Is64Bit];
2356 const MCInstrDesc &
II =
TII.get(
Opc);
2362 if (BW == 64 && !Is64Bit)
2363 SrcReg = fastEmitInst_extractsubreg(MVT::i32, SrcReg, AArch64::sub_32);
2365 if ((BW < 32) && !IsBitTest)
2366 SrcReg = emitIntExt(VT, SrcReg, MVT::i32,
true);
2370 MachineInstrBuilder MIB =
2371 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
2381bool AArch64FastISel::selectBranch(
const Instruction *
I) {
2384 MachineBasicBlock *MSucc = FuncInfo.getMBB(BI->
getSuccessor(0));
2390 MachineBasicBlock *FBB = FuncInfo.getMBB(BI->
getSuccessor(1));
2393 if (CI->
hasOneUse() && isValueAvailable(CI)) {
2396 switch (Predicate) {
2400 fastEmitBranch(FBB, MIMD.getDL());
2403 fastEmitBranch(
TBB, MIMD.getDL());
2408 if (emitCompareAndBranch(BI))
2412 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2425 switch (Predicate) {
2441 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2447 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2455 uint64_t
Imm = CI->getZExtValue();
2457 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::B))
2462 auto BranchProbability = FuncInfo.BPI->getEdgeProbability(
2464 FuncInfo.MBB->addSuccessor(Target, BranchProbability);
2466 FuncInfo.MBB->addSuccessorWithoutProb(Target);
2478 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2492 unsigned Opcode = AArch64::TBNZW;
2493 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2495 Opcode = AArch64::TBZW;
2498 const MCInstrDesc &
II =
TII.get(Opcode);
2501 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2502 .
addReg(ConstrainedCondReg)
2510bool AArch64FastISel::selectIndirectBr(
const Instruction *
I) {
2517 if (FuncInfo.MF->getFunction().hasFnAttribute(
"ptrauth-indirect-gotos"))
2521 const MCInstrDesc &
II =
TII.get(AArch64::BR);
2527 FuncInfo.MBB->addSuccessor(FuncInfo.getMBB(Succ));
2532bool AArch64FastISel::selectCmp(
const Instruction *
I) {
2542 switch (Predicate) {
2546 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2547 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2548 TII.get(TargetOpcode::COPY), ResultReg)
2552 ResultReg = fastEmit_i(MVT::i32, MVT::i32,
ISD::Constant, 1);
2557 updateValueMap(
I, ResultReg);
2565 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2569 static unsigned CondCodeTable[2][2] = {
2574 switch (Predicate) {
2586 Register TmpReg1 = createResultReg(&AArch64::GPR32RegClass);
2587 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2592 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2598 updateValueMap(
I, ResultReg);
2606 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2612 updateValueMap(
I, ResultReg);
2618bool AArch64FastISel::optimizeSelect(
const SelectInst *SI) {
2619 if (!
SI->getType()->isIntegerTy(1))
2622 const Value *Src1Val, *Src2Val;
2624 bool NeedExtraOp =
false;
2627 Src1Val =
SI->getCondition();
2628 Src2Val =
SI->getFalseValue();
2629 Opc = AArch64::ORRWrr;
2632 Src1Val =
SI->getFalseValue();
2633 Src2Val =
SI->getCondition();
2634 Opc = AArch64::BICWrr;
2638 Src1Val =
SI->getCondition();
2639 Src2Val =
SI->getTrueValue();
2640 Opc = AArch64::ORRWrr;
2644 Src1Val =
SI->getCondition();
2645 Src2Val =
SI->getTrueValue();
2646 Opc = AArch64::ANDWrr;
2653 Register Src1Reg = getRegForValue(Src1Val);
2657 Register Src2Reg = getRegForValue(Src2Val);
2662 Src1Reg = emitLogicalOp_ri(
ISD::XOR, MVT::i32, Src1Reg, 1);
2664 Register ResultReg = fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, Src1Reg,
2666 updateValueMap(SI, ResultReg);
2670bool AArch64FastISel::selectSelect(
const Instruction *
I) {
2673 if (!isTypeSupported(
I->getType(), VT))
2677 const TargetRegisterClass *RC;
2685 Opc = AArch64::CSELWr;
2686 RC = &AArch64::GPR32RegClass;
2689 Opc = AArch64::CSELXr;
2690 RC = &AArch64::GPR64RegClass;
2693 Opc = AArch64::FCSELSrrr;
2694 RC = &AArch64::FPR32RegClass;
2697 Opc = AArch64::FCSELDrrr;
2698 RC = &AArch64::FPR64RegClass;
2707 if (optimizeSelect(SI))
2711 if (foldXALUIntrinsic(CC,
I,
Cond)) {
2717 isValueAvailable(
Cond)) {
2721 const Value *FoldSelect =
nullptr;
2722 switch (Predicate) {
2726 FoldSelect =
SI->getFalseValue();
2729 FoldSelect =
SI->getTrueValue();
2734 Register SrcReg = getRegForValue(FoldSelect);
2738 updateValueMap(
I, SrcReg);
2748 switch (Predicate) {
2766 const MCInstrDesc &
II =
TII.get(AArch64::ANDSWri);
2770 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II,
2776 Register Src1Reg = getRegForValue(
SI->getTrueValue());
2777 Register Src2Reg = getRegForValue(
SI->getFalseValue());
2779 if (!Src1Reg || !Src2Reg)
2783 Src2Reg = fastEmitInst_rri(
Opc, RC, Src1Reg, Src2Reg, ExtraCC);
2785 Register ResultReg = fastEmitInst_rri(
Opc, RC, Src1Reg, Src2Reg, CC);
2786 updateValueMap(
I, ResultReg);
2790bool AArch64FastISel::selectFPExt(
const Instruction *
I) {
2792 if (!
I->getType()->isDoubleTy() || !
V->getType()->isFloatTy())
2799 Register ResultReg = createResultReg(&AArch64::FPR64RegClass);
2800 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTDSr),
2802 updateValueMap(
I, ResultReg);
2806bool AArch64FastISel::selectFPTrunc(
const Instruction *
I) {
2808 if (!
I->getType()->isFloatTy() || !
V->getType()->isDoubleTy())
2815 Register ResultReg = createResultReg(&AArch64::FPR32RegClass);
2816 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTSDr),
2818 updateValueMap(
I, ResultReg);
2823bool AArch64FastISel::selectFPToInt(
const Instruction *
I,
bool Signed) {
2825 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2828 Register SrcReg = getRegForValue(
I->getOperand(0));
2832 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2833 if (SrcVT == MVT::f128 || SrcVT == MVT::f16 || SrcVT == MVT::bf16)
2837 if (SrcVT == MVT::f64) {
2839 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWDr : AArch64::FCVTZSUXDr;
2841 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWDr : AArch64::FCVTZUUXDr;
2844 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWSr : AArch64::FCVTZSUXSr;
2846 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWSr : AArch64::FCVTZUUXSr;
2848 Register ResultReg = createResultReg(
2849 DestVT == MVT::i32 ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass);
2850 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
2852 updateValueMap(
I, ResultReg);
2856bool AArch64FastISel::selectIntToFP(
const Instruction *
I,
bool Signed) {
2858 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2861 if (DestVT == MVT::f16 || DestVT == MVT::bf16)
2864 assert((DestVT == MVT::f32 || DestVT == MVT::f64) &&
2865 "Unexpected value type.");
2867 Register SrcReg = getRegForValue(
I->getOperand(0));
2871 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2874 if (SrcVT == MVT::i16 || SrcVT == MVT::i8 || SrcVT == MVT::i1) {
2882 if (SrcVT == MVT::i64) {
2884 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUXSri : AArch64::SCVTFUXDri;
2886 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUXSri : AArch64::UCVTFUXDri;
2889 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUWSri : AArch64::SCVTFUWDri;
2891 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUWSri : AArch64::UCVTFUWDri;
2894 Register ResultReg = fastEmitInst_r(
Opc, TLI.getRegClassFor(DestVT), SrcReg);
2895 updateValueMap(
I, ResultReg);
2899bool AArch64FastISel::fastLowerArguments() {
2900 if (!FuncInfo.CanLowerReturn)
2907 CallingConv::ID CC =
F->getCallingConv();
2908 if (CC != CallingConv::C && CC != CallingConv::Swift)
2915 unsigned GPRCnt = 0;
2916 unsigned FPRCnt = 0;
2917 for (
auto const &Arg :
F->args()) {
2918 if (Arg.hasAttribute(Attribute::ByVal) ||
2919 Arg.hasAttribute(Attribute::InReg) ||
2920 Arg.hasAttribute(Attribute::StructRet) ||
2921 Arg.hasAttribute(Attribute::SwiftSelf) ||
2922 Arg.hasAttribute(Attribute::SwiftAsync) ||
2923 Arg.hasAttribute(Attribute::SwiftError) ||
2924 Arg.hasAttribute(Attribute::Nest))
2927 Type *ArgTy = Arg.getType();
2931 EVT ArgVT = TLI.getValueType(
DL, ArgTy);
2943 if (VT >= MVT::i1 && VT <= MVT::i64)
2945 else if ((VT >= MVT::f16 && VT <= MVT::f64) || VT.
is64BitVector() ||
2951 if (GPRCnt > 8 || FPRCnt > 8)
2956 { AArch64::W0, AArch64::W1, AArch64::W2, AArch64::W3, AArch64::W4,
2957 AArch64::W5, AArch64::W6, AArch64::W7 },
2958 { AArch64::X0, AArch64::X1, AArch64::X2, AArch64::X3, AArch64::X4,
2959 AArch64::X5, AArch64::X6, AArch64::X7 },
2960 { AArch64::H0, AArch64::H1, AArch64::H2, AArch64::H3, AArch64::H4,
2961 AArch64::H5, AArch64::H6, AArch64::H7 },
2962 { AArch64::S0, AArch64::S1, AArch64::S2, AArch64::S3, AArch64::S4,
2963 AArch64::S5, AArch64::S6, AArch64::S7 },
2964 { AArch64::D0, AArch64::D1, AArch64::D2, AArch64::D3, AArch64::D4,
2965 AArch64::D5, AArch64::D6, AArch64::D7 },
2966 { AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,
2967 AArch64::Q5, AArch64::Q6, AArch64::Q7 }
2970 unsigned GPRIdx = 0;
2971 unsigned FPRIdx = 0;
2972 for (
auto const &Arg :
F->args()) {
2973 MVT VT = TLI.getSimpleValueType(
DL, Arg.getType());
2975 const TargetRegisterClass *RC;
2976 if (VT >= MVT::i1 && VT <= MVT::i32) {
2978 RC = &AArch64::GPR32RegClass;
2980 }
else if (VT == MVT::i64) {
2982 RC = &AArch64::GPR64RegClass;
2983 }
else if (VT == MVT::f16 || VT == MVT::bf16) {
2985 RC = &AArch64::FPR16RegClass;
2986 }
else if (VT == MVT::f32) {
2988 RC = &AArch64::FPR32RegClass;
2991 RC = &AArch64::FPR64RegClass;
2994 RC = &AArch64::FPR128RegClass;
2998 Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
3002 Register ResultReg = createResultReg(RC);
3003 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3004 TII.get(TargetOpcode::COPY), ResultReg)
3006 updateValueMap(&Arg, ResultReg);
3011bool AArch64FastISel::processCallArgs(CallLoweringInfo &CLI,
3012 SmallVectorImpl<MVT> &OutVTs,
3013 SmallVectorImpl<Type *> &OrigTys,
3014 unsigned &NumBytes) {
3015 CallingConv::ID CC = CLI.CallConv;
3017 CCState CCInfo(CC,
false, *FuncInfo.MF, ArgLocs, *
Context);
3018 CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, OrigTys,
3019 CCAssignFnForCall(CC));
3022 NumBytes = CCInfo.getStackSize();
3025 unsigned AdjStackDown =
TII.getCallFrameSetupOpcode();
3026 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackDown))
3030 for (CCValAssign &VA : ArgLocs) {
3031 const Value *ArgVal = CLI.OutVals[VA.getValNo()];
3032 MVT ArgVT = OutVTs[VA.getValNo()];
3034 Register ArgReg = getRegForValue(ArgVal);
3039 switch (VA.getLocInfo()) {
3043 MVT DestVT = VA.getLocVT();
3045 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
false);
3053 MVT DestVT = VA.getLocVT();
3055 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
true);
3065 if (VA.isRegLoc() && !VA.needsCustom()) {
3066 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3067 TII.get(TargetOpcode::COPY), VA.getLocReg()).
addReg(ArgReg);
3068 CLI.OutRegs.push_back(VA.getLocReg());
3069 }
else if (VA.needsCustom()) {
3073 assert(VA.isMemLoc() &&
"Assuming store on stack.");
3082 unsigned BEAlign = 0;
3083 if (ArgSize < 8 && !Subtarget->isLittleEndian())
3084 BEAlign = 8 - ArgSize;
3087 Addr.setKind(Address::RegBase);
3088 Addr.setReg(AArch64::SP);
3089 Addr.setOffset(VA.getLocMemOffset() + BEAlign);
3092 MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
3096 if (!
emitStore(ArgVT, ArgReg, Addr, MMO))
3103bool AArch64FastISel::finishCall(CallLoweringInfo &CLI,
unsigned NumBytes) {
3104 CallingConv::ID CC = CLI.CallConv;
3107 unsigned AdjStackUp =
TII.getCallFrameDestroyOpcode();
3108 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackUp))
3113 CCState CCInfo(CC,
false, *FuncInfo.MF, RVLocs, *
Context);
3114 CCInfo.AnalyzeCallResult(CLI.Ins, CCAssignFnForCall(CC));
3116 Register ResultReg = FuncInfo.CreateRegs(CLI.RetTy);
3117 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
3118 CCValAssign &VA = RVLocs[i];
3127 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
3133 CLI.ResultReg = ResultReg;
3134 CLI.NumResultRegs = RVLocs.
size();
3139bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
3140 CallingConv::ID CC = CLI.CallConv;
3141 bool IsTailCall = CLI.IsTailCall;
3142 bool IsVarArg = CLI.IsVarArg;
3146 if (!Callee && !Symbol)
3151 if (CLI.CB && CLI.CB->hasFnAttr(Attribute::ReturnsTwice) &&
3152 !Subtarget->noBTIAtReturnTwice() &&
3153 MF->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement())
3157 if (CLI.CB && CLI.CB->isIndirectCall() &&
3181 if (MF->getFunction().getParent()->getRtLibUseGOT())
3191 for (
auto Flag : CLI.OutFlags)
3193 Flag.isSwiftSelf() ||
Flag.isSwiftAsync() ||
Flag.isSwiftError())
3199 OutVTs.
reserve(CLI.OutVals.size());
3201 for (
auto *Val : CLI.OutVals) {
3203 if (!isTypeLegal(Val->getType(), VT) &&
3204 !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16))
3216 if (Callee && !computeCallAddress(Callee, Addr))
3223 Addr.getGlobalValue()->hasExternalWeakLinkage())
3228 if (!processCallArgs(CLI, OutVTs, OrigTys, NumBytes))
3236 MachineInstrBuilder MIB;
3238 const MCInstrDesc &
II =
3240 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II);
3243 else if (Addr.getGlobalValue())
3245 else if (Addr.getReg()) {
3253 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
3254 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
3258 CallReg = createResultReg(&AArch64::GPR64RegClass);
3259 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3260 TII.get(AArch64::LDRXui), CallReg)
3264 }
else if (Addr.getGlobalValue())
3265 CallReg = materializeGV(Addr.getGlobalValue());
3266 else if (Addr.getReg())
3267 CallReg = Addr.getReg();
3274 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II).
addReg(CallReg);
3278 for (
auto Reg : CLI.OutRegs)
3288 return finishCall(CLI, NumBytes);
3291bool AArch64FastISel::isMemCpySmall(uint64_t Len, MaybeAlign Alignment) {
3293 return Len / Alignment->value() <= 4;
3298bool AArch64FastISel::tryEmitSmallMemCpy(
Address Dest,
Address Src,
3299 uint64_t Len, MaybeAlign Alignment) {
3301 if (!isMemCpySmall(Len, Alignment))
3304 int64_t UnscaledOffset = 0;
3310 if (!Alignment || *Alignment >= 8) {
3321 assert(Alignment &&
"Alignment is set in this branch");
3323 if (Len >= 4 && *Alignment == 4)
3325 else if (Len >= 2 && *Alignment == 2)
3341 UnscaledOffset +=
Size;
3344 Dest.setOffset(OrigDest.getOffset() + UnscaledOffset);
3345 Src.setOffset(OrigSrc.getOffset() + UnscaledOffset);
3354 const Instruction *
I,
3368 if (!isTypeLegal(RetTy, RetVT))
3371 if (RetVT != MVT::i32 && RetVT != MVT::i64)
3386 case Intrinsic::smul_with_overflow:
3388 if (
C->getValue() == 2)
3389 IID = Intrinsic::sadd_with_overflow;
3391 case Intrinsic::umul_with_overflow:
3393 if (
C->getValue() == 2)
3394 IID = Intrinsic::uadd_with_overflow;
3402 case Intrinsic::sadd_with_overflow:
3403 case Intrinsic::ssub_with_overflow:
3406 case Intrinsic::uadd_with_overflow:
3409 case Intrinsic::usub_with_overflow:
3412 case Intrinsic::smul_with_overflow:
3413 case Intrinsic::umul_with_overflow:
3419 if (!isValueAvailable(
II))
3425 for (
auto Itr = std::prev(Start); Itr != End; --Itr) {
3433 if (EVI->getAggregateOperand() !=
II)
3441bool AArch64FastISel::fastLowerIntrinsicCall(
const IntrinsicInst *
II) {
3443 switch (
II->getIntrinsicID()) {
3444 default:
return false;
3445 case Intrinsic::frameaddress: {
3446 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3451 Register SrcReg =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3452 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3462 DestReg = fastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,
3464 assert(DestReg &&
"Unexpected LDR instruction emission failure.");
3468 updateValueMap(
II, SrcReg);
3471 case Intrinsic::sponentry: {
3472 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3476 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
3477 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3478 TII.get(AArch64::ADDXri), ResultReg)
3483 updateValueMap(
II, ResultReg);
3486 case Intrinsic::memcpy:
3487 case Intrinsic::memmove: {
3490 if (MTI->isVolatile())
3495 bool IsMemCpy = (
II->getIntrinsicID() == Intrinsic::memcpy);
3500 MaybeAlign Alignment;
3501 if (MTI->getDestAlign() || MTI->getSourceAlign())
3502 Alignment = std::min(MTI->getDestAlign().valueOrOne(),
3503 MTI->getSourceAlign().valueOrOne());
3504 if (isMemCpySmall(Len, Alignment)) {
3506 if (!computeAddress(MTI->getRawDest(), Dest) ||
3507 !computeAddress(MTI->getRawSource(), Src))
3509 if (tryEmitSmallMemCpy(Dest, Src, Len, Alignment))
3514 if (!MTI->getLength()->getType()->isIntegerTy(64))
3517 if (MTI->getSourceAddressSpace() > 255 || MTI->getDestAddressSpace() > 255)
3523 return lowerCallTo(
II, IntrMemName,
II->arg_size() - 1);
3525 case Intrinsic::memset: {
3539 return lowerCallTo(
II,
"memset",
II->arg_size() - 1);
3541 case Intrinsic::sin:
3542 case Intrinsic::cos:
3543 case Intrinsic::tan:
3544 case Intrinsic::pow: {
3546 if (!isTypeLegal(
II->getType(), RetVT))
3549 if (RetVT != MVT::f32 && RetVT != MVT::f64)
3552 static const RTLIB::Libcall LibCallTable[4][2] = {
3553 {RTLIB::SIN_F32, RTLIB::SIN_F64},
3554 {RTLIB::COS_F32, RTLIB::COS_F64},
3555 {RTLIB::TAN_F32, RTLIB::TAN_F64},
3556 {RTLIB::POW_F32, RTLIB::POW_F64}};
3558 bool Is64Bit = RetVT == MVT::f64;
3559 switch (
II->getIntrinsicID()) {
3562 case Intrinsic::sin:
3563 LC = LibCallTable[0][Is64Bit];
3565 case Intrinsic::cos:
3566 LC = LibCallTable[1][Is64Bit];
3568 case Intrinsic::tan:
3569 LC = LibCallTable[2][Is64Bit];
3571 case Intrinsic::pow:
3572 LC = LibCallTable[3][Is64Bit];
3577 Args.reserve(
II->arg_size());
3580 for (
auto &Arg :
II->args())
3581 Args.emplace_back(Arg);
3583 CallLoweringInfo CLI;
3584 MCContext &Ctx = MF->getContext();
3586 RTLIB::LibcallImpl LCImpl = LibcallLowering->getLibcallImpl(LC);
3587 if (LCImpl == RTLIB::Unsupported)
3590 CallingConv::ID CC = LibcallLowering->getLibcallImplCallingConv(LCImpl);
3592 CLI.setCallee(
DL, Ctx, CC,
II->getType(), FuncName, std::move(Args));
3593 if (!lowerCallTo(CLI))
3595 updateValueMap(
II, CLI.ResultReg);
3598 case Intrinsic::fabs: {
3600 if (!isTypeLegal(
II->getType(), VT))
3608 Opc = AArch64::FABSSr;
3611 Opc = AArch64::FABSDr;
3614 Register SrcReg = getRegForValue(
II->getOperand(0));
3617 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3618 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
3620 updateValueMap(
II, ResultReg);
3623 case Intrinsic::trap:
3624 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3627 case Intrinsic::debugtrap:
3628 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3632 case Intrinsic::sqrt: {
3633 Type *RetTy =
II->getCalledFunction()->getReturnType();
3636 if (!isTypeLegal(RetTy, VT))
3639 Register Op0Reg = getRegForValue(
II->getOperand(0));
3647 updateValueMap(
II, ResultReg);
3650 case Intrinsic::sadd_with_overflow:
3651 case Intrinsic::uadd_with_overflow:
3652 case Intrinsic::ssub_with_overflow:
3653 case Intrinsic::usub_with_overflow:
3654 case Intrinsic::smul_with_overflow:
3655 case Intrinsic::umul_with_overflow: {
3659 Type *RetTy = Ty->getTypeAtIndex(0U);
3662 if (!isTypeLegal(RetTy, VT))
3665 if (VT != MVT::i32 && VT != MVT::i64)
3679 case Intrinsic::smul_with_overflow:
3681 if (
C->getValue() == 2) {
3682 IID = Intrinsic::sadd_with_overflow;
3686 case Intrinsic::umul_with_overflow:
3688 if (
C->getValue() == 2) {
3689 IID = Intrinsic::uadd_with_overflow;
3695 Register ResultReg1, ResultReg2, MulReg;
3699 case Intrinsic::sadd_with_overflow:
3700 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3703 case Intrinsic::uadd_with_overflow:
3704 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3707 case Intrinsic::ssub_with_overflow:
3708 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3711 case Intrinsic::usub_with_overflow:
3712 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3715 case Intrinsic::smul_with_overflow: {
3725 if (VT == MVT::i32) {
3726 MulReg = emitSMULL_rr(MVT::i64, LHSReg, RHSReg);
3728 fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3730 emitAddSub_rx(
false, MVT::i64, MulReg, MulSubReg,
3735 assert(VT == MVT::i64 &&
"Unexpected value type.");
3738 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3745 case Intrinsic::umul_with_overflow: {
3755 if (VT == MVT::i32) {
3756 MulReg = emitUMULL_rr(MVT::i64, LHSReg, RHSReg);
3758 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3759 TII.get(AArch64::ANDSXri), AArch64::XZR)
3762 MulReg = fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3764 assert(VT == MVT::i64 &&
"Unexpected value type.");
3767 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3769 emitSubs_rr(VT, AArch64::XZR, UMULHReg,
false);
3776 ResultReg1 = createResultReg(TLI.getRegClassFor(VT));
3777 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3778 TII.get(TargetOpcode::COPY), ResultReg1).
addReg(MulReg);
3784 ResultReg2 = fastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,
3785 AArch64::WZR, AArch64::WZR,
3786 getInvertedCondCode(CC));
3788 assert((ResultReg1 + 1) == ResultReg2 &&
3789 "Nonconsecutive result registers.");
3790 updateValueMap(
II, ResultReg1, 2);
3793 case Intrinsic::aarch64_crc32b:
3794 case Intrinsic::aarch64_crc32h:
3795 case Intrinsic::aarch64_crc32w:
3796 case Intrinsic::aarch64_crc32x:
3797 case Intrinsic::aarch64_crc32cb:
3798 case Intrinsic::aarch64_crc32ch:
3799 case Intrinsic::aarch64_crc32cw:
3800 case Intrinsic::aarch64_crc32cx: {
3801 if (!Subtarget->hasCRC())
3805 switch (
II->getIntrinsicID()) {
3808 case Intrinsic::aarch64_crc32b:
3809 Opc = AArch64::CRC32Brr;
3811 case Intrinsic::aarch64_crc32h:
3812 Opc = AArch64::CRC32Hrr;
3814 case Intrinsic::aarch64_crc32w:
3815 Opc = AArch64::CRC32Wrr;
3817 case Intrinsic::aarch64_crc32x:
3818 Opc = AArch64::CRC32Xrr;
3820 case Intrinsic::aarch64_crc32cb:
3821 Opc = AArch64::CRC32CBrr;
3823 case Intrinsic::aarch64_crc32ch:
3824 Opc = AArch64::CRC32CHrr;
3826 case Intrinsic::aarch64_crc32cw:
3827 Opc = AArch64::CRC32CWrr;
3829 case Intrinsic::aarch64_crc32cx:
3830 Opc = AArch64::CRC32CXrr;
3834 Register LHSReg = getRegForValue(
II->getArgOperand(0));
3835 Register RHSReg = getRegForValue(
II->getArgOperand(1));
3836 if (!LHSReg || !RHSReg)
3840 fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, LHSReg, RHSReg);
3841 updateValueMap(
II, ResultReg);
3848bool AArch64FastISel::selectRet(
const Instruction *
I) {
3850 const Function &
F = *
I->getParent()->getParent();
3852 if (!FuncInfo.CanLowerReturn)
3858 if (TLI.supportSwiftError() &&
3859 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
3862 if (TLI.supportSplitCSR(FuncInfo.MF))
3869 CallingConv::ID CC =
F.getCallingConv();
3875 CCState CCInfo(CC,
F.isVarArg(), *FuncInfo.MF, ValLocs,
I->getContext());
3879 if (ValLocs.
size() != 1)
3882 CCValAssign &VA = ValLocs[0];
3901 if (!
MRI.getRegClass(SrcReg)->contains(DestReg))
3904 EVT RVEVT = TLI.getValueType(
DL, RV->
getType());
3914 if (RVVT == MVT::f128)
3919 if (RVVT != DestVT) {
3920 if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
3923 if (!Outs[0].
Flags.isZExt() && !Outs[0].Flags.isSExt())
3926 bool IsZExt = Outs[0].Flags.isZExt();
3927 SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
3935 SrcReg = emitAnd_ri(MVT::i64, SrcReg, 0xffffffff);
3938 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3939 TII.get(TargetOpcode::COPY), DestReg).
addReg(SrcReg);
3945 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3946 TII.get(AArch64::RET_ReallyLR));
3952bool AArch64FastISel::selectTrunc(
const Instruction *
I) {
3953 Type *DestTy =
I->getType();
3955 Type *SrcTy =
Op->getType();
3957 EVT SrcEVT = TLI.getValueType(
DL, SrcTy,
true);
3958 EVT DestEVT = TLI.getValueType(
DL, DestTy,
true);
3967 if (SrcVT != MVT::i64 && SrcVT != MVT::i32 && SrcVT != MVT::i16 &&
3970 if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8 &&
3984 if (SrcVT == MVT::i64) {
4001 Register Reg32 = fastEmitInst_extractsubreg(MVT::i32, SrcReg,
4004 ResultReg = emitAnd_ri(MVT::i32, Reg32, Mask);
4005 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4007 ResultReg = createResultReg(&AArch64::GPR32RegClass);
4008 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4009 TII.get(TargetOpcode::COPY), ResultReg)
4013 updateValueMap(
I, ResultReg);
4017Register AArch64FastISel::emiti1Ext(
Register SrcReg, MVT DestVT,
bool IsZExt) {
4018 assert((DestVT == MVT::i8 || DestVT == MVT::i16 || DestVT == MVT::i32 ||
4019 DestVT == MVT::i64) &&
4020 "Unexpected value type.");
4022 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4026 Register ResultReg = emitAnd_ri(MVT::i32, SrcReg, 1);
4027 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4028 if (DestVT == MVT::i64) {
4031 Register Reg64 =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4032 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4033 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4036 .
addImm(AArch64::sub_32);
4041 if (DestVT == MVT::i64) {
4045 return fastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,
4060 Opc = AArch64::MADDWrrr; ZReg = AArch64::WZR;
break;
4062 Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR;
break;
4065 const TargetRegisterClass *RC =
4066 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4067 return fastEmitInst_rrr(
Opc, RC, Op0, Op1, ZReg);
4071 if (RetVT != MVT::i64)
4074 return fastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,
4075 Op0, Op1, AArch64::XZR);
4079 if (RetVT != MVT::i64)
4082 return fastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,
4083 Op0, Op1, AArch64::XZR);
4089 bool NeedTrunc =
false;
4094 case MVT::i8:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4095 case MVT::i16:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4096 case MVT::i32:
Opc = AArch64::LSLVWr;
break;
4097 case MVT::i64:
Opc = AArch64::LSLVXr;
break;
4100 const TargetRegisterClass *RC =
4101 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4103 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4105 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4107 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4112 uint64_t Shift,
bool IsZExt) {
4114 "Unexpected source/return type pair.");
4115 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4116 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4117 "Unexpected source value type.");
4118 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4119 RetVT == MVT::i64) &&
"Unexpected return value type.");
4121 bool Is64Bit = (RetVT == MVT::i64);
4122 unsigned RegSize = Is64Bit ? 64 : 32;
4125 const TargetRegisterClass *RC =
4126 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4130 if (RetVT == SrcVT) {
4131 Register ResultReg = createResultReg(RC);
4132 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4133 TII.get(TargetOpcode::COPY), ResultReg)
4137 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4141 if (Shift >= DstBits)
4169 unsigned ImmR =
RegSize - Shift;
4171 unsigned ImmS = std::min<unsigned>(SrcBits - 1, DstBits - 1 - Shift);
4172 static const unsigned OpcTable[2][2] = {
4173 {AArch64::SBFMWri, AArch64::SBFMXri},
4174 {AArch64::UBFMWri, AArch64::UBFMXri}
4176 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4177 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4179 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4180 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4183 .
addImm(AArch64::sub_32);
4186 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4192 bool NeedTrunc =
false;
4197 case MVT::i8:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4198 case MVT::i16:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4199 case MVT::i32:
Opc = AArch64::LSRVWr;
break;
4200 case MVT::i64:
Opc = AArch64::LSRVXr;
break;
4203 const TargetRegisterClass *RC =
4204 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4206 Op0Reg = emitAnd_ri(MVT::i32, Op0Reg, Mask);
4207 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4209 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4211 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4216 uint64_t Shift,
bool IsZExt) {
4218 "Unexpected source/return type pair.");
4219 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4220 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4221 "Unexpected source value type.");
4222 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4223 RetVT == MVT::i64) &&
"Unexpected return value type.");
4225 bool Is64Bit = (RetVT == MVT::i64);
4226 unsigned RegSize = Is64Bit ? 64 : 32;
4229 const TargetRegisterClass *RC =
4230 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4234 if (RetVT == SrcVT) {
4235 Register ResultReg = createResultReg(RC);
4236 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4237 TII.get(TargetOpcode::COPY), ResultReg)
4241 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4245 if (Shift >= DstBits)
4273 if (Shift >= SrcBits && IsZExt)
4274 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4279 Op0 = emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4287 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4288 unsigned ImmS = SrcBits - 1;
4289 static const unsigned OpcTable[2][2] = {
4290 {AArch64::SBFMWri, AArch64::SBFMXri},
4291 {AArch64::UBFMWri, AArch64::UBFMXri}
4293 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4294 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4296 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4297 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4300 .
addImm(AArch64::sub_32);
4303 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4309 bool NeedTrunc =
false;
4314 case MVT::i8:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4315 case MVT::i16:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4316 case MVT::i32:
Opc = AArch64::ASRVWr;
break;
4317 case MVT::i64:
Opc = AArch64::ASRVXr;
break;
4320 const TargetRegisterClass *RC =
4321 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4323 Op0Reg = emitIntExt(RetVT, Op0Reg, MVT::i32,
false);
4324 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4326 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4328 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4333 uint64_t Shift,
bool IsZExt) {
4335 "Unexpected source/return type pair.");
4336 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4337 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4338 "Unexpected source value type.");
4339 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4340 RetVT == MVT::i64) &&
"Unexpected return value type.");
4342 bool Is64Bit = (RetVT == MVT::i64);
4343 unsigned RegSize = Is64Bit ? 64 : 32;
4346 const TargetRegisterClass *RC =
4347 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4351 if (RetVT == SrcVT) {
4352 Register ResultReg = createResultReg(RC);
4353 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4354 TII.get(TargetOpcode::COPY), ResultReg)
4358 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4362 if (Shift >= DstBits)
4390 if (Shift >= SrcBits && IsZExt)
4391 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4393 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4394 unsigned ImmS = SrcBits - 1;
4395 static const unsigned OpcTable[2][2] = {
4396 {AArch64::SBFMWri, AArch64::SBFMXri},
4397 {AArch64::UBFMWri, AArch64::UBFMXri}
4399 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4400 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4402 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4403 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4406 .
addImm(AArch64::sub_32);
4409 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4412Register AArch64FastISel::emitIntExt(MVT SrcVT,
Register SrcReg, MVT DestVT,
4414 assert(DestVT != MVT::i1 &&
"ZeroExt/SignExt an i1?");
4420 if (((DestVT != MVT::i8) && (DestVT != MVT::i16) &&
4421 (DestVT != MVT::i32) && (DestVT != MVT::i64)) ||
4422 ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) &&
4423 (SrcVT != MVT::i16) && (SrcVT != MVT::i32)))
4433 return emiti1Ext(SrcReg, DestVT, IsZExt);
4435 if (DestVT == MVT::i64)
4436 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4438 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4442 if (DestVT == MVT::i64)
4443 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4445 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4449 assert(DestVT == MVT::i64 &&
"IntExt i32 to i32?!?");
4450 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4456 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4458 else if (DestVT == MVT::i64) {
4459 Register Src64 =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4460 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4461 TII.get(AArch64::SUBREG_TO_REG), Src64)
4464 .
addImm(AArch64::sub_32);
4468 const TargetRegisterClass *RC =
4469 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4470 return fastEmitInst_rii(
Opc, RC, SrcReg, 0, Imm);
4477 case AArch64::LDURBBi:
4478 case AArch64::LDURHHi:
4479 case AArch64::LDURWi:
4480 case AArch64::LDRBBui:
4481 case AArch64::LDRHHui:
4482 case AArch64::LDRWui:
4483 case AArch64::LDRBBroX:
4484 case AArch64::LDRHHroX:
4485 case AArch64::LDRWroX:
4486 case AArch64::LDRBBroW:
4487 case AArch64::LDRHHroW:
4488 case AArch64::LDRWroW:
4497 case AArch64::LDURSBWi:
4498 case AArch64::LDURSHWi:
4499 case AArch64::LDURSBXi:
4500 case AArch64::LDURSHXi:
4501 case AArch64::LDURSWi:
4502 case AArch64::LDRSBWui:
4503 case AArch64::LDRSHWui:
4504 case AArch64::LDRSBXui:
4505 case AArch64::LDRSHXui:
4506 case AArch64::LDRSWui:
4507 case AArch64::LDRSBWroX:
4508 case AArch64::LDRSHWroX:
4509 case AArch64::LDRSBXroX:
4510 case AArch64::LDRSHXroX:
4511 case AArch64::LDRSWroX:
4512 case AArch64::LDRSBWroW:
4513 case AArch64::LDRSHWroW:
4514 case AArch64::LDRSBXroW:
4515 case AArch64::LDRSHXroW:
4516 case AArch64::LDRSWroW:
4521bool AArch64FastISel::optimizeIntExtLoad(
const Instruction *
I, MVT RetVT,
4524 if (!LI || !LI->hasOneUse())
4532 MachineInstr *
MI =
MRI.getUniqueVRegDef(
Reg);
4539 const auto *LoadMI =
MI;
4540 if (LoadMI->getOpcode() == TargetOpcode::COPY &&
4541 LoadMI->getOperand(1).getSubReg() == AArch64::sub_32) {
4542 Register LoadReg =
MI->getOperand(1).getReg();
4543 LoadMI =
MRI.getUniqueVRegDef(LoadReg);
4544 assert(LoadMI &&
"Expected valid instruction");
4550 if (RetVT != MVT::i64 || SrcVT > MVT::i32) {
4551 updateValueMap(
I,
Reg);
4556 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
4557 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4558 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4561 .
addImm(AArch64::sub_32);
4564 assert((
MI->getOpcode() == TargetOpcode::COPY &&
4565 MI->getOperand(1).getSubReg() == AArch64::sub_32) &&
4566 "Expected copy instruction");
4567 Reg =
MI->getOperand(1).getReg();
4569 removeDeadCode(
I, std::next(
I));
4571 updateValueMap(
I,
Reg);
4575bool AArch64FastISel::selectIntExt(
const Instruction *
I) {
4577 "Unexpected integer extend instruction.");
4580 if (!isTypeSupported(
I->getType(), RetVT))
4583 if (!isTypeSupported(
I->getOperand(0)->getType(), SrcVT))
4587 if (optimizeIntExtLoad(
I, RetVT, SrcVT))
4590 Register SrcReg = getRegForValue(
I->getOperand(0));
4597 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr())) {
4598 if (RetVT == MVT::i64 && SrcVT != MVT::i64) {
4599 Register ResultReg = createResultReg(&AArch64::GPR64RegClass);
4600 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4601 TII.get(AArch64::SUBREG_TO_REG), ResultReg)
4604 .
addImm(AArch64::sub_32);
4608 updateValueMap(
I, SrcReg);
4613 Register ResultReg = emitIntExt(SrcVT, SrcReg, RetVT, IsZExt);
4617 updateValueMap(
I, ResultReg);
4621bool AArch64FastISel::selectRem(
const Instruction *
I,
unsigned ISDOpcode) {
4622 EVT DestEVT = TLI.getValueType(
DL,
I->getType(),
true);
4627 if (DestVT != MVT::i64 && DestVT != MVT::i32)
4631 bool Is64bit = (DestVT == MVT::i64);
4632 switch (ISDOpcode) {
4636 DivOpc = Is64bit ? AArch64::SDIVXr : AArch64::SDIVWr;
4639 DivOpc = Is64bit ? AArch64::UDIVXr : AArch64::UDIVWr;
4642 unsigned MSubOpc = Is64bit ? AArch64::MSUBXrrr : AArch64::MSUBWrrr;
4643 Register Src0Reg = getRegForValue(
I->getOperand(0));
4647 Register Src1Reg = getRegForValue(
I->getOperand(1));
4651 const TargetRegisterClass *RC =
4652 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4653 Register QuotReg = fastEmitInst_rr(DivOpc, RC, Src0Reg, Src1Reg);
4654 assert(QuotReg &&
"Unexpected DIV instruction emission failure.");
4657 Register ResultReg = fastEmitInst_rrr(MSubOpc, RC, QuotReg, Src1Reg, Src0Reg);
4658 updateValueMap(
I, ResultReg);
4662bool AArch64FastISel::selectMul(
const Instruction *
I) {
4664 if (!isTypeSupported(
I->getType(), VT,
true))
4670 const Value *Src0 =
I->getOperand(0);
4671 const Value *Src1 =
I->getOperand(1);
4673 if (
C->getValue().isPowerOf2())
4678 if (
C->getValue().isPowerOf2()) {
4679 uint64_t ShiftVal =
C->getValue().logBase2();
4685 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), VT)) {
4688 Src0 = ZExt->getOperand(0);
4694 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), VT)) {
4697 Src0 = SExt->getOperand(0);
4702 Register Src0Reg = getRegForValue(Src0);
4706 Register ResultReg = emitLSL_ri(VT, SrcVT, Src0Reg, ShiftVal, IsZExt);
4709 updateValueMap(
I, ResultReg);
4714 Register Src0Reg = getRegForValue(
I->getOperand(0));
4718 Register Src1Reg = getRegForValue(
I->getOperand(1));
4722 Register ResultReg = emitMul_rr(VT, Src0Reg, Src1Reg);
4727 updateValueMap(
I, ResultReg);
4731bool AArch64FastISel::selectShift(
const Instruction *
I) {
4733 if (!isTypeSupported(
I->getType(), RetVT,
true))
4737 return selectOperator(
I,
I->getOpcode());
4741 uint64_t ShiftVal =
C->getZExtValue();
4743 bool IsZExt =
I->getOpcode() != Instruction::AShr;
4744 const Value *Op0 =
I->getOperand(0);
4748 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), TmpVT)) {
4751 Op0 = ZExt->getOperand(0);
4757 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), TmpVT)) {
4760 Op0 = SExt->getOperand(0);
4765 Register Op0Reg = getRegForValue(Op0);
4769 switch (
I->getOpcode()) {
4771 case Instruction::Shl:
4772 ResultReg = emitLSL_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4774 case Instruction::AShr:
4775 ResultReg = emitASR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4777 case Instruction::LShr:
4778 ResultReg = emitLSR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4784 updateValueMap(
I, ResultReg);
4788 Register Op0Reg = getRegForValue(
I->getOperand(0));
4792 Register Op1Reg = getRegForValue(
I->getOperand(1));
4797 switch (
I->getOpcode()) {
4799 case Instruction::Shl:
4800 ResultReg = emitLSL_rr(RetVT, Op0Reg, Op1Reg);
4802 case Instruction::AShr:
4803 ResultReg = emitASR_rr(RetVT, Op0Reg, Op1Reg);
4805 case Instruction::LShr:
4806 ResultReg = emitLSR_rr(RetVT, Op0Reg, Op1Reg);
4813 updateValueMap(
I, ResultReg);
4817bool AArch64FastISel::selectBitCast(
const Instruction *
I) {
4820 if (!isTypeLegal(
I->getOperand(0)->getType(), SrcVT))
4822 if (!isTypeLegal(
I->getType(), RetVT))
4826 if (RetVT == MVT::f32 && SrcVT == MVT::i32)
4827 Opc = AArch64::FMOVWSr;
4828 else if (RetVT == MVT::f64 && SrcVT == MVT::i64)
4829 Opc = AArch64::FMOVXDr;
4830 else if (RetVT == MVT::i32 && SrcVT == MVT::f32)
4831 Opc = AArch64::FMOVSWr;
4832 else if (RetVT == MVT::i64 && SrcVT == MVT::f64)
4833 Opc = AArch64::FMOVDXr;
4837 const TargetRegisterClass *RC =
nullptr;
4840 case MVT::i32: RC = &AArch64::GPR32RegClass;
break;
4841 case MVT::i64: RC = &AArch64::GPR64RegClass;
break;
4842 case MVT::f32: RC = &AArch64::FPR32RegClass;
break;
4843 case MVT::f64: RC = &AArch64::FPR64RegClass;
break;
4845 Register Op0Reg = getRegForValue(
I->getOperand(0));
4849 Register ResultReg = fastEmitInst_r(
Opc, RC, Op0Reg);
4853 updateValueMap(
I, ResultReg);
4857bool AArch64FastISel::selectFRem(
const Instruction *
I) {
4859 if (!isTypeLegal(
I->getType(), RetVT))
4862 RTLIB::LibcallImpl LCImpl =
4864 if (LCImpl == RTLIB::Unsupported)
4868 Args.reserve(
I->getNumOperands());
4871 for (
auto &Arg :
I->operands())
4872 Args.emplace_back(Arg);
4874 CallLoweringInfo CLI;
4875 MCContext &Ctx = MF->getContext();
4876 CallingConv::ID CC = LibcallLowering->getLibcallImplCallingConv(LCImpl);
4879 CLI.setCallee(
DL, Ctx, CC,
I->getType(), FuncName, std::move(Args));
4880 if (!lowerCallTo(CLI))
4882 updateValueMap(
I, CLI.ResultReg);
4886bool AArch64FastISel::selectSDiv(
const Instruction *
I) {
4888 if (!isTypeLegal(
I->getType(), VT))
4895 if ((VT != MVT::i32 && VT != MVT::i64) || !
C ||
4896 !(
C.isPowerOf2() ||
C.isNegatedPowerOf2()))
4899 unsigned Lg2 =
C.countr_zero();
4900 Register Src0Reg = getRegForValue(
I->getOperand(0));
4905 Register ResultReg = emitASR_ri(VT, VT, Src0Reg, Lg2);
4908 updateValueMap(
I, ResultReg);
4912 int64_t Pow2MinusOne = (1ULL << Lg2) - 1;
4913 Register AddReg = emitAdd_ri_(VT, Src0Reg, Pow2MinusOne);
4918 if (!emitICmp_ri(VT, Src0Reg, 0))
4922 const TargetRegisterClass *RC;
4923 if (VT == MVT::i64) {
4924 SelectOpc = AArch64::CSELXr;
4925 RC = &AArch64::GPR64RegClass;
4927 SelectOpc = AArch64::CSELWr;
4928 RC = &AArch64::GPR32RegClass;
4930 Register SelectReg = fastEmitInst_rri(SelectOpc, RC, AddReg, Src0Reg,
4937 Register ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
4940 ResultReg = emitAddSub_rs(
false, VT, ZeroReg, SelectReg,
4943 ResultReg = emitASR_ri(VT, VT, SelectReg, Lg2);
4948 updateValueMap(
I, ResultReg);
4955Register AArch64FastISel::getRegForGEPIndex(
const Value *Idx) {
4956 Register IdxN = getRegForValue(Idx);
4962 MVT PtrVT = TLI.getPointerTy(
DL);
4964 if (IdxVT.
bitsLT(PtrVT)) {
4965 IdxN = emitIntExt(IdxVT.
getSimpleVT(), IdxN, PtrVT,
false);
4966 }
else if (IdxVT.
bitsGT(PtrVT))
4967 llvm_unreachable(
"AArch64 FastISel doesn't support types larger than i64");
4975bool AArch64FastISel::selectGetElementPtr(
const Instruction *
I) {
4979 Register N = getRegForValue(
I->getOperand(0));
4985 uint64_t TotalOffs = 0;
4986 MVT VT = TLI.getPointerTy(
DL);
4989 const Value *Idx = GTI.getOperand();
4990 if (
auto *StTy = GTI.getStructTypeOrNull()) {
4994 TotalOffs +=
DL.getStructLayout(StTy)->getElementOffset(
Field);
5001 TotalOffs += GTI.getSequentialElementStride(
DL) *
5006 N = emitAdd_ri_(VT,
N, TotalOffs);
5013 uint64_t ElementSize = GTI.getSequentialElementStride(
DL);
5014 Register IdxN = getRegForGEPIndex(Idx);
5018 if (ElementSize != 1) {
5022 IdxN = emitMul_rr(VT, IdxN,
C);
5032 N = emitAdd_ri_(VT,
N, TotalOffs);
5036 updateValueMap(
I,
N);
5040bool AArch64FastISel::selectAtomicCmpXchg(
const AtomicCmpXchgInst *
I) {
5041 assert(TM.getOptLevel() == CodeGenOptLevel::None &&
5042 "cmpxchg survived AtomicExpand at optlevel > -O0");
5045 Type *RetTy = RetPairTy->getTypeAtIndex(0U);
5046 assert(RetPairTy->getTypeAtIndex(1U)->isIntegerTy(1) &&
5047 "cmpxchg has a non-i1 status result");
5050 if (!isTypeLegal(RetTy, VT))
5053 const TargetRegisterClass *ResRC;
5054 unsigned Opc, CmpOpc;
5057 if (VT == MVT::i32) {
5058 Opc = AArch64::CMP_SWAP_32;
5059 CmpOpc = AArch64::SUBSWrs;
5060 ResRC = &AArch64::GPR32RegClass;
5061 }
else if (VT == MVT::i64) {
5062 Opc = AArch64::CMP_SWAP_64;
5063 CmpOpc = AArch64::SUBSXrs;
5064 ResRC = &AArch64::GPR64RegClass;
5069 const MCInstrDesc &
II =
TII.get(
Opc);
5071 Register AddrReg = getRegForValue(
I->getPointerOperand());
5072 Register DesiredReg = getRegForValue(
I->getCompareOperand());
5073 Register NewReg = getRegForValue(
I->getNewValOperand());
5075 if (!AddrReg || !DesiredReg || !NewReg)
5082 const Register ResultReg1 = createResultReg(ResRC);
5083 const Register ResultReg2 = createResultReg(&AArch64::GPR32RegClass);
5084 const Register ScratchReg = createResultReg(&AArch64::GPR32RegClass);
5087 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
5094 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CmpOpc))
5095 .
addDef(VT == MVT::i32 ? AArch64::WZR : AArch64::XZR)
5100 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr))
5106 assert((ResultReg1 + 1) == ResultReg2 &&
"Nonconsecutive result registers.");
5107 updateValueMap(
I, ResultReg1, 2);
5111bool AArch64FastISel::fastSelectInstruction(
const Instruction *
I) {
5112 if (TLI.fallBackToDAGISel(*
I))
5114 switch (
I->getOpcode()) {
5117 case Instruction::Add:
5118 case Instruction::Sub:
5119 return selectAddSub(
I);
5120 case Instruction::Mul:
5121 return selectMul(
I);
5122 case Instruction::SDiv:
5123 return selectSDiv(
I);
5124 case Instruction::SRem:
5128 case Instruction::URem:
5132 case Instruction::Shl:
5133 case Instruction::LShr:
5134 case Instruction::AShr:
5135 return selectShift(
I);
5136 case Instruction::And:
5137 case Instruction::Or:
5138 case Instruction::Xor:
5139 return selectLogicalOp(
I);
5140 case Instruction::Br:
5141 return selectBranch(
I);
5142 case Instruction::IndirectBr:
5143 return selectIndirectBr(
I);
5144 case Instruction::BitCast:
5146 return selectBitCast(
I);
5148 case Instruction::FPToSI:
5150 return selectFPToInt(
I,
true);
5152 case Instruction::FPToUI:
5153 return selectFPToInt(
I,
false);
5154 case Instruction::ZExt:
5155 case Instruction::SExt:
5156 return selectIntExt(
I);
5157 case Instruction::Trunc:
5159 return selectTrunc(
I);
5161 case Instruction::FPExt:
5162 return selectFPExt(
I);
5163 case Instruction::FPTrunc:
5164 return selectFPTrunc(
I);
5165 case Instruction::SIToFP:
5167 return selectIntToFP(
I,
true);
5169 case Instruction::UIToFP:
5170 return selectIntToFP(
I,
false);
5171 case Instruction::Load:
5172 return selectLoad(
I);
5173 case Instruction::Store:
5174 return selectStore(
I);
5175 case Instruction::FCmp:
5176 case Instruction::ICmp:
5177 return selectCmp(
I);
5178 case Instruction::Select:
5179 return selectSelect(
I);
5180 case Instruction::Ret:
5181 return selectRet(
I);
5182 case Instruction::FRem:
5183 return selectFRem(
I);
5184 case Instruction::GetElementPtr:
5185 return selectGetElementPtr(
I);
5186 case Instruction::AtomicCmpXchg:
5191 return selectOperator(
I,
I->getOpcode());
5205 return new AArch64FastISel(FuncInfo, LibInfo, LibcallLowering);
unsigned const MachineRegisterInfo * MRI
static bool isIntExtFree(const Instruction *I)
Check if the sign-/zero-extend will be a noop.
static bool isSExtLoad(const MachineInstr *LI)
static AArch64CC::CondCode getCompareCC(CmpInst::Predicate Pred)
static bool isMulPowOf2(const Value *I)
Check if the multiply is by a power-of-2 constant.
static unsigned getImplicitScaleFactor(MVT VT)
Determine the implicit scale factor that is applied by a memory operation for a given value type.
static bool isZExtLoad(const MachineInstr *LI)
static unsigned selectBinaryOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
Select the AArch64 opcode for the basic binary operation GenericOpc (such as G_OR or G_SDIV),...
static void emitLoad(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2, int Offset, bool IsPostDec)
Emit a load-pair instruction for frame-destroy.
static void emitStore(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2, int Offset, bool IsPreDec)
Emit a store-pair instruction for frame-setup.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
This file defines the FastISel class.
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
uint64_t IntrinsicInst * II
OptimizedStructLayoutField Field
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
SI Pre allocate WWM Registers
This file defines the SmallVector class.
static SDValue emitCmp(SelectionDAG &DAG, const SDLoc &DL, Comparison &C)
static const unsigned FramePtr
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
bool isAnyArgRegReserved(const MachineFunction &MF) const
void emitReservedArgRegCallError(const MachineFunction &MF) const
Register getFrameRegister(const MachineFunction &MF) const override
bool isTargetWindows() const
const AArch64RegisterInfo * getRegisterInfo() const override
bool useSmallAddressing() const
bool isTargetDarwin() const
bool isTargetILP32() const
bool isTargetMachO() const
unsigned ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const
ClassifyGlobalReference - Find the target operand flags that describe how a global value should be re...
bool isLittleEndian() const
bool isWindowsArm64EC() const
bool hasCustomCallingConv() const
PointerType * getType() const
Overload to return most specific pointer type.
InstListType::const_iterator const_iterator
BasicBlock * getSuccessor(unsigned i) const
bool isUnconditional() const
Value * getCondition() const
Register getLocReg() const
LocInfo getLocInfo() const
unsigned getValNo() const
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
const APFloat & getValueAPF() const
bool isNegative() const
Return true if the sign bit is set.
bool isZero() const
Return true if the value is positive or negative zero.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
LLVM_ABI bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
constexpr bool isVector() const
One or more elements.
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
bool selectBitCast(const User *I)
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
PointerType * getType() const
Global values are always pointers.
iterator_range< succ_op_iterator > successors()
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
Tracks which library functions to use for a particular subtarget.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
bool isVector() const
Return true if this is a vector value type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
bool isValid() const
Return true if this is a valid simple valuetype.
static MVT getIntegerVT(unsigned BitWidth)
bool is64BitVector() const
Return true if this is a 64-bit vector type.
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
void setFrameAddressIsTaken(bool T)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Flags
Flags values. These may be or'd together.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
Value * getLength() const
unsigned getDestAddressSpace() const
constexpr unsigned id() const
SMEAttrs is a utility class to parse the SME ACLE attributes on functions.
bool hasStreamingCompatibleInterface() const
bool hasAgnosticZAInterface() const
bool hasStreamingInterfaceOrBody() const
void reserve(size_type N)
void push_back(const T &Elt)
TypeSize getElementOffset(unsigned Idx) const
Provides information about what library functions are available for the current target.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isArrayTy() const
True if this is an instance of ArrayType.
bool isPointerTy() const
True if this is an instance of PointerType.
bool isStructTy() const
True if this is an instance of StructType.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_PREL
MO_PREL - Indicates that the bits of the symbol operand represented by MO_G0 etc are PC relative.
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering)
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ ADD
Simple integer binary arithmetic operators.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
LLVM_ABI Libcall getREM(EVT VT)
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ User
could "use" a pointer
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
LLVM_ABI void GetReturnInfo(CallingConv::ID CC, Type *ReturnType, AttributeList attr, SmallVectorImpl< ISD::OutputArg > &Outs, const TargetLowering &TLI, const DataLayout &DL)
Given an LLVM IR type and return type attributes, compute the return value EVTs and flags,...
bool CC_AArch64_Win64PCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr unsigned getKillRegState(bool B)
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_AArch64_DarwinPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
unsigned getBLRCallOpcode(const MachineFunction &MF)
Return opcode to be used for indirect calls.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
gep_type_iterator gep_type_end(const User *GEP)
bool isReleaseOrStronger(AtomicOrdering AO)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
bool CC_AArch64_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
generic_gep_type_iterator<> gep_type_iterator
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
AtomicOrdering
Atomic ordering for LLVM's memory model.
bool CC_AArch64_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
bool RetCC_AArch64_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
gep_type_iterator gep_type_begin(const User *GEP)
bool CC_AArch64_Win64_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
ElementCount getVectorElementCount() const
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool isVector() const
Return true if this is a vector value type.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.