57#include "llvm/IR/IntrinsicsAArch64.h"
81class AArch64FastISel final :
public FastISel {
84 using BaseKind =
enum {
90 BaseKind
Kind = RegBase;
96 unsigned OffsetReg = 0;
104 void setKind(BaseKind K) {
Kind =
K; }
105 BaseKind getKind()
const {
return Kind; }
108 bool isRegBase()
const {
return Kind == RegBase; }
109 bool isFIBase()
const {
return Kind == FrameIndexBase; }
111 void setReg(
unsigned Reg) {
112 assert(isRegBase() &&
"Invalid base register access!");
117 assert(isRegBase() &&
"Invalid base register access!");
121 void setOffsetReg(
unsigned Reg) {
125 unsigned getOffsetReg()
const {
129 void setFI(
unsigned FI) {
130 assert(isFIBase() &&
"Invalid base frame index access!");
134 unsigned getFI()
const {
135 assert(isFIBase() &&
"Invalid base frame index access!");
139 void setOffset(int64_t O) {
Offset =
O; }
141 void setShift(
unsigned S) { Shift = S; }
142 unsigned getShift() {
return Shift; }
171 bool selectRem(
const Instruction *
I,
unsigned ISDOpcode);
184 bool isTypeLegal(
Type *Ty,
MVT &VT);
185 bool isTypeSupported(
Type *Ty,
MVT &VT,
bool IsVectorAllowed =
false);
186 bool isValueAvailable(
const Value *V)
const;
187 bool computeAddress(
const Value *Obj, Address &
Addr,
Type *Ty =
nullptr);
188 bool computeCallAddress(
const Value *V, Address &
Addr);
189 bool simplifyAddress(Address &
Addr,
MVT VT);
194 bool tryEmitSmallMemCpy(Address Dest, Address Src,
uint64_t Len,
203 unsigned emitAddSub(
bool UseAdd,
MVT RetVT,
const Value *LHS,
204 const Value *RHS,
bool SetFlags =
false,
205 bool WantResult =
true,
bool IsZExt =
false);
206 unsigned emitAddSub_rr(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
207 unsigned RHSReg,
bool SetFlags =
false,
208 bool WantResult =
true);
209 unsigned emitAddSub_ri(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
210 uint64_t Imm,
bool SetFlags =
false,
211 bool WantResult =
true);
212 unsigned emitAddSub_rs(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
214 uint64_t ShiftImm,
bool SetFlags =
false,
215 bool WantResult =
true);
216 unsigned emitAddSub_rx(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
218 uint64_t ShiftImm,
bool SetFlags =
false,
219 bool WantResult =
true);
222 bool emitCompareAndBranch(
const BranchInst *BI);
224 bool emitICmp(
MVT RetVT,
const Value *LHS,
const Value *RHS,
bool IsZExt);
225 bool emitICmp_ri(
MVT RetVT,
unsigned LHSReg,
uint64_t Imm);
226 bool emitFCmp(
MVT RetVT,
const Value *LHS,
const Value *RHS);
231 bool emitStoreRelease(
MVT VT,
unsigned SrcReg,
unsigned AddrReg,
233 unsigned emitIntExt(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
bool isZExt);
234 unsigned emiti1Ext(
unsigned SrcReg,
MVT DestVT,
bool isZExt);
235 unsigned emitAdd(
MVT RetVT,
const Value *LHS,
const Value *RHS,
236 bool SetFlags =
false,
bool WantResult =
true,
237 bool IsZExt =
false);
238 unsigned emitAdd_ri_(
MVT VT,
unsigned Op0, int64_t Imm);
239 unsigned emitSub(
MVT RetVT,
const Value *LHS,
const Value *RHS,
240 bool SetFlags =
false,
bool WantResult =
true,
241 bool IsZExt =
false);
242 unsigned emitSubs_rr(
MVT RetVT,
unsigned LHSReg,
unsigned RHSReg,
243 bool WantResult =
true);
244 unsigned emitSubs_rs(
MVT RetVT,
unsigned LHSReg,
unsigned RHSReg,
246 bool WantResult =
true);
247 unsigned emitLogicalOp(
unsigned ISDOpc,
MVT RetVT,
const Value *LHS,
249 unsigned emitLogicalOp_ri(
unsigned ISDOpc,
MVT RetVT,
unsigned LHSReg,
251 unsigned emitLogicalOp_rs(
unsigned ISDOpc,
MVT RetVT,
unsigned LHSReg,
252 unsigned RHSReg,
uint64_t ShiftImm);
253 unsigned emitAnd_ri(
MVT RetVT,
unsigned LHSReg,
uint64_t Imm);
254 unsigned emitMul_rr(
MVT RetVT,
unsigned Op0,
unsigned Op1);
255 unsigned emitSMULL_rr(
MVT RetVT,
unsigned Op0,
unsigned Op1);
256 unsigned emitUMULL_rr(
MVT RetVT,
unsigned Op0,
unsigned Op1);
257 unsigned emitLSL_rr(
MVT RetVT,
unsigned Op0Reg,
unsigned Op1Reg);
258 unsigned emitLSL_ri(
MVT RetVT,
MVT SrcVT,
unsigned Op0Reg,
uint64_t Imm,
260 unsigned emitLSR_rr(
MVT RetVT,
unsigned Op0Reg,
unsigned Op1Reg);
261 unsigned emitLSR_ri(
MVT RetVT,
MVT SrcVT,
unsigned Op0Reg,
uint64_t Imm,
263 unsigned emitASR_rr(
MVT RetVT,
unsigned Op0Reg,
unsigned Op1Reg);
264 unsigned emitASR_ri(
MVT RetVT,
MVT SrcVT,
unsigned Op0Reg,
uint64_t Imm,
265 bool IsZExt =
false);
276 bool finishCall(CallLoweringInfo &CLI,
unsigned NumBytes);
293#include "AArch64GenFastISel.inc"
300 assert((isa<ZExtInst>(
I) || isa<SExtInst>(
I)) &&
301 "Unexpected integer extend instruction.");
302 assert(!
I->getType()->isVectorTy() &&
I->getType()->isIntegerTy() &&
303 "Unexpected value type.");
304 bool IsZExt = isa<ZExtInst>(
I);
306 if (
const auto *LI = dyn_cast<LoadInst>(
I->getOperand(0)))
310 if (
const auto *Arg = dyn_cast<Argument>(
I->getOperand(0)))
311 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr()))
342 if (Subtarget->isTargetDarwin())
344 if (Subtarget->isTargetWindows())
349unsigned AArch64FastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
351 "Alloca should always return a pointer.");
354 if (!FuncInfo.StaticAllocaMap.count(AI))
358 FuncInfo.StaticAllocaMap.find(AI);
360 if (SI != FuncInfo.StaticAllocaMap.end()) {
361 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
362 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
373unsigned AArch64FastISel::materializeInt(
const ConstantInt *CI,
MVT VT) {
382 : &AArch64::GPR32RegClass;
383 unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
384 Register ResultReg = createResultReg(RC);
385 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
390unsigned AArch64FastISel::materializeFP(
const ConstantFP *CFP,
MVT VT) {
394 return fastMaterializeFloatZero(CFP);
396 if (VT != MVT::f32 && VT != MVT::f64)
400 bool Is64Bit = (VT == MVT::f64);
406 unsigned Opc = Is64Bit ? AArch64::FMOVDi : AArch64::FMOVSi;
407 return fastEmitInst_i(Opc, TLI.getRegClassFor(VT), Imm);
412 unsigned Opc1 = Is64Bit ? AArch64::MOVi64imm : AArch64::MOVi32imm;
414 &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
416 Register TmpReg = createResultReg(RC);
417 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc1), TmpReg)
420 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
421 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
422 TII.get(TargetOpcode::COPY), ResultReg)
432 unsigned CPI = MCP.getConstantPoolIndex(cast<Constant>(CFP), Alignment);
433 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
434 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
437 unsigned Opc = Is64Bit ? AArch64::LDRDui : AArch64::LDRSui;
438 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
439 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg)
445unsigned AArch64FastISel::materializeGV(
const GlobalValue *GV) {
452 if (!Subtarget->useSmallAddressing() && !Subtarget->isTargetMachO())
455 unsigned OpFlags = Subtarget->ClassifyGlobalReference(GV,
TM);
457 EVT DestEVT = TLI.getValueType(
DL, GV->
getType(),
true);
461 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
466 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
471 if (Subtarget->isTargetILP32()) {
472 ResultReg = createResultReg(&AArch64::GPR32RegClass);
473 LdrOpc = AArch64::LDRWui;
475 ResultReg = createResultReg(&AArch64::GPR64RegClass);
476 LdrOpc = AArch64::LDRXui;
478 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(LdrOpc),
483 if (!Subtarget->isTargetILP32())
488 Register Result64 = createResultReg(&AArch64::GPR64RegClass);
489 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
490 TII.get(TargetOpcode::SUBREG_TO_REG))
498 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
516 unsigned DstReg = createResultReg(&AArch64::GPR64commonRegClass);
517 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::MOVKXi),
526 ResultReg = createResultReg(&AArch64::GPR64spRegClass);
527 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
537unsigned AArch64FastISel::fastMaterializeConstant(
const Constant *
C) {
538 EVT CEVT = TLI.getValueType(
DL,
C->getType(),
true);
546 if (isa<ConstantPointerNull>(
C)) {
547 assert(VT == MVT::i64 &&
"Expected 64-bit pointers");
551 if (
const auto *CI = dyn_cast<ConstantInt>(
C))
552 return materializeInt(CI, VT);
553 else if (
const ConstantFP *CFP = dyn_cast<ConstantFP>(
C))
554 return materializeFP(CFP, VT);
555 else if (
const GlobalValue *GV = dyn_cast<GlobalValue>(
C))
556 return materializeGV(GV);
561unsigned AArch64FastISel::fastMaterializeFloatZero(
const ConstantFP* CFP) {
563 "Floating-point constant is not a positive zero.");
565 if (!isTypeLegal(CFP->
getType(), VT))
568 if (VT != MVT::f32 && VT != MVT::f64)
571 bool Is64Bit = (VT == MVT::f64);
572 unsigned ZReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
573 unsigned Opc = Is64Bit ? AArch64::FMOVXDr : AArch64::FMOVWSr;
574 return fastEmitInst_r(Opc, TLI.getRegClassFor(VT), ZReg);
579 if (
const auto *
MI = dyn_cast<MulOperator>(
I)) {
580 if (
const auto *
C = dyn_cast<ConstantInt>(
MI->getOperand(0)))
581 if (
C->getValue().isPowerOf2())
583 if (
const auto *
C = dyn_cast<ConstantInt>(
MI->getOperand(1)))
584 if (
C->getValue().isPowerOf2())
591bool AArch64FastISel::computeAddress(
const Value *Obj, Address &
Addr,
Type *Ty)
593 const User *
U =
nullptr;
594 unsigned Opcode = Instruction::UserOp1;
595 if (
const Instruction *
I = dyn_cast<Instruction>(Obj)) {
598 if (FuncInfo.StaticAllocaMap.count(
static_cast<const AllocaInst *
>(Obj)) ||
599 FuncInfo.MBBMap[
I->getParent()] == FuncInfo.MBB) {
603 }
else if (
const ConstantExpr *
C = dyn_cast<ConstantExpr>(Obj)) {
608 if (
auto *Ty = dyn_cast<PointerType>(Obj->
getType()))
609 if (Ty->getAddressSpace() > 255)
617 case Instruction::BitCast:
619 return computeAddress(
U->getOperand(0),
Addr, Ty);
621 case Instruction::IntToPtr:
623 if (TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
624 TLI.getPointerTy(
DL))
625 return computeAddress(
U->getOperand(0),
Addr, Ty);
628 case Instruction::PtrToInt:
630 if (TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
631 return computeAddress(
U->getOperand(0),
Addr, Ty);
634 case Instruction::GetElementPtr: {
642 const Value *
Op = GTI.getOperand();
643 if (
StructType *STy = GTI.getStructTypeOrNull()) {
645 unsigned Idx = cast<ConstantInt>(
Op)->getZExtValue();
648 uint64_t S =
DL.getTypeAllocSize(GTI.getIndexedType());
655 if (canFoldAddIntoGEP(U,
Op)) {
658 cast<ConstantInt>(cast<AddOperator>(
Op)->getOperand(1));
661 Op = cast<AddOperator>(
Op)->getOperand(0);
665 goto unsupported_gep;
671 Addr.setOffset(TmpOffset);
672 if (computeAddress(
U->getOperand(0),
Addr, Ty))
681 case Instruction::Alloca: {
684 FuncInfo.StaticAllocaMap.find(AI);
685 if (SI != FuncInfo.StaticAllocaMap.end()) {
686 Addr.setKind(Address::FrameIndexBase);
692 case Instruction::Add: {
697 if (isa<ConstantInt>(LHS))
700 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
702 return computeAddress(LHS,
Addr, Ty);
706 if (computeAddress(LHS,
Addr, Ty) && computeAddress(RHS,
Addr, Ty))
712 case Instruction::Sub: {
717 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
719 return computeAddress(LHS,
Addr, Ty);
723 case Instruction::Shl: {
724 if (
Addr.getOffsetReg())
727 const auto *CI = dyn_cast<ConstantInt>(
U->getOperand(1));
732 if (Val < 1 || Val > 3)
738 NumBytes = NumBits / 8;
743 if (NumBytes != (1ULL << Val))
749 const Value *Src =
U->getOperand(0);
750 if (
const auto *
I = dyn_cast<Instruction>(Src)) {
751 if (FuncInfo.MBBMap[
I->getParent()] == FuncInfo.MBB) {
753 if (
const auto *ZE = dyn_cast<ZExtInst>(
I)) {
755 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
757 Src = ZE->getOperand(0);
759 }
else if (
const auto *SE = dyn_cast<SExtInst>(
I)) {
761 SE->getOperand(0)->getType()->isIntegerTy(32)) {
763 Src = SE->getOperand(0);
769 if (
const auto *AI = dyn_cast<BinaryOperator>(Src))
770 if (AI->
getOpcode() == Instruction::And) {
774 if (
const auto *
C = dyn_cast<ConstantInt>(LHS))
775 if (
C->getValue() == 0xffffffff)
778 if (
const auto *
C = dyn_cast<ConstantInt>(RHS))
779 if (
C->getValue() == 0xffffffff) {
784 Reg = fastEmitInst_extractsubreg(MVT::i32, Reg, AArch64::sub_32);
785 Addr.setOffsetReg(Reg);
793 Addr.setOffsetReg(Reg);
796 case Instruction::Mul: {
797 if (
Addr.getOffsetReg())
807 if (
const auto *
C = dyn_cast<ConstantInt>(LHS))
808 if (
C->getValue().isPowerOf2())
811 assert(isa<ConstantInt>(RHS) &&
"Expected an ConstantInt.");
812 const auto *
C = cast<ConstantInt>(RHS);
813 unsigned Val =
C->getValue().logBase2();
814 if (Val < 1 || Val > 3)
820 NumBytes = NumBits / 8;
825 if (NumBytes != (1ULL << Val))
832 if (
const auto *
I = dyn_cast<Instruction>(Src)) {
833 if (FuncInfo.MBBMap[
I->getParent()] == FuncInfo.MBB) {
835 if (
const auto *ZE = dyn_cast<ZExtInst>(
I)) {
837 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
839 Src = ZE->getOperand(0);
841 }
else if (
const auto *SE = dyn_cast<SExtInst>(
I)) {
843 SE->getOperand(0)->getType()->isIntegerTy(32)) {
845 Src = SE->getOperand(0);
854 Addr.setOffsetReg(Reg);
857 case Instruction::And: {
858 if (
Addr.getOffsetReg())
861 if (!Ty ||
DL.getTypeSizeInBits(Ty) != 8)
867 if (
const auto *
C = dyn_cast<ConstantInt>(LHS))
868 if (
C->getValue() == 0xffffffff)
871 if (
const auto *
C = dyn_cast<ConstantInt>(RHS))
872 if (
C->getValue() == 0xffffffff) {
880 Reg = fastEmitInst_extractsubreg(MVT::i32, Reg, AArch64::sub_32);
881 Addr.setOffsetReg(Reg);
886 case Instruction::SExt:
887 case Instruction::ZExt: {
888 if (!
Addr.getReg() ||
Addr.getOffsetReg())
891 const Value *Src =
nullptr;
893 if (
const auto *ZE = dyn_cast<ZExtInst>(U)) {
894 if (!
isIntExtFree(ZE) && ZE->getOperand(0)->getType()->isIntegerTy(32)) {
896 Src = ZE->getOperand(0);
898 }
else if (
const auto *SE = dyn_cast<SExtInst>(U)) {
899 if (!
isIntExtFree(SE) && SE->getOperand(0)->getType()->isIntegerTy(32)) {
901 Src = SE->getOperand(0);
912 Addr.setOffsetReg(Reg);
917 if (
Addr.isRegBase() && !
Addr.getReg()) {
925 if (!
Addr.getOffsetReg()) {
929 Addr.setOffsetReg(Reg);
936bool AArch64FastISel::computeCallAddress(
const Value *V, Address &
Addr) {
937 const User *
U =
nullptr;
938 unsigned Opcode = Instruction::UserOp1;
941 if (
const auto *
I = dyn_cast<Instruction>(V)) {
944 InMBB =
I->getParent() == FuncInfo.MBB->getBasicBlock();
945 }
else if (
const auto *
C = dyn_cast<ConstantExpr>(V)) {
952 case Instruction::BitCast:
955 return computeCallAddress(
U->getOperand(0),
Addr);
957 case Instruction::IntToPtr:
960 TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
961 TLI.getPointerTy(
DL))
962 return computeCallAddress(
U->getOperand(0),
Addr);
964 case Instruction::PtrToInt:
966 if (InMBB && TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
967 return computeCallAddress(
U->getOperand(0),
Addr);
971 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
972 Addr.setGlobalValue(GV);
977 if (!
Addr.getGlobalValue()) {
978 Addr.setReg(getRegForValue(V));
979 return Addr.getReg() != 0;
985bool AArch64FastISel::isTypeLegal(
Type *Ty,
MVT &VT) {
986 EVT evt = TLI.getValueType(
DL, Ty,
true);
988 if (Subtarget->isTargetILP32() && Ty->
isPointerTy())
992 if (evt == MVT::Other || !evt.
isSimple())
1002 return TLI.isTypeLegal(VT);
1009bool AArch64FastISel::isTypeSupported(
Type *Ty,
MVT &VT,
bool IsVectorAllowed) {
1013 if (isTypeLegal(Ty, VT))
1018 if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)
1024bool AArch64FastISel::isValueAvailable(
const Value *V)
const {
1025 if (!isa<Instruction>(V))
1028 const auto *
I = cast<Instruction>(V);
1029 return FuncInfo.MBBMap[
I->getParent()] == FuncInfo.MBB;
1032bool AArch64FastISel::simplifyAddress(Address &
Addr,
MVT VT) {
1033 if (Subtarget->isTargetILP32())
1040 bool ImmediateOffsetNeedsLowering =
false;
1041 bool RegisterOffsetNeedsLowering =
false;
1044 ImmediateOffsetNeedsLowering =
true;
1045 else if (
Offset > 0 && !(
Offset & (ScaleFactor - 1)) &&
1046 !isUInt<12>(
Offset / ScaleFactor))
1047 ImmediateOffsetNeedsLowering =
true;
1052 if (!ImmediateOffsetNeedsLowering &&
Addr.getOffset() &&
Addr.getOffsetReg())
1053 RegisterOffsetNeedsLowering =
true;
1056 if (
Addr.isRegBase() &&
Addr.getOffsetReg() && !
Addr.getReg())
1057 RegisterOffsetNeedsLowering =
true;
1062 if ((ImmediateOffsetNeedsLowering ||
Addr.getOffsetReg()) &&
Addr.isFIBase())
1064 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
1065 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADDXri),
1070 Addr.setKind(Address::RegBase);
1071 Addr.setReg(ResultReg);
1074 if (RegisterOffsetNeedsLowering) {
1075 unsigned ResultReg = 0;
1076 if (
Addr.getReg()) {
1079 ResultReg = emitAddSub_rx(
true, MVT::i64,
Addr.getReg(),
1080 Addr.getOffsetReg(),
Addr.getExtendType(),
1083 ResultReg = emitAddSub_rs(
true, MVT::i64,
Addr.getReg(),
1088 ResultReg = emitLSL_ri(MVT::i64, MVT::i32,
Addr.getOffsetReg(),
1089 Addr.getShift(),
true);
1091 ResultReg = emitLSL_ri(MVT::i64, MVT::i32,
Addr.getOffsetReg(),
1092 Addr.getShift(),
false);
1094 ResultReg = emitLSL_ri(MVT::i64, MVT::i64,
Addr.getOffsetReg(),
1100 Addr.setReg(ResultReg);
1101 Addr.setOffsetReg(0);
1108 if (ImmediateOffsetNeedsLowering) {
1112 ResultReg = emitAdd_ri_(MVT::i64,
Addr.getReg(),
Offset);
1118 Addr.setReg(ResultReg);
1124void AArch64FastISel::addLoadStoreOperands(Address &
Addr,
1127 unsigned ScaleFactor,
1129 int64_t
Offset =
Addr.getOffset() / ScaleFactor;
1131 if (
Addr.isFIBase()) {
1132 int FI =
Addr.getFI();
1135 MMO = FuncInfo.MF->getMachineMemOperand(
1137 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
1141 assert(
Addr.isRegBase() &&
"Unexpected address kind.");
1148 if (
Addr.getOffsetReg()) {
1149 assert(
Addr.getOffset() == 0 &&
"Unexpected offset");
1164unsigned AArch64FastISel::emitAddSub(
bool UseAdd,
MVT RetVT,
const Value *LHS,
1165 const Value *RHS,
bool SetFlags,
1166 bool WantResult,
bool IsZExt) {
1168 bool NeedExtend =
false;
1191 if (UseAdd && isa<Constant>(LHS) && !isa<Constant>(RHS))
1195 if (UseAdd &&
LHS->
hasOneUse() && isValueAvailable(LHS))
1200 if (UseAdd &&
LHS->
hasOneUse() && isValueAvailable(LHS))
1201 if (
const auto *SI = dyn_cast<BinaryOperator>(LHS))
1202 if (isa<ConstantInt>(
SI->getOperand(1)))
1203 if (
SI->getOpcode() == Instruction::Shl ||
1204 SI->getOpcode() == Instruction::LShr ||
1205 SI->getOpcode() == Instruction::AShr )
1208 Register LHSReg = getRegForValue(LHS);
1213 LHSReg = emitIntExt(SrcVT, LHSReg, RetVT, IsZExt);
1215 unsigned ResultReg = 0;
1216 if (
const auto *
C = dyn_cast<ConstantInt>(RHS)) {
1217 uint64_t Imm = IsZExt ?
C->getZExtValue() :
C->getSExtValue();
1218 if (
C->isNegative())
1219 ResultReg = emitAddSub_ri(!UseAdd, RetVT, LHSReg, -Imm, SetFlags,
1222 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, Imm, SetFlags,
1224 }
else if (
const auto *
C = dyn_cast<Constant>(RHS))
1225 if (
C->isNullValue())
1226 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, 0, SetFlags, WantResult);
1233 isValueAvailable(RHS)) {
1234 if (
const auto *SI = dyn_cast<BinaryOperator>(RHS))
1235 if (
const auto *
C = dyn_cast<ConstantInt>(
SI->getOperand(1)))
1236 if ((
SI->getOpcode() == Instruction::Shl) && (
C->getZExtValue() < 4)) {
1237 Register RHSReg = getRegForValue(
SI->getOperand(0));
1240 return emitAddSub_rx(UseAdd, RetVT, LHSReg, RHSReg, ExtendType,
1241 C->getZExtValue(), SetFlags, WantResult);
1243 Register RHSReg = getRegForValue(RHS);
1246 return emitAddSub_rx(UseAdd, RetVT, LHSReg, RHSReg, ExtendType, 0,
1247 SetFlags, WantResult);
1253 const Value *MulLHS = cast<MulOperator>(RHS)->getOperand(0);
1254 const Value *MulRHS = cast<MulOperator>(RHS)->getOperand(1);
1256 if (
const auto *
C = dyn_cast<ConstantInt>(MulLHS))
1257 if (
C->getValue().isPowerOf2())
1260 assert(isa<ConstantInt>(MulRHS) &&
"Expected a ConstantInt.");
1261 uint64_t ShiftVal = cast<ConstantInt>(MulRHS)->getValue().logBase2();
1262 Register RHSReg = getRegForValue(MulLHS);
1265 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg,
AArch64_AM::LSL,
1266 ShiftVal, SetFlags, WantResult);
1274 if (
const auto *SI = dyn_cast<BinaryOperator>(RHS)) {
1275 if (
const auto *
C = dyn_cast<ConstantInt>(
SI->getOperand(1))) {
1277 switch (
SI->getOpcode()) {
1285 Register RHSReg = getRegForValue(
SI->getOperand(0));
1288 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg, ShiftType,
1289 ShiftVal, SetFlags, WantResult);
1297 Register RHSReg = getRegForValue(RHS);
1302 RHSReg = emitIntExt(SrcVT, RHSReg, RetVT, IsZExt);
1304 return emitAddSub_rr(UseAdd, RetVT, LHSReg, RHSReg, SetFlags, WantResult);
1307unsigned AArch64FastISel::emitAddSub_rr(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
1308 unsigned RHSReg,
bool SetFlags,
1310 assert(LHSReg && RHSReg &&
"Invalid register number.");
1312 if (LHSReg == AArch64::SP || LHSReg == AArch64::WSP ||
1313 RHSReg == AArch64::SP || RHSReg == AArch64::WSP)
1316 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1319 static const unsigned OpcTable[2][2][2] = {
1320 { { AArch64::SUBWrr, AArch64::SUBXrr },
1321 { AArch64::ADDWrr, AArch64::ADDXrr } },
1322 { { AArch64::SUBSWrr, AArch64::SUBSXrr },
1323 { AArch64::ADDSWrr, AArch64::ADDSXrr } }
1325 bool Is64Bit = RetVT == MVT::i64;
1326 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1328 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1331 ResultReg = createResultReg(RC);
1333 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1338 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)
1344unsigned AArch64FastISel::emitAddSub_ri(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
1347 assert(LHSReg &&
"Invalid register number.");
1349 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1353 if (isUInt<12>(Imm))
1355 else if ((Imm & 0xfff000) == Imm) {
1361 static const unsigned OpcTable[2][2][2] = {
1362 { { AArch64::SUBWri, AArch64::SUBXri },
1363 { AArch64::ADDWri, AArch64::ADDXri } },
1364 { { AArch64::SUBSWri, AArch64::SUBSXri },
1365 { AArch64::ADDSWri, AArch64::ADDSXri } }
1367 bool Is64Bit = RetVT == MVT::i64;
1368 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1371 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1373 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1376 ResultReg = createResultReg(RC);
1378 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1382 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)
1389unsigned AArch64FastISel::emitAddSub_rs(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
1394 assert(LHSReg && RHSReg &&
"Invalid register number.");
1395 assert(LHSReg != AArch64::SP && LHSReg != AArch64::WSP &&
1396 RHSReg != AArch64::SP && RHSReg != AArch64::WSP);
1398 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1405 static const unsigned OpcTable[2][2][2] = {
1406 { { AArch64::SUBWrs, AArch64::SUBXrs },
1407 { AArch64::ADDWrs, AArch64::ADDXrs } },
1408 { { AArch64::SUBSWrs, AArch64::SUBSXrs },
1409 { AArch64::ADDSWrs, AArch64::ADDSXrs } }
1411 bool Is64Bit = RetVT == MVT::i64;
1412 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1414 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1417 ResultReg = createResultReg(RC);
1419 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1424 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)
1427 .
addImm(getShifterImm(ShiftType, ShiftImm));
1431unsigned AArch64FastISel::emitAddSub_rx(
bool UseAdd,
MVT RetVT,
unsigned LHSReg,
1436 assert(LHSReg && RHSReg &&
"Invalid register number.");
1437 assert(LHSReg != AArch64::XZR && LHSReg != AArch64::WZR &&
1438 RHSReg != AArch64::XZR && RHSReg != AArch64::WZR);
1440 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1446 static const unsigned OpcTable[2][2][2] = {
1447 { { AArch64::SUBWrx, AArch64::SUBXrx },
1448 { AArch64::ADDWrx, AArch64::ADDXrx } },
1449 { { AArch64::SUBSWrx, AArch64::SUBSXrx },
1450 { AArch64::ADDSWrx, AArch64::ADDSXrx } }
1452 bool Is64Bit = RetVT == MVT::i64;
1453 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1456 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1458 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
1461 ResultReg = createResultReg(RC);
1463 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1468 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)
1471 .
addImm(getArithExtendImm(ExtType, ShiftImm));
1475bool AArch64FastISel::emitCmp(
const Value *LHS,
const Value *RHS,
bool IsZExt) {
1477 EVT EVT = TLI.getValueType(
DL, Ty,
true);
1490 return emitICmp(VT, LHS, RHS, IsZExt);
1493 return emitFCmp(VT, LHS, RHS);
1497bool AArch64FastISel::emitICmp(
MVT RetVT,
const Value *LHS,
const Value *RHS,
1499 return emitSub(RetVT, LHS, RHS,
true,
false,
1503bool AArch64FastISel::emitICmp_ri(
MVT RetVT,
unsigned LHSReg,
uint64_t Imm) {
1504 return emitAddSub_ri(
false, RetVT, LHSReg, Imm,
1508bool AArch64FastISel::emitFCmp(
MVT RetVT,
const Value *LHS,
const Value *RHS) {
1509 if (RetVT != MVT::f32 && RetVT != MVT::f64)
1514 bool UseImm =
false;
1515 if (
const auto *CFP = dyn_cast<ConstantFP>(RHS))
1519 Register LHSReg = getRegForValue(LHS);
1524 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDri : AArch64::FCMPSri;
1525 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc))
1530 Register RHSReg = getRegForValue(RHS);
1534 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDrr : AArch64::FCMPSrr;
1535 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc))
1541unsigned AArch64FastISel::emitAdd(
MVT RetVT,
const Value *LHS,
const Value *RHS,
1542 bool SetFlags,
bool WantResult,
bool IsZExt) {
1543 return emitAddSub(
true, RetVT, LHS, RHS, SetFlags, WantResult,
1552unsigned AArch64FastISel::emitAdd_ri_(
MVT VT,
unsigned Op0, int64_t Imm) {
1555 ResultReg = emitAddSub_ri(
false, VT, Op0, -Imm);
1557 ResultReg = emitAddSub_ri(
true, VT, Op0, Imm);
1566 ResultReg = emitAddSub_rr(
true, VT, Op0, CReg);
1570unsigned AArch64FastISel::emitSub(
MVT RetVT,
const Value *LHS,
const Value *RHS,
1571 bool SetFlags,
bool WantResult,
bool IsZExt) {
1572 return emitAddSub(
false, RetVT, LHS, RHS, SetFlags, WantResult,
1576unsigned AArch64FastISel::emitSubs_rr(
MVT RetVT,
unsigned LHSReg,
1577 unsigned RHSReg,
bool WantResult) {
1578 return emitAddSub_rr(
false, RetVT, LHSReg, RHSReg,
1582unsigned AArch64FastISel::emitSubs_rs(
MVT RetVT,
unsigned LHSReg,
1585 uint64_t ShiftImm,
bool WantResult) {
1586 return emitAddSub_rs(
false, RetVT, LHSReg, RHSReg, ShiftType,
1587 ShiftImm,
true, WantResult);
1590unsigned AArch64FastISel::emitLogicalOp(
unsigned ISDOpc,
MVT RetVT,
1593 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS))
1603 if (
const auto *SI = dyn_cast<ShlOperator>(LHS))
1604 if (isa<ConstantInt>(
SI->getOperand(1)))
1607 Register LHSReg = getRegForValue(LHS);
1611 unsigned ResultReg = 0;
1612 if (
const auto *
C = dyn_cast<ConstantInt>(RHS)) {
1614 ResultReg = emitLogicalOp_ri(ISDOpc, RetVT, LHSReg, Imm);
1622 const Value *MulLHS = cast<MulOperator>(RHS)->getOperand(0);
1623 const Value *MulRHS = cast<MulOperator>(RHS)->getOperand(1);
1625 if (
const auto *
C = dyn_cast<ConstantInt>(MulLHS))
1626 if (
C->getValue().isPowerOf2())
1629 assert(isa<ConstantInt>(MulRHS) &&
"Expected a ConstantInt.");
1630 uint64_t ShiftVal = cast<ConstantInt>(MulRHS)->getValue().logBase2();
1632 Register RHSReg = getRegForValue(MulLHS);
1635 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);
1643 if (
const auto *SI = dyn_cast<ShlOperator>(RHS))
1644 if (
const auto *
C = dyn_cast<ConstantInt>(
SI->getOperand(1))) {
1646 Register RHSReg = getRegForValue(
SI->getOperand(0));
1649 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);
1655 Register RHSReg = getRegForValue(RHS);
1660 ResultReg = fastEmit_rr(VT, VT, ISDOpc, LHSReg, RHSReg);
1661 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1663 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1668unsigned AArch64FastISel::emitLogicalOp_ri(
unsigned ISDOpc,
MVT RetVT,
1671 "ISD nodes are not consecutive!");
1672 static const unsigned OpcTable[3][2] = {
1673 { AArch64::ANDWri, AArch64::ANDXri },
1674 { AArch64::ORRWri, AArch64::ORRXri },
1675 { AArch64::EORWri, AArch64::EORXri }
1688 Opc = OpcTable[
Idx][0];
1689 RC = &AArch64::GPR32spRegClass;
1694 Opc = OpcTable[ISDOpc -
ISD::AND][1];
1695 RC = &AArch64::GPR64spRegClass;
1704 fastEmitInst_ri(Opc, RC, LHSReg,
1706 if (RetVT >= MVT::i8 && RetVT <= MVT::i16 && ISDOpc !=
ISD::AND) {
1708 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1713unsigned AArch64FastISel::emitLogicalOp_rs(
unsigned ISDOpc,
MVT RetVT,
1714 unsigned LHSReg,
unsigned RHSReg,
1717 "ISD nodes are not consecutive!");
1718 static const unsigned OpcTable[3][2] = {
1719 { AArch64::ANDWrs, AArch64::ANDXrs },
1720 { AArch64::ORRWrs, AArch64::ORRXrs },
1721 { AArch64::EORWrs, AArch64::EORXrs }
1737 Opc = OpcTable[ISDOpc -
ISD::AND][0];
1738 RC = &AArch64::GPR32RegClass;
1741 Opc = OpcTable[ISDOpc -
ISD::AND][1];
1742 RC = &AArch64::GPR64RegClass;
1746 fastEmitInst_rri(Opc, RC, LHSReg, RHSReg,
1748 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1750 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
1755unsigned AArch64FastISel::emitAnd_ri(
MVT RetVT,
unsigned LHSReg,
1757 return emitLogicalOp_ri(
ISD::AND, RetVT, LHSReg, Imm);
1760unsigned AArch64FastISel::emitLoad(
MVT VT,
MVT RetVT, Address
Addr,
1762 if (!TLI.allowsMisalignedMemoryAccesses(VT))
1766 if (!simplifyAddress(
Addr, VT))
1775 bool UseScaled =
true;
1776 if ((
Addr.getOffset() < 0) || (
Addr.getOffset() & (ScaleFactor - 1))) {
1781 static const unsigned GPOpcTable[2][8][4] = {
1783 { { AArch64::LDURSBWi, AArch64::LDURSHWi, AArch64::LDURWi,
1785 { AArch64::LDURSBXi, AArch64::LDURSHXi, AArch64::LDURSWi,
1787 { AArch64::LDRSBWui, AArch64::LDRSHWui, AArch64::LDRWui,
1789 { AArch64::LDRSBXui, AArch64::LDRSHXui, AArch64::LDRSWui,
1791 { AArch64::LDRSBWroX, AArch64::LDRSHWroX, AArch64::LDRWroX,
1793 { AArch64::LDRSBXroX, AArch64::LDRSHXroX, AArch64::LDRSWroX,
1795 { AArch64::LDRSBWroW, AArch64::LDRSHWroW, AArch64::LDRWroW,
1797 { AArch64::LDRSBXroW, AArch64::LDRSHXroW, AArch64::LDRSWroW,
1801 { { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1803 { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1805 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1807 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1809 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1811 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1813 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1815 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1820 static const unsigned FPOpcTable[4][2] = {
1821 { AArch64::LDURSi, AArch64::LDURDi },
1822 { AArch64::LDRSui, AArch64::LDRDui },
1823 { AArch64::LDRSroX, AArch64::LDRDroX },
1824 { AArch64::LDRSroW, AArch64::LDRDroW }
1829 bool UseRegOffset =
Addr.isRegBase() && !
Addr.getOffset() &&
Addr.getReg() &&
1830 Addr.getOffsetReg();
1831 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
1836 bool IsRet64Bit = RetVT == MVT::i64;
1842 Opc = GPOpcTable[WantZExt][2 *
Idx + IsRet64Bit][0];
1843 RC = (IsRet64Bit && !WantZExt) ?
1844 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1847 Opc = GPOpcTable[WantZExt][2 *
Idx + IsRet64Bit][1];
1848 RC = (IsRet64Bit && !WantZExt) ?
1849 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1852 Opc = GPOpcTable[WantZExt][2 *
Idx + IsRet64Bit][2];
1853 RC = (IsRet64Bit && !WantZExt) ?
1854 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
1857 Opc = GPOpcTable[WantZExt][2 *
Idx + IsRet64Bit][3];
1858 RC = &AArch64::GPR64RegClass;
1861 Opc = FPOpcTable[
Idx][0];
1862 RC = &AArch64::FPR32RegClass;
1865 Opc = FPOpcTable[
Idx][1];
1866 RC = &AArch64::FPR64RegClass;
1871 Register ResultReg = createResultReg(RC);
1873 TII.get(Opc), ResultReg);
1877 if (VT == MVT::i1) {
1878 unsigned ANDReg = emitAnd_ri(MVT::i32, ResultReg, 1);
1879 assert(ANDReg &&
"Unexpected AND instruction emission failure.");
1885 if (WantZExt && RetVT == MVT::i64 && VT <= MVT::i32) {
1886 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
1887 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1888 TII.get(AArch64::SUBREG_TO_REG), Reg64)
1891 .
addImm(AArch64::sub_32);
1897bool AArch64FastISel::selectAddSub(
const Instruction *
I) {
1899 if (!isTypeSupported(
I->getType(), VT,
true))
1903 return selectOperator(
I,
I->getOpcode());
1906 switch (
I->getOpcode()) {
1909 case Instruction::Add:
1910 ResultReg = emitAdd(VT,
I->getOperand(0),
I->getOperand(1));
1912 case Instruction::Sub:
1913 ResultReg = emitSub(VT,
I->getOperand(0),
I->getOperand(1));
1919 updateValueMap(
I, ResultReg);
1923bool AArch64FastISel::selectLogicalOp(
const Instruction *
I) {
1925 if (!isTypeSupported(
I->getType(), VT,
true))
1929 return selectOperator(
I,
I->getOpcode());
1932 switch (
I->getOpcode()) {
1935 case Instruction::And:
1936 ResultReg = emitLogicalOp(
ISD::AND, VT,
I->getOperand(0),
I->getOperand(1));
1938 case Instruction::Or:
1939 ResultReg = emitLogicalOp(
ISD::OR, VT,
I->getOperand(0),
I->getOperand(1));
1941 case Instruction::Xor:
1942 ResultReg = emitLogicalOp(
ISD::XOR, VT,
I->getOperand(0),
I->getOperand(1));
1948 updateValueMap(
I, ResultReg);
1952bool AArch64FastISel::selectLoad(
const Instruction *
I) {
1957 if (!isTypeSupported(
I->getType(), VT,
true) ||
1958 cast<LoadInst>(
I)->isAtomic())
1961 const Value *SV =
I->getOperand(0);
1962 if (TLI.supportSwiftError()) {
1965 if (
const Argument *Arg = dyn_cast<Argument>(SV)) {
1966 if (Arg->hasSwiftErrorAttr())
1970 if (
const AllocaInst *Alloca = dyn_cast<AllocaInst>(SV)) {
1971 if (Alloca->isSwiftError())
1978 if (!computeAddress(
I->getOperand(0),
Addr,
I->getType()))
1982 bool WantZExt =
true;
1984 const Value *IntExtVal =
nullptr;
1985 if (
I->hasOneUse()) {
1986 if (
const auto *ZE = dyn_cast<ZExtInst>(
I->use_begin()->getUser())) {
1987 if (isTypeSupported(ZE->getType(), RetVT))
1991 }
else if (
const auto *SE = dyn_cast<SExtInst>(
I->use_begin()->getUser())) {
1992 if (isTypeSupported(SE->getType(), RetVT))
2000 unsigned ResultReg =
2001 emitLoad(VT, RetVT,
Addr, WantZExt, createMachineMemOperandFor(
I));
2022 auto *
MI =
MRI.getUniqueVRegDef(Reg);
2024 if (RetVT == MVT::i64 && VT <= MVT::i32) {
2028 ResultReg = std::prev(
I)->getOperand(0).getReg();
2029 removeDeadCode(
I, std::next(
I));
2031 ResultReg = fastEmitInst_extractsubreg(MVT::i32, ResultReg,
2034 updateValueMap(
I, ResultReg);
2043 for (
auto &Opnd :
MI->uses()) {
2045 Reg = Opnd.getReg();
2050 removeDeadCode(
I, std::next(
I));
2053 MI =
MRI.getUniqueVRegDef(Reg);
2055 updateValueMap(IntExtVal, ResultReg);
2059 updateValueMap(
I, ResultReg);
2063bool AArch64FastISel::emitStoreRelease(
MVT VT,
unsigned SrcReg,
2068 default:
return false;
2069 case MVT::i8: Opc = AArch64::STLRB;
break;
2070 case MVT::i16: Opc = AArch64::STLRH;
break;
2071 case MVT::i32: Opc = AArch64::STLRW;
break;
2072 case MVT::i64: Opc = AArch64::STLRX;
break;
2078 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)
2085bool AArch64FastISel::emitStore(
MVT VT,
unsigned SrcReg, Address
Addr,
2087 if (!TLI.allowsMisalignedMemoryAccesses(VT))
2091 if (!simplifyAddress(
Addr, VT))
2100 bool UseScaled =
true;
2101 if ((
Addr.getOffset() < 0) || (
Addr.getOffset() & (ScaleFactor - 1))) {
2106 static const unsigned OpcTable[4][6] = {
2107 { AArch64::STURBBi, AArch64::STURHHi, AArch64::STURWi, AArch64::STURXi,
2108 AArch64::STURSi, AArch64::STURDi },
2109 { AArch64::STRBBui, AArch64::STRHHui, AArch64::STRWui, AArch64::STRXui,
2110 AArch64::STRSui, AArch64::STRDui },
2111 { AArch64::STRBBroX, AArch64::STRHHroX, AArch64::STRWroX, AArch64::STRXroX,
2112 AArch64::STRSroX, AArch64::STRDroX },
2113 { AArch64::STRBBroW, AArch64::STRHHroW, AArch64::STRWroW, AArch64::STRXroW,
2114 AArch64::STRSroW, AArch64::STRDroW }
2118 bool VTIsi1 =
false;
2119 bool UseRegOffset =
Addr.isRegBase() && !
Addr.getOffset() &&
Addr.getReg() &&
2120 Addr.getOffsetReg();
2121 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
2128 case MVT::i1: VTIsi1 =
true; [[fallthrough]];
2129 case MVT::i8: Opc = OpcTable[
Idx][0];
break;
2130 case MVT::i16: Opc = OpcTable[
Idx][1];
break;
2131 case MVT::i32: Opc = OpcTable[
Idx][2];
break;
2132 case MVT::i64: Opc = OpcTable[
Idx][3];
break;
2133 case MVT::f32: Opc = OpcTable[
Idx][4];
break;
2134 case MVT::f64: Opc = OpcTable[
Idx][5];
break;
2138 if (VTIsi1 && SrcReg != AArch64::WZR) {
2139 unsigned ANDReg = emitAnd_ri(MVT::i32, SrcReg, 1);
2140 assert(ANDReg &&
"Unexpected AND instruction emission failure.");
2147 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II).
addReg(SrcReg);
2153bool AArch64FastISel::selectStore(
const Instruction *
I) {
2155 const Value *Op0 =
I->getOperand(0);
2159 if (!isTypeSupported(Op0->
getType(), VT,
true))
2162 const Value *PtrV =
I->getOperand(1);
2163 if (TLI.supportSwiftError()) {
2166 if (
const Argument *Arg = dyn_cast<Argument>(PtrV)) {
2167 if (Arg->hasSwiftErrorAttr())
2171 if (
const AllocaInst *Alloca = dyn_cast<AllocaInst>(PtrV)) {
2172 if (Alloca->isSwiftError())
2179 unsigned SrcReg = 0;
2180 if (
const auto *CI = dyn_cast<ConstantInt>(Op0)) {
2182 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2183 }
else if (
const auto *CF = dyn_cast<ConstantFP>(Op0)) {
2184 if (CF->isZero() && !CF->isNegative()) {
2186 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2191 SrcReg = getRegForValue(Op0);
2196 auto *
SI = cast<StoreInst>(
I);
2199 if (
SI->isAtomic()) {
2204 Register AddrReg = getRegForValue(PtrV);
2205 return emitStoreRelease(VT, SrcReg, AddrReg,
2206 createMachineMemOperandFor(
I));
2267bool AArch64FastISel::emitCompareAndBranch(
const BranchInst *BI) {
2271 if (FuncInfo.MF->getFunction().hasFnAttribute(
2272 Attribute::SpeculativeLoadHardening))
2294 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2301 switch (Predicate) {
2306 if (isa<Constant>(LHS) && cast<Constant>(LHS)->isNullValue())
2309 if (!isa<Constant>(RHS) || !cast<Constant>(RHS)->isNullValue())
2312 if (
const auto *AI = dyn_cast<BinaryOperator>(LHS))
2313 if (AI->
getOpcode() == Instruction::And && isValueAvailable(AI)) {
2317 if (
const auto *
C = dyn_cast<ConstantInt>(AndLHS))
2318 if (
C->getValue().isPowerOf2())
2321 if (
const auto *
C = dyn_cast<ConstantInt>(AndRHS))
2322 if (
C->getValue().isPowerOf2()) {
2323 TestBit =
C->getValue().logBase2();
2335 if (!isa<Constant>(RHS) || !cast<Constant>(RHS)->isNullValue())
2343 if (!isa<ConstantInt>(RHS))
2346 if (cast<ConstantInt>(RHS)->getValue() !=
APInt(BW, -1,
true))
2354 static const unsigned OpcTable[2][2][2] = {
2355 { {AArch64::CBZW, AArch64::CBZX },
2356 {AArch64::CBNZW, AArch64::CBNZX} },
2357 { {AArch64::TBZW, AArch64::TBZX },
2358 {AArch64::TBNZW, AArch64::TBNZX} }
2361 bool IsBitTest = TestBit != -1;
2362 bool Is64Bit = BW == 64;
2363 if (TestBit < 32 && TestBit >= 0)
2366 unsigned Opc = OpcTable[IsBitTest][IsCmpNE][Is64Bit];
2369 Register SrcReg = getRegForValue(LHS);
2373 if (BW == 64 && !Is64Bit)
2374 SrcReg = fastEmitInst_extractsubreg(MVT::i32, SrcReg, AArch64::sub_32);
2376 if ((BW < 32) && !IsBitTest)
2377 SrcReg = emitIntExt(VT, SrcReg, MVT::i32,
true);
2382 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc))
2392bool AArch64FastISel::selectBranch(
const Instruction *
I) {
2404 if (CI->
hasOneUse() && isValueAvailable(CI)) {
2407 switch (Predicate) {
2411 fastEmitBranch(FBB, MIMD.getDL());
2414 fastEmitBranch(
TBB, MIMD.getDL());
2419 if (emitCompareAndBranch(BI))
2423 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2436 switch (Predicate) {
2452 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2458 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2465 }
else if (
const auto *CI = dyn_cast<ConstantInt>(BI->
getCondition())) {
2468 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::B))
2477 FuncInfo.MBB->addSuccessorWithoutProb(
Target);
2489 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::Bcc))
2503 unsigned Opcode = AArch64::TBNZW;
2504 if (FuncInfo.MBB->isLayoutSuccessor(
TBB)) {
2512 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)
2513 .
addReg(ConstrainedCondReg)
2521bool AArch64FastISel::selectIndirectBr(
const Instruction *
I) {
2530 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II).
addReg(AddrReg);
2534 FuncInfo.MBB->addSuccessor(FuncInfo.MBBMap[Succ]);
2540 const CmpInst *CI = cast<CmpInst>(
I);
2548 unsigned ResultReg = 0;
2549 switch (Predicate) {
2553 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2554 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2555 TII.get(TargetOpcode::COPY), ResultReg)
2559 ResultReg = fastEmit_i(MVT::i32, MVT::i32,
ISD::Constant, 1);
2564 updateValueMap(
I, ResultReg);
2572 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2576 static unsigned CondCodeTable[2][2] = {
2581 switch (Predicate) {
2593 Register TmpReg1 = createResultReg(&AArch64::GPR32RegClass);
2594 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2599 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2605 updateValueMap(
I, ResultReg);
2613 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr),
2619 updateValueMap(
I, ResultReg);
2625bool AArch64FastISel::optimizeSelect(
const SelectInst *SI) {
2626 if (!
SI->getType()->isIntegerTy(1))
2629 const Value *Src1Val, *Src2Val;
2631 bool NeedExtraOp =
false;
2632 if (
auto *CI = dyn_cast<ConstantInt>(
SI->getTrueValue())) {
2634 Src1Val =
SI->getCondition();
2635 Src2Val =
SI->getFalseValue();
2636 Opc = AArch64::ORRWrr;
2639 Src1Val =
SI->getFalseValue();
2640 Src2Val =
SI->getCondition();
2641 Opc = AArch64::BICWrr;
2643 }
else if (
auto *CI = dyn_cast<ConstantInt>(
SI->getFalseValue())) {
2645 Src1Val =
SI->getCondition();
2646 Src2Val =
SI->getTrueValue();
2647 Opc = AArch64::ORRWrr;
2651 Src1Val =
SI->getCondition();
2652 Src2Val =
SI->getTrueValue();
2653 Opc = AArch64::ANDWrr;
2660 Register Src1Reg = getRegForValue(Src1Val);
2664 Register Src2Reg = getRegForValue(Src2Val);
2669 Src1Reg = emitLogicalOp_ri(
ISD::XOR, MVT::i32, Src1Reg, 1);
2671 Register ResultReg = fastEmitInst_rr(Opc, &AArch64::GPR32RegClass, Src1Reg,
2673 updateValueMap(SI, ResultReg);
2677bool AArch64FastISel::selectSelect(
const Instruction *
I) {
2678 assert(isa<SelectInst>(
I) &&
"Expected a select instruction.");
2680 if (!isTypeSupported(
I->getType(), VT))
2692 Opc = AArch64::CSELWr;
2693 RC = &AArch64::GPR32RegClass;
2696 Opc = AArch64::CSELXr;
2697 RC = &AArch64::GPR64RegClass;
2700 Opc = AArch64::FCSELSrrr;
2701 RC = &AArch64::FPR32RegClass;
2704 Opc = AArch64::FCSELDrrr;
2705 RC = &AArch64::FPR64RegClass;
2714 if (optimizeSelect(SI))
2718 if (foldXALUIntrinsic(
CC,
I,
Cond)) {
2723 }
else if (isa<CmpInst>(
Cond) && cast<CmpInst>(
Cond)->hasOneUse() &&
2724 isValueAvailable(
Cond)) {
2725 const auto *
Cmp = cast<CmpInst>(
Cond);
2728 const Value *FoldSelect =
nullptr;
2729 switch (Predicate) {
2733 FoldSelect =
SI->getFalseValue();
2736 FoldSelect =
SI->getTrueValue();
2741 Register SrcReg = getRegForValue(FoldSelect);
2745 updateValueMap(
I, SrcReg);
2755 switch (Predicate) {
2777 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II,
2783 Register Src1Reg = getRegForValue(
SI->getTrueValue());
2784 Register Src2Reg = getRegForValue(
SI->getFalseValue());
2786 if (!Src1Reg || !Src2Reg)
2790 Src2Reg = fastEmitInst_rri(Opc, RC, Src1Reg, Src2Reg, ExtraCC);
2792 Register ResultReg = fastEmitInst_rri(Opc, RC, Src1Reg, Src2Reg,
CC);
2793 updateValueMap(
I, ResultReg);
2797bool AArch64FastISel::selectFPExt(
const Instruction *
I) {
2799 if (!
I->getType()->isDoubleTy() || !
V->getType()->isFloatTy())
2806 Register ResultReg = createResultReg(&AArch64::FPR64RegClass);
2807 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTDSr),
2809 updateValueMap(
I, ResultReg);
2813bool AArch64FastISel::selectFPTrunc(
const Instruction *
I) {
2815 if (!
I->getType()->isFloatTy() || !
V->getType()->isDoubleTy())
2822 Register ResultReg = createResultReg(&AArch64::FPR32RegClass);
2823 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::FCVTSDr),
2825 updateValueMap(
I, ResultReg);
2832 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2835 Register SrcReg = getRegForValue(
I->getOperand(0));
2839 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2840 if (SrcVT == MVT::f128 || SrcVT == MVT::f16)
2844 if (SrcVT == MVT::f64) {
2846 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWDr : AArch64::FCVTZSUXDr;
2848 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWDr : AArch64::FCVTZUUXDr;
2851 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWSr : AArch64::FCVTZSUXSr;
2853 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWSr : AArch64::FCVTZUUXSr;
2855 Register ResultReg = createResultReg(
2856 DestVT == MVT::i32 ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass);
2857 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg)
2859 updateValueMap(
I, ResultReg);
2865 if (!isTypeLegal(
I->getType(), DestVT) || DestVT.
isVector())
2868 if (DestVT == MVT::f16)
2871 assert((DestVT == MVT::f32 || DestVT == MVT::f64) &&
2872 "Unexpected value type.");
2874 Register SrcReg = getRegForValue(
I->getOperand(0));
2878 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType(),
true);
2881 if (SrcVT == MVT::i16 || SrcVT == MVT::i8 || SrcVT == MVT::i1) {
2889 if (SrcVT == MVT::i64) {
2891 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUXSri : AArch64::SCVTFUXDri;
2893 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUXSri : AArch64::UCVTFUXDri;
2896 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUWSri : AArch64::SCVTFUWDri;
2898 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUWSri : AArch64::UCVTFUWDri;
2901 Register ResultReg = fastEmitInst_r(Opc, TLI.getRegClassFor(DestVT), SrcReg);
2902 updateValueMap(
I, ResultReg);
2906bool AArch64FastISel::fastLowerArguments() {
2907 if (!FuncInfo.CanLowerReturn)
2918 if (Subtarget->hasCustomCallingConv())
2922 unsigned GPRCnt = 0;
2923 unsigned FPRCnt = 0;
2924 for (
auto const &Arg :
F->args()) {
2925 if (Arg.hasAttribute(Attribute::ByVal) ||
2926 Arg.hasAttribute(Attribute::InReg) ||
2927 Arg.hasAttribute(Attribute::StructRet) ||
2928 Arg.hasAttribute(Attribute::SwiftSelf) ||
2929 Arg.hasAttribute(Attribute::SwiftAsync) ||
2930 Arg.hasAttribute(Attribute::SwiftError) ||
2931 Arg.hasAttribute(Attribute::Nest))
2934 Type *ArgTy = Arg.getType();
2938 EVT ArgVT = TLI.getValueType(
DL, ArgTy);
2947 (!Subtarget->hasNEON() || !Subtarget->isLittleEndian()))
2950 if (VT >= MVT::i1 && VT <= MVT::i64)
2952 else if ((VT >= MVT::f16 && VT <= MVT::f64) || VT.
is64BitVector() ||
2958 if (GPRCnt > 8 || FPRCnt > 8)
2963 { AArch64::W0, AArch64::W1, AArch64::W2, AArch64::W3, AArch64::W4,
2964 AArch64::W5, AArch64::W6, AArch64::W7 },
2965 { AArch64::X0, AArch64::X1, AArch64::X2, AArch64::X3, AArch64::X4,
2966 AArch64::X5, AArch64::X6, AArch64::X7 },
2967 { AArch64::H0, AArch64::H1, AArch64::H2, AArch64::H3, AArch64::H4,
2968 AArch64::H5, AArch64::H6, AArch64::H7 },
2969 { AArch64::S0, AArch64::S1, AArch64::S2, AArch64::S3, AArch64::S4,
2970 AArch64::S5, AArch64::S6, AArch64::S7 },
2971 { AArch64::D0, AArch64::D1, AArch64::D2, AArch64::D3, AArch64::D4,
2972 AArch64::D5, AArch64::D6, AArch64::D7 },
2973 { AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,
2974 AArch64::Q5, AArch64::Q6, AArch64::Q7 }
2978 unsigned FPRIdx = 0;
2979 for (
auto const &Arg :
F->args()) {
2980 MVT VT = TLI.getSimpleValueType(
DL, Arg.getType());
2983 if (VT >= MVT::i1 && VT <= MVT::i32) {
2985 RC = &AArch64::GPR32RegClass;
2987 }
else if (VT == MVT::i64) {
2989 RC = &AArch64::GPR64RegClass;
2990 }
else if (VT == MVT::f16) {
2992 RC = &AArch64::FPR16RegClass;
2993 }
else if (VT == MVT::f32) {
2995 RC = &AArch64::FPR32RegClass;
2998 RC = &AArch64::FPR64RegClass;
3001 RC = &AArch64::FPR128RegClass;
3005 Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
3009 Register ResultReg = createResultReg(RC);
3010 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3011 TII.get(TargetOpcode::COPY), ResultReg)
3013 updateValueMap(&Arg, ResultReg);
3018bool AArch64FastISel::processCallArgs(CallLoweringInfo &CLI,
3020 unsigned &NumBytes) {
3023 CCState CCInfo(
CC,
false, *FuncInfo.MF, ArgLocs, *Context);
3024 CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, CCAssignFnForCall(
CC));
3027 NumBytes = CCInfo.getStackSize();
3030 unsigned AdjStackDown =
TII.getCallFrameSetupOpcode();
3031 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackDown))
3036 const Value *ArgVal = CLI.OutVals[VA.getValNo()];
3037 MVT ArgVT = OutVTs[VA.getValNo()];
3039 Register ArgReg = getRegForValue(ArgVal);
3044 switch (VA.getLocInfo()) {
3048 MVT DestVT = VA.getLocVT();
3050 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
false);
3058 MVT DestVT = VA.getLocVT();
3060 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT,
true);
3070 if (VA.isRegLoc() && !VA.needsCustom()) {
3071 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3072 TII.get(TargetOpcode::COPY), VA.getLocReg()).
addReg(ArgReg);
3073 CLI.OutRegs.push_back(VA.getLocReg());
3074 }
else if (VA.needsCustom()) {
3078 assert(VA.isMemLoc() &&
"Assuming store on stack.");
3081 if (isa<UndefValue>(ArgVal))
3087 unsigned BEAlign = 0;
3088 if (ArgSize < 8 && !Subtarget->isLittleEndian())
3089 BEAlign = 8 - ArgSize;
3092 Addr.setKind(Address::RegBase);
3093 Addr.setReg(AArch64::SP);
3094 Addr.setOffset(VA.getLocMemOffset() + BEAlign);
3108bool AArch64FastISel::finishCall(CallLoweringInfo &CLI,
unsigned NumBytes) {
3112 unsigned AdjStackUp =
TII.getCallFrameDestroyOpcode();
3113 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackUp))
3118 CCState CCInfo(
CC,
false, *FuncInfo.MF, RVLocs, *Context);
3119 CCInfo.AnalyzeCallResult(CLI.Ins, CCAssignFnForCall(
CC));
3121 Register ResultReg = FuncInfo.CreateRegs(CLI.RetTy);
3122 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
3125 unsigned CopyReg = ResultReg + i;
3128 if (CopyVT.
isVector() && !Subtarget->isLittleEndian())
3132 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
3138 CLI.ResultReg = ResultReg;
3139 CLI.NumResultRegs = RVLocs.
size();
3144bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
3146 bool IsTailCall = CLI.IsTailCall;
3147 bool IsVarArg = CLI.IsVarArg;
3151 if (!Callee && !Symbol)
3156 if (CLI.CB && CLI.CB->hasFnAttr(Attribute::ReturnsTwice) &&
3157 !Subtarget->noBTIAtReturnTwice() &&
3162 if (CLI.CB && CLI.CB->isIndirectCall() &&
3172 if (Subtarget->isTargetILP32())
3188 for (
auto Flag : CLI.OutFlags)
3190 Flag.isSwiftSelf() ||
Flag.isSwiftAsync() ||
Flag.isSwiftError())
3195 OutVTs.
reserve(CLI.OutVals.size());
3197 for (
auto *Val : CLI.OutVals) {
3199 if (!isTypeLegal(Val->getType(), VT) &&
3200 !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16))
3211 if (Callee && !computeCallAddress(Callee,
Addr))
3217 if (Subtarget->isTargetWindows() &&
Addr.getGlobalValue() &&
3218 Addr.getGlobalValue()->hasExternalWeakLinkage())
3223 if (!processCallArgs(CLI, OutVTs, NumBytes))
3227 if (
RegInfo->isAnyArgRegReserved(*MF))
3228 RegInfo->emitReservedArgRegCallError(*MF);
3232 if (Subtarget->useSmallAddressing()) {
3235 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II);
3238 else if (
Addr.getGlobalValue())
3240 else if (
Addr.getReg()) {
3246 unsigned CallReg = 0;
3248 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
3249 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::ADRP),
3253 CallReg = createResultReg(&AArch64::GPR64RegClass);
3254 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3255 TII.get(AArch64::LDRXui), CallReg)
3259 }
else if (
Addr.getGlobalValue())
3260 CallReg = materializeGV(
Addr.getGlobalValue());
3261 else if (
Addr.getReg())
3262 CallReg =
Addr.getReg();
3269 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II).
addReg(CallReg);
3273 for (
auto Reg : CLI.OutRegs)
3283 return finishCall(CLI, NumBytes);
3288 return Len / Alignment->value() <= 4;
3293bool AArch64FastISel::tryEmitSmallMemCpy(Address Dest, Address Src,
3296 if (!isMemCpySmall(Len, Alignment))
3299 int64_t UnscaledOffset = 0;
3305 if (!Alignment || *Alignment >= 8) {
3316 assert(Alignment &&
"Alignment is set in this branch");
3318 if (Len >= 4 && *Alignment == 4)
3320 else if (Len >= 2 && *Alignment == 2)
3327 unsigned ResultReg =
emitLoad(VT, VT, Src);
3336 UnscaledOffset +=
Size;
3339 Dest.setOffset(OrigDest.getOffset() + UnscaledOffset);
3340 Src.setOffset(OrigSrc.getOffset() + UnscaledOffset);
3351 if (!isa<ExtractValueInst>(
Cond))
3354 const auto *EV = cast<ExtractValueInst>(
Cond);
3355 if (!isa<IntrinsicInst>(EV->getAggregateOperand()))
3358 const auto *II = cast<IntrinsicInst>(EV->getAggregateOperand());
3362 cast<StructType>(
Callee->getReturnType())->getTypeAtIndex(0U);
3363 if (!isTypeLegal(
RetTy, RetVT))
3366 if (RetVT != MVT::i32 && RetVT != MVT::i64)
3369 const Value *
LHS = II->getArgOperand(0);
3370 const Value *
RHS = II->getArgOperand(1);
3373 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS) && II->isCommutative())
3381 case Intrinsic::smul_with_overflow:
3382 if (
const auto *
C = dyn_cast<ConstantInt>(RHS))
3383 if (
C->getValue() == 2)
3384 IID = Intrinsic::sadd_with_overflow;
3386 case Intrinsic::umul_with_overflow:
3387 if (
const auto *
C = dyn_cast<ConstantInt>(RHS))
3388 if (
C->getValue() == 2)
3389 IID = Intrinsic::uadd_with_overflow;
3397 case Intrinsic::sadd_with_overflow:
3398 case Intrinsic::ssub_with_overflow:
3401 case Intrinsic::uadd_with_overflow:
3404 case Intrinsic::usub_with_overflow:
3407 case Intrinsic::smul_with_overflow:
3408 case Intrinsic::umul_with_overflow:
3414 if (!isValueAvailable(II))
3420 for (
auto Itr = std::prev(Start); Itr !=
End; --Itr) {
3423 if (!isa<ExtractValueInst>(Itr))
3427 const auto *EVI = cast<ExtractValueInst>(Itr);
3428 if (EVI->getAggregateOperand() != II)
3436bool AArch64FastISel::fastLowerIntrinsicCall(
const IntrinsicInst *II) {
3439 default:
return false;
3440 case Intrinsic::frameaddress: {
3446 Register SrcReg =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3447 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3455 unsigned Depth = cast<ConstantInt>(II->
getOperand(0))->getZExtValue();
3457 DestReg = fastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,
3459 assert(DestReg &&
"Unexpected LDR instruction emission failure.");
3463 updateValueMap(II, SrcReg);
3466 case Intrinsic::sponentry: {
3471 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);
3472 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3473 TII.get(AArch64::ADDXri), ResultReg)
3478 updateValueMap(II, ResultReg);
3481 case Intrinsic::memcpy:
3482 case Intrinsic::memmove: {
3483 const auto *MTI = cast<MemTransferInst>(II);
3485 if (MTI->isVolatile())
3491 if (isa<ConstantInt>(MTI->getLength()) && IsMemCpy) {
3494 uint64_t Len = cast<ConstantInt>(MTI->getLength())->getZExtValue();
3496 if (MTI->getDestAlign() || MTI->getSourceAlign())
3497 Alignment = std::min(MTI->getDestAlign().valueOrOne(),
3498 MTI->getSourceAlign().valueOrOne());
3499 if (isMemCpySmall(Len, Alignment)) {
3501 if (!computeAddress(MTI->getRawDest(), Dest) ||
3502 !computeAddress(MTI->getRawSource(), Src))
3504 if (tryEmitSmallMemCpy(Dest, Src, Len, Alignment))
3509 if (!MTI->getLength()->getType()->isIntegerTy(64))
3512 if (MTI->getSourceAddressSpace() > 255 || MTI->getDestAddressSpace() > 255)
3517 const char *IntrMemName = isa<MemCpyInst>(II) ?
"memcpy" :
"memmove";
3518 return lowerCallTo(II, IntrMemName, II->
arg_size() - 1);
3520 case Intrinsic::memset: {
3521 const MemSetInst *MSI = cast<MemSetInst>(II);
3534 return lowerCallTo(II,
"memset", II->
arg_size() - 1);
3536 case Intrinsic::sin:
3537 case Intrinsic::cos:
3538 case Intrinsic::pow: {
3540 if (!isTypeLegal(II->
getType(), RetVT))
3543 if (RetVT != MVT::f32 && RetVT != MVT::f64)
3547 { RTLIB::SIN_F32, RTLIB::SIN_F64 },
3548 { RTLIB::COS_F32, RTLIB::COS_F64 },
3549 { RTLIB::POW_F32, RTLIB::POW_F64 }
3552 bool Is64Bit = RetVT == MVT::f64;
3556 case Intrinsic::sin:
3557 LC = LibCallTable[0][Is64Bit];
3559 case Intrinsic::cos:
3560 LC = LibCallTable[1][Is64Bit];
3562 case Intrinsic::pow:
3563 LC = LibCallTable[2][Is64Bit];
3571 for (
auto &Arg : II->
args()) {
3574 Entry.Ty = Arg->getType();
3575 Args.push_back(Entry);
3578 CallLoweringInfo CLI;
3580 CLI.setCallee(
DL, Ctx, TLI.getLibcallCallingConv(LC), II->
getType(),
3581 TLI.getLibcallName(LC), std::move(Args));
3582 if (!lowerCallTo(CLI))
3584 updateValueMap(II, CLI.ResultReg);
3587 case Intrinsic::fabs: {
3589 if (!isTypeLegal(II->
getType(), VT))
3597 Opc = AArch64::FABSSr;
3600 Opc = AArch64::FABSDr;
3606 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3607 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg)
3609 updateValueMap(II, ResultReg);
3612 case Intrinsic::trap:
3613 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3616 case Intrinsic::debugtrap:
3617 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::BRK))
3621 case Intrinsic::sqrt: {
3625 if (!isTypeLegal(
RetTy, VT))
3632 unsigned ResultReg = fastEmit_r(VT, VT,
ISD::FSQRT, Op0Reg);
3636 updateValueMap(II, ResultReg);
3639 case Intrinsic::sadd_with_overflow:
3640 case Intrinsic::uadd_with_overflow:
3641 case Intrinsic::ssub_with_overflow:
3642 case Intrinsic::usub_with_overflow:
3643 case Intrinsic::smul_with_overflow:
3644 case Intrinsic::umul_with_overflow: {
3647 auto *Ty = cast<StructType>(
Callee->getReturnType());
3651 if (!isTypeLegal(
RetTy, VT))
3654 if (VT != MVT::i32 && VT != MVT::i64)
3660 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS) && II->
isCommutative())
3668 case Intrinsic::smul_with_overflow:
3669 if (
const auto *
C = dyn_cast<ConstantInt>(RHS))
3670 if (
C->getValue() == 2) {
3671 IID = Intrinsic::sadd_with_overflow;
3675 case Intrinsic::umul_with_overflow:
3676 if (
const auto *
C = dyn_cast<ConstantInt>(RHS))
3677 if (
C->getValue() == 2) {
3678 IID = Intrinsic::uadd_with_overflow;
3684 unsigned ResultReg1 = 0, ResultReg2 = 0, MulReg = 0;
3688 case Intrinsic::sadd_with_overflow:
3689 ResultReg1 = emitAdd(VT, LHS, RHS,
true);
3692 case Intrinsic::uadd_with_overflow:
3693 ResultReg1 = emitAdd(VT, LHS, RHS,
true);
3696 case Intrinsic::ssub_with_overflow:
3697 ResultReg1 = emitSub(VT, LHS, RHS,
true);
3700 case Intrinsic::usub_with_overflow:
3701 ResultReg1 = emitSub(VT, LHS, RHS,
true);
3704 case Intrinsic::smul_with_overflow: {
3706 Register LHSReg = getRegForValue(LHS);
3710 Register RHSReg = getRegForValue(RHS);
3714 if (VT == MVT::i32) {
3715 MulReg = emitSMULL_rr(MVT::i64, LHSReg, RHSReg);
3717 fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3719 emitAddSub_rx(
false, MVT::i64, MulReg, MulSubReg,
3724 assert(VT == MVT::i64 &&
"Unexpected value type.");
3727 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3728 unsigned SMULHReg = fastEmit_rr(VT, VT,
ISD::MULHS, LHSReg, RHSReg);
3734 case Intrinsic::umul_with_overflow: {
3736 Register LHSReg = getRegForValue(LHS);
3740 Register RHSReg = getRegForValue(RHS);
3744 if (VT == MVT::i32) {
3745 MulReg = emitUMULL_rr(MVT::i64, LHSReg, RHSReg);
3747 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3748 TII.get(AArch64::ANDSXri), AArch64::XZR)
3751 MulReg = fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);
3753 assert(VT == MVT::i64 &&
"Unexpected value type.");
3756 MulReg = emitMul_rr(VT, LHSReg, RHSReg);
3757 unsigned UMULHReg = fastEmit_rr(VT, VT,
ISD::MULHU, LHSReg, RHSReg);
3758 emitSubs_rr(VT, AArch64::XZR, UMULHReg,
false);
3765 ResultReg1 = createResultReg(TLI.getRegClassFor(VT));
3766 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3767 TII.get(TargetOpcode::COPY), ResultReg1).
addReg(MulReg);
3773 ResultReg2 = fastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,
3774 AArch64::WZR, AArch64::WZR,
3775 getInvertedCondCode(
CC));
3777 assert((ResultReg1 + 1) == ResultReg2 &&
3778 "Nonconsecutive result registers.");
3779 updateValueMap(II, ResultReg1, 2);
3782 case Intrinsic::aarch64_crc32b:
3783 case Intrinsic::aarch64_crc32h:
3784 case Intrinsic::aarch64_crc32w:
3785 case Intrinsic::aarch64_crc32x:
3786 case Intrinsic::aarch64_crc32cb:
3787 case Intrinsic::aarch64_crc32ch:
3788 case Intrinsic::aarch64_crc32cw:
3789 case Intrinsic::aarch64_crc32cx: {
3790 if (!Subtarget->hasCRC())
3797 case Intrinsic::aarch64_crc32b:
3798 Opc = AArch64::CRC32Brr;
3800 case Intrinsic::aarch64_crc32h:
3801 Opc = AArch64::CRC32Hrr;
3803 case Intrinsic::aarch64_crc32w:
3804 Opc = AArch64::CRC32Wrr;
3806 case Intrinsic::aarch64_crc32x:
3807 Opc = AArch64::CRC32Xrr;
3809 case Intrinsic::aarch64_crc32cb:
3810 Opc = AArch64::CRC32CBrr;
3812 case Intrinsic::aarch64_crc32ch:
3813 Opc = AArch64::CRC32CHrr;
3815 case Intrinsic::aarch64_crc32cw:
3816 Opc = AArch64::CRC32CWrr;
3818 case Intrinsic::aarch64_crc32cx:
3819 Opc = AArch64::CRC32CXrr;
3825 if (!LHSReg || !RHSReg)
3829 fastEmitInst_rr(Opc, &AArch64::GPR32RegClass, LHSReg, RHSReg);
3830 updateValueMap(II, ResultReg);
3839 const Function &
F = *
I->getParent()->getParent();
3841 if (!FuncInfo.CanLowerReturn)
3847 if (TLI.supportSwiftError() &&
3848 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
3851 if (TLI.supportSplitCSR(FuncInfo.MF))
3857 if (
Ret->getNumOperands() > 0) {
3864 CCState CCInfo(
CC,
F.isVarArg(), *FuncInfo.MF, ValLocs,
I->getContext());
3868 if (ValLocs.
size() != 1)
3872 const Value *RV =
Ret->getOperand(0);
3890 if (!
MRI.getRegClass(SrcReg)->contains(DestReg))
3899 !Subtarget->isLittleEndian())
3903 if (RVVT == MVT::f128)
3908 if (RVVT != DestVT) {
3909 if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
3912 if (!Outs[0].
Flags.isZExt() && !Outs[0].Flags.isSExt())
3915 bool IsZExt = Outs[0].Flags.isZExt();
3916 SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
3924 SrcReg = emitAnd_ri(MVT::i64, SrcReg, 0xffffffff);
3927 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3928 TII.get(TargetOpcode::COPY), DestReg).
addReg(SrcReg);
3935 TII.get(AArch64::RET_ReallyLR));
3936 for (
unsigned RetReg : RetRegs)
3941bool AArch64FastISel::selectTrunc(
const Instruction *
I) {
3942 Type *DestTy =
I->getType();
3944 Type *SrcTy =
Op->getType();
3946 EVT SrcEVT = TLI.getValueType(
DL, SrcTy,
true);
3947 EVT DestEVT = TLI.getValueType(
DL, DestTy,
true);
3956 if (SrcVT != MVT::i64 && SrcVT != MVT::i32 && SrcVT != MVT::i16 &&
3959 if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8 &&
3973 if (SrcVT == MVT::i64) {
3990 Register Reg32 = fastEmitInst_extractsubreg(MVT::i32, SrcReg,
3993 ResultReg = emitAnd_ri(MVT::i32, Reg32, Mask);
3994 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
3996 ResultReg = createResultReg(&AArch64::GPR32RegClass);
3997 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3998 TII.get(TargetOpcode::COPY), ResultReg)
4002 updateValueMap(
I, ResultReg);
4006unsigned AArch64FastISel::emiti1Ext(
unsigned SrcReg,
MVT DestVT,
bool IsZExt) {
4007 assert((DestVT == MVT::i8 || DestVT == MVT::i16 || DestVT == MVT::i32 ||
4008 DestVT == MVT::i64) &&
4009 "Unexpected value type.");
4011 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4015 unsigned ResultReg = emitAnd_ri(MVT::i32, SrcReg, 1);
4016 assert(ResultReg &&
"Unexpected AND instruction emission failure.");
4017 if (DestVT == MVT::i64) {
4020 Register Reg64 =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4021 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4022 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4025 .
addImm(AArch64::sub_32);
4030 if (DestVT == MVT::i64) {
4034 return fastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,
4039unsigned AArch64FastISel::emitMul_rr(
MVT RetVT,
unsigned Op0,
unsigned Op1) {
4047 Opc = AArch64::MADDWrrr; ZReg = AArch64::WZR;
break;
4049 Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR;
break;
4053 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4054 return fastEmitInst_rrr(Opc, RC, Op0, Op1, ZReg);
4057unsigned AArch64FastISel::emitSMULL_rr(
MVT RetVT,
unsigned Op0,
unsigned Op1) {
4058 if (RetVT != MVT::i64)
4061 return fastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,
4062 Op0, Op1, AArch64::XZR);
4065unsigned AArch64FastISel::emitUMULL_rr(
MVT RetVT,
unsigned Op0,
unsigned Op1) {
4066 if (RetVT != MVT::i64)
4069 return fastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,
4070 Op0, Op1, AArch64::XZR);
4073unsigned AArch64FastISel::emitLSL_rr(
MVT RetVT,
unsigned Op0Reg,
4076 bool NeedTrunc =
false;
4080 case MVT::i8: Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4081 case MVT::i16: Opc = AArch64::LSLVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4082 case MVT::i32: Opc = AArch64::LSLVWr;
break;
4083 case MVT::i64: Opc = AArch64::LSLVXr;
break;
4087 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4089 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4091 Register ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op1Reg);
4093 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4097unsigned AArch64FastISel::emitLSL_ri(
MVT RetVT,
MVT SrcVT,
unsigned Op0,
4100 "Unexpected source/return type pair.");
4101 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4102 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4103 "Unexpected source value type.");
4104 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4105 RetVT == MVT::i64) &&
"Unexpected return value type.");
4107 bool Is64Bit = (RetVT == MVT::i64);
4108 unsigned RegSize = Is64Bit ? 64 : 32;
4112 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4116 if (RetVT == SrcVT) {
4117 Register ResultReg = createResultReg(RC);
4118 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4119 TII.get(TargetOpcode::COPY), ResultReg)
4123 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4127 if (Shift >= DstBits)
4155 unsigned ImmR =
RegSize - Shift;
4157 unsigned ImmS = std::min<unsigned>(SrcBits - 1, DstBits - 1 - Shift);
4158 static const unsigned OpcTable[2][2] = {
4159 {AArch64::SBFMWri, AArch64::SBFMXri},
4160 {AArch64::UBFMWri, AArch64::UBFMXri}
4162 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4163 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4165 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4166 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4169 .
addImm(AArch64::sub_32);
4172 return fastEmitInst_rii(Opc, RC, Op0, ImmR, ImmS);
4175unsigned AArch64FastISel::emitLSR_rr(
MVT RetVT,
unsigned Op0Reg,
4178 bool NeedTrunc =
false;
4182 case MVT::i8: Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4183 case MVT::i16: Opc = AArch64::LSRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4184 case MVT::i32: Opc = AArch64::LSRVWr;
break;
4185 case MVT::i64: Opc = AArch64::LSRVXr;
break;
4189 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4191 Op0Reg = emitAnd_ri(MVT::i32, Op0Reg, Mask);
4192 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4194 Register ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op1Reg);
4196 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4200unsigned AArch64FastISel::emitLSR_ri(
MVT RetVT,
MVT SrcVT,
unsigned Op0,
4203 "Unexpected source/return type pair.");
4204 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4205 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4206 "Unexpected source value type.");
4207 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4208 RetVT == MVT::i64) &&
"Unexpected return value type.");
4210 bool Is64Bit = (RetVT == MVT::i64);
4211 unsigned RegSize = Is64Bit ? 64 : 32;
4215 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4219 if (RetVT == SrcVT) {
4220 Register ResultReg = createResultReg(RC);
4221 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4222 TII.get(TargetOpcode::COPY), ResultReg)
4226 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4230 if (Shift >= DstBits)
4258 if (Shift >= SrcBits && IsZExt)
4264 Op0 = emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4272 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4273 unsigned ImmS = SrcBits - 1;
4274 static const unsigned OpcTable[2][2] = {
4275 {AArch64::SBFMWri, AArch64::SBFMXri},
4276 {AArch64::UBFMWri, AArch64::UBFMXri}
4278 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4279 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4281 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4282 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4285 .
addImm(AArch64::sub_32);
4288 return fastEmitInst_rii(Opc, RC, Op0, ImmR, ImmS);
4291unsigned AArch64FastISel::emitASR_rr(
MVT RetVT,
unsigned Op0Reg,
4294 bool NeedTrunc =
false;
4298 case MVT::i8: Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xff;
break;
4299 case MVT::i16: Opc = AArch64::ASRVWr; NeedTrunc =
true;
Mask = 0xffff;
break;
4300 case MVT::i32: Opc = AArch64::ASRVWr;
break;
4301 case MVT::i64: Opc = AArch64::ASRVXr;
break;
4305 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4307 Op0Reg = emitIntExt(RetVT, Op0Reg, MVT::i32,
false);
4308 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);
4310 Register ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op1Reg);
4312 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);
4316unsigned AArch64FastISel::emitASR_ri(
MVT RetVT,
MVT SrcVT,
unsigned Op0,
4319 "Unexpected source/return type pair.");
4320 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4321 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4322 "Unexpected source value type.");
4323 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4324 RetVT == MVT::i64) &&
"Unexpected return value type.");
4326 bool Is64Bit = (RetVT == MVT::i64);
4327 unsigned RegSize = Is64Bit ? 64 : 32;
4331 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4335 if (RetVT == SrcVT) {
4336 Register ResultReg = createResultReg(RC);
4337 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4338 TII.get(TargetOpcode::COPY), ResultReg)
4342 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
4346 if (Shift >= DstBits)
4374 if (Shift >= SrcBits && IsZExt)
4377 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4378 unsigned ImmS = SrcBits - 1;
4379 static const unsigned OpcTable[2][2] = {
4380 {AArch64::SBFMWri, AArch64::SBFMXri},
4381 {AArch64::UBFMWri, AArch64::UBFMXri}
4383 unsigned Opc = OpcTable[IsZExt][Is64Bit];
4384 if (SrcVT.
SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4386 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4387 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4390 .
addImm(AArch64::sub_32);
4393 return fastEmitInst_rii(Opc, RC, Op0, ImmR, ImmS);
4396unsigned AArch64FastISel::emitIntExt(
MVT SrcVT,
unsigned SrcReg,
MVT DestVT,
4398 assert(DestVT != MVT::i1 &&
"ZeroExt/SignExt an i1?");
4404 if (((DestVT != MVT::i8) && (DestVT != MVT::i16) &&
4405 (DestVT != MVT::i32) && (DestVT != MVT::i64)) ||
4406 ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) &&
4407 (SrcVT != MVT::i16) && (SrcVT != MVT::i32)))
4417 return emiti1Ext(SrcReg, DestVT, IsZExt);
4419 if (DestVT == MVT::i64)
4420 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4422 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4426 if (DestVT == MVT::i64)
4427 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4429 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
4433 assert(DestVT == MVT::i64 &&
"IntExt i32 to i32?!?");
4434 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
4440 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4442 else if (DestVT == MVT::i64) {
4443 Register Src64 =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4444 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4445 TII.get(AArch64::SUBREG_TO_REG), Src64)
4448 .
addImm(AArch64::sub_32);
4453 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4454 return fastEmitInst_rii(Opc, RC, SrcReg, 0, Imm);
4461 case AArch64::LDURBBi:
4462 case AArch64::LDURHHi:
4463 case AArch64::LDURWi:
4464 case AArch64::LDRBBui:
4465 case AArch64::LDRHHui:
4466 case AArch64::LDRWui:
4467 case AArch64::LDRBBroX:
4468 case AArch64::LDRHHroX:
4469 case AArch64::LDRWroX:
4470 case AArch64::LDRBBroW:
4471 case AArch64::LDRHHroW:
4472 case AArch64::LDRWroW:
4481 case AArch64::LDURSBWi:
4482 case AArch64::LDURSHWi:
4483 case AArch64::LDURSBXi:
4484 case AArch64::LDURSHXi:
4485 case AArch64::LDURSWi:
4486 case AArch64::LDRSBWui:
4487 case AArch64::LDRSHWui:
4488 case AArch64::LDRSBXui:
4489 case AArch64::LDRSHXui:
4490 case AArch64::LDRSWui:
4491 case AArch64::LDRSBWroX:
4492 case AArch64::LDRSHWroX:
4493 case AArch64::LDRSBXroX:
4494 case AArch64::LDRSHXroX:
4495 case AArch64::LDRSWroX:
4496 case AArch64::LDRSBWroW:
4497 case AArch64::LDRSHWroW:
4498 case AArch64::LDRSBXroW:
4499 case AArch64::LDRSHXroW:
4500 case AArch64::LDRSWroW:
4505bool AArch64FastISel::optimizeIntExtLoad(
const Instruction *
I,
MVT RetVT,
4507 const auto *LI = dyn_cast<LoadInst>(
I->getOperand(0));
4508 if (!LI || !LI->hasOneUse())
4522 bool IsZExt = isa<ZExtInst>(
I);
4523 const auto *LoadMI =
MI;
4524 if (LoadMI->getOpcode() == TargetOpcode::COPY &&
4525 LoadMI->getOperand(1).getSubReg() == AArch64::sub_32) {
4526 Register LoadReg =
MI->getOperand(1).getReg();
4527 LoadMI =
MRI.getUniqueVRegDef(LoadReg);
4528 assert(LoadMI &&
"Expected valid instruction");
4534 if (RetVT != MVT::i64 || SrcVT > MVT::i32) {
4535 updateValueMap(
I, Reg);
4540 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);
4541 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4542 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4545 .
addImm(AArch64::sub_32);
4548 assert((
MI->getOpcode() == TargetOpcode::COPY &&
4549 MI->getOperand(1).getSubReg() == AArch64::sub_32) &&
4550 "Expected copy instruction");
4551 Reg =
MI->getOperand(1).getReg();
4553 removeDeadCode(
I, std::next(
I));
4555 updateValueMap(
I, Reg);
4559bool AArch64FastISel::selectIntExt(
const Instruction *
I) {
4560 assert((isa<ZExtInst>(
I) || isa<SExtInst>(
I)) &&
4561 "Unexpected integer extend instruction.");
4564 if (!isTypeSupported(
I->getType(), RetVT))
4567 if (!isTypeSupported(
I->getOperand(0)->getType(), SrcVT))
4571 if (optimizeIntExtLoad(
I, RetVT, SrcVT))
4574 Register SrcReg = getRegForValue(
I->getOperand(0));
4579 bool IsZExt = isa<ZExtInst>(
I);
4580 if (
const auto *Arg = dyn_cast<Argument>(
I->getOperand(0))) {
4581 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr())) {
4582 if (RetVT == MVT::i64 && SrcVT != MVT::i64) {
4583 Register ResultReg = createResultReg(&AArch64::GPR64RegClass);
4584 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
4585 TII.get(AArch64::SUBREG_TO_REG), ResultReg)
4588 .
addImm(AArch64::sub_32);
4592 updateValueMap(
I, SrcReg);
4597 unsigned ResultReg = emitIntExt(SrcVT, SrcReg, RetVT, IsZExt);
4601 updateValueMap(
I, ResultReg);
4605bool AArch64FastISel::selectRem(
const Instruction *
I,
unsigned ISDOpcode) {
4606 EVT DestEVT = TLI.getValueType(
DL,
I->getType(),
true);
4611 if (DestVT != MVT::i64 && DestVT != MVT::i32)
4615 bool Is64bit = (DestVT == MVT::i64);
4616 switch (ISDOpcode) {
4620 DivOpc = Is64bit ? AArch64::SDIVXr : AArch64::SDIVWr;
4623 DivOpc = Is64bit ? AArch64::UDIVXr : AArch64::UDIVWr;
4626 unsigned MSubOpc = Is64bit ? AArch64::MSUBXrrr : AArch64::MSUBWrrr;
4627 Register Src0Reg = getRegForValue(
I->getOperand(0));
4631 Register Src1Reg = getRegForValue(
I->getOperand(1));
4636 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4637 Register QuotReg = fastEmitInst_rr(DivOpc, RC, Src0Reg, Src1Reg);
4638 assert(QuotReg &&
"Unexpected DIV instruction emission failure.");
4641 Register ResultReg = fastEmitInst_rrr(MSubOpc, RC, QuotReg, Src1Reg, Src0Reg);
4642 updateValueMap(
I, ResultReg);
4648 if (!isTypeSupported(
I->getType(), VT,
true))
4654 const Value *Src0 =
I->getOperand(0);
4655 const Value *Src1 =
I->getOperand(1);
4656 if (
const auto *
C = dyn_cast<ConstantInt>(Src0))
4657 if (
C->getValue().isPowerOf2())
4661 if (
const auto *
C = dyn_cast<ConstantInt>(Src1))
4662 if (
C->getValue().isPowerOf2()) {
4663 uint64_t ShiftVal =
C->getValue().logBase2();
4666 if (
const auto *ZExt = dyn_cast<ZExtInst>(Src0)) {
4669 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), VT)) {
4672 Src0 = ZExt->getOperand(0);
4675 }
else if (
const auto *SExt = dyn_cast<SExtInst>(Src0)) {
4678 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), VT)) {
4681 Src0 = SExt->getOperand(0);
4686 Register Src0Reg = getRegForValue(Src0);
4690 unsigned ResultReg =
4691 emitLSL_ri(VT, SrcVT, Src0Reg, ShiftVal, IsZExt);
4694 updateValueMap(
I, ResultReg);
4699 Register Src0Reg = getRegForValue(
I->getOperand(0));
4703 Register Src1Reg = getRegForValue(
I->getOperand(1));
4707 unsigned ResultReg = emitMul_rr(VT, Src0Reg, Src1Reg);
4712 updateValueMap(
I, ResultReg);
4716bool AArch64FastISel::selectShift(
const Instruction *
I) {
4718 if (!isTypeSupported(
I->getType(), RetVT,
true))
4722 return selectOperator(
I,
I->getOpcode());
4724 if (
const auto *
C = dyn_cast<ConstantInt>(
I->getOperand(1))) {
4725 unsigned ResultReg = 0;
4728 bool IsZExt =
I->getOpcode() != Instruction::AShr;
4729 const Value *Op0 =
I->getOperand(0);
4730 if (
const auto *ZExt = dyn_cast<ZExtInst>(Op0)) {
4733 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), TmpVT)) {
4736 Op0 = ZExt->getOperand(0);
4739 }
else if (
const auto *SExt = dyn_cast<SExtInst>(Op0)) {
4742 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), TmpVT)) {
4745 Op0 = SExt->getOperand(0);
4750 Register Op0Reg = getRegForValue(Op0);
4754 switch (
I->getOpcode()) {
4756 case Instruction::Shl:
4757 ResultReg = emitLSL_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4759 case Instruction::AShr:
4760 ResultReg = emitASR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4762 case Instruction::LShr:
4763 ResultReg = emitLSR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);
4769 updateValueMap(
I, ResultReg);
4773 Register Op0Reg = getRegForValue(
I->getOperand(0));
4777 Register Op1Reg = getRegForValue(
I->getOperand(1));
4781 unsigned ResultReg = 0;
4782 switch (
I->getOpcode()) {
4784 case Instruction::Shl:
4785 ResultReg = emitLSL_rr(RetVT, Op0Reg, Op1Reg);
4787 case Instruction::AShr:
4788 ResultReg = emitASR_rr(RetVT, Op0Reg, Op1Reg);
4790 case Instruction::LShr:
4791 ResultReg = emitLSR_rr(RetVT, Op0Reg, Op1Reg);
4798 updateValueMap(
I, ResultReg);
4802bool AArch64FastISel::selectBitCast(
const Instruction *
I) {
4805 if (!isTypeLegal(
I->getOperand(0)->getType(), SrcVT))
4807 if (!isTypeLegal(
I->getType(), RetVT))
4811 if (RetVT == MVT::f32 && SrcVT == MVT::i32)
4812 Opc = AArch64::FMOVWSr;
4813 else if (RetVT == MVT::f64 && SrcVT == MVT::i64)
4814 Opc = AArch64::FMOVXDr;
4815 else if (RetVT == MVT::i32 && SrcVT == MVT::f32)
4816 Opc = AArch64::FMOVSWr;
4817 else if (RetVT == MVT::i64 && SrcVT == MVT::f64)
4818 Opc = AArch64::FMOVDXr;
4825 case MVT::i32: RC = &AArch64::GPR32RegClass;
break;
4826 case MVT::i64: RC = &AArch64::GPR64RegClass;
break;
4827 case MVT::f32: RC = &AArch64::FPR32RegClass;
break;
4828 case MVT::f64: RC = &AArch64::FPR64RegClass;
break;
4830 Register Op0Reg = getRegForValue(
I->getOperand(0));
4834 Register ResultReg = fastEmitInst_r(Opc, RC, Op0Reg);
4838 updateValueMap(
I, ResultReg);
4842bool AArch64FastISel::selectFRem(
const Instruction *
I) {
4844 if (!isTypeLegal(
I->getType(), RetVT))
4852 LC = RTLIB::REM_F32;
4855 LC = RTLIB::REM_F64;
4860 Args.reserve(
I->getNumOperands());
4863 for (
auto &Arg :
I->operands()) {
4866 Entry.Ty = Arg->getType();
4867 Args.push_back(Entry);
4870 CallLoweringInfo CLI;
4872 CLI.setCallee(
DL, Ctx, TLI.getLibcallCallingConv(LC),
I->getType(),
4873 TLI.getLibcallName(LC), std::move(Args));
4874 if (!lowerCallTo(CLI))
4876 updateValueMap(
I, CLI.ResultReg);
4880bool AArch64FastISel::selectSDiv(
const Instruction *
I) {
4882 if (!isTypeLegal(
I->getType(), VT))
4885 if (!isa<ConstantInt>(
I->getOperand(1)))
4888 const APInt &
C = cast<ConstantInt>(
I->getOperand(1))->getValue();
4889 if ((VT != MVT::i32 && VT != MVT::i64) || !
C ||
4890 !(
C.isPowerOf2() ||
C.isNegatedPowerOf2()))
4893 unsigned Lg2 =
C.countr_zero();
4894 Register Src0Reg = getRegForValue(
I->getOperand(0));
4898 if (cast<BinaryOperator>(
I)->isExact()) {
4899 unsigned ResultReg = emitASR_ri(VT, VT, Src0Reg, Lg2);
4902 updateValueMap(
I, ResultReg);
4906 int64_t Pow2MinusOne = (1ULL << Lg2) - 1;
4907 unsigned AddReg = emitAdd_ri_(VT, Src0Reg, Pow2MinusOne);
4912 if (!emitICmp_ri(VT, Src0Reg, 0))
4917 if (VT == MVT::i64) {
4918 SelectOpc = AArch64::CSELXr;
4919 RC = &AArch64::GPR64RegClass;
4921 SelectOpc = AArch64::CSELWr;
4922 RC = &AArch64::GPR32RegClass;
4924 Register SelectReg = fastEmitInst_rri(SelectOpc, RC, AddReg, Src0Reg,
4931 unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
4934 ResultReg = emitAddSub_rs(
false, VT, ZeroReg, SelectReg,
4937 ResultReg = emitASR_ri(VT, VT, SelectReg, Lg2);
4942 updateValueMap(
I, ResultReg);
4949unsigned AArch64FastISel::getRegForGEPIndex(
const Value *
Idx) {
4956 MVT PtrVT = TLI.getPointerTy(
DL);
4958 if (IdxVT.
bitsLT(PtrVT)) {
4959 IdxN = emitIntExt(IdxVT.
getSimpleVT(), IdxN, PtrVT,
false);
4960 }
else if (IdxVT.
bitsGT(PtrVT))
4961 llvm_unreachable(
"AArch64 FastISel doesn't support types larger than i64");
4969bool AArch64FastISel::selectGetElementPtr(
const Instruction *
I) {
4970 if (Subtarget->isTargetILP32())
4973 Register N = getRegForValue(
I->getOperand(0));
4980 MVT VT = TLI.getPointerTy(
DL);
4983 const Value *
Idx = GTI.getOperand();
4984 if (
auto *StTy = GTI.getStructTypeOrNull()) {
4985 unsigned Field = cast<ConstantInt>(
Idx)->getZExtValue();
4988 TotalOffs +=
DL.getStructLayout(StTy)->getElementOffset(
Field);
4990 Type *Ty = GTI.getIndexedType();
4993 if (
const auto *CI = dyn_cast<ConstantInt>(
Idx)) {
4998 DL.getTypeAllocSize(Ty) * cast<ConstantInt>(CI)->getSExtValue();
5002 N = emitAdd_ri_(VT,
N, TotalOffs);
5009 uint64_t ElementSize =
DL.getTypeAllocSize(Ty);
5010 unsigned IdxN = getRegForGEPIndex(
Idx);
5014 if (ElementSize != 1) {
5018 IdxN = emitMul_rr(VT, IdxN,
C);
5028 N = emitAdd_ri_(VT,
N, TotalOffs);
5032 updateValueMap(
I,
N);
5037 assert(
TM.getOptLevel() == CodeGenOptLevel::None &&
5038 "cmpxchg survived AtomicExpand at optlevel > -O0");
5040 auto *RetPairTy = cast<StructType>(
I->getType());
5041 Type *
RetTy = RetPairTy->getTypeAtIndex(0U);
5042 assert(RetPairTy->getTypeAtIndex(1U)->isIntegerTy(1) &&
5043 "cmpxchg has a non-i1 status result");
5046 if (!isTypeLegal(
RetTy, VT))
5050 unsigned Opc, CmpOpc;
5053 if (VT == MVT::i32) {
5054 Opc = AArch64::CMP_SWAP_32;
5055 CmpOpc = AArch64::SUBSWrs;
5056 ResRC = &AArch64::GPR32RegClass;
5057 }
else if (VT == MVT::i64) {
5058 Opc = AArch64::CMP_SWAP_64;
5059 CmpOpc = AArch64::SUBSXrs;
5060 ResRC = &AArch64::GPR64RegClass;
5068 II, getRegForValue(
I->getPointerOperand()), II.
getNumDefs());
5070 II, getRegForValue(
I->getCompareOperand()), II.
getNumDefs() + 1);
5072 II, getRegForValue(
I->getNewValOperand()), II.
getNumDefs() + 2);
5074 const Register ResultReg1 = createResultReg(ResRC);
5075 const Register ResultReg2 = createResultReg(&AArch64::GPR32RegClass);
5076 const Register ScratchReg = createResultReg(&AArch64::GPR32RegClass);
5079 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)
5086 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CmpOpc))
5087 .
addDef(VT == MVT::i32 ? AArch64::WZR : AArch64::XZR)
5092 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AArch64::CSINCWr))
5098 assert((ResultReg1 + 1) == ResultReg2 &&
"Nonconsecutive result registers.");
5099 updateValueMap(
I, ResultReg1, 2);
5103bool AArch64FastISel::fastSelectInstruction(
const Instruction *
I) {
5104 if (TLI.fallBackToDAGISel(*
I))
5106 switch (
I->getOpcode()) {
5109 case Instruction::Add:
5110 case Instruction::Sub:
5111 return selectAddSub(
I);
5112 case Instruction::Mul:
5113 return selectMul(
I);
5114 case Instruction::SDiv:
5115 return selectSDiv(
I);
5116 case Instruction::SRem:
5120 case Instruction::URem:
5124 case Instruction::Shl:
5125 case Instruction::LShr:
5126 case Instruction::AShr:
5127 return selectShift(
I);
5128 case Instruction::And:
5129 case Instruction::Or:
5130 case Instruction::Xor:
5131 return selectLogicalOp(
I);
5132 case Instruction::Br:
5133 return selectBranch(
I);
5134 case Instruction::IndirectBr:
5135 return selectIndirectBr(
I);
5136 case Instruction::BitCast:
5138 return selectBitCast(
I);
5140 case Instruction::FPToSI:
5142 return selectFPToInt(
I,
true);
5144 case Instruction::FPToUI:
5145 return selectFPToInt(
I,
false);
5146 case Instruction::ZExt:
5147 case Instruction::SExt:
5148 return selectIntExt(
I);
5149 case Instruction::Trunc:
5151 return selectTrunc(
I);
5153 case Instruction::FPExt:
5154 return selectFPExt(
I);
5155 case Instruction::FPTrunc:
5156 return selectFPTrunc(
I);
5157 case Instruction::SIToFP:
5159 return selectIntToFP(
I,
true);
5161 case Instruction::UIToFP:
5162 return selectIntToFP(
I,
false);
5163 case Instruction::Load:
5164 return selectLoad(
I);
5165 case Instruction::Store:
5166 return selectStore(
I);
5167 case Instruction::FCmp:
5168 case Instruction::ICmp:
5169 return selectCmp(
I);
5170 case Instruction::Select:
5171 return selectSelect(
I);
5172 case Instruction::Ret:
5173 return selectRet(
I);
5174 case Instruction::FRem:
5175 return selectFRem(
I);
5176 case Instruction::GetElementPtr:
5177 return selectGetElementPtr(
I);
5178 case Instruction::AtomicCmpXchg:
5179 return selectAtomicCmpXchg(cast<AtomicCmpXchgInst>(
I));
5183 return selectOperator(
I,
I->getOpcode());
5193 return new AArch64FastISel(FuncInfo, LibInfo);
unsigned const MachineRegisterInfo * MRI
static bool isIntExtFree(const Instruction *I)
Check if the sign-/zero-extend will be a noop.
static bool isSExtLoad(const MachineInstr *LI)
static AArch64CC::CondCode getCompareCC(CmpInst::Predicate Pred)
static bool isMulPowOf2(const Value *I)
Check if the multiply is by a power-of-2 constant.
static unsigned getImplicitScaleFactor(MVT VT)
Determine the implicit scale factor that is applied by a memory operation for a given value type.
static bool isZExtLoad(const MachineInstr *LI)
static unsigned selectBinaryOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
Select the AArch64 opcode for the basic binary operation GenericOpc (such as G_OR or G_SDIV),...
static void emitLoad(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2, int Offset, bool IsPostDec)
Emit a load-pair instruction for frame-destroy.
static void emitStore(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2, int Offset, bool IsPreDec)
Emit a store-pair instruction for frame-setup.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
This file defines the FastISel class.
const HexagonInstrInfo * TII