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))
487 .
addReg(ResultReg, RegState::Kill)
492 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
510 Register DstReg = createResultReg(&AArch64::GPR64commonRegClass);
511 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::MOVKXi),
520 ResultReg = createResultReg(&AArch64::GPR64spRegClass);
521 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
531Register AArch64FastISel::fastMaterializeConstant(
const Constant *
C) {
532 EVT CEVT = TLI.getValueType(
DL,
C->getType(),
true);
541 assert(VT == MVT::i64 &&
"Expected 64-bit pointers");
542 return materializeInt(ConstantInt::get(Type::getInt64Ty(*
Context), 0), VT);
546 return materializeInt(CI, VT);
548 return materializeFP(CFP, VT);
550 return materializeGV(GV);
555Register AArch64FastISel::fastMaterializeFloatZero(
const ConstantFP *CFP) {
557 "Floating-point constant is not a positive zero.");
559 if (!isTypeLegal(CFP->
getType(), VT))
562 if (VT != MVT::f32 && VT != MVT::f64)
565 bool Is64Bit = (VT == MVT::f64);
566 unsigned ZReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
567 unsigned Opc = Is64Bit ? AArch64::FMOVXDr : AArch64::FMOVWSr;
568 return fastEmitInst_r(
Opc, TLI.getRegClassFor(VT), ZReg);
575 if (
C->getValue().isPowerOf2())
578 if (
C->getValue().isPowerOf2())
585bool AArch64FastISel::computeAddress(
const Value *Obj,
Address &Addr,
Type *Ty)
587 const User *
U =
nullptr;
588 unsigned Opcode = Instruction::UserOp1;
592 if (FuncInfo.StaticAllocaMap.count(
static_cast<const AllocaInst *
>(Obj)) ||
593 FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
594 Opcode =
I->getOpcode();
598 Opcode =
C->getOpcode();
603 if (Ty->getAddressSpace() > 255)
611 case Instruction::BitCast:
613 return computeAddress(
U->getOperand(0), Addr, Ty);
615 case Instruction::IntToPtr:
617 if (TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
618 TLI.getPointerTy(
DL))
619 return computeAddress(
U->getOperand(0), Addr, Ty);
622 case Instruction::PtrToInt:
624 if (TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
625 return computeAddress(
U->getOperand(0), Addr, Ty);
628 case Instruction::GetElementPtr: {
630 uint64_t TmpOffset = Addr.getOffset();
636 const Value *
Op = GTI.getOperand();
637 if (StructType *STy = GTI.getStructTypeOrNull()) {
638 const StructLayout *SL =
DL.getStructLayout(STy);
642 uint64_t S = GTI.getSequentialElementStride(
DL);
649 if (canFoldAddIntoGEP(U,
Op)) {
659 goto unsupported_gep;
665 Addr.setOffset(TmpOffset);
666 if (computeAddress(
U->getOperand(0), Addr, Ty))
675 case Instruction::Alloca: {
677 DenseMap<const AllocaInst *, int>::iterator
SI =
678 FuncInfo.StaticAllocaMap.find(AI);
679 if (SI != FuncInfo.StaticAllocaMap.end()) {
680 Addr.setKind(Address::FrameIndexBase);
681 Addr.setFI(
SI->second);
686 case Instruction::Add: {
696 return computeAddress(
LHS, Addr, Ty);
700 if (computeAddress(
LHS, Addr, Ty) && computeAddress(
RHS, Addr, Ty))
706 case Instruction::Sub: {
713 return computeAddress(
LHS, Addr, Ty);
717 case Instruction::Shl: {
718 if (Addr.getOffsetReg())
726 if (Val < 1 || Val > 3)
729 uint64_t NumBytes = 0;
731 uint64_t NumBits =
DL.getTypeSizeInBits(Ty);
732 NumBytes = NumBits / 8;
737 if (NumBytes != (1ULL << Val))
743 const Value *Src =
U->getOperand(0);
745 if (FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
749 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
751 Src = ZE->getOperand(0);
755 SE->getOperand(0)->getType()->isIntegerTy(32)) {
757 Src = SE->getOperand(0);
764 if (AI->
getOpcode() == Instruction::And) {
769 if (
C->getValue() == 0xffffffff)
773 if (
C->getValue() == 0xffffffff) {
778 Reg = fastEmitInst_extractsubreg(MVT::i32,
Reg, AArch64::sub_32);
779 Addr.setOffsetReg(
Reg);
787 Addr.setOffsetReg(
Reg);
790 case Instruction::Mul: {
791 if (Addr.getOffsetReg())
802 if (
C->getValue().isPowerOf2())
807 unsigned Val =
C->getValue().logBase2();
808 if (Val < 1 || Val > 3)
811 uint64_t NumBytes = 0;
813 uint64_t NumBits =
DL.getTypeSizeInBits(Ty);
814 NumBytes = NumBits / 8;
819 if (NumBytes != (1ULL << Val))
827 if (FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
831 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
833 Src = ZE->getOperand(0);
837 SE->getOperand(0)->getType()->isIntegerTy(32)) {
839 Src = SE->getOperand(0);
848 Addr.setOffsetReg(
Reg);
851 case Instruction::And: {
852 if (Addr.getOffsetReg())
855 if (!Ty ||
DL.getTypeSizeInBits(Ty) != 8)
862 if (
C->getValue() == 0xffffffff)
866 if (
C->getValue() == 0xffffffff) {
874 Reg = fastEmitInst_extractsubreg(MVT::i32,
Reg, AArch64::sub_32);
875 Addr.setOffsetReg(
Reg);
880 case Instruction::SExt:
881 case Instruction::ZExt: {
882 if (!Addr.getReg() || Addr.getOffsetReg())
885 const Value *Src =
nullptr;
888 if (!
isIntExtFree(ZE) && ZE->getOperand(0)->getType()->isIntegerTy(32)) {
890 Src = ZE->getOperand(0);
893 if (!
isIntExtFree(SE) && SE->getOperand(0)->getType()->isIntegerTy(32)) {
895 Src = SE->getOperand(0);
906 Addr.setOffsetReg(
Reg);
911 if (Addr.isRegBase() && !Addr.getReg()) {
919 if (!Addr.getOffsetReg()) {
923 Addr.setOffsetReg(
Reg);
930bool AArch64FastISel::computeCallAddress(
const Value *V,
Address &Addr) {
931 const User *
U =
nullptr;
932 unsigned Opcode = Instruction::UserOp1;
936 Opcode =
I->getOpcode();
938 InMBB =
I->getParent() == FuncInfo.MBB->getBasicBlock();
940 Opcode =
C->getOpcode();
946 case Instruction::BitCast:
949 return computeCallAddress(
U->getOperand(0), Addr);
951 case Instruction::IntToPtr:
954 TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
955 TLI.getPointerTy(
DL))
956 return computeCallAddress(
U->getOperand(0), Addr);
958 case Instruction::PtrToInt:
960 if (InMBB && TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
961 return computeCallAddress(
U->getOperand(0), Addr);
966 Addr.setGlobalValue(GV);
971 if (!Addr.getGlobalValue()) {
972 Addr.setReg(getRegForValue(V));
973 return Addr.getReg().isValid();
979bool AArch64FastISel::isTypeLegal(
Type *Ty, MVT &VT) {
980 EVT evt = TLI.getValueType(
DL, Ty,
true);
986 if (evt == MVT::Other || !evt.
isSimple())
996 return TLI.isTypeLegal(VT);
1003bool AArch64FastISel::isTypeSupported(
Type *Ty, MVT &VT,
bool IsVectorAllowed) {
1007 if (isTypeLegal(Ty, VT))
1012 if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)
1018bool AArch64FastISel::isValueAvailable(
const Value *V)
const {
1023 return FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB;
1026bool AArch64FastISel::simplifyAddress(
Address &Addr, MVT VT) {
1034 bool ImmediateOffsetNeedsLowering =
false;
1035 bool RegisterOffsetNeedsLowering =
false;
1036 int64_t
Offset = Addr.getOffset();
1038 ImmediateOffsetNeedsLowering =
true;
1039 else if (
Offset > 0 && !(
Offset & (ScaleFactor - 1)) &&
1041 ImmediateOffsetNeedsLowering =
true;
1046 if (!ImmediateOffsetNeedsLowering && Addr.getOffset() && Addr.getOffsetReg())
1047 RegisterOffsetNeedsLowering =
true;
1050 if (Addr.isRegBase() && Addr.getOffsetReg() && !Addr.getReg())
1051 RegisterOffsetNeedsLowering =
true;
1056 if ((ImmediateOffsetNeedsLowering || Addr.getOffsetReg()) && Addr.isFIBase())
1058 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
1059 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
1064 Addr.setKind(Address::RegBase);
1065 Addr.setReg(ResultReg);
1068 if (RegisterOffsetNeedsLowering) {
1070 if (Addr.getReg()) {
1073 ResultReg = emitAddSub_rx(
true, MVT::i64, Addr.getReg(),
1074 Addr.getOffsetReg(), Addr.getExtendType(),
1077 ResultReg = emitAddSub_rs(
true, MVT::i64, Addr.getReg(),
1082 ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1083 Addr.getShift(),
true);
1085 ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1086 Addr.getShift(),
false);
1088 ResultReg = emitLSL_ri(MVT::i64, MVT::i64, Addr.getOffsetReg(),
1094 Addr.setReg(ResultReg);
1095 Addr.setOffsetReg(0);
1102 if (ImmediateOffsetNeedsLowering) {
1106 ResultReg = emitAdd_ri_(MVT::i64, Addr.getReg(),
Offset);
1112 Addr.setReg(ResultReg);
1118void AArch64FastISel::addLoadStoreOperands(
Address &Addr,
1119 const MachineInstrBuilder &MIB,
1121 unsigned ScaleFactor,
1122 MachineMemOperand *MMO) {
1123 int64_t
Offset = Addr.getOffset() / ScaleFactor;
1125 if (Addr.isFIBase()) {
1126 int FI = Addr.getFI();
1129 MMO = FuncInfo.MF->getMachineMemOperand(
1131 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
1135 assert(Addr.isRegBase() &&
"Unexpected address kind.");
1142 if (Addr.getOffsetReg()) {
1143 assert(Addr.getOffset() == 0 &&
"Unexpected offset");
1146 MIB.
addReg(Addr.getReg());
1147 MIB.
addReg(Addr.getOffsetReg());
1149 MIB.
addImm(Addr.getShift() != 0);
1158Register AArch64FastISel::emitAddSub(
bool UseAdd, MVT RetVT,
const Value *
LHS,
1160 bool WantResult,
bool IsZExt) {
1162 bool NeedExtend =
false;
1197 if (
SI->getOpcode() == Instruction::Shl ||
1198 SI->getOpcode() == Instruction::LShr ||
1199 SI->getOpcode() == Instruction::AShr )
1207 LHSReg = emitIntExt(SrcVT, LHSReg, RetVT, IsZExt);
1211 uint64_t
Imm = IsZExt ?
C->getZExtValue() :
C->getSExtValue();
1212 if (
C->isNegative())
1213 ResultReg = emitAddSub_ri(!UseAdd, RetVT, LHSReg, -Imm, SetFlags,
1216 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, Imm, SetFlags,
1219 if (
C->isNullValue())
1220 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, 0, SetFlags, WantResult);
1227 isValueAvailable(
RHS)) {
1231 return emitAddSub_rx(UseAdd, RetVT, LHSReg, RHSReg, ExtendType, 0,
1232 SetFlags, WantResult);
1242 if (
C->getValue().isPowerOf2())
1247 Register RHSReg = getRegForValue(MulLHS);
1250 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg,
AArch64_AM::LSL,
1251 ShiftVal, SetFlags, WantResult);
1262 switch (
SI->getOpcode()) {
1268 uint64_t ShiftVal =
C->getZExtValue();
1270 Register RHSReg = getRegForValue(
SI->getOperand(0));
1273 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg, ShiftType,
1274 ShiftVal, SetFlags, WantResult);
1287 RHSReg = emitIntExt(SrcVT, RHSReg, RetVT, IsZExt);
1289 return emitAddSub_rr(UseAdd, RetVT, LHSReg, RHSReg, SetFlags, WantResult);
1292Register AArch64FastISel::emitAddSub_rr(
bool UseAdd, MVT RetVT,
Register LHSReg,
1295 assert(LHSReg && RHSReg &&
"Invalid register number.");
1297 if (LHSReg == AArch64::SP || LHSReg == AArch64::WSP ||
1298 RHSReg == AArch64::SP || RHSReg == AArch64::WSP)
1301 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1304 static const unsigned OpcTable[2][2][2] = {
1305 { { AArch64::SUBWrr, AArch64::SUBXrr },
1306 { AArch64::ADDWrr, AArch64::ADDXrr } },
1307 { { AArch64::SUBSWrr, AArch64::SUBSXrr },
1308 { AArch64::ADDSWrr, AArch64::ADDSXrr } }
1310 bool Is64Bit = RetVT == MVT::i64;
1311 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1312 const TargetRegisterClass *RC =
1313 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1316 ResultReg = createResultReg(RC);
1318 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1320 const MCInstrDesc &
II =
TII.get(
Opc);
1323 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1329Register AArch64FastISel::emitAddSub_ri(
bool UseAdd, MVT RetVT,
Register LHSReg,
1330 uint64_t Imm,
bool SetFlags,
1332 assert(LHSReg &&
"Invalid register number.");
1334 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1340 else if ((Imm & 0xfff000) == Imm) {
1346 static const unsigned OpcTable[2][2][2] = {
1347 { { AArch64::SUBWri, AArch64::SUBXri },
1348 { AArch64::ADDWri, AArch64::ADDXri } },
1349 { { AArch64::SUBSWri, AArch64::SUBSXri },
1350 { AArch64::ADDSWri, AArch64::ADDSXri } }
1352 bool Is64Bit = RetVT == MVT::i64;
1353 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1354 const TargetRegisterClass *RC;
1356 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1358 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1361 ResultReg = createResultReg(RC);
1363 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1365 const MCInstrDesc &
II =
TII.get(
Opc);
1367 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1374Register AArch64FastISel::emitAddSub_rs(
bool UseAdd, MVT RetVT,
Register LHSReg,
1377 uint64_t ShiftImm,
bool SetFlags,
1379 assert(LHSReg && RHSReg &&
"Invalid register number.");
1380 assert(LHSReg != AArch64::SP && LHSReg != AArch64::WSP &&
1381 RHSReg != AArch64::SP && RHSReg != AArch64::WSP);
1383 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1390 static const unsigned OpcTable[2][2][2] = {
1391 { { AArch64::SUBWrs, AArch64::SUBXrs },
1392 { AArch64::ADDWrs, AArch64::ADDXrs } },
1393 { { AArch64::SUBSWrs, AArch64::SUBSXrs },
1394 { AArch64::ADDSWrs, AArch64::ADDSXrs } }
1396 bool Is64Bit = RetVT == MVT::i64;
1397 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1398 const TargetRegisterClass *RC =
1399 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1402 ResultReg = createResultReg(RC);
1404 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1406 const MCInstrDesc &
II =
TII.get(
Opc);
1409 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1412 .
addImm(getShifterImm(ShiftType, ShiftImm));
1416Register AArch64FastISel::emitAddSub_rx(
bool UseAdd, MVT RetVT,
Register LHSReg,
1419 uint64_t ShiftImm,
bool SetFlags,
1421 assert(LHSReg && RHSReg &&
"Invalid register number.");
1422 assert(LHSReg != AArch64::XZR && LHSReg != AArch64::WZR &&
1423 RHSReg != AArch64::XZR && RHSReg != AArch64::WZR);
1425 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1431 static const unsigned OpcTable[2][2][2] = {
1432 { { AArch64::SUBWrx, AArch64::SUBXrx },
1433 { AArch64::ADDWrx, AArch64::ADDXrx } },
1434 { { AArch64::SUBSWrx, AArch64::SUBSXrx },
1435 { AArch64::ADDSWrx, AArch64::ADDSXrx } }
1437 bool Is64Bit = RetVT == MVT::i64;
1438 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1439 const TargetRegisterClass *RC =
nullptr;
1441 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1443 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1446 ResultReg = createResultReg(RC);
1448 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1450 const MCInstrDesc &
II =
TII.get(
Opc);
1453 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1456 .
addImm(getArithExtendImm(ExtType, ShiftImm));
1460bool AArch64FastISel::emitCmp(
const Value *
LHS,
const Value *
RHS,
bool IsZExt) {
1462 EVT EVT = TLI.getValueType(
DL, Ty,
true);
1475 return emitICmp(VT,
LHS,
RHS, IsZExt);
1478 return emitFCmp(VT,
LHS,
RHS);
1482bool AArch64FastISel::emitICmp(MVT RetVT,
const Value *
LHS,
const Value *
RHS,
1484 return emitSub(RetVT,
LHS,
RHS,
true,
false,
1489bool AArch64FastISel::emitICmp_ri(MVT RetVT,
Register LHSReg, uint64_t Imm) {
1490 return emitAddSub_ri(
false, RetVT, LHSReg, Imm,
1495bool AArch64FastISel::emitFCmp(MVT RetVT,
const Value *
LHS,
const Value *
RHS) {
1496 if (RetVT != MVT::f32 && RetVT != MVT::f64)
1501 bool UseImm =
false;
1511 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDri : AArch64::FCMPSri;
1512 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1521 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDrr : AArch64::FCMPSrr;
1522 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1529 bool SetFlags,
bool WantResult,
bool IsZExt) {
1530 return emitAddSub(
true, RetVT,
LHS,
RHS, SetFlags, WantResult,
1542 ResultReg = emitAddSub_ri(
false, VT, Op0, -Imm);
1544 ResultReg = emitAddSub_ri(
true, VT, Op0, Imm);
1553 ResultReg = emitAddSub_rr(
true, VT, Op0, CReg);
1558 bool SetFlags,
bool WantResult,
bool IsZExt) {
1559 return emitAddSub(
false, RetVT,
LHS,
RHS, SetFlags, WantResult,
1564 Register RHSReg,
bool WantResult) {
1565 return emitAddSub_rr(
false, RetVT, LHSReg, RHSReg,
1572 uint64_t ShiftImm,
bool WantResult) {
1573 return emitAddSub_rs(
false, RetVT, LHSReg, RHSReg, ShiftType,
1574 ShiftImm,
true, WantResult);
1577Register AArch64FastISel::emitLogicalOp(
unsigned ISDOpc, MVT RetVT,
1600 uint64_t
Imm =
C->getZExtValue();
1601 ResultReg = emitLogicalOp_ri(ISDOpc, RetVT, LHSReg, Imm);
1613 if (
C->getValue().isPowerOf2())
1619 Register RHSReg = getRegForValue(MulLHS);
1622 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);
1632 uint64_t ShiftVal =
C->getZExtValue();
1633 Register RHSReg = getRegForValue(
SI->getOperand(0));
1636 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);
1646 MVT VT = std::max(MVT::i32, RetVT.
SimpleTy);
1647 ResultReg = fastEmit_rr(VT, VT, ISDOpc, LHSReg, RHSReg);
1648 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1649 uint64_t
Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1650 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1655Register AArch64FastISel::emitLogicalOp_ri(
unsigned ISDOpc, MVT RetVT,
1658 "ISD nodes are not consecutive!");
1659 static const unsigned OpcTable[3][2] = {
1660 { AArch64::ANDWri, AArch64::ANDXri },
1661 { AArch64::ORRWri, AArch64::ORRXri },
1662 { AArch64::EORWri, AArch64::EORXri }
1664 const TargetRegisterClass *RC;
1675 Opc = OpcTable[Idx][0];
1676 RC = &AArch64::GPR32spRegClass;
1682 RC = &AArch64::GPR64spRegClass;
1691 fastEmitInst_ri(
Opc, RC, LHSReg,
1693 if (RetVT >= MVT::i8 && RetVT <= MVT::i16 && ISDOpc !=
ISD::AND) {
1694 uint64_t
Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1695 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1700Register AArch64FastISel::emitLogicalOp_rs(
unsigned ISDOpc, MVT RetVT,
1702 uint64_t ShiftImm) {
1704 "ISD nodes are not consecutive!");
1705 static const unsigned OpcTable[3][2] = {
1706 { AArch64::ANDWrs, AArch64::ANDXrs },
1707 { AArch64::ORRWrs, AArch64::ORRXrs },
1708 { AArch64::EORWrs, AArch64::EORXrs }
1715 const TargetRegisterClass *RC;
1725 RC = &AArch64::GPR32RegClass;
1729 RC = &AArch64::GPR64RegClass;
1733 fastEmitInst_rri(
Opc, RC, LHSReg, RHSReg,
1735 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1736 uint64_t
Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1737 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1742Register AArch64FastISel::emitAnd_ri(MVT RetVT,
Register LHSReg, uint64_t Imm) {
1743 return emitLogicalOp_ri(
ISD::AND, RetVT, LHSReg, Imm);
1747 bool WantZExt, MachineMemOperand *MMO) {
1748 if (!TLI.allowsMisalignedMemoryAccesses(VT))
1752 if (!simplifyAddress(Addr, VT))
1761 bool UseScaled =
true;
1762 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
1767 static const unsigned GPOpcTable[2][8][4] = {
1769 { { AArch64::LDURSBWi, AArch64::LDURSHWi, AArch64::LDURWi,
1771 { AArch64::LDURSBXi, AArch64::LDURSHXi, AArch64::LDURSWi,
1773 { AArch64::LDRSBWui, AArch64::LDRSHWui, AArch64::LDRWui,
1775 { AArch64::LDRSBXui, AArch64::LDRSHXui, AArch64::LDRSWui,
1777 { AArch64::LDRSBWroX, AArch64::LDRSHWroX, AArch64::LDRWroX,
1779 { AArch64::LDRSBXroX, AArch64::LDRSHXroX, AArch64::LDRSWroX,
1781 { AArch64::LDRSBWroW, AArch64::LDRSHWroW, AArch64::LDRWroW,
1783 { AArch64::LDRSBXroW, AArch64::LDRSHXroW, AArch64::LDRSWroW,
1787 { { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1789 { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1791 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1793 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1795 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1797 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1799 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1801 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1806 static const unsigned FPOpcTable[4][2] = {
1807 { AArch64::LDURSi, AArch64::LDURDi },
1808 { AArch64::LDRSui, AArch64::LDRDui },
1809 { AArch64::LDRSroX, AArch64::LDRDroX },
1810 { AArch64::LDRSroW, AArch64::LDRDroW }
1814 const TargetRegisterClass *RC;
1815 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
1816 Addr.getOffsetReg();
1817 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
1822 bool IsRet64Bit = RetVT == MVT::i64;
1828 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][0];
1829 RC = (IsRet64Bit && !WantZExt) ?
1830 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1833 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][1];
1834 RC = (IsRet64Bit && !WantZExt) ?
1835 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1838 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][2];
1839 RC = (IsRet64Bit && !WantZExt) ?
1840 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1843 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][3];
1844 RC = &AArch64::GPR64RegClass;
1847 Opc = FPOpcTable[Idx][0];
1848 RC = &AArch64::FPR32RegClass;
1851 Opc = FPOpcTable[Idx][1];
1852 RC = &AArch64::FPR64RegClass;
1857 Register ResultReg = createResultReg(RC);
1858 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1859 TII.get(
Opc), ResultReg);
1863 if (VT == MVT::i1) {
1864 Register ANDReg = emitAnd_ri(MVT::i32, ResultReg, 1);
1865 assert(ANDReg &&
"Unexpected AND instruction emission failure.");
1871 if (WantZExt && RetVT == MVT::i64 && VT <= MVT::i32) {
1872 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
1873 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1874 TII.get(AArch64::SUBREG_TO_REG), Reg64)
1876 .
addImm(AArch64::sub_32);
1882bool AArch64FastISel::selectAddSub(
const Instruction *
I) {
1884 if (!isTypeSupported(
I->getType(), VT,
true))
1888 return selectOperator(
I,
I->getOpcode());
1891 switch (
I->getOpcode()) {
1894 case Instruction::Add:
1895 ResultReg = emitAdd(VT,
I->getOperand(0),
I->getOperand(1));
1897 case Instruction::Sub:
1898 ResultReg = emitSub(VT,
I->getOperand(0),
I->getOperand(1));
1904 updateValueMap(
I, ResultReg);
1908bool AArch64FastISel::selectLogicalOp(
const Instruction *
I) {
1910 if (!isTypeSupported(
I->getType(), VT,
true))
1914 return selectOperator(
I,
I->getOpcode());
1917 switch (
I->getOpcode()) {
1920 case Instruction::And:
1921 ResultReg = emitLogicalOp(
ISD::AND, VT,
I->getOperand(0),
I->getOperand(1));
1923 case Instruction::Or:
1924 ResultReg = emitLogicalOp(
ISD::OR, VT,
I->getOperand(0),
I->getOperand(1));
1926 case Instruction::Xor:
1927 ResultReg = emitLogicalOp(
ISD::XOR, VT,
I->getOperand(0),
I->getOperand(1));
1933 updateValueMap(
I, ResultReg);
1937bool AArch64FastISel::selectLoad(
const Instruction *
I) {
1942 if (!isTypeSupported(
I->getType(), VT,
true) ||
1946 const Value *SV =
I->getOperand(0);
1947 if (TLI.supportSwiftError()) {
1951 if (Arg->hasSwiftErrorAttr())
1956 if (Alloca->isSwiftError())
1963 if (!computeAddress(
I->getOperand(0), Addr,
I->getType()))
1967 bool WantZExt =
true;
1969 const Value *IntExtVal =
nullptr;
1970 if (
I->hasOneUse()) {
1972 if (isTypeSupported(ZE->getType(), RetVT))
1977 if (isTypeSupported(SE->getType(), RetVT))
1986 emitLoad(VT, RetVT, Addr, WantZExt, createMachineMemOperandFor(
I));
2007 auto *
MI =
MRI.getUniqueVRegDef(
Reg);
2009 if (RetVT == MVT::i64 && VT <= MVT::i32) {
2013 ResultReg = std::prev(
I)->getOperand(0).getReg();
2014 removeDeadCode(
I, std::next(
I));
2016 ResultReg = fastEmitInst_extractsubreg(MVT::i32, ResultReg,
2019 updateValueMap(
I, ResultReg);
2028 for (
auto &Opnd :
MI->uses()) {
2030 Reg = Opnd.getReg();
2035 removeDeadCode(
I, std::next(
I));
2040 updateValueMap(IntExtVal, ResultReg);
2044 updateValueMap(
I, ResultReg);
2048bool AArch64FastISel::emitStoreRelease(MVT VT,
Register SrcReg,
2050 MachineMemOperand *MMO) {
2053 default:
return false;
2054 case MVT::i8:
Opc = AArch64::STLRB;
break;
2055 case MVT::i16:
Opc = AArch64::STLRH;
break;
2056 case MVT::i32:
Opc = AArch64::STLRW;
break;
2057 case MVT::i64:
Opc = AArch64::STLRX;
break;
2060 const MCInstrDesc &
II =
TII.get(
Opc);
2063 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2071 MachineMemOperand *MMO) {
2072 if (!TLI.allowsMisalignedMemoryAccesses(VT))
2076 if (!simplifyAddress(Addr, VT))
2085 bool UseScaled =
true;
2086 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
2091 static const unsigned OpcTable[4][6] = {
2092 { AArch64::STURBBi, AArch64::STURHHi, AArch64::STURWi, AArch64::STURXi,
2093 AArch64::STURSi, AArch64::STURDi },
2094 { AArch64::STRBBui, AArch64::STRHHui, AArch64::STRWui, AArch64::STRXui,
2095 AArch64::STRSui, AArch64::STRDui },
2096 { AArch64::STRBBroX, AArch64::STRHHroX, AArch64::STRWroX, AArch64::STRXroX,
2097 AArch64::STRSroX, AArch64::STRDroX },
2098 { AArch64::STRBBroW, AArch64::STRHHroW, AArch64::STRWroW, AArch64::STRXroW,
2099 AArch64::STRSroW, AArch64::STRDroW }
2103 bool VTIsi1 =
false;
2104 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
2105 Addr.getOffsetReg();
2106 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
2113 case MVT::i1: VTIsi1 =
true; [[fallthrough]];
2114 case MVT::i8:
Opc = OpcTable[Idx][0];
break;
2115 case MVT::i16:
Opc = OpcTable[Idx][1];
break;
2116 case MVT::i32:
Opc = OpcTable[Idx][2];
break;
2117 case MVT::i64:
Opc = OpcTable[Idx][3];
break;
2118 case MVT::f32:
Opc = OpcTable[Idx][4];
break;
2119 case MVT::f64:
Opc = OpcTable[Idx][5];
break;
2123 if (VTIsi1 && SrcReg != AArch64::WZR) {
2124 Register ANDReg = emitAnd_ri(MVT::i32, SrcReg, 1);
2125 assert(ANDReg &&
"Unexpected AND instruction emission failure.");
2129 const MCInstrDesc &
II =
TII.get(
Opc);
2131 MachineInstrBuilder MIB =
2138bool AArch64FastISel::selectStore(
const Instruction *
I) {
2140 const Value *Op0 =
I->getOperand(0);
2144 if (!isTypeSupported(Op0->
getType(), VT,
true))
2147 const Value *PtrV =
I->getOperand(1);
2148 if (TLI.supportSwiftError()) {
2152 if (Arg->hasSwiftErrorAttr())
2157 if (Alloca->isSwiftError())
2167 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2169 if (CF->isZero() && !CF->isNegative()) {
2171 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2176 SrcReg = getRegForValue(Op0);
2184 if (
SI->isAtomic()) {
2189 Register AddrReg = getRegForValue(PtrV);
2192 return emitStoreRelease(VT, SrcReg, AddrReg,
2193 createMachineMemOperandFor(
I));
2199 if (!computeAddress(PtrV, Addr, Op0->
getType()))
2202 if (!
emitStore(VT, SrcReg, Addr, createMachineMemOperandFor(
I)))
2254bool AArch64FastISel::emitCompareAndBranch(
const BranchInst *BI) {
2258 if (FuncInfo.MF->getFunction().hasFnAttribute(
2259 Attribute::SpeculativeLoadHardening))
2278 MachineBasicBlock *FBB = FuncInfo.getMBB(BI->
getSuccessor(1));
2281 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2288 switch (Predicate) {
2300 if (AI->
getOpcode() == Instruction::And && isValueAvailable(AI)) {
2305 if (
C->getValue().isPowerOf2())
2309 if (
C->getValue().isPowerOf2()) {
2310 TestBit =
C->getValue().logBase2();
2341 static const unsigned OpcTable[2][2][2] = {
2342 { {AArch64::CBZW, AArch64::CBZX },
2343 {AArch64::CBNZW, AArch64::CBNZX} },
2344 { {AArch64::TBZW, AArch64::TBZX },
2345 {AArch64::TBNZW, AArch64::TBNZX} }
2348 bool IsBitTest = TestBit != -1;
2349 bool Is64Bit = BW == 64;
2350 if (TestBit < 32 && TestBit >= 0)
2353 unsigned Opc = OpcTable[IsBitTest][IsCmpNE][Is64Bit];
2354 const MCInstrDesc &
II =
TII.get(
Opc);
2360 if (BW == 64 && !Is64Bit)
2361 SrcReg = fastEmitInst_extractsubreg(MVT::i32, SrcReg, AArch64::sub_32);
2363 if ((BW < 32) && !IsBitTest)
2364 SrcReg = emitIntExt(VT, SrcReg, MVT::i32,
true);
2368 MachineInstrBuilder MIB =
2369 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
2379bool AArch64FastISel::selectBranch(
const Instruction *
I) {
2382 MachineBasicBlock *MSucc = FuncInfo.getMBB(BI->
getSuccessor(0));
2388 MachineBasicBlock *FBB = FuncInfo.getMBB(BI->
getSuccessor(1));
2391 if (CI->
hasOneUse() && isValueAvailable(CI)) {
2394 switch (Predicate) {
2398 fastEmitBranch(FBB, MIMD.getDL());
2401 fastEmitBranch(
TBB, MIMD.getDL());
2406 if (emitCompareAndBranch(BI))
2410 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2423 switch (Predicate) {
2439 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2445 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2453 uint64_t
Imm = CI->getZExtValue();
2455 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::B))
2460 auto BranchProbability = FuncInfo.BPI->getEdgeProbability(
2462 FuncInfo.MBB->addSuccessor(Target, BranchProbability);
2464 FuncInfo.MBB->addSuccessorWithoutProb(Target);
2476 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2490 unsigned Opcode = AArch64::TBNZW;
2491 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2493 Opcode = AArch64::TBZW;
2496 const MCInstrDesc &
II =
TII.get(Opcode);
2499 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2500 .
addReg(ConstrainedCondReg)
2508bool AArch64FastISel::selectIndirectBr(
const Instruction *
I) {
2515 if (FuncInfo.MF->getFunction().hasFnAttribute(
"ptrauth-indirect-gotos"))
2519 const MCInstrDesc &
II =
TII.get(AArch64::BR);
2525 FuncInfo.MBB->addSuccessor(FuncInfo.getMBB(Succ));
2530bool AArch64FastISel::selectCmp(
const Instruction *
I) {
2540 switch (Predicate) {
2544 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2545 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2546 TII.get(TargetOpcode::COPY), ResultReg)
2550 ResultReg = fastEmit_i(MVT::i32, MVT::i32,
ISD::Constant, 1);
2555 updateValueMap(
I, ResultReg);
2563 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2567 static unsigned CondCodeTable[2][2] = {
2572 switch (Predicate) {
2584 Register TmpReg1 = createResultReg(&AArch64::GPR32RegClass);
2585 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2590 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2596 updateValueMap(
I, ResultReg);
2604 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2610 updateValueMap(
I, ResultReg);
2616bool AArch64FastISel::optimizeSelect(
const SelectInst *SI) {
2617 if (!
SI->getType()->isIntegerTy(1))
2620 const Value *Src1Val, *Src2Val;
2622 bool NeedExtraOp =
false;
2625 Src1Val =
SI->getCondition();
2626 Src2Val =
SI->getFalseValue();
2627 Opc = AArch64::ORRWrr;
2630 Src1Val =
SI->getFalseValue();
2631 Src2Val =
SI->getCondition();
2632 Opc = AArch64::BICWrr;
2636 Src1Val =
SI->getCondition();
2637 Src2Val =
SI->getTrueValue();
2638 Opc = AArch64::ORRWrr;
2642 Src1Val =
SI->getCondition();
2643 Src2Val =
SI->getTrueValue();
2644 Opc = AArch64::ANDWrr;
2651 Register Src1Reg = getRegForValue(Src1Val);
2655 Register Src2Reg = getRegForValue(Src2Val);
2660 Src1Reg = emitLogicalOp_ri(
ISD::XOR, MVT::i32, Src1Reg, 1);
2662 Register ResultReg = fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, Src1Reg,
2664 updateValueMap(SI, ResultReg);
2668bool AArch64FastISel::selectSelect(
const Instruction *
I) {
2671 if (!isTypeSupported(
I->getType(), VT))
2675 const TargetRegisterClass *RC;
2683 Opc = AArch64::CSELWr;
2684 RC = &AArch64::GPR32RegClass;
2687 Opc = AArch64::CSELXr;
2688 RC = &AArch64::GPR64RegClass;
2691 Opc = AArch64::FCSELSrrr;
2692 RC = &AArch64::FPR32RegClass;
2695 Opc = AArch64::FCSELDrrr;
2696 RC = &AArch64::FPR64RegClass;
2705 if (optimizeSelect(SI))
2709 if (foldXALUIntrinsic(CC,
I,
Cond)) {
2715 isValueAvailable(
Cond)) {
2719 const Value *FoldSelect =
nullptr;
2720 switch (Predicate) {
2724 FoldSelect =
SI->getFalseValue();
2727 FoldSelect =
SI->getTrueValue();
2732 Register SrcReg = getRegForValue(FoldSelect);
2736 updateValueMap(
I, SrcReg);
2746 switch (Predicate) {
2764 const MCInstrDesc &
II =
TII.get(AArch64::ANDSWri);
2768 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II,
2774 Register Src1Reg = getRegForValue(
SI->getTrueValue());
2775 Register Src2Reg = getRegForValue(
SI->getFalseValue());
2777 if (!Src1Reg || !Src2Reg)
2781 Src2Reg = fastEmitInst_rri(
Opc, RC, Src1Reg, Src2Reg, ExtraCC);
2783 Register ResultReg = fastEmitInst_rri(
Opc, RC, Src1Reg, Src2Reg, CC);
2784 updateValueMap(
I, ResultReg);
2788bool AArch64FastISel::selectFPExt(
const Instruction *
I) {
2790 if (!
I->getType()->isDoubleTy() || !
V->getType()->isFloatTy())
2797 Register ResultReg = createResultReg(&AArch64::FPR64RegClass);
2798 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTDSr),
2800 updateValueMap(
I, ResultReg);
2804bool AArch64FastISel::selectFPTrunc(
const Instruction *
I) {
2806 if (!
I->getType()->isFloatTy() || !
V->getType()->isDoubleTy())
2813 Register ResultReg = createResultReg(&AArch64::FPR32RegClass);
2814 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTSDr),
2816 updateValueMap(
I, ResultReg);
2821bool AArch64FastISel::selectFPToInt(
const Instruction *
I,
bool Signed) {
2823 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2826 Register SrcReg = getRegForValue(
I->getOperand(0));
2830 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2831 if (SrcVT == MVT::f128 || SrcVT == MVT::f16 || SrcVT == MVT::bf16)
2835 if (SrcVT == MVT::f64) {
2837 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWDr : AArch64::FCVTZSUXDr;
2839 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWDr : AArch64::FCVTZUUXDr;
2842 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWSr : AArch64::FCVTZSUXSr;
2844 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWSr : AArch64::FCVTZUUXSr;
2846 Register ResultReg = createResultReg(
2847 DestVT == MVT::i32 ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass);
2848 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
2850 updateValueMap(
I, ResultReg);
2854bool AArch64FastISel::selectIntToFP(
const Instruction *
I,
bool Signed) {
2856 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2859 if (DestVT == MVT::f16 || DestVT == MVT::bf16)
2862 assert((DestVT == MVT::f32 || DestVT == MVT::f64) &&
2863 "Unexpected value type.");
2865 Register SrcReg = getRegForValue(
I->getOperand(0));
2869 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2872 if (SrcVT == MVT::i16 || SrcVT == MVT::i8 || SrcVT == MVT::i1) {
2880 if (SrcVT == MVT::i64) {
2882 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUXSri : AArch64::SCVTFUXDri;
2884 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUXSri : AArch64::UCVTFUXDri;
2887 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUWSri : AArch64::SCVTFUWDri;
2889 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUWSri : AArch64::UCVTFUWDri;
2892 Register ResultReg = fastEmitInst_r(
Opc, TLI.getRegClassFor(DestVT), SrcReg);
2893 updateValueMap(
I, ResultReg);
2897bool AArch64FastISel::fastLowerArguments() {
2898 if (!FuncInfo.CanLowerReturn)
2905 CallingConv::ID CC =
F->getCallingConv();
2906 if (CC != CallingConv::C && CC != CallingConv::Swift)
2913 unsigned GPRCnt = 0;
2914 unsigned FPRCnt = 0;
2915 for (
auto const &Arg :
F->args()) {
2916 if (Arg.hasAttribute(Attribute::ByVal) ||
2917 Arg.hasAttribute(Attribute::InReg) ||
2918 Arg.hasAttribute(Attribute::StructRet) ||
2919 Arg.hasAttribute(Attribute::SwiftSelf) ||
2920 Arg.hasAttribute(Attribute::SwiftAsync) ||
2921 Arg.hasAttribute(Attribute::SwiftError) ||
2922 Arg.hasAttribute(Attribute::Nest))
2925 Type *ArgTy = Arg.getType();
2929 EVT ArgVT = TLI.getValueType(
DL, ArgTy);
2941 if (VT >= MVT::i1 && VT <= MVT::i64)
2943 else if ((VT >= MVT::f16 && VT <= MVT::f64) || VT.
is64BitVector() ||
2949 if (GPRCnt > 8 || FPRCnt > 8)
2954 { AArch64::W0, AArch64::W1, AArch64::W2, AArch64::W3, AArch64::W4,
2955 AArch64::W5, AArch64::W6, AArch64::W7 },
2956 { AArch64::X0, AArch64::X1, AArch64::X2, AArch64::X3, AArch64::X4,
2957 AArch64::X5, AArch64::X6, AArch64::X7 },
2958 { AArch64::H0, AArch64::H1, AArch64::H2, AArch64::H3, AArch64::H4,
2959 AArch64::H5, AArch64::H6, AArch64::H7 },
2960 { AArch64::S0, AArch64::S1, AArch64::S2, AArch64::S3, AArch64::S4,
2961 AArch64::S5, AArch64::S6, AArch64::S7 },
2962 { AArch64::D0, AArch64::D1, AArch64::D2, AArch64::D3, AArch64::D4,
2963 AArch64::D5, AArch64::D6, AArch64::D7 },
2964 { AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,
2965 AArch64::Q5, AArch64::Q6, AArch64::Q7 }
2968 unsigned GPRIdx = 0;
2969 unsigned FPRIdx = 0;
2970 for (
auto const &Arg :
F->args()) {
2971 MVT VT = TLI.getSimpleValueType(
DL, Arg.getType());
2973 const TargetRegisterClass *RC;
2974 if (VT >= MVT::i1 && VT <= MVT::i32) {
2976 RC = &AArch64::GPR32RegClass;
2978 }
else if (VT == MVT::i64) {
2980 RC = &AArch64::GPR64RegClass;
2981 }
else if (VT == MVT::f16 || VT == MVT::bf16) {
2983 RC = &AArch64::FPR16RegClass;
2984 }
else if (VT == MVT::f32) {
2986 RC = &AArch64::FPR32RegClass;
2989 RC = &AArch64::FPR64RegClass;
2992 RC = &AArch64::FPR128RegClass;
2996 Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
3000 Register ResultReg = createResultReg(RC);
3001 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3002 TII.get(TargetOpcode::COPY), ResultReg)
3004 updateValueMap(&Arg, ResultReg);
3009bool AArch64FastISel::processCallArgs(CallLoweringInfo &CLI,
3010 SmallVectorImpl<MVT> &OutVTs,
3011 SmallVectorImpl<Type *> &OrigTys,
3012 unsigned &NumBytes) {
3013 CallingConv::ID CC = CLI.CallConv;
3015 CCState CCInfo(CC,
false, *FuncInfo.MF, ArgLocs, *
Context);
3016 CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, OrigTys,
3017 CCAssignFnForCall(CC));
3020 NumBytes = CCInfo.getStackSize();
3023 unsigned AdjStackDown =
TII.getCallFrameSetupOpcode();
3024 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackDown))
3028 for (CCValAssign &VA : ArgLocs) {
3029 const Value *ArgVal = CLI.OutVals[VA.getValNo()];
3030 MVT ArgVT = OutVTs[VA.getValNo()];
3032 Register ArgReg = getRegForValue(ArgVal);
3037 switch (VA.getLocInfo()) {
3041 MVT DestVT = VA.getLocVT();
3043 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
false);
3051 MVT DestVT = VA.getLocVT();
3053 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
true);
3063 if (VA.isRegLoc() && !VA.needsCustom()) {
3064 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3065 TII.get(TargetOpcode::COPY), VA.getLocReg()).
addReg(ArgReg);
3066 CLI.OutRegs.push_back(VA.getLocReg());
3067 }
else if (VA.needsCustom()) {
3071 assert(VA.isMemLoc() &&
"Assuming store on stack.");
3080 unsigned BEAlign = 0;
3081 if (ArgSize < 8 && !Subtarget->isLittleEndian())
3082 BEAlign = 8 - ArgSize;
3085 Addr.setKind(Address::RegBase);
3086 Addr.setReg(AArch64::SP);
3087 Addr.setOffset(VA.getLocMemOffset() + BEAlign);
3090 MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
3094 if (!
emitStore(ArgVT, ArgReg, Addr, MMO))
3101bool AArch64FastISel::finishCall(CallLoweringInfo &CLI,
unsigned NumBytes) {
3102 CallingConv::ID CC = CLI.CallConv;
3105 unsigned AdjStackUp =
TII.getCallFrameDestroyOpcode();
3106 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackUp))
3111 CCState CCInfo(CC,
false, *FuncInfo.MF, RVLocs, *
Context);
3112 CCInfo.AnalyzeCallResult(CLI.Ins, CCAssignFnForCall(CC));
3114 Register ResultReg = FuncInfo.CreateRegs(CLI.RetTy);
3115 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
3116 CCValAssign &VA = RVLocs[i];
3125 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
3131 CLI.ResultReg = ResultReg;
3132 CLI.NumResultRegs = RVLocs.
size();
3137bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
3138 CallingConv::ID CC = CLI.CallConv;
3139 bool IsTailCall = CLI.IsTailCall;
3140 bool IsVarArg = CLI.IsVarArg;
3144 if (!Callee && !Symbol)
3149 if (CLI.CB && CLI.CB->hasFnAttr(Attribute::ReturnsTwice) &&
3150 !Subtarget->noBTIAtReturnTwice() &&
3151 MF->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement())
3155 if (CLI.CB && CLI.CB->isIndirectCall() &&
3179 if (MF->getFunction().getParent()->getRtLibUseGOT())
3189 for (
auto Flag : CLI.OutFlags)
3191 Flag.isSwiftSelf() ||
Flag.isSwiftAsync() ||
Flag.isSwiftError())
3197 OutVTs.
reserve(CLI.OutVals.size());
3199 for (
auto *Val : CLI.OutVals) {
3201 if (!isTypeLegal(Val->getType(), VT) &&
3202 !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16))
3214 if (Callee && !computeCallAddress(Callee, Addr))
3221 Addr.getGlobalValue()->hasExternalWeakLinkage())
3226 if (!processCallArgs(CLI, OutVTs, OrigTys, NumBytes))
3234 MachineInstrBuilder MIB;
3236 const MCInstrDesc &
II =
3238 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II);
3241 else if (Addr.getGlobalValue())
3243 else if (Addr.getReg()) {
3251 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
3252 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
3256 CallReg = createResultReg(&AArch64::GPR64RegClass);
3257 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3258 TII.get(AArch64::LDRXui), CallReg)
3262 }
else if (Addr.getGlobalValue())
3263 CallReg = materializeGV(Addr.getGlobalValue());
3264 else if (Addr.getReg())
3265 CallReg = Addr.getReg();
3272 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II).
addReg(CallReg);
3276 for (
auto Reg : CLI.OutRegs)
3286 return finishCall(CLI, NumBytes);
3289bool AArch64FastISel::isMemCpySmall(uint64_t Len, MaybeAlign Alignment) {
3291 return Len / Alignment->value() <= 4;
3296bool AArch64FastISel::tryEmitSmallMemCpy(
Address Dest,
Address Src,
3297 uint64_t Len, MaybeAlign Alignment) {
3299 if (!isMemCpySmall(Len, Alignment))
3302 int64_t UnscaledOffset = 0;
3308 if (!Alignment || *Alignment >= 8) {
3319 assert(Alignment &&
"Alignment is set in this branch");
3321 if (Len >= 4 && *Alignment == 4)
3323 else if (Len >= 2 && *Alignment == 2)
3339 UnscaledOffset +=
Size;
3342 Dest.setOffset(OrigDest.getOffset() + UnscaledOffset);
3343 Src.setOffset(OrigSrc.getOffset() + UnscaledOffset);
3352 const Instruction *
I,
3366 if (!isTypeLegal(RetTy, RetVT))
3369 if (RetVT != MVT::i32 && RetVT != MVT::i64)
3384 case Intrinsic::smul_with_overflow:
3386 if (
C->getValue() == 2)
3387 IID = Intrinsic::sadd_with_overflow;
3389 case Intrinsic::umul_with_overflow:
3391 if (
C->getValue() == 2)
3392 IID = Intrinsic::uadd_with_overflow;
3400 case Intrinsic::sadd_with_overflow:
3401 case Intrinsic::ssub_with_overflow:
3404 case Intrinsic::uadd_with_overflow:
3407 case Intrinsic::usub_with_overflow:
3410 case Intrinsic::smul_with_overflow:
3411 case Intrinsic::umul_with_overflow:
3417 if (!isValueAvailable(
II))
3423 for (
auto Itr = std::prev(Start); Itr != End; --Itr) {
3431 if (EVI->getAggregateOperand() !=
II)
3439bool AArch64FastISel::fastLowerIntrinsicCall(
const IntrinsicInst *
II) {
3441 switch (
II->getIntrinsicID()) {
3442 default:
return false;
3443 case Intrinsic::frameaddress: {
3444 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3449 Register SrcReg =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3450 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3460 DestReg = fastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,
3462 assert(DestReg &&
"Unexpected LDR instruction emission failure.");
3466 updateValueMap(
II, SrcReg);
3469 case Intrinsic::sponentry: {
3470 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3474 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
3475 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3476 TII.get(AArch64::ADDXri), ResultReg)
3481 updateValueMap(
II, ResultReg);
3484 case Intrinsic::memcpy:
3485 case Intrinsic::memmove: {
3488 if (MTI->isVolatile())
3493 bool IsMemCpy = (
II->getIntrinsicID() == Intrinsic::memcpy);
3498 MaybeAlign Alignment;
3499 if (MTI->getDestAlign() || MTI->getSourceAlign())
3500 Alignment = std::min(MTI->getDestAlign().valueOrOne(),
3501 MTI->getSourceAlign().valueOrOne());
3502 if (isMemCpySmall(Len, Alignment)) {
3504 if (!computeAddress(MTI->getRawDest(), Dest) ||
3505 !computeAddress(MTI->getRawSource(), Src))
3507 if (tryEmitSmallMemCpy(Dest, Src, Len, Alignment))
3512 if (!MTI->getLength()->getType()->isIntegerTy(64))
3515 if (MTI->getSourceAddressSpace() > 255 || MTI->getDestAddressSpace() > 255)
3521 return lowerCallTo(
II, IntrMemName,
II->arg_size() - 1);
3523 case Intrinsic::memset: {
3537 return lowerCallTo(
II,
"memset",
II->arg_size() - 1);
3539 case Intrinsic::sin:
3540 case Intrinsic::cos:
3541 case Intrinsic::tan:
3542 case Intrinsic::pow: {
3544 if (!isTypeLegal(
II->getType(), RetVT))
3547 if (RetVT != MVT::f32 && RetVT != MVT::f64)
3550 static const RTLIB::Libcall LibCallTable[4][2] = {
3551 {RTLIB::SIN_F32, RTLIB::SIN_F64},
3552 {RTLIB::COS_F32, RTLIB::COS_F64},
3553 {RTLIB::TAN_F32, RTLIB::TAN_F64},
3554 {RTLIB::POW_F32, RTLIB::POW_F64}};
3556 bool Is64Bit = RetVT == MVT::f64;
3557 switch (
II->getIntrinsicID()) {
3560 case Intrinsic::sin:
3561 LC = LibCallTable[0][Is64Bit];
3563 case Intrinsic::cos:
3564 LC = LibCallTable[1][Is64Bit];
3566 case Intrinsic::tan:
3567 LC = LibCallTable[2][Is64Bit];
3569 case Intrinsic::pow:
3570 LC = LibCallTable[3][Is64Bit];
3575 Args.reserve(
II->arg_size());
3578 for (
auto &Arg :
II->args())
3579 Args.emplace_back(Arg);
3581 CallLoweringInfo CLI;
3582 MCContext &Ctx = MF->getContext();
3584 RTLIB::LibcallImpl LCImpl = LibcallLowering->getLibcallImpl(LC);
3585 if (LCImpl == RTLIB::Unsupported)
3588 CallingConv::ID CC = LibcallLowering->getLibcallImplCallingConv(LCImpl);
3590 CLI.setCallee(
DL, Ctx, CC,
II->getType(), FuncName, std::move(Args));
3591 if (!lowerCallTo(CLI))
3593 updateValueMap(
II, CLI.ResultReg);
3596 case Intrinsic::fabs: {
3598 if (!isTypeLegal(
II->getType(), VT))
3606 Opc = AArch64::FABSSr;
3609 Opc = AArch64::FABSDr;
3612 Register SrcReg = getRegForValue(
II->getOperand(0));
3615 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3616 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
3618 updateValueMap(
II, ResultReg);
3621 case Intrinsic::trap:
3622 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3625 case Intrinsic::debugtrap:
3626 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3630 case Intrinsic::sqrt: {
3631 Type *RetTy =
II->getCalledFunction()->getReturnType();
3634 if (!isTypeLegal(RetTy, VT))
3637 Register Op0Reg = getRegForValue(
II->getOperand(0));
3645 updateValueMap(
II, ResultReg);
3648 case Intrinsic::sadd_with_overflow:
3649 case Intrinsic::uadd_with_overflow:
3650 case Intrinsic::ssub_with_overflow:
3651 case Intrinsic::usub_with_overflow:
3652 case Intrinsic::smul_with_overflow:
3653 case Intrinsic::umul_with_overflow: {
3657 Type *RetTy = Ty->getTypeAtIndex(0U);
3660 if (!isTypeLegal(RetTy, VT))
3663 if (VT != MVT::i32 && VT != MVT::i64)
3677 case Intrinsic::smul_with_overflow:
3679 if (
C->getValue() == 2) {
3680 IID = Intrinsic::sadd_with_overflow;
3684 case Intrinsic::umul_with_overflow:
3686 if (
C->getValue() == 2) {
3687 IID = Intrinsic::uadd_with_overflow;
3693 Register ResultReg1, ResultReg2, MulReg;
3697 case Intrinsic::sadd_with_overflow:
3698 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3701 case Intrinsic::uadd_with_overflow:
3702 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3705 case Intrinsic::ssub_with_overflow:
3706 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3709 case Intrinsic::usub_with_overflow:
3710 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3713 case Intrinsic::smul_with_overflow: {
3723 if (VT == MVT::i32) {
3724 MulReg = emitSMULL_rr(MVT::i64, LHSReg, RHSReg);
3726 fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3728 emitAddSub_rx(
false, MVT::i64, MulReg, MulSubReg,
3733 assert(VT == MVT::i64 &&
"Unexpected value type.");
3736 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3743 case Intrinsic::umul_with_overflow: {
3753 if (VT == MVT::i32) {
3754 MulReg = emitUMULL_rr(MVT::i64, LHSReg, RHSReg);
3756 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3757 TII.get(AArch64::ANDSXri), AArch64::XZR)
3760 MulReg = fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3762 assert(VT == MVT::i64 &&
"Unexpected value type.");
3765 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3767 emitSubs_rr(VT, AArch64::XZR, UMULHReg,
false);
3774 ResultReg1 = createResultReg(TLI.getRegClassFor(VT));
3775 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3776 TII.get(TargetOpcode::COPY), ResultReg1).
addReg(MulReg);
3782 ResultReg2 = fastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,
3783 AArch64::WZR, AArch64::WZR,
3784 getInvertedCondCode(CC));
3786 assert((ResultReg1 + 1) == ResultReg2 &&
3787 "Nonconsecutive result registers.");
3788 updateValueMap(
II, ResultReg1, 2);
3791 case Intrinsic::aarch64_crc32b:
3792 case Intrinsic::aarch64_crc32h:
3793 case Intrinsic::aarch64_crc32w:
3794 case Intrinsic::aarch64_crc32x:
3795 case Intrinsic::aarch64_crc32cb:
3796 case Intrinsic::aarch64_crc32ch:
3797 case Intrinsic::aarch64_crc32cw:
3798 case Intrinsic::aarch64_crc32cx: {
3799 if (!Subtarget->hasCRC())
3803 switch (
II->getIntrinsicID()) {
3806 case Intrinsic::aarch64_crc32b:
3807 Opc = AArch64::CRC32Brr;
3809 case Intrinsic::aarch64_crc32h:
3810 Opc = AArch64::CRC32Hrr;
3812 case Intrinsic::aarch64_crc32w:
3813 Opc = AArch64::CRC32Wrr;
3815 case Intrinsic::aarch64_crc32x:
3816 Opc = AArch64::CRC32Xrr;
3818 case Intrinsic::aarch64_crc32cb:
3819 Opc = AArch64::CRC32CBrr;
3821 case Intrinsic::aarch64_crc32ch:
3822 Opc = AArch64::CRC32CHrr;
3824 case Intrinsic::aarch64_crc32cw:
3825 Opc = AArch64::CRC32CWrr;
3827 case Intrinsic::aarch64_crc32cx:
3828 Opc = AArch64::CRC32CXrr;
3832 Register LHSReg = getRegForValue(
II->getArgOperand(0));
3833 Register RHSReg = getRegForValue(
II->getArgOperand(1));
3834 if (!LHSReg || !RHSReg)
3838 fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, LHSReg, RHSReg);
3839 updateValueMap(
II, ResultReg);
3846bool AArch64FastISel::selectRet(
const Instruction *
I) {
3848 const Function &
F = *
I->getParent()->getParent();
3850 if (!FuncInfo.CanLowerReturn)
3856 if (TLI.supportSwiftError() &&
3857 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
3860 if (TLI.supportSplitCSR(FuncInfo.MF))
3867 CallingConv::ID CC =
F.getCallingConv();
3873 CCState CCInfo(CC,
F.isVarArg(), *FuncInfo.MF, ValLocs,
I->getContext());
3877 if (ValLocs.
size() != 1)
3880 CCValAssign &VA = ValLocs[0];
3899 if (!
MRI.getRegClass(SrcReg)->contains(DestReg))
3902 EVT RVEVT = TLI.getValueType(
DL, RV->
getType());
3912 if (RVVT == MVT::f128)
3917 if (RVVT != DestVT) {
3918 if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
3921 if (!Outs[0].
Flags.isZExt() && !Outs[0].Flags.isSExt())
3924 bool IsZExt = Outs[0].Flags.isZExt();
3925 SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
3933 SrcReg = emitAnd_ri(MVT::i64, SrcReg, 0xffffffff);
3936 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3937 TII.get(TargetOpcode::COPY), DestReg).
addReg(SrcReg);
3943 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3944 TII.get(AArch64::RET_ReallyLR));
3946 MIB.
addReg(RetReg, RegState::Implicit);
3950bool AArch64FastISel::selectTrunc(
const Instruction *
I) {
3951 Type *DestTy =
I->getType();
3953 Type *SrcTy =
Op->getType();
3955 EVT SrcEVT = TLI.getValueType(
DL, SrcTy,
true);
3956 EVT DestEVT = TLI.getValueType(
DL, DestTy,
true);
3965 if (SrcVT != MVT::i64 && SrcVT != MVT::i32 && SrcVT != MVT::i16 &&
3968 if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8 &&
3982 if (SrcVT == MVT::i64) {
3999 Register Reg32 = fastEmitInst_extractsubreg(MVT::i32, SrcReg,
4002 ResultReg = emitAnd_ri(MVT::i32, Reg32, Mask);
4003 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4005 ResultReg = createResultReg(&AArch64::GPR32RegClass);
4006 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4007 TII.get(TargetOpcode::COPY), ResultReg)
4011 updateValueMap(
I, ResultReg);
4015Register AArch64FastISel::emiti1Ext(
Register SrcReg, MVT DestVT,
bool IsZExt) {
4016 assert((DestVT == MVT::i8 || DestVT == MVT::i16 || DestVT == MVT::i32 ||
4017 DestVT == MVT::i64) &&
4018 "Unexpected value type.");
4020 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4024 Register ResultReg = emitAnd_ri(MVT::i32, SrcReg, 1);
4025 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4026 if (DestVT == MVT::i64) {
4029 Register Reg64 =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4030 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4031 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4033 .
addImm(AArch64::sub_32);
4038 if (DestVT == MVT::i64) {
4042 return fastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,
4057 Opc = AArch64::MADDWrrr; ZReg = AArch64::WZR;
break;
4059 Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR;
break;
4062 const TargetRegisterClass *RC =
4063 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4064 return fastEmitInst_rrr(
Opc, RC, Op0, Op1, ZReg);
4068 if (RetVT != MVT::i64)
4071 return fastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,
4072 Op0, Op1, AArch64::XZR);
4076 if (RetVT != MVT::i64)
4079 return fastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,
4080 Op0, Op1, AArch64::XZR);
4086 bool NeedTrunc =
false;
4091 case MVT::i8:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4092 case MVT::i16:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4093 case MVT::i32:
Opc = AArch64::LSLVWr;
break;
4094 case MVT::i64:
Opc = AArch64::LSLVXr;
break;
4097 const TargetRegisterClass *RC =
4098 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4100 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4102 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4104 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4109 uint64_t Shift,
bool IsZExt) {
4111 "Unexpected source/return type pair.");
4112 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4113 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4114 "Unexpected source value type.");
4115 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4116 RetVT == MVT::i64) &&
"Unexpected return value type.");
4118 bool Is64Bit = (RetVT == MVT::i64);
4119 unsigned RegSize = Is64Bit ? 64 : 32;
4122 const TargetRegisterClass *RC =
4123 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4127 if (RetVT == SrcVT) {
4128 Register ResultReg = createResultReg(RC);
4129 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4130 TII.get(TargetOpcode::COPY), ResultReg)
4134 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4138 if (Shift >= DstBits)
4166 unsigned ImmR =
RegSize - Shift;
4168 unsigned ImmS = std::min<unsigned>(SrcBits - 1, DstBits - 1 - Shift);
4169 static const unsigned OpcTable[2][2] = {
4170 {AArch64::SBFMWri, AArch64::SBFMXri},
4171 {AArch64::UBFMWri, AArch64::UBFMXri}
4173 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4174 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4176 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4177 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4179 .
addImm(AArch64::sub_32);
4182 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4188 bool NeedTrunc =
false;
4193 case MVT::i8:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4194 case MVT::i16:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4195 case MVT::i32:
Opc = AArch64::LSRVWr;
break;
4196 case MVT::i64:
Opc = AArch64::LSRVXr;
break;
4199 const TargetRegisterClass *RC =
4200 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4202 Op0Reg = emitAnd_ri(MVT::i32, Op0Reg, Mask);
4203 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4205 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4207 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4212 uint64_t Shift,
bool IsZExt) {
4214 "Unexpected source/return type pair.");
4215 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4216 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4217 "Unexpected source value type.");
4218 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4219 RetVT == MVT::i64) &&
"Unexpected return value type.");
4221 bool Is64Bit = (RetVT == MVT::i64);
4222 unsigned RegSize = Is64Bit ? 64 : 32;
4225 const TargetRegisterClass *RC =
4226 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4230 if (RetVT == SrcVT) {
4231 Register ResultReg = createResultReg(RC);
4232 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4233 TII.get(TargetOpcode::COPY), ResultReg)
4237 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4241 if (Shift >= DstBits)
4269 if (Shift >= SrcBits && IsZExt)
4270 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4275 Op0 = emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4283 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4284 unsigned ImmS = SrcBits - 1;
4285 static const unsigned OpcTable[2][2] = {
4286 {AArch64::SBFMWri, AArch64::SBFMXri},
4287 {AArch64::UBFMWri, AArch64::UBFMXri}
4289 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4290 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4292 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4293 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4295 .
addImm(AArch64::sub_32);
4298 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4304 bool NeedTrunc =
false;
4309 case MVT::i8:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4310 case MVT::i16:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4311 case MVT::i32:
Opc = AArch64::ASRVWr;
break;
4312 case MVT::i64:
Opc = AArch64::ASRVXr;
break;
4315 const TargetRegisterClass *RC =
4316 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4318 Op0Reg = emitIntExt(RetVT, Op0Reg, MVT::i32,
false);
4319 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4321 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4323 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4328 uint64_t Shift,
bool IsZExt) {
4330 "Unexpected source/return type pair.");
4331 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4332 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4333 "Unexpected source value type.");
4334 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4335 RetVT == MVT::i64) &&
"Unexpected return value type.");
4337 bool Is64Bit = (RetVT == MVT::i64);
4338 unsigned RegSize = Is64Bit ? 64 : 32;
4341 const TargetRegisterClass *RC =
4342 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4346 if (RetVT == SrcVT) {
4347 Register ResultReg = createResultReg(RC);
4348 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4349 TII.get(TargetOpcode::COPY), ResultReg)
4353 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4357 if (Shift >= DstBits)
4385 if (Shift >= SrcBits && IsZExt)
4386 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4388 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4389 unsigned ImmS = SrcBits - 1;
4390 static const unsigned OpcTable[2][2] = {
4391 {AArch64::SBFMWri, AArch64::SBFMXri},
4392 {AArch64::UBFMWri, AArch64::UBFMXri}
4394 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4395 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4397 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4398 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4400 .
addImm(AArch64::sub_32);
4403 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4406Register AArch64FastISel::emitIntExt(MVT SrcVT,
Register SrcReg, MVT DestVT,
4408 assert(DestVT != MVT::i1 &&
"ZeroExt/SignExt an i1?");
4414 if (((DestVT != MVT::i8) && (DestVT != MVT::i16) &&
4415 (DestVT != MVT::i32) && (DestVT != MVT::i64)) ||
4416 ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) &&
4417 (SrcVT != MVT::i16) && (SrcVT != MVT::i32)))
4427 return emiti1Ext(SrcReg, DestVT, IsZExt);
4429 if (DestVT == MVT::i64)
4430 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4432 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4436 if (DestVT == MVT::i64)
4437 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4439 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4443 assert(DestVT == MVT::i64 &&
"IntExt i32 to i32?!?");
4444 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4450 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4452 else if (DestVT == MVT::i64) {
4453 Register Src64 =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4454 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4455 TII.get(AArch64::SUBREG_TO_REG), Src64)
4457 .
addImm(AArch64::sub_32);
4461 const TargetRegisterClass *RC =
4462 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4463 return fastEmitInst_rii(
Opc, RC, SrcReg, 0, Imm);
4470 case AArch64::LDURBBi:
4471 case AArch64::LDURHHi:
4472 case AArch64::LDURWi:
4473 case AArch64::LDRBBui:
4474 case AArch64::LDRHHui:
4475 case AArch64::LDRWui:
4476 case AArch64::LDRBBroX:
4477 case AArch64::LDRHHroX:
4478 case AArch64::LDRWroX:
4479 case AArch64::LDRBBroW:
4480 case AArch64::LDRHHroW:
4481 case AArch64::LDRWroW:
4490 case AArch64::LDURSBWi:
4491 case AArch64::LDURSHWi:
4492 case AArch64::LDURSBXi:
4493 case AArch64::LDURSHXi:
4494 case AArch64::LDURSWi:
4495 case AArch64::LDRSBWui:
4496 case AArch64::LDRSHWui:
4497 case AArch64::LDRSBXui:
4498 case AArch64::LDRSHXui:
4499 case AArch64::LDRSWui:
4500 case AArch64::LDRSBWroX:
4501 case AArch64::LDRSHWroX:
4502 case AArch64::LDRSBXroX:
4503 case AArch64::LDRSHXroX:
4504 case AArch64::LDRSWroX:
4505 case AArch64::LDRSBWroW:
4506 case AArch64::LDRSHWroW:
4507 case AArch64::LDRSBXroW:
4508 case AArch64::LDRSHXroW:
4509 case AArch64::LDRSWroW:
4514bool AArch64FastISel::optimizeIntExtLoad(
const Instruction *
I, MVT RetVT,
4517 if (!LI || !LI->hasOneUse())
4525 MachineInstr *
MI =
MRI.getUniqueVRegDef(
Reg);
4532 const auto *LoadMI =
MI;
4533 if (LoadMI->getOpcode() == TargetOpcode::COPY &&
4534 LoadMI->getOperand(1).getSubReg() == AArch64::sub_32) {
4535 Register LoadReg =
MI->getOperand(1).getReg();
4536 LoadMI =
MRI.getUniqueVRegDef(LoadReg);
4537 assert(LoadMI &&
"Expected valid instruction");
4543 if (RetVT != MVT::i64 || SrcVT > MVT::i32) {
4544 updateValueMap(
I,
Reg);
4549 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
4550 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4551 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4553 .
addImm(AArch64::sub_32);
4556 assert((
MI->getOpcode() == TargetOpcode::COPY &&
4557 MI->getOperand(1).getSubReg() == AArch64::sub_32) &&
4558 "Expected copy instruction");
4559 Reg =
MI->getOperand(1).getReg();
4561 removeDeadCode(
I, std::next(
I));
4563 updateValueMap(
I,
Reg);
4567bool AArch64FastISel::selectIntExt(
const Instruction *
I) {
4569 "Unexpected integer extend instruction.");
4572 if (!isTypeSupported(
I->getType(), RetVT))
4575 if (!isTypeSupported(
I->getOperand(0)->getType(), SrcVT))
4579 if (optimizeIntExtLoad(
I, RetVT, SrcVT))
4582 Register SrcReg = getRegForValue(
I->getOperand(0));
4589 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr())) {
4590 if (RetVT == MVT::i64 && SrcVT != MVT::i64) {
4591 Register ResultReg = createResultReg(&AArch64::GPR64RegClass);
4592 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4593 TII.get(AArch64::SUBREG_TO_REG), ResultReg)
4595 .
addImm(AArch64::sub_32);
4599 updateValueMap(
I, SrcReg);
4604 Register ResultReg = emitIntExt(SrcVT, SrcReg, RetVT, IsZExt);
4608 updateValueMap(
I, ResultReg);
4612bool AArch64FastISel::selectRem(
const Instruction *
I,
unsigned ISDOpcode) {
4613 EVT DestEVT = TLI.getValueType(
DL,
I->getType(),
true);
4618 if (DestVT != MVT::i64 && DestVT != MVT::i32)
4622 bool Is64bit = (DestVT == MVT::i64);
4623 switch (ISDOpcode) {
4627 DivOpc = Is64bit ? AArch64::SDIVXr : AArch64::SDIVWr;
4630 DivOpc = Is64bit ? AArch64::UDIVXr : AArch64::UDIVWr;
4633 unsigned MSubOpc = Is64bit ? AArch64::MSUBXrrr : AArch64::MSUBWrrr;
4634 Register Src0Reg = getRegForValue(
I->getOperand(0));
4638 Register Src1Reg = getRegForValue(
I->getOperand(1));
4642 const TargetRegisterClass *RC =
4643 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4644 Register QuotReg = fastEmitInst_rr(DivOpc, RC, Src0Reg, Src1Reg);
4645 assert(QuotReg &&
"Unexpected DIV instruction emission failure.");
4648 Register ResultReg = fastEmitInst_rrr(MSubOpc, RC, QuotReg, Src1Reg, Src0Reg);
4649 updateValueMap(
I, ResultReg);
4653bool AArch64FastISel::selectMul(
const Instruction *
I) {
4655 if (!isTypeSupported(
I->getType(), VT,
true))
4661 const Value *Src0 =
I->getOperand(0);
4662 const Value *Src1 =
I->getOperand(1);
4664 if (
C->getValue().isPowerOf2())
4669 if (
C->getValue().isPowerOf2()) {
4670 uint64_t ShiftVal =
C->getValue().logBase2();
4676 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), VT)) {
4679 Src0 = ZExt->getOperand(0);
4685 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), VT)) {
4688 Src0 = SExt->getOperand(0);
4693 Register Src0Reg = getRegForValue(Src0);
4697 Register ResultReg = emitLSL_ri(VT, SrcVT, Src0Reg, ShiftVal, IsZExt);
4700 updateValueMap(
I, ResultReg);
4705 Register Src0Reg = getRegForValue(
I->getOperand(0));
4709 Register Src1Reg = getRegForValue(
I->getOperand(1));
4713 Register ResultReg = emitMul_rr(VT, Src0Reg, Src1Reg);
4718 updateValueMap(
I, ResultReg);
4722bool AArch64FastISel::selectShift(
const Instruction *
I) {
4724 if (!isTypeSupported(
I->getType(), RetVT,
true))
4728 return selectOperator(
I,
I->getOpcode());
4732 uint64_t ShiftVal =
C->getZExtValue();
4734 bool IsZExt =
I->getOpcode() != Instruction::AShr;
4735 const Value *Op0 =
I->getOperand(0);
4739 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), TmpVT)) {
4742 Op0 = ZExt->getOperand(0);
4748 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), TmpVT)) {
4751 Op0 = SExt->getOperand(0);
4756 Register Op0Reg = getRegForValue(Op0);
4760 switch (
I->getOpcode()) {
4762 case Instruction::Shl:
4763 ResultReg = emitLSL_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4765 case Instruction::AShr:
4766 ResultReg = emitASR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4768 case Instruction::LShr:
4769 ResultReg = emitLSR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4775 updateValueMap(
I, ResultReg);
4779 Register Op0Reg = getRegForValue(
I->getOperand(0));
4783 Register Op1Reg = getRegForValue(
I->getOperand(1));
4788 switch (
I->getOpcode()) {
4790 case Instruction::Shl:
4791 ResultReg = emitLSL_rr(RetVT, Op0Reg, Op1Reg);
4793 case Instruction::AShr:
4794 ResultReg = emitASR_rr(RetVT, Op0Reg, Op1Reg);
4796 case Instruction::LShr:
4797 ResultReg = emitLSR_rr(RetVT, Op0Reg, Op1Reg);
4804 updateValueMap(
I, ResultReg);
4808bool AArch64FastISel::selectBitCast(
const Instruction *
I) {
4811 if (!isTypeLegal(
I->getOperand(0)->getType(), SrcVT))
4813 if (!isTypeLegal(
I->getType(), RetVT))
4817 if (RetVT == MVT::f32 && SrcVT == MVT::i32)
4818 Opc = AArch64::FMOVWSr;
4819 else if (RetVT == MVT::f64 && SrcVT == MVT::i64)
4820 Opc = AArch64::FMOVXDr;
4821 else if (RetVT == MVT::i32 && SrcVT == MVT::f32)
4822 Opc = AArch64::FMOVSWr;
4823 else if (RetVT == MVT::i64 && SrcVT == MVT::f64)
4824 Opc = AArch64::FMOVDXr;
4828 const TargetRegisterClass *RC =
nullptr;
4831 case MVT::i32: RC = &AArch64::GPR32RegClass;
break;
4832 case MVT::i64: RC = &AArch64::GPR64RegClass;
break;
4833 case MVT::f32: RC = &AArch64::FPR32RegClass;
break;
4834 case MVT::f64: RC = &AArch64::FPR64RegClass;
break;
4836 Register Op0Reg = getRegForValue(
I->getOperand(0));
4840 Register ResultReg = fastEmitInst_r(
Opc, RC, Op0Reg);
4844 updateValueMap(
I, ResultReg);
4848bool AArch64FastISel::selectFRem(
const Instruction *
I) {
4850 if (!isTypeLegal(
I->getType(), RetVT))
4853 RTLIB::LibcallImpl LCImpl =
4855 if (LCImpl == RTLIB::Unsupported)
4859 Args.reserve(
I->getNumOperands());
4862 for (
auto &Arg :
I->operands())
4863 Args.emplace_back(Arg);
4865 CallLoweringInfo CLI;
4866 MCContext &Ctx = MF->getContext();
4867 CallingConv::ID CC = LibcallLowering->getLibcallImplCallingConv(LCImpl);
4870 CLI.setCallee(
DL, Ctx, CC,
I->getType(), FuncName, std::move(Args));
4871 if (!lowerCallTo(CLI))
4873 updateValueMap(
I, CLI.ResultReg);
4877bool AArch64FastISel::selectSDiv(
const Instruction *
I) {
4879 if (!isTypeLegal(
I->getType(), VT))
4886 if ((VT != MVT::i32 && VT != MVT::i64) || !
C ||
4887 !(
C.isPowerOf2() ||
C.isNegatedPowerOf2()))
4890 unsigned Lg2 =
C.countr_zero();
4891 Register Src0Reg = getRegForValue(
I->getOperand(0));
4896 Register ResultReg = emitASR_ri(VT, VT, Src0Reg, Lg2);
4899 updateValueMap(
I, ResultReg);
4903 int64_t Pow2MinusOne = (1ULL << Lg2) - 1;
4904 Register AddReg = emitAdd_ri_(VT, Src0Reg, Pow2MinusOne);
4909 if (!emitICmp_ri(VT, Src0Reg, 0))
4913 const TargetRegisterClass *RC;
4914 if (VT == MVT::i64) {
4915 SelectOpc = AArch64::CSELXr;
4916 RC = &AArch64::GPR64RegClass;
4918 SelectOpc = AArch64::CSELWr;
4919 RC = &AArch64::GPR32RegClass;
4921 Register SelectReg = fastEmitInst_rri(SelectOpc, RC, AddReg, Src0Reg,
4928 Register ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
4931 ResultReg = emitAddSub_rs(
false, VT, ZeroReg, SelectReg,
4934 ResultReg = emitASR_ri(VT, VT, SelectReg, Lg2);
4939 updateValueMap(
I, ResultReg);
4946Register AArch64FastISel::getRegForGEPIndex(
const Value *Idx) {
4947 Register IdxN = getRegForValue(Idx);
4953 MVT PtrVT = TLI.getPointerTy(
DL);
4955 if (IdxVT.
bitsLT(PtrVT)) {
4956 IdxN = emitIntExt(IdxVT.
getSimpleVT(), IdxN, PtrVT,
false);
4957 }
else if (IdxVT.
bitsGT(PtrVT))
4958 llvm_unreachable(
"AArch64 FastISel doesn't support types larger than i64");
4966bool AArch64FastISel::selectGetElementPtr(
const Instruction *
I) {
4970 Register N = getRegForValue(
I->getOperand(0));
4976 uint64_t TotalOffs = 0;
4977 MVT VT = TLI.getPointerTy(
DL);
4980 const Value *Idx = GTI.getOperand();
4981 if (
auto *StTy = GTI.getStructTypeOrNull()) {
4985 TotalOffs +=
DL.getStructLayout(StTy)->getElementOffset(
Field);
4992 TotalOffs += GTI.getSequentialElementStride(
DL) *
4997 N = emitAdd_ri_(VT,
N, TotalOffs);
5004 uint64_t ElementSize = GTI.getSequentialElementStride(
DL);
5005 Register IdxN = getRegForGEPIndex(Idx);
5009 if (ElementSize != 1) {
5013 IdxN = emitMul_rr(VT, IdxN,
C);
5023 N = emitAdd_ri_(VT,
N, TotalOffs);
5027 updateValueMap(
I,
N);
5031bool AArch64FastISel::selectAtomicCmpXchg(
const AtomicCmpXchgInst *
I) {
5032 assert(TM.getOptLevel() == CodeGenOptLevel::None &&
5033 "cmpxchg survived AtomicExpand at optlevel > -O0");
5036 Type *RetTy = RetPairTy->getTypeAtIndex(0U);
5037 assert(RetPairTy->getTypeAtIndex(1U)->isIntegerTy(1) &&
5038 "cmpxchg has a non-i1 status result");
5041 if (!isTypeLegal(RetTy, VT))
5044 const TargetRegisterClass *ResRC;
5045 unsigned Opc, CmpOpc;
5048 if (VT == MVT::i32) {
5049 Opc = AArch64::CMP_SWAP_32;
5050 CmpOpc = AArch64::SUBSWrs;
5051 ResRC = &AArch64::GPR32RegClass;
5052 }
else if (VT == MVT::i64) {
5053 Opc = AArch64::CMP_SWAP_64;
5054 CmpOpc = AArch64::SUBSXrs;
5055 ResRC = &AArch64::GPR64RegClass;
5060 const MCInstrDesc &
II =
TII.get(
Opc);
5062 Register AddrReg = getRegForValue(
I->getPointerOperand());
5063 Register DesiredReg = getRegForValue(
I->getCompareOperand());
5064 Register NewReg = getRegForValue(
I->getNewValOperand());
5066 if (!AddrReg || !DesiredReg || !NewReg)
5073 const Register ResultReg1 = createResultReg(ResRC);
5074 const Register ResultReg2 = createResultReg(&AArch64::GPR32RegClass);
5075 const Register ScratchReg = createResultReg(&AArch64::GPR32RegClass);
5078 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
5085 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CmpOpc))
5086 .
addDef(VT == MVT::i32 ? AArch64::WZR : AArch64::XZR)
5091 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr))
5097 assert((ResultReg1 + 1) == ResultReg2 &&
"Nonconsecutive result registers.");
5098 updateValueMap(
I, ResultReg1, 2);
5102bool AArch64FastISel::fastSelectInstruction(
const Instruction *
I) {
5103 if (TLI.fallBackToDAGISel(*
I))
5105 switch (
I->getOpcode()) {
5108 case Instruction::Add:
5109 case Instruction::Sub:
5110 return selectAddSub(
I);
5111 case Instruction::Mul:
5112 return selectMul(
I);
5113 case Instruction::SDiv:
5114 return selectSDiv(
I);
5115 case Instruction::SRem:
5119 case Instruction::URem:
5123 case Instruction::Shl:
5124 case Instruction::LShr:
5125 case Instruction::AShr:
5126 return selectShift(
I);
5127 case Instruction::And:
5128 case Instruction::Or:
5129 case Instruction::Xor:
5130 return selectLogicalOp(
I);
5131 case Instruction::Br:
5132 return selectBranch(
I);
5133 case Instruction::IndirectBr:
5134 return selectIndirectBr(
I);
5135 case Instruction::BitCast:
5137 return selectBitCast(
I);
5139 case Instruction::FPToSI:
5141 return selectFPToInt(
I,
true);
5143 case Instruction::FPToUI:
5144 return selectFPToInt(
I,
false);
5145 case Instruction::ZExt:
5146 case Instruction::SExt:
5147 return selectIntExt(
I);
5148 case Instruction::Trunc:
5150 return selectTrunc(
I);
5152 case Instruction::FPExt:
5153 return selectFPExt(
I);
5154 case Instruction::FPTrunc:
5155 return selectFPTrunc(
I);
5156 case Instruction::SIToFP:
5158 return selectIntToFP(
I,
true);
5160 case Instruction::UIToFP:
5161 return selectIntToFP(
I,
false);
5162 case Instruction::Load:
5163 return selectLoad(
I);
5164 case Instruction::Store:
5165 return selectStore(
I);
5166 case Instruction::FCmp:
5167 case Instruction::ICmp:
5168 return selectCmp(
I);
5169 case Instruction::Select:
5170 return selectSelect(
I);
5171 case Instruction::Ret:
5172 return selectRet(
I);
5173 case Instruction::FRem:
5174 return selectFRem(
I);
5175 case Instruction::GetElementPtr:
5176 return selectGetElementPtr(
I);
5177 case Instruction::AtomicCmpXchg:
5182 return selectOperator(
I,
I->getOpcode());
5196 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 & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
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)
@ User
could "use" a pointer
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
LLVM_ABI void GetReturnInfo(CallingConv::ID CC, Type *ReturnType, AttributeList attr, SmallVectorImpl< ISD::OutputArg > &Outs, const TargetLowering &TLI, const DataLayout &DL)
Given an LLVM IR type and return type attributes, compute the return value EVTs and flags,...
bool CC_AArch64_Win64PCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_AArch64_DarwinPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
unsigned getBLRCallOpcode(const MachineFunction &MF)
Return opcode to be used for indirect calls.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
gep_type_iterator gep_type_end(const User *GEP)
bool isReleaseOrStronger(AtomicOrdering AO)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
bool CC_AArch64_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
generic_gep_type_iterator<> gep_type_iterator
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
AtomicOrdering
Atomic ordering for LLVM's memory model.
bool CC_AArch64_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
bool RetCC_AArch64_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
gep_type_iterator gep_type_begin(const User *GEP)
bool CC_AArch64_Win64_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
ElementCount getVectorElementCount() const
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool isVector() const
Return true if this is a vector value type.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.