57#include "llvm/IR/IntrinsicsAArch64.h"
81class AArch64FastISel final :
public FastISel {
84 enum BaseKind { RegBase, FrameIndexBase };
87 BaseKind Kind = RegBase;
96 const GlobalValue *GV =
nullptr;
101 void setKind(BaseKind K) { Kind =
K; }
102 BaseKind getKind()
const {
return Kind; }
105 bool isRegBase()
const {
return Kind == RegBase; }
106 bool isFIBase()
const {
return Kind == FrameIndexBase; }
109 assert(isRegBase() &&
"Invalid base register access!");
114 assert(isRegBase() &&
"Invalid base register access!");
120 Register getOffsetReg()
const {
return OffsetReg; }
122 void setFI(
unsigned FI) {
123 assert(isFIBase() &&
"Invalid base frame index access!");
127 unsigned getFI()
const {
128 assert(isFIBase() &&
"Invalid base frame index access!");
132 void setOffset(int64_t O) { Offset =
O; }
134 void setShift(
unsigned S) { Shift = S; }
135 unsigned getShift() {
return Shift; }
137 void setGlobalValue(
const GlobalValue *
G) { GV =
G; }
138 const GlobalValue *getGlobalValue() {
return GV; }
143 const AArch64Subtarget *Subtarget;
144 LLVMContext *Context;
146 bool fastLowerArguments()
override;
147 bool fastLowerCall(CallLoweringInfo &CLI)
override;
148 bool fastLowerIntrinsicCall(
const IntrinsicInst *
II)
override;
152 bool selectAddSub(
const Instruction *
I);
153 bool selectLogicalOp(
const Instruction *
I);
154 bool selectLoad(
const Instruction *
I);
155 bool selectStore(
const Instruction *
I);
156 bool selectBranch(
const Instruction *
I);
157 bool selectIndirectBr(
const Instruction *
I);
158 bool selectCmp(
const Instruction *
I);
159 bool selectSelect(
const Instruction *
I);
160 bool selectFPExt(
const Instruction *
I);
161 bool selectFPTrunc(
const Instruction *
I);
162 bool selectFPToInt(
const Instruction *
I,
bool Signed);
163 bool selectIntToFP(
const Instruction *
I,
bool Signed);
164 bool selectRem(
const Instruction *
I,
unsigned ISDOpcode);
165 bool selectRet(
const Instruction *
I);
166 bool selectTrunc(
const Instruction *
I);
167 bool selectIntExt(
const Instruction *
I);
168 bool selectMul(
const Instruction *
I);
169 bool selectShift(
const Instruction *
I);
170 bool selectBitCast(
const Instruction *
I);
171 bool selectFRem(
const Instruction *
I);
172 bool selectSDiv(
const Instruction *
I);
173 bool selectGetElementPtr(
const Instruction *
I);
174 bool selectAtomicCmpXchg(
const AtomicCmpXchgInst *
I);
177 bool isTypeLegal(
Type *Ty, MVT &VT);
178 bool isTypeSupported(
Type *Ty, MVT &VT,
bool IsVectorAllowed =
false);
179 bool isValueAvailable(
const Value *V)
const;
180 bool computeAddress(
const Value *Obj, Address &Addr,
Type *Ty =
nullptr);
181 bool computeCallAddress(
const Value *V, Address &Addr);
182 bool simplifyAddress(Address &Addr, MVT VT);
183 void addLoadStoreOperands(Address &Addr,
const MachineInstrBuilder &MIB,
185 unsigned ScaleFactor, MachineMemOperand *MMO);
186 bool isMemCpySmall(uint64_t Len, MaybeAlign Alignment);
187 bool tryEmitSmallMemCpy(Address Dest, Address Src, uint64_t Len,
188 MaybeAlign Alignment);
191 bool optimizeIntExtLoad(
const Instruction *
I, MVT RetVT, MVT SrcVT);
192 bool optimizeSelect(
const SelectInst *SI);
197 const Value *
RHS,
bool SetFlags =
false,
198 bool WantResult =
true,
bool IsZExt =
false);
200 Register RHSReg,
bool SetFlags =
false,
201 bool WantResult =
true);
202 Register emitAddSub_ri(
bool UseAdd, MVT RetVT,
Register LHSReg, uint64_t Imm,
203 bool SetFlags =
false,
bool WantResult =
true);
206 uint64_t ShiftImm,
bool SetFlags =
false,
207 bool WantResult =
true);
210 uint64_t ShiftImm,
bool SetFlags =
false,
211 bool WantResult =
true);
214 bool emitCompareAndBranch(
const CondBrInst *BI);
217 bool emitICmp_ri(MVT RetVT,
Register LHSReg, uint64_t Imm);
220 MachineMemOperand *MMO =
nullptr);
222 MachineMemOperand *MMO =
nullptr);
224 MachineMemOperand *MMO =
nullptr);
228 bool SetFlags =
false,
bool WantResult =
true,
229 bool IsZExt =
false);
232 bool SetFlags =
false,
bool WantResult =
true,
233 bool IsZExt =
false);
235 bool WantResult =
true);
238 bool WantResult =
true);
244 Register RHSReg, uint64_t ShiftImm);
257 bool IsZExt =
false);
259 Register materializeInt(
const ConstantInt *CI, MVT VT);
260 Register materializeFP(
const ConstantFP *CFP, MVT VT);
261 Register materializeGV(
const GlobalValue *GV);
265 CCAssignFn *CCAssignFnForCall(CallingConv::ID CC)
const;
266 bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs,
267 SmallVectorImpl<Type *> &OrigTys,
unsigned &NumBytes);
268 bool finishCall(CallLoweringInfo &CLI,
unsigned NumBytes);
272 Register fastMaterializeAlloca(
const AllocaInst *AI)
override;
273 Register fastMaterializeConstant(
const Constant *
C)
override;
274 Register fastMaterializeFloatZero(
const ConstantFP *CF)
override;
276 explicit AArch64FastISel(FunctionLoweringInfo &FuncInfo,
277 const TargetLibraryInfo *LibInfo,
278 const LibcallLoweringInfo *libcallLowering)
279 : FastISel(FuncInfo, LibInfo, libcallLowering,
285 bool fastSelectInstruction(
const Instruction *
I)
override;
287#include "AArch64GenFastISel.inc"
295 "Unexpected integer extend instruction.");
296 assert(!
I->getType()->isVectorTy() &&
I->getType()->isIntegerTy() &&
297 "Unexpected value type.");
305 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr()))
332 if (CC == CallingConv::GHC)
334 if (CC == CallingConv::CFGuard_Check)
343Register AArch64FastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
345 "Alloca should always return a pointer.");
348 auto SI = FuncInfo.StaticAllocaMap.find(AI);
349 if (SI == FuncInfo.StaticAllocaMap.end())
352 if (SI != FuncInfo.StaticAllocaMap.end()) {
353 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
354 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
365Register AArch64FastISel::materializeInt(
const ConstantInt *CI, MVT VT) {
373 const TargetRegisterClass *RC = (VT == MVT::i64) ? &AArch64::GPR64RegClass
374 : &AArch64::GPR32RegClass;
375 unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
376 Register ResultReg = createResultReg(RC);
377 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
382Register AArch64FastISel::materializeFP(
const ConstantFP *CFP, MVT VT) {
386 return fastMaterializeFloatZero(CFP);
388 if (VT != MVT::f32 && VT != MVT::f64)
392 bool Is64Bit = (VT == MVT::f64);
398 unsigned Opc = Is64Bit ? AArch64::FMOVDi : AArch64::FMOVSi;
399 return fastEmitInst_i(
Opc, TLI.getRegClassFor(VT), Imm);
404 unsigned Opc1 = Is64Bit ? AArch64::MOVi64imm : AArch64::MOVi32imm;
405 const TargetRegisterClass *RC = Is64Bit ?
406 &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
408 Register TmpReg = createResultReg(RC);
409 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc1), TmpReg)
410 .addImm(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
412 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
413 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
414 TII.get(TargetOpcode::COPY), ResultReg)
415 .addReg(TmpReg, getKillRegState(true));
422 Align Alignment =
DL.getPrefTypeAlign(CFP->
getType());
424 unsigned CPI = MCP.getConstantPoolIndex(
cast<Constant>(CFP), Alignment);
425 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
426 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
429 unsigned Opc = Is64Bit ? AArch64::LDRDui : AArch64::LDRSui;
430 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
431 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
437Register AArch64FastISel::materializeGV(
const GlobalValue *GV) {
447 if (FuncInfo.MF->getInfo<AArch64FunctionInfo>()->hasELFSignedGOT())
452 EVT DestEVT = TLI.getValueType(
DL, GV->
getType(),
true);
456 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
461 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
467 ResultReg = createResultReg(&AArch64::GPR32RegClass);
468 LdrOpc = AArch64::LDRWui;
470 ResultReg = createResultReg(&AArch64::GPR64RegClass);
471 LdrOpc = AArch64::LDRXui;
473 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(LdrOpc),
483 Register Result64 = createResultReg(&AArch64::GPR64RegClass);
484 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
485 TII.get(TargetOpcode::SUBREG_TO_REG))
487 .
addReg(ResultReg, RegState::Kill)
492 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
510 Register DstReg = createResultReg(&AArch64::GPR64commonRegClass);
511 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::MOVKXi),
520 ResultReg = createResultReg(&AArch64::GPR64spRegClass);
521 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
531Register AArch64FastISel::fastMaterializeConstant(
const Constant *
C) {
532 EVT CEVT = TLI.getValueType(
DL,
C->getType(),
true);
541 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));
2038 MI = MRI.getUniqueVRegDef(
Reg);
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 CondBrInst *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))
2375 finishCondBranch(BI->getParent(),
TBB, FBB);
2379bool AArch64FastISel::selectBranch(
const Instruction *
I) {
2383 MachineBasicBlock *FBB = FuncInfo.getMBB(BI->
getSuccessor(1));
2386 if (CI->
hasOneUse() && isValueAvailable(CI)) {
2389 switch (Predicate) {
2393 fastEmitBranch(FBB, MIMD.getDL());
2396 fastEmitBranch(
TBB, MIMD.getDL());
2401 if (emitCompareAndBranch(BI))
2405 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2418 switch (Predicate) {
2434 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2440 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2444 finishCondBranch(BI->getParent(),
TBB, FBB);
2448 uint64_t
Imm = CI->getZExtValue();
2450 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::B))
2455 auto BranchProbability = FuncInfo.BPI->getEdgeProbability(
2456 BI->getParent(),
Target->getBasicBlock());
2457 FuncInfo.MBB->addSuccessor(Target, BranchProbability);
2459 FuncInfo.MBB->addSuccessorWithoutProb(Target);
2471 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2475 finishCondBranch(BI->getParent(),
TBB, FBB);
2485 unsigned Opcode = AArch64::TBNZW;
2486 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2488 Opcode = AArch64::TBZW;
2491 const MCInstrDesc &
II =
TII.get(Opcode);
2494 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2495 .
addReg(ConstrainedCondReg)
2499 finishCondBranch(BI->getParent(),
TBB, FBB);
2503bool AArch64FastISel::selectIndirectBr(
const Instruction *
I) {
2510 if (FuncInfo.MF->getFunction().hasFnAttribute(
"ptrauth-indirect-gotos"))
2514 const MCInstrDesc &
II =
TII.get(AArch64::BR);
2520 FuncInfo.MBB->addSuccessor(FuncInfo.getMBB(Succ));
2525bool AArch64FastISel::selectCmp(
const Instruction *
I) {
2535 switch (Predicate) {
2539 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2540 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2541 TII.get(TargetOpcode::COPY), ResultReg)
2545 ResultReg = fastEmit_i(MVT::i32, MVT::i32,
ISD::Constant, 1);
2550 updateValueMap(
I, ResultReg);
2558 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2562 static unsigned CondCodeTable[2][2] = {
2567 switch (Predicate) {
2579 Register TmpReg1 = createResultReg(&AArch64::GPR32RegClass);
2580 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2585 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2591 updateValueMap(
I, ResultReg);
2599 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2605 updateValueMap(
I, ResultReg);
2611bool AArch64FastISel::optimizeSelect(
const SelectInst *SI) {
2612 if (!
SI->getType()->isIntegerTy(1))
2615 const Value *Src1Val, *Src2Val;
2617 bool NeedExtraOp =
false;
2620 Src1Val =
SI->getCondition();
2621 Src2Val =
SI->getFalseValue();
2622 Opc = AArch64::ORRWrr;
2625 Src1Val =
SI->getFalseValue();
2626 Src2Val =
SI->getCondition();
2627 Opc = AArch64::BICWrr;
2631 Src1Val =
SI->getCondition();
2632 Src2Val =
SI->getTrueValue();
2633 Opc = AArch64::ORRWrr;
2637 Src1Val =
SI->getCondition();
2638 Src2Val =
SI->getTrueValue();
2639 Opc = AArch64::ANDWrr;
2646 Register Src1Reg = getRegForValue(Src1Val);
2650 Register Src2Reg = getRegForValue(Src2Val);
2655 Src1Reg = emitLogicalOp_ri(
ISD::XOR, MVT::i32, Src1Reg, 1);
2657 Register ResultReg = fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, Src1Reg,
2659 updateValueMap(SI, ResultReg);
2663bool AArch64FastISel::selectSelect(
const Instruction *
I) {
2666 if (!isTypeSupported(
I->getType(), VT))
2670 const TargetRegisterClass *RC;
2678 Opc = AArch64::CSELWr;
2679 RC = &AArch64::GPR32RegClass;
2682 Opc = AArch64::CSELXr;
2683 RC = &AArch64::GPR64RegClass;
2686 Opc = AArch64::FCSELSrrr;
2687 RC = &AArch64::FPR32RegClass;
2690 Opc = AArch64::FCSELDrrr;
2691 RC = &AArch64::FPR64RegClass;
2700 if (optimizeSelect(SI))
2704 if (foldXALUIntrinsic(CC,
I,
Cond)) {
2710 isValueAvailable(
Cond)) {
2714 const Value *FoldSelect =
nullptr;
2715 switch (Predicate) {
2719 FoldSelect =
SI->getFalseValue();
2722 FoldSelect =
SI->getTrueValue();
2727 Register SrcReg = getRegForValue(FoldSelect);
2731 updateValueMap(
I, SrcReg);
2741 switch (Predicate) {
2759 const MCInstrDesc &
II =
TII.get(AArch64::ANDSWri);
2763 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II,
2769 Register Src1Reg = getRegForValue(
SI->getTrueValue());
2770 Register Src2Reg = getRegForValue(
SI->getFalseValue());
2772 if (!Src1Reg || !Src2Reg)
2776 Src2Reg = fastEmitInst_rri(
Opc, RC, Src1Reg, Src2Reg, ExtraCC);
2778 Register ResultReg = fastEmitInst_rri(
Opc, RC, Src1Reg, Src2Reg, CC);
2779 updateValueMap(
I, ResultReg);
2783bool AArch64FastISel::selectFPExt(
const Instruction *
I) {
2785 if (!
I->getType()->isDoubleTy() || !
V->getType()->isFloatTy())
2792 Register ResultReg = createResultReg(&AArch64::FPR64RegClass);
2793 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTDSr),
2795 updateValueMap(
I, ResultReg);
2799bool AArch64FastISel::selectFPTrunc(
const Instruction *
I) {
2801 if (!
I->getType()->isFloatTy() || !
V->getType()->isDoubleTy())
2808 Register ResultReg = createResultReg(&AArch64::FPR32RegClass);
2809 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTSDr),
2811 updateValueMap(
I, ResultReg);
2816bool AArch64FastISel::selectFPToInt(
const Instruction *
I,
bool Signed) {
2818 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2821 Register SrcReg = getRegForValue(
I->getOperand(0));
2825 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2826 if (SrcVT == MVT::f128 || SrcVT == MVT::f16 || SrcVT == MVT::bf16)
2830 if (SrcVT == MVT::f64) {
2832 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWDr : AArch64::FCVTZSUXDr;
2834 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWDr : AArch64::FCVTZUUXDr;
2837 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWSr : AArch64::FCVTZSUXSr;
2839 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWSr : AArch64::FCVTZUUXSr;
2841 Register ResultReg = createResultReg(
2842 DestVT == MVT::i32 ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass);
2843 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
2845 updateValueMap(
I, ResultReg);
2849bool AArch64FastISel::selectIntToFP(
const Instruction *
I,
bool Signed) {
2851 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2854 if (DestVT == MVT::f16 || DestVT == MVT::bf16)
2857 assert((DestVT == MVT::f32 || DestVT == MVT::f64) &&
2858 "Unexpected value type.");
2860 Register SrcReg = getRegForValue(
I->getOperand(0));
2864 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2867 if (SrcVT == MVT::i16 || SrcVT == MVT::i8 || SrcVT == MVT::i1) {
2875 if (SrcVT == MVT::i64) {
2877 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUXSri : AArch64::SCVTFUXDri;
2879 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUXSri : AArch64::UCVTFUXDri;
2882 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUWSri : AArch64::SCVTFUWDri;
2884 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUWSri : AArch64::UCVTFUWDri;
2887 Register ResultReg = fastEmitInst_r(
Opc, TLI.getRegClassFor(DestVT), SrcReg);
2888 updateValueMap(
I, ResultReg);
2892bool AArch64FastISel::fastLowerArguments() {
2893 if (!FuncInfo.CanLowerReturn)
2900 CallingConv::ID CC =
F->getCallingConv();
2901 if (CC != CallingConv::C && CC != CallingConv::Swift)
2908 unsigned GPRCnt = 0;
2909 unsigned FPRCnt = 0;
2910 for (
auto const &Arg :
F->args()) {
2911 if (Arg.hasAttribute(Attribute::ByVal) ||
2912 Arg.hasAttribute(Attribute::InReg) ||
2913 Arg.hasAttribute(Attribute::StructRet) ||
2914 Arg.hasAttribute(Attribute::SwiftSelf) ||
2915 Arg.hasAttribute(Attribute::SwiftAsync) ||
2916 Arg.hasAttribute(Attribute::SwiftError) ||
2917 Arg.hasAttribute(Attribute::Nest))
2920 Type *ArgTy = Arg.getType();
2924 EVT ArgVT = TLI.getValueType(
DL, ArgTy);
2936 if (VT >= MVT::i1 && VT <= MVT::i64)
2938 else if ((VT >= MVT::f16 && VT <= MVT::f64) || VT.
is64BitVector() ||
2944 if (GPRCnt > 8 || FPRCnt > 8)
2949 { AArch64::W0, AArch64::W1, AArch64::W2, AArch64::W3, AArch64::W4,
2950 AArch64::W5, AArch64::W6, AArch64::W7 },
2951 { AArch64::X0, AArch64::X1, AArch64::X2, AArch64::X3, AArch64::X4,
2952 AArch64::X5, AArch64::X6, AArch64::X7 },
2953 { AArch64::H0, AArch64::H1, AArch64::H2, AArch64::H3, AArch64::H4,
2954 AArch64::H5, AArch64::H6, AArch64::H7 },
2955 { AArch64::S0, AArch64::S1, AArch64::S2, AArch64::S3, AArch64::S4,
2956 AArch64::S5, AArch64::S6, AArch64::S7 },
2957 { AArch64::D0, AArch64::D1, AArch64::D2, AArch64::D3, AArch64::D4,
2958 AArch64::D5, AArch64::D6, AArch64::D7 },
2959 { AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,
2960 AArch64::Q5, AArch64::Q6, AArch64::Q7 }
2963 unsigned GPRIdx = 0;
2964 unsigned FPRIdx = 0;
2965 for (
auto const &Arg :
F->args()) {
2966 MVT VT = TLI.getSimpleValueType(
DL, Arg.getType());
2968 const TargetRegisterClass *RC;
2969 if (VT >= MVT::i1 && VT <= MVT::i32) {
2971 RC = &AArch64::GPR32RegClass;
2973 }
else if (VT == MVT::i64) {
2975 RC = &AArch64::GPR64RegClass;
2976 }
else if (VT == MVT::f16 || VT == MVT::bf16) {
2978 RC = &AArch64::FPR16RegClass;
2979 }
else if (VT == MVT::f32) {
2981 RC = &AArch64::FPR32RegClass;
2984 RC = &AArch64::FPR64RegClass;
2987 RC = &AArch64::FPR128RegClass;
2991 Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
2995 Register ResultReg = createResultReg(RC);
2996 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2997 TII.get(TargetOpcode::COPY), ResultReg)
2999 updateValueMap(&Arg, ResultReg);
3004bool AArch64FastISel::processCallArgs(CallLoweringInfo &CLI,
3005 SmallVectorImpl<MVT> &OutVTs,
3006 SmallVectorImpl<Type *> &OrigTys,
3007 unsigned &NumBytes) {
3008 CallingConv::ID CC = CLI.CallConv;
3010 CCState CCInfo(CC,
false, *FuncInfo.MF, ArgLocs, *
Context);
3011 CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, OrigTys,
3012 CCAssignFnForCall(CC));
3015 NumBytes = CCInfo.getStackSize();
3018 unsigned AdjStackDown =
TII.getCallFrameSetupOpcode();
3019 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackDown))
3023 for (CCValAssign &VA : ArgLocs) {
3024 const Value *ArgVal = CLI.OutVals[VA.getValNo()];
3025 MVT ArgVT = OutVTs[VA.getValNo()];
3027 Register ArgReg = getRegForValue(ArgVal);
3032 switch (VA.getLocInfo()) {
3036 MVT DestVT = VA.getLocVT();
3038 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
false);
3046 MVT DestVT = VA.getLocVT();
3048 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
true);
3058 if (VA.isRegLoc() && !VA.needsCustom()) {
3059 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3060 TII.get(TargetOpcode::COPY), VA.getLocReg()).
addReg(ArgReg);
3061 CLI.OutRegs.push_back(VA.getLocReg());
3062 }
else if (VA.needsCustom()) {
3066 assert(VA.isMemLoc() &&
"Assuming store on stack.");
3075 unsigned BEAlign = 0;
3076 if (ArgSize < 8 && !Subtarget->isLittleEndian())
3077 BEAlign = 8 - ArgSize;
3080 Addr.setKind(Address::RegBase);
3081 Addr.setReg(AArch64::SP);
3082 Addr.setOffset(VA.getLocMemOffset() + BEAlign);
3085 MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
3089 if (!
emitStore(ArgVT, ArgReg, Addr, MMO))
3096bool AArch64FastISel::finishCall(CallLoweringInfo &CLI,
unsigned NumBytes) {
3097 CallingConv::ID CC = CLI.CallConv;
3100 unsigned AdjStackUp =
TII.getCallFrameDestroyOpcode();
3101 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackUp))
3106 CCState CCInfo(CC,
false, *FuncInfo.MF, RVLocs, *
Context);
3107 CCInfo.AnalyzeCallResult(CLI.Ins, CCAssignFnForCall(CC));
3109 Register ResultReg = FuncInfo.CreateRegs(CLI.RetTy);
3110 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
3111 CCValAssign &VA = RVLocs[i];
3120 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
3126 CLI.ResultReg = ResultReg;
3127 CLI.NumResultRegs = RVLocs.
size();
3132bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
3133 CallingConv::ID CC = CLI.CallConv;
3134 bool IsTailCall = CLI.IsTailCall;
3135 bool IsVarArg = CLI.IsVarArg;
3139 if (!Callee && !Symbol)
3144 if (CLI.CB && CLI.CB->hasFnAttr(Attribute::ReturnsTwice) &&
3145 !Subtarget->noBTIAtReturnTwice() &&
3146 MF->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement())
3150 if (CLI.CB && CLI.CB->isIndirectCall() &&
3174 if (MF->getFunction().getParent()->getRtLibUseGOT())
3184 for (
auto Flag : CLI.OutFlags)
3186 Flag.isSwiftSelf() ||
Flag.isSwiftAsync() ||
Flag.isSwiftError())
3192 OutVTs.
reserve(CLI.OutVals.size());
3194 for (
auto *Val : CLI.OutVals) {
3196 if (!isTypeLegal(Val->getType(), VT) &&
3197 !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16))
3209 if (Callee && !computeCallAddress(Callee, Addr))
3216 Addr.getGlobalValue()->hasExternalWeakLinkage())
3221 if (!processCallArgs(CLI, OutVTs, OrigTys, NumBytes))
3229 MachineInstrBuilder MIB;
3231 const MCInstrDesc &
II =
3233 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II);
3236 else if (Addr.getGlobalValue())
3238 else if (Addr.getReg()) {
3246 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
3247 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
3251 CallReg = createResultReg(&AArch64::GPR64RegClass);
3252 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3253 TII.get(AArch64::LDRXui), CallReg)
3257 }
else if (Addr.getGlobalValue())
3258 CallReg = materializeGV(Addr.getGlobalValue());
3259 else if (Addr.getReg())
3260 CallReg = Addr.getReg();
3267 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II).
addReg(CallReg);
3271 for (
auto Reg : CLI.OutRegs)
3281 return finishCall(CLI, NumBytes);
3284bool AArch64FastISel::isMemCpySmall(uint64_t Len, MaybeAlign Alignment) {
3286 return Len / Alignment->value() <= 4;
3291bool AArch64FastISel::tryEmitSmallMemCpy(
Address Dest,
Address Src,
3292 uint64_t Len, MaybeAlign Alignment) {
3294 if (!isMemCpySmall(Len, Alignment))
3297 int64_t UnscaledOffset = 0;
3303 if (!Alignment || *Alignment >= 8) {
3314 assert(Alignment &&
"Alignment is set in this branch");
3316 if (Len >= 4 && *Alignment == 4)
3318 else if (Len >= 2 && *Alignment == 2)
3334 UnscaledOffset +=
Size;
3337 Dest.setOffset(OrigDest.getOffset() + UnscaledOffset);
3338 Src.setOffset(OrigSrc.getOffset() + UnscaledOffset);
3347 const Instruction *
I,
3361 if (!isTypeLegal(RetTy, RetVT))
3364 if (RetVT != MVT::i32 && RetVT != MVT::i64)
3379 case Intrinsic::smul_with_overflow:
3381 if (
C->getValue() == 2)
3382 IID = Intrinsic::sadd_with_overflow;
3384 case Intrinsic::umul_with_overflow:
3386 if (
C->getValue() == 2)
3387 IID = Intrinsic::uadd_with_overflow;
3395 case Intrinsic::sadd_with_overflow:
3396 case Intrinsic::ssub_with_overflow:
3399 case Intrinsic::uadd_with_overflow:
3402 case Intrinsic::usub_with_overflow:
3405 case Intrinsic::smul_with_overflow:
3406 case Intrinsic::umul_with_overflow:
3412 if (!isValueAvailable(
II))
3418 for (
auto Itr = std::prev(Start); Itr != End; --Itr) {
3426 if (EVI->getAggregateOperand() !=
II)
3434bool AArch64FastISel::fastLowerIntrinsicCall(
const IntrinsicInst *
II) {
3436 switch (
II->getIntrinsicID()) {
3437 default:
return false;
3438 case Intrinsic::frameaddress: {
3439 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3444 Register SrcReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3445 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3455 DestReg = fastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,
3457 assert(DestReg &&
"Unexpected LDR instruction emission failure.");
3461 updateValueMap(
II, SrcReg);
3464 case Intrinsic::sponentry: {
3465 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3469 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
3470 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3471 TII.get(AArch64::ADDXri), ResultReg)
3476 updateValueMap(
II, ResultReg);
3479 case Intrinsic::memcpy:
3480 case Intrinsic::memmove: {
3483 if (MTI->isVolatile())
3488 bool IsMemCpy = (
II->getIntrinsicID() == Intrinsic::memcpy);
3493 MaybeAlign Alignment;
3494 if (MTI->getDestAlign() || MTI->getSourceAlign())
3495 Alignment = std::min(MTI->getDestAlign().valueOrOne(),
3496 MTI->getSourceAlign().valueOrOne());
3497 if (isMemCpySmall(Len, Alignment)) {
3499 if (!computeAddress(MTI->getRawDest(), Dest) ||
3500 !computeAddress(MTI->getRawSource(), Src))
3502 if (tryEmitSmallMemCpy(Dest, Src, Len, Alignment))
3507 if (!MTI->getLength()->getType()->isIntegerTy(64))
3510 if (MTI->getSourceAddressSpace() > 255 || MTI->getDestAddressSpace() > 255)
3516 return lowerCallTo(
II, IntrMemName,
II->arg_size() - 1);
3518 case Intrinsic::memset: {
3532 return lowerCallTo(
II,
"memset",
II->arg_size() - 1);
3534 case Intrinsic::sin:
3535 case Intrinsic::cos:
3536 case Intrinsic::tan:
3537 case Intrinsic::pow: {
3539 if (!isTypeLegal(
II->getType(), RetVT))
3542 if (RetVT != MVT::f32 && RetVT != MVT::f64)
3545 static const RTLIB::Libcall LibCallTable[4][2] = {
3546 {RTLIB::SIN_F32, RTLIB::SIN_F64},
3547 {RTLIB::COS_F32, RTLIB::COS_F64},
3548 {RTLIB::TAN_F32, RTLIB::TAN_F64},
3549 {RTLIB::POW_F32, RTLIB::POW_F64}};
3551 bool Is64Bit = RetVT == MVT::f64;
3552 switch (
II->getIntrinsicID()) {
3555 case Intrinsic::sin:
3556 LC = LibCallTable[0][Is64Bit];
3558 case Intrinsic::cos:
3559 LC = LibCallTable[1][Is64Bit];
3561 case Intrinsic::tan:
3562 LC = LibCallTable[2][Is64Bit];
3564 case Intrinsic::pow:
3565 LC = LibCallTable[3][Is64Bit];
3570 Args.reserve(
II->arg_size());
3573 for (
auto &Arg :
II->args())
3574 Args.emplace_back(Arg);
3576 CallLoweringInfo CLI;
3577 MCContext &Ctx = MF->getContext();
3579 RTLIB::LibcallImpl LCImpl = LibcallLowering->getLibcallImpl(LC);
3580 if (LCImpl == RTLIB::Unsupported)
3583 CallingConv::ID CC = LibcallLowering->getLibcallImplCallingConv(LCImpl);
3585 CLI.setCallee(
DL, Ctx, CC,
II->getType(), FuncName, std::move(Args));
3586 if (!lowerCallTo(CLI))
3588 updateValueMap(
II, CLI.ResultReg);
3591 case Intrinsic::fabs: {
3593 if (!isTypeLegal(
II->getType(), VT))
3601 Opc = AArch64::FABSSr;
3604 Opc = AArch64::FABSDr;
3607 Register SrcReg = getRegForValue(
II->getOperand(0));
3610 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3611 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
3613 updateValueMap(
II, ResultReg);
3616 case Intrinsic::trap:
3617 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3620 case Intrinsic::debugtrap:
3621 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3625 case Intrinsic::sqrt: {
3626 Type *RetTy =
II->getCalledFunction()->getReturnType();
3629 if (!isTypeLegal(RetTy, VT))
3632 Register Op0Reg = getRegForValue(
II->getOperand(0));
3640 updateValueMap(
II, ResultReg);
3643 case Intrinsic::sadd_with_overflow:
3644 case Intrinsic::uadd_with_overflow:
3645 case Intrinsic::ssub_with_overflow:
3646 case Intrinsic::usub_with_overflow:
3647 case Intrinsic::smul_with_overflow:
3648 case Intrinsic::umul_with_overflow: {
3652 Type *RetTy = Ty->getTypeAtIndex(0U);
3655 if (!isTypeLegal(RetTy, VT))
3658 if (VT != MVT::i32 && VT != MVT::i64)
3672 case Intrinsic::smul_with_overflow:
3674 if (
C->getValue() == 2) {
3675 IID = Intrinsic::sadd_with_overflow;
3679 case Intrinsic::umul_with_overflow:
3681 if (
C->getValue() == 2) {
3682 IID = Intrinsic::uadd_with_overflow;
3688 Register ResultReg1, ResultReg2, MulReg;
3692 case Intrinsic::sadd_with_overflow:
3693 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3696 case Intrinsic::uadd_with_overflow:
3697 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3700 case Intrinsic::ssub_with_overflow:
3701 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3704 case Intrinsic::usub_with_overflow:
3705 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3708 case Intrinsic::smul_with_overflow: {
3718 if (VT == MVT::i32) {
3719 MulReg = emitSMULL_rr(MVT::i64, LHSReg, RHSReg);
3721 fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3723 emitAddSub_rx(
false, MVT::i64, MulReg, MulSubReg,
3728 assert(VT == MVT::i64 &&
"Unexpected value type.");
3731 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3738 case Intrinsic::umul_with_overflow: {
3748 if (VT == MVT::i32) {
3749 MulReg = emitUMULL_rr(MVT::i64, LHSReg, RHSReg);
3751 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3752 TII.get(AArch64::ANDSXri), AArch64::XZR)
3755 MulReg = fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3757 assert(VT == MVT::i64 &&
"Unexpected value type.");
3760 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3762 emitSubs_rr(VT, AArch64::XZR, UMULHReg,
false);
3769 ResultReg1 = createResultReg(TLI.getRegClassFor(VT));
3770 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3771 TII.get(TargetOpcode::COPY), ResultReg1).
addReg(MulReg);
3777 ResultReg2 = fastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,
3778 AArch64::WZR, AArch64::WZR,
3779 getInvertedCondCode(CC));
3781 assert((ResultReg1 + 1) == ResultReg2 &&
3782 "Nonconsecutive result registers.");
3783 updateValueMap(
II, ResultReg1, 2);
3786 case Intrinsic::aarch64_crc32b:
3787 case Intrinsic::aarch64_crc32h:
3788 case Intrinsic::aarch64_crc32w:
3789 case Intrinsic::aarch64_crc32x:
3790 case Intrinsic::aarch64_crc32cb:
3791 case Intrinsic::aarch64_crc32ch:
3792 case Intrinsic::aarch64_crc32cw:
3793 case Intrinsic::aarch64_crc32cx: {
3794 if (!Subtarget->hasCRC())
3798 switch (
II->getIntrinsicID()) {
3801 case Intrinsic::aarch64_crc32b:
3802 Opc = AArch64::CRC32Brr;
3804 case Intrinsic::aarch64_crc32h:
3805 Opc = AArch64::CRC32Hrr;
3807 case Intrinsic::aarch64_crc32w:
3808 Opc = AArch64::CRC32Wrr;
3810 case Intrinsic::aarch64_crc32x:
3811 Opc = AArch64::CRC32Xrr;
3813 case Intrinsic::aarch64_crc32cb:
3814 Opc = AArch64::CRC32CBrr;
3816 case Intrinsic::aarch64_crc32ch:
3817 Opc = AArch64::CRC32CHrr;
3819 case Intrinsic::aarch64_crc32cw:
3820 Opc = AArch64::CRC32CWrr;
3822 case Intrinsic::aarch64_crc32cx:
3823 Opc = AArch64::CRC32CXrr;
3827 Register LHSReg = getRegForValue(
II->getArgOperand(0));
3828 Register RHSReg = getRegForValue(
II->getArgOperand(1));
3829 if (!LHSReg || !RHSReg)
3833 fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, LHSReg, RHSReg);
3834 updateValueMap(
II, ResultReg);
3841bool AArch64FastISel::selectRet(
const Instruction *
I) {
3843 const Function &
F = *
I->getParent()->getParent();
3845 if (!FuncInfo.CanLowerReturn)
3851 if (TLI.supportSwiftError() &&
3852 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
3855 if (TLI.supportSplitCSR(FuncInfo.MF))
3862 CallingConv::ID CC =
F.getCallingConv();
3868 CCState CCInfo(CC,
F.isVarArg(), *FuncInfo.MF, ValLocs,
I->getContext());
3872 if (ValLocs.
size() != 1)
3875 CCValAssign &VA = ValLocs[0];
3894 if (!MRI.getRegClass(SrcReg)->contains(DestReg))
3897 EVT RVEVT = TLI.getValueType(
DL, RV->
getType());
3907 if (RVVT == MVT::f128)
3912 if (RVVT != DestVT) {
3913 if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
3916 if (!Outs[0].
Flags.isZExt() && !Outs[0].Flags.isSExt())
3919 bool IsZExt = Outs[0].Flags.isZExt();
3920 SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
3928 SrcReg = emitAnd_ri(MVT::i64, SrcReg, 0xffffffff);
3931 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3932 TII.get(TargetOpcode::COPY), DestReg).
addReg(SrcReg);
3938 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3939 TII.get(AArch64::RET_ReallyLR));
3941 MIB.
addReg(RetReg, RegState::Implicit);
3945bool AArch64FastISel::selectTrunc(
const Instruction *
I) {
3946 Type *DestTy =
I->getType();
3948 Type *SrcTy =
Op->getType();
3950 EVT SrcEVT = TLI.getValueType(
DL, SrcTy,
true);
3951 EVT DestEVT = TLI.getValueType(
DL, DestTy,
true);
3960 if (SrcVT != MVT::i64 && SrcVT != MVT::i32 && SrcVT != MVT::i16 &&
3963 if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8 &&
3977 if (SrcVT == MVT::i64) {
3994 Register Reg32 = fastEmitInst_extractsubreg(MVT::i32, SrcReg,
3997 ResultReg = emitAnd_ri(MVT::i32, Reg32, Mask);
3998 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4000 ResultReg = createResultReg(&AArch64::GPR32RegClass);
4001 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4002 TII.get(TargetOpcode::COPY), ResultReg)
4006 updateValueMap(
I, ResultReg);
4010Register AArch64FastISel::emiti1Ext(
Register SrcReg, MVT DestVT,
bool IsZExt) {
4011 assert((DestVT == MVT::i8 || DestVT == MVT::i16 || DestVT == MVT::i32 ||
4012 DestVT == MVT::i64) &&
4013 "Unexpected value type.");
4015 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4019 Register ResultReg = emitAnd_ri(MVT::i32, SrcReg, 1);
4020 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4021 if (DestVT == MVT::i64) {
4024 Register Reg64 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4025 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4026 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4028 .
addImm(AArch64::sub_32);
4033 if (DestVT == MVT::i64) {
4037 return fastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,
4052 Opc = AArch64::MADDWrrr; ZReg = AArch64::WZR;
break;
4054 Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR;
break;
4057 const TargetRegisterClass *RC =
4058 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4059 return fastEmitInst_rrr(
Opc, RC, Op0, Op1, ZReg);
4063 if (RetVT != MVT::i64)
4066 return fastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,
4067 Op0, Op1, AArch64::XZR);
4071 if (RetVT != MVT::i64)
4074 return fastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,
4075 Op0, Op1, AArch64::XZR);
4081 bool NeedTrunc =
false;
4086 case MVT::i8:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4087 case MVT::i16:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4088 case MVT::i32:
Opc = AArch64::LSLVWr;
break;
4089 case MVT::i64:
Opc = AArch64::LSLVXr;
break;
4092 const TargetRegisterClass *RC =
4093 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4095 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4097 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4099 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4104 uint64_t Shift,
bool IsZExt) {
4106 "Unexpected source/return type pair.");
4107 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4108 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4109 "Unexpected source value type.");
4110 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4111 RetVT == MVT::i64) &&
"Unexpected return value type.");
4113 bool Is64Bit = (RetVT == MVT::i64);
4114 unsigned RegSize = Is64Bit ? 64 : 32;
4117 const TargetRegisterClass *RC =
4118 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4122 if (RetVT == SrcVT) {
4123 Register ResultReg = createResultReg(RC);
4124 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4125 TII.get(TargetOpcode::COPY), ResultReg)
4129 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4133 if (Shift >= DstBits)
4161 unsigned ImmR =
RegSize - Shift;
4163 unsigned ImmS = std::min<unsigned>(SrcBits - 1, DstBits - 1 - Shift);
4164 static const unsigned OpcTable[2][2] = {
4165 {AArch64::SBFMWri, AArch64::SBFMXri},
4166 {AArch64::UBFMWri, AArch64::UBFMXri}
4168 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4169 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4170 Register TmpReg = MRI.createVirtualRegister(RC);
4171 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4172 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4174 .
addImm(AArch64::sub_32);
4177 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4183 bool NeedTrunc =
false;
4188 case MVT::i8:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4189 case MVT::i16:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4190 case MVT::i32:
Opc = AArch64::LSRVWr;
break;
4191 case MVT::i64:
Opc = AArch64::LSRVXr;
break;
4194 const TargetRegisterClass *RC =
4195 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4197 Op0Reg = emitAnd_ri(MVT::i32, Op0Reg, Mask);
4198 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4200 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4202 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4207 uint64_t Shift,
bool IsZExt) {
4209 "Unexpected source/return type pair.");
4210 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4211 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4212 "Unexpected source value type.");
4213 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4214 RetVT == MVT::i64) &&
"Unexpected return value type.");
4216 bool Is64Bit = (RetVT == MVT::i64);
4217 unsigned RegSize = Is64Bit ? 64 : 32;
4220 const TargetRegisterClass *RC =
4221 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4225 if (RetVT == SrcVT) {
4226 Register ResultReg = createResultReg(RC);
4227 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4228 TII.get(TargetOpcode::COPY), ResultReg)
4232 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4236 if (Shift >= DstBits)
4264 if (Shift >= SrcBits && IsZExt)
4265 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4270 Op0 = emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4278 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4279 unsigned ImmS = SrcBits - 1;
4280 static const unsigned OpcTable[2][2] = {
4281 {AArch64::SBFMWri, AArch64::SBFMXri},
4282 {AArch64::UBFMWri, AArch64::UBFMXri}
4284 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4285 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4286 Register TmpReg = MRI.createVirtualRegister(RC);
4287 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4288 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4290 .
addImm(AArch64::sub_32);
4293 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4299 bool NeedTrunc =
false;
4304 case MVT::i8:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4305 case MVT::i16:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4306 case MVT::i32:
Opc = AArch64::ASRVWr;
break;
4307 case MVT::i64:
Opc = AArch64::ASRVXr;
break;
4310 const TargetRegisterClass *RC =
4311 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4313 Op0Reg = emitIntExt(RetVT, Op0Reg, MVT::i32,
false);
4314 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4316 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4318 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4323 uint64_t Shift,
bool IsZExt) {
4325 "Unexpected source/return type pair.");
4326 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4327 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4328 "Unexpected source value type.");
4329 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4330 RetVT == MVT::i64) &&
"Unexpected return value type.");
4332 bool Is64Bit = (RetVT == MVT::i64);
4333 unsigned RegSize = Is64Bit ? 64 : 32;
4336 const TargetRegisterClass *RC =
4337 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4341 if (RetVT == SrcVT) {
4342 Register ResultReg = createResultReg(RC);
4343 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4344 TII.get(TargetOpcode::COPY), ResultReg)
4348 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4352 if (Shift >= DstBits)
4380 if (Shift >= SrcBits && IsZExt)
4381 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4383 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4384 unsigned ImmS = SrcBits - 1;
4385 static const unsigned OpcTable[2][2] = {
4386 {AArch64::SBFMWri, AArch64::SBFMXri},
4387 {AArch64::UBFMWri, AArch64::UBFMXri}
4389 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4390 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4391 Register TmpReg = MRI.createVirtualRegister(RC);
4392 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4393 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4395 .
addImm(AArch64::sub_32);
4398 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4401Register AArch64FastISel::emitIntExt(MVT SrcVT,
Register SrcReg, MVT DestVT,
4403 assert(DestVT != MVT::i1 &&
"ZeroExt/SignExt an i1?");
4409 if (((DestVT != MVT::i8) && (DestVT != MVT::i16) &&
4410 (DestVT != MVT::i32) && (DestVT != MVT::i64)) ||
4411 ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) &&
4412 (SrcVT != MVT::i16) && (SrcVT != MVT::i32)))
4422 return emiti1Ext(SrcReg, DestVT, IsZExt);
4424 if (DestVT == MVT::i64)
4425 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4427 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4431 if (DestVT == MVT::i64)
4432 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4434 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4438 assert(DestVT == MVT::i64 &&
"IntExt i32 to i32?!?");
4439 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4445 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4447 else if (DestVT == MVT::i64) {
4448 Register Src64 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4449 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4450 TII.get(AArch64::SUBREG_TO_REG), Src64)
4452 .
addImm(AArch64::sub_32);
4456 const TargetRegisterClass *RC =
4457 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4458 return fastEmitInst_rii(
Opc, RC, SrcReg, 0, Imm);
4465 case AArch64::LDURBBi:
4466 case AArch64::LDURHHi:
4467 case AArch64::LDURWi:
4468 case AArch64::LDRBBui:
4469 case AArch64::LDRHHui:
4470 case AArch64::LDRWui:
4471 case AArch64::LDRBBroX:
4472 case AArch64::LDRHHroX:
4473 case AArch64::LDRWroX:
4474 case AArch64::LDRBBroW:
4475 case AArch64::LDRHHroW:
4476 case AArch64::LDRWroW:
4485 case AArch64::LDURSBWi:
4486 case AArch64::LDURSHWi:
4487 case AArch64::LDURSBXi:
4488 case AArch64::LDURSHXi:
4489 case AArch64::LDURSWi:
4490 case AArch64::LDRSBWui:
4491 case AArch64::LDRSHWui:
4492 case AArch64::LDRSBXui:
4493 case AArch64::LDRSHXui:
4494 case AArch64::LDRSWui:
4495 case AArch64::LDRSBWroX:
4496 case AArch64::LDRSHWroX:
4497 case AArch64::LDRSBXroX:
4498 case AArch64::LDRSHXroX:
4499 case AArch64::LDRSWroX:
4500 case AArch64::LDRSBWroW:
4501 case AArch64::LDRSHWroW:
4502 case AArch64::LDRSBXroW:
4503 case AArch64::LDRSHXroW:
4504 case AArch64::LDRSWroW:
4509bool AArch64FastISel::optimizeIntExtLoad(
const Instruction *
I, MVT RetVT,
4512 if (!LI || !LI->hasOneUse())
4520 MachineInstr *
MI = MRI.getUniqueVRegDef(
Reg);
4527 const auto *LoadMI =
MI;
4528 if (LoadMI->getOpcode() == TargetOpcode::COPY &&
4529 LoadMI->getOperand(1).getSubReg() == AArch64::sub_32) {
4530 Register LoadReg =
MI->getOperand(1).getReg();
4531 LoadMI = MRI.getUniqueVRegDef(LoadReg);
4532 assert(LoadMI &&
"Expected valid instruction");
4538 if (RetVT != MVT::i64 || SrcVT > MVT::i32) {
4539 updateValueMap(
I,
Reg);
4544 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
4545 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4546 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4548 .
addImm(AArch64::sub_32);
4551 assert((
MI->getOpcode() == TargetOpcode::COPY &&
4552 MI->getOperand(1).getSubReg() == AArch64::sub_32) &&
4553 "Expected copy instruction");
4554 Reg =
MI->getOperand(1).getReg();
4556 removeDeadCode(
I, std::next(
I));
4558 updateValueMap(
I,
Reg);
4562bool AArch64FastISel::selectIntExt(
const Instruction *
I) {
4564 "Unexpected integer extend instruction.");
4567 if (!isTypeSupported(
I->getType(), RetVT))
4570 if (!isTypeSupported(
I->getOperand(0)->getType(), SrcVT))
4574 if (optimizeIntExtLoad(
I, RetVT, SrcVT))
4577 Register SrcReg = getRegForValue(
I->getOperand(0));
4584 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr())) {
4585 if (RetVT == MVT::i64 && SrcVT != MVT::i64) {
4586 Register ResultReg = createResultReg(&AArch64::GPR64RegClass);
4587 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4588 TII.get(AArch64::SUBREG_TO_REG), ResultReg)
4590 .
addImm(AArch64::sub_32);
4594 updateValueMap(
I, SrcReg);
4599 Register ResultReg = emitIntExt(SrcVT, SrcReg, RetVT, IsZExt);
4603 updateValueMap(
I, ResultReg);
4607bool AArch64FastISel::selectRem(
const Instruction *
I,
unsigned ISDOpcode) {
4608 EVT DestEVT = TLI.getValueType(
DL,
I->getType(),
true);
4613 if (DestVT != MVT::i64 && DestVT != MVT::i32)
4617 bool Is64bit = (DestVT == MVT::i64);
4618 switch (ISDOpcode) {
4622 DivOpc = Is64bit ? AArch64::SDIVXr : AArch64::SDIVWr;
4625 DivOpc = Is64bit ? AArch64::UDIVXr : AArch64::UDIVWr;
4628 unsigned MSubOpc = Is64bit ? AArch64::MSUBXrrr : AArch64::MSUBWrrr;
4629 Register Src0Reg = getRegForValue(
I->getOperand(0));
4633 Register Src1Reg = getRegForValue(
I->getOperand(1));
4637 const TargetRegisterClass *RC =
4638 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4639 Register QuotReg = fastEmitInst_rr(DivOpc, RC, Src0Reg, Src1Reg);
4640 assert(QuotReg &&
"Unexpected DIV instruction emission failure.");
4643 Register ResultReg = fastEmitInst_rrr(MSubOpc, RC, QuotReg, Src1Reg, Src0Reg);
4644 updateValueMap(
I, ResultReg);
4648bool AArch64FastISel::selectMul(
const Instruction *
I) {
4650 if (!isTypeSupported(
I->getType(), VT,
true))
4656 const Value *Src0 =
I->getOperand(0);
4657 const Value *Src1 =
I->getOperand(1);
4659 if (
C->getValue().isPowerOf2())
4664 if (
C->getValue().isPowerOf2()) {
4665 uint64_t ShiftVal =
C->getValue().logBase2();
4671 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), VT)) {
4674 Src0 = ZExt->getOperand(0);
4680 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), VT)) {
4683 Src0 = SExt->getOperand(0);
4688 Register Src0Reg = getRegForValue(Src0);
4692 Register ResultReg = emitLSL_ri(VT, SrcVT, Src0Reg, ShiftVal, IsZExt);
4695 updateValueMap(
I, ResultReg);
4700 Register Src0Reg = getRegForValue(
I->getOperand(0));
4704 Register Src1Reg = getRegForValue(
I->getOperand(1));
4708 Register ResultReg = emitMul_rr(VT, Src0Reg, Src1Reg);
4713 updateValueMap(
I, ResultReg);
4717bool AArch64FastISel::selectShift(
const Instruction *
I) {
4719 if (!isTypeSupported(
I->getType(), RetVT,
true))
4723 return selectOperator(
I,
I->getOpcode());
4727 uint64_t ShiftVal =
C->getZExtValue();
4729 bool IsZExt =
I->getOpcode() != Instruction::AShr;
4730 const Value *Op0 =
I->getOperand(0);
4734 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), TmpVT)) {
4737 Op0 = ZExt->getOperand(0);
4743 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), TmpVT)) {
4746 Op0 = SExt->getOperand(0);
4751 Register Op0Reg = getRegForValue(Op0);
4755 switch (
I->getOpcode()) {
4757 case Instruction::Shl:
4758 ResultReg = emitLSL_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4760 case Instruction::AShr:
4761 ResultReg = emitASR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4763 case Instruction::LShr:
4764 ResultReg = emitLSR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4770 updateValueMap(
I, ResultReg);
4774 Register Op0Reg = getRegForValue(
I->getOperand(0));
4778 Register Op1Reg = getRegForValue(
I->getOperand(1));
4783 switch (
I->getOpcode()) {
4785 case Instruction::Shl:
4786 ResultReg = emitLSL_rr(RetVT, Op0Reg, Op1Reg);
4788 case Instruction::AShr:
4789 ResultReg = emitASR_rr(RetVT, Op0Reg, Op1Reg);
4791 case Instruction::LShr:
4792 ResultReg = emitLSR_rr(RetVT, Op0Reg, Op1Reg);
4799 updateValueMap(
I, ResultReg);
4803bool AArch64FastISel::selectBitCast(
const Instruction *
I) {
4806 if (!isTypeLegal(
I->getOperand(0)->getType(), SrcVT))
4808 if (!isTypeLegal(
I->getType(), RetVT))
4812 if (RetVT == MVT::f32 && SrcVT == MVT::i32)
4813 Opc = AArch64::FMOVWSr;
4814 else if (RetVT == MVT::f64 && SrcVT == MVT::i64)
4815 Opc = AArch64::FMOVXDr;
4816 else if (RetVT == MVT::i32 && SrcVT == MVT::f32)
4817 Opc = AArch64::FMOVSWr;
4818 else if (RetVT == MVT::i64 && SrcVT == MVT::f64)
4819 Opc = AArch64::FMOVDXr;
4823 const TargetRegisterClass *RC =
nullptr;
4826 case MVT::i32: RC = &AArch64::GPR32RegClass;
break;
4827 case MVT::i64: RC = &AArch64::GPR64RegClass;
break;
4828 case MVT::f32: RC = &AArch64::FPR32RegClass;
break;
4829 case MVT::f64: RC = &AArch64::FPR64RegClass;
break;
4831 Register Op0Reg = getRegForValue(
I->getOperand(0));
4835 Register ResultReg = fastEmitInst_r(
Opc, RC, Op0Reg);
4839 updateValueMap(
I, ResultReg);
4843bool AArch64FastISel::selectFRem(
const Instruction *
I) {
4845 if (!isTypeLegal(
I->getType(), RetVT))
4848 RTLIB::LibcallImpl LCImpl =
4850 if (LCImpl == RTLIB::Unsupported)
4854 Args.reserve(
I->getNumOperands());
4857 for (
auto &Arg :
I->operands())
4858 Args.emplace_back(Arg);
4860 CallLoweringInfo CLI;
4861 MCContext &Ctx = MF->getContext();
4862 CallingConv::ID CC = LibcallLowering->getLibcallImplCallingConv(LCImpl);
4865 CLI.setCallee(
DL, Ctx, CC,
I->getType(), FuncName, std::move(Args));
4866 if (!lowerCallTo(CLI))
4868 updateValueMap(
I, CLI.ResultReg);
4872bool AArch64FastISel::selectSDiv(
const Instruction *
I) {
4874 if (!isTypeLegal(
I->getType(), VT))
4881 if ((VT != MVT::i32 && VT != MVT::i64) || !
C ||
4882 !(
C.isPowerOf2() ||
C.isNegatedPowerOf2()))
4885 unsigned Lg2 =
C.countr_zero();
4886 Register Src0Reg = getRegForValue(
I->getOperand(0));
4891 Register ResultReg = emitASR_ri(VT, VT, Src0Reg, Lg2);
4894 updateValueMap(
I, ResultReg);
4898 int64_t Pow2MinusOne = (1ULL << Lg2) - 1;
4899 Register AddReg = emitAdd_ri_(VT, Src0Reg, Pow2MinusOne);
4904 if (!emitICmp_ri(VT, Src0Reg, 0))
4908 const TargetRegisterClass *RC;
4909 if (VT == MVT::i64) {
4910 SelectOpc = AArch64::CSELXr;
4911 RC = &AArch64::GPR64RegClass;
4913 SelectOpc = AArch64::CSELWr;
4914 RC = &AArch64::GPR32RegClass;
4916 Register SelectReg = fastEmitInst_rri(SelectOpc, RC, AddReg, Src0Reg,
4923 Register ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
4926 ResultReg = emitAddSub_rs(
false, VT, ZeroReg, SelectReg,
4929 ResultReg = emitASR_ri(VT, VT, SelectReg, Lg2);
4934 updateValueMap(
I, ResultReg);
4941Register AArch64FastISel::getRegForGEPIndex(
const Value *Idx) {
4942 Register IdxN = getRegForValue(Idx);
4948 MVT PtrVT = TLI.getPointerTy(
DL);
4950 if (IdxVT.
bitsLT(PtrVT)) {
4951 IdxN = emitIntExt(IdxVT.
getSimpleVT(), IdxN, PtrVT,
false);
4952 }
else if (IdxVT.
bitsGT(PtrVT))
4953 llvm_unreachable(
"AArch64 FastISel doesn't support types larger than i64");
4961bool AArch64FastISel::selectGetElementPtr(
const Instruction *
I) {
4965 Register N = getRegForValue(
I->getOperand(0));
4971 uint64_t TotalOffs = 0;
4972 MVT VT = TLI.getPointerTy(
DL);
4975 const Value *Idx = GTI.getOperand();
4976 if (
auto *StTy = GTI.getStructTypeOrNull()) {
4980 TotalOffs +=
DL.getStructLayout(StTy)->getElementOffset(
Field);
4987 TotalOffs += GTI.getSequentialElementStride(
DL) *
4992 N = emitAdd_ri_(VT,
N, TotalOffs);
4999 uint64_t ElementSize = GTI.getSequentialElementStride(
DL);
5000 Register IdxN = getRegForGEPIndex(Idx);
5004 if (ElementSize != 1) {
5008 IdxN = emitMul_rr(VT, IdxN,
C);
5018 N = emitAdd_ri_(VT,
N, TotalOffs);
5022 updateValueMap(
I,
N);
5026bool AArch64FastISel::selectAtomicCmpXchg(
const AtomicCmpXchgInst *
I) {
5027 assert(TM.getOptLevel() == CodeGenOptLevel::None &&
5028 "cmpxchg survived AtomicExpand at optlevel > -O0");
5031 Type *RetTy = RetPairTy->getTypeAtIndex(0U);
5032 assert(RetPairTy->getTypeAtIndex(1U)->isIntegerTy(1) &&
5033 "cmpxchg has a non-i1 status result");
5036 if (!isTypeLegal(RetTy, VT))
5039 const TargetRegisterClass *ResRC;
5040 unsigned Opc, CmpOpc;
5043 if (VT == MVT::i32) {
5044 Opc = AArch64::CMP_SWAP_32;
5045 CmpOpc = AArch64::SUBSWrs;
5046 ResRC = &AArch64::GPR32RegClass;
5047 }
else if (VT == MVT::i64) {
5048 Opc = AArch64::CMP_SWAP_64;
5049 CmpOpc = AArch64::SUBSXrs;
5050 ResRC = &AArch64::GPR64RegClass;
5055 const MCInstrDesc &
II =
TII.get(
Opc);
5057 Register AddrReg = getRegForValue(
I->getPointerOperand());
5058 Register DesiredReg = getRegForValue(
I->getCompareOperand());
5059 Register NewReg = getRegForValue(
I->getNewValOperand());
5061 if (!AddrReg || !DesiredReg || !NewReg)
5068 const Register ResultReg1 = createResultReg(ResRC);
5069 const Register ResultReg2 = createResultReg(&AArch64::GPR32RegClass);
5070 const Register ScratchReg = createResultReg(&AArch64::GPR32RegClass);
5073 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
5080 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CmpOpc))
5081 .
addDef(VT == MVT::i32 ? AArch64::WZR : AArch64::XZR)
5086 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr))
5092 assert((ResultReg1 + 1) == ResultReg2 &&
"Nonconsecutive result registers.");
5093 updateValueMap(
I, ResultReg1, 2);
5097bool AArch64FastISel::fastSelectInstruction(
const Instruction *
I) {
5098 if (TLI.fallBackToDAGISel(*
I))
5100 switch (
I->getOpcode()) {
5103 case Instruction::Add:
5104 case Instruction::Sub:
5105 return selectAddSub(
I);
5106 case Instruction::Mul:
5107 return selectMul(
I);
5108 case Instruction::SDiv:
5109 return selectSDiv(
I);
5110 case Instruction::SRem:
5114 case Instruction::URem:
5118 case Instruction::Shl:
5119 case Instruction::LShr:
5120 case Instruction::AShr:
5121 return selectShift(
I);
5122 case Instruction::And:
5123 case Instruction::Or:
5124 case Instruction::Xor:
5125 return selectLogicalOp(
I);
5126 case Instruction::CondBr:
5127 return selectBranch(
I);
5128 case Instruction::IndirectBr:
5129 return selectIndirectBr(
I);
5130 case Instruction::BitCast:
5132 return selectBitCast(
I);
5134 case Instruction::FPToSI:
5136 return selectFPToInt(
I,
true);
5138 case Instruction::FPToUI:
5139 return selectFPToInt(
I,
false);
5140 case Instruction::ZExt:
5141 case Instruction::SExt:
5142 return selectIntExt(
I);
5143 case Instruction::Trunc:
5145 return selectTrunc(
I);
5147 case Instruction::FPExt:
5148 return selectFPExt(
I);
5149 case Instruction::FPTrunc:
5150 return selectFPTrunc(
I);
5151 case Instruction::SIToFP:
5153 return selectIntToFP(
I,
true);
5155 case Instruction::UIToFP:
5156 return selectIntToFP(
I,
false);
5157 case Instruction::Load:
5158 return selectLoad(
I);
5159 case Instruction::Store:
5160 return selectStore(
I);
5161 case Instruction::FCmp:
5162 case Instruction::ICmp:
5163 return selectCmp(
I);
5164 case Instruction::Select:
5165 return selectSelect(
I);
5166 case Instruction::Ret:
5167 return selectRet(
I);
5168 case Instruction::FRem:
5169 return selectFRem(
I);
5170 case Instruction::GetElementPtr:
5171 return selectGetElementPtr(
I);
5172 case Instruction::AtomicCmpXchg:
5177 return selectOperator(
I,
I->getOpcode());
5191 return new AArch64FastISel(FuncInfo, LibInfo, LibcallLowering);
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
Register getLocReg() const
LocInfo getLocInfo() const
unsigned getValNo() const
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Value * getCondition() const
BasicBlock * getSuccessor(unsigned i) const
const APFloat & getValueAPF() const
bool isNegative() const
Return true if the sign bit is set.
bool isZero() const
Return true if the value is positive or negative zero.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
LLVM_ABI bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
constexpr bool isVector() const
One or more elements.
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
bool selectBitCast(const User *I)
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
PointerType * getType() const
Global values are always pointers.
iterator_range< succ_iterator > successors()
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
Tracks which library functions to use for a particular subtarget.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
bool isVector() const
Return true if this is a vector value type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
bool isValid() const
Return true if this is a valid simple valuetype.
static MVT getIntegerVT(unsigned BitWidth)
bool is64BitVector() const
Return true if this is a 64-bit vector type.
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
void setFrameAddressIsTaken(bool T)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
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.
#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.