80 class AArch64FastISel final :
public FastISel {
83 using BaseKind =
enum {
89 BaseKind
Kind = RegBase;
95 unsigned OffsetReg = 0;
103 void setKind(BaseKind K) { Kind = K; }
104 BaseKind getKind()
const {
return Kind; }
107 bool isRegBase()
const {
return Kind == RegBase; }
108 bool isFIBase()
const {
return Kind == FrameIndexBase; }
110 void setReg(
unsigned Reg) {
111 assert(isRegBase() &&
"Invalid base register access!");
116 assert(isRegBase() &&
"Invalid base register access!");
120 void setOffsetReg(
unsigned Reg) {
124 unsigned getOffsetReg()
const {
128 void setFI(
unsigned FI) {
129 assert(isFIBase() &&
"Invalid base frame index access!");
133 unsigned getFI()
const {
134 assert(isFIBase() &&
"Invalid base frame index access!");
138 void setOffset(int64_t
O) { Offset =
O; }
140 void setShift(
unsigned S) { Shift = S; }
141 unsigned getShift() {
return Shift; }
152 bool fastLowerArguments()
override;
153 bool fastLowerCall(CallLoweringInfo &CLI)
override;
154 bool fastLowerIntrinsicCall(
const IntrinsicInst *II)
override;
170 bool selectRem(
const Instruction *
I,
unsigned ISDOpcode);
183 bool isTypeLegal(
Type *Ty,
MVT &VT);
184 bool isTypeSupported(
Type *Ty,
MVT &VT,
bool IsVectorAllowed =
false);
185 bool isValueAvailable(
const Value *V)
const;
192 bool isMemCpySmall(uint64_t Len,
unsigned Alignment);
199 std::pair<unsigned, bool> getRegForGEPIndex(
const Value *Idx);
202 unsigned emitAddSub(
bool UseAdd,
MVT RetVT,
const Value *LHS,
203 const Value *RHS,
bool SetFlags =
false,
204 bool WantResult =
true,
bool IsZExt =
false);
205 unsigned emitAddSub_rr(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
206 bool LHSIsKill,
unsigned RHSReg,
bool RHSIsKill,
207 bool SetFlags =
false,
bool WantResult =
true);
208 unsigned emitAddSub_ri(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
209 bool LHSIsKill, uint64_t Imm,
bool SetFlags =
false,
210 bool WantResult =
true);
211 unsigned emitAddSub_rs(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
212 bool LHSIsKill,
unsigned RHSReg,
bool RHSIsKill,
214 uint64_t ShiftImm,
bool SetFlags =
false,
215 bool WantResult =
true);
216 unsigned emitAddSub_rx(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
217 bool LHSIsKill,
unsigned RHSReg,
bool RHSIsKill,
219 uint64_t ShiftImm,
bool SetFlags =
false,
220 bool WantResult =
true);
223 bool emitCompareAndBranch(
const BranchInst *BI);
225 bool emitICmp(
MVT RetVT,
const Value *LHS,
const Value *RHS,
bool IsZExt);
226 bool emitICmp_ri(
MVT RetVT,
unsigned LHSReg,
bool LHSIsKill, uint64_t Imm);
227 bool emitFCmp(
MVT RetVT,
const Value *LHS,
const Value *RHS);
228 unsigned emitLoad(
MVT VT,
MVT ResultVT,
Address Addr,
bool WantZExt =
true,
230 bool emitStore(
MVT VT,
unsigned SrcReg,
Address Addr,
232 bool emitStoreRelease(
MVT VT,
unsigned SrcReg,
unsigned AddrReg,
234 unsigned emitIntExt(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
bool isZExt);
235 unsigned emiti1Ext(
unsigned SrcReg,
MVT DestVT,
bool isZExt);
236 unsigned emitAdd(
MVT RetVT,
const Value *LHS,
const Value *RHS,
237 bool SetFlags =
false,
bool WantResult =
true,
238 bool IsZExt =
false);
239 unsigned emitAdd_ri_(
MVT VT,
unsigned Op0,
bool Op0IsKill, int64_t Imm);
240 unsigned emitSub(
MVT RetVT,
const Value *LHS,
const Value *RHS,
241 bool SetFlags =
false,
bool WantResult =
true,
242 bool IsZExt =
false);
243 unsigned emitSubs_rr(
MVT RetVT,
unsigned LHSReg,
bool LHSIsKill,
244 unsigned RHSReg,
bool RHSIsKill,
bool WantResult =
true);
245 unsigned emitSubs_rs(
MVT RetVT,
unsigned LHSReg,
bool LHSIsKill,
246 unsigned RHSReg,
bool RHSIsKill,
248 bool WantResult =
true);
249 unsigned emitLogicalOp(
unsigned ISDOpc,
MVT RetVT,
const Value *LHS,
251 unsigned emitLogicalOp_ri(
unsigned ISDOpc,
MVT RetVT,
unsigned LHSReg,
252 bool LHSIsKill, uint64_t Imm);
253 unsigned emitLogicalOp_rs(
unsigned ISDOpc,
MVT RetVT,
unsigned LHSReg,
254 bool LHSIsKill,
unsigned RHSReg,
bool RHSIsKill,
256 unsigned emitAnd_ri(
MVT RetVT,
unsigned LHSReg,
bool LHSIsKill, uint64_t Imm);
257 unsigned emitMul_rr(
MVT RetVT,
unsigned Op0,
bool Op0IsKill,
258 unsigned Op1,
bool Op1IsKill);
259 unsigned emitSMULL_rr(
MVT RetVT,
unsigned Op0,
bool Op0IsKill,
260 unsigned Op1,
bool Op1IsKill);
261 unsigned emitUMULL_rr(
MVT RetVT,
unsigned Op0,
bool Op0IsKill,
262 unsigned Op1,
bool Op1IsKill);
263 unsigned emitLSL_rr(
MVT RetVT,
unsigned Op0Reg,
bool Op0IsKill,
264 unsigned Op1Reg,
bool Op1IsKill);
265 unsigned emitLSL_ri(
MVT RetVT,
MVT SrcVT,
unsigned Op0Reg,
bool Op0IsKill,
266 uint64_t Imm,
bool IsZExt =
true);
267 unsigned emitLSR_rr(
MVT RetVT,
unsigned Op0Reg,
bool Op0IsKill,
268 unsigned Op1Reg,
bool Op1IsKill);
269 unsigned emitLSR_ri(
MVT RetVT,
MVT SrcVT,
unsigned Op0Reg,
bool Op0IsKill,
270 uint64_t Imm,
bool IsZExt =
true);
271 unsigned emitASR_rr(
MVT RetVT,
unsigned Op0Reg,
bool Op0IsKill,
272 unsigned Op1Reg,
bool Op1IsKill);
273 unsigned emitASR_ri(
MVT RetVT,
MVT SrcVT,
unsigned Op0Reg,
bool Op0IsKill,
274 uint64_t Imm,
bool IsZExt =
false);
285 bool finishCall(CallLoweringInfo &CLI,
MVT RetVT,
unsigned NumBytes);
289 unsigned fastMaterializeAlloca(
const AllocaInst *AI)
override;
290 unsigned fastMaterializeConstant(
const Constant *
C)
override;
291 unsigned fastMaterializeFloatZero(
const ConstantFP* CF)
override;
301 bool fastSelectInstruction(
const Instruction *
I)
override;
303 #include "AArch64GenFastISel.inc" 308 #include "AArch64GenCallingConv.inc" 312 assert((isa<ZExtInst>(I) || isa<SExtInst>(I)) &&
313 "Unexpected integer extend instruction.");
315 "Unexpected value type.");
316 bool IsZExt = isa<ZExtInst>(
I);
318 if (
const auto *LI = dyn_cast<LoadInst>(I->
getOperand(0)))
323 if ((IsZExt &&
Arg->hasZExtAttr()) || (!IsZExt &&
Arg->hasSExtAttr()))
351 return CC_AArch64_WebKit_JS;
353 return CC_AArch64_GHC;
354 return Subtarget->
isTargetDarwin() ? CC_AArch64_DarwinPCS : CC_AArch64_AAPCS;
357 unsigned AArch64FastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
359 "Alloca should always return a pointer.");
362 if (!FuncInfo.StaticAllocaMap.count(AI))
366 FuncInfo.StaticAllocaMap.find(AI);
368 if (SI != FuncInfo.StaticAllocaMap.
end()) {
369 unsigned ResultReg = createResultReg(&AArch64::GPR64spRegClass);
370 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AArch64::ADDXri),
372 .addFrameIndex(SI->second)
381 unsigned AArch64FastISel::materializeInt(
const ConstantInt *CI,
MVT VT) {
390 : &AArch64::GPR32RegClass;
391 unsigned ZeroReg = (VT ==
MVT::i64) ? AArch64::XZR : AArch64::WZR;
392 unsigned ResultReg = createResultReg(RC);
393 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(TargetOpcode::COPY),
398 unsigned AArch64FastISel::materializeFP(
const ConstantFP *CFP,
MVT VT) {
402 return fastMaterializeFloatZero(CFP);
411 if (TLI.isFPImmLegal(Val, VT)) {
414 assert((Imm != -1) &&
"Cannot encode floating-point constant.");
415 unsigned Opc = Is64Bit ? AArch64::FMOVDi : AArch64::FMOVSi;
416 return fastEmitInst_i(Opc, TLI.getRegClassFor(VT), Imm);
421 unsigned Opc1 = Is64Bit ? AArch64::MOVi64imm : AArch64::MOVi32imm;
423 &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
425 unsigned TmpReg = createResultReg(RC);
426 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc1), TmpReg)
429 unsigned ResultReg = createResultReg(TLI.getRegClassFor(VT));
430 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
431 TII.get(TargetOpcode::COPY), ResultReg)
439 unsigned Align = DL.getPrefTypeAlignment(CFP->
getType());
441 Align = DL.getTypeAllocSize(CFP->
getType());
443 unsigned CPI = MCP.getConstantPoolIndex(cast<Constant>(CFP), Align);
444 unsigned ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
448 unsigned Opc = Is64Bit ? AArch64::LDRDui : AArch64::LDRSui;
449 unsigned ResultReg = createResultReg(TLI.getRegClassFor(VT));
450 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
456 unsigned AArch64FastISel::materializeGV(
const GlobalValue *GV) {
468 EVT DestEVT = TLI.getValueType(DL, GV->
getType(),
true);
472 unsigned ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
481 ResultReg = createResultReg(&AArch64::GPR64RegClass);
482 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AArch64::LDRXui),
493 ResultReg = createResultReg(&AArch64::GPR64spRegClass);
494 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AArch64::ADDXri),
504 unsigned AArch64FastISel::fastMaterializeConstant(
const Constant *
C) {
505 EVT CEVT = TLI.getValueType(DL, C->
getType(),
true);
512 if (
const auto *CI = dyn_cast<ConstantInt>(C))
513 return materializeInt(CI, VT);
514 else if (
const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
515 return materializeFP(CFP, VT);
516 else if (
const GlobalValue *GV = dyn_cast<GlobalValue>(C))
517 return materializeGV(GV);
522 unsigned AArch64FastISel::fastMaterializeFloatZero(
const ConstantFP* CFP) {
524 "Floating-point constant is not a positive zero.");
526 if (!isTypeLegal(CFP->
getType(), VT))
533 unsigned ZReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
534 unsigned Opc = Is64Bit ? AArch64::FMOVXDr : AArch64::FMOVWSr;
535 return fastEmitInst_r(Opc, TLI.getRegClassFor(VT), ZReg,
true);
540 if (
const auto *
MI = dyn_cast<MulOperator>(I)) {
541 if (
const auto *C = dyn_cast<ConstantInt>(
MI->getOperand(0)))
542 if (C->getValue().isPowerOf2())
544 if (
const auto *C = dyn_cast<ConstantInt>(
MI->getOperand(1)))
545 if (C->getValue().isPowerOf2())
552 bool AArch64FastISel::computeAddress(
const Value *Obj,
Address &Addr,
Type *Ty)
554 const User *U =
nullptr;
555 unsigned Opcode = Instruction::UserOp1;
556 if (
const Instruction *
I = dyn_cast<Instruction>(Obj)) {
559 if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
560 FuncInfo.MBBMap[
I->getParent()] == FuncInfo.MBB) {
561 Opcode =
I->getOpcode();
564 }
else if (
const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
565 Opcode = C->getOpcode();
569 if (
auto *Ty = dyn_cast<PointerType>(Obj->
getType()))
570 if (Ty->getAddressSpace() > 255)
578 case Instruction::BitCast:
580 return computeAddress(U->
getOperand(0), Addr, Ty);
582 case Instruction::IntToPtr:
585 TLI.getPointerTy(DL))
586 return computeAddress(U->
getOperand(0), Addr, Ty);
589 case Instruction::PtrToInt:
591 if (TLI.getValueType(DL, U->
getType()) == TLI.getPointerTy(DL))
592 return computeAddress(U->
getOperand(0), Addr, Ty);
595 case Instruction::GetElementPtr: {
597 uint64_t TmpOffset = Addr.getOffset();
603 const Value *
Op = GTI.getOperand();
604 if (
StructType *STy = GTI.getStructTypeOrNull()) {
606 unsigned Idx = cast<ConstantInt>(
Op)->getZExtValue();
609 uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
611 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
616 if (canFoldAddIntoGEP(U, Op)) {
619 cast<ConstantInt>(cast<AddOperator>(
Op)->getOperand(1));
622 Op = cast<AddOperator>(
Op)->getOperand(0);
626 goto unsupported_gep;
632 Addr.setOffset(TmpOffset);
633 if (computeAddress(U->
getOperand(0), Addr, Ty))
642 case Instruction::Alloca: {
645 FuncInfo.StaticAllocaMap.find(AI);
646 if (SI != FuncInfo.StaticAllocaMap.end()) {
647 Addr.setKind(Address::FrameIndexBase);
648 Addr.setFI(SI->second);
658 if (isa<ConstantInt>(LHS))
661 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
663 return computeAddress(LHS, Addr, Ty);
667 if (computeAddress(LHS, Addr, Ty) && computeAddress(RHS, Addr, Ty))
673 case Instruction::Sub: {
678 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
680 return computeAddress(LHS, Addr, Ty);
684 case Instruction::Shl: {
685 if (Addr.getOffsetReg())
693 if (Val < 1 || Val > 3)
696 uint64_t NumBytes = 0;
698 uint64_t NumBits = DL.getTypeSizeInBits(Ty);
699 NumBytes = NumBits / 8;
704 if (NumBytes != (1ULL << Val))
711 if (
const auto *
I = dyn_cast<Instruction>(Src)) {
712 if (FuncInfo.MBBMap[
I->getParent()] == FuncInfo.MBB) {
714 if (
const auto *ZE = dyn_cast<ZExtInst>(
I)) {
716 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
718 Src = ZE->getOperand(0);
720 }
else if (
const auto *SE = dyn_cast<SExtInst>(
I)) {
722 SE->getOperand(0)->getType()->isIntegerTy(32)) {
724 Src = SE->getOperand(0);
730 if (
const auto *AI = dyn_cast<BinaryOperator>(Src))
731 if (AI->
getOpcode() == Instruction::And) {
735 if (
const auto *C = dyn_cast<ConstantInt>(LHS))
736 if (C->getValue() == 0xffffffff)
739 if (
const auto *C = dyn_cast<ConstantInt>(RHS))
740 if (C->getValue() == 0xffffffff) {
742 unsigned Reg = getRegForValue(LHS);
745 bool RegIsKill = hasTrivialKill(LHS);
746 Reg = fastEmitInst_extractsubreg(
MVT::i32, Reg, RegIsKill,
748 Addr.setOffsetReg(Reg);
753 unsigned Reg = getRegForValue(Src);
756 Addr.setOffsetReg(Reg);
759 case Instruction::Mul: {
760 if (Addr.getOffsetReg())
770 if (
const auto *C = dyn_cast<ConstantInt>(LHS))
771 if (C->getValue().isPowerOf2())
774 assert(isa<ConstantInt>(RHS) &&
"Expected an ConstantInt.");
775 const auto *C = cast<ConstantInt>(RHS);
776 unsigned Val = C->getValue().logBase2();
777 if (Val < 1 || Val > 3)
780 uint64_t NumBytes = 0;
782 uint64_t NumBits = DL.getTypeSizeInBits(Ty);
783 NumBytes = NumBits / 8;
788 if (NumBytes != (1ULL << Val))
794 const Value *Src = LHS;
795 if (
const auto *
I = dyn_cast<Instruction>(Src)) {
796 if (FuncInfo.MBBMap[
I->getParent()] == FuncInfo.MBB) {
798 if (
const auto *ZE = dyn_cast<ZExtInst>(
I)) {
800 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
802 Src = ZE->getOperand(0);
804 }
else if (
const auto *SE = dyn_cast<SExtInst>(
I)) {
806 SE->getOperand(0)->getType()->isIntegerTy(32)) {
808 Src = SE->getOperand(0);
814 unsigned Reg = getRegForValue(Src);
817 Addr.setOffsetReg(Reg);
820 case Instruction::And: {
821 if (Addr.getOffsetReg())
824 if (!Ty || DL.getTypeSizeInBits(Ty) != 8)
830 if (
const auto *C = dyn_cast<ConstantInt>(LHS))
831 if (C->getValue() == 0xffffffff)
834 if (
const auto *C = dyn_cast<ConstantInt>(RHS))
835 if (C->getValue() == 0xffffffff) {
840 unsigned Reg = getRegForValue(LHS);
843 bool RegIsKill = hasTrivialKill(LHS);
844 Reg = fastEmitInst_extractsubreg(
MVT::i32, Reg, RegIsKill,
846 Addr.setOffsetReg(Reg);
851 case Instruction::SExt:
852 case Instruction::ZExt: {
853 if (!Addr.getReg() || Addr.getOffsetReg())
856 const Value *Src =
nullptr;
858 if (
const auto *ZE = dyn_cast<ZExtInst>(U)) {
859 if (!
isIntExtFree(ZE) && ZE->getOperand(0)->getType()->isIntegerTy(32)) {
861 Src = ZE->getOperand(0);
863 }
else if (
const auto *SE = dyn_cast<SExtInst>(U)) {
864 if (!
isIntExtFree(SE) && SE->getOperand(0)->getType()->isIntegerTy(32)) {
866 Src = SE->getOperand(0);
874 unsigned Reg = getRegForValue(Src);
877 Addr.setOffsetReg(Reg);
882 if (Addr.isRegBase() && !Addr.getReg()) {
883 unsigned Reg = getRegForValue(Obj);
890 if (!Addr.getOffsetReg()) {
891 unsigned Reg = getRegForValue(Obj);
894 Addr.setOffsetReg(Reg);
901 bool AArch64FastISel::computeCallAddress(
const Value *V,
Address &Addr) {
902 const User *U =
nullptr;
903 unsigned Opcode = Instruction::UserOp1;
906 if (
const auto *
I = dyn_cast<Instruction>(V)) {
907 Opcode =
I->getOpcode();
909 InMBB =
I->getParent() == FuncInfo.MBB->getBasicBlock();
910 }
else if (
const auto *C = dyn_cast<ConstantExpr>(V)) {
911 Opcode = C->getOpcode();
917 case Instruction::BitCast:
920 return computeCallAddress(U->
getOperand(0), Addr);
922 case Instruction::IntToPtr:
926 TLI.getPointerTy(DL))
927 return computeCallAddress(U->
getOperand(0), Addr);
929 case Instruction::PtrToInt:
931 if (InMBB && TLI.getValueType(DL, U->
getType()) == TLI.getPointerTy(DL))
932 return computeCallAddress(U->
getOperand(0), Addr);
936 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
937 Addr.setGlobalValue(GV);
942 if (!Addr.getGlobalValue()) {
943 Addr.setReg(getRegForValue(V));
944 return Addr.getReg() != 0;
950 bool AArch64FastISel::isTypeLegal(
Type *Ty,
MVT &VT) {
951 EVT evt = TLI.getValueType(DL, Ty,
true);
964 return TLI.isTypeLegal(VT);
971 bool AArch64FastISel::isTypeSupported(
Type *Ty,
MVT &VT,
bool IsVectorAllowed) {
975 if (isTypeLegal(Ty, VT))
986 bool AArch64FastISel::isValueAvailable(
const Value *V)
const {
987 if (!isa<Instruction>(V))
990 const auto *
I = cast<Instruction>(V);
991 return FuncInfo.MBBMap[
I->getParent()] == FuncInfo.MBB;
994 bool AArch64FastISel::simplifyAddress(
Address &Addr,
MVT VT) {
999 bool ImmediateOffsetNeedsLowering =
false;
1000 bool RegisterOffsetNeedsLowering =
false;
1001 int64_t Offset = Addr.getOffset();
1002 if (((Offset < 0) || (Offset & (ScaleFactor - 1))) && !isInt<9>(Offset))
1003 ImmediateOffsetNeedsLowering =
true;
1004 else if (Offset > 0 && !(Offset & (ScaleFactor - 1)) &&
1005 !isUInt<12>(Offset / ScaleFactor))
1006 ImmediateOffsetNeedsLowering =
true;
1011 if (!ImmediateOffsetNeedsLowering && Addr.getOffset() && Addr.getOffsetReg())
1012 RegisterOffsetNeedsLowering =
true;
1015 if (Addr.isRegBase() && Addr.getOffsetReg() && !Addr.getReg())
1016 RegisterOffsetNeedsLowering =
true;
1021 if ((ImmediateOffsetNeedsLowering || Addr.getOffsetReg()) && Addr.isFIBase())
1023 unsigned ResultReg = createResultReg(&AArch64::GPR64spRegClass);
1024 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AArch64::ADDXri),
1026 .addFrameIndex(Addr.getFI())
1029 Addr.setKind(Address::RegBase);
1030 Addr.setReg(ResultReg);
1033 if (RegisterOffsetNeedsLowering) {
1034 unsigned ResultReg = 0;
1035 if (Addr.getReg()) {
1038 ResultReg = emitAddSub_rx(
true,
MVT::i64, Addr.getReg(),
1039 false, Addr.getOffsetReg(),
1040 false, Addr.getExtendType(),
1043 ResultReg = emitAddSub_rs(
true,
MVT::i64, Addr.getReg(),
1044 false, Addr.getOffsetReg(),
1050 false, Addr.getShift(),
1054 false, Addr.getShift(),
1058 false, Addr.getShift());
1063 Addr.setReg(ResultReg);
1064 Addr.setOffsetReg(0);
1071 if (ImmediateOffsetNeedsLowering) {
1081 Addr.setReg(ResultReg);
1087 void AArch64FastISel::addLoadStoreOperands(
Address &Addr,
1090 unsigned ScaleFactor,
1092 int64_t Offset = Addr.getOffset() / ScaleFactor;
1094 if (Addr.isFIBase()) {
1095 int FI = Addr.getFI();
1098 MMO = FuncInfo.MF->getMachineMemOperand(
1100 MFI.getObjectSize(FI), MFI.getObjectAlignment(FI));
1104 assert(Addr.isRegBase() &&
"Unexpected address kind.");
1111 if (Addr.getOffsetReg()) {
1112 assert(Addr.getOffset() == 0 &&
"Unexpected offset");
1115 MIB.
addReg(Addr.getReg());
1116 MIB.
addReg(Addr.getOffsetReg());
1118 MIB.
addImm(Addr.getShift() != 0);
1120 MIB.
addReg(Addr.getReg()).addImm(Offset);
1127 unsigned AArch64FastISel::emitAddSub(
bool UseAdd,
MVT RetVT,
const Value *LHS,
1128 const Value *RHS,
bool SetFlags,
1129 bool WantResult,
bool IsZExt) {
1131 bool NeedExtend =
false;
1154 if (UseAdd && isa<Constant>(LHS) && !isa<Constant>(RHS))
1158 if (UseAdd && LHS->
hasOneUse() && isValueAvailable(LHS))
1163 if (UseAdd && LHS->
hasOneUse() && isValueAvailable(LHS))
1164 if (
const auto *
SI = dyn_cast<BinaryOperator>(LHS))
1165 if (isa<ConstantInt>(
SI->getOperand(1)))
1166 if (
SI->getOpcode() == Instruction::Shl ||
1167 SI->getOpcode() == Instruction::LShr ||
1168 SI->getOpcode() == Instruction::AShr )
1171 unsigned LHSReg = getRegForValue(LHS);
1174 bool LHSIsKill = hasTrivialKill(LHS);
1177 LHSReg = emitIntExt(SrcVT, LHSReg, RetVT, IsZExt);
1179 unsigned ResultReg = 0;
1180 if (
const auto *C = dyn_cast<ConstantInt>(RHS)) {
1181 uint64_t Imm = IsZExt ? C->getZExtValue() : C->getSExtValue();
1182 if (C->isNegative())
1183 ResultReg = emitAddSub_ri(!UseAdd, RetVT, LHSReg, LHSIsKill, -Imm,
1184 SetFlags, WantResult);
1186 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, LHSIsKill, Imm, SetFlags,
1188 }
else if (
const auto *C = dyn_cast<Constant>(RHS))
1190 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, LHSIsKill, 0, SetFlags,
1198 isValueAvailable(RHS)) {
1199 if (
const auto *
SI = dyn_cast<BinaryOperator>(RHS))
1200 if (
const auto *C = dyn_cast<ConstantInt>(
SI->getOperand(1)))
1201 if ((
SI->getOpcode() == Instruction::Shl) && (C->getZExtValue() < 4)) {
1202 unsigned RHSReg = getRegForValue(
SI->getOperand(0));
1205 bool RHSIsKill = hasTrivialKill(
SI->getOperand(0));
1206 return emitAddSub_rx(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg,
1207 RHSIsKill, ExtendType, C->getZExtValue(),
1208 SetFlags, WantResult);
1210 unsigned RHSReg = getRegForValue(RHS);
1213 bool RHSIsKill = hasTrivialKill(RHS);
1214 return emitAddSub_rx(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
1215 ExtendType, 0, SetFlags, WantResult);
1219 if (RHS->
hasOneUse() && isValueAvailable(RHS)) {
1221 const Value *MulLHS = cast<MulOperator>(RHS)->getOperand(0);
1222 const Value *MulRHS = cast<MulOperator>(RHS)->getOperand(1);
1224 if (
const auto *C = dyn_cast<ConstantInt>(MulLHS))
1225 if (C->getValue().isPowerOf2())
1228 assert(isa<ConstantInt>(MulRHS) &&
"Expected a ConstantInt.");
1229 uint64_t ShiftVal = cast<ConstantInt>(MulRHS)->getValue().logBase2();
1230 unsigned RHSReg = getRegForValue(MulLHS);
1233 bool RHSIsKill = hasTrivialKill(MulLHS);
1234 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg,
1243 if (RHS->
hasOneUse() && isValueAvailable(RHS)) {
1244 if (
const auto *
SI = dyn_cast<BinaryOperator>(RHS)) {
1245 if (
const auto *C = dyn_cast<ConstantInt>(
SI->getOperand(1))) {
1247 switch (
SI->getOpcode()) {
1253 uint64_t ShiftVal = C->getZExtValue();
1255 unsigned RHSReg = getRegForValue(
SI->getOperand(0));
1258 bool RHSIsKill = hasTrivialKill(
SI->getOperand(0));
1259 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg,
1260 RHSIsKill, ShiftType, ShiftVal, SetFlags,
1269 unsigned RHSReg = getRegForValue(RHS);
1272 bool RHSIsKill = hasTrivialKill(RHS);
1275 RHSReg = emitIntExt(SrcVT, RHSReg, RetVT, IsZExt);
1277 return emitAddSub_rr(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
1278 SetFlags, WantResult);
1281 unsigned AArch64FastISel::emitAddSub_rr(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
1282 bool LHSIsKill,
unsigned RHSReg,
1283 bool RHSIsKill,
bool SetFlags,
1285 assert(LHSReg && RHSReg &&
"Invalid register number.");
1287 if (LHSReg == AArch64::SP || LHSReg == AArch64::WSP ||
1288 RHSReg == AArch64::SP || RHSReg == AArch64::WSP)
1294 static const unsigned OpcTable[2][2][2] = {
1295 { { AArch64::SUBWrr, AArch64::SUBXrr },
1296 { AArch64::ADDWrr, AArch64::ADDXrr } },
1297 { { AArch64::SUBSWrr, AArch64::SUBSXrr },
1298 { AArch64::ADDSWrr, AArch64::ADDSXrr } }
1301 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1303 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1306 ResultReg = createResultReg(RC);
1308 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1313 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
1319 unsigned AArch64FastISel::emitAddSub_ri(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
1320 bool LHSIsKill, uint64_t Imm,
1321 bool SetFlags,
bool WantResult) {
1322 assert(LHSReg &&
"Invalid register number.");
1328 if (isUInt<12>(Imm))
1330 else if ((Imm & 0xfff000) == Imm) {
1336 static const unsigned OpcTable[2][2][2] = {
1337 { { AArch64::SUBWri, AArch64::SUBXri },
1338 { AArch64::ADDWri, AArch64::ADDXri } },
1339 { { AArch64::SUBSWri, AArch64::SUBSXri },
1340 { AArch64::ADDSWri, AArch64::ADDSXri } }
1343 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1346 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1348 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1351 ResultReg = createResultReg(RC);
1353 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1357 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
1364 unsigned AArch64FastISel::emitAddSub_rs(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
1365 bool LHSIsKill,
unsigned RHSReg,
1368 uint64_t ShiftImm,
bool SetFlags,
1370 assert(LHSReg && RHSReg &&
"Invalid register number.");
1371 assert(LHSReg != AArch64::SP && LHSReg != AArch64::WSP &&
1372 RHSReg != AArch64::SP && RHSReg != AArch64::WSP);
1381 static const unsigned OpcTable[2][2][2] = {
1382 { { AArch64::SUBWrs, AArch64::SUBXrs },
1383 { AArch64::ADDWrs, AArch64::ADDXrs } },
1384 { { AArch64::SUBSWrs, AArch64::SUBSXrs },
1385 { AArch64::ADDSWrs, AArch64::ADDSXrs } }
1388 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1390 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1393 ResultReg = createResultReg(RC);
1395 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1400 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
1407 unsigned AArch64FastISel::emitAddSub_rx(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
1408 bool LHSIsKill,
unsigned RHSReg,
1411 uint64_t ShiftImm,
bool SetFlags,
1413 assert(LHSReg && RHSReg &&
"Invalid register number.");
1414 assert(LHSReg != AArch64::XZR && LHSReg != AArch64::WZR &&
1415 RHSReg != AArch64::XZR && RHSReg != AArch64::WZR);
1423 static const unsigned OpcTable[2][2][2] = {
1424 { { AArch64::SUBWrx, AArch64::SUBXrx },
1425 { AArch64::ADDWrx, AArch64::ADDXrx } },
1426 { { AArch64::SUBSWrx, AArch64::SUBSXrx },
1427 { AArch64::ADDSWrx, AArch64::ADDSXrx } }
1430 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1433 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1435 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1438 ResultReg = createResultReg(RC);
1440 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1445 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
1454 EVT EVT = TLI.getValueType(DL, Ty,
true);
1467 return emitICmp(VT, LHS, RHS, IsZExt);
1470 return emitFCmp(VT, LHS, RHS);
1474 bool AArch64FastISel::emitICmp(
MVT RetVT,
const Value *LHS,
const Value *RHS,
1476 return emitSub(RetVT, LHS, RHS,
true,
false,
1480 bool AArch64FastISel::emitICmp_ri(
MVT RetVT,
unsigned LHSReg,
bool LHSIsKill,
1482 return emitAddSub_ri(
false, RetVT, LHSReg, LHSIsKill, Imm,
1486 bool AArch64FastISel::emitFCmp(
MVT RetVT,
const Value *LHS,
const Value *RHS) {
1492 bool UseImm =
false;
1493 if (
const auto *CFP = dyn_cast<ConstantFP>(RHS))
1497 unsigned LHSReg = getRegForValue(LHS);
1500 bool LHSIsKill = hasTrivialKill(LHS);
1503 unsigned Opc = (RetVT ==
MVT::f64) ? AArch64::FCMPDri : AArch64::FCMPSri;
1504 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc))
1509 unsigned RHSReg = getRegForValue(RHS);
1512 bool RHSIsKill = hasTrivialKill(RHS);
1514 unsigned Opc = (RetVT ==
MVT::f64) ? AArch64::FCMPDrr : AArch64::FCMPSrr;
1515 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc))
1521 unsigned AArch64FastISel::emitAdd(
MVT RetVT,
const Value *LHS,
const Value *RHS,
1522 bool SetFlags,
bool WantResult,
bool IsZExt) {
1523 return emitAddSub(
true, RetVT, LHS, RHS, SetFlags, WantResult,
1532 unsigned AArch64FastISel::emitAdd_ri_(
MVT VT,
unsigned Op0,
bool Op0IsKill,
1536 ResultReg = emitAddSub_ri(
false, VT, Op0, Op0IsKill, -Imm);
1538 ResultReg = emitAddSub_ri(
true, VT, Op0, Op0IsKill, Imm);
1547 ResultReg = emitAddSub_rr(
true, VT, Op0, Op0IsKill, CReg,
true);
1551 unsigned AArch64FastISel::emitSub(
MVT RetVT,
const Value *LHS,
const Value *RHS,
1552 bool SetFlags,
bool WantResult,
bool IsZExt) {
1553 return emitAddSub(
false, RetVT, LHS, RHS, SetFlags, WantResult,
1557 unsigned AArch64FastISel::emitSubs_rr(
MVT RetVT,
unsigned LHSReg,
1558 bool LHSIsKill,
unsigned RHSReg,
1559 bool RHSIsKill,
bool WantResult) {
1560 return emitAddSub_rr(
false, RetVT, LHSReg, LHSIsKill, RHSReg,
1561 RHSIsKill,
true, WantResult);
1564 unsigned AArch64FastISel::emitSubs_rs(
MVT RetVT,
unsigned LHSReg,
1565 bool LHSIsKill,
unsigned RHSReg,
1568 uint64_t ShiftImm,
bool WantResult) {
1569 return emitAddSub_rs(
false, RetVT, LHSReg, LHSIsKill, RHSReg,
1570 RHSIsKill, ShiftType, ShiftImm,
true,
1574 unsigned AArch64FastISel::emitLogicalOp(
unsigned ISDOpc,
MVT RetVT,
1577 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS))
1581 if (LHS->
hasOneUse() && isValueAvailable(LHS))
1586 if (LHS->
hasOneUse() && isValueAvailable(LHS))
1587 if (
const auto *
SI = dyn_cast<ShlOperator>(LHS))
1588 if (isa<ConstantInt>(
SI->getOperand(1)))
1591 unsigned LHSReg = getRegForValue(LHS);
1594 bool LHSIsKill = hasTrivialKill(LHS);
1596 unsigned ResultReg = 0;
1597 if (
const auto *C = dyn_cast<ConstantInt>(RHS)) {
1598 uint64_t Imm = C->getZExtValue();
1599 ResultReg = emitLogicalOp_ri(ISDOpc, RetVT, LHSReg, LHSIsKill, Imm);
1605 if (RHS->
hasOneUse() && isValueAvailable(RHS)) {
1607 const Value *MulLHS = cast<MulOperator>(RHS)->getOperand(0);
1608 const Value *MulRHS = cast<MulOperator>(RHS)->getOperand(1);
1610 if (
const auto *C = dyn_cast<ConstantInt>(MulLHS))
1611 if (C->getValue().isPowerOf2())
1614 assert(isa<ConstantInt>(MulRHS) &&
"Expected a ConstantInt.");
1615 uint64_t ShiftVal = cast<ConstantInt>(MulRHS)->getValue().logBase2();
1617 unsigned RHSReg = getRegForValue(MulLHS);
1620 bool RHSIsKill = hasTrivialKill(MulLHS);
1621 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, LHSIsKill, RHSReg,
1622 RHSIsKill, ShiftVal);
1629 if (RHS->
hasOneUse() && isValueAvailable(RHS)) {
1630 if (
const auto *
SI = dyn_cast<ShlOperator>(RHS))
1631 if (
const auto *C = dyn_cast<ConstantInt>(
SI->getOperand(1))) {
1632 uint64_t ShiftVal = C->getZExtValue();
1633 unsigned RHSReg = getRegForValue(
SI->getOperand(0));
1636 bool RHSIsKill = hasTrivialKill(
SI->getOperand(0));
1637 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, LHSIsKill, RHSReg,
1638 RHSIsKill, ShiftVal);
1644 unsigned RHSReg = getRegForValue(RHS);
1647 bool RHSIsKill = hasTrivialKill(RHS);
1650 ResultReg = fastEmit_rr(VT, VT, ISDOpc, LHSReg, LHSIsKill, RHSReg, RHSIsKill);
1652 uint64_t
Mask = (RetVT ==
MVT::i8) ? 0xff : 0xffff;
1653 ResultReg = emitAnd_ri(
MVT::i32, ResultReg,
true, Mask);
1658 unsigned AArch64FastISel::emitLogicalOp_ri(
unsigned ISDOpc,
MVT RetVT,
1659 unsigned LHSReg,
bool LHSIsKill,
1662 "ISD nodes are not consecutive!");
1663 static const unsigned OpcTable[3][2] = {
1664 { AArch64::ANDWri, AArch64::ANDXri },
1665 { AArch64::ORRWri, AArch64::ORRXri },
1666 { AArch64::EORWri, AArch64::EORXri }
1679 Opc = OpcTable[Idx][0];
1680 RC = &AArch64::GPR32spRegClass;
1685 Opc = OpcTable[ISDOpc -
ISD::AND][1];
1686 RC = &AArch64::GPR64spRegClass;
1694 unsigned ResultReg =
1695 fastEmitInst_ri(Opc, RC, LHSReg, LHSIsKill,
1698 uint64_t
Mask = (RetVT ==
MVT::i8) ? 0xff : 0xffff;
1699 ResultReg = emitAnd_ri(
MVT::i32, ResultReg,
true, Mask);
1704 unsigned AArch64FastISel::emitLogicalOp_rs(
unsigned ISDOpc,
MVT RetVT,
1705 unsigned LHSReg,
bool LHSIsKill,
1706 unsigned RHSReg,
bool RHSIsKill,
1707 uint64_t ShiftImm) {
1709 "ISD nodes are not consecutive!");
1710 static const unsigned OpcTable[3][2] = {
1711 { AArch64::ANDWrs, AArch64::ANDXrs },
1712 { AArch64::ORRWrs, AArch64::ORRXrs },
1713 { AArch64::EORWrs, AArch64::EORXrs }
1729 Opc = OpcTable[ISDOpc -
ISD::AND][0];
1730 RC = &AArch64::GPR32RegClass;
1733 Opc = OpcTable[ISDOpc -
ISD::AND][1];
1734 RC = &AArch64::GPR64RegClass;
1737 unsigned ResultReg =
1738 fastEmitInst_rri(Opc, RC, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
1741 uint64_t
Mask = (RetVT ==
MVT::i8) ? 0xff : 0xffff;
1742 ResultReg = emitAnd_ri(
MVT::i32, ResultReg,
true, Mask);
1747 unsigned AArch64FastISel::emitAnd_ri(
MVT RetVT,
unsigned LHSReg,
bool LHSIsKill,
1749 return emitLogicalOp_ri(
ISD::AND, RetVT, LHSReg, LHSIsKill, Imm);
1752 unsigned AArch64FastISel::emitLoad(
MVT VT,
MVT RetVT,
Address Addr,
1754 if (!TLI.allowsMisalignedMemoryAccesses(VT))
1758 if (!simplifyAddress(Addr, VT))
1767 bool UseScaled =
true;
1768 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
1773 static const unsigned GPOpcTable[2][8][4] = {
1775 { { AArch64::LDURSBWi, AArch64::LDURSHWi, AArch64::LDURWi,
1777 { AArch64::LDURSBXi, AArch64::LDURSHXi, AArch64::LDURSWi,
1779 { AArch64::LDRSBWui, AArch64::LDRSHWui, AArch64::LDRWui,
1781 { AArch64::LDRSBXui, AArch64::LDRSHXui, AArch64::LDRSWui,
1783 { AArch64::LDRSBWroX, AArch64::LDRSHWroX, AArch64::LDRWroX,
1785 { AArch64::LDRSBXroX, AArch64::LDRSHXroX, AArch64::LDRSWroX,
1787 { AArch64::LDRSBWroW, AArch64::LDRSHWroW, AArch64::LDRWroW,
1789 { AArch64::LDRSBXroW, AArch64::LDRSHXroW, AArch64::LDRSWroW,
1793 { { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1795 { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1797 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1799 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1801 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1803 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1805 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1807 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1812 static const unsigned FPOpcTable[4][2] = {
1813 { AArch64::LDURSi, AArch64::LDURDi },
1814 { AArch64::LDRSui, AArch64::LDRDui },
1815 { AArch64::LDRSroX, AArch64::LDRDroX },
1816 { AArch64::LDRSroW, AArch64::LDRDroW }
1821 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
1822 Addr.getOffsetReg();
1823 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
1828 bool IsRet64Bit = RetVT ==
MVT::i64;
1834 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][0];
1835 RC = (IsRet64Bit && !WantZExt) ?
1836 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1839 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][1];
1840 RC = (IsRet64Bit && !WantZExt) ?
1841 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1844 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][2];
1845 RC = (IsRet64Bit && !WantZExt) ?
1846 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1849 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][3];
1850 RC = &AArch64::GPR64RegClass;
1853 Opc = FPOpcTable[Idx][0];
1854 RC = &AArch64::FPR32RegClass;
1857 Opc = FPOpcTable[Idx][1];
1858 RC = &AArch64::FPR64RegClass;
1863 unsigned ResultReg = createResultReg(RC);
1865 TII.get(Opc), ResultReg);
1870 unsigned ANDReg = emitAnd_ri(
MVT::i32, ResultReg,
true, 1);
1871 assert(ANDReg &&
"Unexpected AND instruction emission failure.");
1878 unsigned Reg64 = createResultReg(&AArch64::GPR64RegClass);
1879 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1880 TII.get(AArch64::SUBREG_TO_REG), Reg64)
1883 .
addImm(AArch64::sub_32);
1889 bool AArch64FastISel::selectAddSub(
const Instruction *
I) {
1891 if (!isTypeSupported(I->
getType(), VT,
true))
1895 return selectOperator(I, I->
getOpcode());
1904 case Instruction::Sub:
1911 updateValueMap(I, ResultReg);
1915 bool AArch64FastISel::selectLogicalOp(
const Instruction *I) {
1917 if (!isTypeSupported(I->
getType(), VT,
true))
1921 return selectOperator(I, I->
getOpcode());
1927 case Instruction::And:
1930 case Instruction::Or:
1933 case Instruction::Xor:
1940 updateValueMap(I, ResultReg);
1944 bool AArch64FastISel::selectLoad(
const Instruction *I) {
1949 if (!isTypeSupported(I->
getType(), VT,
true) ||
1950 cast<LoadInst>(I)->isAtomic())
1954 if (TLI.supportSwiftError()) {
1957 if (
const Argument *
Arg = dyn_cast<Argument>(SV)) {
1958 if (
Arg->hasSwiftErrorAttr())
1962 if (
const AllocaInst *Alloca = dyn_cast<AllocaInst>(SV)) {
1963 if (Alloca->isSwiftError())
1974 bool WantZExt =
true;
1976 const Value *IntExtVal =
nullptr;
1978 if (
const auto *ZE = dyn_cast<ZExtInst>(I->
use_begin()->getUser())) {
1979 if (isTypeSupported(ZE->getType(), RetVT))
1983 }
else if (
const auto *SE = dyn_cast<SExtInst>(I->
use_begin()->getUser())) {
1984 if (isTypeSupported(SE->getType(), RetVT))
1992 unsigned ResultReg =
1993 emitLoad(VT, RetVT, Addr, WantZExt, createMachineMemOperandFor(I));
2013 unsigned Reg = lookUpRegForValue(IntExtVal);
2014 auto *
MI =
MRI.getUniqueVRegDef(Reg);
2020 ResultReg = std::prev(I)->getOperand(0).getReg();
2021 removeDeadCode(I, std::next(I));
2023 ResultReg = fastEmitInst_extractsubreg(
MVT::i32, ResultReg,
2027 updateValueMap(I, ResultReg);
2036 for (
auto &Opnd :
MI->uses()) {
2038 Reg = Opnd.getReg();
2043 removeDeadCode(I, std::next(I));
2046 MI =
MRI.getUniqueVRegDef(Reg);
2048 updateValueMap(IntExtVal, ResultReg);
2052 updateValueMap(I, ResultReg);
2056 bool AArch64FastISel::emitStoreRelease(
MVT VT,
unsigned SrcReg,
2061 default:
return false;
2062 case MVT::i8: Opc = AArch64::STLRB;
break;
2063 case MVT::i16: Opc = AArch64::STLRH;
break;
2064 case MVT::i32: Opc = AArch64::STLRW;
break;
2065 case MVT::i64: Opc = AArch64::STLRX;
break;
2071 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
2078 bool AArch64FastISel::emitStore(
MVT VT,
unsigned SrcReg,
Address Addr,
2080 if (!TLI.allowsMisalignedMemoryAccesses(VT))
2084 if (!simplifyAddress(Addr, VT))
2093 bool UseScaled =
true;
2094 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
2099 static const unsigned OpcTable[4][6] = {
2100 { AArch64::STURBBi, AArch64::STURHHi, AArch64::STURWi, AArch64::STURXi,
2101 AArch64::STURSi, AArch64::STURDi },
2102 { AArch64::STRBBui, AArch64::STRHHui, AArch64::STRWui, AArch64::STRXui,
2103 AArch64::STRSui, AArch64::STRDui },
2104 { AArch64::STRBBroX, AArch64::STRHHroX, AArch64::STRWroX, AArch64::STRXroX,
2105 AArch64::STRSroX, AArch64::STRDroX },
2106 { AArch64::STRBBroW, AArch64::STRHHroW, AArch64::STRWroW, AArch64::STRXroW,
2107 AArch64::STRSroW, AArch64::STRDroW }
2111 bool VTIsi1 =
false;
2112 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
2113 Addr.getOffsetReg();
2114 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
2122 case MVT::i8: Opc = OpcTable[Idx][0];
break;
2123 case MVT::i16: Opc = OpcTable[Idx][1];
break;
2124 case MVT::i32: Opc = OpcTable[Idx][2];
break;
2125 case MVT::i64: Opc = OpcTable[Idx][3];
break;
2126 case MVT::f32: Opc = OpcTable[Idx][4];
break;
2127 case MVT::f64: Opc = OpcTable[Idx][5];
break;
2131 if (VTIsi1 && SrcReg != AArch64::WZR) {
2132 unsigned ANDReg = emitAnd_ri(
MVT::i32, SrcReg,
false, 1);
2133 assert(ANDReg &&
"Unexpected AND instruction emission failure.");
2140 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II).
addReg(SrcReg);
2146 bool AArch64FastISel::selectStore(
const Instruction *I) {
2152 if (!isTypeSupported(Op0->
getType(), VT,
true))
2156 if (TLI.supportSwiftError()) {
2159 if (
const Argument *
Arg = dyn_cast<Argument>(PtrV)) {
2160 if (
Arg->hasSwiftErrorAttr())
2164 if (
const AllocaInst *Alloca = dyn_cast<AllocaInst>(PtrV)) {
2165 if (Alloca->isSwiftError())
2172 unsigned SrcReg = 0;
2173 if (
const auto *CI = dyn_cast<ConstantInt>(Op0)) {
2175 SrcReg = (VT ==
MVT::i64) ? AArch64::XZR : AArch64::WZR;
2176 }
else if (
const auto *CF = dyn_cast<ConstantFP>(Op0)) {
2177 if (CF->isZero() && !CF->isNegative()) {
2179 SrcReg = (VT ==
MVT::i64) ? AArch64::XZR : AArch64::WZR;
2184 SrcReg = getRegForValue(Op0);
2189 auto *
SI = cast<StoreInst>(
I);
2192 if (
SI->isAtomic()) {
2197 unsigned AddrReg = getRegForValue(PtrV);
2198 return emitStoreRelease(VT, SrcReg, AddrReg,
2199 createMachineMemOperandFor(I));
2205 if (!computeAddress(PtrV, Addr, Op0->
getType()))
2208 if (!emitStore(VT, SrcReg, Addr, createMachineMemOperandFor(I)))
2260 bool AArch64FastISel::emitCompareAndBranch(
const BranchInst *BI) {
2264 if (FuncInfo.MF->getFunction().hasFnAttribute(
2276 if (!isTypeSupported(LHS->
getType(), VT))
2287 if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
2294 switch (Predicate) {
2299 if (isa<Constant>(LHS) && cast<Constant>(LHS)->isNullValue())
2302 if (!isa<Constant>(RHS) || !cast<Constant>(RHS)->isNullValue())
2305 if (
const auto *AI = dyn_cast<BinaryOperator>(LHS))
2306 if (AI->
getOpcode() == Instruction::And && isValueAvailable(AI)) {
2310 if (
const auto *C = dyn_cast<ConstantInt>(AndLHS))
2311 if (C->getValue().isPowerOf2())
2314 if (
const auto *C = dyn_cast<ConstantInt>(AndRHS))
2315 if (C->getValue().isPowerOf2()) {
2316 TestBit = C->getValue().logBase2();
2328 if (!isa<Constant>(RHS) || !cast<Constant>(RHS)->isNullValue())
2336 if (!isa<ConstantInt>(RHS))
2339 if (cast<ConstantInt>(RHS)->getValue() !=
APInt(BW, -1,
true))
2347 static const unsigned OpcTable[2][2][2] = {
2348 { {AArch64::CBZW, AArch64::CBZX },
2349 {AArch64::CBNZW, AArch64::CBNZX} },
2350 { {AArch64::TBZW, AArch64::TBZX },
2351 {AArch64::TBNZW, AArch64::TBNZX} }
2354 bool IsBitTest = TestBit != -1;
2355 bool Is64Bit = BW == 64;
2356 if (TestBit < 32 && TestBit >= 0)
2359 unsigned Opc = OpcTable[IsBitTest][IsCmpNE][Is64Bit];
2362 unsigned SrcReg = getRegForValue(LHS);
2365 bool SrcIsKill = hasTrivialKill(LHS);
2367 if (BW == 64 && !Is64Bit)
2368 SrcReg = fastEmitInst_extractsubreg(
MVT::i32, SrcReg, SrcIsKill,
2371 if ((BW < 32) && !IsBitTest)
2372 SrcReg = emitIntExt(VT, SrcReg,
MVT::i32,
true);
2377 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc))
2383 finishCondBranch(BI->
getParent(), TBB, FBB);
2387 bool AArch64FastISel::selectBranch(
const Instruction *I) {
2399 if (CI->
hasOneUse() && isValueAvailable(CI)) {
2402 switch (Predicate) {
2406 fastEmitBranch(FBB, DbgLoc);
2409 fastEmitBranch(TBB, DbgLoc);
2414 if (emitCompareAndBranch(BI))
2418 if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
2431 switch (Predicate) {
2447 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AArch64::Bcc))
2453 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AArch64::Bcc))
2457 finishCondBranch(BI->
getParent(), TBB, FBB);
2460 }
else if (
const auto *CI = dyn_cast<ConstantInt>(BI->
getCondition())) {
2472 FuncInfo.MBB->addSuccessorWithoutProb(Target);
2484 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AArch64::Bcc))
2488 finishCondBranch(BI->
getParent(), TBB, FBB);
2496 bool CondRegIsKill = hasTrivialKill(BI->
getCondition());
2499 unsigned Opcode = AArch64::TBNZW;
2500 if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
2502 Opcode = AArch64::TBZW;
2506 unsigned ConstrainedCondReg
2508 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
2513 finishCondBranch(BI->
getParent(), TBB, FBB);
2517 bool AArch64FastISel::selectIndirectBr(
const Instruction *I) {
2519 unsigned AddrReg = getRegForValue(BI->
getOperand(0));
2526 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II).
addReg(AddrReg);
2530 FuncInfo.MBB->addSuccessor(FuncInfo.MBBMap[Succ]);
2535 bool AArch64FastISel::selectCmp(
const Instruction *I) {
2536 const CmpInst *CI = cast<CmpInst>(
I);
2544 unsigned ResultReg = 0;
2545 switch (Predicate) {
2549 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2550 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
2551 TII.get(TargetOpcode::COPY), ResultReg)
2560 updateValueMap(I, ResultReg);
2568 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2572 static unsigned CondCodeTable[2][2] = {
2577 switch (Predicate) {
2581 CondCodes = &CondCodeTable[0][0];
2584 CondCodes = &CondCodeTable[1][0];
2589 unsigned TmpReg1 = createResultReg(&AArch64::GPR32RegClass);
2590 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AArch64::CSINCWr),
2594 .addImm(CondCodes[0]);
2595 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AArch64::CSINCWr),
2599 .addImm(CondCodes[1]);
2601 updateValueMap(I, ResultReg);
2609 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AArch64::CSINCWr),
2613 .addImm(invertedCC);
2615 updateValueMap(I, ResultReg);
2621 bool AArch64FastISel::optimizeSelect(
const SelectInst *
SI) {
2625 const Value *Src1Val, *Src2Val;
2627 bool NeedExtraOp =
false;
2628 if (
auto *CI = dyn_cast<ConstantInt>(SI->
getTrueValue())) {
2632 Opc = AArch64::ORRWrr;
2637 Opc = AArch64::BICWrr;
2639 }
else if (
auto *CI = dyn_cast<ConstantInt>(SI->
getFalseValue())) {
2643 Opc = AArch64::ORRWrr;
2649 Opc = AArch64::ANDWrr;
2656 unsigned Src1Reg = getRegForValue(Src1Val);
2659 bool Src1IsKill = hasTrivialKill(Src1Val);
2661 unsigned Src2Reg = getRegForValue(Src2Val);
2664 bool Src2IsKill = hasTrivialKill(Src2Val);
2670 unsigned ResultReg = fastEmitInst_rr(Opc, &AArch64::GPR32RegClass, Src1Reg,
2671 Src1IsKill, Src2Reg, Src2IsKill);
2672 updateValueMap(SI, ResultReg);
2676 bool AArch64FastISel::selectSelect(
const Instruction *I) {
2677 assert(isa<SelectInst>(I) &&
"Expected a select instruction.");
2679 if (!isTypeSupported(I->
getType(), VT))
2691 Opc = AArch64::CSELWr;
2692 RC = &AArch64::GPR32RegClass;
2695 Opc = AArch64::CSELXr;
2696 RC = &AArch64::GPR64RegClass;
2699 Opc = AArch64::FCSELSrrr;
2700 RC = &AArch64::FPR32RegClass;
2703 Opc = AArch64::FCSELDrrr;
2704 RC = &AArch64::FPR64RegClass;
2713 if (optimizeSelect(SI))
2717 if (foldXALUIntrinsic(CC, I, Cond)) {
2719 unsigned CondReg = getRegForValue(Cond);
2722 }
else if (isa<CmpInst>(Cond) && cast<CmpInst>(Cond)->hasOneUse() &&
2723 isValueAvailable(Cond)) {
2724 const auto *Cmp = cast<CmpInst>(Cond);
2727 const Value *FoldSelect =
nullptr;
2728 switch (Predicate) {
2740 unsigned SrcReg = getRegForValue(FoldSelect);
2743 unsigned UseReg = lookUpRegForValue(SI);
2745 MRI.clearKillFlags(UseReg);
2747 updateValueMap(I, SrcReg);
2752 if (!
emitCmp(Cmp->getOperand(0), Cmp->getOperand(1), Cmp->isUnsigned()))
2757 switch (Predicate) {
2771 unsigned CondReg = getRegForValue(Cond);
2774 bool CondIsKill = hasTrivialKill(Cond);
2780 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II,
2792 if (!Src1Reg || !Src2Reg)
2796 Src2Reg = fastEmitInst_rri(Opc, RC, Src1Reg, Src1IsKill, Src2Reg,
2797 Src2IsKill, ExtraCC);
2800 unsigned ResultReg = fastEmitInst_rri(Opc, RC, Src1Reg, Src1IsKill, Src2Reg,
2802 updateValueMap(I, ResultReg);
2806 bool AArch64FastISel::selectFPExt(
const Instruction *I) {
2811 unsigned Op = getRegForValue(V);
2815 unsigned ResultReg = createResultReg(&AArch64::FPR64RegClass);
2816 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AArch64::FCVTDSr),
2817 ResultReg).addReg(Op);
2818 updateValueMap(I, ResultReg);
2822 bool AArch64FastISel::selectFPTrunc(
const Instruction *I) {
2827 unsigned Op = getRegForValue(V);
2831 unsigned ResultReg = createResultReg(&AArch64::FPR32RegClass);
2832 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AArch64::FCVTSDr),
2833 ResultReg).addReg(Op);
2834 updateValueMap(I, ResultReg);
2844 unsigned SrcReg = getRegForValue(I->
getOperand(0));
2855 Opc = (DestVT ==
MVT::i32) ? AArch64::FCVTZSUWDr : AArch64::FCVTZSUXDr;
2857 Opc = (DestVT ==
MVT::i32) ? AArch64::FCVTZUUWDr : AArch64::FCVTZUUXDr;
2860 Opc = (DestVT ==
MVT::i32) ? AArch64::FCVTZSUWSr : AArch64::FCVTZSUXSr;
2862 Opc = (DestVT ==
MVT::i32) ? AArch64::FCVTZUUWSr : AArch64::FCVTZUUXSr;
2864 unsigned ResultReg = createResultReg(
2865 DestVT ==
MVT::i32 ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass);
2866 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
2868 updateValueMap(I, ResultReg);
2872 bool AArch64FastISel::selectIntToFP(
const Instruction *I,
bool Signed) {
2881 "Unexpected value type.");
2883 unsigned SrcReg = getRegForValue(I->
getOperand(0));
2886 bool SrcIsKill = hasTrivialKill(I->
getOperand(0));
2902 Opc = (DestVT ==
MVT::f32) ? AArch64::SCVTFUXSri : AArch64::SCVTFUXDri;
2904 Opc = (DestVT ==
MVT::f32) ? AArch64::UCVTFUXSri : AArch64::UCVTFUXDri;
2907 Opc = (DestVT ==
MVT::f32) ? AArch64::SCVTFUWSri : AArch64::SCVTFUWDri;
2909 Opc = (DestVT ==
MVT::f32) ? AArch64::UCVTFUWSri : AArch64::UCVTFUWDri;
2912 unsigned ResultReg = fastEmitInst_r(Opc, TLI.getRegClassFor(DestVT), SrcReg,
2914 updateValueMap(I, ResultReg);
2918 bool AArch64FastISel::fastLowerArguments() {
2919 if (!FuncInfo.CanLowerReturn)
2934 unsigned GPRCnt = 0;
2935 unsigned FPRCnt = 0;
2936 for (
auto const &
Arg : F->
args()) {
2949 EVT ArgVT = TLI.getValueType(DL, ArgTy);
2969 if (GPRCnt > 8 || FPRCnt > 8)
2973 static const MCPhysReg Registers[6][8] = {
2974 { AArch64::W0, AArch64::W1, AArch64::W2, AArch64::W3, AArch64::W4,
2975 AArch64::W5, AArch64::W6, AArch64::W7 },
2976 { AArch64::X0, AArch64::X1, AArch64::X2, AArch64::X3, AArch64::X4,
2977 AArch64::X5, AArch64::X6, AArch64::X7 },
2978 { AArch64::H0, AArch64::H1, AArch64::H2, AArch64::H3, AArch64::H4,
2979 AArch64::H5, AArch64::H6, AArch64::H7 },
2980 { AArch64::S0, AArch64::S1, AArch64::S2, AArch64::S3, AArch64::S4,
2981 AArch64::S5, AArch64::S6, AArch64::S7 },
2982 { AArch64::D0, AArch64::D1, AArch64::D2, AArch64::D3, AArch64::D4,
2983 AArch64::D5, AArch64::D6, AArch64::D7 },
2984 { AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,
2985 AArch64::Q5, AArch64::Q6, AArch64::Q7 }
2989 unsigned FPRIdx = 0;
2990 for (
auto const &
Arg : F->
args()) {
2995 SrcReg = Registers[0][GPRIdx++];
2996 RC = &AArch64::GPR32RegClass;
2999 SrcReg = Registers[1][GPRIdx++];
3000 RC = &AArch64::GPR64RegClass;
3002 SrcReg = Registers[2][FPRIdx++];
3003 RC = &AArch64::FPR16RegClass;
3005 SrcReg = Registers[3][FPRIdx++];
3006 RC = &AArch64::FPR32RegClass;
3008 SrcReg = Registers[4][FPRIdx++];
3009 RC = &AArch64::FPR64RegClass;
3011 SrcReg = Registers[5][FPRIdx++];
3012 RC = &AArch64::FPR128RegClass;
3016 unsigned DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
3020 unsigned ResultReg = createResultReg(RC);
3021 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3022 TII.get(TargetOpcode::COPY), ResultReg)
3024 updateValueMap(&
Arg, ResultReg);
3029 bool AArch64FastISel::processCallArgs(CallLoweringInfo &CLI,
3031 unsigned &NumBytes) {
3034 CCState CCInfo(CC,
false, *FuncInfo.MF, ArgLocs, *Context);
3041 unsigned AdjStackDown =
TII.getCallFrameSetupOpcode();
3042 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AdjStackDown))
3043 .addImm(NumBytes).
addImm(0);
3047 const Value *ArgVal = CLI.OutVals[VA.getValNo()];
3048 MVT ArgVT = OutVTs[VA.getValNo()];
3050 unsigned ArgReg = getRegForValue(ArgVal);
3055 switch (VA.getLocInfo()) {
3059 MVT DestVT = VA.getLocVT();
3061 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
false);
3069 MVT DestVT = VA.getLocVT();
3071 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
true);
3081 if (VA.isRegLoc() && !VA.needsCustom()) {
3082 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3083 TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(ArgReg);
3084 CLI.OutRegs.push_back(VA.getLocReg());
3085 }
else if (VA.needsCustom()) {
3089 assert(VA.isMemLoc() &&
"Assuming store on stack.");
3092 if (isa<UndefValue>(ArgVal))
3098 unsigned BEAlign = 0;
3099 if (ArgSize < 8 && !Subtarget->isLittleEndian())
3100 BEAlign = 8 - ArgSize;
3103 Addr.setKind(Address::RegBase);
3104 Addr.setReg(AArch64::SP);
3105 Addr.setOffset(VA.getLocMemOffset() + BEAlign);
3107 unsigned Alignment = DL.getABITypeAlignment(ArgVal->
getType());
3112 if (!emitStore(ArgVT, ArgReg, Addr, MMO))
3119 bool AArch64FastISel::finishCall(CallLoweringInfo &CLI,
MVT RetVT,
3120 unsigned NumBytes) {
3124 unsigned AdjStackUp =
TII.getCallFrameDestroyOpcode();
3125 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AdjStackUp))
3126 .addImm(NumBytes).
addImm(0);
3131 CCState CCInfo(CC,
false, *FuncInfo.MF, RVLocs, *Context);
3135 if (RVLocs.
size() != 1)
3139 MVT CopyVT = RVLocs[0].getValVT();
3145 unsigned ResultReg = createResultReg(TLI.getRegClassFor(CopyVT));
3146 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3147 TII.get(TargetOpcode::COPY), ResultReg)
3148 .addReg(RVLocs[0].getLocReg());
3149 CLI.InRegs.push_back(RVLocs[0].getLocReg());
3151 CLI.ResultReg = ResultReg;
3152 CLI.NumResultRegs = 1;
3158 bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
3160 bool IsTailCall = CLI.IsTailCall;
3161 bool IsVarArg = CLI.IsVarArg;
3165 if (!Callee && !Symbol)
3187 if (CLI.RetTy->isVoidTy())
3189 else if (!isTypeLegal(CLI.RetTy, RetVT))
3192 for (
auto Flag : CLI.OutFlags)
3194 Flag.isSwiftSelf() ||
Flag.isSwiftError())
3199 OutVTs.
reserve(CLI.OutVals.size());
3201 for (
auto *Val : CLI.OutVals) {
3203 if (!isTypeLegal(Val->getType(), VT) &&
3215 if (Callee && !computeCallAddress(Callee, Addr))
3220 if (!processCallArgs(CLI, OutVTs, NumBytes))
3231 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II);
3234 else if (Addr.getGlobalValue())
3236 else if (Addr.getReg()) {
3242 unsigned CallReg = 0;
3244 unsigned ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
3249 CallReg = createResultReg(&AArch64::GPR64RegClass);
3250 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3251 TII.get(AArch64::LDRXui), CallReg)
3255 }
else if (Addr.getGlobalValue())
3256 CallReg = materializeGV(Addr.getGlobalValue());
3257 else if (Addr.getReg())
3258 CallReg = Addr.getReg();
3265 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II).
addReg(CallReg);
3269 for (
auto Reg : CLI.OutRegs)
3279 return finishCall(CLI, RetVT, NumBytes);
3282 bool AArch64FastISel::isMemCpySmall(uint64_t Len,
unsigned Alignment) {
3284 return Len / Alignment <= 4;
3289 bool AArch64FastISel::tryEmitSmallMemCpy(
Address Dest,
Address Src,
3290 uint64_t Len,
unsigned Alignment) {
3292 if (!isMemCpySmall(Len, Alignment))
3295 int64_t UnscaledOffset = 0;
3301 if (!Alignment || Alignment >= 8) {
3313 if (Len >= 4 && Alignment == 4)
3315 else if (Len >= 2 && Alignment == 2)
3322 unsigned ResultReg = emitLoad(VT, VT, Src);
3326 if (!emitStore(VT, ResultReg, Dest))
3331 UnscaledOffset +=
Size;
3334 Dest.setOffset(OrigDest.getOffset() + UnscaledOffset);
3335 Src.setOffset(OrigSrc.getOffset() + UnscaledOffset);
3345 const Value *Cond) {
3346 if (!isa<ExtractValueInst>(Cond))
3349 const auto *EV = cast<ExtractValueInst>(Cond);
3350 if (!isa<IntrinsicInst>(EV->getAggregateOperand()))
3353 const auto *II = cast<IntrinsicInst>(EV->getAggregateOperand());
3357 cast<StructType>(Callee->
getReturnType())->getTypeAtIndex(0U);
3358 if (!isTypeLegal(RetTy, RetVT))
3364 const Value *LHS = II->getArgOperand(0);
3365 const Value *RHS = II->getArgOperand(1);
3368 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS) &&
3369 isCommutativeIntrinsic(II))
3378 if (
const auto *C = dyn_cast<ConstantInt>(RHS))
3379 if (C->getValue() == 2)
3383 if (
const auto *C = dyn_cast<ConstantInt>(RHS))
3384 if (C->getValue() == 2)
3410 if (!isValueAvailable(II))
3416 for (
auto Itr = std::prev(Start); Itr != End; --Itr) {
3419 if (!isa<ExtractValueInst>(Itr))
3423 const auto *EVI = cast<ExtractValueInst>(Itr);
3424 if (EVI->getAggregateOperand() != II)
3432 bool AArch64FastISel::fastLowerIntrinsicCall(
const IntrinsicInst *II) {
3435 default:
return false;
3442 unsigned SrcReg =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3443 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3444 TII.get(TargetOpcode::COPY), SrcReg).addReg(FramePtr);
3451 unsigned Depth = cast<ConstantInt>(II->
getOperand(0))->getZExtValue();
3453 DestReg = fastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,
3455 assert(DestReg &&
"Unexpected LDR instruction emission failure.");
3459 updateValueMap(II, SrcReg);
3467 unsigned ResultReg = createResultReg(&AArch64::GPR64spRegClass);
3468 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3469 TII.get(AArch64::ADDXri), ResultReg)
3474 updateValueMap(II, ResultReg);
3479 const auto *MTI = cast<MemTransferInst>(II);
3481 if (MTI->isVolatile())
3487 if (isa<ConstantInt>(MTI->getLength()) && IsMemCpy) {
3490 uint64_t Len = cast<ConstantInt>(MTI->getLength())->getZExtValue();
3491 unsigned Alignment =
MinAlign(MTI->getDestAlignment(),
3492 MTI->getSourceAlignment());
3493 if (isMemCpySmall(Len, Alignment)) {
3495 if (!computeAddress(MTI->getRawDest(), Dest) ||
3496 !computeAddress(MTI->getRawSource(), Src))
3498 if (tryEmitSmallMemCpy(Dest, Src, Len, Alignment))
3503 if (!MTI->getLength()->getType()->isIntegerTy(64))
3506 if (MTI->getSourceAddressSpace() > 255 || MTI->getDestAddressSpace() > 255)
3511 const char *IntrMemName = isa<MemCpyInst>(II) ?
"memcpy" :
"memmove";
3515 const MemSetInst *MSI = cast<MemSetInst>(II);
3534 if (!isTypeLegal(II->
getType(), RetVT))
3541 { RTLIB::SIN_F32, RTLIB::SIN_F64 },
3542 { RTLIB::COS_F32, RTLIB::COS_F64 },
3543 { RTLIB::POW_F32, RTLIB::POW_F64 }
3551 LC = LibCallTable[0][Is64Bit];
3554 LC = LibCallTable[1][Is64Bit];
3557 LC = LibCallTable[2][Is64Bit];
3569 Args.push_back(Entry);
3572 CallLoweringInfo CLI;
3574 CLI.setCallee(DL, Ctx, TLI.getLibcallCallingConv(LC), II->
getType(),
3575 TLI.getLibcallName(LC), std::move(Args));
3576 if (!lowerCallTo(CLI))
3578 updateValueMap(II, CLI.ResultReg);
3583 if (!isTypeLegal(II->
getType(), VT))
3591 Opc = AArch64::FABSSr;
3594 Opc = AArch64::FABSDr;
3597 unsigned SrcReg = getRegForValue(II->
getOperand(0));
3600 bool SrcRegIsKill = hasTrivialKill(II->
getOperand(0));
3601 unsigned ResultReg = createResultReg(TLI.getRegClassFor(VT));
3602 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
3604 updateValueMap(II, ResultReg);
3608 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AArch64::BRK))
3616 if (!isTypeLegal(RetTy, VT))
3619 unsigned Op0Reg = getRegForValue(II->
getOperand(0));
3622 bool Op0IsKill = hasTrivialKill(II->
getOperand(0));
3624 unsigned ResultReg = fastEmit_r(VT, VT,
ISD::FSQRT, Op0Reg, Op0IsKill);
3628 updateValueMap(II, ResultReg);
3640 Type *RetTy = Ty->getTypeAtIndex(0U);
3643 if (!isTypeLegal(RetTy, VT))
3652 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS) &&
3653 isCommutativeIntrinsic(II))
3662 if (
const auto *C = dyn_cast<ConstantInt>(RHS))
3663 if (C->getValue() == 2) {
3669 if (
const auto *C = dyn_cast<ConstantInt>(RHS))
3670 if (C->getValue() == 2) {
3677 unsigned ResultReg1 = 0, ResultReg2 = 0, MulReg = 0;
3682 ResultReg1 = emitAdd(VT, LHS, RHS,
true);
3686 ResultReg1 = emitAdd(VT, LHS, RHS,
true);
3690 ResultReg1 = emitSub(VT, LHS, RHS,
true);
3694 ResultReg1 = emitSub(VT, LHS, RHS,
true);
3699 unsigned LHSReg = getRegForValue(LHS);
3702 bool LHSIsKill = hasTrivialKill(LHS);
3704 unsigned RHSReg = getRegForValue(RHS);
3707 bool RHSIsKill = hasTrivialKill(RHS);
3710 MulReg = emitSMULL_rr(
MVT::i64, LHSReg, LHSIsKill, RHSReg, RHSIsKill);
3713 MulReg = fastEmitInst_extractsubreg(VT, MulReg,
true,
3715 ShiftReg = fastEmitInst_extractsubreg(VT, ShiftReg,
true,
3717 emitSubs_rs(VT, ShiftReg,
true, MulReg,
false,
3723 MulReg = emitMul_rr(VT, LHSReg,
false, RHSReg,
3725 unsigned SMULHReg = fastEmit_rr(VT, VT,
ISD::MULHS, LHSReg, LHSIsKill,
3727 emitSubs_rs(VT, SMULHReg,
true, MulReg,
false,
3734 unsigned LHSReg = getRegForValue(LHS);
3737 bool LHSIsKill = hasTrivialKill(LHS);
3739 unsigned RHSReg = getRegForValue(RHS);
3742 bool RHSIsKill = hasTrivialKill(RHS);
3745 MulReg = emitUMULL_rr(
MVT::i64, LHSReg, LHSIsKill, RHSReg, RHSIsKill);
3746 emitSubs_rs(
MVT::i64, AArch64::XZR,
true, MulReg,
3749 MulReg = fastEmitInst_extractsubreg(VT, MulReg,
true,
3755 MulReg = emitMul_rr(VT, LHSReg,
false, RHSReg,
3757 unsigned UMULHReg = fastEmit_rr(VT, VT,
ISD::MULHU, LHSReg, LHSIsKill,
3759 emitSubs_rr(VT, AArch64::XZR,
true, UMULHReg,
3767 ResultReg1 = createResultReg(TLI.getRegClassFor(VT));
3768 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3769 TII.get(TargetOpcode::COPY), ResultReg1).addReg(MulReg);
3775 ResultReg2 = fastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,
3776 AArch64::WZR,
true, AArch64::WZR,
3779 assert((ResultReg1 + 1) == ResultReg2 &&
3780 "Nonconsecutive result registers.");
3781 updateValueMap(II, ResultReg1, 2);
3788 bool AArch64FastISel::selectRet(
const Instruction *I) {
3792 if (!FuncInfo.CanLowerReturn)
3798 if (TLI.supportSwiftError() &&
3802 if (TLI.supportSplitCSR(FuncInfo.MF))
3811 GetReturnInfo(CC, F.getReturnType(), F.getAttributes(), Outs, TLI, DL);
3817 : RetCC_AArch64_AAPCS;
3818 CCInfo.AnalyzeReturn(Outs, RetCC);
3821 if (ValLocs.size() != 1)
3836 unsigned Reg = getRegForValue(RV);
3840 unsigned SrcReg = Reg + VA.
getValNo();
3843 if (!
MRI.getRegClass(SrcReg)->contains(DestReg))
3846 EVT RVEVT = TLI.getValueType(DL, RV->
getType());
3861 if (RVVT != DestVT) {
3865 if (!Outs[0].Flags.isZExt() && !Outs[0].Flags.isSExt())
3868 bool IsZExt = Outs[0].Flags.isZExt();
3869 SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
3875 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3876 TII.get(TargetOpcode::COPY), DestReg).addReg(SrcReg);
3883 TII.get(AArch64::RET_ReallyLR));
3884 for (
unsigned RetReg : RetRegs)
3889 bool AArch64FastISel::selectTrunc(
const Instruction *I) {
3894 EVT SrcEVT = TLI.getValueType(DL, SrcTy,
true);
3895 EVT DestEVT = TLI.getValueType(DL, DestTy,
true);
3911 unsigned SrcReg = getRegForValue(Op);
3914 bool SrcIsKill = hasTrivialKill(Op);
3939 unsigned Reg32 = fastEmitInst_extractsubreg(
MVT::i32, SrcReg, SrcIsKill,
3942 ResultReg = emitAnd_ri(
MVT::i32, Reg32,
true, Mask);
3943 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
3945 ResultReg = createResultReg(&AArch64::GPR32RegClass);
3946 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3947 TII.get(TargetOpcode::COPY), ResultReg)
3951 updateValueMap(I, ResultReg);
3955 unsigned AArch64FastISel::emiti1Ext(
unsigned SrcReg,
MVT DestVT,
bool IsZExt) {
3958 "Unexpected value type.");
3964 unsigned ResultReg = emitAnd_ri(
MVT::i32, SrcReg,
false, 1);
3965 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
3969 unsigned Reg64 =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3970 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3971 TII.get(AArch64::SUBREG_TO_REG), Reg64)
3974 .
addImm(AArch64::sub_32);
3983 return fastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,
3988 unsigned AArch64FastISel::emitMul_rr(
MVT RetVT,
unsigned Op0,
bool Op0IsKill,
3989 unsigned Op1,
bool Op1IsKill) {
3997 Opc = AArch64::MADDWrrr; ZReg = AArch64::WZR;
break;
3999 Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR;
break;
4003 (RetVT ==
MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4004 return fastEmitInst_rrr(Opc, RC, Op0, Op0IsKill, Op1, Op1IsKill,
4008 unsigned AArch64FastISel::emitSMULL_rr(
MVT RetVT,
unsigned Op0,
bool Op0IsKill,
4009 unsigned Op1,
bool Op1IsKill) {
4013 return fastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,
4014 Op0, Op0IsKill, Op1, Op1IsKill,
4015 AArch64::XZR,
true);
4018 unsigned AArch64FastISel::emitUMULL_rr(
MVT RetVT,
unsigned Op0,
bool Op0IsKill,
4019 unsigned Op1,
bool Op1IsKill) {
4023 return fastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,
4024 Op0, Op0IsKill, Op1, Op1IsKill,
4025 AArch64::XZR,
true);
4028 unsigned AArch64FastISel::emitLSL_rr(
MVT RetVT,
unsigned Op0Reg,
bool Op0IsKill,
4029 unsigned Op1Reg,
bool Op1IsKill) {
4031 bool NeedTrunc =
false;
4035 case MVT::i8: Opc = AArch64::LSLVWr; NeedTrunc =
true; Mask = 0xff;
break;
4036 case MVT::i16: Opc = AArch64::LSLVWr; NeedTrunc =
true; Mask = 0xffff;
break;
4037 case MVT::i32: Opc = AArch64::LSLVWr;
break;
4038 case MVT::i64: Opc = AArch64::LSLVXr;
break;
4042 (RetVT ==
MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4044 Op1Reg = emitAnd_ri(
MVT::i32, Op1Reg, Op1IsKill, Mask);
4047 unsigned ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op0IsKill, Op1Reg,
4050 ResultReg = emitAnd_ri(
MVT::i32, ResultReg,
true, Mask);
4054 unsigned AArch64FastISel::emitLSL_ri(
MVT RetVT,
MVT SrcVT,
unsigned Op0,
4055 bool Op0IsKill, uint64_t Shift,
4058 "Unexpected source/return type pair.");
4061 "Unexpected source value type.");
4063 RetVT ==
MVT::i64) &&
"Unexpected return value type.");
4065 bool Is64Bit = (RetVT ==
MVT::i64);
4066 unsigned RegSize = Is64Bit ? 64 : 32;
4070 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4074 if (RetVT == SrcVT) {
4075 unsigned ResultReg = createResultReg(RC);
4076 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4077 TII.get(TargetOpcode::COPY), ResultReg)
4081 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4085 if (Shift >= DstBits)
4113 unsigned ImmR = RegSize - Shift;
4115 unsigned ImmS = std::min<unsigned>(SrcBits - 1, DstBits - 1 - Shift);
4116 static const unsigned OpcTable[2][2] = {
4117 {AArch64::SBFMWri, AArch64::SBFMXri},
4118 {AArch64::UBFMWri, AArch64::UBFMXri}
4120 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4122 unsigned TmpReg =
MRI.createVirtualRegister(RC);
4123 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4124 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4127 .
addImm(AArch64::sub_32);
4131 return fastEmitInst_rii(Opc, RC, Op0, Op0IsKill, ImmR, ImmS);
4134 unsigned AArch64FastISel::emitLSR_rr(
MVT RetVT,
unsigned Op0Reg,
bool Op0IsKill,
4135 unsigned Op1Reg,
bool Op1IsKill) {
4137 bool NeedTrunc =
false;
4141 case MVT::i8: Opc = AArch64::LSRVWr; NeedTrunc =
true; Mask = 0xff;
break;
4142 case MVT::i16: Opc = AArch64::LSRVWr; NeedTrunc =
true; Mask = 0xffff;
break;
4143 case MVT::i32: Opc = AArch64::LSRVWr;
break;
4144 case MVT::i64: Opc = AArch64::LSRVXr;
break;
4148 (RetVT ==
MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4150 Op0Reg = emitAnd_ri(
MVT::i32, Op0Reg, Op0IsKill, Mask);
4151 Op1Reg = emitAnd_ri(
MVT::i32, Op1Reg, Op1IsKill, Mask);
4152 Op0IsKill = Op1IsKill =
true;
4154 unsigned ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op0IsKill, Op1Reg,
4157 ResultReg = emitAnd_ri(
MVT::i32, ResultReg,
true, Mask);
4161 unsigned AArch64FastISel::emitLSR_ri(
MVT RetVT,
MVT SrcVT,
unsigned Op0,
4162 bool Op0IsKill, uint64_t Shift,
4165 "Unexpected source/return type pair.");
4168 "Unexpected source value type.");
4170 RetVT ==
MVT::i64) &&
"Unexpected return value type.");
4172 bool Is64Bit = (RetVT ==
MVT::i64);
4173 unsigned RegSize = Is64Bit ? 64 : 32;
4177 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4181 if (RetVT == SrcVT) {
4182 unsigned ResultReg = createResultReg(RC);
4183 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4184 TII.get(TargetOpcode::COPY), ResultReg)
4188 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4192 if (Shift >= DstBits)
4220 if (Shift >= SrcBits && IsZExt)
4226 Op0 = emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4235 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4236 unsigned ImmS = SrcBits - 1;
4237 static const unsigned OpcTable[2][2] = {
4238 {AArch64::SBFMWri, AArch64::SBFMXri},
4239 {AArch64::UBFMWri, AArch64::UBFMXri}
4241 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4243 unsigned TmpReg =
MRI.createVirtualRegister(RC);
4244 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4245 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4248 .
addImm(AArch64::sub_32);
4252 return fastEmitInst_rii(Opc, RC, Op0, Op0IsKill, ImmR, ImmS);
4255 unsigned AArch64FastISel::emitASR_rr(
MVT RetVT,
unsigned Op0Reg,
bool Op0IsKill,
4256 unsigned Op1Reg,
bool Op1IsKill) {
4258 bool NeedTrunc =
false;
4262 case MVT::i8: Opc = AArch64::ASRVWr; NeedTrunc =
true; Mask = 0xff;
break;
4263 case MVT::i16: Opc = AArch64::ASRVWr; NeedTrunc =
true; Mask = 0xffff;
break;
4264 case MVT::i32: Opc = AArch64::ASRVWr;
break;
4265 case MVT::i64: Opc = AArch64::ASRVXr;
break;
4269 (RetVT ==
MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4271 Op0Reg = emitIntExt(RetVT, Op0Reg,
MVT::i32,
false);
4272 Op1Reg = emitAnd_ri(
MVT::i32, Op1Reg, Op1IsKill, Mask);
4273 Op0IsKill = Op1IsKill =
true;
4275 unsigned ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op0IsKill, Op1Reg,
4278 ResultReg = emitAnd_ri(
MVT::i32, ResultReg,
true, Mask);
4282 unsigned AArch64FastISel::emitASR_ri(
MVT RetVT,
MVT SrcVT,
unsigned Op0,
4283 bool Op0IsKill, uint64_t Shift,
4286 "Unexpected source/return type pair.");
4289 "Unexpected source value type.");
4291 RetVT ==
MVT::i64) &&
"Unexpected return value type.");
4293 bool Is64Bit = (RetVT ==
MVT::i64);
4294 unsigned RegSize = Is64Bit ? 64 : 32;
4298 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4302 if (RetVT == SrcVT) {
4303 unsigned ResultReg = createResultReg(RC);
4304 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4305 TII.get(TargetOpcode::COPY), ResultReg)
4309 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4313 if (Shift >= DstBits)
4341 if (Shift >= SrcBits && IsZExt)
4344 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4345 unsigned ImmS = SrcBits - 1;
4346 static const unsigned OpcTable[2][2] = {
4347 {AArch64::SBFMWri, AArch64::SBFMXri},
4348 {AArch64::UBFMWri, AArch64::UBFMXri}
4350 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4352 unsigned TmpReg =
MRI.createVirtualRegister(RC);
4353 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4354 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4357 .
addImm(AArch64::sub_32);
4361 return fastEmitInst_rii(Opc, RC, Op0, Op0IsKill, ImmR, ImmS);
4364 unsigned AArch64FastISel::emitIntExt(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
4385 return emiti1Ext(SrcReg, DestVT, IsZExt);
4388 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4390 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4395 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4397 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4402 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4411 unsigned Src64 =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4412 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4413 TII.get(AArch64::SUBREG_TO_REG), Src64)
4416 .
addImm(AArch64::sub_32);
4421 (DestVT ==
MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4422 return fastEmitInst_rii(Opc, RC, SrcReg,
false, 0, Imm);
4429 case AArch64::LDURBBi:
4430 case AArch64::LDURHHi:
4431 case AArch64::LDURWi:
4432 case AArch64::LDRBBui:
4433 case AArch64::LDRHHui:
4434 case AArch64::LDRWui:
4435 case AArch64::LDRBBroX:
4436 case AArch64::LDRHHroX:
4437 case AArch64::LDRWroX:
4438 case AArch64::LDRBBroW:
4439 case AArch64::LDRHHroW:
4440 case AArch64::LDRWroW:
4449 case AArch64::LDURSBWi:
4450 case AArch64::LDURSHWi:
4451 case AArch64::LDURSBXi:
4452 case AArch64::LDURSHXi:
4453 case AArch64::LDURSWi:
4454 case AArch64::LDRSBWui:
4455 case AArch64::LDRSHWui:
4456 case AArch64::LDRSBXui:
4457 case AArch64::LDRSHXui:
4458 case AArch64::LDRSWui:
4459 case AArch64::LDRSBWroX:
4460 case AArch64::LDRSHWroX:
4461 case AArch64::LDRSBXroX:
4462 case AArch64::LDRSHXroX:
4463 case AArch64::LDRSWroX:
4464 case AArch64::LDRSBWroW:
4465 case AArch64::LDRSHWroW:
4466 case AArch64::LDRSBXroW:
4467 case AArch64::LDRSHXroW:
4468 case AArch64::LDRSWroW:
4473 bool AArch64FastISel::optimizeIntExtLoad(
const Instruction *I,
MVT RetVT,
4476 if (!LI || !LI->hasOneUse())
4480 unsigned Reg = lookUpRegForValue(LI);
4490 bool IsZExt = isa<ZExtInst>(
I);
4491 const auto *LoadMI =
MI;
4492 if (LoadMI->getOpcode() == TargetOpcode::COPY &&
4493 LoadMI->getOperand(1).getSubReg() == AArch64::sub_32) {
4495 LoadMI =
MRI.getUniqueVRegDef(LoadReg);
4496 assert(LoadMI &&
"Expected valid instruction");
4503 updateValueMap(I, Reg);
4508 unsigned Reg64 = createResultReg(&AArch64::GPR64RegClass);
4509 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4510 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4513 .
addImm(AArch64::sub_32);
4518 "Expected copy instruction");
4521 removeDeadCode(I, std::next(I));
4523 updateValueMap(I, Reg);
4527 bool AArch64FastISel::selectIntExt(
const Instruction *I) {
4528 assert((isa<ZExtInst>(I) || isa<SExtInst>(I)) &&
4529 "Unexpected integer extend instruction.");
4532 if (!isTypeSupported(I->
getType(), RetVT))
4539 if (optimizeIntExtLoad(I, RetVT, SrcVT))
4542 unsigned SrcReg = getRegForValue(I->
getOperand(0));
4545 bool SrcIsKill = hasTrivialKill(I->
getOperand(0));
4548 bool IsZExt = isa<ZExtInst>(
I);
4549 if (
const auto *
Arg = dyn_cast<Argument>(I->
getOperand(0))) {
4550 if ((IsZExt &&
Arg->hasZExtAttr()) || (!IsZExt &&
Arg->hasSExtAttr())) {
4552 unsigned ResultReg = createResultReg(&AArch64::GPR64RegClass);
4553 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4554 TII.get(AArch64::SUBREG_TO_REG), ResultReg)
4557 .
addImm(AArch64::sub_32);
4564 unsigned UseReg = lookUpRegForValue(I);
4566 MRI.clearKillFlags(UseReg);
4568 updateValueMap(I, SrcReg);
4573 unsigned ResultReg = emitIntExt(SrcVT, SrcReg, RetVT, IsZExt);
4577 updateValueMap(I, ResultReg);
4581 bool AArch64FastISel::selectRem(
const Instruction *I,
unsigned ISDOpcode) {
4582 EVT DestEVT = TLI.getValueType(DL, I->
getType(),
true);
4591 bool Is64bit = (DestVT ==
MVT::i64);
4592 switch (ISDOpcode) {
4596 DivOpc = Is64bit ? AArch64::SDIVXr : AArch64::SDIVWr;
4599 DivOpc = Is64bit ? AArch64::UDIVXr : AArch64::UDIVWr;
4602 unsigned MSubOpc = Is64bit ? AArch64::MSUBXrrr : AArch64::MSUBWrrr;
4603 unsigned Src0Reg = getRegForValue(I->
getOperand(0));
4606 bool Src0IsKill = hasTrivialKill(I->
getOperand(0));
4608 unsigned Src1Reg = getRegForValue(I->
getOperand(1));
4611 bool Src1IsKill = hasTrivialKill(I->
getOperand(1));
4614 (DestVT ==
MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4615 unsigned QuotReg = fastEmitInst_rr(DivOpc, RC, Src0Reg,
false,
4617 assert(QuotReg &&
"Unexpected DIV instruction emission failure.");
4620 unsigned ResultReg = fastEmitInst_rrr(MSubOpc, RC, QuotReg,
true,
4621 Src1Reg, Src1IsKill, Src0Reg,
4623 updateValueMap(I, ResultReg);
4627 bool AArch64FastISel::selectMul(
const Instruction *I) {
4629 if (!isTypeSupported(I->
getType(), VT,
true))
4637 if (
const auto *C = dyn_cast<ConstantInt>(Src0))
4638 if (C->getValue().isPowerOf2())
4642 if (
const auto *C = dyn_cast<ConstantInt>(Src1))
4643 if (C->getValue().isPowerOf2()) {
4644 uint64_t ShiftVal = C->getValue().logBase2();
4647 if (
const auto *ZExt = dyn_cast<ZExtInst>(Src0)) {
4650 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), VT)) {
4653 Src0 = ZExt->getOperand(0);
4656 }
else if (
const auto *SExt = dyn_cast<SExtInst>(Src0)) {
4659 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), VT)) {
4662 Src0 = SExt->getOperand(0);
4667 unsigned Src0Reg = getRegForValue(Src0);
4670 bool Src0IsKill = hasTrivialKill(Src0);
4672 unsigned ResultReg =
4673 emitLSL_ri(VT, SrcVT, Src0Reg, Src0IsKill, ShiftVal, IsZExt);
4676 updateValueMap(I, ResultReg);
4681 unsigned Src0Reg = getRegForValue(I->
getOperand(0));
4684 bool Src0IsKill = hasTrivialKill(I->
getOperand(0));
4686 unsigned Src1Reg = getRegForValue(I->
getOperand(1));
4689 bool Src1IsKill = hasTrivialKill(I->
getOperand(1));
4691 unsigned ResultReg = emitMul_rr(VT, Src0Reg, Src0IsKill, Src1Reg, Src1IsKill);
4696 updateValueMap(I, ResultReg);
4700 bool AArch64FastISel::selectShift(
const Instruction *I) {
4702 if (!isTypeSupported(I->
getType(), RetVT,
true))
4706 return selectOperator(I, I->
getOpcode());
4708 if (
const auto *C = dyn_cast<ConstantInt>(I->
getOperand(1))) {
4709 unsigned ResultReg = 0;
4710 uint64_t ShiftVal = C->getZExtValue();
4712 bool IsZExt = I->
getOpcode() != Instruction::AShr;
4714 if (
const auto *ZExt = dyn_cast<ZExtInst>(Op0)) {
4717 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), TmpVT)) {
4720 Op0 = ZExt->getOperand(0);
4723 }
else if (
const auto *SExt = dyn_cast<SExtInst>(Op0)) {
4726 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), TmpVT)) {
4729 Op0 = SExt->getOperand(0);
4734 unsigned Op0Reg = getRegForValue(Op0);
4737 bool Op0IsKill = hasTrivialKill(Op0);
4741 case Instruction::Shl:
4742 ResultReg = emitLSL_ri(RetVT, SrcVT, Op0Reg, Op0IsKill, ShiftVal, IsZExt);
4744 case Instruction::AShr:
4745 ResultReg = emitASR_ri(RetVT, SrcVT, Op0Reg, Op0IsKill, ShiftVal, IsZExt);
4747 case Instruction::LShr:
4748 ResultReg = emitLSR_ri(RetVT, SrcVT, Op0Reg, Op0IsKill, ShiftVal, IsZExt);
4754 updateValueMap(I, ResultReg);
4758 unsigned Op0Reg = getRegForValue(I->
getOperand(0));
4761 bool Op0IsKill = hasTrivialKill(I->
getOperand(0));
4763 unsigned Op1Reg = getRegForValue(I->
getOperand(1));
4766 bool Op1IsKill = hasTrivialKill(I->
getOperand(1));
4768 unsigned ResultReg = 0;
4771 case Instruction::Shl:
4772 ResultReg = emitLSL_rr(RetVT, Op0Reg, Op0IsKill, Op1Reg, Op1IsKill);
4774 case Instruction::AShr:
4775 ResultReg = emitASR_rr(RetVT, Op0Reg, Op0IsKill, Op1Reg, Op1IsKill);
4777 case Instruction::LShr:
4778 ResultReg = emitLSR_rr(RetVT, Op0Reg, Op0IsKill, Op1Reg, Op1IsKill);
4785 updateValueMap(I, ResultReg);
4789 bool AArch64FastISel::selectBitCast(
const Instruction *I) {
4794 if (!isTypeLegal(I->
getType(), RetVT))
4799 Opc = AArch64::FMOVWSr;
4801 Opc = AArch64::FMOVXDr;
4803 Opc = AArch64::FMOVSWr;
4805 Opc = AArch64::FMOVDXr;
4812 case MVT::i32: RC = &AArch64::GPR32RegClass;
break;
4813 case MVT::i64: RC = &AArch64::GPR64RegClass;
break;
4814 case MVT::f32: RC = &AArch64::FPR32RegClass;
break;
4815 case MVT::f64: RC = &AArch64::FPR64RegClass;
break;
4817 unsigned Op0Reg = getRegForValue(I->
getOperand(0));
4820 bool Op0IsKill = hasTrivialKill(I->
getOperand(0));
4821 unsigned ResultReg = fastEmitInst_r(Opc, RC, Op0Reg, Op0IsKill);
4826 updateValueMap(I, ResultReg);
4830 bool AArch64FastISel::selectFRem(
const Instruction *I) {
4832 if (!isTypeLegal(I->
getType(), RetVT))
4840 LC = RTLIB::REM_F32;
4843 LC = RTLIB::REM_F64;
4855 Args.push_back(Entry);
4858 CallLoweringInfo CLI;
4860 CLI.setCallee(DL, Ctx, TLI.getLibcallCallingConv(LC), I->
getType(),
4861 TLI.getLibcallName(LC), std::move(Args));
4862 if (!lowerCallTo(CLI))
4864 updateValueMap(I, CLI.ResultReg);
4868 bool AArch64FastISel::selectSDiv(
const Instruction *I) {
4870 if (!isTypeLegal(I->
getType(), VT))
4882 unsigned Src0Reg = getRegForValue(I->
getOperand(0));
4885 bool Src0IsKill = hasTrivialKill(I->
getOperand(0));
4887 if (cast<BinaryOperator>(I)->isExact()) {
4888 unsigned ResultReg = emitASR_ri(VT, VT, Src0Reg, Src0IsKill, Lg2);
4891 updateValueMap(I, ResultReg);
4895 int64_t Pow2MinusOne = (1ULL << Lg2) - 1;
4896 unsigned AddReg = emitAdd_ri_(VT, Src0Reg,
false, Pow2MinusOne);
4901 if (!emitICmp_ri(VT, Src0Reg,
false, 0))
4907 SelectOpc = AArch64::CSELXr;
4908 RC = &AArch64::GPR64RegClass;
4910 SelectOpc = AArch64::CSELWr;
4911 RC = &AArch64::GPR32RegClass;
4913 unsigned SelectReg =
4914 fastEmitInst_rri(SelectOpc, RC, AddReg,
true, Src0Reg,
4921 unsigned ZeroReg = (VT ==
MVT::i64) ? AArch64::XZR : AArch64::WZR;
4924 ResultReg = emitAddSub_rs(
false, VT, ZeroReg,
true,
4927 ResultReg = emitASR_ri(VT, VT, SelectReg,
true, Lg2);
4932 updateValueMap(I, ResultReg);
4939 std::pair<unsigned, bool> AArch64FastISel::getRegForGEPIndex(
const Value *Idx) {
4940 unsigned IdxN = getRegForValue(Idx);
4943 return std::pair<unsigned, bool>(0,
false);
4945 bool IdxNIsKill = hasTrivialKill(Idx);
4948 MVT PtrVT = TLI.getPointerTy(DL);
4950 if (IdxVT.
bitsLT(PtrVT)) {
4951 IdxN = emitIntExt(IdxVT.
getSimpleVT(), IdxN, PtrVT,
false);
4953 }
else if (IdxVT.
bitsGT(PtrVT))
4954 llvm_unreachable(
"AArch64 FastISel doesn't support types larger than i64");
4955 return std::pair<unsigned, bool>(IdxN, IdxNIsKill);
4962 bool AArch64FastISel::selectGetElementPtr(
const Instruction *I) {
4966 bool NIsKill = hasTrivialKill(I->
getOperand(0));
4970 uint64_t TotalOffs = 0;
4971 MVT VT = TLI.getPointerTy(DL);
4974 const Value *Idx = GTI.getOperand();
4975 if (
auto *StTy = GTI.getStructTypeOrNull()) {
4976 unsigned Field = cast<ConstantInt>(Idx)->getZExtValue();
4979 TotalOffs += DL.getStructLayout(StTy)->getElementOffset(Field);
4981 Type *Ty = GTI.getIndexedType();
4984 if (
const auto *CI = dyn_cast<ConstantInt>(Idx)) {
4989 DL.getTypeAllocSize(Ty) * cast<ConstantInt>(CI)->getSExtValue();
4993 N = emitAdd_ri_(VT, N, NIsKill, TotalOffs);
5001 uint64_t ElementSize = DL.getTypeAllocSize(Ty);
5002 std::pair<unsigned, bool> Pair = getRegForGEPIndex(Idx);
5003 unsigned IdxN = Pair.first;
5004 bool IdxNIsKill = Pair.second;
5008 if (ElementSize != 1) {
5009 unsigned C = fastEmit_i(VT, VT,
ISD::Constant, ElementSize);
5012 IdxN = emitMul_rr(VT, IdxN, IdxNIsKill, C,
true);
5017 N = fastEmit_rr(VT, VT,
ISD::ADD, N, NIsKill, IdxN, IdxNIsKill);
5023 N = emitAdd_ri_(VT, N, NIsKill, TotalOffs);
5027 updateValueMap(I, N);
5033 "cmpxchg survived AtomicExpand at optlevel > -O0");
5035 auto *RetPairTy = cast<StructType>(I->
getType());
5036 Type *RetTy = RetPairTy->getTypeAtIndex(0U);
5037 assert(RetPairTy->getTypeAtIndex(1U)->isIntegerTy(1) &&
5038 "cmpxchg has a non-i1 status result");
5041 if (!isTypeLegal(RetTy, VT))
5045 unsigned Opc, CmpOpc;
5049 Opc = AArch64::CMP_SWAP_32;
5050 CmpOpc = AArch64::SUBSWrs;
5051 ResRC = &AArch64::GPR32RegClass;
5053 Opc = AArch64::CMP_SWAP_64;
5054 CmpOpc = AArch64::SUBSXrs;
5055 ResRC = &AArch64::GPR64RegClass;
5069 const unsigned ResultReg1 = createResultReg(ResRC);
5070 const unsigned ResultReg2 = createResultReg(&AArch64::GPR32RegClass);
5071 const unsigned ScratchReg = createResultReg(&AArch64::GPR32RegClass);
5074 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
5081 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(CmpOpc))
5082 .addDef(VT ==
MVT::i32 ? AArch64::WZR : AArch64::XZR)
5087 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(AArch64::CSINCWr))
5093 assert((ResultReg1 + 1) == ResultReg2 &&
"Nonconsecutive result registers.");
5094 updateValueMap(I, ResultReg1, 2);
5098 bool AArch64FastISel::fastSelectInstruction(
const Instruction *I) {
5103 case Instruction::Sub:
5104 return selectAddSub(I);
5105 case Instruction::Mul:
5106 return selectMul(I);
5107 case Instruction::SDiv:
5108 return selectSDiv(I);
5109 case Instruction::SRem:
5113 case Instruction::URem:
5117 case Instruction::Shl:
5118 case Instruction::LShr:
5119 case Instruction::AShr:
5120 return selectShift(I);
5121 case Instruction::And:
5122 case Instruction::Or:
5123 case Instruction::Xor:
5124 return selectLogicalOp(I);
5125 case Instruction::Br:
5126 return selectBranch(I);
5127 case Instruction::IndirectBr:
5128 return selectIndirectBr(I);
5129 case Instruction::BitCast:
5131 return selectBitCast(I);
5133 case Instruction::FPToSI:
5135 return selectFPToInt(I,
true);
5137 case Instruction::FPToUI:
5138 return selectFPToInt(I,
false);
5139 case Instruction::ZExt:
5140 case Instruction::SExt:
5141 return selectIntExt(I);
5142 case Instruction::Trunc:
5144 return selectTrunc(I);
5146 case Instruction::FPExt:
5147 return selectFPExt(I);
5148 case Instruction::FPTrunc:
5149 return selectFPTrunc(I);
5150 case Instruction::SIToFP:
5152 return selectIntToFP(I,
true);
5154 case Instruction::UIToFP:
5155 return selectIntToFP(I,
false);
5157 return selectLoad(I);
5159 return selectStore(I);
5160 case Instruction::FCmp:
5161 case Instruction::ICmp:
5162 return selectCmp(I);
5164 return selectSelect(I);
5166 return selectRet(I);
5167 case Instruction::FRem:
5168 return selectFRem(I);
5169 case Instruction::GetElementPtr:
5170 return selectGetElementPtr(I);
5171 case Instruction::AtomicCmpXchg:
5172 return selectAtomicCmpXchg(cast<AtomicCmpXchgInst>(I));
5176 (void)&CC_AArch64_DarwinPCS_VarArg;
5177 (void)&CC_AArch64_Win64_VarArg;
5180 return selectOperator(I, I->
getOpcode());
5187 return new AArch64FastISel(FuncInfo, LibInfo);
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
void setFrameAddressIsTaken(bool T)
Return a value (possibly void), from a function.
static MVT getIntegerVT(unsigned BitWidth)
void AnalyzeCallResult(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeCallResult - Analyze the return values of a call, incorporating info about the passed values i...
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
This class is the base class for the comparison instructions.
C - The default llvm calling convention, compatible with C.
bool isLittleEndian() const
uint64_t getZExtValue() const
Get zero extended value.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
This class represents an incoming formal argument to a Function.
Atomic ordering constants.
This class represents lattice values for constants.
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
bool hasCustomCallingConv() const
bool isSized(SmallPtrSetImpl< Type *> *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
an instruction that atomically checks whether a specified value is in a memory location, and, if it is, stores a new value there.
bool isVector() const
Return true if this is a vector value type.
void push_back(const T &Elt)
static CondCode getInvertedCondCode(CondCode Code)
Describe properties that are true of each instruction in the target description file.
unsigned getReg() const
getReg - Returns the register number.
unsigned char ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const
ClassifyGlobalReference - Find the target operand flags that describe how a global value should be re...
unsigned getSubReg() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Libcall
RTLIB::Libcall enum - This enum defines all of the runtime library calls the backend can emit...
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change...
gep_type_iterator gep_type_end(const User *GEP)
const Value * getTrueValue() const
0 1 0 0 True if ordered and less than
unsigned getValNo() const
LLVMContext & getContext() const
All values hold a context through their type.
1 1 1 0 True if unordered or not equal
This class wraps the llvm.memset intrinsic.
BasicBlock * getSuccessor(unsigned i) const
Value * getNewValOperand()
unsigned const TargetRegisterInfo * TRI
block Block Frequency true
An instruction for reading from memory.
Value * getCondition() const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
bool isVectorTy() const
True if this is an instance of VectorType.
void reserve(size_type N)
Value * getLength() const
bool isAnyArgRegReserved(const MachineFunction &MF) const
unsigned getFrameRegister(const MachineFunction &MF) const override
Value * getArgOperand(unsigned i) const
1 0 0 1 True if unordered or equal
unsigned countTrailingZeros() const
Count the number of trailing zero bits.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
A description of a memory reference used in the backend.
bool isTargetDarwin() const
This class represents the LLVM 'select' instruction.
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
const HexagonInstrInfo * TII
PointerType * getType() const
Overload to return most specific pointer type.
Class to represent struct types.
const MachineInstrBuilder & addUse(unsigned RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
bool isIntegerTy() const
True if this is an instance of IntegerType.
0 1 0 1 True if ordered and less than or equal
This file contains the simple types necessary to represent the attributes associated with functions a...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool isTargetMachO() const
unsigned getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
LocInfo getLocInfo() const
This file implements a class to represent arbitrary precision integral constant values and operations...
bool is64BitVector() const
Return true if this is a 64-bit vector type.
AtomicOrdering
Atomic ordering for LLVM's memory model.
unsigned getSizeInBits() const
Context object for machine code objects.
Value * getPointerOperand()
bool isOne() const
This is just a convenience method to make client code smaller for a common case.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
A constant value that is initialized with an expression using other constant values.
iterator_range< succ_op_iterator > successors()
unsigned getNextStackOffset() const
getNextStackOffset - Return the next stack offset such that all stack slots satisfy their alignment r...
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Type * getType() const
All values are typed, get the type of this value.
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
const AArch64RegisterInfo * getRegisterInfo() const override
static bool isZExtLoad(const MachineInstr *LI)
bool isNegative() const
Return true if the sign bit is set.
Simple integer binary arithmetic operators.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
iterator_range< User::op_iterator > arg_operands()
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
amdgpu Simplify well known AMD library false Value * Callee
Value * getOperand(unsigned i) const
unsigned getKillRegState(bool B)
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
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 ==...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Flag
These should be considered private to the implementation of the MCInstrDesc class.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
constexpr uint64_t MinAlign(uint64_t A, uint64_t B)
A and B are either alignments or offsets.
static unsigned selectBinaryOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
Select the AArch64 opcode for the basic binary operation GenericOpc (such as G_OR or G_SDIV)...
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool isNegative() const
Determine sign of this APInt.
Type * getReturnType() const
Returns the type of the ret val.
Control flow instructions. These all have token chains.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
unsigned const MachineRegisterInfo * MRI
static int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
Conditional or Unconditional Branch instruction.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
Value * getCompareOperand()
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Indirect Branch Instruction.
static bool isIntExtFree(const Instruction *I)
Check if the sign-/zero-extend will be a noop.
ConstantFP - Floating Point Values [float, double].
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
bool useSmallAddressing() const
static bool isSExtLoad(const MachineInstr *LI)
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
static AArch64CC::CondCode getCompareCC(CmpInst::Predicate Pred)
0 1 1 1 True if ordered (no nans)
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const Value * getCondition() const
1 1 1 1 Always true (always folded)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
static unsigned getImplicitScaleFactor(MVT VT)
Determine the implicit scale factor that is applied by a memory operation for a given value type...
1 1 0 1 True if unordered, less than, or equal
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
The memory access writes data.
const APFloat & getValueAPF() const
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
bool isReleaseOrStronger(AtomicOrdering ao)
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 isFloatingPoint() const
Return true if this is a FP or a vector FP type.
0 0 1 0 True if ordered and greater than
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 AArch64_AM::ShiftExtendType getExtendType(unsigned Imm)
getExtendType - Extract the extend type for operands of arithmetic ops.
Iterator for intrusive lists based on ilist_node.
unsigned getNumOperands() const
CCState - This class holds information needed while lowering arguments and return values...
This is the shared class of boolean and integer constants.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
1 1 0 0 True if unordered or less than
Provides information about what library functions are available for the current target.
CCValAssign - Represent assignment of one arg/retval to a location.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned char TargetFlags=0) const
int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool selectBitCast(const User *I)
Target - Wrapper for Target specific information.
Class for arbitrary precision integers.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
This file defines the FastISel class.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
const Value * getFalseValue() const
static unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, unsigned Imm)
getArithExtendImm - Encode the extend type and shift amount for an arithmetic instruction: imm: 3-bit...
Flags
Flags values. These may be or'd together.
amdgpu Simplify well known AMD library false Value Value * Arg
The memory access reads data.
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Representation of each machine instruction.
void emitReservedArgRegCallError(const MachineFunction &MF) const
unsigned getNumArgOperands() const
bool isVector() const
Return true if this is a vector value type.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Bitwise operators - logical and, logical or, logical xor.
unsigned getDestAddressSpace() const
uint64_t getElementOffset(unsigned Idx) const
unsigned greater or equal
bool isZero() const
Return true if the value is positive or negative zero.
static unsigned UseReg(const MachineOperand &MO)
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation.
const Function * getParent() const
Return the enclosing method, or null if none.
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page...
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
0 1 1 0 True if ordered and operands are unequal
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool isUnconditional() const
1 0 1 0 True if unordered or greater than
static EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static SDValue emitCmp(SelectionDAG &DAG, const SDLoc &DL, Comparison &C)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
0 0 0 1 True if ordered and equal
LLVM Value Representation.
1 0 1 1 True if unordered, greater than, or equal
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
bool hasOneUse() const
Return true if there is exactly one user of this value.
static MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow...
unsigned constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const MCInstrDesc &II, const MachineOperand &RegMO, unsigned OpIdx)
Try to constrain Reg so that it is usable by argument OpIdx of the provided MCInstrDesc II...
APInt bitcastToAPInt() const
const MachineInstrBuilder & addDef(unsigned RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0) const
unsigned getLocReg() const
TRUNCATE - Completely drop the high bits.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
const MachineOperand & getOperand(unsigned i) const
0 0 1 1 True if ordered and greater than or equal
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
PointerType * getType() const
Global values are always pointers.
iterator_range< arg_iterator > args()
0 0 0 0 Always false (always folded)
bool isStructTy() const
True if this is an instance of StructType.
bool isArrayTy() const
True if this is an instance of ArrayType.
A wrapper class for inspecting calls to intrinsic functions.
const BasicBlock * getParent() const
an instruction to allocate memory on the stack
static bool isMulPowOf2(const Value *I)
Check if the multiply is by a power-of-2 constant.
gep_type_iterator gep_type_begin(const User *GEP)
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...