57#include "llvm/IR/IntrinsicsAArch64.h"
81class AArch64FastISel final :
public FastISel {
84 enum BaseKind { RegBase, FrameIndexBase };
87 BaseKind Kind = RegBase;
96 const GlobalValue *GV =
nullptr;
101 void setKind(BaseKind K) { Kind =
K; }
102 BaseKind getKind()
const {
return Kind; }
105 bool isRegBase()
const {
return Kind == RegBase; }
106 bool isFIBase()
const {
return Kind == FrameIndexBase; }
109 assert(isRegBase() &&
"Invalid base register access!");
114 assert(isRegBase() &&
"Invalid base register access!");
120 Register getOffsetReg()
const {
return OffsetReg; }
122 void setFI(
unsigned FI) {
123 assert(isFIBase() &&
"Invalid base frame index access!");
127 unsigned getFI()
const {
128 assert(isFIBase() &&
"Invalid base frame index access!");
132 void setOffset(int64_t O) { Offset =
O; }
134 void setShift(
unsigned S) { Shift = S; }
135 unsigned getShift() {
return Shift; }
137 void setGlobalValue(
const GlobalValue *
G) { GV =
G; }
138 const GlobalValue *getGlobalValue() {
return GV; }
143 const AArch64Subtarget *Subtarget;
144 LLVMContext *Context;
146 bool fastLowerArguments()
override;
147 bool fastLowerCall(CallLoweringInfo &CLI)
override;
148 bool fastLowerIntrinsicCall(
const IntrinsicInst *
II)
override;
152 bool selectAddSub(
const Instruction *
I);
153 bool selectLogicalOp(
const Instruction *
I);
154 bool selectLoad(
const Instruction *
I);
155 bool selectStore(
const Instruction *
I);
156 bool selectBranch(
const Instruction *
I);
157 bool selectIndirectBr(
const Instruction *
I);
158 bool selectCmp(
const Instruction *
I);
159 bool selectSelect(
const Instruction *
I);
160 bool selectFPExt(
const Instruction *
I);
161 bool selectFPTrunc(
const Instruction *
I);
162 bool selectFPToInt(
const Instruction *
I,
bool Signed);
163 bool selectIntToFP(
const Instruction *
I,
bool Signed);
164 bool selectRem(
const Instruction *
I,
unsigned ISDOpcode);
165 bool selectRet(
const Instruction *
I);
166 bool selectTrunc(
const Instruction *
I);
167 bool selectIntExt(
const Instruction *
I);
168 bool selectMul(
const Instruction *
I);
169 bool selectShift(
const Instruction *
I);
170 bool selectBitCast(
const Instruction *
I);
171 bool selectFRem(
const Instruction *
I);
172 bool selectSDiv(
const Instruction *
I);
173 bool selectGetElementPtr(
const Instruction *
I);
174 bool selectAtomicCmpXchg(
const AtomicCmpXchgInst *
I);
177 bool isTypeLegal(
Type *Ty, MVT &VT);
178 bool isTypeSupported(
Type *Ty, MVT &VT,
bool IsVectorAllowed =
false);
179 bool isValueAvailable(
const Value *V)
const;
180 bool computeAddress(
const Value *Obj, Address &Addr,
Type *Ty =
nullptr);
181 bool computeCallAddress(
const Value *V, Address &Addr);
182 bool simplifyAddress(Address &Addr, MVT VT);
183 void addLoadStoreOperands(Address &Addr,
const MachineInstrBuilder &MIB,
185 unsigned ScaleFactor, MachineMemOperand *MMO);
186 bool isMemCpySmall(
uint64_t Len, MaybeAlign Alignment);
187 bool tryEmitSmallMemCpy(Address Dest, Address Src,
uint64_t Len,
188 MaybeAlign Alignment);
191 bool optimizeIntExtLoad(
const Instruction *
I, MVT RetVT, MVT SrcVT);
192 bool optimizeSelect(
const SelectInst *SI);
197 const Value *
RHS,
bool SetFlags =
false,
198 bool WantResult =
true,
bool IsZExt =
false);
200 Register RHSReg,
bool SetFlags =
false,
201 bool WantResult =
true);
203 bool SetFlags =
false,
bool WantResult =
true);
206 uint64_t ShiftImm,
bool SetFlags =
false,
207 bool WantResult =
true);
210 uint64_t ShiftImm,
bool SetFlags =
false,
211 bool WantResult =
true);
214 bool emitCompareAndBranch(
const CondBrInst *BI);
220 MachineMemOperand *MMO =
nullptr);
222 MachineMemOperand *MMO =
nullptr);
224 MachineMemOperand *MMO =
nullptr);
228 bool SetFlags =
false,
bool WantResult =
true,
229 bool IsZExt =
false);
232 bool SetFlags =
false,
bool WantResult =
true,
233 bool IsZExt =
false);
235 bool WantResult =
true);
238 bool WantResult =
true);
257 bool IsZExt =
false);
259 Register materializeInt(
const ConstantInt *CI, MVT VT);
260 Register materializeFP(
const ConstantFP *CFP, MVT VT);
261 Register materializeGV(
const GlobalValue *GV);
265 CCAssignFn *CCAssignFnForCall(CallingConv::ID CC)
const;
266 bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs,
267 SmallVectorImpl<Type *> &OrigTys,
unsigned &NumBytes);
268 bool finishCall(CallLoweringInfo &CLI,
unsigned NumBytes);
272 Register fastMaterializeAlloca(
const AllocaInst *AI)
override;
273 Register fastMaterializeConstant(
const Constant *
C)
override;
274 Register fastMaterializeFloatZero(
const ConstantFP *CF)
override;
276 explicit AArch64FastISel(FunctionLoweringInfo &FuncInfo,
277 const TargetLibraryInfo *LibInfo,
278 const LibcallLoweringInfo *libcallLowering)
279 : FastISel(FuncInfo, LibInfo, libcallLowering,
285 bool fastSelectInstruction(
const Instruction *
I)
override;
287#include "AArch64GenFastISel.inc"
295 "Unexpected integer extend instruction.");
296 assert(!
I->getType()->isVectorTy() &&
I->getType()->isIntegerTy() &&
297 "Unexpected value type.");
305 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr()))
332 if (CC == CallingConv::GHC)
334 if (CC == CallingConv::CFGuard_Check)
343Register AArch64FastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
345 "Alloca should always return a pointer.");
348 auto SI = FuncInfo.StaticAllocaMap.find(AI);
349 if (SI == FuncInfo.StaticAllocaMap.end())
352 if (SI != FuncInfo.StaticAllocaMap.end()) {
353 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
354 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
365Register AArch64FastISel::materializeInt(
const ConstantInt *CI, MVT VT) {
374 : &AArch64::GPR32RegClass;
375 unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
376 Register ResultReg = createResultReg(RC);
377 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
382Register AArch64FastISel::materializeFP(
const ConstantFP *CFP, MVT VT) {
386 return fastMaterializeFloatZero(CFP);
388 if (VT != MVT::f32 && VT != MVT::f64)
392 bool Is64Bit = (VT == MVT::f64);
398 unsigned Opc = Is64Bit ? AArch64::FMOVDi : AArch64::FMOVSi;
399 return fastEmitInst_i(
Opc, TLI.getRegClassFor(VT),
Imm);
404 unsigned Opc1 = Is64Bit ? AArch64::MOVi64imm : AArch64::MOVi32imm;
405 const TargetRegisterClass *RC = Is64Bit ?
406 &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
408 Register TmpReg = createResultReg(RC);
409 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc1), TmpReg)
410 .addImm(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
412 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
413 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
414 TII.get(TargetOpcode::COPY), ResultReg)
415 .addReg(TmpReg, getKillRegState(true));
422 Align Alignment =
DL.getPrefTypeAlign(CFP->
getType());
424 unsigned CPI = MCP.getConstantPoolIndex(
cast<Constant>(CFP), Alignment);
425 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
426 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
429 unsigned Opc = Is64Bit ? AArch64::LDRDui : AArch64::LDRSui;
430 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
431 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
437Register AArch64FastISel::materializeGV(
const GlobalValue *GV) {
447 if (FuncInfo.MF->getInfo<AArch64FunctionInfo>()->hasELFSignedGOT())
452 EVT DestEVT = TLI.getValueType(
DL, GV->
getType(),
true);
456 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
461 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
467 ResultReg = createResultReg(&AArch64::GPR32RegClass);
468 LdrOpc = AArch64::LDRWui;
470 ResultReg = createResultReg(&AArch64::GPR64RegClass);
471 LdrOpc = AArch64::LDRXui;
473 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(LdrOpc),
483 Register Result64 = createResultReg(&AArch64::GPR64RegClass);
484 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
485 TII.get(TargetOpcode::SUBREG_TO_REG))
487 .
addReg(ResultReg, RegState::Kill)
492 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
510 Register DstReg = createResultReg(&AArch64::GPR64commonRegClass);
511 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::MOVKXi),
520 ResultReg = createResultReg(&AArch64::GPR64spRegClass);
521 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
531Register AArch64FastISel::fastMaterializeConstant(
const Constant *
C) {
532 EVT CEVT = TLI.getValueType(
DL,
C->getType(),
true);
541 if (
C->getType()->isVectorTy())
543 assert(VT == MVT::i64 &&
"Expected 64-bit pointers");
544 return materializeInt(ConstantInt::get(Type::getInt64Ty(*
Context), 0), VT);
548 return materializeInt(CI, VT);
550 return materializeFP(CFP, VT);
552 return materializeGV(GV);
557Register AArch64FastISel::fastMaterializeFloatZero(
const ConstantFP *CFP) {
559 "Floating-point constant is not a positive zero.");
561 if (!isTypeLegal(CFP->
getType(), VT))
564 if (VT != MVT::f32 && VT != MVT::f64)
567 bool Is64Bit = (VT == MVT::f64);
568 unsigned ZReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
569 unsigned Opc = Is64Bit ? AArch64::FMOVXDr : AArch64::FMOVWSr;
570 return fastEmitInst_r(
Opc, TLI.getRegClassFor(VT), ZReg);
577 if (
C->getValue().isPowerOf2())
580 if (
C->getValue().isPowerOf2())
587bool AArch64FastISel::computeAddress(
const Value *Obj,
Address &Addr,
Type *Ty)
589 const User *
U =
nullptr;
590 unsigned Opcode = Instruction::UserOp1;
594 if (FuncInfo.StaticAllocaMap.count(
static_cast<const AllocaInst *
>(Obj)) ||
595 FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
596 Opcode =
I->getOpcode();
600 Opcode =
C->getOpcode();
605 if (Ty->getAddressSpace() > 255)
613 case Instruction::BitCast:
615 return computeAddress(
U->getOperand(0), Addr, Ty);
617 case Instruction::IntToPtr:
619 if (TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
620 TLI.getPointerTy(
DL))
621 return computeAddress(
U->getOperand(0), Addr, Ty);
624 case Instruction::PtrToInt:
626 if (TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
627 return computeAddress(
U->getOperand(0), Addr, Ty);
630 case Instruction::GetElementPtr: {
632 uint64_t TmpOffset = Addr.getOffset();
638 const Value *
Op = GTI.getOperand();
639 if (StructType *STy = GTI.getStructTypeOrNull()) {
640 const StructLayout *SL =
DL.getStructLayout(STy);
644 uint64_t S = GTI.getSequentialElementStride(
DL);
651 if (canFoldAddIntoGEP(U,
Op)) {
661 goto unsupported_gep;
667 Addr.setOffset(TmpOffset);
668 if (computeAddress(
U->getOperand(0), Addr, Ty))
677 case Instruction::Alloca: {
679 auto SI = FuncInfo.StaticAllocaMap.find(AI);
680 if (SI != FuncInfo.StaticAllocaMap.end()) {
681 Addr.setKind(Address::FrameIndexBase);
682 Addr.setFI(
SI->second);
687 case Instruction::Add: {
697 return computeAddress(
LHS, Addr, Ty);
701 if (computeAddress(
LHS, Addr, Ty) && computeAddress(
RHS, Addr, Ty))
707 case Instruction::Sub: {
714 return computeAddress(
LHS, Addr, Ty);
718 case Instruction::Shl: {
719 if (Addr.getOffsetReg())
727 if (Val < 1 || Val > 3)
733 NumBytes = NumBits / 8;
738 if (NumBytes != (1ULL << Val))
744 const Value *Src =
U->getOperand(0);
746 if (FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
750 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
752 Src = ZE->getOperand(0);
756 SE->getOperand(0)->getType()->isIntegerTy(32)) {
758 Src = SE->getOperand(0);
765 if (AI->
getOpcode() == Instruction::And) {
770 if (
C->getValue() == 0xffffffff)
774 if (
C->getValue() == 0xffffffff) {
779 Reg = fastEmitInst_extractsubreg(MVT::i32,
Reg, AArch64::sub_32);
780 Addr.setOffsetReg(
Reg);
788 Addr.setOffsetReg(
Reg);
791 case Instruction::Mul: {
792 if (Addr.getOffsetReg())
803 if (
C->getValue().isPowerOf2())
808 unsigned Val =
C->getValue().logBase2();
809 if (Val < 1 || Val > 3)
815 NumBytes = NumBits / 8;
820 if (NumBytes != (1ULL << Val))
828 if (FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
832 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
834 Src = ZE->getOperand(0);
838 SE->getOperand(0)->getType()->isIntegerTy(32)) {
840 Src = SE->getOperand(0);
849 Addr.setOffsetReg(
Reg);
852 case Instruction::And: {
853 if (Addr.getOffsetReg())
856 if (!Ty ||
DL.getTypeSizeInBits(Ty) != 8)
863 if (
C->getValue() == 0xffffffff)
867 if (
C->getValue() == 0xffffffff) {
875 Reg = fastEmitInst_extractsubreg(MVT::i32,
Reg, AArch64::sub_32);
876 Addr.setOffsetReg(
Reg);
881 case Instruction::SExt:
882 case Instruction::ZExt: {
883 if (!Addr.getReg() || Addr.getOffsetReg())
886 const Value *Src =
nullptr;
889 if (!
isIntExtFree(ZE) && ZE->getOperand(0)->getType()->isIntegerTy(32)) {
891 Src = ZE->getOperand(0);
894 if (!
isIntExtFree(SE) && SE->getOperand(0)->getType()->isIntegerTy(32)) {
896 Src = SE->getOperand(0);
907 Addr.setOffsetReg(
Reg);
912 if (Addr.isRegBase() && !Addr.getReg()) {
920 if (!Addr.getOffsetReg()) {
924 Addr.setOffsetReg(
Reg);
931bool AArch64FastISel::computeCallAddress(
const Value *V,
Address &Addr) {
932 const User *
U =
nullptr;
933 unsigned Opcode = Instruction::UserOp1;
937 Opcode =
I->getOpcode();
939 InMBB =
I->getParent() == FuncInfo.MBB->getBasicBlock();
941 Opcode =
C->getOpcode();
947 case Instruction::BitCast:
950 return computeCallAddress(
U->getOperand(0), Addr);
952 case Instruction::IntToPtr:
955 TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
956 TLI.getPointerTy(
DL))
957 return computeCallAddress(
U->getOperand(0), Addr);
959 case Instruction::PtrToInt:
961 if (InMBB && TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
962 return computeCallAddress(
U->getOperand(0), Addr);
967 Addr.setGlobalValue(GV);
972 if (!Addr.getGlobalValue()) {
973 Addr.setReg(getRegForValue(V));
974 return Addr.getReg().isValid();
980bool AArch64FastISel::isTypeLegal(
Type *Ty, MVT &VT) {
981 EVT evt = TLI.getValueType(
DL, Ty,
true);
987 if (evt == MVT::Other || !evt.
isSimple())
997 return TLI.isTypeLegal(VT);
1004bool AArch64FastISel::isTypeSupported(
Type *Ty, MVT &VT,
bool IsVectorAllowed) {
1008 if (isTypeLegal(Ty, VT))
1013 if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)
1019bool AArch64FastISel::isValueAvailable(
const Value *V)
const {
1024 return FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB;
1027bool AArch64FastISel::simplifyAddress(
Address &Addr, MVT VT) {
1035 bool ImmediateOffsetNeedsLowering =
false;
1036 bool RegisterOffsetNeedsLowering =
false;
1037 int64_t
Offset = Addr.getOffset();
1039 ImmediateOffsetNeedsLowering =
true;
1040 else if (
Offset > 0 && !(
Offset & (ScaleFactor - 1)) &&
1042 ImmediateOffsetNeedsLowering =
true;
1047 if (!ImmediateOffsetNeedsLowering && Addr.getOffset() && Addr.getOffsetReg())
1048 RegisterOffsetNeedsLowering =
true;
1051 if (Addr.isRegBase() && Addr.getOffsetReg() && !Addr.getReg())
1052 RegisterOffsetNeedsLowering =
true;
1057 if ((ImmediateOffsetNeedsLowering || Addr.getOffsetReg()) && Addr.isFIBase())
1059 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
1060 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
1065 Addr.setKind(Address::RegBase);
1066 Addr.setReg(ResultReg);
1069 if (RegisterOffsetNeedsLowering) {
1071 if (Addr.getReg()) {
1074 ResultReg = emitAddSub_rx(
true, MVT::i64, Addr.getReg(),
1075 Addr.getOffsetReg(), Addr.getExtendType(),
1078 ResultReg = emitAddSub_rs(
true, MVT::i64, Addr.getReg(),
1083 ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1084 Addr.getShift(),
true);
1086 ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1087 Addr.getShift(),
false);
1089 ResultReg = emitLSL_ri(MVT::i64, MVT::i64, Addr.getOffsetReg(),
1095 Addr.setReg(ResultReg);
1096 Addr.setOffsetReg(0);
1103 if (ImmediateOffsetNeedsLowering) {
1107 ResultReg = emitAdd_ri_(MVT::i64, Addr.getReg(),
Offset);
1113 Addr.setReg(ResultReg);
1119void AArch64FastISel::addLoadStoreOperands(
Address &Addr,
1120 const MachineInstrBuilder &MIB,
1122 unsigned ScaleFactor,
1123 MachineMemOperand *MMO) {
1124 int64_t
Offset = Addr.getOffset() / ScaleFactor;
1126 if (Addr.isFIBase()) {
1127 int FI = Addr.getFI();
1130 MMO = FuncInfo.MF->getMachineMemOperand(
1132 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
1136 assert(Addr.isRegBase() &&
"Unexpected address kind.");
1143 if (Addr.getOffsetReg()) {
1144 assert(Addr.getOffset() == 0 &&
"Unexpected offset");
1147 MIB.
addReg(Addr.getReg());
1148 MIB.
addReg(Addr.getOffsetReg());
1150 MIB.
addImm(Addr.getShift() != 0);
1159Register AArch64FastISel::emitAddSub(
bool UseAdd, MVT RetVT,
const Value *
LHS,
1161 bool WantResult,
bool IsZExt) {
1163 bool NeedExtend =
false;
1198 if (
SI->getOpcode() == Instruction::Shl ||
1199 SI->getOpcode() == Instruction::LShr ||
1200 SI->getOpcode() == Instruction::AShr )
1208 LHSReg = emitIntExt(SrcVT, LHSReg, RetVT, IsZExt);
1212 uint64_t Imm = IsZExt ?
C->getZExtValue() :
C->getSExtValue();
1213 if (
C->isNegative())
1214 ResultReg = emitAddSub_ri(!UseAdd, RetVT, LHSReg, -
Imm, SetFlags,
1217 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg,
Imm, SetFlags,
1220 if (
C->isNullValue())
1221 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, 0, SetFlags, WantResult);
1228 isValueAvailable(
RHS)) {
1232 return emitAddSub_rx(UseAdd, RetVT, LHSReg, RHSReg, ExtendType, 0,
1233 SetFlags, WantResult);
1243 if (
C->getValue().isPowerOf2())
1248 Register RHSReg = getRegForValue(MulLHS);
1251 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg,
AArch64_AM::LSL,
1252 ShiftVal, SetFlags, WantResult);
1263 switch (
SI->getOpcode()) {
1271 Register RHSReg = getRegForValue(
SI->getOperand(0));
1274 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg, ShiftType,
1275 ShiftVal, SetFlags, WantResult);
1288 RHSReg = emitIntExt(SrcVT, RHSReg, RetVT, IsZExt);
1290 return emitAddSub_rr(UseAdd, RetVT, LHSReg, RHSReg, SetFlags, WantResult);
1293Register AArch64FastISel::emitAddSub_rr(
bool UseAdd, MVT RetVT,
Register LHSReg,
1296 assert(LHSReg && RHSReg &&
"Invalid register number.");
1298 if (LHSReg == AArch64::SP || LHSReg == AArch64::WSP ||
1299 RHSReg == AArch64::SP || RHSReg == AArch64::WSP)
1302 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1305 static const unsigned OpcTable[2][2][2] = {
1306 { { AArch64::SUBWrr, AArch64::SUBXrr },
1307 { AArch64::ADDWrr, AArch64::ADDXrr } },
1308 { { AArch64::SUBSWrr, AArch64::SUBSXrr },
1309 { AArch64::ADDSWrr, AArch64::ADDSXrr } }
1311 bool Is64Bit = RetVT == MVT::i64;
1312 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1314 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1317 ResultReg = createResultReg(RC);
1319 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1321 const MCInstrDesc &
II =
TII.get(
Opc);
1324 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1330Register AArch64FastISel::emitAddSub_ri(
bool UseAdd, MVT RetVT,
Register LHSReg,
1333 assert(LHSReg &&
"Invalid register number.");
1335 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1341 else if ((
Imm & 0xfff000) ==
Imm) {
1347 static const unsigned OpcTable[2][2][2] = {
1348 { { AArch64::SUBWri, AArch64::SUBXri },
1349 { AArch64::ADDWri, AArch64::ADDXri } },
1350 { { AArch64::SUBSWri, AArch64::SUBSXri },
1351 { AArch64::ADDSWri, AArch64::ADDSXri } }
1353 bool Is64Bit = RetVT == MVT::i64;
1354 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1357 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1359 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1362 ResultReg = createResultReg(RC);
1364 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1366 const MCInstrDesc &
II =
TII.get(
Opc);
1368 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1375Register AArch64FastISel::emitAddSub_rs(
bool UseAdd, MVT RetVT,
Register LHSReg,
1380 assert(LHSReg && RHSReg &&
"Invalid register number.");
1381 assert(LHSReg != AArch64::SP && LHSReg != AArch64::WSP &&
1382 RHSReg != AArch64::SP && RHSReg != AArch64::WSP);
1384 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1391 static const unsigned OpcTable[2][2][2] = {
1392 { { AArch64::SUBWrs, AArch64::SUBXrs },
1393 { AArch64::ADDWrs, AArch64::ADDXrs } },
1394 { { AArch64::SUBSWrs, AArch64::SUBSXrs },
1395 { AArch64::ADDSWrs, AArch64::ADDSXrs } }
1397 bool Is64Bit = RetVT == MVT::i64;
1398 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1400 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1403 ResultReg = createResultReg(RC);
1405 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1407 const MCInstrDesc &
II =
TII.get(
Opc);
1410 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1413 .
addImm(getShifterImm(ShiftType, ShiftImm));
1417Register AArch64FastISel::emitAddSub_rx(
bool UseAdd, MVT RetVT,
Register LHSReg,
1422 assert(LHSReg && RHSReg &&
"Invalid register number.");
1423 assert(LHSReg != AArch64::XZR && LHSReg != AArch64::WZR &&
1424 RHSReg != AArch64::XZR && RHSReg != AArch64::WZR);
1426 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1432 static const unsigned OpcTable[2][2][2] = {
1433 { { AArch64::SUBWrx, AArch64::SUBXrx },
1434 { AArch64::ADDWrx, AArch64::ADDXrx } },
1435 { { AArch64::SUBSWrx, AArch64::SUBSXrx },
1436 { AArch64::ADDSWrx, AArch64::ADDSXrx } }
1438 bool Is64Bit = RetVT == MVT::i64;
1439 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1442 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1444 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1447 ResultReg = createResultReg(RC);
1449 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1451 const MCInstrDesc &
II =
TII.get(
Opc);
1454 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
1457 .
addImm(getArithExtendImm(ExtType, ShiftImm));
1461bool AArch64FastISel::emitCmp(
const Value *
LHS,
const Value *
RHS,
bool IsZExt) {
1463 EVT EVT = TLI.getValueType(
DL, Ty,
true);
1476 return emitICmp(VT,
LHS,
RHS, IsZExt);
1479 return emitFCmp(VT,
LHS,
RHS);
1483bool AArch64FastISel::emitICmp(MVT RetVT,
const Value *
LHS,
const Value *
RHS,
1485 return emitSub(RetVT,
LHS,
RHS,
true,
false,
1491 return emitAddSub_ri(
false, RetVT, LHSReg,
Imm,
1496bool AArch64FastISel::emitFCmp(MVT RetVT,
const Value *
LHS,
const Value *
RHS) {
1497 if (RetVT != MVT::f32 && RetVT != MVT::f64)
1502 bool UseImm =
false;
1512 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDri : AArch64::FCMPSri;
1513 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1522 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDrr : AArch64::FCMPSrr;
1523 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1530 bool SetFlags,
bool WantResult,
bool IsZExt) {
1531 return emitAddSub(
true, RetVT,
LHS,
RHS, SetFlags, WantResult,
1543 ResultReg = emitAddSub_ri(
false, VT, Op0, -
Imm);
1545 ResultReg = emitAddSub_ri(
true, VT, Op0,
Imm);
1554 ResultReg = emitAddSub_rr(
true, VT, Op0, CReg);
1559 bool SetFlags,
bool WantResult,
bool IsZExt) {
1560 return emitAddSub(
false, RetVT,
LHS,
RHS, SetFlags, WantResult,
1565 Register RHSReg,
bool WantResult) {
1566 return emitAddSub_rr(
false, RetVT, LHSReg, RHSReg,
1573 uint64_t ShiftImm,
bool WantResult) {
1574 return emitAddSub_rs(
false, RetVT, LHSReg, RHSReg, ShiftType,
1575 ShiftImm,
true, WantResult);
1578Register AArch64FastISel::emitLogicalOp(
unsigned ISDOpc, MVT RetVT,
1602 ResultReg = emitLogicalOp_ri(ISDOpc, RetVT, LHSReg,
Imm);
1614 if (
C->getValue().isPowerOf2())
1620 Register RHSReg = getRegForValue(MulLHS);
1623 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);
1634 Register RHSReg = getRegForValue(
SI->getOperand(0));
1637 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);
1647 MVT VT = std::max(MVT::i32, RetVT.
SimpleTy);
1648 ResultReg = fastEmit_rr(VT, VT, ISDOpc, LHSReg, RHSReg);
1649 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1651 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1656Register AArch64FastISel::emitLogicalOp_ri(
unsigned ISDOpc, MVT RetVT,
1659 "ISD nodes are not consecutive!");
1660 static const unsigned OpcTable[3][2] = {
1661 { AArch64::ANDWri, AArch64::ANDXri },
1662 { AArch64::ORRWri, AArch64::ORRXri },
1663 { AArch64::EORWri, AArch64::EORXri }
1676 Opc = OpcTable[Idx][0];
1677 RC = &AArch64::GPR32spRegClass;
1683 RC = &AArch64::GPR64spRegClass;
1692 fastEmitInst_ri(
Opc, RC, LHSReg,
1694 if (RetVT >= MVT::i8 && RetVT <= MVT::i16 && ISDOpc !=
ISD::AND) {
1696 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1701Register AArch64FastISel::emitLogicalOp_rs(
unsigned ISDOpc, MVT RetVT,
1705 "ISD nodes are not consecutive!");
1706 static const unsigned OpcTable[3][2] = {
1707 { AArch64::ANDWrs, AArch64::ANDXrs },
1708 { AArch64::ORRWrs, AArch64::ORRXrs },
1709 { AArch64::EORWrs, AArch64::EORXrs }
1726 RC = &AArch64::GPR32RegClass;
1730 RC = &AArch64::GPR64RegClass;
1734 fastEmitInst_rri(
Opc, RC, LHSReg, RHSReg,
1736 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1738 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1744 return emitLogicalOp_ri(
ISD::AND, RetVT, LHSReg,
Imm);
1748 bool WantZExt, MachineMemOperand *MMO) {
1749 if (!TLI.allowsMisalignedMemoryAccesses(VT))
1753 if (!simplifyAddress(Addr, VT))
1762 bool UseScaled =
true;
1763 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
1768 static const unsigned GPOpcTable[2][8][4] = {
1770 { { AArch64::LDURSBWi, AArch64::LDURSHWi, AArch64::LDURWi,
1772 { AArch64::LDURSBXi, AArch64::LDURSHXi, AArch64::LDURSWi,
1774 { AArch64::LDRSBWui, AArch64::LDRSHWui, AArch64::LDRWui,
1776 { AArch64::LDRSBXui, AArch64::LDRSHXui, AArch64::LDRSWui,
1778 { AArch64::LDRSBWroX, AArch64::LDRSHWroX, AArch64::LDRWroX,
1780 { AArch64::LDRSBXroX, AArch64::LDRSHXroX, AArch64::LDRSWroX,
1782 { AArch64::LDRSBWroW, AArch64::LDRSHWroW, AArch64::LDRWroW,
1784 { AArch64::LDRSBXroW, AArch64::LDRSHXroW, AArch64::LDRSWroW,
1788 { { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1790 { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1792 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1794 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1796 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1798 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1800 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1802 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1807 static const unsigned FPOpcTable[4][2] = {
1808 { AArch64::LDURSi, AArch64::LDURDi },
1809 { AArch64::LDRSui, AArch64::LDRDui },
1810 { AArch64::LDRSroX, AArch64::LDRDroX },
1811 { AArch64::LDRSroW, AArch64::LDRDroW }
1816 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
1817 Addr.getOffsetReg();
1818 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
1823 bool IsRet64Bit = RetVT == MVT::i64;
1829 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][0];
1830 RC = (IsRet64Bit && !WantZExt) ?
1831 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1834 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][1];
1835 RC = (IsRet64Bit && !WantZExt) ?
1836 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1839 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][2];
1840 RC = (IsRet64Bit && !WantZExt) ?
1841 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1844 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][3];
1845 RC = &AArch64::GPR64RegClass;
1848 Opc = FPOpcTable[Idx][0];
1849 RC = &AArch64::FPR32RegClass;
1852 Opc = FPOpcTable[Idx][1];
1853 RC = &AArch64::FPR64RegClass;
1858 Register ResultReg = createResultReg(RC);
1859 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1860 TII.get(
Opc), ResultReg);
1864 if (VT == MVT::i1) {
1865 Register ANDReg = emitAnd_ri(MVT::i32, ResultReg, 1);
1866 assert(ANDReg &&
"Unexpected AND instruction emission failure.");
1872 if (WantZExt && RetVT == MVT::i64 && VT <= MVT::i32) {
1873 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
1874 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1875 TII.get(AArch64::SUBREG_TO_REG), Reg64)
1877 .
addImm(AArch64::sub_32);
1883bool AArch64FastISel::selectAddSub(
const Instruction *
I) {
1885 if (!isTypeSupported(
I->getType(), VT,
true))
1889 return selectOperator(
I,
I->getOpcode());
1892 switch (
I->getOpcode()) {
1895 case Instruction::Add:
1896 ResultReg = emitAdd(VT,
I->getOperand(0),
I->getOperand(1));
1898 case Instruction::Sub:
1899 ResultReg = emitSub(VT,
I->getOperand(0),
I->getOperand(1));
1905 updateValueMap(
I, ResultReg);
1909bool AArch64FastISel::selectLogicalOp(
const Instruction *
I) {
1911 if (!isTypeSupported(
I->getType(), VT,
true))
1915 return selectOperator(
I,
I->getOpcode());
1918 switch (
I->getOpcode()) {
1921 case Instruction::And:
1922 ResultReg = emitLogicalOp(
ISD::AND, VT,
I->getOperand(0),
I->getOperand(1));
1924 case Instruction::Or:
1925 ResultReg = emitLogicalOp(
ISD::OR, VT,
I->getOperand(0),
I->getOperand(1));
1927 case Instruction::Xor:
1928 ResultReg = emitLogicalOp(
ISD::XOR, VT,
I->getOperand(0),
I->getOperand(1));
1934 updateValueMap(
I, ResultReg);
1938bool AArch64FastISel::selectLoad(
const Instruction *
I) {
1943 if (!isTypeSupported(
I->getType(), VT,
true) ||
1947 const Value *SV =
I->getOperand(0);
1948 if (TLI.supportSwiftError()) {
1952 if (Arg->hasSwiftErrorAttr())
1957 if (Alloca->isSwiftError())
1964 if (!computeAddress(
I->getOperand(0), Addr,
I->getType()))
1968 bool WantZExt =
true;
1970 const Value *IntExtVal =
nullptr;
1971 if (
I->hasOneUse()) {
1973 if (isTypeSupported(ZE->getType(), RetVT))
1978 if (isTypeSupported(SE->getType(), RetVT))
1987 emitLoad(VT, RetVT, Addr, WantZExt, createMachineMemOperandFor(
I));
2008 auto *
MI = MRI.getUniqueVRegDef(
Reg);
2010 if (RetVT == MVT::i64 && VT <= MVT::i32) {
2014 ResultReg = std::prev(
I)->getOperand(0).getReg();
2015 removeDeadCode(
I, std::next(
I));
2017 ResultReg = fastEmitInst_extractsubreg(MVT::i32, ResultReg,
2020 updateValueMap(
I, ResultReg);
2029 for (
auto &Opnd :
MI->uses()) {
2031 Reg = Opnd.getReg();
2036 removeDeadCode(
I, std::next(
I));
2039 MI = MRI.getUniqueVRegDef(
Reg);
2041 updateValueMap(IntExtVal, ResultReg);
2045 updateValueMap(
I, ResultReg);
2049bool AArch64FastISel::emitStoreRelease(MVT VT,
Register SrcReg,
2051 MachineMemOperand *MMO) {
2054 default:
return false;
2055 case MVT::i8:
Opc = AArch64::STLRB;
break;
2056 case MVT::i16:
Opc = AArch64::STLRH;
break;
2057 case MVT::i32:
Opc = AArch64::STLRW;
break;
2058 case MVT::i64:
Opc = AArch64::STLRX;
break;
2061 const MCInstrDesc &
II =
TII.get(
Opc);
2064 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2072 MachineMemOperand *MMO) {
2073 if (!TLI.allowsMisalignedMemoryAccesses(VT))
2077 if (!simplifyAddress(Addr, VT))
2086 bool UseScaled =
true;
2087 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
2092 static const unsigned OpcTable[4][6] = {
2093 { AArch64::STURBBi, AArch64::STURHHi, AArch64::STURWi, AArch64::STURXi,
2094 AArch64::STURSi, AArch64::STURDi },
2095 { AArch64::STRBBui, AArch64::STRHHui, AArch64::STRWui, AArch64::STRXui,
2096 AArch64::STRSui, AArch64::STRDui },
2097 { AArch64::STRBBroX, AArch64::STRHHroX, AArch64::STRWroX, AArch64::STRXroX,
2098 AArch64::STRSroX, AArch64::STRDroX },
2099 { AArch64::STRBBroW, AArch64::STRHHroW, AArch64::STRWroW, AArch64::STRXroW,
2100 AArch64::STRSroW, AArch64::STRDroW }
2104 bool VTIsi1 =
false;
2105 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
2106 Addr.getOffsetReg();
2107 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
2114 case MVT::i1: VTIsi1 =
true; [[fallthrough]];
2115 case MVT::i8:
Opc = OpcTable[Idx][0];
break;
2116 case MVT::i16:
Opc = OpcTable[Idx][1];
break;
2117 case MVT::i32:
Opc = OpcTable[Idx][2];
break;
2118 case MVT::i64:
Opc = OpcTable[Idx][3];
break;
2119 case MVT::f32:
Opc = OpcTable[Idx][4];
break;
2120 case MVT::f64:
Opc = OpcTable[Idx][5];
break;
2124 if (VTIsi1 && SrcReg != AArch64::WZR) {
2125 Register ANDReg = emitAnd_ri(MVT::i32, SrcReg, 1);
2126 assert(ANDReg &&
"Unexpected AND instruction emission failure.");
2130 const MCInstrDesc &
II =
TII.get(
Opc);
2132 MachineInstrBuilder MIB =
2139bool AArch64FastISel::selectStore(
const Instruction *
I) {
2141 const Value *Op0 =
I->getOperand(0);
2145 if (!isTypeSupported(Op0->
getType(), VT,
true))
2148 const Value *PtrV =
I->getOperand(1);
2149 if (TLI.supportSwiftError()) {
2153 if (Arg->hasSwiftErrorAttr())
2158 if (Alloca->isSwiftError())
2168 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2170 if (CF->isZero() && !CF->isNegative()) {
2172 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2177 SrcReg = getRegForValue(Op0);
2185 if (
SI->isAtomic()) {
2190 Register AddrReg = getRegForValue(PtrV);
2193 return emitStoreRelease(VT, SrcReg, AddrReg,
2194 createMachineMemOperandFor(
I));
2200 if (!computeAddress(PtrV, Addr, Op0->
getType()))
2203 if (!
emitStore(VT, SrcReg, Addr, createMachineMemOperandFor(
I)))
2255bool AArch64FastISel::emitCompareAndBranch(
const CondBrInst *BI) {
2259 if (FuncInfo.MF->getFunction().hasFnAttribute(
2260 Attribute::SpeculativeLoadHardening))
2279 MachineBasicBlock *FBB = FuncInfo.getMBB(BI->
getSuccessor(1));
2282 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2289 switch (Predicate) {
2301 if (AI->
getOpcode() == Instruction::And && isValueAvailable(AI)) {
2306 if (
C->getValue().isPowerOf2())
2310 if (
C->getValue().isPowerOf2()) {
2311 TestBit =
C->getValue().logBase2();
2342 static const unsigned OpcTable[2][2][2] = {
2343 { {AArch64::CBZW, AArch64::CBZX },
2344 {AArch64::CBNZW, AArch64::CBNZX} },
2345 { {AArch64::TBZW, AArch64::TBZX },
2346 {AArch64::TBNZW, AArch64::TBNZX} }
2349 bool IsBitTest = TestBit != -1;
2350 bool Is64Bit = BW == 64;
2351 if (TestBit < 32 && TestBit >= 0)
2354 unsigned Opc = OpcTable[IsBitTest][IsCmpNE][Is64Bit];
2355 const MCInstrDesc &
II =
TII.get(
Opc);
2361 if (BW == 64 && !Is64Bit)
2362 SrcReg = fastEmitInst_extractsubreg(MVT::i32, SrcReg, AArch64::sub_32);
2364 if ((BW < 32) && !IsBitTest)
2365 SrcReg = emitIntExt(VT, SrcReg, MVT::i32,
true);
2369 MachineInstrBuilder MIB =
2370 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
2380bool AArch64FastISel::selectBranch(
const Instruction *
I) {
2384 MachineBasicBlock *FBB = FuncInfo.getMBB(BI->
getSuccessor(1));
2387 if (CI->
hasOneUse() && isValueAvailable(CI)) {
2390 switch (Predicate) {
2394 fastEmitBranch(FBB, MIMD.getDL());
2397 fastEmitBranch(
TBB, MIMD.getDL());
2402 if (emitCompareAndBranch(BI))
2406 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2419 switch (Predicate) {
2435 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2441 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2451 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::B))
2456 auto BranchProbability = FuncInfo.BPI->getEdgeProbability(
2458 FuncInfo.MBB->addSuccessor(Target, BranchProbability);
2460 FuncInfo.MBB->addSuccessorWithoutProb(Target);
2472 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2487 if (FuncInfo.MF->getFunction().hasFnAttribute(
2488 Attribute::SpeculativeLoadHardening))
2491 unsigned Opcode = AArch64::TBNZW;
2492 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2494 Opcode = AArch64::TBZW;
2497 const MCInstrDesc &
II =
TII.get(Opcode);
2500 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2501 .
addReg(ConstrainedCondReg)
2509bool AArch64FastISel::selectIndirectBr(
const Instruction *
I) {
2516 if (FuncInfo.MF->getFunction().hasFnAttribute(
"ptrauth-indirect-gotos"))
2520 const MCInstrDesc &
II =
TII.get(AArch64::BR);
2526 FuncInfo.MBB->addSuccessor(FuncInfo.getMBB(Succ));
2531bool AArch64FastISel::selectCmp(
const Instruction *
I) {
2541 switch (Predicate) {
2545 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2546 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2547 TII.get(TargetOpcode::COPY), ResultReg)
2551 ResultReg = fastEmit_i(MVT::i32, MVT::i32,
ISD::Constant, 1);
2556 updateValueMap(
I, ResultReg);
2564 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2568 static unsigned CondCodeTable[2][2] = {
2573 switch (Predicate) {
2585 Register TmpReg1 = createResultReg(&AArch64::GPR32RegClass);
2586 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2591 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2597 updateValueMap(
I, ResultReg);
2605 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2611 updateValueMap(
I, ResultReg);
2617bool AArch64FastISel::optimizeSelect(
const SelectInst *SI) {
2618 if (!
SI->getType()->isIntegerTy(1))
2621 const Value *Src1Val, *Src2Val;
2623 bool NeedExtraOp =
false;
2626 Src1Val =
SI->getCondition();
2627 Src2Val =
SI->getFalseValue();
2628 Opc = AArch64::ORRWrr;
2631 Src1Val =
SI->getFalseValue();
2632 Src2Val =
SI->getCondition();
2633 Opc = AArch64::BICWrr;
2637 Src1Val =
SI->getCondition();
2638 Src2Val =
SI->getTrueValue();
2639 Opc = AArch64::ORRWrr;
2643 Src1Val =
SI->getCondition();
2644 Src2Val =
SI->getTrueValue();
2645 Opc = AArch64::ANDWrr;
2652 Register Src1Reg = getRegForValue(Src1Val);
2656 Register Src2Reg = getRegForValue(Src2Val);
2661 Src1Reg = emitLogicalOp_ri(
ISD::XOR, MVT::i32, Src1Reg, 1);
2663 Register ResultReg = fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, Src1Reg,
2665 updateValueMap(SI, ResultReg);
2669bool AArch64FastISel::selectSelect(
const Instruction *
I) {
2672 if (!isTypeSupported(
I->getType(), VT))
2684 Opc = AArch64::CSELWr;
2685 RC = &AArch64::GPR32RegClass;
2688 Opc = AArch64::CSELXr;
2689 RC = &AArch64::GPR64RegClass;
2692 Opc = AArch64::FCSELSrrr;
2693 RC = &AArch64::FPR32RegClass;
2696 Opc = AArch64::FCSELDrrr;
2697 RC = &AArch64::FPR64RegClass;
2706 if (optimizeSelect(SI))
2710 if (foldXALUIntrinsic(CC,
I,
Cond)) {
2716 isValueAvailable(
Cond)) {
2720 const Value *FoldSelect =
nullptr;
2721 switch (Predicate) {
2725 FoldSelect =
SI->getFalseValue();
2728 FoldSelect =
SI->getTrueValue();
2733 Register SrcReg = getRegForValue(FoldSelect);
2737 updateValueMap(
I, SrcReg);
2747 switch (Predicate) {
2765 const MCInstrDesc &
II =
TII.get(AArch64::ANDSWri);
2769 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II,
2775 Register Src1Reg = getRegForValue(
SI->getTrueValue());
2776 Register Src2Reg = getRegForValue(
SI->getFalseValue());
2778 if (!Src1Reg || !Src2Reg)
2782 Src2Reg = fastEmitInst_rri(
Opc, RC, Src1Reg, Src2Reg, ExtraCC);
2784 Register ResultReg = fastEmitInst_rri(
Opc, RC, Src1Reg, Src2Reg, CC);
2785 updateValueMap(
I, ResultReg);
2789bool AArch64FastISel::selectFPExt(
const Instruction *
I) {
2791 if (!
I->getType()->isDoubleTy() || !
V->getType()->isFloatTy())
2798 Register ResultReg = createResultReg(&AArch64::FPR64RegClass);
2799 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTDSr),
2801 updateValueMap(
I, ResultReg);
2805bool AArch64FastISel::selectFPTrunc(
const Instruction *
I) {
2807 if (!
I->getType()->isFloatTy() || !
V->getType()->isDoubleTy())
2814 Register ResultReg = createResultReg(&AArch64::FPR32RegClass);
2815 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTSDr),
2817 updateValueMap(
I, ResultReg);
2822bool AArch64FastISel::selectFPToInt(
const Instruction *
I,
bool Signed) {
2824 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2827 Register SrcReg = getRegForValue(
I->getOperand(0));
2831 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2832 if (SrcVT == MVT::f128 || SrcVT == MVT::f16 || SrcVT == MVT::bf16)
2836 if (SrcVT == MVT::f64) {
2838 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWDr : AArch64::FCVTZSUXDr;
2840 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWDr : AArch64::FCVTZUUXDr;
2843 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWSr : AArch64::FCVTZSUXSr;
2845 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWSr : AArch64::FCVTZUUXSr;
2847 Register ResultReg = createResultReg(
2848 DestVT == MVT::i32 ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass);
2849 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
2851 updateValueMap(
I, ResultReg);
2855bool AArch64FastISel::selectIntToFP(
const Instruction *
I,
bool Signed) {
2857 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2860 if (DestVT == MVT::f16 || DestVT == MVT::bf16)
2863 assert((DestVT == MVT::f32 || DestVT == MVT::f64) &&
2864 "Unexpected value type.");
2866 Register SrcReg = getRegForValue(
I->getOperand(0));
2870 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2873 if (SrcVT == MVT::i16 || SrcVT == MVT::i8 || SrcVT == MVT::i1) {
2881 if (SrcVT == MVT::i64) {
2883 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUXSri : AArch64::SCVTFUXDri;
2885 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUXSri : AArch64::UCVTFUXDri;
2888 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUWSri : AArch64::SCVTFUWDri;
2890 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUWSri : AArch64::UCVTFUWDri;
2893 Register ResultReg = fastEmitInst_r(
Opc, TLI.getRegClassFor(DestVT), SrcReg);
2894 updateValueMap(
I, ResultReg);
2898bool AArch64FastISel::fastLowerArguments() {
2899 if (!FuncInfo.CanLowerReturn)
2906 CallingConv::ID CC =
F->getCallingConv();
2907 if (CC != CallingConv::C && CC != CallingConv::Swift)
2914 unsigned GPRCnt = 0;
2915 unsigned FPRCnt = 0;
2916 for (
auto const &Arg :
F->args()) {
2917 if (Arg.hasAttribute(Attribute::ByVal) ||
2918 Arg.hasAttribute(Attribute::InReg) ||
2919 Arg.hasAttribute(Attribute::StructRet) ||
2920 Arg.hasAttribute(Attribute::SwiftSelf) ||
2921 Arg.hasAttribute(Attribute::SwiftAsync) ||
2922 Arg.hasAttribute(Attribute::SwiftError) ||
2923 Arg.hasAttribute(Attribute::Nest))
2926 Type *ArgTy = Arg.getType();
2930 EVT ArgVT = TLI.getValueType(
DL, ArgTy);
2942 if (VT >= MVT::i1 && VT <= MVT::i64)
2944 else if ((VT >= MVT::f16 && VT <= MVT::f64) || VT.
is64BitVector() ||
2950 if (GPRCnt > 8 || FPRCnt > 8)
2955 { AArch64::W0, AArch64::W1, AArch64::W2, AArch64::W3, AArch64::W4,
2956 AArch64::W5, AArch64::W6, AArch64::W7 },
2957 { AArch64::X0, AArch64::X1, AArch64::X2, AArch64::X3, AArch64::X4,
2958 AArch64::X5, AArch64::X6, AArch64::X7 },
2959 { AArch64::H0, AArch64::H1, AArch64::H2, AArch64::H3, AArch64::H4,
2960 AArch64::H5, AArch64::H6, AArch64::H7 },
2961 { AArch64::S0, AArch64::S1, AArch64::S2, AArch64::S3, AArch64::S4,
2962 AArch64::S5, AArch64::S6, AArch64::S7 },
2963 { AArch64::D0, AArch64::D1, AArch64::D2, AArch64::D3, AArch64::D4,
2964 AArch64::D5, AArch64::D6, AArch64::D7 },
2965 { AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,
2966 AArch64::Q5, AArch64::Q6, AArch64::Q7 }
2969 unsigned GPRIdx = 0;
2970 unsigned FPRIdx = 0;
2971 for (
auto const &Arg :
F->args()) {
2972 MVT VT = TLI.getSimpleValueType(
DL, Arg.getType());
2975 if (VT >= MVT::i1 && VT <= MVT::i32) {
2977 RC = &AArch64::GPR32RegClass;
2979 }
else if (VT == MVT::i64) {
2981 RC = &AArch64::GPR64RegClass;
2982 }
else if (VT == MVT::f16 || VT == MVT::bf16) {
2984 RC = &AArch64::FPR16RegClass;
2985 }
else if (VT == MVT::f32) {
2987 RC = &AArch64::FPR32RegClass;
2990 RC = &AArch64::FPR64RegClass;
2993 RC = &AArch64::FPR128RegClass;
2997 Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
3001 Register ResultReg = createResultReg(RC);
3002 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3003 TII.get(TargetOpcode::COPY), ResultReg)
3005 updateValueMap(&Arg, ResultReg);
3010bool AArch64FastISel::processCallArgs(CallLoweringInfo &CLI,
3011 SmallVectorImpl<MVT> &OutVTs,
3012 SmallVectorImpl<Type *> &OrigTys,
3013 unsigned &NumBytes) {
3014 CallingConv::ID CC = CLI.CallConv;
3016 CCState CCInfo(CC,
false, *FuncInfo.MF, ArgLocs, *
Context);
3017 CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, OrigTys,
3018 CCAssignFnForCall(CC));
3021 NumBytes = CCInfo.getStackSize();
3024 unsigned AdjStackDown =
TII.getCallFrameSetupOpcode();
3025 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackDown))
3029 for (CCValAssign &VA : ArgLocs) {
3030 const Value *ArgVal = CLI.OutVals[VA.getValNo()];
3031 MVT ArgVT = OutVTs[VA.getValNo()];
3033 Register ArgReg = getRegForValue(ArgVal);
3038 switch (VA.getLocInfo()) {
3042 MVT DestVT = VA.getLocVT();
3044 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
false);
3052 MVT DestVT = VA.getLocVT();
3054 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
true);
3064 if (VA.isRegLoc() && !VA.needsCustom()) {
3065 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3066 TII.get(TargetOpcode::COPY), VA.getLocReg()).
addReg(ArgReg);
3067 CLI.OutRegs.push_back(VA.getLocReg());
3068 }
else if (VA.needsCustom()) {
3072 assert(VA.isMemLoc() &&
"Assuming store on stack.");
3081 unsigned BEAlign = 0;
3082 if (ArgSize < 8 && !Subtarget->isLittleEndian())
3083 BEAlign = 8 - ArgSize;
3086 Addr.setKind(Address::RegBase);
3087 Addr.setReg(AArch64::SP);
3088 Addr.setOffset(VA.getLocMemOffset() + BEAlign);
3091 MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
3095 if (!
emitStore(ArgVT, ArgReg, Addr, MMO))
3102bool AArch64FastISel::finishCall(CallLoweringInfo &CLI,
unsigned NumBytes) {
3103 CallingConv::ID CC = CLI.CallConv;
3106 unsigned AdjStackUp =
TII.getCallFrameDestroyOpcode();
3107 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackUp))
3112 CCState CCInfo(CC,
false, *FuncInfo.MF, RVLocs, *
Context);
3113 CCInfo.AnalyzeCallResult(CLI.Ins, CCAssignFnForCall(CC));
3115 Register ResultReg = FuncInfo.CreateRegs(CLI.RetTy);
3116 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
3117 CCValAssign &VA = RVLocs[i];
3126 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
3132 CLI.ResultReg = ResultReg;
3133 CLI.NumResultRegs = RVLocs.
size();
3138bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
3139 CallingConv::ID CC = CLI.CallConv;
3140 bool IsTailCall = CLI.IsTailCall;
3141 bool IsVarArg = CLI.IsVarArg;
3145 if (!Callee && !Symbol)
3150 if (CLI.CB && CLI.CB->hasFnAttr(Attribute::ReturnsTwice) &&
3151 !Subtarget->noBTIAtReturnTwice() &&
3152 MF->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement())
3156 if (CLI.CB && CLI.CB->isIndirectCall() &&
3180 if (MF->getFunction().getParent()->getRtLibUseGOT())
3190 for (
auto Flag : CLI.OutFlags)
3192 Flag.isSwiftSelf() ||
Flag.isSwiftAsync() ||
Flag.isSwiftError())
3198 OutVTs.
reserve(CLI.OutVals.size());
3200 for (
auto *Val : CLI.OutVals) {
3202 if (!isTypeLegal(Val->getType(), VT) &&
3203 !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16))
3215 if (Callee && !computeCallAddress(Callee, Addr))
3222 Addr.getGlobalValue()->hasExternalWeakLinkage())
3227 if (!processCallArgs(CLI, OutVTs, OrigTys, NumBytes))
3235 MachineInstrBuilder MIB;
3237 const MCInstrDesc &
II =
3239 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II);
3242 else if (Addr.getGlobalValue())
3244 else if (Addr.getReg()) {
3252 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
3253 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
3257 CallReg = createResultReg(&AArch64::GPR64RegClass);
3258 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3259 TII.get(AArch64::LDRXui), CallReg)
3263 }
else if (Addr.getGlobalValue())
3264 CallReg = materializeGV(Addr.getGlobalValue());
3265 else if (Addr.getReg())
3266 CallReg = Addr.getReg();
3273 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II).
addReg(CallReg);
3277 for (
auto Reg : CLI.OutRegs)
3287 return finishCall(CLI, NumBytes);
3290bool AArch64FastISel::isMemCpySmall(
uint64_t Len, MaybeAlign Alignment) {
3292 return Len / Alignment->value() <= 4;
3297bool AArch64FastISel::tryEmitSmallMemCpy(
Address Dest,
Address Src,
3298 uint64_t Len, MaybeAlign Alignment) {
3300 if (!isMemCpySmall(Len, Alignment))
3303 int64_t UnscaledOffset = 0;
3309 if (!Alignment || *Alignment >= 8) {
3320 assert(Alignment &&
"Alignment is set in this branch");
3322 if (Len >= 4 && *Alignment == 4)
3324 else if (Len >= 2 && *Alignment == 2)
3340 UnscaledOffset +=
Size;
3343 Dest.setOffset(OrigDest.getOffset() + UnscaledOffset);
3344 Src.setOffset(OrigSrc.getOffset() + UnscaledOffset);
3353 const Instruction *
I,
3367 if (!isTypeLegal(RetTy, RetVT))
3370 if (RetVT != MVT::i32 && RetVT != MVT::i64)
3385 case Intrinsic::smul_with_overflow:
3387 if (
C->getValue() == 2)
3388 IID = Intrinsic::sadd_with_overflow;
3390 case Intrinsic::umul_with_overflow:
3392 if (
C->getValue() == 2)
3393 IID = Intrinsic::uadd_with_overflow;
3401 case Intrinsic::sadd_with_overflow:
3402 case Intrinsic::ssub_with_overflow:
3405 case Intrinsic::uadd_with_overflow:
3408 case Intrinsic::usub_with_overflow:
3411 case Intrinsic::smul_with_overflow:
3412 case Intrinsic::umul_with_overflow:
3418 if (!isValueAvailable(
II))
3424 for (
auto Itr = std::prev(Start); Itr != End; --Itr) {
3432 if (EVI->getAggregateOperand() !=
II)
3440bool AArch64FastISel::fastLowerIntrinsicCall(
const IntrinsicInst *
II) {
3442 switch (
II->getIntrinsicID()) {
3443 default:
return false;
3444 case Intrinsic::frameaddress: {
3445 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3450 Register SrcReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3451 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3461 DestReg = fastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,
3463 assert(DestReg &&
"Unexpected LDR instruction emission failure.");
3467 updateValueMap(
II, SrcReg);
3470 case Intrinsic::sponentry: {
3471 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3475 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
3476 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3477 TII.get(AArch64::ADDXri), ResultReg)
3482 updateValueMap(
II, ResultReg);
3485 case Intrinsic::memcpy:
3486 case Intrinsic::memmove: {
3489 if (MTI->isVolatile())
3494 bool IsMemCpy = (
II->getIntrinsicID() == Intrinsic::memcpy);
3499 MaybeAlign Alignment;
3500 if (MTI->getDestAlign() || MTI->getSourceAlign())
3501 Alignment = std::min(MTI->getDestAlign().valueOrOne(),
3502 MTI->getSourceAlign().valueOrOne());
3503 if (isMemCpySmall(Len, Alignment)) {
3505 if (!computeAddress(MTI->getRawDest(), Dest) ||
3506 !computeAddress(MTI->getRawSource(), Src))
3508 if (tryEmitSmallMemCpy(Dest, Src, Len, Alignment))
3513 if (!MTI->getLength()->getType()->isIntegerTy(64))
3516 if (MTI->getSourceAddressSpace() > 255 || MTI->getDestAddressSpace() > 255)
3522 return lowerCallTo(
II, IntrMemName,
II->arg_size() - 1);
3524 case Intrinsic::memset: {
3538 return lowerCallTo(
II,
"memset",
II->arg_size() - 1);
3540 case Intrinsic::sin:
3541 case Intrinsic::cos:
3542 case Intrinsic::tan:
3543 case Intrinsic::pow: {
3545 if (!isTypeLegal(
II->getType(), RetVT))
3548 if (RetVT != MVT::f32 && RetVT != MVT::f64)
3551 static const RTLIB::Libcall LibCallTable[4][2] = {
3552 {RTLIB::SIN_F32, RTLIB::SIN_F64},
3553 {RTLIB::COS_F32, RTLIB::COS_F64},
3554 {RTLIB::TAN_F32, RTLIB::TAN_F64},
3555 {RTLIB::POW_F32, RTLIB::POW_F64}};
3557 bool Is64Bit = RetVT == MVT::f64;
3558 switch (
II->getIntrinsicID()) {
3561 case Intrinsic::sin:
3562 LC = LibCallTable[0][Is64Bit];
3564 case Intrinsic::cos:
3565 LC = LibCallTable[1][Is64Bit];
3567 case Intrinsic::tan:
3568 LC = LibCallTable[2][Is64Bit];
3570 case Intrinsic::pow:
3571 LC = LibCallTable[3][Is64Bit];
3576 Args.reserve(
II->arg_size());
3579 for (
auto &Arg :
II->args())
3580 Args.emplace_back(Arg);
3582 CallLoweringInfo CLI;
3583 MCContext &Ctx = MF->getContext();
3585 RTLIB::LibcallImpl LCImpl = LibcallLowering->getLibcallImpl(LC);
3586 if (LCImpl == RTLIB::Unsupported)
3589 CallingConv::ID CC = LibcallLowering->getLibcallImplCallingConv(LCImpl);
3591 CLI.setCallee(
DL, Ctx, CC,
II->getType(), FuncName, std::move(Args));
3592 if (!lowerCallTo(CLI))
3594 updateValueMap(
II, CLI.ResultReg);
3597 case Intrinsic::fabs: {
3599 if (!isTypeLegal(
II->getType(), VT))
3607 Opc = AArch64::FABSSr;
3610 Opc = AArch64::FABSDr;
3613 Register SrcReg = getRegForValue(
II->getOperand(0));
3616 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3617 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
3619 updateValueMap(
II, ResultReg);
3622 case Intrinsic::trap:
3623 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3626 case Intrinsic::debugtrap:
3627 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3631 case Intrinsic::sqrt: {
3632 Type *RetTy =
II->getCalledFunction()->getReturnType();
3635 if (!isTypeLegal(RetTy, VT))
3638 Register Op0Reg = getRegForValue(
II->getOperand(0));
3646 updateValueMap(
II, ResultReg);
3649 case Intrinsic::sadd_with_overflow:
3650 case Intrinsic::uadd_with_overflow:
3651 case Intrinsic::ssub_with_overflow:
3652 case Intrinsic::usub_with_overflow:
3653 case Intrinsic::smul_with_overflow:
3654 case Intrinsic::umul_with_overflow: {
3658 Type *RetTy = Ty->getTypeAtIndex(0U);
3661 if (!isTypeLegal(RetTy, VT))
3664 if (VT != MVT::i32 && VT != MVT::i64)
3678 case Intrinsic::smul_with_overflow:
3680 if (
C->getValue() == 2) {
3681 IID = Intrinsic::sadd_with_overflow;
3685 case Intrinsic::umul_with_overflow:
3687 if (
C->getValue() == 2) {
3688 IID = Intrinsic::uadd_with_overflow;
3694 Register ResultReg1, ResultReg2, MulReg;
3698 case Intrinsic::sadd_with_overflow:
3699 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3702 case Intrinsic::uadd_with_overflow:
3703 ResultReg1 = emitAdd(VT,
LHS,
RHS,
true);
3706 case Intrinsic::ssub_with_overflow:
3707 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3710 case Intrinsic::usub_with_overflow:
3711 ResultReg1 = emitSub(VT,
LHS,
RHS,
true);
3714 case Intrinsic::smul_with_overflow: {
3724 if (VT == MVT::i32) {
3725 MulReg = emitSMULL_rr(MVT::i64, LHSReg, RHSReg);
3727 fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3729 emitAddSub_rx(
false, MVT::i64, MulReg, MulSubReg,
3734 assert(VT == MVT::i64 &&
"Unexpected value type.");
3737 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3744 case Intrinsic::umul_with_overflow: {
3754 if (VT == MVT::i32) {
3755 MulReg = emitUMULL_rr(MVT::i64, LHSReg, RHSReg);
3757 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3758 TII.get(AArch64::ANDSXri), AArch64::XZR)
3761 MulReg = fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3763 assert(VT == MVT::i64 &&
"Unexpected value type.");
3766 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3768 emitSubs_rr(VT, AArch64::XZR, UMULHReg,
false);
3775 ResultReg1 = createResultReg(TLI.getRegClassFor(VT));
3776 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3777 TII.get(TargetOpcode::COPY), ResultReg1).
addReg(MulReg);
3783 ResultReg2 = fastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,
3784 AArch64::WZR, AArch64::WZR,
3785 getInvertedCondCode(CC));
3787 assert((ResultReg1 + 1) == ResultReg2 &&
3788 "Nonconsecutive result registers.");
3789 updateValueMap(
II, ResultReg1, 2);
3792 case Intrinsic::aarch64_crc32b:
3793 case Intrinsic::aarch64_crc32h:
3794 case Intrinsic::aarch64_crc32w:
3795 case Intrinsic::aarch64_crc32x:
3796 case Intrinsic::aarch64_crc32cb:
3797 case Intrinsic::aarch64_crc32ch:
3798 case Intrinsic::aarch64_crc32cw:
3799 case Intrinsic::aarch64_crc32cx: {
3800 if (!Subtarget->hasCRC())
3804 switch (
II->getIntrinsicID()) {
3807 case Intrinsic::aarch64_crc32b:
3808 Opc = AArch64::CRC32Brr;
3810 case Intrinsic::aarch64_crc32h:
3811 Opc = AArch64::CRC32Hrr;
3813 case Intrinsic::aarch64_crc32w:
3814 Opc = AArch64::CRC32Wrr;
3816 case Intrinsic::aarch64_crc32x:
3817 Opc = AArch64::CRC32Xrr;
3819 case Intrinsic::aarch64_crc32cb:
3820 Opc = AArch64::CRC32CBrr;
3822 case Intrinsic::aarch64_crc32ch:
3823 Opc = AArch64::CRC32CHrr;
3825 case Intrinsic::aarch64_crc32cw:
3826 Opc = AArch64::CRC32CWrr;
3828 case Intrinsic::aarch64_crc32cx:
3829 Opc = AArch64::CRC32CXrr;
3833 Register LHSReg = getRegForValue(
II->getArgOperand(0));
3834 Register RHSReg = getRegForValue(
II->getArgOperand(1));
3835 if (!LHSReg || !RHSReg)
3839 fastEmitInst_rr(
Opc, &AArch64::GPR32RegClass, LHSReg, RHSReg);
3840 updateValueMap(
II, ResultReg);
3847bool AArch64FastISel::selectRet(
const Instruction *
I) {
3849 const Function &
F = *
I->getParent()->getParent();
3851 if (!FuncInfo.CanLowerReturn)
3857 if (TLI.supportSwiftError() &&
3858 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
3861 if (TLI.supportSplitCSR(FuncInfo.MF))
3868 CallingConv::ID CC =
F.getCallingConv();
3874 CCState CCInfo(CC,
F.isVarArg(), *FuncInfo.MF, ValLocs,
I->getContext());
3878 if (ValLocs.
size() != 1)
3881 CCValAssign &VA = ValLocs[0];
3900 if (!MRI.getRegClass(SrcReg)->contains(DestReg))
3903 EVT RVEVT = TLI.getValueType(
DL, RV->
getType());
3913 if (RVVT == MVT::f128)
3918 if (RVVT != DestVT) {
3919 if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
3922 if (!Outs[0].
Flags.isZExt() && !Outs[0].Flags.isSExt())
3925 bool IsZExt = Outs[0].Flags.isZExt();
3926 SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
3934 SrcReg = emitAnd_ri(MVT::i64, SrcReg, 0xffffffff);
3937 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3938 TII.get(TargetOpcode::COPY), DestReg).
addReg(SrcReg);
3944 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3945 TII.get(AArch64::RET_ReallyLR));
3947 MIB.
addReg(RetReg, RegState::Implicit);
3951bool AArch64FastISel::selectTrunc(
const Instruction *
I) {
3952 Type *DestTy =
I->getType();
3954 Type *SrcTy =
Op->getType();
3956 EVT SrcEVT = TLI.getValueType(
DL, SrcTy,
true);
3957 EVT DestEVT = TLI.getValueType(
DL, DestTy,
true);
3966 if (SrcVT != MVT::i64 && SrcVT != MVT::i32 && SrcVT != MVT::i16 &&
3969 if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8 &&
3983 if (SrcVT == MVT::i64) {
4000 Register Reg32 = fastEmitInst_extractsubreg(MVT::i32, SrcReg,
4003 ResultReg = emitAnd_ri(MVT::i32, Reg32, Mask);
4004 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4006 ResultReg = createResultReg(&AArch64::GPR32RegClass);
4007 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4008 TII.get(TargetOpcode::COPY), ResultReg)
4012 updateValueMap(
I, ResultReg);
4016Register AArch64FastISel::emiti1Ext(
Register SrcReg, MVT DestVT,
bool IsZExt) {
4017 assert((DestVT == MVT::i8 || DestVT == MVT::i16 || DestVT == MVT::i32 ||
4018 DestVT == MVT::i64) &&
4019 "Unexpected value type.");
4021 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4025 Register ResultReg = emitAnd_ri(MVT::i32, SrcReg, 1);
4026 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4027 if (DestVT == MVT::i64) {
4030 Register Reg64 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4031 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4032 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4034 .
addImm(AArch64::sub_32);
4039 if (DestVT == MVT::i64) {
4043 return fastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,
4058 Opc = AArch64::MADDWrrr; ZReg = AArch64::WZR;
break;
4060 Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR;
break;
4064 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4065 return fastEmitInst_rrr(
Opc, RC, Op0, Op1, ZReg);
4069 if (RetVT != MVT::i64)
4072 return fastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,
4073 Op0, Op1, AArch64::XZR);
4077 if (RetVT != MVT::i64)
4080 return fastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,
4081 Op0, Op1, AArch64::XZR);
4087 bool NeedTrunc =
false;
4092 case MVT::i8:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4093 case MVT::i16:
Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4094 case MVT::i32:
Opc = AArch64::LSLVWr;
break;
4095 case MVT::i64:
Opc = AArch64::LSLVXr;
break;
4099 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4101 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4103 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4105 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4112 "Unexpected source/return type pair.");
4113 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4114 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4115 "Unexpected source value type.");
4116 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4117 RetVT == MVT::i64) &&
"Unexpected return value type.");
4119 bool Is64Bit = (RetVT == MVT::i64);
4120 unsigned RegSize = Is64Bit ? 64 : 32;
4124 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4128 if (RetVT == SrcVT) {
4129 Register ResultReg = createResultReg(RC);
4130 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4131 TII.get(TargetOpcode::COPY), ResultReg)
4135 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4139 if (Shift >= DstBits)
4167 unsigned ImmR =
RegSize - Shift;
4169 unsigned ImmS = std::min<unsigned>(SrcBits - 1, DstBits - 1 - Shift);
4170 static const unsigned OpcTable[2][2] = {
4171 {AArch64::SBFMWri, AArch64::SBFMXri},
4172 {AArch64::UBFMWri, AArch64::UBFMXri}
4174 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4175 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4176 Register TmpReg = MRI.createVirtualRegister(RC);
4177 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4178 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4180 .
addImm(AArch64::sub_32);
4183 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4189 bool NeedTrunc =
false;
4194 case MVT::i8:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4195 case MVT::i16:
Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4196 case MVT::i32:
Opc = AArch64::LSRVWr;
break;
4197 case MVT::i64:
Opc = AArch64::LSRVXr;
break;
4201 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4203 Op0Reg = emitAnd_ri(MVT::i32, Op0Reg, Mask);
4204 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4206 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4208 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4215 "Unexpected source/return type pair.");
4216 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4217 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4218 "Unexpected source value type.");
4219 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4220 RetVT == MVT::i64) &&
"Unexpected return value type.");
4222 bool Is64Bit = (RetVT == MVT::i64);
4223 unsigned RegSize = Is64Bit ? 64 : 32;
4227 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4231 if (RetVT == SrcVT) {
4232 Register ResultReg = createResultReg(RC);
4233 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4234 TII.get(TargetOpcode::COPY), ResultReg)
4238 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4242 if (Shift >= DstBits)
4270 if (Shift >= SrcBits && IsZExt)
4271 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4276 Op0 = emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4284 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4285 unsigned ImmS = SrcBits - 1;
4286 static const unsigned OpcTable[2][2] = {
4287 {AArch64::SBFMWri, AArch64::SBFMXri},
4288 {AArch64::UBFMWri, AArch64::UBFMXri}
4290 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4291 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4292 Register TmpReg = MRI.createVirtualRegister(RC);
4293 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4294 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4296 .
addImm(AArch64::sub_32);
4299 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4305 bool NeedTrunc =
false;
4310 case MVT::i8:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4311 case MVT::i16:
Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4312 case MVT::i32:
Opc = AArch64::ASRVWr;
break;
4313 case MVT::i64:
Opc = AArch64::ASRVXr;
break;
4317 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4319 Op0Reg = emitIntExt(RetVT, Op0Reg, MVT::i32,
false);
4320 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4322 Register ResultReg = fastEmitInst_rr(
Opc, RC, Op0Reg, Op1Reg);
4324 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4331 "Unexpected source/return type pair.");
4332 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4333 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4334 "Unexpected source value type.");
4335 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4336 RetVT == MVT::i64) &&
"Unexpected return value type.");
4338 bool Is64Bit = (RetVT == MVT::i64);
4339 unsigned RegSize = Is64Bit ? 64 : 32;
4343 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4347 if (RetVT == SrcVT) {
4348 Register ResultReg = createResultReg(RC);
4349 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4350 TII.get(TargetOpcode::COPY), ResultReg)
4354 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4358 if (Shift >= DstBits)
4386 if (Shift >= SrcBits && IsZExt)
4387 return materializeInt(ConstantInt::get(*
Context, APInt(
RegSize, 0)), RetVT);
4389 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4390 unsigned ImmS = SrcBits - 1;
4391 static const unsigned OpcTable[2][2] = {
4392 {AArch64::SBFMWri, AArch64::SBFMXri},
4393 {AArch64::UBFMWri, AArch64::UBFMXri}
4395 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4396 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4397 Register TmpReg = MRI.createVirtualRegister(RC);
4398 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4399 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4401 .
addImm(AArch64::sub_32);
4404 return fastEmitInst_rii(
Opc, RC, Op0, ImmR, ImmS);
4407Register AArch64FastISel::emitIntExt(MVT SrcVT,
Register SrcReg, MVT DestVT,
4409 assert(DestVT != MVT::i1 &&
"ZeroExt/SignExt an i1?");
4415 if (((DestVT != MVT::i8) && (DestVT != MVT::i16) &&
4416 (DestVT != MVT::i32) && (DestVT != MVT::i64)) ||
4417 ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) &&
4418 (SrcVT != MVT::i16) && (SrcVT != MVT::i32)))
4428 return emiti1Ext(SrcReg, DestVT, IsZExt);
4430 if (DestVT == MVT::i64)
4431 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4433 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4437 if (DestVT == MVT::i64)
4438 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4440 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4444 assert(DestVT == MVT::i64 &&
"IntExt i32 to i32?!?");
4445 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4451 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4453 else if (DestVT == MVT::i64) {
4454 Register Src64 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4455 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4456 TII.get(AArch64::SUBREG_TO_REG), Src64)
4458 .
addImm(AArch64::sub_32);
4463 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4464 return fastEmitInst_rii(
Opc, RC, SrcReg, 0,
Imm);
4467bool AArch64FastISel::optimizeIntExtLoad(
const Instruction *
I, MVT RetVT,
4470 if (!LI || !LI->hasOneUse())
4478 MachineInstr *
MI = MRI.getUniqueVRegDef(
Reg);
4485 const auto *LoadMI =
MI;
4486 if (LoadMI->getOpcode() == TargetOpcode::COPY &&
4487 LoadMI->getOperand(1).getSubReg() == AArch64::sub_32) {
4488 Register LoadReg =
MI->getOperand(1).getReg();
4489 LoadMI = MRI.getUniqueVRegDef(LoadReg);
4490 assert(LoadMI &&
"Expected valid instruction");
4497 if (RetVT != MVT::i64 || SrcVT > MVT::i32) {
4498 updateValueMap(
I,
Reg);
4503 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
4504 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4505 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4507 .
addImm(AArch64::sub_32);
4510 assert((
MI->getOpcode() == TargetOpcode::COPY &&
4511 MI->getOperand(1).getSubReg() == AArch64::sub_32) &&
4512 "Expected copy instruction");
4513 Reg =
MI->getOperand(1).getReg();
4515 removeDeadCode(
I, std::next(
I));
4517 updateValueMap(
I,
Reg);
4521bool AArch64FastISel::selectIntExt(
const Instruction *
I) {
4523 "Unexpected integer extend instruction.");
4526 if (!isTypeSupported(
I->getType(), RetVT))
4529 if (!isTypeSupported(
I->getOperand(0)->getType(), SrcVT))
4533 if (optimizeIntExtLoad(
I, RetVT, SrcVT))
4536 Register SrcReg = getRegForValue(
I->getOperand(0));
4543 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr())) {
4544 if (RetVT == MVT::i64 && SrcVT != MVT::i64) {
4545 Register ResultReg = createResultReg(&AArch64::GPR64RegClass);
4546 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4547 TII.get(AArch64::SUBREG_TO_REG), ResultReg)
4549 .
addImm(AArch64::sub_32);
4553 updateValueMap(
I, SrcReg);
4558 Register ResultReg = emitIntExt(SrcVT, SrcReg, RetVT, IsZExt);
4562 updateValueMap(
I, ResultReg);
4566bool AArch64FastISel::selectRem(
const Instruction *
I,
unsigned ISDOpcode) {
4567 EVT DestEVT = TLI.getValueType(
DL,
I->getType(),
true);
4572 if (DestVT != MVT::i64 && DestVT != MVT::i32)
4576 bool Is64bit = (DestVT == MVT::i64);
4577 switch (ISDOpcode) {
4581 DivOpc = Is64bit ? AArch64::SDIVXr : AArch64::SDIVWr;
4584 DivOpc = Is64bit ? AArch64::UDIVXr : AArch64::UDIVWr;
4587 unsigned MSubOpc = Is64bit ? AArch64::MSUBXrrr : AArch64::MSUBWrrr;
4588 Register Src0Reg = getRegForValue(
I->getOperand(0));
4592 Register Src1Reg = getRegForValue(
I->getOperand(1));
4597 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4598 Register QuotReg = fastEmitInst_rr(DivOpc, RC, Src0Reg, Src1Reg);
4599 assert(QuotReg &&
"Unexpected DIV instruction emission failure.");
4602 Register ResultReg = fastEmitInst_rrr(MSubOpc, RC, QuotReg, Src1Reg, Src0Reg);
4603 updateValueMap(
I, ResultReg);
4607bool AArch64FastISel::selectMul(
const Instruction *
I) {
4609 if (!isTypeSupported(
I->getType(), VT,
true))
4615 const Value *Src0 =
I->getOperand(0);
4616 const Value *Src1 =
I->getOperand(1);
4618 if (
C->getValue().isPowerOf2())
4623 if (
C->getValue().isPowerOf2()) {
4624 uint64_t ShiftVal =
C->getValue().logBase2();
4630 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), VT)) {
4633 Src0 = ZExt->getOperand(0);
4639 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), VT)) {
4642 Src0 = SExt->getOperand(0);
4647 Register Src0Reg = getRegForValue(Src0);
4651 Register ResultReg = emitLSL_ri(VT, SrcVT, Src0Reg, ShiftVal, IsZExt);
4654 updateValueMap(
I, ResultReg);
4659 Register Src0Reg = getRegForValue(
I->getOperand(0));
4663 Register Src1Reg = getRegForValue(
I->getOperand(1));
4667 Register ResultReg = emitMul_rr(VT, Src0Reg, Src1Reg);
4672 updateValueMap(
I, ResultReg);
4676bool AArch64FastISel::selectShift(
const Instruction *
I) {
4678 if (!isTypeSupported(
I->getType(), RetVT,
true))
4682 return selectOperator(
I,
I->getOpcode());
4688 bool IsZExt =
I->getOpcode() != Instruction::AShr;
4689 const Value *Op0 =
I->getOperand(0);
4693 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), TmpVT)) {
4696 Op0 = ZExt->getOperand(0);
4702 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), TmpVT)) {
4705 Op0 = SExt->getOperand(0);
4710 Register Op0Reg = getRegForValue(Op0);
4714 switch (
I->getOpcode()) {
4716 case Instruction::Shl:
4717 ResultReg = emitLSL_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4719 case Instruction::AShr:
4720 ResultReg = emitASR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4722 case Instruction::LShr:
4723 ResultReg = emitLSR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4729 updateValueMap(
I, ResultReg);
4733 Register Op0Reg = getRegForValue(
I->getOperand(0));
4737 Register Op1Reg = getRegForValue(
I->getOperand(1));
4742 switch (
I->getOpcode()) {
4744 case Instruction::Shl:
4745 ResultReg = emitLSL_rr(RetVT, Op0Reg, Op1Reg);
4747 case Instruction::AShr:
4748 ResultReg = emitASR_rr(RetVT, Op0Reg, Op1Reg);
4750 case Instruction::LShr:
4751 ResultReg = emitLSR_rr(RetVT, Op0Reg, Op1Reg);
4758 updateValueMap(
I, ResultReg);
4762bool AArch64FastISel::selectBitCast(
const Instruction *
I) {
4765 if (!isTypeLegal(
I->getOperand(0)->getType(), SrcVT))
4767 if (!isTypeLegal(
I->getType(), RetVT))
4771 if (RetVT == MVT::f32 && SrcVT == MVT::i32)
4772 Opc = AArch64::FMOVWSr;
4773 else if (RetVT == MVT::f64 && SrcVT == MVT::i64)
4774 Opc = AArch64::FMOVXDr;
4775 else if (RetVT == MVT::i32 && SrcVT == MVT::f32)
4776 Opc = AArch64::FMOVSWr;
4777 else if (RetVT == MVT::i64 && SrcVT == MVT::f64)
4778 Opc = AArch64::FMOVDXr;
4785 case MVT::i32: RC = &AArch64::GPR32RegClass;
break;
4786 case MVT::i64: RC = &AArch64::GPR64RegClass;
break;
4787 case MVT::f32: RC = &AArch64::FPR32RegClass;
break;
4788 case MVT::f64: RC = &AArch64::FPR64RegClass;
break;
4790 Register Op0Reg = getRegForValue(
I->getOperand(0));
4794 Register ResultReg = fastEmitInst_r(
Opc, RC, Op0Reg);
4798 updateValueMap(
I, ResultReg);
4802bool AArch64FastISel::selectFRem(
const Instruction *
I) {
4804 if (!isTypeLegal(
I->getType(), RetVT))
4807 RTLIB::LibcallImpl LCImpl =
4808 LibcallLowering->getLibcallImpl(RTLIB::getREM(RetVT));
4809 if (LCImpl == RTLIB::Unsupported)
4813 Args.reserve(
I->getNumOperands());
4816 for (
auto &Arg :
I->operands())
4817 Args.emplace_back(Arg);
4819 CallLoweringInfo CLI;
4820 MCContext &Ctx = MF->getContext();
4821 CallingConv::ID CC = LibcallLowering->getLibcallImplCallingConv(LCImpl);
4824 CLI.setCallee(
DL, Ctx, CC,
I->getType(), FuncName, std::move(Args));
4825 if (!lowerCallTo(CLI))
4827 updateValueMap(
I, CLI.ResultReg);
4831bool AArch64FastISel::selectSDiv(
const Instruction *
I) {
4833 if (!isTypeLegal(
I->getType(), VT))
4840 if ((VT != MVT::i32 && VT != MVT::i64) || !
C ||
4841 !(
C.isPowerOf2() ||
C.isNegatedPowerOf2()))
4844 unsigned Lg2 =
C.countr_zero();
4845 Register Src0Reg = getRegForValue(
I->getOperand(0));
4850 Register ResultReg = emitASR_ri(VT, VT, Src0Reg, Lg2);
4853 updateValueMap(
I, ResultReg);
4857 int64_t Pow2MinusOne = (1ULL << Lg2) - 1;
4858 Register AddReg = emitAdd_ri_(VT, Src0Reg, Pow2MinusOne);
4863 if (!emitICmp_ri(VT, Src0Reg, 0))
4868 if (VT == MVT::i64) {
4869 SelectOpc = AArch64::CSELXr;
4870 RC = &AArch64::GPR64RegClass;
4872 SelectOpc = AArch64::CSELWr;
4873 RC = &AArch64::GPR32RegClass;
4875 Register SelectReg = fastEmitInst_rri(SelectOpc, RC, AddReg, Src0Reg,
4882 Register ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
4885 ResultReg = emitAddSub_rs(
false, VT, ZeroReg, SelectReg,
4888 ResultReg = emitASR_ri(VT, VT, SelectReg, Lg2);
4893 updateValueMap(
I, ResultReg);
4900Register AArch64FastISel::getRegForGEPIndex(
const Value *Idx) {
4901 Register IdxN = getRegForValue(Idx);
4907 MVT PtrVT = TLI.getPointerTy(
DL);
4909 if (IdxVT.
bitsLT(PtrVT)) {
4910 IdxN = emitIntExt(IdxVT.
getSimpleVT(), IdxN, PtrVT,
false);
4911 }
else if (IdxVT.
bitsGT(PtrVT))
4912 llvm_unreachable(
"AArch64 FastISel doesn't support types larger than i64");
4920bool AArch64FastISel::selectGetElementPtr(
const Instruction *
I) {
4924 Register N = getRegForValue(
I->getOperand(0));
4931 MVT VT = TLI.getPointerTy(
DL);
4934 const Value *Idx = GTI.getOperand();
4935 if (
auto *StTy = GTI.getStructTypeOrNull()) {
4939 TotalOffs +=
DL.getStructLayout(StTy)->getElementOffset(
Field);
4946 TotalOffs += GTI.getSequentialElementStride(
DL) *
4951 N = emitAdd_ri_(VT,
N, TotalOffs);
4958 uint64_t ElementSize = GTI.getSequentialElementStride(
DL);
4959 Register IdxN = getRegForGEPIndex(Idx);
4963 if (ElementSize != 1) {
4967 IdxN = emitMul_rr(VT, IdxN,
C);
4977 N = emitAdd_ri_(VT,
N, TotalOffs);
4981 updateValueMap(
I,
N);
4985bool AArch64FastISel::selectAtomicCmpXchg(
const AtomicCmpXchgInst *
I) {
4986 assert(TM.getOptLevel() == CodeGenOptLevel::None &&
4987 "cmpxchg survived AtomicExpand at optlevel > -O0");
4990 Type *RetTy = RetPairTy->getTypeAtIndex(0U);
4991 assert(RetPairTy->getTypeAtIndex(1U)->isIntegerTy(1) &&
4992 "cmpxchg has a non-i1 status result");
4995 if (!isTypeLegal(RetTy, VT))
4999 unsigned Opc, CmpOpc;
5002 if (VT == MVT::i32) {
5003 Opc = AArch64::CMP_SWAP_32;
5004 CmpOpc = AArch64::SUBSWrs;
5005 ResRC = &AArch64::GPR32RegClass;
5006 }
else if (VT == MVT::i64) {
5007 Opc = AArch64::CMP_SWAP_64;
5008 CmpOpc = AArch64::SUBSXrs;
5009 ResRC = &AArch64::GPR64RegClass;
5014 const MCInstrDesc &
II =
TII.get(
Opc);
5016 Register AddrReg = getRegForValue(
I->getPointerOperand());
5017 Register DesiredReg = getRegForValue(
I->getCompareOperand());
5018 Register NewReg = getRegForValue(
I->getNewValOperand());
5020 if (!AddrReg || !DesiredReg || !NewReg)
5027 const Register ResultReg1 = createResultReg(ResRC);
5028 const Register ResultReg2 = createResultReg(&AArch64::GPR32RegClass);
5029 const Register ScratchReg = createResultReg(&AArch64::GPR32RegClass);
5032 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
5039 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CmpOpc))
5040 .
addDef(VT == MVT::i32 ? AArch64::WZR : AArch64::XZR)
5045 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr))
5051 assert((ResultReg1 + 1) == ResultReg2 &&
"Nonconsecutive result registers.");
5052 updateValueMap(
I, ResultReg1, 2);
5056bool AArch64FastISel::fastSelectInstruction(
const Instruction *
I) {
5057 if (TLI.fallBackToDAGISel(*
I))
5059 switch (
I->getOpcode()) {
5062 case Instruction::Add:
5063 case Instruction::Sub:
5064 return selectAddSub(
I);
5065 case Instruction::Mul:
5066 return selectMul(
I);
5067 case Instruction::SDiv:
5068 return selectSDiv(
I);
5069 case Instruction::SRem:
5073 case Instruction::URem:
5077 case Instruction::Shl:
5078 case Instruction::LShr:
5079 case Instruction::AShr:
5080 return selectShift(
I);
5081 case Instruction::And:
5082 case Instruction::Or:
5083 case Instruction::Xor:
5084 return selectLogicalOp(
I);
5085 case Instruction::CondBr:
5086 return selectBranch(
I);
5087 case Instruction::IndirectBr:
5088 return selectIndirectBr(
I);
5089 case Instruction::BitCast:
5091 return selectBitCast(
I);
5093 case Instruction::FPToSI:
5095 return selectFPToInt(
I,
true);
5097 case Instruction::FPToUI:
5098 return selectFPToInt(
I,
false);
5099 case Instruction::ZExt:
5100 case Instruction::SExt:
5101 return selectIntExt(
I);
5102 case Instruction::Trunc:
5104 return selectTrunc(
I);
5106 case Instruction::FPExt:
5107 return selectFPExt(
I);
5108 case Instruction::FPTrunc:
5109 return selectFPTrunc(
I);
5110 case Instruction::SIToFP:
5112 return selectIntToFP(
I,
true);
5114 case Instruction::UIToFP:
5115 return selectIntToFP(
I,
false);
5116 case Instruction::Load:
5117 return selectLoad(
I);
5118 case Instruction::Store:
5119 return selectStore(
I);
5120 case Instruction::FCmp:
5121 case Instruction::ICmp:
5122 return selectCmp(
I);
5123 case Instruction::Select:
5124 return selectSelect(
I);
5125 case Instruction::Ret:
5126 return selectRet(
I);
5127 case Instruction::FRem:
5128 return selectFRem(
I);
5129 case Instruction::GetElementPtr:
5130 return selectGetElementPtr(
I);
5131 case Instruction::AtomicCmpXchg:
5136 return selectOperator(
I,
I->getOpcode());
5150 return new AArch64FastISel(FuncInfo, LibInfo, LibcallLowering);
static bool isIntExtFree(const Instruction *I)
Check if the sign-/zero-extend will be a noop.
static AArch64CC::CondCode getCompareCC(CmpInst::Predicate Pred)
static bool isMulPowOf2(const Value *I)
Check if the multiply is by a power-of-2 constant.
static unsigned getImplicitScaleFactor(MVT VT)
Determine the implicit scale factor that is applied by a memory operation for a given value type.
static unsigned selectBinaryOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
Select the AArch64 opcode for the basic binary operation GenericOpc, appropriate for the register ban...
static void emitLoad(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2, int Offset, bool IsPostDec)
Emit a load-pair instruction for frame-destroy.
static void emitStore(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2, int Offset, bool IsPreDec)
Emit a store-pair instruction for frame-setup.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
This file defines the FastISel class.
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
static constexpr Value * getValue(Ty &ValueOrUse)
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
uint64_t IntrinsicInst * II
OptimizedStructLayoutField Field
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
SI Pre allocate WWM Registers
This file defines the SmallVector class.
static SDValue emitCmp(SelectionDAG &DAG, const SDLoc &DL, Comparison &C)
static const unsigned FramePtr
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
static bool isZExtLoad(const MachineInstr &MI)
Returns whether the instruction is a zero-extending load.
static bool isSExtLoad(const MachineInstr &MI)
Returns whether the instruction is a sign-extending load.
bool isAnyArgRegReserved(const MachineFunction &MF) const
void emitReservedArgRegCallError(const MachineFunction &MF) const
Register getFrameRegister(const MachineFunction &MF) const override
bool isTargetWindows() const
const AArch64RegisterInfo * getRegisterInfo() const override
bool useSmallAddressing() const
bool isTargetDarwin() const
bool isTargetILP32() const
bool isTargetMachO() const
unsigned ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const
ClassifyGlobalReference - Find the target operand flags that describe how a global value should be re...
bool isLittleEndian() const
bool isWindowsArm64EC() const
bool hasCustomCallingConv() const
PointerType * getType() const
Overload to return most specific pointer type.
InstListType::const_iterator const_iterator
Register getLocReg() const
LocInfo getLocInfo() const
unsigned getValNo() const
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Value * getCondition() const
BasicBlock * getSuccessor(unsigned i) const
const APFloat & getValueAPF() const
bool isNegative() const
Return true if the sign bit is set.
bool isZero() const
Return true if the value is positive or negative zero.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
constexpr bool isVector() const
One or more elements.
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
bool selectBitCast(const User *I)
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
PointerType * getType() const
Global values are always pointers.
iterator_range< succ_iterator > successors()
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
Tracks which library functions to use for a particular subtarget or function.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
bool isVector() const
Return true if this is a vector value type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
bool isValid() const
Return true if this is a valid simple valuetype.
static MVT getIntegerVT(unsigned BitWidth)
bool is64BitVector() const
Return true if this is a 64-bit vector type.
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
void setFrameAddressIsTaken(bool T)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Flags
Flags values. These may be or'd together.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
Value * getLength() const
unsigned getDestAddressSpace() const
constexpr unsigned id() const
SMEAttrs is a utility class to parse the SME ACLE attributes on functions.
bool hasStreamingCompatibleInterface() const
bool hasAgnosticZAInterface() const
bool hasStreamingInterfaceOrBody() const
void reserve(size_type N)
void push_back(const T &Elt)
TypeSize getElementOffset(unsigned Idx) const
Provides information about what library functions are available for the current target.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isArrayTy() const
True if this is an instance of ArrayType.
bool isPointerTy() const
True if this is an instance of PointerType.
bool isStructTy() const
True if this is an instance of StructType.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_PREL
MO_PREL - Indicates that the bits of the symbol operand represented by MO_G0 etc are PC relative.
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering)
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ ADD
Simple integer binary arithmetic operators.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
@ User
could "use" a pointer
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
LLVM_ABI void GetReturnInfo(CallingConv::ID CC, Type *ReturnType, AttributeList attr, SmallVectorImpl< ISD::OutputArg > &Outs, const TargetLowering &TLI, const DataLayout &DL)
Given an LLVM IR type and return type attributes, compute the return value EVTs and flags,...
bool CC_AArch64_Win64PCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_AArch64_DarwinPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
unsigned getBLRCallOpcode(const MachineFunction &MF)
Return opcode to be used for indirect calls.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
gep_type_iterator gep_type_end(const User *GEP)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
bool isReleaseOrStronger(AtomicOrdering AO)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
bool CC_AArch64_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
generic_gep_type_iterator<> gep_type_iterator
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
AtomicOrdering
Atomic ordering for LLVM's memory model.
bool CC_AArch64_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
bool RetCC_AArch64_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
gep_type_iterator gep_type_begin(const User *GEP)
bool CC_AArch64_Win64_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
ElementCount getVectorElementCount() const
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool isVector() const
Return true if this is a vector value type.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.