5203 lines · cpp
1//===- AArch6464FastISel.cpp - AArch64 FastISel implementation ------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines the AArch64-specific support for the FastISel class. Some10// of the target-specific code is generated by tablegen in the file11// AArch64GenFastISel.inc, which is #included here.12//13//===----------------------------------------------------------------------===//14 15#include "AArch64.h"16#include "AArch64CallingConvention.h"17#include "AArch64MachineFunctionInfo.h"18#include "AArch64RegisterInfo.h"19#include "AArch64SMEAttributes.h"20#include "AArch64Subtarget.h"21#include "MCTargetDesc/AArch64AddressingModes.h"22#include "Utils/AArch64BaseInfo.h"23#include "llvm/ADT/APFloat.h"24#include "llvm/ADT/APInt.h"25#include "llvm/ADT/DenseMap.h"26#include "llvm/ADT/SmallVector.h"27#include "llvm/Analysis/BranchProbabilityInfo.h"28#include "llvm/CodeGen/CallingConvLower.h"29#include "llvm/CodeGen/FastISel.h"30#include "llvm/CodeGen/FunctionLoweringInfo.h"31#include "llvm/CodeGen/ISDOpcodes.h"32#include "llvm/CodeGen/MachineBasicBlock.h"33#include "llvm/CodeGen/MachineConstantPool.h"34#include "llvm/CodeGen/MachineFrameInfo.h"35#include "llvm/CodeGen/MachineInstr.h"36#include "llvm/CodeGen/MachineInstrBuilder.h"37#include "llvm/CodeGen/MachineMemOperand.h"38#include "llvm/CodeGen/MachineRegisterInfo.h"39#include "llvm/CodeGen/ValueTypes.h"40#include "llvm/CodeGenTypes/MachineValueType.h"41#include "llvm/IR/Argument.h"42#include "llvm/IR/Attributes.h"43#include "llvm/IR/BasicBlock.h"44#include "llvm/IR/CallingConv.h"45#include "llvm/IR/Constant.h"46#include "llvm/IR/Constants.h"47#include "llvm/IR/DataLayout.h"48#include "llvm/IR/DerivedTypes.h"49#include "llvm/IR/Function.h"50#include "llvm/IR/GetElementPtrTypeIterator.h"51#include "llvm/IR/GlobalValue.h"52#include "llvm/IR/InstrTypes.h"53#include "llvm/IR/Instruction.h"54#include "llvm/IR/Instructions.h"55#include "llvm/IR/IntrinsicInst.h"56#include "llvm/IR/Intrinsics.h"57#include "llvm/IR/IntrinsicsAArch64.h"58#include "llvm/IR/Module.h"59#include "llvm/IR/Operator.h"60#include "llvm/IR/Type.h"61#include "llvm/IR/User.h"62#include "llvm/IR/Value.h"63#include "llvm/MC/MCInstrDesc.h"64#include "llvm/MC/MCSymbol.h"65#include "llvm/Support/AtomicOrdering.h"66#include "llvm/Support/Casting.h"67#include "llvm/Support/CodeGen.h"68#include "llvm/Support/Compiler.h"69#include "llvm/Support/ErrorHandling.h"70#include "llvm/Support/MathExtras.h"71#include <algorithm>72#include <cassert>73#include <cstdint>74#include <iterator>75#include <utility>76 77using namespace llvm;78 79namespace {80 81class AArch64FastISel final : public FastISel {82 class Address {83 public:84 enum BaseKind { RegBase, FrameIndexBase };85 86 private:87 BaseKind Kind = RegBase;88 AArch64_AM::ShiftExtendType ExtType = AArch64_AM::InvalidShiftExtend;89 union {90 unsigned Reg;91 int FI;92 } Base;93 Register OffsetReg;94 unsigned Shift = 0;95 int64_t Offset = 0;96 const GlobalValue *GV = nullptr;97 98 public:99 Address() { Base.Reg = 0; }100 101 void setKind(BaseKind K) { Kind = K; }102 BaseKind getKind() const { return Kind; }103 void setExtendType(AArch64_AM::ShiftExtendType E) { ExtType = E; }104 AArch64_AM::ShiftExtendType getExtendType() const { return ExtType; }105 bool isRegBase() const { return Kind == RegBase; }106 bool isFIBase() const { return Kind == FrameIndexBase; }107 108 void setReg(Register Reg) {109 assert(isRegBase() && "Invalid base register access!");110 Base.Reg = Reg.id();111 }112 113 Register getReg() const {114 assert(isRegBase() && "Invalid base register access!");115 return Base.Reg;116 }117 118 void setOffsetReg(Register Reg) { OffsetReg = Reg; }119 120 Register getOffsetReg() const { return OffsetReg; }121 122 void setFI(unsigned FI) {123 assert(isFIBase() && "Invalid base frame index access!");124 Base.FI = FI;125 }126 127 unsigned getFI() const {128 assert(isFIBase() && "Invalid base frame index access!");129 return Base.FI;130 }131 132 void setOffset(int64_t O) { Offset = O; }133 int64_t getOffset() { return Offset; }134 void setShift(unsigned S) { Shift = S; }135 unsigned getShift() { return Shift; }136 137 void setGlobalValue(const GlobalValue *G) { GV = G; }138 const GlobalValue *getGlobalValue() { return GV; }139 };140 141 /// Subtarget - Keep a pointer to the AArch64Subtarget around so that we can142 /// make the right decision when generating code for different targets.143 const AArch64Subtarget *Subtarget;144 LLVMContext *Context;145 146 bool fastLowerArguments() override;147 bool fastLowerCall(CallLoweringInfo &CLI) override;148 bool fastLowerIntrinsicCall(const IntrinsicInst *II) override;149 150private:151 // Selection routines.152 bool selectAddSub(const Instruction *I);153 bool selectLogicalOp(const Instruction *I);154 bool selectLoad(const Instruction *I);155 bool selectStore(const Instruction *I);156 bool selectBranch(const Instruction *I);157 bool selectIndirectBr(const Instruction *I);158 bool selectCmp(const Instruction *I);159 bool selectSelect(const Instruction *I);160 bool selectFPExt(const Instruction *I);161 bool selectFPTrunc(const Instruction *I);162 bool selectFPToInt(const Instruction *I, bool Signed);163 bool selectIntToFP(const Instruction *I, bool Signed);164 bool selectRem(const Instruction *I, unsigned ISDOpcode);165 bool selectRet(const Instruction *I);166 bool selectTrunc(const Instruction *I);167 bool selectIntExt(const Instruction *I);168 bool selectMul(const Instruction *I);169 bool selectShift(const Instruction *I);170 bool selectBitCast(const Instruction *I);171 bool selectFRem(const Instruction *I);172 bool selectSDiv(const Instruction *I);173 bool selectGetElementPtr(const Instruction *I);174 bool selectAtomicCmpXchg(const AtomicCmpXchgInst *I);175 176 // Utility helper routines.177 bool isTypeLegal(Type *Ty, MVT &VT);178 bool isTypeSupported(Type *Ty, MVT &VT, bool IsVectorAllowed = false);179 bool isValueAvailable(const Value *V) const;180 bool computeAddress(const Value *Obj, Address &Addr, Type *Ty = nullptr);181 bool computeCallAddress(const Value *V, Address &Addr);182 bool simplifyAddress(Address &Addr, MVT VT);183 void addLoadStoreOperands(Address &Addr, const MachineInstrBuilder &MIB,184 MachineMemOperand::Flags Flags,185 unsigned ScaleFactor, MachineMemOperand *MMO);186 bool isMemCpySmall(uint64_t Len, MaybeAlign Alignment);187 bool tryEmitSmallMemCpy(Address Dest, Address Src, uint64_t Len,188 MaybeAlign Alignment);189 bool foldXALUIntrinsic(AArch64CC::CondCode &CC, const Instruction *I,190 const Value *Cond);191 bool optimizeIntExtLoad(const Instruction *I, MVT RetVT, MVT SrcVT);192 bool optimizeSelect(const SelectInst *SI);193 Register getRegForGEPIndex(const Value *Idx);194 195 // Emit helper routines.196 Register emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS,197 const Value *RHS, bool SetFlags = false,198 bool WantResult = true, bool IsZExt = false);199 Register emitAddSub_rr(bool UseAdd, MVT RetVT, Register LHSReg,200 Register RHSReg, bool SetFlags = false,201 bool WantResult = true);202 Register emitAddSub_ri(bool UseAdd, MVT RetVT, Register LHSReg, uint64_t Imm,203 bool SetFlags = false, bool WantResult = true);204 Register emitAddSub_rs(bool UseAdd, MVT RetVT, Register LHSReg,205 Register RHSReg, AArch64_AM::ShiftExtendType ShiftType,206 uint64_t ShiftImm, bool SetFlags = false,207 bool WantResult = true);208 Register emitAddSub_rx(bool UseAdd, MVT RetVT, Register LHSReg,209 Register RHSReg, AArch64_AM::ShiftExtendType ExtType,210 uint64_t ShiftImm, bool SetFlags = false,211 bool WantResult = true);212 213 // Emit functions.214 bool emitCompareAndBranch(const BranchInst *BI);215 bool emitCmp(const Value *LHS, const Value *RHS, bool IsZExt);216 bool emitICmp(MVT RetVT, const Value *LHS, const Value *RHS, bool IsZExt);217 bool emitICmp_ri(MVT RetVT, Register LHSReg, uint64_t Imm);218 bool emitFCmp(MVT RetVT, const Value *LHS, const Value *RHS);219 Register emitLoad(MVT VT, MVT ResultVT, Address Addr, bool WantZExt = true,220 MachineMemOperand *MMO = nullptr);221 bool emitStore(MVT VT, Register SrcReg, Address Addr,222 MachineMemOperand *MMO = nullptr);223 bool emitStoreRelease(MVT VT, Register SrcReg, Register AddrReg,224 MachineMemOperand *MMO = nullptr);225 Register emitIntExt(MVT SrcVT, Register SrcReg, MVT DestVT, bool isZExt);226 Register emiti1Ext(Register SrcReg, MVT DestVT, bool isZExt);227 Register emitAdd(MVT RetVT, const Value *LHS, const Value *RHS,228 bool SetFlags = false, bool WantResult = true,229 bool IsZExt = false);230 Register emitAdd_ri_(MVT VT, Register Op0, int64_t Imm);231 Register emitSub(MVT RetVT, const Value *LHS, const Value *RHS,232 bool SetFlags = false, bool WantResult = true,233 bool IsZExt = false);234 Register emitSubs_rr(MVT RetVT, Register LHSReg, Register RHSReg,235 bool WantResult = true);236 Register emitSubs_rs(MVT RetVT, Register LHSReg, Register RHSReg,237 AArch64_AM::ShiftExtendType ShiftType, uint64_t ShiftImm,238 bool WantResult = true);239 Register emitLogicalOp(unsigned ISDOpc, MVT RetVT, const Value *LHS,240 const Value *RHS);241 Register emitLogicalOp_ri(unsigned ISDOpc, MVT RetVT, Register LHSReg,242 uint64_t Imm);243 Register emitLogicalOp_rs(unsigned ISDOpc, MVT RetVT, Register LHSReg,244 Register RHSReg, uint64_t ShiftImm);245 Register emitAnd_ri(MVT RetVT, Register LHSReg, uint64_t Imm);246 Register emitMul_rr(MVT RetVT, Register Op0, Register Op1);247 Register emitSMULL_rr(MVT RetVT, Register Op0, Register Op1);248 Register emitUMULL_rr(MVT RetVT, Register Op0, Register Op1);249 Register emitLSL_rr(MVT RetVT, Register Op0Reg, Register Op1Reg);250 Register emitLSL_ri(MVT RetVT, MVT SrcVT, Register Op0Reg, uint64_t Imm,251 bool IsZExt = true);252 Register emitLSR_rr(MVT RetVT, Register Op0Reg, Register Op1Reg);253 Register emitLSR_ri(MVT RetVT, MVT SrcVT, Register Op0Reg, uint64_t Imm,254 bool IsZExt = true);255 Register emitASR_rr(MVT RetVT, Register Op0Reg, Register Op1Reg);256 Register emitASR_ri(MVT RetVT, MVT SrcVT, Register Op0Reg, uint64_t Imm,257 bool IsZExt = false);258 259 Register materializeInt(const ConstantInt *CI, MVT VT);260 Register materializeFP(const ConstantFP *CFP, MVT VT);261 Register materializeGV(const GlobalValue *GV);262 263 // Call handling routines.264private:265 CCAssignFn *CCAssignFnForCall(CallingConv::ID CC) const;266 bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs,267 SmallVectorImpl<Type *> &OrigTys, unsigned &NumBytes);268 bool finishCall(CallLoweringInfo &CLI, unsigned NumBytes);269 270public:271 // Backend specific FastISel code.272 Register fastMaterializeAlloca(const AllocaInst *AI) override;273 Register fastMaterializeConstant(const Constant *C) override;274 Register fastMaterializeFloatZero(const ConstantFP *CF) override;275 276 explicit AArch64FastISel(FunctionLoweringInfo &FuncInfo,277 const TargetLibraryInfo *LibInfo)278 : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {279 Subtarget = &FuncInfo.MF->getSubtarget<AArch64Subtarget>();280 Context = &FuncInfo.Fn->getContext();281 }282 283 bool fastSelectInstruction(const Instruction *I) override;284 285#include "AArch64GenFastISel.inc"286};287 288} // end anonymous namespace289 290/// Check if the sign-/zero-extend will be a noop.291static bool isIntExtFree(const Instruction *I) {292 assert((isa<ZExtInst>(I) || isa<SExtInst>(I)) &&293 "Unexpected integer extend instruction.");294 assert(!I->getType()->isVectorTy() && I->getType()->isIntegerTy() &&295 "Unexpected value type.");296 bool IsZExt = isa<ZExtInst>(I);297 298 if (const auto *LI = dyn_cast<LoadInst>(I->getOperand(0)))299 if (LI->hasOneUse())300 return true;301 302 if (const auto *Arg = dyn_cast<Argument>(I->getOperand(0)))303 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr()))304 return true;305 306 return false;307}308 309/// Determine the implicit scale factor that is applied by a memory310/// operation for a given value type.311static unsigned getImplicitScaleFactor(MVT VT) {312 switch (VT.SimpleTy) {313 default:314 return 0; // invalid315 case MVT::i1: // fall-through316 case MVT::i8:317 return 1;318 case MVT::i16:319 return 2;320 case MVT::i32: // fall-through321 case MVT::f32:322 return 4;323 case MVT::i64: // fall-through324 case MVT::f64:325 return 8;326 }327}328 329CCAssignFn *AArch64FastISel::CCAssignFnForCall(CallingConv::ID CC) const {330 if (CC == CallingConv::GHC)331 return CC_AArch64_GHC;332 if (CC == CallingConv::CFGuard_Check)333 return CC_AArch64_Win64_CFGuard_Check;334 if (Subtarget->isTargetDarwin())335 return CC_AArch64_DarwinPCS;336 if (Subtarget->isTargetWindows())337 return CC_AArch64_Win64PCS;338 return CC_AArch64_AAPCS;339}340 341Register AArch64FastISel::fastMaterializeAlloca(const AllocaInst *AI) {342 assert(TLI.getValueType(DL, AI->getType(), true) == MVT::i64 &&343 "Alloca should always return a pointer.");344 345 // Don't handle dynamic allocas.346 auto SI = FuncInfo.StaticAllocaMap.find(AI);347 if (SI == FuncInfo.StaticAllocaMap.end())348 return Register();349 350 if (SI != FuncInfo.StaticAllocaMap.end()) {351 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);352 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADDXri),353 ResultReg)354 .addFrameIndex(SI->second)355 .addImm(0)356 .addImm(0);357 return ResultReg;358 }359 360 return Register();361}362 363Register AArch64FastISel::materializeInt(const ConstantInt *CI, MVT VT) {364 if (VT > MVT::i64)365 return Register();366 367 if (!CI->isZero())368 return fastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue());369 370 // Create a copy from the zero register to materialize a "0" value.371 const TargetRegisterClass *RC = (VT == MVT::i64) ? &AArch64::GPR64RegClass372 : &AArch64::GPR32RegClass;373 unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;374 Register ResultReg = createResultReg(RC);375 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(TargetOpcode::COPY),376 ResultReg).addReg(ZeroReg, getKillRegState(true));377 return ResultReg;378}379 380Register AArch64FastISel::materializeFP(const ConstantFP *CFP, MVT VT) {381 // Positive zero (+0.0) has to be materialized with a fmov from the zero382 // register, because the immediate version of fmov cannot encode zero.383 if (CFP->isNullValue())384 return fastMaterializeFloatZero(CFP);385 386 if (VT != MVT::f32 && VT != MVT::f64)387 return Register();388 389 const APFloat Val = CFP->getValueAPF();390 bool Is64Bit = (VT == MVT::f64);391 // This checks to see if we can use FMOV instructions to materialize392 // a constant, otherwise we have to materialize via the constant pool.393 int Imm =394 Is64Bit ? AArch64_AM::getFP64Imm(Val) : AArch64_AM::getFP32Imm(Val);395 if (Imm != -1) {396 unsigned Opc = Is64Bit ? AArch64::FMOVDi : AArch64::FMOVSi;397 return fastEmitInst_i(Opc, TLI.getRegClassFor(VT), Imm);398 }399 400 // For the large code model materialize the FP constant in code.401 if (TM.getCodeModel() == CodeModel::Large) {402 unsigned Opc1 = Is64Bit ? AArch64::MOVi64imm : AArch64::MOVi32imm;403 const TargetRegisterClass *RC = Is64Bit ?404 &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;405 406 Register TmpReg = createResultReg(RC);407 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc1), TmpReg)408 .addImm(CFP->getValueAPF().bitcastToAPInt().getZExtValue());409 410 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));411 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,412 TII.get(TargetOpcode::COPY), ResultReg)413 .addReg(TmpReg, getKillRegState(true));414 415 return ResultReg;416 }417 418 // Materialize via constant pool. MachineConstantPool wants an explicit419 // alignment.420 Align Alignment = DL.getPrefTypeAlign(CFP->getType());421 422 unsigned CPI = MCP.getConstantPoolIndex(cast<Constant>(CFP), Alignment);423 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);424 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADRP),425 ADRPReg).addConstantPoolIndex(CPI, 0, AArch64II::MO_PAGE);426 427 unsigned Opc = Is64Bit ? AArch64::LDRDui : AArch64::LDRSui;428 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));429 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)430 .addReg(ADRPReg)431 .addConstantPoolIndex(CPI, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC);432 return ResultReg;433}434 435Register AArch64FastISel::materializeGV(const GlobalValue *GV) {436 // We can't handle thread-local variables quickly yet.437 if (GV->isThreadLocal())438 return Register();439 440 // MachO still uses GOT for large code-model accesses, but ELF requires441 // movz/movk sequences, which FastISel doesn't handle yet.442 if (!Subtarget->useSmallAddressing() && !Subtarget->isTargetMachO())443 return Register();444 445 if (FuncInfo.MF->getInfo<AArch64FunctionInfo>()->hasELFSignedGOT())446 return Register();447 448 unsigned OpFlags = Subtarget->ClassifyGlobalReference(GV, TM);449 450 EVT DestEVT = TLI.getValueType(DL, GV->getType(), true);451 if (!DestEVT.isSimple())452 return Register();453 454 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);455 Register ResultReg;456 457 if (OpFlags & AArch64II::MO_GOT) {458 // ADRP + LDRX459 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADRP),460 ADRPReg)461 .addGlobalAddress(GV, 0, AArch64II::MO_PAGE | OpFlags);462 463 unsigned LdrOpc;464 if (Subtarget->isTargetILP32()) {465 ResultReg = createResultReg(&AArch64::GPR32RegClass);466 LdrOpc = AArch64::LDRWui;467 } else {468 ResultReg = createResultReg(&AArch64::GPR64RegClass);469 LdrOpc = AArch64::LDRXui;470 }471 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(LdrOpc),472 ResultReg)473 .addReg(ADRPReg)474 .addGlobalAddress(GV, 0, AArch64II::MO_GOT | AArch64II::MO_PAGEOFF |475 AArch64II::MO_NC | OpFlags);476 if (!Subtarget->isTargetILP32())477 return ResultReg;478 479 // LDRWui produces a 32-bit register, but pointers in-register are 64-bits480 // so we must extend the result on ILP32.481 Register Result64 = createResultReg(&AArch64::GPR64RegClass);482 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,483 TII.get(TargetOpcode::SUBREG_TO_REG))484 .addDef(Result64)485 .addImm(0)486 .addReg(ResultReg, RegState::Kill)487 .addImm(AArch64::sub_32);488 return Result64;489 } else {490 // ADRP + ADDX491 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADRP),492 ADRPReg)493 .addGlobalAddress(GV, 0, AArch64II::MO_PAGE | OpFlags);494 495 if (OpFlags & AArch64II::MO_TAGGED) {496 // MO_TAGGED on the page indicates a tagged address. Set the tag now.497 // We do so by creating a MOVK that sets bits 48-63 of the register to498 // (global address + 0x100000000 - PC) >> 48. This assumes that we're in499 // the small code model so we can assume a binary size of <= 4GB, which500 // makes the untagged PC relative offset positive. The binary must also be501 // loaded into address range [0, 2^48). Both of these properties need to502 // be ensured at runtime when using tagged addresses.503 //504 // TODO: There is duplicate logic in AArch64ExpandPseudoInsts.cpp that505 // also uses BuildMI for making an ADRP (+ MOVK) + ADD, but the operands506 // are not exactly 1:1 with FastISel so we cannot easily abstract this507 // out. At some point, it would be nice to find a way to not have this508 // duplicate code.509 Register DstReg = createResultReg(&AArch64::GPR64commonRegClass);510 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::MOVKXi),511 DstReg)512 .addReg(ADRPReg)513 .addGlobalAddress(GV, /*Offset=*/0x100000000,514 AArch64II::MO_PREL | AArch64II::MO_G3)515 .addImm(48);516 ADRPReg = DstReg;517 }518 519 ResultReg = createResultReg(&AArch64::GPR64spRegClass);520 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADDXri),521 ResultReg)522 .addReg(ADRPReg)523 .addGlobalAddress(GV, 0,524 AArch64II::MO_PAGEOFF | AArch64II::MO_NC | OpFlags)525 .addImm(0);526 }527 return ResultReg;528}529 530Register AArch64FastISel::fastMaterializeConstant(const Constant *C) {531 EVT CEVT = TLI.getValueType(DL, C->getType(), true);532 533 // Only handle simple types.534 if (!CEVT.isSimple())535 return Register();536 MVT VT = CEVT.getSimpleVT();537 // arm64_32 has 32-bit pointers held in 64-bit registers. Because of that,538 // 'null' pointers need to have a somewhat special treatment.539 if (isa<ConstantPointerNull>(C)) {540 assert(VT == MVT::i64 && "Expected 64-bit pointers");541 return materializeInt(ConstantInt::get(Type::getInt64Ty(*Context), 0), VT);542 }543 544 if (const auto *CI = dyn_cast<ConstantInt>(C))545 return materializeInt(CI, VT);546 else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))547 return materializeFP(CFP, VT);548 else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))549 return materializeGV(GV);550 551 return Register();552}553 554Register AArch64FastISel::fastMaterializeFloatZero(const ConstantFP *CFP) {555 assert(CFP->isNullValue() &&556 "Floating-point constant is not a positive zero.");557 MVT VT;558 if (!isTypeLegal(CFP->getType(), VT))559 return Register();560 561 if (VT != MVT::f32 && VT != MVT::f64)562 return Register();563 564 bool Is64Bit = (VT == MVT::f64);565 unsigned ZReg = Is64Bit ? AArch64::XZR : AArch64::WZR;566 unsigned Opc = Is64Bit ? AArch64::FMOVXDr : AArch64::FMOVWSr;567 return fastEmitInst_r(Opc, TLI.getRegClassFor(VT), ZReg);568}569 570/// Check if the multiply is by a power-of-2 constant.571static bool isMulPowOf2(const Value *I) {572 if (const auto *MI = dyn_cast<MulOperator>(I)) {573 if (const auto *C = dyn_cast<ConstantInt>(MI->getOperand(0)))574 if (C->getValue().isPowerOf2())575 return true;576 if (const auto *C = dyn_cast<ConstantInt>(MI->getOperand(1)))577 if (C->getValue().isPowerOf2())578 return true;579 }580 return false;581}582 583// Computes the address to get to an object.584bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr, Type *Ty)585{586 const User *U = nullptr;587 unsigned Opcode = Instruction::UserOp1;588 if (const Instruction *I = dyn_cast<Instruction>(Obj)) {589 // Don't walk into other basic blocks unless the object is an alloca from590 // another block, otherwise it may not have a virtual register assigned.591 if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||592 FuncInfo.getMBB(I->getParent()) == FuncInfo.MBB) {593 Opcode = I->getOpcode();594 U = I;595 }596 } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {597 Opcode = C->getOpcode();598 U = C;599 }600 601 if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))602 if (Ty->getAddressSpace() > 255)603 // Fast instruction selection doesn't support the special604 // address spaces.605 return false;606 607 switch (Opcode) {608 default:609 break;610 case Instruction::BitCast:611 // Look through bitcasts.612 return computeAddress(U->getOperand(0), Addr, Ty);613 614 case Instruction::IntToPtr:615 // Look past no-op inttoptrs.616 if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==617 TLI.getPointerTy(DL))618 return computeAddress(U->getOperand(0), Addr, Ty);619 break;620 621 case Instruction::PtrToInt:622 // Look past no-op ptrtoints.623 if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))624 return computeAddress(U->getOperand(0), Addr, Ty);625 break;626 627 case Instruction::GetElementPtr: {628 Address SavedAddr = Addr;629 uint64_t TmpOffset = Addr.getOffset();630 631 // Iterate through the GEP folding the constants into offsets where632 // we can.633 for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);634 GTI != E; ++GTI) {635 const Value *Op = GTI.getOperand();636 if (StructType *STy = GTI.getStructTypeOrNull()) {637 const StructLayout *SL = DL.getStructLayout(STy);638 unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();639 TmpOffset += SL->getElementOffset(Idx);640 } else {641 uint64_t S = GTI.getSequentialElementStride(DL);642 while (true) {643 if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {644 // Constant-offset addressing.645 TmpOffset += CI->getSExtValue() * S;646 break;647 }648 if (canFoldAddIntoGEP(U, Op)) {649 // A compatible add with a constant operand. Fold the constant.650 ConstantInt *CI =651 cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));652 TmpOffset += CI->getSExtValue() * S;653 // Iterate on the other operand.654 Op = cast<AddOperator>(Op)->getOperand(0);655 continue;656 }657 // Unsupported658 goto unsupported_gep;659 }660 }661 }662 663 // Try to grab the base operand now.664 Addr.setOffset(TmpOffset);665 if (computeAddress(U->getOperand(0), Addr, Ty))666 return true;667 668 // We failed, restore everything and try the other options.669 Addr = SavedAddr;670 671 unsupported_gep:672 break;673 }674 case Instruction::Alloca: {675 const AllocaInst *AI = cast<AllocaInst>(Obj);676 DenseMap<const AllocaInst *, int>::iterator SI =677 FuncInfo.StaticAllocaMap.find(AI);678 if (SI != FuncInfo.StaticAllocaMap.end()) {679 Addr.setKind(Address::FrameIndexBase);680 Addr.setFI(SI->second);681 return true;682 }683 break;684 }685 case Instruction::Add: {686 // Adds of constants are common and easy enough.687 const Value *LHS = U->getOperand(0);688 const Value *RHS = U->getOperand(1);689 690 if (isa<ConstantInt>(LHS))691 std::swap(LHS, RHS);692 693 if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {694 Addr.setOffset(Addr.getOffset() + CI->getSExtValue());695 return computeAddress(LHS, Addr, Ty);696 }697 698 Address Backup = Addr;699 if (computeAddress(LHS, Addr, Ty) && computeAddress(RHS, Addr, Ty))700 return true;701 Addr = Backup;702 703 break;704 }705 case Instruction::Sub: {706 // Subs of constants are common and easy enough.707 const Value *LHS = U->getOperand(0);708 const Value *RHS = U->getOperand(1);709 710 if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {711 Addr.setOffset(Addr.getOffset() - CI->getSExtValue());712 return computeAddress(LHS, Addr, Ty);713 }714 break;715 }716 case Instruction::Shl: {717 if (Addr.getOffsetReg())718 break;719 720 const auto *CI = dyn_cast<ConstantInt>(U->getOperand(1));721 if (!CI)722 break;723 724 unsigned Val = CI->getZExtValue();725 if (Val < 1 || Val > 3)726 break;727 728 uint64_t NumBytes = 0;729 if (Ty && Ty->isSized()) {730 uint64_t NumBits = DL.getTypeSizeInBits(Ty);731 NumBytes = NumBits / 8;732 if (!isPowerOf2_64(NumBits))733 NumBytes = 0;734 }735 736 if (NumBytes != (1ULL << Val))737 break;738 739 Addr.setShift(Val);740 Addr.setExtendType(AArch64_AM::LSL);741 742 const Value *Src = U->getOperand(0);743 if (const auto *I = dyn_cast<Instruction>(Src)) {744 if (FuncInfo.getMBB(I->getParent()) == FuncInfo.MBB) {745 // Fold the zext or sext when it won't become a noop.746 if (const auto *ZE = dyn_cast<ZExtInst>(I)) {747 if (!isIntExtFree(ZE) &&748 ZE->getOperand(0)->getType()->isIntegerTy(32)) {749 Addr.setExtendType(AArch64_AM::UXTW);750 Src = ZE->getOperand(0);751 }752 } else if (const auto *SE = dyn_cast<SExtInst>(I)) {753 if (!isIntExtFree(SE) &&754 SE->getOperand(0)->getType()->isIntegerTy(32)) {755 Addr.setExtendType(AArch64_AM::SXTW);756 Src = SE->getOperand(0);757 }758 }759 }760 }761 762 if (const auto *AI = dyn_cast<BinaryOperator>(Src))763 if (AI->getOpcode() == Instruction::And) {764 const Value *LHS = AI->getOperand(0);765 const Value *RHS = AI->getOperand(1);766 767 if (const auto *C = dyn_cast<ConstantInt>(LHS))768 if (C->getValue() == 0xffffffff)769 std::swap(LHS, RHS);770 771 if (const auto *C = dyn_cast<ConstantInt>(RHS))772 if (C->getValue() == 0xffffffff) {773 Addr.setExtendType(AArch64_AM::UXTW);774 Register Reg = getRegForValue(LHS);775 if (!Reg)776 return false;777 Reg = fastEmitInst_extractsubreg(MVT::i32, Reg, AArch64::sub_32);778 Addr.setOffsetReg(Reg);779 return true;780 }781 }782 783 Register Reg = getRegForValue(Src);784 if (!Reg)785 return false;786 Addr.setOffsetReg(Reg);787 return true;788 }789 case Instruction::Mul: {790 if (Addr.getOffsetReg())791 break;792 793 if (!isMulPowOf2(U))794 break;795 796 const Value *LHS = U->getOperand(0);797 const Value *RHS = U->getOperand(1);798 799 // Canonicalize power-of-2 value to the RHS.800 if (const auto *C = dyn_cast<ConstantInt>(LHS))801 if (C->getValue().isPowerOf2())802 std::swap(LHS, RHS);803 804 assert(isa<ConstantInt>(RHS) && "Expected an ConstantInt.");805 const auto *C = cast<ConstantInt>(RHS);806 unsigned Val = C->getValue().logBase2();807 if (Val < 1 || Val > 3)808 break;809 810 uint64_t NumBytes = 0;811 if (Ty && Ty->isSized()) {812 uint64_t NumBits = DL.getTypeSizeInBits(Ty);813 NumBytes = NumBits / 8;814 if (!isPowerOf2_64(NumBits))815 NumBytes = 0;816 }817 818 if (NumBytes != (1ULL << Val))819 break;820 821 Addr.setShift(Val);822 Addr.setExtendType(AArch64_AM::LSL);823 824 const Value *Src = LHS;825 if (const auto *I = dyn_cast<Instruction>(Src)) {826 if (FuncInfo.getMBB(I->getParent()) == FuncInfo.MBB) {827 // Fold the zext or sext when it won't become a noop.828 if (const auto *ZE = dyn_cast<ZExtInst>(I)) {829 if (!isIntExtFree(ZE) &&830 ZE->getOperand(0)->getType()->isIntegerTy(32)) {831 Addr.setExtendType(AArch64_AM::UXTW);832 Src = ZE->getOperand(0);833 }834 } else if (const auto *SE = dyn_cast<SExtInst>(I)) {835 if (!isIntExtFree(SE) &&836 SE->getOperand(0)->getType()->isIntegerTy(32)) {837 Addr.setExtendType(AArch64_AM::SXTW);838 Src = SE->getOperand(0);839 }840 }841 }842 }843 844 Register Reg = getRegForValue(Src);845 if (!Reg)846 return false;847 Addr.setOffsetReg(Reg);848 return true;849 }850 case Instruction::And: {851 if (Addr.getOffsetReg())852 break;853 854 if (!Ty || DL.getTypeSizeInBits(Ty) != 8)855 break;856 857 const Value *LHS = U->getOperand(0);858 const Value *RHS = U->getOperand(1);859 860 if (const auto *C = dyn_cast<ConstantInt>(LHS))861 if (C->getValue() == 0xffffffff)862 std::swap(LHS, RHS);863 864 if (const auto *C = dyn_cast<ConstantInt>(RHS))865 if (C->getValue() == 0xffffffff) {866 Addr.setShift(0);867 Addr.setExtendType(AArch64_AM::LSL);868 Addr.setExtendType(AArch64_AM::UXTW);869 870 Register Reg = getRegForValue(LHS);871 if (!Reg)872 return false;873 Reg = fastEmitInst_extractsubreg(MVT::i32, Reg, AArch64::sub_32);874 Addr.setOffsetReg(Reg);875 return true;876 }877 break;878 }879 case Instruction::SExt:880 case Instruction::ZExt: {881 if (!Addr.getReg() || Addr.getOffsetReg())882 break;883 884 const Value *Src = nullptr;885 // Fold the zext or sext when it won't become a noop.886 if (const auto *ZE = dyn_cast<ZExtInst>(U)) {887 if (!isIntExtFree(ZE) && ZE->getOperand(0)->getType()->isIntegerTy(32)) {888 Addr.setExtendType(AArch64_AM::UXTW);889 Src = ZE->getOperand(0);890 }891 } else if (const auto *SE = dyn_cast<SExtInst>(U)) {892 if (!isIntExtFree(SE) && SE->getOperand(0)->getType()->isIntegerTy(32)) {893 Addr.setExtendType(AArch64_AM::SXTW);894 Src = SE->getOperand(0);895 }896 }897 898 if (!Src)899 break;900 901 Addr.setShift(0);902 Register Reg = getRegForValue(Src);903 if (!Reg)904 return false;905 Addr.setOffsetReg(Reg);906 return true;907 }908 } // end switch909 910 if (Addr.isRegBase() && !Addr.getReg()) {911 Register Reg = getRegForValue(Obj);912 if (!Reg)913 return false;914 Addr.setReg(Reg);915 return true;916 }917 918 if (!Addr.getOffsetReg()) {919 Register Reg = getRegForValue(Obj);920 if (!Reg)921 return false;922 Addr.setOffsetReg(Reg);923 return true;924 }925 926 return false;927}928 929bool AArch64FastISel::computeCallAddress(const Value *V, Address &Addr) {930 const User *U = nullptr;931 unsigned Opcode = Instruction::UserOp1;932 bool InMBB = true;933 934 if (const auto *I = dyn_cast<Instruction>(V)) {935 Opcode = I->getOpcode();936 U = I;937 InMBB = I->getParent() == FuncInfo.MBB->getBasicBlock();938 } else if (const auto *C = dyn_cast<ConstantExpr>(V)) {939 Opcode = C->getOpcode();940 U = C;941 }942 943 switch (Opcode) {944 default: break;945 case Instruction::BitCast:946 // Look past bitcasts if its operand is in the same BB.947 if (InMBB)948 return computeCallAddress(U->getOperand(0), Addr);949 break;950 case Instruction::IntToPtr:951 // Look past no-op inttoptrs if its operand is in the same BB.952 if (InMBB &&953 TLI.getValueType(DL, U->getOperand(0)->getType()) ==954 TLI.getPointerTy(DL))955 return computeCallAddress(U->getOperand(0), Addr);956 break;957 case Instruction::PtrToInt:958 // Look past no-op ptrtoints if its operand is in the same BB.959 if (InMBB && TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))960 return computeCallAddress(U->getOperand(0), Addr);961 break;962 }963 964 if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {965 Addr.setGlobalValue(GV);966 return true;967 }968 969 // If all else fails, try to materialize the value in a register.970 if (!Addr.getGlobalValue()) {971 Addr.setReg(getRegForValue(V));972 return Addr.getReg().isValid();973 }974 975 return false;976}977 978bool AArch64FastISel::isTypeLegal(Type *Ty, MVT &VT) {979 EVT evt = TLI.getValueType(DL, Ty, true);980 981 if (Subtarget->isTargetILP32() && Ty->isPointerTy())982 return false;983 984 // Only handle simple types.985 if (evt == MVT::Other || !evt.isSimple())986 return false;987 VT = evt.getSimpleVT();988 989 // This is a legal type, but it's not something we handle in fast-isel.990 if (VT == MVT::f128)991 return false;992 993 // Handle all other legal types, i.e. a register that will directly hold this994 // value.995 return TLI.isTypeLegal(VT);996}997 998/// Determine if the value type is supported by FastISel.999///1000/// FastISel for AArch64 can handle more value types than are legal. This adds1001/// simple value type such as i1, i8, and i16.1002bool AArch64FastISel::isTypeSupported(Type *Ty, MVT &VT, bool IsVectorAllowed) {1003 if (Ty->isVectorTy() && !IsVectorAllowed)1004 return false;1005 1006 if (isTypeLegal(Ty, VT))1007 return true;1008 1009 // If this is a type than can be sign or zero-extended to a basic operation1010 // go ahead and accept it now.1011 if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)1012 return true;1013 1014 return false;1015}1016 1017bool AArch64FastISel::isValueAvailable(const Value *V) const {1018 if (!isa<Instruction>(V))1019 return true;1020 1021 const auto *I = cast<Instruction>(V);1022 return FuncInfo.getMBB(I->getParent()) == FuncInfo.MBB;1023}1024 1025bool AArch64FastISel::simplifyAddress(Address &Addr, MVT VT) {1026 if (Subtarget->isTargetILP32())1027 return false;1028 1029 unsigned ScaleFactor = getImplicitScaleFactor(VT);1030 if (!ScaleFactor)1031 return false;1032 1033 bool ImmediateOffsetNeedsLowering = false;1034 bool RegisterOffsetNeedsLowering = false;1035 int64_t Offset = Addr.getOffset();1036 if (((Offset < 0) || (Offset & (ScaleFactor - 1))) && !isInt<9>(Offset))1037 ImmediateOffsetNeedsLowering = true;1038 else if (Offset > 0 && !(Offset & (ScaleFactor - 1)) &&1039 !isUInt<12>(Offset / ScaleFactor))1040 ImmediateOffsetNeedsLowering = true;1041 1042 // Cannot encode an offset register and an immediate offset in the same1043 // instruction. Fold the immediate offset into the load/store instruction and1044 // emit an additional add to take care of the offset register.1045 if (!ImmediateOffsetNeedsLowering && Addr.getOffset() && Addr.getOffsetReg())1046 RegisterOffsetNeedsLowering = true;1047 1048 // Cannot encode zero register as base.1049 if (Addr.isRegBase() && Addr.getOffsetReg() && !Addr.getReg())1050 RegisterOffsetNeedsLowering = true;1051 1052 // If this is a stack pointer and the offset needs to be simplified then put1053 // the alloca address into a register, set the base type back to register and1054 // continue. This should almost never happen.1055 if ((ImmediateOffsetNeedsLowering || Addr.getOffsetReg()) && Addr.isFIBase())1056 {1057 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);1058 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADDXri),1059 ResultReg)1060 .addFrameIndex(Addr.getFI())1061 .addImm(0)1062 .addImm(0);1063 Addr.setKind(Address::RegBase);1064 Addr.setReg(ResultReg);1065 }1066 1067 if (RegisterOffsetNeedsLowering) {1068 Register ResultReg;1069 if (Addr.getReg()) {1070 if (Addr.getExtendType() == AArch64_AM::SXTW ||1071 Addr.getExtendType() == AArch64_AM::UXTW )1072 ResultReg = emitAddSub_rx(/*UseAdd=*/true, MVT::i64, Addr.getReg(),1073 Addr.getOffsetReg(), Addr.getExtendType(),1074 Addr.getShift());1075 else1076 ResultReg = emitAddSub_rs(/*UseAdd=*/true, MVT::i64, Addr.getReg(),1077 Addr.getOffsetReg(), AArch64_AM::LSL,1078 Addr.getShift());1079 } else {1080 if (Addr.getExtendType() == AArch64_AM::UXTW)1081 ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),1082 Addr.getShift(), /*IsZExt=*/true);1083 else if (Addr.getExtendType() == AArch64_AM::SXTW)1084 ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),1085 Addr.getShift(), /*IsZExt=*/false);1086 else1087 ResultReg = emitLSL_ri(MVT::i64, MVT::i64, Addr.getOffsetReg(),1088 Addr.getShift());1089 }1090 if (!ResultReg)1091 return false;1092 1093 Addr.setReg(ResultReg);1094 Addr.setOffsetReg(0);1095 Addr.setShift(0);1096 Addr.setExtendType(AArch64_AM::InvalidShiftExtend);1097 }1098 1099 // Since the offset is too large for the load/store instruction get the1100 // reg+offset into a register.1101 if (ImmediateOffsetNeedsLowering) {1102 Register ResultReg;1103 if (Addr.getReg())1104 // Try to fold the immediate into the add instruction.1105 ResultReg = emitAdd_ri_(MVT::i64, Addr.getReg(), Offset);1106 else1107 ResultReg = fastEmit_i(MVT::i64, MVT::i64, ISD::Constant, Offset);1108 1109 if (!ResultReg)1110 return false;1111 Addr.setReg(ResultReg);1112 Addr.setOffset(0);1113 }1114 return true;1115}1116 1117void AArch64FastISel::addLoadStoreOperands(Address &Addr,1118 const MachineInstrBuilder &MIB,1119 MachineMemOperand::Flags Flags,1120 unsigned ScaleFactor,1121 MachineMemOperand *MMO) {1122 int64_t Offset = Addr.getOffset() / ScaleFactor;1123 // Frame base works a bit differently. Handle it separately.1124 if (Addr.isFIBase()) {1125 int FI = Addr.getFI();1126 // FIXME: We shouldn't be using getObjectSize/getObjectAlignment. The size1127 // and alignment should be based on the VT.1128 MMO = FuncInfo.MF->getMachineMemOperand(1129 MachinePointerInfo::getFixedStack(*FuncInfo.MF, FI, Offset), Flags,1130 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));1131 // Now add the rest of the operands.1132 MIB.addFrameIndex(FI).addImm(Offset);1133 } else {1134 assert(Addr.isRegBase() && "Unexpected address kind.");1135 const MCInstrDesc &II = MIB->getDesc();1136 unsigned Idx = (Flags & MachineMemOperand::MOStore) ? 1 : 0;1137 Addr.setReg(1138 constrainOperandRegClass(II, Addr.getReg(), II.getNumDefs()+Idx));1139 Addr.setOffsetReg(1140 constrainOperandRegClass(II, Addr.getOffsetReg(), II.getNumDefs()+Idx+1));1141 if (Addr.getOffsetReg()) {1142 assert(Addr.getOffset() == 0 && "Unexpected offset");1143 bool IsSigned = Addr.getExtendType() == AArch64_AM::SXTW ||1144 Addr.getExtendType() == AArch64_AM::SXTX;1145 MIB.addReg(Addr.getReg());1146 MIB.addReg(Addr.getOffsetReg());1147 MIB.addImm(IsSigned);1148 MIB.addImm(Addr.getShift() != 0);1149 } else1150 MIB.addReg(Addr.getReg()).addImm(Offset);1151 }1152 1153 if (MMO)1154 MIB.addMemOperand(MMO);1155}1156 1157Register AArch64FastISel::emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS,1158 const Value *RHS, bool SetFlags,1159 bool WantResult, bool IsZExt) {1160 AArch64_AM::ShiftExtendType ExtendType = AArch64_AM::InvalidShiftExtend;1161 bool NeedExtend = false;1162 switch (RetVT.SimpleTy) {1163 default:1164 return Register();1165 case MVT::i1:1166 NeedExtend = true;1167 break;1168 case MVT::i8:1169 NeedExtend = true;1170 ExtendType = IsZExt ? AArch64_AM::UXTB : AArch64_AM::SXTB;1171 break;1172 case MVT::i16:1173 NeedExtend = true;1174 ExtendType = IsZExt ? AArch64_AM::UXTH : AArch64_AM::SXTH;1175 break;1176 case MVT::i32: // fall-through1177 case MVT::i64:1178 break;1179 }1180 MVT SrcVT = RetVT;1181 RetVT.SimpleTy = std::max(RetVT.SimpleTy, MVT::i32);1182 1183 // Canonicalize immediates to the RHS first.1184 if (UseAdd && isa<Constant>(LHS) && !isa<Constant>(RHS))1185 std::swap(LHS, RHS);1186 1187 // Canonicalize mul by power of 2 to the RHS.1188 if (UseAdd && LHS->hasOneUse() && isValueAvailable(LHS))1189 if (isMulPowOf2(LHS))1190 std::swap(LHS, RHS);1191 1192 // Canonicalize shift immediate to the RHS.1193 if (UseAdd && LHS->hasOneUse() && isValueAvailable(LHS))1194 if (const auto *SI = dyn_cast<BinaryOperator>(LHS))1195 if (isa<ConstantInt>(SI->getOperand(1)))1196 if (SI->getOpcode() == Instruction::Shl ||1197 SI->getOpcode() == Instruction::LShr ||1198 SI->getOpcode() == Instruction::AShr )1199 std::swap(LHS, RHS);1200 1201 Register LHSReg = getRegForValue(LHS);1202 if (!LHSReg)1203 return Register();1204 1205 if (NeedExtend)1206 LHSReg = emitIntExt(SrcVT, LHSReg, RetVT, IsZExt);1207 1208 Register ResultReg;1209 if (const auto *C = dyn_cast<ConstantInt>(RHS)) {1210 uint64_t Imm = IsZExt ? C->getZExtValue() : C->getSExtValue();1211 if (C->isNegative())1212 ResultReg = emitAddSub_ri(!UseAdd, RetVT, LHSReg, -Imm, SetFlags,1213 WantResult);1214 else1215 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, Imm, SetFlags,1216 WantResult);1217 } else if (const auto *C = dyn_cast<Constant>(RHS))1218 if (C->isNullValue())1219 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, 0, SetFlags, WantResult);1220 1221 if (ResultReg)1222 return ResultReg;1223 1224 // Only extend the RHS within the instruction if there is a valid extend type.1225 if (ExtendType != AArch64_AM::InvalidShiftExtend && RHS->hasOneUse() &&1226 isValueAvailable(RHS)) {1227 Register RHSReg = getRegForValue(RHS);1228 if (!RHSReg)1229 return Register();1230 return emitAddSub_rx(UseAdd, RetVT, LHSReg, RHSReg, ExtendType, 0,1231 SetFlags, WantResult);1232 }1233 1234 // Check if the mul can be folded into the instruction.1235 if (RHS->hasOneUse() && isValueAvailable(RHS)) {1236 if (isMulPowOf2(RHS)) {1237 const Value *MulLHS = cast<MulOperator>(RHS)->getOperand(0);1238 const Value *MulRHS = cast<MulOperator>(RHS)->getOperand(1);1239 1240 if (const auto *C = dyn_cast<ConstantInt>(MulLHS))1241 if (C->getValue().isPowerOf2())1242 std::swap(MulLHS, MulRHS);1243 1244 assert(isa<ConstantInt>(MulRHS) && "Expected a ConstantInt.");1245 uint64_t ShiftVal = cast<ConstantInt>(MulRHS)->getValue().logBase2();1246 Register RHSReg = getRegForValue(MulLHS);1247 if (!RHSReg)1248 return Register();1249 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg, AArch64_AM::LSL,1250 ShiftVal, SetFlags, WantResult);1251 if (ResultReg)1252 return ResultReg;1253 }1254 }1255 1256 // Check if the shift can be folded into the instruction.1257 if (RHS->hasOneUse() && isValueAvailable(RHS)) {1258 if (const auto *SI = dyn_cast<BinaryOperator>(RHS)) {1259 if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1))) {1260 AArch64_AM::ShiftExtendType ShiftType = AArch64_AM::InvalidShiftExtend;1261 switch (SI->getOpcode()) {1262 default: break;1263 case Instruction::Shl: ShiftType = AArch64_AM::LSL; break;1264 case Instruction::LShr: ShiftType = AArch64_AM::LSR; break;1265 case Instruction::AShr: ShiftType = AArch64_AM::ASR; break;1266 }1267 uint64_t ShiftVal = C->getZExtValue();1268 if (ShiftType != AArch64_AM::InvalidShiftExtend) {1269 Register RHSReg = getRegForValue(SI->getOperand(0));1270 if (!RHSReg)1271 return Register();1272 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, RHSReg, ShiftType,1273 ShiftVal, SetFlags, WantResult);1274 if (ResultReg)1275 return ResultReg;1276 }1277 }1278 }1279 }1280 1281 Register RHSReg = getRegForValue(RHS);1282 if (!RHSReg)1283 return Register();1284 1285 if (NeedExtend)1286 RHSReg = emitIntExt(SrcVT, RHSReg, RetVT, IsZExt);1287 1288 return emitAddSub_rr(UseAdd, RetVT, LHSReg, RHSReg, SetFlags, WantResult);1289}1290 1291Register AArch64FastISel::emitAddSub_rr(bool UseAdd, MVT RetVT, Register LHSReg,1292 Register RHSReg, bool SetFlags,1293 bool WantResult) {1294 assert(LHSReg && RHSReg && "Invalid register number.");1295 1296 if (LHSReg == AArch64::SP || LHSReg == AArch64::WSP ||1297 RHSReg == AArch64::SP || RHSReg == AArch64::WSP)1298 return Register();1299 1300 if (RetVT != MVT::i32 && RetVT != MVT::i64)1301 return Register();1302 1303 static const unsigned OpcTable[2][2][2] = {1304 { { AArch64::SUBWrr, AArch64::SUBXrr },1305 { AArch64::ADDWrr, AArch64::ADDXrr } },1306 { { AArch64::SUBSWrr, AArch64::SUBSXrr },1307 { AArch64::ADDSWrr, AArch64::ADDSXrr } }1308 };1309 bool Is64Bit = RetVT == MVT::i64;1310 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];1311 const TargetRegisterClass *RC =1312 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;1313 Register ResultReg;1314 if (WantResult)1315 ResultReg = createResultReg(RC);1316 else1317 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;1318 1319 const MCInstrDesc &II = TII.get(Opc);1320 LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());1321 RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);1322 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)1323 .addReg(LHSReg)1324 .addReg(RHSReg);1325 return ResultReg;1326}1327 1328Register AArch64FastISel::emitAddSub_ri(bool UseAdd, MVT RetVT, Register LHSReg,1329 uint64_t Imm, bool SetFlags,1330 bool WantResult) {1331 assert(LHSReg && "Invalid register number.");1332 1333 if (RetVT != MVT::i32 && RetVT != MVT::i64)1334 return Register();1335 1336 unsigned ShiftImm;1337 if (isUInt<12>(Imm))1338 ShiftImm = 0;1339 else if ((Imm & 0xfff000) == Imm) {1340 ShiftImm = 12;1341 Imm >>= 12;1342 } else1343 return Register();1344 1345 static const unsigned OpcTable[2][2][2] = {1346 { { AArch64::SUBWri, AArch64::SUBXri },1347 { AArch64::ADDWri, AArch64::ADDXri } },1348 { { AArch64::SUBSWri, AArch64::SUBSXri },1349 { AArch64::ADDSWri, AArch64::ADDSXri } }1350 };1351 bool Is64Bit = RetVT == MVT::i64;1352 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];1353 const TargetRegisterClass *RC;1354 if (SetFlags)1355 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;1356 else1357 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;1358 Register ResultReg;1359 if (WantResult)1360 ResultReg = createResultReg(RC);1361 else1362 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;1363 1364 const MCInstrDesc &II = TII.get(Opc);1365 LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());1366 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)1367 .addReg(LHSReg)1368 .addImm(Imm)1369 .addImm(getShifterImm(AArch64_AM::LSL, ShiftImm));1370 return ResultReg;1371}1372 1373Register AArch64FastISel::emitAddSub_rs(bool UseAdd, MVT RetVT, Register LHSReg,1374 Register RHSReg,1375 AArch64_AM::ShiftExtendType ShiftType,1376 uint64_t ShiftImm, bool SetFlags,1377 bool WantResult) {1378 assert(LHSReg && RHSReg && "Invalid register number.");1379 assert(LHSReg != AArch64::SP && LHSReg != AArch64::WSP &&1380 RHSReg != AArch64::SP && RHSReg != AArch64::WSP);1381 1382 if (RetVT != MVT::i32 && RetVT != MVT::i64)1383 return Register();1384 1385 // Don't deal with undefined shifts.1386 if (ShiftImm >= RetVT.getSizeInBits())1387 return Register();1388 1389 static const unsigned OpcTable[2][2][2] = {1390 { { AArch64::SUBWrs, AArch64::SUBXrs },1391 { AArch64::ADDWrs, AArch64::ADDXrs } },1392 { { AArch64::SUBSWrs, AArch64::SUBSXrs },1393 { AArch64::ADDSWrs, AArch64::ADDSXrs } }1394 };1395 bool Is64Bit = RetVT == MVT::i64;1396 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];1397 const TargetRegisterClass *RC =1398 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;1399 Register ResultReg;1400 if (WantResult)1401 ResultReg = createResultReg(RC);1402 else1403 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;1404 1405 const MCInstrDesc &II = TII.get(Opc);1406 LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());1407 RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);1408 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)1409 .addReg(LHSReg)1410 .addReg(RHSReg)1411 .addImm(getShifterImm(ShiftType, ShiftImm));1412 return ResultReg;1413}1414 1415Register AArch64FastISel::emitAddSub_rx(bool UseAdd, MVT RetVT, Register LHSReg,1416 Register RHSReg,1417 AArch64_AM::ShiftExtendType ExtType,1418 uint64_t ShiftImm, bool SetFlags,1419 bool WantResult) {1420 assert(LHSReg && RHSReg && "Invalid register number.");1421 assert(LHSReg != AArch64::XZR && LHSReg != AArch64::WZR &&1422 RHSReg != AArch64::XZR && RHSReg != AArch64::WZR);1423 1424 if (RetVT != MVT::i32 && RetVT != MVT::i64)1425 return Register();1426 1427 if (ShiftImm >= 4)1428 return Register();1429 1430 static const unsigned OpcTable[2][2][2] = {1431 { { AArch64::SUBWrx, AArch64::SUBXrx },1432 { AArch64::ADDWrx, AArch64::ADDXrx } },1433 { { AArch64::SUBSWrx, AArch64::SUBSXrx },1434 { AArch64::ADDSWrx, AArch64::ADDSXrx } }1435 };1436 bool Is64Bit = RetVT == MVT::i64;1437 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];1438 const TargetRegisterClass *RC = nullptr;1439 if (SetFlags)1440 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;1441 else1442 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;1443 Register ResultReg;1444 if (WantResult)1445 ResultReg = createResultReg(RC);1446 else1447 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;1448 1449 const MCInstrDesc &II = TII.get(Opc);1450 LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());1451 RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);1452 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)1453 .addReg(LHSReg)1454 .addReg(RHSReg)1455 .addImm(getArithExtendImm(ExtType, ShiftImm));1456 return ResultReg;1457}1458 1459bool AArch64FastISel::emitCmp(const Value *LHS, const Value *RHS, bool IsZExt) {1460 Type *Ty = LHS->getType();1461 EVT EVT = TLI.getValueType(DL, Ty, true);1462 if (!EVT.isSimple())1463 return false;1464 MVT VT = EVT.getSimpleVT();1465 1466 switch (VT.SimpleTy) {1467 default:1468 return false;1469 case MVT::i1:1470 case MVT::i8:1471 case MVT::i16:1472 case MVT::i32:1473 case MVT::i64:1474 return emitICmp(VT, LHS, RHS, IsZExt);1475 case MVT::f32:1476 case MVT::f64:1477 return emitFCmp(VT, LHS, RHS);1478 }1479}1480 1481bool AArch64FastISel::emitICmp(MVT RetVT, const Value *LHS, const Value *RHS,1482 bool IsZExt) {1483 return emitSub(RetVT, LHS, RHS, /*SetFlags=*/true, /*WantResult=*/false,1484 IsZExt)1485 .isValid();1486}1487 1488bool AArch64FastISel::emitICmp_ri(MVT RetVT, Register LHSReg, uint64_t Imm) {1489 return emitAddSub_ri(/*UseAdd=*/false, RetVT, LHSReg, Imm,1490 /*SetFlags=*/true, /*WantResult=*/false)1491 .isValid();1492}1493 1494bool AArch64FastISel::emitFCmp(MVT RetVT, const Value *LHS, const Value *RHS) {1495 if (RetVT != MVT::f32 && RetVT != MVT::f64)1496 return false;1497 1498 // Check to see if the 2nd operand is a constant that we can encode directly1499 // in the compare.1500 bool UseImm = false;1501 if (const auto *CFP = dyn_cast<ConstantFP>(RHS))1502 if (CFP->isZero() && !CFP->isNegative())1503 UseImm = true;1504 1505 Register LHSReg = getRegForValue(LHS);1506 if (!LHSReg)1507 return false;1508 1509 if (UseImm) {1510 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDri : AArch64::FCMPSri;1511 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc))1512 .addReg(LHSReg);1513 return true;1514 }1515 1516 Register RHSReg = getRegForValue(RHS);1517 if (!RHSReg)1518 return false;1519 1520 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDrr : AArch64::FCMPSrr;1521 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc))1522 .addReg(LHSReg)1523 .addReg(RHSReg);1524 return true;1525}1526 1527Register AArch64FastISel::emitAdd(MVT RetVT, const Value *LHS, const Value *RHS,1528 bool SetFlags, bool WantResult, bool IsZExt) {1529 return emitAddSub(/*UseAdd=*/true, RetVT, LHS, RHS, SetFlags, WantResult,1530 IsZExt);1531}1532 1533/// This method is a wrapper to simplify add emission.1534///1535/// First try to emit an add with an immediate operand using emitAddSub_ri. If1536/// that fails, then try to materialize the immediate into a register and use1537/// emitAddSub_rr instead.1538Register AArch64FastISel::emitAdd_ri_(MVT VT, Register Op0, int64_t Imm) {1539 Register ResultReg;1540 if (Imm < 0)1541 ResultReg = emitAddSub_ri(false, VT, Op0, -Imm);1542 else1543 ResultReg = emitAddSub_ri(true, VT, Op0, Imm);1544 1545 if (ResultReg)1546 return ResultReg;1547 1548 Register CReg = fastEmit_i(VT, VT, ISD::Constant, Imm);1549 if (!CReg)1550 return Register();1551 1552 ResultReg = emitAddSub_rr(true, VT, Op0, CReg);1553 return ResultReg;1554}1555 1556Register AArch64FastISel::emitSub(MVT RetVT, const Value *LHS, const Value *RHS,1557 bool SetFlags, bool WantResult, bool IsZExt) {1558 return emitAddSub(/*UseAdd=*/false, RetVT, LHS, RHS, SetFlags, WantResult,1559 IsZExt);1560}1561 1562Register AArch64FastISel::emitSubs_rr(MVT RetVT, Register LHSReg,1563 Register RHSReg, bool WantResult) {1564 return emitAddSub_rr(/*UseAdd=*/false, RetVT, LHSReg, RHSReg,1565 /*SetFlags=*/true, WantResult);1566}1567 1568Register AArch64FastISel::emitSubs_rs(MVT RetVT, Register LHSReg,1569 Register RHSReg,1570 AArch64_AM::ShiftExtendType ShiftType,1571 uint64_t ShiftImm, bool WantResult) {1572 return emitAddSub_rs(/*UseAdd=*/false, RetVT, LHSReg, RHSReg, ShiftType,1573 ShiftImm, /*SetFlags=*/true, WantResult);1574}1575 1576Register AArch64FastISel::emitLogicalOp(unsigned ISDOpc, MVT RetVT,1577 const Value *LHS, const Value *RHS) {1578 // Canonicalize immediates to the RHS first.1579 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS))1580 std::swap(LHS, RHS);1581 1582 // Canonicalize mul by power-of-2 to the RHS.1583 if (LHS->hasOneUse() && isValueAvailable(LHS))1584 if (isMulPowOf2(LHS))1585 std::swap(LHS, RHS);1586 1587 // Canonicalize shift immediate to the RHS.1588 if (LHS->hasOneUse() && isValueAvailable(LHS))1589 if (const auto *SI = dyn_cast<ShlOperator>(LHS))1590 if (isa<ConstantInt>(SI->getOperand(1)))1591 std::swap(LHS, RHS);1592 1593 Register LHSReg = getRegForValue(LHS);1594 if (!LHSReg)1595 return Register();1596 1597 Register ResultReg;1598 if (const auto *C = dyn_cast<ConstantInt>(RHS)) {1599 uint64_t Imm = C->getZExtValue();1600 ResultReg = emitLogicalOp_ri(ISDOpc, RetVT, LHSReg, Imm);1601 }1602 if (ResultReg)1603 return ResultReg;1604 1605 // Check if the mul can be folded into the instruction.1606 if (RHS->hasOneUse() && isValueAvailable(RHS)) {1607 if (isMulPowOf2(RHS)) {1608 const Value *MulLHS = cast<MulOperator>(RHS)->getOperand(0);1609 const Value *MulRHS = cast<MulOperator>(RHS)->getOperand(1);1610 1611 if (const auto *C = dyn_cast<ConstantInt>(MulLHS))1612 if (C->getValue().isPowerOf2())1613 std::swap(MulLHS, MulRHS);1614 1615 assert(isa<ConstantInt>(MulRHS) && "Expected a ConstantInt.");1616 uint64_t ShiftVal = cast<ConstantInt>(MulRHS)->getValue().logBase2();1617 1618 Register RHSReg = getRegForValue(MulLHS);1619 if (!RHSReg)1620 return Register();1621 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);1622 if (ResultReg)1623 return ResultReg;1624 }1625 }1626 1627 // Check if the shift can be folded into the instruction.1628 if (RHS->hasOneUse() && isValueAvailable(RHS)) {1629 if (const auto *SI = dyn_cast<ShlOperator>(RHS))1630 if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1))) {1631 uint64_t ShiftVal = C->getZExtValue();1632 Register RHSReg = getRegForValue(SI->getOperand(0));1633 if (!RHSReg)1634 return Register();1635 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, RHSReg, ShiftVal);1636 if (ResultReg)1637 return ResultReg;1638 }1639 }1640 1641 Register RHSReg = getRegForValue(RHS);1642 if (!RHSReg)1643 return Register();1644 1645 MVT VT = std::max(MVT::i32, RetVT.SimpleTy);1646 ResultReg = fastEmit_rr(VT, VT, ISDOpc, LHSReg, RHSReg);1647 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {1648 uint64_t Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;1649 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);1650 }1651 return ResultReg;1652}1653 1654Register AArch64FastISel::emitLogicalOp_ri(unsigned ISDOpc, MVT RetVT,1655 Register LHSReg, uint64_t Imm) {1656 static_assert((ISD::AND + 1 == ISD::OR) && (ISD::AND + 2 == ISD::XOR),1657 "ISD nodes are not consecutive!");1658 static const unsigned OpcTable[3][2] = {1659 { AArch64::ANDWri, AArch64::ANDXri },1660 { AArch64::ORRWri, AArch64::ORRXri },1661 { AArch64::EORWri, AArch64::EORXri }1662 };1663 const TargetRegisterClass *RC;1664 unsigned Opc;1665 unsigned RegSize;1666 switch (RetVT.SimpleTy) {1667 default:1668 return Register();1669 case MVT::i1:1670 case MVT::i8:1671 case MVT::i16:1672 case MVT::i32: {1673 unsigned Idx = ISDOpc - ISD::AND;1674 Opc = OpcTable[Idx][0];1675 RC = &AArch64::GPR32spRegClass;1676 RegSize = 32;1677 break;1678 }1679 case MVT::i64:1680 Opc = OpcTable[ISDOpc - ISD::AND][1];1681 RC = &AArch64::GPR64spRegClass;1682 RegSize = 64;1683 break;1684 }1685 1686 if (!AArch64_AM::isLogicalImmediate(Imm, RegSize))1687 return Register();1688 1689 Register ResultReg =1690 fastEmitInst_ri(Opc, RC, LHSReg,1691 AArch64_AM::encodeLogicalImmediate(Imm, RegSize));1692 if (RetVT >= MVT::i8 && RetVT <= MVT::i16 && ISDOpc != ISD::AND) {1693 uint64_t Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;1694 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);1695 }1696 return ResultReg;1697}1698 1699Register AArch64FastISel::emitLogicalOp_rs(unsigned ISDOpc, MVT RetVT,1700 Register LHSReg, Register RHSReg,1701 uint64_t ShiftImm) {1702 static_assert((ISD::AND + 1 == ISD::OR) && (ISD::AND + 2 == ISD::XOR),1703 "ISD nodes are not consecutive!");1704 static const unsigned OpcTable[3][2] = {1705 { AArch64::ANDWrs, AArch64::ANDXrs },1706 { AArch64::ORRWrs, AArch64::ORRXrs },1707 { AArch64::EORWrs, AArch64::EORXrs }1708 };1709 1710 // Don't deal with undefined shifts.1711 if (ShiftImm >= RetVT.getSizeInBits())1712 return Register();1713 1714 const TargetRegisterClass *RC;1715 unsigned Opc;1716 switch (RetVT.SimpleTy) {1717 default:1718 return Register();1719 case MVT::i1:1720 case MVT::i8:1721 case MVT::i16:1722 case MVT::i32:1723 Opc = OpcTable[ISDOpc - ISD::AND][0];1724 RC = &AArch64::GPR32RegClass;1725 break;1726 case MVT::i64:1727 Opc = OpcTable[ISDOpc - ISD::AND][1];1728 RC = &AArch64::GPR64RegClass;1729 break;1730 }1731 Register ResultReg =1732 fastEmitInst_rri(Opc, RC, LHSReg, RHSReg,1733 AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftImm));1734 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {1735 uint64_t Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;1736 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);1737 }1738 return ResultReg;1739}1740 1741Register AArch64FastISel::emitAnd_ri(MVT RetVT, Register LHSReg, uint64_t Imm) {1742 return emitLogicalOp_ri(ISD::AND, RetVT, LHSReg, Imm);1743}1744 1745Register AArch64FastISel::emitLoad(MVT VT, MVT RetVT, Address Addr,1746 bool WantZExt, MachineMemOperand *MMO) {1747 if (!TLI.allowsMisalignedMemoryAccesses(VT))1748 return Register();1749 1750 // Simplify this down to something we can handle.1751 if (!simplifyAddress(Addr, VT))1752 return Register();1753 1754 unsigned ScaleFactor = getImplicitScaleFactor(VT);1755 if (!ScaleFactor)1756 llvm_unreachable("Unexpected value type.");1757 1758 // Negative offsets require unscaled, 9-bit, signed immediate offsets.1759 // Otherwise, we try using scaled, 12-bit, unsigned immediate offsets.1760 bool UseScaled = true;1761 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {1762 UseScaled = false;1763 ScaleFactor = 1;1764 }1765 1766 static const unsigned GPOpcTable[2][8][4] = {1767 // Sign-extend.1768 { { AArch64::LDURSBWi, AArch64::LDURSHWi, AArch64::LDURWi,1769 AArch64::LDURXi },1770 { AArch64::LDURSBXi, AArch64::LDURSHXi, AArch64::LDURSWi,1771 AArch64::LDURXi },1772 { AArch64::LDRSBWui, AArch64::LDRSHWui, AArch64::LDRWui,1773 AArch64::LDRXui },1774 { AArch64::LDRSBXui, AArch64::LDRSHXui, AArch64::LDRSWui,1775 AArch64::LDRXui },1776 { AArch64::LDRSBWroX, AArch64::LDRSHWroX, AArch64::LDRWroX,1777 AArch64::LDRXroX },1778 { AArch64::LDRSBXroX, AArch64::LDRSHXroX, AArch64::LDRSWroX,1779 AArch64::LDRXroX },1780 { AArch64::LDRSBWroW, AArch64::LDRSHWroW, AArch64::LDRWroW,1781 AArch64::LDRXroW },1782 { AArch64::LDRSBXroW, AArch64::LDRSHXroW, AArch64::LDRSWroW,1783 AArch64::LDRXroW }1784 },1785 // Zero-extend.1786 { { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,1787 AArch64::LDURXi },1788 { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,1789 AArch64::LDURXi },1790 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,1791 AArch64::LDRXui },1792 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,1793 AArch64::LDRXui },1794 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,1795 AArch64::LDRXroX },1796 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,1797 AArch64::LDRXroX },1798 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,1799 AArch64::LDRXroW },1800 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,1801 AArch64::LDRXroW }1802 }1803 };1804 1805 static const unsigned FPOpcTable[4][2] = {1806 { AArch64::LDURSi, AArch64::LDURDi },1807 { AArch64::LDRSui, AArch64::LDRDui },1808 { AArch64::LDRSroX, AArch64::LDRDroX },1809 { AArch64::LDRSroW, AArch64::LDRDroW }1810 };1811 1812 unsigned Opc;1813 const TargetRegisterClass *RC;1814 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&1815 Addr.getOffsetReg();1816 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;1817 if (Addr.getExtendType() == AArch64_AM::UXTW ||1818 Addr.getExtendType() == AArch64_AM::SXTW)1819 Idx++;1820 1821 bool IsRet64Bit = RetVT == MVT::i64;1822 switch (VT.SimpleTy) {1823 default:1824 llvm_unreachable("Unexpected value type.");1825 case MVT::i1: // Intentional fall-through.1826 case MVT::i8:1827 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][0];1828 RC = (IsRet64Bit && !WantZExt) ?1829 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;1830 break;1831 case MVT::i16:1832 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][1];1833 RC = (IsRet64Bit && !WantZExt) ?1834 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;1835 break;1836 case MVT::i32:1837 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][2];1838 RC = (IsRet64Bit && !WantZExt) ?1839 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;1840 break;1841 case MVT::i64:1842 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][3];1843 RC = &AArch64::GPR64RegClass;1844 break;1845 case MVT::f32:1846 Opc = FPOpcTable[Idx][0];1847 RC = &AArch64::FPR32RegClass;1848 break;1849 case MVT::f64:1850 Opc = FPOpcTable[Idx][1];1851 RC = &AArch64::FPR64RegClass;1852 break;1853 }1854 1855 // Create the base instruction, then add the operands.1856 Register ResultReg = createResultReg(RC);1857 MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,1858 TII.get(Opc), ResultReg);1859 addLoadStoreOperands(Addr, MIB, MachineMemOperand::MOLoad, ScaleFactor, MMO);1860 1861 // Loading an i1 requires special handling.1862 if (VT == MVT::i1) {1863 Register ANDReg = emitAnd_ri(MVT::i32, ResultReg, 1);1864 assert(ANDReg && "Unexpected AND instruction emission failure.");1865 ResultReg = ANDReg;1866 }1867 1868 // For zero-extending loads to 64bit we emit a 32bit load and then convert1869 // the 32bit reg to a 64bit reg.1870 if (WantZExt && RetVT == MVT::i64 && VT <= MVT::i32) {1871 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);1872 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,1873 TII.get(AArch64::SUBREG_TO_REG), Reg64)1874 .addImm(0)1875 .addReg(ResultReg, getKillRegState(true))1876 .addImm(AArch64::sub_32);1877 ResultReg = Reg64;1878 }1879 return ResultReg;1880}1881 1882bool AArch64FastISel::selectAddSub(const Instruction *I) {1883 MVT VT;1884 if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true))1885 return false;1886 1887 if (VT.isVector())1888 return selectOperator(I, I->getOpcode());1889 1890 Register ResultReg;1891 switch (I->getOpcode()) {1892 default:1893 llvm_unreachable("Unexpected instruction.");1894 case Instruction::Add:1895 ResultReg = emitAdd(VT, I->getOperand(0), I->getOperand(1));1896 break;1897 case Instruction::Sub:1898 ResultReg = emitSub(VT, I->getOperand(0), I->getOperand(1));1899 break;1900 }1901 if (!ResultReg)1902 return false;1903 1904 updateValueMap(I, ResultReg);1905 return true;1906}1907 1908bool AArch64FastISel::selectLogicalOp(const Instruction *I) {1909 MVT VT;1910 if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true))1911 return false;1912 1913 if (VT.isVector())1914 return selectOperator(I, I->getOpcode());1915 1916 Register ResultReg;1917 switch (I->getOpcode()) {1918 default:1919 llvm_unreachable("Unexpected instruction.");1920 case Instruction::And:1921 ResultReg = emitLogicalOp(ISD::AND, VT, I->getOperand(0), I->getOperand(1));1922 break;1923 case Instruction::Or:1924 ResultReg = emitLogicalOp(ISD::OR, VT, I->getOperand(0), I->getOperand(1));1925 break;1926 case Instruction::Xor:1927 ResultReg = emitLogicalOp(ISD::XOR, VT, I->getOperand(0), I->getOperand(1));1928 break;1929 }1930 if (!ResultReg)1931 return false;1932 1933 updateValueMap(I, ResultReg);1934 return true;1935}1936 1937bool AArch64FastISel::selectLoad(const Instruction *I) {1938 MVT VT;1939 // Verify we have a legal type before going any further. Currently, we handle1940 // simple types that will directly fit in a register (i32/f32/i64/f64) or1941 // those that can be sign or zero-extended to a basic operation (i1/i8/i16).1942 if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true) ||1943 cast<LoadInst>(I)->isAtomic())1944 return false;1945 1946 const Value *SV = I->getOperand(0);1947 if (TLI.supportSwiftError()) {1948 // Swifterror values can come from either a function parameter with1949 // swifterror attribute or an alloca with swifterror attribute.1950 if (const Argument *Arg = dyn_cast<Argument>(SV)) {1951 if (Arg->hasSwiftErrorAttr())1952 return false;1953 }1954 1955 if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(SV)) {1956 if (Alloca->isSwiftError())1957 return false;1958 }1959 }1960 1961 // See if we can handle this address.1962 Address Addr;1963 if (!computeAddress(I->getOperand(0), Addr, I->getType()))1964 return false;1965 1966 // Fold the following sign-/zero-extend into the load instruction.1967 bool WantZExt = true;1968 MVT RetVT = VT;1969 const Value *IntExtVal = nullptr;1970 if (I->hasOneUse()) {1971 if (const auto *ZE = dyn_cast<ZExtInst>(I->use_begin()->getUser())) {1972 if (isTypeSupported(ZE->getType(), RetVT))1973 IntExtVal = ZE;1974 else1975 RetVT = VT;1976 } else if (const auto *SE = dyn_cast<SExtInst>(I->use_begin()->getUser())) {1977 if (isTypeSupported(SE->getType(), RetVT))1978 IntExtVal = SE;1979 else1980 RetVT = VT;1981 WantZExt = false;1982 }1983 }1984 1985 Register ResultReg =1986 emitLoad(VT, RetVT, Addr, WantZExt, createMachineMemOperandFor(I));1987 if (!ResultReg)1988 return false;1989 1990 // There are a few different cases we have to handle, because the load or the1991 // sign-/zero-extend might not be selected by FastISel if we fall-back to1992 // SelectionDAG. There is also an ordering issue when both instructions are in1993 // different basic blocks.1994 // 1.) The load instruction is selected by FastISel, but the integer extend1995 // not. This usually happens when the integer extend is in a different1996 // basic block and SelectionDAG took over for that basic block.1997 // 2.) The load instruction is selected before the integer extend. This only1998 // happens when the integer extend is in a different basic block.1999 // 3.) The load instruction is selected by SelectionDAG and the integer extend2000 // by FastISel. This happens if there are instructions between the load2001 // and the integer extend that couldn't be selected by FastISel.2002 if (IntExtVal) {2003 // The integer extend hasn't been emitted yet. FastISel or SelectionDAG2004 // could select it. Emit a copy to subreg if necessary. FastISel will remove2005 // it when it selects the integer extend.2006 Register Reg = lookUpRegForValue(IntExtVal);2007 auto *MI = MRI.getUniqueVRegDef(Reg);2008 if (!MI) {2009 if (RetVT == MVT::i64 && VT <= MVT::i32) {2010 if (WantZExt) {2011 // Delete the last emitted instruction from emitLoad (SUBREG_TO_REG).2012 MachineBasicBlock::iterator I(std::prev(FuncInfo.InsertPt));2013 ResultReg = std::prev(I)->getOperand(0).getReg();2014 removeDeadCode(I, std::next(I));2015 } else2016 ResultReg = fastEmitInst_extractsubreg(MVT::i32, ResultReg,2017 AArch64::sub_32);2018 }2019 updateValueMap(I, ResultReg);2020 return true;2021 }2022 2023 // The integer extend has already been emitted - delete all the instructions2024 // that have been emitted by the integer extend lowering code and use the2025 // result from the load instruction directly.2026 while (MI) {2027 Reg = 0;2028 for (auto &Opnd : MI->uses()) {2029 if (Opnd.isReg()) {2030 Reg = Opnd.getReg();2031 break;2032 }2033 }2034 MachineBasicBlock::iterator I(MI);2035 removeDeadCode(I, std::next(I));2036 MI = nullptr;2037 if (Reg)2038 MI = MRI.getUniqueVRegDef(Reg);2039 }2040 updateValueMap(IntExtVal, ResultReg);2041 return true;2042 }2043 2044 updateValueMap(I, ResultReg);2045 return true;2046}2047 2048bool AArch64FastISel::emitStoreRelease(MVT VT, Register SrcReg,2049 Register AddrReg,2050 MachineMemOperand *MMO) {2051 unsigned Opc;2052 switch (VT.SimpleTy) {2053 default: return false;2054 case MVT::i8: Opc = AArch64::STLRB; break;2055 case MVT::i16: Opc = AArch64::STLRH; break;2056 case MVT::i32: Opc = AArch64::STLRW; break;2057 case MVT::i64: Opc = AArch64::STLRX; break;2058 }2059 2060 const MCInstrDesc &II = TII.get(Opc);2061 SrcReg = constrainOperandRegClass(II, SrcReg, 0);2062 AddrReg = constrainOperandRegClass(II, AddrReg, 1);2063 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)2064 .addReg(SrcReg)2065 .addReg(AddrReg)2066 .addMemOperand(MMO);2067 return true;2068}2069 2070bool AArch64FastISel::emitStore(MVT VT, Register SrcReg, Address Addr,2071 MachineMemOperand *MMO) {2072 if (!TLI.allowsMisalignedMemoryAccesses(VT))2073 return false;2074 2075 // Simplify this down to something we can handle.2076 if (!simplifyAddress(Addr, VT))2077 return false;2078 2079 unsigned ScaleFactor = getImplicitScaleFactor(VT);2080 if (!ScaleFactor)2081 llvm_unreachable("Unexpected value type.");2082 2083 // Negative offsets require unscaled, 9-bit, signed immediate offsets.2084 // Otherwise, we try using scaled, 12-bit, unsigned immediate offsets.2085 bool UseScaled = true;2086 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {2087 UseScaled = false;2088 ScaleFactor = 1;2089 }2090 2091 static const unsigned OpcTable[4][6] = {2092 { AArch64::STURBBi, AArch64::STURHHi, AArch64::STURWi, AArch64::STURXi,2093 AArch64::STURSi, AArch64::STURDi },2094 { AArch64::STRBBui, AArch64::STRHHui, AArch64::STRWui, AArch64::STRXui,2095 AArch64::STRSui, AArch64::STRDui },2096 { AArch64::STRBBroX, AArch64::STRHHroX, AArch64::STRWroX, AArch64::STRXroX,2097 AArch64::STRSroX, AArch64::STRDroX },2098 { AArch64::STRBBroW, AArch64::STRHHroW, AArch64::STRWroW, AArch64::STRXroW,2099 AArch64::STRSroW, AArch64::STRDroW }2100 };2101 2102 unsigned Opc;2103 bool VTIsi1 = false;2104 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&2105 Addr.getOffsetReg();2106 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;2107 if (Addr.getExtendType() == AArch64_AM::UXTW ||2108 Addr.getExtendType() == AArch64_AM::SXTW)2109 Idx++;2110 2111 switch (VT.SimpleTy) {2112 default: llvm_unreachable("Unexpected value type.");2113 case MVT::i1: VTIsi1 = true; [[fallthrough]];2114 case MVT::i8: Opc = OpcTable[Idx][0]; break;2115 case MVT::i16: Opc = OpcTable[Idx][1]; break;2116 case MVT::i32: Opc = OpcTable[Idx][2]; break;2117 case MVT::i64: Opc = OpcTable[Idx][3]; break;2118 case MVT::f32: Opc = OpcTable[Idx][4]; break;2119 case MVT::f64: Opc = OpcTable[Idx][5]; break;2120 }2121 2122 // Storing an i1 requires special handling.2123 if (VTIsi1 && SrcReg != AArch64::WZR) {2124 Register ANDReg = emitAnd_ri(MVT::i32, SrcReg, 1);2125 assert(ANDReg && "Unexpected AND instruction emission failure.");2126 SrcReg = ANDReg;2127 }2128 // Create the base instruction, then add the operands.2129 const MCInstrDesc &II = TII.get(Opc);2130 SrcReg = constrainOperandRegClass(II, SrcReg, II.getNumDefs());2131 MachineInstrBuilder MIB =2132 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II).addReg(SrcReg);2133 addLoadStoreOperands(Addr, MIB, MachineMemOperand::MOStore, ScaleFactor, MMO);2134 2135 return true;2136}2137 2138bool AArch64FastISel::selectStore(const Instruction *I) {2139 MVT VT;2140 const Value *Op0 = I->getOperand(0);2141 // Verify we have a legal type before going any further. Currently, we handle2142 // simple types that will directly fit in a register (i32/f32/i64/f64) or2143 // those that can be sign or zero-extended to a basic operation (i1/i8/i16).2144 if (!isTypeSupported(Op0->getType(), VT, /*IsVectorAllowed=*/true))2145 return false;2146 2147 const Value *PtrV = I->getOperand(1);2148 if (TLI.supportSwiftError()) {2149 // Swifterror values can come from either a function parameter with2150 // swifterror attribute or an alloca with swifterror attribute.2151 if (const Argument *Arg = dyn_cast<Argument>(PtrV)) {2152 if (Arg->hasSwiftErrorAttr())2153 return false;2154 }2155 2156 if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(PtrV)) {2157 if (Alloca->isSwiftError())2158 return false;2159 }2160 }2161 2162 // Get the value to be stored into a register. Use the zero register directly2163 // when possible to avoid an unnecessary copy and a wasted register.2164 Register SrcReg;2165 if (const auto *CI = dyn_cast<ConstantInt>(Op0)) {2166 if (CI->isZero())2167 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;2168 } else if (const auto *CF = dyn_cast<ConstantFP>(Op0)) {2169 if (CF->isZero() && !CF->isNegative()) {2170 VT = MVT::getIntegerVT(VT.getSizeInBits());2171 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;2172 }2173 }2174 2175 if (!SrcReg)2176 SrcReg = getRegForValue(Op0);2177 2178 if (!SrcReg)2179 return false;2180 2181 auto *SI = cast<StoreInst>(I);2182 2183 // Try to emit a STLR for seq_cst/release.2184 if (SI->isAtomic()) {2185 AtomicOrdering Ord = SI->getOrdering();2186 // The non-atomic instructions are sufficient for relaxed stores.2187 if (isReleaseOrStronger(Ord)) {2188 // The STLR addressing mode only supports a base reg; pass that directly.2189 Register AddrReg = getRegForValue(PtrV);2190 if (!AddrReg)2191 return false;2192 return emitStoreRelease(VT, SrcReg, AddrReg,2193 createMachineMemOperandFor(I));2194 }2195 }2196 2197 // See if we can handle this address.2198 Address Addr;2199 if (!computeAddress(PtrV, Addr, Op0->getType()))2200 return false;2201 2202 if (!emitStore(VT, SrcReg, Addr, createMachineMemOperandFor(I)))2203 return false;2204 return true;2205}2206 2207static AArch64CC::CondCode getCompareCC(CmpInst::Predicate Pred) {2208 switch (Pred) {2209 case CmpInst::FCMP_ONE:2210 case CmpInst::FCMP_UEQ:2211 default:2212 // AL is our "false" for now. The other two need more compares.2213 return AArch64CC::AL;2214 case CmpInst::ICMP_EQ:2215 case CmpInst::FCMP_OEQ:2216 return AArch64CC::EQ;2217 case CmpInst::ICMP_SGT:2218 case CmpInst::FCMP_OGT:2219 return AArch64CC::GT;2220 case CmpInst::ICMP_SGE:2221 case CmpInst::FCMP_OGE:2222 return AArch64CC::GE;2223 case CmpInst::ICMP_UGT:2224 case CmpInst::FCMP_UGT:2225 return AArch64CC::HI;2226 case CmpInst::FCMP_OLT:2227 return AArch64CC::MI;2228 case CmpInst::ICMP_ULE:2229 case CmpInst::FCMP_OLE:2230 return AArch64CC::LS;2231 case CmpInst::FCMP_ORD:2232 return AArch64CC::VC;2233 case CmpInst::FCMP_UNO:2234 return AArch64CC::VS;2235 case CmpInst::FCMP_UGE:2236 return AArch64CC::PL;2237 case CmpInst::ICMP_SLT:2238 case CmpInst::FCMP_ULT:2239 return AArch64CC::LT;2240 case CmpInst::ICMP_SLE:2241 case CmpInst::FCMP_ULE:2242 return AArch64CC::LE;2243 case CmpInst::FCMP_UNE:2244 case CmpInst::ICMP_NE:2245 return AArch64CC::NE;2246 case CmpInst::ICMP_UGE:2247 return AArch64CC::HS;2248 case CmpInst::ICMP_ULT:2249 return AArch64CC::LO;2250 }2251}2252 2253/// Try to emit a combined compare-and-branch instruction.2254bool AArch64FastISel::emitCompareAndBranch(const BranchInst *BI) {2255 // Speculation tracking/SLH assumes that optimized TB(N)Z/CB(N)Z instructions2256 // will not be produced, as they are conditional branch instructions that do2257 // not set flags.2258 if (FuncInfo.MF->getFunction().hasFnAttribute(2259 Attribute::SpeculativeLoadHardening))2260 return false;2261 2262 assert(isa<CmpInst>(BI->getCondition()) && "Expected cmp instruction");2263 const CmpInst *CI = cast<CmpInst>(BI->getCondition());2264 CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);2265 2266 const Value *LHS = CI->getOperand(0);2267 const Value *RHS = CI->getOperand(1);2268 2269 MVT VT;2270 if (!isTypeSupported(LHS->getType(), VT))2271 return false;2272 2273 unsigned BW = VT.getSizeInBits();2274 if (BW > 64)2275 return false;2276 2277 MachineBasicBlock *TBB = FuncInfo.getMBB(BI->getSuccessor(0));2278 MachineBasicBlock *FBB = FuncInfo.getMBB(BI->getSuccessor(1));2279 2280 // Try to take advantage of fallthrough opportunities.2281 if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {2282 std::swap(TBB, FBB);2283 Predicate = CmpInst::getInversePredicate(Predicate);2284 }2285 2286 int TestBit = -1;2287 bool IsCmpNE;2288 switch (Predicate) {2289 default:2290 return false;2291 case CmpInst::ICMP_EQ:2292 case CmpInst::ICMP_NE:2293 if (isa<Constant>(LHS) && cast<Constant>(LHS)->isNullValue())2294 std::swap(LHS, RHS);2295 2296 if (!isa<Constant>(RHS) || !cast<Constant>(RHS)->isNullValue())2297 return false;2298 2299 if (const auto *AI = dyn_cast<BinaryOperator>(LHS))2300 if (AI->getOpcode() == Instruction::And && isValueAvailable(AI)) {2301 const Value *AndLHS = AI->getOperand(0);2302 const Value *AndRHS = AI->getOperand(1);2303 2304 if (const auto *C = dyn_cast<ConstantInt>(AndLHS))2305 if (C->getValue().isPowerOf2())2306 std::swap(AndLHS, AndRHS);2307 2308 if (const auto *C = dyn_cast<ConstantInt>(AndRHS))2309 if (C->getValue().isPowerOf2()) {2310 TestBit = C->getValue().logBase2();2311 LHS = AndLHS;2312 }2313 }2314 2315 if (VT == MVT::i1)2316 TestBit = 0;2317 2318 IsCmpNE = Predicate == CmpInst::ICMP_NE;2319 break;2320 case CmpInst::ICMP_SLT:2321 case CmpInst::ICMP_SGE:2322 if (!isa<Constant>(RHS) || !cast<Constant>(RHS)->isNullValue())2323 return false;2324 2325 TestBit = BW - 1;2326 IsCmpNE = Predicate == CmpInst::ICMP_SLT;2327 break;2328 case CmpInst::ICMP_SGT:2329 case CmpInst::ICMP_SLE:2330 if (!isa<ConstantInt>(RHS))2331 return false;2332 2333 if (cast<ConstantInt>(RHS)->getValue() != APInt(BW, -1, true))2334 return false;2335 2336 TestBit = BW - 1;2337 IsCmpNE = Predicate == CmpInst::ICMP_SLE;2338 break;2339 } // end switch2340 2341 static const unsigned OpcTable[2][2][2] = {2342 { {AArch64::CBZW, AArch64::CBZX },2343 {AArch64::CBNZW, AArch64::CBNZX} },2344 { {AArch64::TBZW, AArch64::TBZX },2345 {AArch64::TBNZW, AArch64::TBNZX} }2346 };2347 2348 bool IsBitTest = TestBit != -1;2349 bool Is64Bit = BW == 64;2350 if (TestBit < 32 && TestBit >= 0)2351 Is64Bit = false;2352 2353 unsigned Opc = OpcTable[IsBitTest][IsCmpNE][Is64Bit];2354 const MCInstrDesc &II = TII.get(Opc);2355 2356 Register SrcReg = getRegForValue(LHS);2357 if (!SrcReg)2358 return false;2359 2360 if (BW == 64 && !Is64Bit)2361 SrcReg = fastEmitInst_extractsubreg(MVT::i32, SrcReg, AArch64::sub_32);2362 2363 if ((BW < 32) && !IsBitTest)2364 SrcReg = emitIntExt(VT, SrcReg, MVT::i32, /*isZExt=*/true);2365 2366 // Emit the combined compare and branch instruction.2367 SrcReg = constrainOperandRegClass(II, SrcReg, II.getNumDefs());2368 MachineInstrBuilder MIB =2369 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc))2370 .addReg(SrcReg);2371 if (IsBitTest)2372 MIB.addImm(TestBit);2373 MIB.addMBB(TBB);2374 2375 finishCondBranch(BI->getParent(), TBB, FBB);2376 return true;2377}2378 2379bool AArch64FastISel::selectBranch(const Instruction *I) {2380 const BranchInst *BI = cast<BranchInst>(I);2381 if (BI->isUnconditional()) {2382 MachineBasicBlock *MSucc = FuncInfo.getMBB(BI->getSuccessor(0));2383 fastEmitBranch(MSucc, BI->getDebugLoc());2384 return true;2385 }2386 2387 MachineBasicBlock *TBB = FuncInfo.getMBB(BI->getSuccessor(0));2388 MachineBasicBlock *FBB = FuncInfo.getMBB(BI->getSuccessor(1));2389 2390 if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) {2391 if (CI->hasOneUse() && isValueAvailable(CI)) {2392 // Try to optimize or fold the cmp.2393 CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);2394 switch (Predicate) {2395 default:2396 break;2397 case CmpInst::FCMP_FALSE:2398 fastEmitBranch(FBB, MIMD.getDL());2399 return true;2400 case CmpInst::FCMP_TRUE:2401 fastEmitBranch(TBB, MIMD.getDL());2402 return true;2403 }2404 2405 // Try to emit a combined compare-and-branch first.2406 if (emitCompareAndBranch(BI))2407 return true;2408 2409 // Try to take advantage of fallthrough opportunities.2410 if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {2411 std::swap(TBB, FBB);2412 Predicate = CmpInst::getInversePredicate(Predicate);2413 }2414 2415 // Emit the cmp.2416 if (!emitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned()))2417 return false;2418 2419 // FCMP_UEQ and FCMP_ONE cannot be checked with a single branch2420 // instruction.2421 AArch64CC::CondCode CC = getCompareCC(Predicate);2422 AArch64CC::CondCode ExtraCC = AArch64CC::AL;2423 switch (Predicate) {2424 default:2425 break;2426 case CmpInst::FCMP_UEQ:2427 ExtraCC = AArch64CC::EQ;2428 CC = AArch64CC::VS;2429 break;2430 case CmpInst::FCMP_ONE:2431 ExtraCC = AArch64CC::MI;2432 CC = AArch64CC::GT;2433 break;2434 }2435 assert((CC != AArch64CC::AL) && "Unexpected condition code.");2436 2437 // Emit the extra branch for FCMP_UEQ and FCMP_ONE.2438 if (ExtraCC != AArch64CC::AL) {2439 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::Bcc))2440 .addImm(ExtraCC)2441 .addMBB(TBB);2442 }2443 2444 // Emit the branch.2445 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::Bcc))2446 .addImm(CC)2447 .addMBB(TBB);2448 2449 finishCondBranch(BI->getParent(), TBB, FBB);2450 return true;2451 }2452 } else if (const auto *CI = dyn_cast<ConstantInt>(BI->getCondition())) {2453 uint64_t Imm = CI->getZExtValue();2454 MachineBasicBlock *Target = (Imm == 0) ? FBB : TBB;2455 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::B))2456 .addMBB(Target);2457 2458 // Obtain the branch probability and add the target to the successor list.2459 if (FuncInfo.BPI) {2460 auto BranchProbability = FuncInfo.BPI->getEdgeProbability(2461 BI->getParent(), Target->getBasicBlock());2462 FuncInfo.MBB->addSuccessor(Target, BranchProbability);2463 } else2464 FuncInfo.MBB->addSuccessorWithoutProb(Target);2465 return true;2466 } else {2467 AArch64CC::CondCode CC = AArch64CC::NE;2468 if (foldXALUIntrinsic(CC, I, BI->getCondition())) {2469 // Fake request the condition, otherwise the intrinsic might be completely2470 // optimized away.2471 Register CondReg = getRegForValue(BI->getCondition());2472 if (!CondReg)2473 return false;2474 2475 // Emit the branch.2476 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::Bcc))2477 .addImm(CC)2478 .addMBB(TBB);2479 2480 finishCondBranch(BI->getParent(), TBB, FBB);2481 return true;2482 }2483 }2484 2485 Register CondReg = getRegForValue(BI->getCondition());2486 if (!CondReg)2487 return false;2488 2489 // i1 conditions come as i32 values, test the lowest bit with tb(n)z.2490 unsigned Opcode = AArch64::TBNZW;2491 if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {2492 std::swap(TBB, FBB);2493 Opcode = AArch64::TBZW;2494 }2495 2496 const MCInstrDesc &II = TII.get(Opcode);2497 Register ConstrainedCondReg2498 = constrainOperandRegClass(II, CondReg, II.getNumDefs());2499 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)2500 .addReg(ConstrainedCondReg)2501 .addImm(0)2502 .addMBB(TBB);2503 2504 finishCondBranch(BI->getParent(), TBB, FBB);2505 return true;2506}2507 2508bool AArch64FastISel::selectIndirectBr(const Instruction *I) {2509 const IndirectBrInst *BI = cast<IndirectBrInst>(I);2510 Register AddrReg = getRegForValue(BI->getOperand(0));2511 if (!AddrReg)2512 return false;2513 2514 // Authenticated indirectbr is not implemented yet.2515 if (FuncInfo.MF->getFunction().hasFnAttribute("ptrauth-indirect-gotos"))2516 return false;2517 2518 // Emit the indirect branch.2519 const MCInstrDesc &II = TII.get(AArch64::BR);2520 AddrReg = constrainOperandRegClass(II, AddrReg, II.getNumDefs());2521 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II).addReg(AddrReg);2522 2523 // Make sure the CFG is up-to-date.2524 for (const auto *Succ : BI->successors())2525 FuncInfo.MBB->addSuccessor(FuncInfo.getMBB(Succ));2526 2527 return true;2528}2529 2530bool AArch64FastISel::selectCmp(const Instruction *I) {2531 const CmpInst *CI = cast<CmpInst>(I);2532 2533 // Vectors of i1 are weird: bail out.2534 if (CI->getType()->isVectorTy())2535 return false;2536 2537 // Try to optimize or fold the cmp.2538 CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);2539 Register ResultReg;2540 switch (Predicate) {2541 default:2542 break;2543 case CmpInst::FCMP_FALSE:2544 ResultReg = createResultReg(&AArch64::GPR32RegClass);2545 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,2546 TII.get(TargetOpcode::COPY), ResultReg)2547 .addReg(AArch64::WZR, getKillRegState(true));2548 break;2549 case CmpInst::FCMP_TRUE:2550 ResultReg = fastEmit_i(MVT::i32, MVT::i32, ISD::Constant, 1);2551 break;2552 }2553 2554 if (ResultReg) {2555 updateValueMap(I, ResultReg);2556 return true;2557 }2558 2559 // Emit the cmp.2560 if (!emitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned()))2561 return false;2562 2563 ResultReg = createResultReg(&AArch64::GPR32RegClass);2564 2565 // FCMP_UEQ and FCMP_ONE cannot be checked with a single instruction. These2566 // condition codes are inverted, because they are used by CSINC.2567 static unsigned CondCodeTable[2][2] = {2568 { AArch64CC::NE, AArch64CC::VC },2569 { AArch64CC::PL, AArch64CC::LE }2570 };2571 unsigned *CondCodes = nullptr;2572 switch (Predicate) {2573 default:2574 break;2575 case CmpInst::FCMP_UEQ:2576 CondCodes = &CondCodeTable[0][0];2577 break;2578 case CmpInst::FCMP_ONE:2579 CondCodes = &CondCodeTable[1][0];2580 break;2581 }2582 2583 if (CondCodes) {2584 Register TmpReg1 = createResultReg(&AArch64::GPR32RegClass);2585 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::CSINCWr),2586 TmpReg1)2587 .addReg(AArch64::WZR, getKillRegState(true))2588 .addReg(AArch64::WZR, getKillRegState(true))2589 .addImm(CondCodes[0]);2590 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::CSINCWr),2591 ResultReg)2592 .addReg(TmpReg1, getKillRegState(true))2593 .addReg(AArch64::WZR, getKillRegState(true))2594 .addImm(CondCodes[1]);2595 2596 updateValueMap(I, ResultReg);2597 return true;2598 }2599 2600 // Now set a register based on the comparison.2601 AArch64CC::CondCode CC = getCompareCC(Predicate);2602 assert((CC != AArch64CC::AL) && "Unexpected condition code.");2603 AArch64CC::CondCode invertedCC = getInvertedCondCode(CC);2604 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::CSINCWr),2605 ResultReg)2606 .addReg(AArch64::WZR, getKillRegState(true))2607 .addReg(AArch64::WZR, getKillRegState(true))2608 .addImm(invertedCC);2609 2610 updateValueMap(I, ResultReg);2611 return true;2612}2613 2614/// Optimize selects of i1 if one of the operands has a 'true' or 'false'2615/// value.2616bool AArch64FastISel::optimizeSelect(const SelectInst *SI) {2617 if (!SI->getType()->isIntegerTy(1))2618 return false;2619 2620 const Value *Src1Val, *Src2Val;2621 unsigned Opc = 0;2622 bool NeedExtraOp = false;2623 if (auto *CI = dyn_cast<ConstantInt>(SI->getTrueValue())) {2624 if (CI->isOne()) {2625 Src1Val = SI->getCondition();2626 Src2Val = SI->getFalseValue();2627 Opc = AArch64::ORRWrr;2628 } else {2629 assert(CI->isZero());2630 Src1Val = SI->getFalseValue();2631 Src2Val = SI->getCondition();2632 Opc = AArch64::BICWrr;2633 }2634 } else if (auto *CI = dyn_cast<ConstantInt>(SI->getFalseValue())) {2635 if (CI->isOne()) {2636 Src1Val = SI->getCondition();2637 Src2Val = SI->getTrueValue();2638 Opc = AArch64::ORRWrr;2639 NeedExtraOp = true;2640 } else {2641 assert(CI->isZero());2642 Src1Val = SI->getCondition();2643 Src2Val = SI->getTrueValue();2644 Opc = AArch64::ANDWrr;2645 }2646 }2647 2648 if (!Opc)2649 return false;2650 2651 Register Src1Reg = getRegForValue(Src1Val);2652 if (!Src1Reg)2653 return false;2654 2655 Register Src2Reg = getRegForValue(Src2Val);2656 if (!Src2Reg)2657 return false;2658 2659 if (NeedExtraOp)2660 Src1Reg = emitLogicalOp_ri(ISD::XOR, MVT::i32, Src1Reg, 1);2661 2662 Register ResultReg = fastEmitInst_rr(Opc, &AArch64::GPR32RegClass, Src1Reg,2663 Src2Reg);2664 updateValueMap(SI, ResultReg);2665 return true;2666}2667 2668bool AArch64FastISel::selectSelect(const Instruction *I) {2669 assert(isa<SelectInst>(I) && "Expected a select instruction.");2670 MVT VT;2671 if (!isTypeSupported(I->getType(), VT))2672 return false;2673 2674 unsigned Opc;2675 const TargetRegisterClass *RC;2676 switch (VT.SimpleTy) {2677 default:2678 return false;2679 case MVT::i1:2680 case MVT::i8:2681 case MVT::i16:2682 case MVT::i32:2683 Opc = AArch64::CSELWr;2684 RC = &AArch64::GPR32RegClass;2685 break;2686 case MVT::i64:2687 Opc = AArch64::CSELXr;2688 RC = &AArch64::GPR64RegClass;2689 break;2690 case MVT::f32:2691 Opc = AArch64::FCSELSrrr;2692 RC = &AArch64::FPR32RegClass;2693 break;2694 case MVT::f64:2695 Opc = AArch64::FCSELDrrr;2696 RC = &AArch64::FPR64RegClass;2697 break;2698 }2699 2700 const SelectInst *SI = cast<SelectInst>(I);2701 const Value *Cond = SI->getCondition();2702 AArch64CC::CondCode CC = AArch64CC::NE;2703 AArch64CC::CondCode ExtraCC = AArch64CC::AL;2704 2705 if (optimizeSelect(SI))2706 return true;2707 2708 // Try to pickup the flags, so we don't have to emit another compare.2709 if (foldXALUIntrinsic(CC, I, Cond)) {2710 // Fake request the condition to force emission of the XALU intrinsic.2711 Register CondReg = getRegForValue(Cond);2712 if (!CondReg)2713 return false;2714 } else if (isa<CmpInst>(Cond) && cast<CmpInst>(Cond)->hasOneUse() &&2715 isValueAvailable(Cond)) {2716 const auto *Cmp = cast<CmpInst>(Cond);2717 // Try to optimize or fold the cmp.2718 CmpInst::Predicate Predicate = optimizeCmpPredicate(Cmp);2719 const Value *FoldSelect = nullptr;2720 switch (Predicate) {2721 default:2722 break;2723 case CmpInst::FCMP_FALSE:2724 FoldSelect = SI->getFalseValue();2725 break;2726 case CmpInst::FCMP_TRUE:2727 FoldSelect = SI->getTrueValue();2728 break;2729 }2730 2731 if (FoldSelect) {2732 Register SrcReg = getRegForValue(FoldSelect);2733 if (!SrcReg)2734 return false;2735 2736 updateValueMap(I, SrcReg);2737 return true;2738 }2739 2740 // Emit the cmp.2741 if (!emitCmp(Cmp->getOperand(0), Cmp->getOperand(1), Cmp->isUnsigned()))2742 return false;2743 2744 // FCMP_UEQ and FCMP_ONE cannot be checked with a single select instruction.2745 CC = getCompareCC(Predicate);2746 switch (Predicate) {2747 default:2748 break;2749 case CmpInst::FCMP_UEQ:2750 ExtraCC = AArch64CC::EQ;2751 CC = AArch64CC::VS;2752 break;2753 case CmpInst::FCMP_ONE:2754 ExtraCC = AArch64CC::MI;2755 CC = AArch64CC::GT;2756 break;2757 }2758 assert((CC != AArch64CC::AL) && "Unexpected condition code.");2759 } else {2760 Register CondReg = getRegForValue(Cond);2761 if (!CondReg)2762 return false;2763 2764 const MCInstrDesc &II = TII.get(AArch64::ANDSWri);2765 CondReg = constrainOperandRegClass(II, CondReg, 1);2766 2767 // Emit a TST instruction (ANDS wzr, reg, #imm).2768 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II,2769 AArch64::WZR)2770 .addReg(CondReg)2771 .addImm(AArch64_AM::encodeLogicalImmediate(1, 32));2772 }2773 2774 Register Src1Reg = getRegForValue(SI->getTrueValue());2775 Register Src2Reg = getRegForValue(SI->getFalseValue());2776 2777 if (!Src1Reg || !Src2Reg)2778 return false;2779 2780 if (ExtraCC != AArch64CC::AL)2781 Src2Reg = fastEmitInst_rri(Opc, RC, Src1Reg, Src2Reg, ExtraCC);2782 2783 Register ResultReg = fastEmitInst_rri(Opc, RC, Src1Reg, Src2Reg, CC);2784 updateValueMap(I, ResultReg);2785 return true;2786}2787 2788bool AArch64FastISel::selectFPExt(const Instruction *I) {2789 Value *V = I->getOperand(0);2790 if (!I->getType()->isDoubleTy() || !V->getType()->isFloatTy())2791 return false;2792 2793 Register Op = getRegForValue(V);2794 if (Op == 0)2795 return false;2796 2797 Register ResultReg = createResultReg(&AArch64::FPR64RegClass);2798 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::FCVTDSr),2799 ResultReg).addReg(Op);2800 updateValueMap(I, ResultReg);2801 return true;2802}2803 2804bool AArch64FastISel::selectFPTrunc(const Instruction *I) {2805 Value *V = I->getOperand(0);2806 if (!I->getType()->isFloatTy() || !V->getType()->isDoubleTy())2807 return false;2808 2809 Register Op = getRegForValue(V);2810 if (Op == 0)2811 return false;2812 2813 Register ResultReg = createResultReg(&AArch64::FPR32RegClass);2814 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::FCVTSDr),2815 ResultReg).addReg(Op);2816 updateValueMap(I, ResultReg);2817 return true;2818}2819 2820// FPToUI and FPToSI2821bool AArch64FastISel::selectFPToInt(const Instruction *I, bool Signed) {2822 MVT DestVT;2823 if (!isTypeLegal(I->getType(), DestVT) || DestVT.isVector())2824 return false;2825 2826 Register SrcReg = getRegForValue(I->getOperand(0));2827 if (!SrcReg)2828 return false;2829 2830 EVT SrcVT = TLI.getValueType(DL, I->getOperand(0)->getType(), true);2831 if (SrcVT == MVT::f128 || SrcVT == MVT::f16 || SrcVT == MVT::bf16)2832 return false;2833 2834 unsigned Opc;2835 if (SrcVT == MVT::f64) {2836 if (Signed)2837 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWDr : AArch64::FCVTZSUXDr;2838 else2839 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWDr : AArch64::FCVTZUUXDr;2840 } else {2841 if (Signed)2842 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWSr : AArch64::FCVTZSUXSr;2843 else2844 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWSr : AArch64::FCVTZUUXSr;2845 }2846 Register ResultReg = createResultReg(2847 DestVT == MVT::i32 ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass);2848 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)2849 .addReg(SrcReg);2850 updateValueMap(I, ResultReg);2851 return true;2852}2853 2854bool AArch64FastISel::selectIntToFP(const Instruction *I, bool Signed) {2855 MVT DestVT;2856 if (!isTypeLegal(I->getType(), DestVT) || DestVT.isVector())2857 return false;2858 // Let regular ISEL handle FP162859 if (DestVT == MVT::f16 || DestVT == MVT::bf16)2860 return false;2861 2862 assert((DestVT == MVT::f32 || DestVT == MVT::f64) &&2863 "Unexpected value type.");2864 2865 Register SrcReg = getRegForValue(I->getOperand(0));2866 if (!SrcReg)2867 return false;2868 2869 EVT SrcVT = TLI.getValueType(DL, I->getOperand(0)->getType(), true);2870 2871 // Handle sign-extension.2872 if (SrcVT == MVT::i16 || SrcVT == MVT::i8 || SrcVT == MVT::i1) {2873 SrcReg =2874 emitIntExt(SrcVT.getSimpleVT(), SrcReg, MVT::i32, /*isZExt*/ !Signed);2875 if (!SrcReg)2876 return false;2877 }2878 2879 unsigned Opc;2880 if (SrcVT == MVT::i64) {2881 if (Signed)2882 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUXSri : AArch64::SCVTFUXDri;2883 else2884 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUXSri : AArch64::UCVTFUXDri;2885 } else {2886 if (Signed)2887 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUWSri : AArch64::SCVTFUWDri;2888 else2889 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUWSri : AArch64::UCVTFUWDri;2890 }2891 2892 Register ResultReg = fastEmitInst_r(Opc, TLI.getRegClassFor(DestVT), SrcReg);2893 updateValueMap(I, ResultReg);2894 return true;2895}2896 2897bool AArch64FastISel::fastLowerArguments() {2898 if (!FuncInfo.CanLowerReturn)2899 return false;2900 2901 const Function *F = FuncInfo.Fn;2902 if (F->isVarArg())2903 return false;2904 2905 CallingConv::ID CC = F->getCallingConv();2906 if (CC != CallingConv::C && CC != CallingConv::Swift)2907 return false;2908 2909 if (Subtarget->hasCustomCallingConv())2910 return false;2911 2912 // Only handle simple cases of up to 8 GPR and FPR each.2913 unsigned GPRCnt = 0;2914 unsigned FPRCnt = 0;2915 for (auto const &Arg : F->args()) {2916 if (Arg.hasAttribute(Attribute::ByVal) ||2917 Arg.hasAttribute(Attribute::InReg) ||2918 Arg.hasAttribute(Attribute::StructRet) ||2919 Arg.hasAttribute(Attribute::SwiftSelf) ||2920 Arg.hasAttribute(Attribute::SwiftAsync) ||2921 Arg.hasAttribute(Attribute::SwiftError) ||2922 Arg.hasAttribute(Attribute::Nest))2923 return false;2924 2925 Type *ArgTy = Arg.getType();2926 if (ArgTy->isStructTy() || ArgTy->isArrayTy())2927 return false;2928 2929 EVT ArgVT = TLI.getValueType(DL, ArgTy);2930 if (!ArgVT.isSimple())2931 return false;2932 2933 MVT VT = ArgVT.getSimpleVT().SimpleTy;2934 if (VT.isFloatingPoint() && !Subtarget->hasFPARMv8())2935 return false;2936 2937 if (VT.isVector() &&2938 (!Subtarget->hasNEON() || !Subtarget->isLittleEndian()))2939 return false;2940 2941 if (VT >= MVT::i1 && VT <= MVT::i64)2942 ++GPRCnt;2943 else if ((VT >= MVT::f16 && VT <= MVT::f64) || VT.is64BitVector() ||2944 VT.is128BitVector())2945 ++FPRCnt;2946 else2947 return false;2948 2949 if (GPRCnt > 8 || FPRCnt > 8)2950 return false;2951 }2952 2953 static const MCPhysReg Registers[6][8] = {2954 { AArch64::W0, AArch64::W1, AArch64::W2, AArch64::W3, AArch64::W4,2955 AArch64::W5, AArch64::W6, AArch64::W7 },2956 { AArch64::X0, AArch64::X1, AArch64::X2, AArch64::X3, AArch64::X4,2957 AArch64::X5, AArch64::X6, AArch64::X7 },2958 { AArch64::H0, AArch64::H1, AArch64::H2, AArch64::H3, AArch64::H4,2959 AArch64::H5, AArch64::H6, AArch64::H7 },2960 { AArch64::S0, AArch64::S1, AArch64::S2, AArch64::S3, AArch64::S4,2961 AArch64::S5, AArch64::S6, AArch64::S7 },2962 { AArch64::D0, AArch64::D1, AArch64::D2, AArch64::D3, AArch64::D4,2963 AArch64::D5, AArch64::D6, AArch64::D7 },2964 { AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,2965 AArch64::Q5, AArch64::Q6, AArch64::Q7 }2966 };2967 2968 unsigned GPRIdx = 0;2969 unsigned FPRIdx = 0;2970 for (auto const &Arg : F->args()) {2971 MVT VT = TLI.getSimpleValueType(DL, Arg.getType());2972 unsigned SrcReg;2973 const TargetRegisterClass *RC;2974 if (VT >= MVT::i1 && VT <= MVT::i32) {2975 SrcReg = Registers[0][GPRIdx++];2976 RC = &AArch64::GPR32RegClass;2977 VT = MVT::i32;2978 } else if (VT == MVT::i64) {2979 SrcReg = Registers[1][GPRIdx++];2980 RC = &AArch64::GPR64RegClass;2981 } else if (VT == MVT::f16 || VT == MVT::bf16) {2982 SrcReg = Registers[2][FPRIdx++];2983 RC = &AArch64::FPR16RegClass;2984 } else if (VT == MVT::f32) {2985 SrcReg = Registers[3][FPRIdx++];2986 RC = &AArch64::FPR32RegClass;2987 } else if ((VT == MVT::f64) || VT.is64BitVector()) {2988 SrcReg = Registers[4][FPRIdx++];2989 RC = &AArch64::FPR64RegClass;2990 } else if (VT.is128BitVector()) {2991 SrcReg = Registers[5][FPRIdx++];2992 RC = &AArch64::FPR128RegClass;2993 } else2994 llvm_unreachable("Unexpected value type.");2995 2996 Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);2997 // FIXME: Unfortunately it's necessary to emit a copy from the livein copy.2998 // Without this, EmitLiveInCopies may eliminate the livein if its only2999 // use is a bitcast (which isn't turned into an instruction).3000 Register ResultReg = createResultReg(RC);3001 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,3002 TII.get(TargetOpcode::COPY), ResultReg)3003 .addReg(DstReg, getKillRegState(true));3004 updateValueMap(&Arg, ResultReg);3005 }3006 return true;3007}3008 3009bool AArch64FastISel::processCallArgs(CallLoweringInfo &CLI,3010 SmallVectorImpl<MVT> &OutVTs,3011 SmallVectorImpl<Type *> &OrigTys,3012 unsigned &NumBytes) {3013 CallingConv::ID CC = CLI.CallConv;3014 SmallVector<CCValAssign, 16> ArgLocs;3015 CCState CCInfo(CC, false, *FuncInfo.MF, ArgLocs, *Context);3016 CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, OrigTys,3017 CCAssignFnForCall(CC));3018 3019 // Get a count of how many bytes are to be pushed on the stack.3020 NumBytes = CCInfo.getStackSize();3021 3022 // Issue CALLSEQ_START3023 unsigned AdjStackDown = TII.getCallFrameSetupOpcode();3024 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AdjStackDown))3025 .addImm(NumBytes).addImm(0);3026 3027 // Process the args.3028 for (CCValAssign &VA : ArgLocs) {3029 const Value *ArgVal = CLI.OutVals[VA.getValNo()];3030 MVT ArgVT = OutVTs[VA.getValNo()];3031 3032 Register ArgReg = getRegForValue(ArgVal);3033 if (!ArgReg)3034 return false;3035 3036 // Handle arg promotion: SExt, ZExt, AExt.3037 switch (VA.getLocInfo()) {3038 case CCValAssign::Full:3039 break;3040 case CCValAssign::SExt: {3041 MVT DestVT = VA.getLocVT();3042 MVT SrcVT = ArgVT;3043 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/false);3044 if (!ArgReg)3045 return false;3046 break;3047 }3048 case CCValAssign::AExt:3049 // Intentional fall-through.3050 case CCValAssign::ZExt: {3051 MVT DestVT = VA.getLocVT();3052 MVT SrcVT = ArgVT;3053 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/true);3054 if (!ArgReg)3055 return false;3056 break;3057 }3058 default:3059 llvm_unreachable("Unknown arg promotion!");3060 }3061 3062 // Now copy/store arg to correct locations.3063 if (VA.isRegLoc() && !VA.needsCustom()) {3064 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,3065 TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(ArgReg);3066 CLI.OutRegs.push_back(VA.getLocReg());3067 } else if (VA.needsCustom()) {3068 // FIXME: Handle custom args.3069 return false;3070 } else {3071 assert(VA.isMemLoc() && "Assuming store on stack.");3072 3073 // Don't emit stores for undef values.3074 if (isa<UndefValue>(ArgVal))3075 continue;3076 3077 // Need to store on the stack.3078 unsigned ArgSize = (ArgVT.getSizeInBits() + 7) / 8;3079 3080 unsigned BEAlign = 0;3081 if (ArgSize < 8 && !Subtarget->isLittleEndian())3082 BEAlign = 8 - ArgSize;3083 3084 Address Addr;3085 Addr.setKind(Address::RegBase);3086 Addr.setReg(AArch64::SP);3087 Addr.setOffset(VA.getLocMemOffset() + BEAlign);3088 3089 Align Alignment = DL.getABITypeAlign(ArgVal->getType());3090 MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(3091 MachinePointerInfo::getStack(*FuncInfo.MF, Addr.getOffset()),3092 MachineMemOperand::MOStore, ArgVT.getStoreSize(), Alignment);3093 3094 if (!emitStore(ArgVT, ArgReg, Addr, MMO))3095 return false;3096 }3097 }3098 return true;3099}3100 3101bool AArch64FastISel::finishCall(CallLoweringInfo &CLI, unsigned NumBytes) {3102 CallingConv::ID CC = CLI.CallConv;3103 3104 // Issue CALLSEQ_END3105 unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();3106 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AdjStackUp))3107 .addImm(NumBytes).addImm(0);3108 3109 // Now the return values.3110 SmallVector<CCValAssign, 16> RVLocs;3111 CCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context);3112 CCInfo.AnalyzeCallResult(CLI.Ins, CCAssignFnForCall(CC));3113 3114 Register ResultReg = FuncInfo.CreateRegs(CLI.RetTy);3115 for (unsigned i = 0; i != RVLocs.size(); ++i) {3116 CCValAssign &VA = RVLocs[i];3117 MVT CopyVT = VA.getValVT();3118 Register CopyReg = ResultReg + i;3119 3120 // TODO: Handle big-endian results3121 if (CopyVT.isVector() && !Subtarget->isLittleEndian())3122 return false;3123 3124 // Copy result out of their specified physreg.3125 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(TargetOpcode::COPY),3126 CopyReg)3127 .addReg(VA.getLocReg());3128 CLI.InRegs.push_back(VA.getLocReg());3129 }3130 3131 CLI.ResultReg = ResultReg;3132 CLI.NumResultRegs = RVLocs.size();3133 3134 return true;3135}3136 3137bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {3138 CallingConv::ID CC = CLI.CallConv;3139 bool IsTailCall = CLI.IsTailCall;3140 bool IsVarArg = CLI.IsVarArg;3141 const Value *Callee = CLI.Callee;3142 MCSymbol *Symbol = CLI.Symbol;3143 3144 if (!Callee && !Symbol)3145 return false;3146 3147 // Allow SelectionDAG isel to handle calls to functions like setjmp that need3148 // a bti instruction following the call.3149 if (CLI.CB && CLI.CB->hasFnAttr(Attribute::ReturnsTwice) &&3150 !Subtarget->noBTIAtReturnTwice() &&3151 MF->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement())3152 return false;3153 3154 // Allow SelectionDAG isel to handle indirect calls with KCFI checks.3155 if (CLI.CB && CLI.CB->isIndirectCall() &&3156 CLI.CB->getOperandBundle(LLVMContext::OB_kcfi))3157 return false;3158 3159 // Allow SelectionDAG isel to handle tail calls.3160 if (IsTailCall)3161 return false;3162 3163 // FIXME: we could and should support this, but for now correctness at -O0 is3164 // more important.3165 if (Subtarget->isTargetILP32())3166 return false;3167 3168 CodeModel::Model CM = TM.getCodeModel();3169 // Only support the small-addressing and large code models.3170 if (CM != CodeModel::Large && !Subtarget->useSmallAddressing())3171 return false;3172 3173 // FIXME: Add large code model support for ELF.3174 if (CM == CodeModel::Large && !Subtarget->isTargetMachO())3175 return false;3176 3177 // ELF -fno-plt compiled intrinsic calls do not have the nonlazybind3178 // attribute. Check "RtLibUseGOT" instead.3179 if (MF->getFunction().getParent()->getRtLibUseGOT())3180 return false;3181 3182 // Let SDISel handle vararg functions.3183 if (IsVarArg)3184 return false;3185 3186 if (Subtarget->isWindowsArm64EC())3187 return false;3188 3189 for (auto Flag : CLI.OutFlags)3190 if (Flag.isInReg() || Flag.isSRet() || Flag.isNest() || Flag.isByVal() ||3191 Flag.isSwiftSelf() || Flag.isSwiftAsync() || Flag.isSwiftError())3192 return false;3193 3194 // Set up the argument vectors.3195 SmallVector<MVT, 16> OutVTs;3196 SmallVector<Type *, 16> OrigTys;3197 OutVTs.reserve(CLI.OutVals.size());3198 3199 for (auto *Val : CLI.OutVals) {3200 MVT VT;3201 if (!isTypeLegal(Val->getType(), VT) &&3202 !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16))3203 return false;3204 3205 // We don't handle vector parameters yet.3206 if (VT.isVector() || VT.getSizeInBits() > 64)3207 return false;3208 3209 OutVTs.push_back(VT);3210 OrigTys.push_back(Val->getType());3211 }3212 3213 Address Addr;3214 if (Callee && !computeCallAddress(Callee, Addr))3215 return false;3216 3217 // The weak function target may be zero; in that case we must use indirect3218 // addressing via a stub on windows as it may be out of range for a3219 // PC-relative jump.3220 if (Subtarget->isTargetWindows() && Addr.getGlobalValue() &&3221 Addr.getGlobalValue()->hasExternalWeakLinkage())3222 return false;3223 3224 // Handle the arguments now that we've gotten them.3225 unsigned NumBytes;3226 if (!processCallArgs(CLI, OutVTs, OrigTys, NumBytes))3227 return false;3228 3229 const AArch64RegisterInfo *RegInfo = Subtarget->getRegisterInfo();3230 if (RegInfo->isAnyArgRegReserved(*MF))3231 RegInfo->emitReservedArgRegCallError(*MF);3232 3233 // Issue the call.3234 MachineInstrBuilder MIB;3235 if (Subtarget->useSmallAddressing()) {3236 const MCInstrDesc &II =3237 TII.get(Addr.getReg() ? getBLRCallOpcode(*MF) : (unsigned)AArch64::BL);3238 MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II);3239 if (Symbol)3240 MIB.addSym(Symbol, 0);3241 else if (Addr.getGlobalValue())3242 MIB.addGlobalAddress(Addr.getGlobalValue(), 0, 0);3243 else if (Addr.getReg()) {3244 Register Reg = constrainOperandRegClass(II, Addr.getReg(), 0);3245 MIB.addReg(Reg);3246 } else3247 return false;3248 } else {3249 Register CallReg;3250 if (Symbol) {3251 Register ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);3252 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADRP),3253 ADRPReg)3254 .addSym(Symbol, AArch64II::MO_GOT | AArch64II::MO_PAGE);3255 3256 CallReg = createResultReg(&AArch64::GPR64RegClass);3257 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,3258 TII.get(AArch64::LDRXui), CallReg)3259 .addReg(ADRPReg)3260 .addSym(Symbol,3261 AArch64II::MO_GOT | AArch64II::MO_PAGEOFF | AArch64II::MO_NC);3262 } else if (Addr.getGlobalValue())3263 CallReg = materializeGV(Addr.getGlobalValue());3264 else if (Addr.getReg())3265 CallReg = Addr.getReg();3266 3267 if (!CallReg)3268 return false;3269 3270 const MCInstrDesc &II = TII.get(getBLRCallOpcode(*MF));3271 CallReg = constrainOperandRegClass(II, CallReg, 0);3272 MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II).addReg(CallReg);3273 }3274 3275 // Add implicit physical register uses to the call.3276 for (auto Reg : CLI.OutRegs)3277 MIB.addReg(Reg, RegState::Implicit);3278 3279 // Add a register mask with the call-preserved registers.3280 // Proper defs for return values will be added by setPhysRegsDeadExcept().3281 MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC));3282 3283 CLI.Call = MIB;3284 3285 // Finish off the call including any return values.3286 return finishCall(CLI, NumBytes);3287}3288 3289bool AArch64FastISel::isMemCpySmall(uint64_t Len, MaybeAlign Alignment) {3290 if (Alignment)3291 return Len / Alignment->value() <= 4;3292 else3293 return Len < 32;3294}3295 3296bool AArch64FastISel::tryEmitSmallMemCpy(Address Dest, Address Src,3297 uint64_t Len, MaybeAlign Alignment) {3298 // Make sure we don't bloat code by inlining very large memcpy's.3299 if (!isMemCpySmall(Len, Alignment))3300 return false;3301 3302 int64_t UnscaledOffset = 0;3303 Address OrigDest = Dest;3304 Address OrigSrc = Src;3305 3306 while (Len) {3307 MVT VT;3308 if (!Alignment || *Alignment >= 8) {3309 if (Len >= 8)3310 VT = MVT::i64;3311 else if (Len >= 4)3312 VT = MVT::i32;3313 else if (Len >= 2)3314 VT = MVT::i16;3315 else {3316 VT = MVT::i8;3317 }3318 } else {3319 assert(Alignment && "Alignment is set in this branch");3320 // Bound based on alignment.3321 if (Len >= 4 && *Alignment == 4)3322 VT = MVT::i32;3323 else if (Len >= 2 && *Alignment == 2)3324 VT = MVT::i16;3325 else {3326 VT = MVT::i8;3327 }3328 }3329 3330 Register ResultReg = emitLoad(VT, VT, Src);3331 if (!ResultReg)3332 return false;3333 3334 if (!emitStore(VT, ResultReg, Dest))3335 return false;3336 3337 int64_t Size = VT.getSizeInBits() / 8;3338 Len -= Size;3339 UnscaledOffset += Size;3340 3341 // We need to recompute the unscaled offset for each iteration.3342 Dest.setOffset(OrigDest.getOffset() + UnscaledOffset);3343 Src.setOffset(OrigSrc.getOffset() + UnscaledOffset);3344 }3345 3346 return true;3347}3348 3349/// Check if it is possible to fold the condition from the XALU intrinsic3350/// into the user. The condition code will only be updated on success.3351bool AArch64FastISel::foldXALUIntrinsic(AArch64CC::CondCode &CC,3352 const Instruction *I,3353 const Value *Cond) {3354 if (!isa<ExtractValueInst>(Cond))3355 return false;3356 3357 const auto *EV = cast<ExtractValueInst>(Cond);3358 if (!isa<IntrinsicInst>(EV->getAggregateOperand()))3359 return false;3360 3361 const auto *II = cast<IntrinsicInst>(EV->getAggregateOperand());3362 MVT RetVT;3363 const Function *Callee = II->getCalledFunction();3364 Type *RetTy =3365 cast<StructType>(Callee->getReturnType())->getTypeAtIndex(0U);3366 if (!isTypeLegal(RetTy, RetVT))3367 return false;3368 3369 if (RetVT != MVT::i32 && RetVT != MVT::i64)3370 return false;3371 3372 const Value *LHS = II->getArgOperand(0);3373 const Value *RHS = II->getArgOperand(1);3374 3375 // Canonicalize immediate to the RHS.3376 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS) && II->isCommutative())3377 std::swap(LHS, RHS);3378 3379 // Simplify multiplies.3380 Intrinsic::ID IID = II->getIntrinsicID();3381 switch (IID) {3382 default:3383 break;3384 case Intrinsic::smul_with_overflow:3385 if (const auto *C = dyn_cast<ConstantInt>(RHS))3386 if (C->getValue() == 2)3387 IID = Intrinsic::sadd_with_overflow;3388 break;3389 case Intrinsic::umul_with_overflow:3390 if (const auto *C = dyn_cast<ConstantInt>(RHS))3391 if (C->getValue() == 2)3392 IID = Intrinsic::uadd_with_overflow;3393 break;3394 }3395 3396 AArch64CC::CondCode TmpCC;3397 switch (IID) {3398 default:3399 return false;3400 case Intrinsic::sadd_with_overflow:3401 case Intrinsic::ssub_with_overflow:3402 TmpCC = AArch64CC::VS;3403 break;3404 case Intrinsic::uadd_with_overflow:3405 TmpCC = AArch64CC::HS;3406 break;3407 case Intrinsic::usub_with_overflow:3408 TmpCC = AArch64CC::LO;3409 break;3410 case Intrinsic::smul_with_overflow:3411 case Intrinsic::umul_with_overflow:3412 TmpCC = AArch64CC::NE;3413 break;3414 }3415 3416 // Check if both instructions are in the same basic block.3417 if (!isValueAvailable(II))3418 return false;3419 3420 // Make sure nothing is in the way3421 BasicBlock::const_iterator Start(I);3422 BasicBlock::const_iterator End(II);3423 for (auto Itr = std::prev(Start); Itr != End; --Itr) {3424 // We only expect extractvalue instructions between the intrinsic and the3425 // instruction to be selected.3426 if (!isa<ExtractValueInst>(Itr))3427 return false;3428 3429 // Check that the extractvalue operand comes from the intrinsic.3430 const auto *EVI = cast<ExtractValueInst>(Itr);3431 if (EVI->getAggregateOperand() != II)3432 return false;3433 }3434 3435 CC = TmpCC;3436 return true;3437}3438 3439bool AArch64FastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) {3440 // FIXME: Handle more intrinsics.3441 switch (II->getIntrinsicID()) {3442 default: return false;3443 case Intrinsic::frameaddress: {3444 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();3445 MFI.setFrameAddressIsTaken(true);3446 3447 const AArch64RegisterInfo *RegInfo = Subtarget->getRegisterInfo();3448 Register FramePtr = RegInfo->getFrameRegister(*(FuncInfo.MF));3449 Register SrcReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);3450 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,3451 TII.get(TargetOpcode::COPY), SrcReg).addReg(FramePtr);3452 // Recursively load frame address3453 // ldr x0, [fp]3454 // ldr x0, [x0]3455 // ldr x0, [x0]3456 // ...3457 Register DestReg;3458 unsigned Depth = cast<ConstantInt>(II->getOperand(0))->getZExtValue();3459 while (Depth--) {3460 DestReg = fastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,3461 SrcReg, 0);3462 assert(DestReg && "Unexpected LDR instruction emission failure.");3463 SrcReg = DestReg;3464 }3465 3466 updateValueMap(II, SrcReg);3467 return true;3468 }3469 case Intrinsic::sponentry: {3470 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();3471 3472 // SP = FP + Fixed Object + 163473 int FI = MFI.CreateFixedObject(4, 0, false);3474 Register ResultReg = createResultReg(&AArch64::GPR64spRegClass);3475 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,3476 TII.get(AArch64::ADDXri), ResultReg)3477 .addFrameIndex(FI)3478 .addImm(0)3479 .addImm(0);3480 3481 updateValueMap(II, ResultReg);3482 return true;3483 }3484 case Intrinsic::memcpy:3485 case Intrinsic::memmove: {3486 const auto *MTI = cast<MemTransferInst>(II);3487 // Don't handle volatile.3488 if (MTI->isVolatile())3489 return false;3490 3491 // Disable inlining for memmove before calls to ComputeAddress. Otherwise,3492 // we would emit dead code because we don't currently handle memmoves.3493 bool IsMemCpy = (II->getIntrinsicID() == Intrinsic::memcpy);3494 if (isa<ConstantInt>(MTI->getLength()) && IsMemCpy) {3495 // Small memcpy's are common enough that we want to do them without a call3496 // if possible.3497 uint64_t Len = cast<ConstantInt>(MTI->getLength())->getZExtValue();3498 MaybeAlign Alignment;3499 if (MTI->getDestAlign() || MTI->getSourceAlign())3500 Alignment = std::min(MTI->getDestAlign().valueOrOne(),3501 MTI->getSourceAlign().valueOrOne());3502 if (isMemCpySmall(Len, Alignment)) {3503 Address Dest, Src;3504 if (!computeAddress(MTI->getRawDest(), Dest) ||3505 !computeAddress(MTI->getRawSource(), Src))3506 return false;3507 if (tryEmitSmallMemCpy(Dest, Src, Len, Alignment))3508 return true;3509 }3510 }3511 3512 if (!MTI->getLength()->getType()->isIntegerTy(64))3513 return false;3514 3515 if (MTI->getSourceAddressSpace() > 255 || MTI->getDestAddressSpace() > 255)3516 // Fast instruction selection doesn't support the special3517 // address spaces.3518 return false;3519 3520 const char *IntrMemName = isa<MemCpyInst>(II) ? "memcpy" : "memmove";3521 return lowerCallTo(II, IntrMemName, II->arg_size() - 1);3522 }3523 case Intrinsic::memset: {3524 const MemSetInst *MSI = cast<MemSetInst>(II);3525 // Don't handle volatile.3526 if (MSI->isVolatile())3527 return false;3528 3529 if (!MSI->getLength()->getType()->isIntegerTy(64))3530 return false;3531 3532 if (MSI->getDestAddressSpace() > 255)3533 // Fast instruction selection doesn't support the special3534 // address spaces.3535 return false;3536 3537 return lowerCallTo(II, "memset", II->arg_size() - 1);3538 }3539 case Intrinsic::sin:3540 case Intrinsic::cos:3541 case Intrinsic::tan:3542 case Intrinsic::pow: {3543 MVT RetVT;3544 if (!isTypeLegal(II->getType(), RetVT))3545 return false;3546 3547 if (RetVT != MVT::f32 && RetVT != MVT::f64)3548 return false;3549 3550 static const RTLIB::Libcall LibCallTable[4][2] = {3551 {RTLIB::SIN_F32, RTLIB::SIN_F64},3552 {RTLIB::COS_F32, RTLIB::COS_F64},3553 {RTLIB::TAN_F32, RTLIB::TAN_F64},3554 {RTLIB::POW_F32, RTLIB::POW_F64}};3555 RTLIB::Libcall LC;3556 bool Is64Bit = RetVT == MVT::f64;3557 switch (II->getIntrinsicID()) {3558 default:3559 llvm_unreachable("Unexpected intrinsic.");3560 case Intrinsic::sin:3561 LC = LibCallTable[0][Is64Bit];3562 break;3563 case Intrinsic::cos:3564 LC = LibCallTable[1][Is64Bit];3565 break;3566 case Intrinsic::tan:3567 LC = LibCallTable[2][Is64Bit];3568 break;3569 case Intrinsic::pow:3570 LC = LibCallTable[3][Is64Bit];3571 break;3572 }3573 3574 ArgListTy Args;3575 Args.reserve(II->arg_size());3576 3577 // Populate the argument list.3578 for (auto &Arg : II->args())3579 Args.emplace_back(Arg);3580 3581 CallLoweringInfo CLI;3582 MCContext &Ctx = MF->getContext();3583 CLI.setCallee(DL, Ctx, TLI.getLibcallCallingConv(LC), II->getType(),3584 TLI.getLibcallName(LC), std::move(Args));3585 if (!lowerCallTo(CLI))3586 return false;3587 updateValueMap(II, CLI.ResultReg);3588 return true;3589 }3590 case Intrinsic::fabs: {3591 MVT VT;3592 if (!isTypeLegal(II->getType(), VT))3593 return false;3594 3595 unsigned Opc;3596 switch (VT.SimpleTy) {3597 default:3598 return false;3599 case MVT::f32:3600 Opc = AArch64::FABSSr;3601 break;3602 case MVT::f64:3603 Opc = AArch64::FABSDr;3604 break;3605 }3606 Register SrcReg = getRegForValue(II->getOperand(0));3607 if (!SrcReg)3608 return false;3609 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));3610 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)3611 .addReg(SrcReg);3612 updateValueMap(II, ResultReg);3613 return true;3614 }3615 case Intrinsic::trap:3616 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::BRK))3617 .addImm(1);3618 return true;3619 case Intrinsic::debugtrap:3620 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::BRK))3621 .addImm(0xF000);3622 return true;3623 3624 case Intrinsic::sqrt: {3625 Type *RetTy = II->getCalledFunction()->getReturnType();3626 3627 MVT VT;3628 if (!isTypeLegal(RetTy, VT))3629 return false;3630 3631 Register Op0Reg = getRegForValue(II->getOperand(0));3632 if (!Op0Reg)3633 return false;3634 3635 Register ResultReg = fastEmit_r(VT, VT, ISD::FSQRT, Op0Reg);3636 if (!ResultReg)3637 return false;3638 3639 updateValueMap(II, ResultReg);3640 return true;3641 }3642 case Intrinsic::sadd_with_overflow:3643 case Intrinsic::uadd_with_overflow:3644 case Intrinsic::ssub_with_overflow:3645 case Intrinsic::usub_with_overflow:3646 case Intrinsic::smul_with_overflow:3647 case Intrinsic::umul_with_overflow: {3648 // This implements the basic lowering of the xalu with overflow intrinsics.3649 const Function *Callee = II->getCalledFunction();3650 auto *Ty = cast<StructType>(Callee->getReturnType());3651 Type *RetTy = Ty->getTypeAtIndex(0U);3652 3653 MVT VT;3654 if (!isTypeLegal(RetTy, VT))3655 return false;3656 3657 if (VT != MVT::i32 && VT != MVT::i64)3658 return false;3659 3660 const Value *LHS = II->getArgOperand(0);3661 const Value *RHS = II->getArgOperand(1);3662 // Canonicalize immediate to the RHS.3663 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS) && II->isCommutative())3664 std::swap(LHS, RHS);3665 3666 // Simplify multiplies.3667 Intrinsic::ID IID = II->getIntrinsicID();3668 switch (IID) {3669 default:3670 break;3671 case Intrinsic::smul_with_overflow:3672 if (const auto *C = dyn_cast<ConstantInt>(RHS))3673 if (C->getValue() == 2) {3674 IID = Intrinsic::sadd_with_overflow;3675 RHS = LHS;3676 }3677 break;3678 case Intrinsic::umul_with_overflow:3679 if (const auto *C = dyn_cast<ConstantInt>(RHS))3680 if (C->getValue() == 2) {3681 IID = Intrinsic::uadd_with_overflow;3682 RHS = LHS;3683 }3684 break;3685 }3686 3687 Register ResultReg1, ResultReg2, MulReg;3688 AArch64CC::CondCode CC = AArch64CC::Invalid;3689 switch (IID) {3690 default: llvm_unreachable("Unexpected intrinsic!");3691 case Intrinsic::sadd_with_overflow:3692 ResultReg1 = emitAdd(VT, LHS, RHS, /*SetFlags=*/true);3693 CC = AArch64CC::VS;3694 break;3695 case Intrinsic::uadd_with_overflow:3696 ResultReg1 = emitAdd(VT, LHS, RHS, /*SetFlags=*/true);3697 CC = AArch64CC::HS;3698 break;3699 case Intrinsic::ssub_with_overflow:3700 ResultReg1 = emitSub(VT, LHS, RHS, /*SetFlags=*/true);3701 CC = AArch64CC::VS;3702 break;3703 case Intrinsic::usub_with_overflow:3704 ResultReg1 = emitSub(VT, LHS, RHS, /*SetFlags=*/true);3705 CC = AArch64CC::LO;3706 break;3707 case Intrinsic::smul_with_overflow: {3708 CC = AArch64CC::NE;3709 Register LHSReg = getRegForValue(LHS);3710 if (!LHSReg)3711 return false;3712 3713 Register RHSReg = getRegForValue(RHS);3714 if (!RHSReg)3715 return false;3716 3717 if (VT == MVT::i32) {3718 MulReg = emitSMULL_rr(MVT::i64, LHSReg, RHSReg);3719 Register MulSubReg =3720 fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);3721 // cmp xreg, wreg, sxtw3722 emitAddSub_rx(/*UseAdd=*/false, MVT::i64, MulReg, MulSubReg,3723 AArch64_AM::SXTW, /*ShiftImm=*/0, /*SetFlags=*/true,3724 /*WantResult=*/false);3725 MulReg = MulSubReg;3726 } else {3727 assert(VT == MVT::i64 && "Unexpected value type.");3728 // LHSReg and RHSReg cannot be killed by this Mul, since they are3729 // reused in the next instruction.3730 MulReg = emitMul_rr(VT, LHSReg, RHSReg);3731 Register SMULHReg = fastEmit_rr(VT, VT, ISD::MULHS, LHSReg, RHSReg);3732 emitSubs_rs(VT, SMULHReg, MulReg, AArch64_AM::ASR, 63,3733 /*WantResult=*/false);3734 }3735 break;3736 }3737 case Intrinsic::umul_with_overflow: {3738 CC = AArch64CC::NE;3739 Register LHSReg = getRegForValue(LHS);3740 if (!LHSReg)3741 return false;3742 3743 Register RHSReg = getRegForValue(RHS);3744 if (!RHSReg)3745 return false;3746 3747 if (VT == MVT::i32) {3748 MulReg = emitUMULL_rr(MVT::i64, LHSReg, RHSReg);3749 // tst xreg, #0xffffffff000000003750 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,3751 TII.get(AArch64::ANDSXri), AArch64::XZR)3752 .addReg(MulReg)3753 .addImm(AArch64_AM::encodeLogicalImmediate(0xFFFFFFFF00000000, 64));3754 MulReg = fastEmitInst_extractsubreg(VT, MulReg, AArch64::sub_32);3755 } else {3756 assert(VT == MVT::i64 && "Unexpected value type.");3757 // LHSReg and RHSReg cannot be killed by this Mul, since they are3758 // reused in the next instruction.3759 MulReg = emitMul_rr(VT, LHSReg, RHSReg);3760 Register UMULHReg = fastEmit_rr(VT, VT, ISD::MULHU, LHSReg, RHSReg);3761 emitSubs_rr(VT, AArch64::XZR, UMULHReg, /*WantResult=*/false);3762 }3763 break;3764 }3765 }3766 3767 if (MulReg) {3768 ResultReg1 = createResultReg(TLI.getRegClassFor(VT));3769 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,3770 TII.get(TargetOpcode::COPY), ResultReg1).addReg(MulReg);3771 }3772 3773 if (!ResultReg1)3774 return false;3775 3776 ResultReg2 = fastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,3777 AArch64::WZR, AArch64::WZR,3778 getInvertedCondCode(CC));3779 (void)ResultReg2;3780 assert((ResultReg1 + 1) == ResultReg2 &&3781 "Nonconsecutive result registers.");3782 updateValueMap(II, ResultReg1, 2);3783 return true;3784 }3785 case Intrinsic::aarch64_crc32b:3786 case Intrinsic::aarch64_crc32h:3787 case Intrinsic::aarch64_crc32w:3788 case Intrinsic::aarch64_crc32x:3789 case Intrinsic::aarch64_crc32cb:3790 case Intrinsic::aarch64_crc32ch:3791 case Intrinsic::aarch64_crc32cw:3792 case Intrinsic::aarch64_crc32cx: {3793 if (!Subtarget->hasCRC())3794 return false;3795 3796 unsigned Opc;3797 switch (II->getIntrinsicID()) {3798 default:3799 llvm_unreachable("Unexpected intrinsic!");3800 case Intrinsic::aarch64_crc32b:3801 Opc = AArch64::CRC32Brr;3802 break;3803 case Intrinsic::aarch64_crc32h:3804 Opc = AArch64::CRC32Hrr;3805 break;3806 case Intrinsic::aarch64_crc32w:3807 Opc = AArch64::CRC32Wrr;3808 break;3809 case Intrinsic::aarch64_crc32x:3810 Opc = AArch64::CRC32Xrr;3811 break;3812 case Intrinsic::aarch64_crc32cb:3813 Opc = AArch64::CRC32CBrr;3814 break;3815 case Intrinsic::aarch64_crc32ch:3816 Opc = AArch64::CRC32CHrr;3817 break;3818 case Intrinsic::aarch64_crc32cw:3819 Opc = AArch64::CRC32CWrr;3820 break;3821 case Intrinsic::aarch64_crc32cx:3822 Opc = AArch64::CRC32CXrr;3823 break;3824 }3825 3826 Register LHSReg = getRegForValue(II->getArgOperand(0));3827 Register RHSReg = getRegForValue(II->getArgOperand(1));3828 if (!LHSReg || !RHSReg)3829 return false;3830 3831 Register ResultReg =3832 fastEmitInst_rr(Opc, &AArch64::GPR32RegClass, LHSReg, RHSReg);3833 updateValueMap(II, ResultReg);3834 return true;3835 }3836 }3837 return false;3838}3839 3840bool AArch64FastISel::selectRet(const Instruction *I) {3841 const ReturnInst *Ret = cast<ReturnInst>(I);3842 const Function &F = *I->getParent()->getParent();3843 3844 if (!FuncInfo.CanLowerReturn)3845 return false;3846 3847 if (F.isVarArg())3848 return false;3849 3850 if (TLI.supportSwiftError() &&3851 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))3852 return false;3853 3854 if (TLI.supportSplitCSR(FuncInfo.MF))3855 return false;3856 3857 // Build a list of return value registers.3858 SmallVector<Register, 4> RetRegs;3859 3860 if (Ret->getNumOperands() > 0) {3861 CallingConv::ID CC = F.getCallingConv();3862 SmallVector<ISD::OutputArg, 4> Outs;3863 GetReturnInfo(CC, F.getReturnType(), F.getAttributes(), Outs, TLI, DL);3864 3865 // Analyze operands of the call, assigning locations to each operand.3866 SmallVector<CCValAssign, 16> ValLocs;3867 CCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs, I->getContext());3868 CCInfo.AnalyzeReturn(Outs, RetCC_AArch64_AAPCS);3869 3870 // Only handle a single return value for now.3871 if (ValLocs.size() != 1)3872 return false;3873 3874 CCValAssign &VA = ValLocs[0];3875 const Value *RV = Ret->getOperand(0);3876 3877 // Don't bother handling odd stuff for now.3878 if ((VA.getLocInfo() != CCValAssign::Full) &&3879 (VA.getLocInfo() != CCValAssign::BCvt))3880 return false;3881 3882 // Only handle register returns for now.3883 if (!VA.isRegLoc())3884 return false;3885 3886 Register Reg = getRegForValue(RV);3887 if (!Reg)3888 return false;3889 3890 Register SrcReg = Reg + VA.getValNo();3891 Register DestReg = VA.getLocReg();3892 // Avoid a cross-class copy. This is very unlikely.3893 if (!MRI.getRegClass(SrcReg)->contains(DestReg))3894 return false;3895 3896 EVT RVEVT = TLI.getValueType(DL, RV->getType());3897 if (!RVEVT.isSimple())3898 return false;3899 3900 // Vectors (of > 1 lane) in big endian need tricky handling.3901 if (RVEVT.isVector() && RVEVT.getVectorElementCount().isVector() &&3902 !Subtarget->isLittleEndian())3903 return false;3904 3905 MVT RVVT = RVEVT.getSimpleVT();3906 if (RVVT == MVT::f128)3907 return false;3908 3909 MVT DestVT = VA.getValVT();3910 // Special handling for extended integers.3911 if (RVVT != DestVT) {3912 if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)3913 return false;3914 3915 if (!Outs[0].Flags.isZExt() && !Outs[0].Flags.isSExt())3916 return false;3917 3918 bool IsZExt = Outs[0].Flags.isZExt();3919 SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);3920 if (!SrcReg)3921 return false;3922 }3923 3924 // "Callee" (i.e. value producer) zero extends pointers at function3925 // boundary.3926 if (Subtarget->isTargetILP32() && RV->getType()->isPointerTy())3927 SrcReg = emitAnd_ri(MVT::i64, SrcReg, 0xffffffff);3928 3929 // Make the copy.3930 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,3931 TII.get(TargetOpcode::COPY), DestReg).addReg(SrcReg);3932 3933 // Add register to return instruction.3934 RetRegs.push_back(VA.getLocReg());3935 }3936 3937 MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,3938 TII.get(AArch64::RET_ReallyLR));3939 for (Register RetReg : RetRegs)3940 MIB.addReg(RetReg, RegState::Implicit);3941 return true;3942}3943 3944bool AArch64FastISel::selectTrunc(const Instruction *I) {3945 Type *DestTy = I->getType();3946 Value *Op = I->getOperand(0);3947 Type *SrcTy = Op->getType();3948 3949 EVT SrcEVT = TLI.getValueType(DL, SrcTy, true);3950 EVT DestEVT = TLI.getValueType(DL, DestTy, true);3951 if (!SrcEVT.isSimple())3952 return false;3953 if (!DestEVT.isSimple())3954 return false;3955 3956 MVT SrcVT = SrcEVT.getSimpleVT();3957 MVT DestVT = DestEVT.getSimpleVT();3958 3959 if (SrcVT != MVT::i64 && SrcVT != MVT::i32 && SrcVT != MVT::i16 &&3960 SrcVT != MVT::i8)3961 return false;3962 if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8 &&3963 DestVT != MVT::i1)3964 return false;3965 3966 Register SrcReg = getRegForValue(Op);3967 if (!SrcReg)3968 return false;3969 3970 // If we're truncating from i64 to a smaller non-legal type then generate an3971 // AND. Otherwise, we know the high bits are undefined and a truncate only3972 // generate a COPY. We cannot mark the source register also as result3973 // register, because this can incorrectly transfer the kill flag onto the3974 // source register.3975 Register ResultReg;3976 if (SrcVT == MVT::i64) {3977 uint64_t Mask = 0;3978 switch (DestVT.SimpleTy) {3979 default:3980 // Trunc i64 to i32 is handled by the target-independent fast-isel.3981 return false;3982 case MVT::i1:3983 Mask = 0x1;3984 break;3985 case MVT::i8:3986 Mask = 0xff;3987 break;3988 case MVT::i16:3989 Mask = 0xffff;3990 break;3991 }3992 // Issue an extract_subreg to get the lower 32-bits.3993 Register Reg32 = fastEmitInst_extractsubreg(MVT::i32, SrcReg,3994 AArch64::sub_32);3995 // Create the AND instruction which performs the actual truncation.3996 ResultReg = emitAnd_ri(MVT::i32, Reg32, Mask);3997 assert(ResultReg && "Unexpected AND instruction emission failure.");3998 } else {3999 ResultReg = createResultReg(&AArch64::GPR32RegClass);4000 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,4001 TII.get(TargetOpcode::COPY), ResultReg)4002 .addReg(SrcReg);4003 }4004 4005 updateValueMap(I, ResultReg);4006 return true;4007}4008 4009Register AArch64FastISel::emiti1Ext(Register SrcReg, MVT DestVT, bool IsZExt) {4010 assert((DestVT == MVT::i8 || DestVT == MVT::i16 || DestVT == MVT::i32 ||4011 DestVT == MVT::i64) &&4012 "Unexpected value type.");4013 // Handle i8 and i16 as i32.4014 if (DestVT == MVT::i8 || DestVT == MVT::i16)4015 DestVT = MVT::i32;4016 4017 if (IsZExt) {4018 Register ResultReg = emitAnd_ri(MVT::i32, SrcReg, 1);4019 assert(ResultReg && "Unexpected AND instruction emission failure.");4020 if (DestVT == MVT::i64) {4021 // We're ZExt i1 to i64. The ANDWri Wd, Ws, #1 implicitly clears the4022 // upper 32 bits. Emit a SUBREG_TO_REG to extend from Wd to Xd.4023 Register Reg64 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);4024 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,4025 TII.get(AArch64::SUBREG_TO_REG), Reg64)4026 .addImm(0)4027 .addReg(ResultReg)4028 .addImm(AArch64::sub_32);4029 ResultReg = Reg64;4030 }4031 return ResultReg;4032 } else {4033 if (DestVT == MVT::i64) {4034 // FIXME: We're SExt i1 to i64.4035 return Register();4036 }4037 return fastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,4038 0, 0);4039 }4040}4041 4042Register AArch64FastISel::emitMul_rr(MVT RetVT, Register Op0, Register Op1) {4043 unsigned Opc;4044 Register ZReg;4045 switch (RetVT.SimpleTy) {4046 default:4047 return Register();4048 case MVT::i8:4049 case MVT::i16:4050 case MVT::i32:4051 RetVT = MVT::i32;4052 Opc = AArch64::MADDWrrr; ZReg = AArch64::WZR; break;4053 case MVT::i64:4054 Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR; break;4055 }4056 4057 const TargetRegisterClass *RC =4058 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;4059 return fastEmitInst_rrr(Opc, RC, Op0, Op1, ZReg);4060}4061 4062Register AArch64FastISel::emitSMULL_rr(MVT RetVT, Register Op0, Register Op1) {4063 if (RetVT != MVT::i64)4064 return Register();4065 4066 return fastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,4067 Op0, Op1, AArch64::XZR);4068}4069 4070Register AArch64FastISel::emitUMULL_rr(MVT RetVT, Register Op0, Register Op1) {4071 if (RetVT != MVT::i64)4072 return Register();4073 4074 return fastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,4075 Op0, Op1, AArch64::XZR);4076}4077 4078Register AArch64FastISel::emitLSL_rr(MVT RetVT, Register Op0Reg,4079 Register Op1Reg) {4080 unsigned Opc = 0;4081 bool NeedTrunc = false;4082 uint64_t Mask = 0;4083 switch (RetVT.SimpleTy) {4084 default:4085 return Register();4086 case MVT::i8: Opc = AArch64::LSLVWr; NeedTrunc = true; Mask = 0xff; break;4087 case MVT::i16: Opc = AArch64::LSLVWr; NeedTrunc = true; Mask = 0xffff; break;4088 case MVT::i32: Opc = AArch64::LSLVWr; break;4089 case MVT::i64: Opc = AArch64::LSLVXr; break;4090 }4091 4092 const TargetRegisterClass *RC =4093 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;4094 if (NeedTrunc)4095 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);4096 4097 Register ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op1Reg);4098 if (NeedTrunc)4099 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);4100 return ResultReg;4101}4102 4103Register AArch64FastISel::emitLSL_ri(MVT RetVT, MVT SrcVT, Register Op0,4104 uint64_t Shift, bool IsZExt) {4105 assert(RetVT.SimpleTy >= SrcVT.SimpleTy &&4106 "Unexpected source/return type pair.");4107 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||4108 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&4109 "Unexpected source value type.");4110 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||4111 RetVT == MVT::i64) && "Unexpected return value type.");4112 4113 bool Is64Bit = (RetVT == MVT::i64);4114 unsigned RegSize = Is64Bit ? 64 : 32;4115 unsigned DstBits = RetVT.getSizeInBits();4116 unsigned SrcBits = SrcVT.getSizeInBits();4117 const TargetRegisterClass *RC =4118 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;4119 4120 // Just emit a copy for "zero" shifts.4121 if (Shift == 0) {4122 if (RetVT == SrcVT) {4123 Register ResultReg = createResultReg(RC);4124 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,4125 TII.get(TargetOpcode::COPY), ResultReg)4126 .addReg(Op0);4127 return ResultReg;4128 } else4129 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);4130 }4131 4132 // Don't deal with undefined shifts.4133 if (Shift >= DstBits)4134 return Register();4135 4136 // For immediate shifts we can fold the zero-/sign-extension into the shift.4137 // {S|U}BFM Wd, Wn, #r, #s4138 // Wd<32+s-r,32-r> = Wn<s:0> when r > s4139 4140 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i164141 // %2 = shl i16 %1, 44142 // Wd<32+7-28,32-28> = Wn<7:0> <- clamp s to 74143 // 0b1111_1111_1111_1111__1111_1010_1010_0000 sext4144 // 0b0000_0000_0000_0000__0000_0101_0101_0000 sext | zext4145 // 0b0000_0000_0000_0000__0000_1010_1010_0000 zext4146 4147 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i164148 // %2 = shl i16 %1, 84149 // Wd<32+7-24,32-24> = Wn<7:0>4150 // 0b1111_1111_1111_1111__1010_1010_0000_0000 sext4151 // 0b0000_0000_0000_0000__0101_0101_0000_0000 sext | zext4152 // 0b0000_0000_0000_0000__1010_1010_0000_0000 zext4153 4154 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i164155 // %2 = shl i16 %1, 124156 // Wd<32+3-20,32-20> = Wn<3:0>4157 // 0b1111_1111_1111_1111__1010_0000_0000_0000 sext4158 // 0b0000_0000_0000_0000__0101_0000_0000_0000 sext | zext4159 // 0b0000_0000_0000_0000__1010_0000_0000_0000 zext4160 4161 unsigned ImmR = RegSize - Shift;4162 // Limit the width to the length of the source type.4163 unsigned ImmS = std::min<unsigned>(SrcBits - 1, DstBits - 1 - Shift);4164 static const unsigned OpcTable[2][2] = {4165 {AArch64::SBFMWri, AArch64::SBFMXri},4166 {AArch64::UBFMWri, AArch64::UBFMXri}4167 };4168 unsigned Opc = OpcTable[IsZExt][Is64Bit];4169 if (SrcVT.SimpleTy <= MVT::i32 && RetVT == MVT::i64) {4170 Register TmpReg = MRI.createVirtualRegister(RC);4171 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,4172 TII.get(AArch64::SUBREG_TO_REG), TmpReg)4173 .addImm(0)4174 .addReg(Op0)4175 .addImm(AArch64::sub_32);4176 Op0 = TmpReg;4177 }4178 return fastEmitInst_rii(Opc, RC, Op0, ImmR, ImmS);4179}4180 4181Register AArch64FastISel::emitLSR_rr(MVT RetVT, Register Op0Reg,4182 Register Op1Reg) {4183 unsigned Opc = 0;4184 bool NeedTrunc = false;4185 uint64_t Mask = 0;4186 switch (RetVT.SimpleTy) {4187 default:4188 return Register();4189 case MVT::i8: Opc = AArch64::LSRVWr; NeedTrunc = true; Mask = 0xff; break;4190 case MVT::i16: Opc = AArch64::LSRVWr; NeedTrunc = true; Mask = 0xffff; break;4191 case MVT::i32: Opc = AArch64::LSRVWr; break;4192 case MVT::i64: Opc = AArch64::LSRVXr; break;4193 }4194 4195 const TargetRegisterClass *RC =4196 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;4197 if (NeedTrunc) {4198 Op0Reg = emitAnd_ri(MVT::i32, Op0Reg, Mask);4199 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);4200 }4201 Register ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op1Reg);4202 if (NeedTrunc)4203 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);4204 return ResultReg;4205}4206 4207Register AArch64FastISel::emitLSR_ri(MVT RetVT, MVT SrcVT, Register Op0,4208 uint64_t Shift, bool IsZExt) {4209 assert(RetVT.SimpleTy >= SrcVT.SimpleTy &&4210 "Unexpected source/return type pair.");4211 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||4212 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&4213 "Unexpected source value type.");4214 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||4215 RetVT == MVT::i64) && "Unexpected return value type.");4216 4217 bool Is64Bit = (RetVT == MVT::i64);4218 unsigned RegSize = Is64Bit ? 64 : 32;4219 unsigned DstBits = RetVT.getSizeInBits();4220 unsigned SrcBits = SrcVT.getSizeInBits();4221 const TargetRegisterClass *RC =4222 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;4223 4224 // Just emit a copy for "zero" shifts.4225 if (Shift == 0) {4226 if (RetVT == SrcVT) {4227 Register ResultReg = createResultReg(RC);4228 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,4229 TII.get(TargetOpcode::COPY), ResultReg)4230 .addReg(Op0);4231 return ResultReg;4232 } else4233 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);4234 }4235 4236 // Don't deal with undefined shifts.4237 if (Shift >= DstBits)4238 return Register();4239 4240 // For immediate shifts we can fold the zero-/sign-extension into the shift.4241 // {S|U}BFM Wd, Wn, #r, #s4242 // Wd<s-r:0> = Wn<s:r> when r <= s4243 4244 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i164245 // %2 = lshr i16 %1, 44246 // Wd<7-4:0> = Wn<7:4>4247 // 0b0000_0000_0000_0000__0000_1111_1111_1010 sext4248 // 0b0000_0000_0000_0000__0000_0000_0000_0101 sext | zext4249 // 0b0000_0000_0000_0000__0000_0000_0000_1010 zext4250 4251 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i164252 // %2 = lshr i16 %1, 84253 // Wd<7-7,0> = Wn<7:7>4254 // 0b0000_0000_0000_0000__0000_0000_1111_1111 sext4255 // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext4256 // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext4257 4258 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i164259 // %2 = lshr i16 %1, 124260 // Wd<7-7,0> = Wn<7:7> <- clamp r to 74261 // 0b0000_0000_0000_0000__0000_0000_0000_1111 sext4262 // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext4263 // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext4264 4265 if (Shift >= SrcBits && IsZExt)4266 return materializeInt(ConstantInt::get(*Context, APInt(RegSize, 0)), RetVT);4267 4268 // It is not possible to fold a sign-extend into the LShr instruction. In this4269 // case emit a sign-extend.4270 if (!IsZExt) {4271 Op0 = emitIntExt(SrcVT, Op0, RetVT, IsZExt);4272 if (!Op0)4273 return Register();4274 SrcVT = RetVT;4275 SrcBits = SrcVT.getSizeInBits();4276 IsZExt = true;4277 }4278 4279 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);4280 unsigned ImmS = SrcBits - 1;4281 static const unsigned OpcTable[2][2] = {4282 {AArch64::SBFMWri, AArch64::SBFMXri},4283 {AArch64::UBFMWri, AArch64::UBFMXri}4284 };4285 unsigned Opc = OpcTable[IsZExt][Is64Bit];4286 if (SrcVT.SimpleTy <= MVT::i32 && RetVT == MVT::i64) {4287 Register TmpReg = MRI.createVirtualRegister(RC);4288 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,4289 TII.get(AArch64::SUBREG_TO_REG), TmpReg)4290 .addImm(0)4291 .addReg(Op0)4292 .addImm(AArch64::sub_32);4293 Op0 = TmpReg;4294 }4295 return fastEmitInst_rii(Opc, RC, Op0, ImmR, ImmS);4296}4297 4298Register AArch64FastISel::emitASR_rr(MVT RetVT, Register Op0Reg,4299 Register Op1Reg) {4300 unsigned Opc = 0;4301 bool NeedTrunc = false;4302 uint64_t Mask = 0;4303 switch (RetVT.SimpleTy) {4304 default:4305 return Register();4306 case MVT::i8: Opc = AArch64::ASRVWr; NeedTrunc = true; Mask = 0xff; break;4307 case MVT::i16: Opc = AArch64::ASRVWr; NeedTrunc = true; Mask = 0xffff; break;4308 case MVT::i32: Opc = AArch64::ASRVWr; break;4309 case MVT::i64: Opc = AArch64::ASRVXr; break;4310 }4311 4312 const TargetRegisterClass *RC =4313 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;4314 if (NeedTrunc) {4315 Op0Reg = emitIntExt(RetVT, Op0Reg, MVT::i32, /*isZExt=*/false);4316 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Mask);4317 }4318 Register ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op1Reg);4319 if (NeedTrunc)4320 ResultReg = emitAnd_ri(MVT::i32, ResultReg, Mask);4321 return ResultReg;4322}4323 4324Register AArch64FastISel::emitASR_ri(MVT RetVT, MVT SrcVT, Register Op0,4325 uint64_t Shift, bool IsZExt) {4326 assert(RetVT.SimpleTy >= SrcVT.SimpleTy &&4327 "Unexpected source/return type pair.");4328 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||4329 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&4330 "Unexpected source value type.");4331 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||4332 RetVT == MVT::i64) && "Unexpected return value type.");4333 4334 bool Is64Bit = (RetVT == MVT::i64);4335 unsigned RegSize = Is64Bit ? 64 : 32;4336 unsigned DstBits = RetVT.getSizeInBits();4337 unsigned SrcBits = SrcVT.getSizeInBits();4338 const TargetRegisterClass *RC =4339 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;4340 4341 // Just emit a copy for "zero" shifts.4342 if (Shift == 0) {4343 if (RetVT == SrcVT) {4344 Register ResultReg = createResultReg(RC);4345 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,4346 TII.get(TargetOpcode::COPY), ResultReg)4347 .addReg(Op0);4348 return ResultReg;4349 } else4350 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);4351 }4352 4353 // Don't deal with undefined shifts.4354 if (Shift >= DstBits)4355 return Register();4356 4357 // For immediate shifts we can fold the zero-/sign-extension into the shift.4358 // {S|U}BFM Wd, Wn, #r, #s4359 // Wd<s-r:0> = Wn<s:r> when r <= s4360 4361 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i164362 // %2 = ashr i16 %1, 44363 // Wd<7-4:0> = Wn<7:4>4364 // 0b1111_1111_1111_1111__1111_1111_1111_1010 sext4365 // 0b0000_0000_0000_0000__0000_0000_0000_0101 sext | zext4366 // 0b0000_0000_0000_0000__0000_0000_0000_1010 zext4367 4368 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i164369 // %2 = ashr i16 %1, 84370 // Wd<7-7,0> = Wn<7:7>4371 // 0b1111_1111_1111_1111__1111_1111_1111_1111 sext4372 // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext4373 // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext4374 4375 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i164376 // %2 = ashr i16 %1, 124377 // Wd<7-7,0> = Wn<7:7> <- clamp r to 74378 // 0b1111_1111_1111_1111__1111_1111_1111_1111 sext4379 // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext4380 // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext4381 4382 if (Shift >= SrcBits && IsZExt)4383 return materializeInt(ConstantInt::get(*Context, APInt(RegSize, 0)), RetVT);4384 4385 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);4386 unsigned ImmS = SrcBits - 1;4387 static const unsigned OpcTable[2][2] = {4388 {AArch64::SBFMWri, AArch64::SBFMXri},4389 {AArch64::UBFMWri, AArch64::UBFMXri}4390 };4391 unsigned Opc = OpcTable[IsZExt][Is64Bit];4392 if (SrcVT.SimpleTy <= MVT::i32 && RetVT == MVT::i64) {4393 Register TmpReg = MRI.createVirtualRegister(RC);4394 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,4395 TII.get(AArch64::SUBREG_TO_REG), TmpReg)4396 .addImm(0)4397 .addReg(Op0)4398 .addImm(AArch64::sub_32);4399 Op0 = TmpReg;4400 }4401 return fastEmitInst_rii(Opc, RC, Op0, ImmR, ImmS);4402}4403 4404Register AArch64FastISel::emitIntExt(MVT SrcVT, Register SrcReg, MVT DestVT,4405 bool IsZExt) {4406 assert(DestVT != MVT::i1 && "ZeroExt/SignExt an i1?");4407 4408 // FastISel does not have plumbing to deal with extensions where the SrcVT or4409 // DestVT are odd things, so test to make sure that they are both types we can4410 // handle (i1/i8/i16/i32 for SrcVT and i8/i16/i32/i64 for DestVT), otherwise4411 // bail out to SelectionDAG.4412 if (((DestVT != MVT::i8) && (DestVT != MVT::i16) &&4413 (DestVT != MVT::i32) && (DestVT != MVT::i64)) ||4414 ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) &&4415 (SrcVT != MVT::i16) && (SrcVT != MVT::i32)))4416 return Register();4417 4418 unsigned Opc;4419 unsigned Imm = 0;4420 4421 switch (SrcVT.SimpleTy) {4422 default:4423 return Register();4424 case MVT::i1:4425 return emiti1Ext(SrcReg, DestVT, IsZExt);4426 case MVT::i8:4427 if (DestVT == MVT::i64)4428 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;4429 else4430 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;4431 Imm = 7;4432 break;4433 case MVT::i16:4434 if (DestVT == MVT::i64)4435 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;4436 else4437 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;4438 Imm = 15;4439 break;4440 case MVT::i32:4441 assert(DestVT == MVT::i64 && "IntExt i32 to i32?!?");4442 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;4443 Imm = 31;4444 break;4445 }4446 4447 // Handle i8 and i16 as i32.4448 if (DestVT == MVT::i8 || DestVT == MVT::i16)4449 DestVT = MVT::i32;4450 else if (DestVT == MVT::i64) {4451 Register Src64 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);4452 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,4453 TII.get(AArch64::SUBREG_TO_REG), Src64)4454 .addImm(0)4455 .addReg(SrcReg)4456 .addImm(AArch64::sub_32);4457 SrcReg = Src64;4458 }4459 4460 const TargetRegisterClass *RC =4461 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;4462 return fastEmitInst_rii(Opc, RC, SrcReg, 0, Imm);4463}4464 4465static bool isZExtLoad(const MachineInstr *LI) {4466 switch (LI->getOpcode()) {4467 default:4468 return false;4469 case AArch64::LDURBBi:4470 case AArch64::LDURHHi:4471 case AArch64::LDURWi:4472 case AArch64::LDRBBui:4473 case AArch64::LDRHHui:4474 case AArch64::LDRWui:4475 case AArch64::LDRBBroX:4476 case AArch64::LDRHHroX:4477 case AArch64::LDRWroX:4478 case AArch64::LDRBBroW:4479 case AArch64::LDRHHroW:4480 case AArch64::LDRWroW:4481 return true;4482 }4483}4484 4485static bool isSExtLoad(const MachineInstr *LI) {4486 switch (LI->getOpcode()) {4487 default:4488 return false;4489 case AArch64::LDURSBWi:4490 case AArch64::LDURSHWi:4491 case AArch64::LDURSBXi:4492 case AArch64::LDURSHXi:4493 case AArch64::LDURSWi:4494 case AArch64::LDRSBWui:4495 case AArch64::LDRSHWui:4496 case AArch64::LDRSBXui:4497 case AArch64::LDRSHXui:4498 case AArch64::LDRSWui:4499 case AArch64::LDRSBWroX:4500 case AArch64::LDRSHWroX:4501 case AArch64::LDRSBXroX:4502 case AArch64::LDRSHXroX:4503 case AArch64::LDRSWroX:4504 case AArch64::LDRSBWroW:4505 case AArch64::LDRSHWroW:4506 case AArch64::LDRSBXroW:4507 case AArch64::LDRSHXroW:4508 case AArch64::LDRSWroW:4509 return true;4510 }4511}4512 4513bool AArch64FastISel::optimizeIntExtLoad(const Instruction *I, MVT RetVT,4514 MVT SrcVT) {4515 const auto *LI = dyn_cast<LoadInst>(I->getOperand(0));4516 if (!LI || !LI->hasOneUse())4517 return false;4518 4519 // Check if the load instruction has already been selected.4520 Register Reg = lookUpRegForValue(LI);4521 if (!Reg)4522 return false;4523 4524 MachineInstr *MI = MRI.getUniqueVRegDef(Reg);4525 if (!MI)4526 return false;4527 4528 // Check if the correct load instruction has been emitted - SelectionDAG might4529 // have emitted a zero-extending load, but we need a sign-extending load.4530 bool IsZExt = isa<ZExtInst>(I);4531 const auto *LoadMI = MI;4532 if (LoadMI->getOpcode() == TargetOpcode::COPY &&4533 LoadMI->getOperand(1).getSubReg() == AArch64::sub_32) {4534 Register LoadReg = MI->getOperand(1).getReg();4535 LoadMI = MRI.getUniqueVRegDef(LoadReg);4536 assert(LoadMI && "Expected valid instruction");4537 }4538 if (!(IsZExt && isZExtLoad(LoadMI)) && !(!IsZExt && isSExtLoad(LoadMI)))4539 return false;4540 4541 // Nothing to be done.4542 if (RetVT != MVT::i64 || SrcVT > MVT::i32) {4543 updateValueMap(I, Reg);4544 return true;4545 }4546 4547 if (IsZExt) {4548 Register Reg64 = createResultReg(&AArch64::GPR64RegClass);4549 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,4550 TII.get(AArch64::SUBREG_TO_REG), Reg64)4551 .addImm(0)4552 .addReg(Reg, getKillRegState(true))4553 .addImm(AArch64::sub_32);4554 Reg = Reg64;4555 } else {4556 assert((MI->getOpcode() == TargetOpcode::COPY &&4557 MI->getOperand(1).getSubReg() == AArch64::sub_32) &&4558 "Expected copy instruction");4559 Reg = MI->getOperand(1).getReg();4560 MachineBasicBlock::iterator I(MI);4561 removeDeadCode(I, std::next(I));4562 }4563 updateValueMap(I, Reg);4564 return true;4565}4566 4567bool AArch64FastISel::selectIntExt(const Instruction *I) {4568 assert((isa<ZExtInst>(I) || isa<SExtInst>(I)) &&4569 "Unexpected integer extend instruction.");4570 MVT RetVT;4571 MVT SrcVT;4572 if (!isTypeSupported(I->getType(), RetVT))4573 return false;4574 4575 if (!isTypeSupported(I->getOperand(0)->getType(), SrcVT))4576 return false;4577 4578 // Try to optimize already sign-/zero-extended values from load instructions.4579 if (optimizeIntExtLoad(I, RetVT, SrcVT))4580 return true;4581 4582 Register SrcReg = getRegForValue(I->getOperand(0));4583 if (!SrcReg)4584 return false;4585 4586 // Try to optimize already sign-/zero-extended values from function arguments.4587 bool IsZExt = isa<ZExtInst>(I);4588 if (const auto *Arg = dyn_cast<Argument>(I->getOperand(0))) {4589 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr())) {4590 if (RetVT == MVT::i64 && SrcVT != MVT::i64) {4591 Register ResultReg = createResultReg(&AArch64::GPR64RegClass);4592 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,4593 TII.get(AArch64::SUBREG_TO_REG), ResultReg)4594 .addImm(0)4595 .addReg(SrcReg)4596 .addImm(AArch64::sub_32);4597 SrcReg = ResultReg;4598 }4599 4600 updateValueMap(I, SrcReg);4601 return true;4602 }4603 }4604 4605 Register ResultReg = emitIntExt(SrcVT, SrcReg, RetVT, IsZExt);4606 if (!ResultReg)4607 return false;4608 4609 updateValueMap(I, ResultReg);4610 return true;4611}4612 4613bool AArch64FastISel::selectRem(const Instruction *I, unsigned ISDOpcode) {4614 EVT DestEVT = TLI.getValueType(DL, I->getType(), true);4615 if (!DestEVT.isSimple())4616 return false;4617 4618 MVT DestVT = DestEVT.getSimpleVT();4619 if (DestVT != MVT::i64 && DestVT != MVT::i32)4620 return false;4621 4622 unsigned DivOpc;4623 bool Is64bit = (DestVT == MVT::i64);4624 switch (ISDOpcode) {4625 default:4626 return false;4627 case ISD::SREM:4628 DivOpc = Is64bit ? AArch64::SDIVXr : AArch64::SDIVWr;4629 break;4630 case ISD::UREM:4631 DivOpc = Is64bit ? AArch64::UDIVXr : AArch64::UDIVWr;4632 break;4633 }4634 unsigned MSubOpc = Is64bit ? AArch64::MSUBXrrr : AArch64::MSUBWrrr;4635 Register Src0Reg = getRegForValue(I->getOperand(0));4636 if (!Src0Reg)4637 return false;4638 4639 Register Src1Reg = getRegForValue(I->getOperand(1));4640 if (!Src1Reg)4641 return false;4642 4643 const TargetRegisterClass *RC =4644 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;4645 Register QuotReg = fastEmitInst_rr(DivOpc, RC, Src0Reg, Src1Reg);4646 assert(QuotReg && "Unexpected DIV instruction emission failure.");4647 // The remainder is computed as numerator - (quotient * denominator) using the4648 // MSUB instruction.4649 Register ResultReg = fastEmitInst_rrr(MSubOpc, RC, QuotReg, Src1Reg, Src0Reg);4650 updateValueMap(I, ResultReg);4651 return true;4652}4653 4654bool AArch64FastISel::selectMul(const Instruction *I) {4655 MVT VT;4656 if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true))4657 return false;4658 4659 if (VT.isVector())4660 return selectBinaryOp(I, ISD::MUL);4661 4662 const Value *Src0 = I->getOperand(0);4663 const Value *Src1 = I->getOperand(1);4664 if (const auto *C = dyn_cast<ConstantInt>(Src0))4665 if (C->getValue().isPowerOf2())4666 std::swap(Src0, Src1);4667 4668 // Try to simplify to a shift instruction.4669 if (const auto *C = dyn_cast<ConstantInt>(Src1))4670 if (C->getValue().isPowerOf2()) {4671 uint64_t ShiftVal = C->getValue().logBase2();4672 MVT SrcVT = VT;4673 bool IsZExt = true;4674 if (const auto *ZExt = dyn_cast<ZExtInst>(Src0)) {4675 if (!isIntExtFree(ZExt)) {4676 MVT VT;4677 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), VT)) {4678 SrcVT = VT;4679 IsZExt = true;4680 Src0 = ZExt->getOperand(0);4681 }4682 }4683 } else if (const auto *SExt = dyn_cast<SExtInst>(Src0)) {4684 if (!isIntExtFree(SExt)) {4685 MVT VT;4686 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), VT)) {4687 SrcVT = VT;4688 IsZExt = false;4689 Src0 = SExt->getOperand(0);4690 }4691 }4692 }4693 4694 Register Src0Reg = getRegForValue(Src0);4695 if (!Src0Reg)4696 return false;4697 4698 Register ResultReg = emitLSL_ri(VT, SrcVT, Src0Reg, ShiftVal, IsZExt);4699 4700 if (ResultReg) {4701 updateValueMap(I, ResultReg);4702 return true;4703 }4704 }4705 4706 Register Src0Reg = getRegForValue(I->getOperand(0));4707 if (!Src0Reg)4708 return false;4709 4710 Register Src1Reg = getRegForValue(I->getOperand(1));4711 if (!Src1Reg)4712 return false;4713 4714 Register ResultReg = emitMul_rr(VT, Src0Reg, Src1Reg);4715 4716 if (!ResultReg)4717 return false;4718 4719 updateValueMap(I, ResultReg);4720 return true;4721}4722 4723bool AArch64FastISel::selectShift(const Instruction *I) {4724 MVT RetVT;4725 if (!isTypeSupported(I->getType(), RetVT, /*IsVectorAllowed=*/true))4726 return false;4727 4728 if (RetVT.isVector())4729 return selectOperator(I, I->getOpcode());4730 4731 if (const auto *C = dyn_cast<ConstantInt>(I->getOperand(1))) {4732 Register ResultReg;4733 uint64_t ShiftVal = C->getZExtValue();4734 MVT SrcVT = RetVT;4735 bool IsZExt = I->getOpcode() != Instruction::AShr;4736 const Value *Op0 = I->getOperand(0);4737 if (const auto *ZExt = dyn_cast<ZExtInst>(Op0)) {4738 if (!isIntExtFree(ZExt)) {4739 MVT TmpVT;4740 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), TmpVT)) {4741 SrcVT = TmpVT;4742 IsZExt = true;4743 Op0 = ZExt->getOperand(0);4744 }4745 }4746 } else if (const auto *SExt = dyn_cast<SExtInst>(Op0)) {4747 if (!isIntExtFree(SExt)) {4748 MVT TmpVT;4749 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), TmpVT)) {4750 SrcVT = TmpVT;4751 IsZExt = false;4752 Op0 = SExt->getOperand(0);4753 }4754 }4755 }4756 4757 Register Op0Reg = getRegForValue(Op0);4758 if (!Op0Reg)4759 return false;4760 4761 switch (I->getOpcode()) {4762 default: llvm_unreachable("Unexpected instruction.");4763 case Instruction::Shl:4764 ResultReg = emitLSL_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);4765 break;4766 case Instruction::AShr:4767 ResultReg = emitASR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);4768 break;4769 case Instruction::LShr:4770 ResultReg = emitLSR_ri(RetVT, SrcVT, Op0Reg, ShiftVal, IsZExt);4771 break;4772 }4773 if (!ResultReg)4774 return false;4775 4776 updateValueMap(I, ResultReg);4777 return true;4778 }4779 4780 Register Op0Reg = getRegForValue(I->getOperand(0));4781 if (!Op0Reg)4782 return false;4783 4784 Register Op1Reg = getRegForValue(I->getOperand(1));4785 if (!Op1Reg)4786 return false;4787 4788 Register ResultReg;4789 switch (I->getOpcode()) {4790 default: llvm_unreachable("Unexpected instruction.");4791 case Instruction::Shl:4792 ResultReg = emitLSL_rr(RetVT, Op0Reg, Op1Reg);4793 break;4794 case Instruction::AShr:4795 ResultReg = emitASR_rr(RetVT, Op0Reg, Op1Reg);4796 break;4797 case Instruction::LShr:4798 ResultReg = emitLSR_rr(RetVT, Op0Reg, Op1Reg);4799 break;4800 }4801 4802 if (!ResultReg)4803 return false;4804 4805 updateValueMap(I, ResultReg);4806 return true;4807}4808 4809bool AArch64FastISel::selectBitCast(const Instruction *I) {4810 MVT RetVT, SrcVT;4811 4812 if (!isTypeLegal(I->getOperand(0)->getType(), SrcVT))4813 return false;4814 if (!isTypeLegal(I->getType(), RetVT))4815 return false;4816 4817 unsigned Opc;4818 if (RetVT == MVT::f32 && SrcVT == MVT::i32)4819 Opc = AArch64::FMOVWSr;4820 else if (RetVT == MVT::f64 && SrcVT == MVT::i64)4821 Opc = AArch64::FMOVXDr;4822 else if (RetVT == MVT::i32 && SrcVT == MVT::f32)4823 Opc = AArch64::FMOVSWr;4824 else if (RetVT == MVT::i64 && SrcVT == MVT::f64)4825 Opc = AArch64::FMOVDXr;4826 else4827 return false;4828 4829 const TargetRegisterClass *RC = nullptr;4830 switch (RetVT.SimpleTy) {4831 default: llvm_unreachable("Unexpected value type.");4832 case MVT::i32: RC = &AArch64::GPR32RegClass; break;4833 case MVT::i64: RC = &AArch64::GPR64RegClass; break;4834 case MVT::f32: RC = &AArch64::FPR32RegClass; break;4835 case MVT::f64: RC = &AArch64::FPR64RegClass; break;4836 }4837 Register Op0Reg = getRegForValue(I->getOperand(0));4838 if (!Op0Reg)4839 return false;4840 4841 Register ResultReg = fastEmitInst_r(Opc, RC, Op0Reg);4842 if (!ResultReg)4843 return false;4844 4845 updateValueMap(I, ResultReg);4846 return true;4847}4848 4849bool AArch64FastISel::selectFRem(const Instruction *I) {4850 MVT RetVT;4851 if (!isTypeLegal(I->getType(), RetVT))4852 return false;4853 4854 RTLIB::Libcall LC;4855 switch (RetVT.SimpleTy) {4856 default:4857 return false;4858 case MVT::f32:4859 LC = RTLIB::REM_F32;4860 break;4861 case MVT::f64:4862 LC = RTLIB::REM_F64;4863 break;4864 }4865 4866 ArgListTy Args;4867 Args.reserve(I->getNumOperands());4868 4869 // Populate the argument list.4870 for (auto &Arg : I->operands())4871 Args.emplace_back(Arg);4872 4873 CallLoweringInfo CLI;4874 MCContext &Ctx = MF->getContext();4875 CLI.setCallee(DL, Ctx, TLI.getLibcallCallingConv(LC), I->getType(),4876 TLI.getLibcallName(LC), std::move(Args));4877 if (!lowerCallTo(CLI))4878 return false;4879 updateValueMap(I, CLI.ResultReg);4880 return true;4881}4882 4883bool AArch64FastISel::selectSDiv(const Instruction *I) {4884 MVT VT;4885 if (!isTypeLegal(I->getType(), VT))4886 return false;4887 4888 if (!isa<ConstantInt>(I->getOperand(1)))4889 return selectBinaryOp(I, ISD::SDIV);4890 4891 const APInt &C = cast<ConstantInt>(I->getOperand(1))->getValue();4892 if ((VT != MVT::i32 && VT != MVT::i64) || !C ||4893 !(C.isPowerOf2() || C.isNegatedPowerOf2()))4894 return selectBinaryOp(I, ISD::SDIV);4895 4896 unsigned Lg2 = C.countr_zero();4897 Register Src0Reg = getRegForValue(I->getOperand(0));4898 if (!Src0Reg)4899 return false;4900 4901 if (cast<BinaryOperator>(I)->isExact()) {4902 Register ResultReg = emitASR_ri(VT, VT, Src0Reg, Lg2);4903 if (!ResultReg)4904 return false;4905 updateValueMap(I, ResultReg);4906 return true;4907 }4908 4909 int64_t Pow2MinusOne = (1ULL << Lg2) - 1;4910 Register AddReg = emitAdd_ri_(VT, Src0Reg, Pow2MinusOne);4911 if (!AddReg)4912 return false;4913 4914 // (Src0 < 0) ? Pow2 - 1 : 0;4915 if (!emitICmp_ri(VT, Src0Reg, 0))4916 return false;4917 4918 unsigned SelectOpc;4919 const TargetRegisterClass *RC;4920 if (VT == MVT::i64) {4921 SelectOpc = AArch64::CSELXr;4922 RC = &AArch64::GPR64RegClass;4923 } else {4924 SelectOpc = AArch64::CSELWr;4925 RC = &AArch64::GPR32RegClass;4926 }4927 Register SelectReg = fastEmitInst_rri(SelectOpc, RC, AddReg, Src0Reg,4928 AArch64CC::LT);4929 if (!SelectReg)4930 return false;4931 4932 // Divide by Pow2 --> ashr. If we're dividing by a negative value we must also4933 // negate the result.4934 Register ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;4935 Register ResultReg;4936 if (C.isNegative())4937 ResultReg = emitAddSub_rs(/*UseAdd=*/false, VT, ZeroReg, SelectReg,4938 AArch64_AM::ASR, Lg2);4939 else4940 ResultReg = emitASR_ri(VT, VT, SelectReg, Lg2);4941 4942 if (!ResultReg)4943 return false;4944 4945 updateValueMap(I, ResultReg);4946 return true;4947}4948 4949/// This is mostly a copy of the existing FastISel getRegForGEPIndex code. We4950/// have to duplicate it for AArch64, because otherwise we would fail during the4951/// sign-extend emission.4952Register AArch64FastISel::getRegForGEPIndex(const Value *Idx) {4953 Register IdxN = getRegForValue(Idx);4954 if (!IdxN)4955 // Unhandled operand. Halt "fast" selection and bail.4956 return Register();4957 4958 // If the index is smaller or larger than intptr_t, truncate or extend it.4959 MVT PtrVT = TLI.getPointerTy(DL);4960 EVT IdxVT = EVT::getEVT(Idx->getType(), /*HandleUnknown=*/false);4961 if (IdxVT.bitsLT(PtrVT)) {4962 IdxN = emitIntExt(IdxVT.getSimpleVT(), IdxN, PtrVT, /*isZExt=*/false);4963 } else if (IdxVT.bitsGT(PtrVT))4964 llvm_unreachable("AArch64 FastISel doesn't support types larger than i64");4965 return IdxN;4966}4967 4968/// This is mostly a copy of the existing FastISel GEP code, but we have to4969/// duplicate it for AArch64, because otherwise we would bail out even for4970/// simple cases. This is because the standard fastEmit functions don't cover4971/// MUL at all and ADD is lowered very inefficientily.4972bool AArch64FastISel::selectGetElementPtr(const Instruction *I) {4973 if (Subtarget->isTargetILP32())4974 return false;4975 4976 Register N = getRegForValue(I->getOperand(0));4977 if (!N)4978 return false;4979 4980 // Keep a running tab of the total offset to coalesce multiple N = N + Offset4981 // into a single N = N + TotalOffset.4982 uint64_t TotalOffs = 0;4983 MVT VT = TLI.getPointerTy(DL);4984 for (gep_type_iterator GTI = gep_type_begin(I), E = gep_type_end(I);4985 GTI != E; ++GTI) {4986 const Value *Idx = GTI.getOperand();4987 if (auto *StTy = GTI.getStructTypeOrNull()) {4988 unsigned Field = cast<ConstantInt>(Idx)->getZExtValue();4989 // N = N + Offset4990 if (Field)4991 TotalOffs += DL.getStructLayout(StTy)->getElementOffset(Field);4992 } else {4993 // If this is a constant subscript, handle it quickly.4994 if (const auto *CI = dyn_cast<ConstantInt>(Idx)) {4995 if (CI->isZero())4996 continue;4997 // N = N + Offset4998 TotalOffs += GTI.getSequentialElementStride(DL) *4999 cast<ConstantInt>(CI)->getSExtValue();5000 continue;5001 }5002 if (TotalOffs) {5003 N = emitAdd_ri_(VT, N, TotalOffs);5004 if (!N)5005 return false;5006 TotalOffs = 0;5007 }5008 5009 // N = N + Idx * ElementSize;5010 uint64_t ElementSize = GTI.getSequentialElementStride(DL);5011 Register IdxN = getRegForGEPIndex(Idx);5012 if (!IdxN)5013 return false;5014 5015 if (ElementSize != 1) {5016 Register C = fastEmit_i(VT, VT, ISD::Constant, ElementSize);5017 if (!C)5018 return false;5019 IdxN = emitMul_rr(VT, IdxN, C);5020 if (!IdxN)5021 return false;5022 }5023 N = fastEmit_rr(VT, VT, ISD::ADD, N, IdxN);5024 if (!N)5025 return false;5026 }5027 }5028 if (TotalOffs) {5029 N = emitAdd_ri_(VT, N, TotalOffs);5030 if (!N)5031 return false;5032 }5033 updateValueMap(I, N);5034 return true;5035}5036 5037bool AArch64FastISel::selectAtomicCmpXchg(const AtomicCmpXchgInst *I) {5038 assert(TM.getOptLevel() == CodeGenOptLevel::None &&5039 "cmpxchg survived AtomicExpand at optlevel > -O0");5040 5041 auto *RetPairTy = cast<StructType>(I->getType());5042 Type *RetTy = RetPairTy->getTypeAtIndex(0U);5043 assert(RetPairTy->getTypeAtIndex(1U)->isIntegerTy(1) &&5044 "cmpxchg has a non-i1 status result");5045 5046 MVT VT;5047 if (!isTypeLegal(RetTy, VT))5048 return false;5049 5050 const TargetRegisterClass *ResRC;5051 unsigned Opc, CmpOpc;5052 // This only supports i32/i64, because i8/i16 aren't legal, and the generic5053 // extractvalue selection doesn't support that.5054 if (VT == MVT::i32) {5055 Opc = AArch64::CMP_SWAP_32;5056 CmpOpc = AArch64::SUBSWrs;5057 ResRC = &AArch64::GPR32RegClass;5058 } else if (VT == MVT::i64) {5059 Opc = AArch64::CMP_SWAP_64;5060 CmpOpc = AArch64::SUBSXrs;5061 ResRC = &AArch64::GPR64RegClass;5062 } else {5063 return false;5064 }5065 5066 const MCInstrDesc &II = TII.get(Opc);5067 5068 Register AddrReg = getRegForValue(I->getPointerOperand());5069 Register DesiredReg = getRegForValue(I->getCompareOperand());5070 Register NewReg = getRegForValue(I->getNewValOperand());5071 5072 if (!AddrReg || !DesiredReg || !NewReg)5073 return false;5074 5075 AddrReg = constrainOperandRegClass(II, AddrReg, II.getNumDefs());5076 DesiredReg = constrainOperandRegClass(II, DesiredReg, II.getNumDefs() + 1);5077 NewReg = constrainOperandRegClass(II, NewReg, II.getNumDefs() + 2);5078 5079 const Register ResultReg1 = createResultReg(ResRC);5080 const Register ResultReg2 = createResultReg(&AArch64::GPR32RegClass);5081 const Register ScratchReg = createResultReg(&AArch64::GPR32RegClass);5082 5083 // FIXME: MachineMemOperand doesn't support cmpxchg yet.5084 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)5085 .addDef(ResultReg1)5086 .addDef(ScratchReg)5087 .addUse(AddrReg)5088 .addUse(DesiredReg)5089 .addUse(NewReg);5090 5091 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(CmpOpc))5092 .addDef(VT == MVT::i32 ? AArch64::WZR : AArch64::XZR)5093 .addUse(ResultReg1)5094 .addUse(DesiredReg)5095 .addImm(0);5096 5097 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::CSINCWr))5098 .addDef(ResultReg2)5099 .addUse(AArch64::WZR)5100 .addUse(AArch64::WZR)5101 .addImm(AArch64CC::NE);5102 5103 assert((ResultReg1 + 1) == ResultReg2 && "Nonconsecutive result registers.");5104 updateValueMap(I, ResultReg1, 2);5105 return true;5106}5107 5108bool AArch64FastISel::fastSelectInstruction(const Instruction *I) {5109 if (TLI.fallBackToDAGISel(*I))5110 return false;5111 switch (I->getOpcode()) {5112 default:5113 break;5114 case Instruction::Add:5115 case Instruction::Sub:5116 return selectAddSub(I);5117 case Instruction::Mul:5118 return selectMul(I);5119 case Instruction::SDiv:5120 return selectSDiv(I);5121 case Instruction::SRem:5122 if (!selectBinaryOp(I, ISD::SREM))5123 return selectRem(I, ISD::SREM);5124 return true;5125 case Instruction::URem:5126 if (!selectBinaryOp(I, ISD::UREM))5127 return selectRem(I, ISD::UREM);5128 return true;5129 case Instruction::Shl:5130 case Instruction::LShr:5131 case Instruction::AShr:5132 return selectShift(I);5133 case Instruction::And:5134 case Instruction::Or:5135 case Instruction::Xor:5136 return selectLogicalOp(I);5137 case Instruction::Br:5138 return selectBranch(I);5139 case Instruction::IndirectBr:5140 return selectIndirectBr(I);5141 case Instruction::BitCast:5142 if (!FastISel::selectBitCast(I))5143 return selectBitCast(I);5144 return true;5145 case Instruction::FPToSI:5146 if (!selectCast(I, ISD::FP_TO_SINT))5147 return selectFPToInt(I, /*Signed=*/true);5148 return true;5149 case Instruction::FPToUI:5150 return selectFPToInt(I, /*Signed=*/false);5151 case Instruction::ZExt:5152 case Instruction::SExt:5153 return selectIntExt(I);5154 case Instruction::Trunc:5155 if (!selectCast(I, ISD::TRUNCATE))5156 return selectTrunc(I);5157 return true;5158 case Instruction::FPExt:5159 return selectFPExt(I);5160 case Instruction::FPTrunc:5161 return selectFPTrunc(I);5162 case Instruction::SIToFP:5163 if (!selectCast(I, ISD::SINT_TO_FP))5164 return selectIntToFP(I, /*Signed=*/true);5165 return true;5166 case Instruction::UIToFP:5167 return selectIntToFP(I, /*Signed=*/false);5168 case Instruction::Load:5169 return selectLoad(I);5170 case Instruction::Store:5171 return selectStore(I);5172 case Instruction::FCmp:5173 case Instruction::ICmp:5174 return selectCmp(I);5175 case Instruction::Select:5176 return selectSelect(I);5177 case Instruction::Ret:5178 return selectRet(I);5179 case Instruction::FRem:5180 return selectFRem(I);5181 case Instruction::GetElementPtr:5182 return selectGetElementPtr(I);5183 case Instruction::AtomicCmpXchg:5184 return selectAtomicCmpXchg(cast<AtomicCmpXchgInst>(I));5185 }5186 5187 // fall-back to target-independent instruction selection.5188 return selectOperator(I, I->getOpcode());5189}5190 5191FastISel *AArch64::createFastISel(FunctionLoweringInfo &FuncInfo,5192 const TargetLibraryInfo *LibInfo) {5193 5194 SMEAttrs CallerAttrs =5195 FuncInfo.MF->getInfo<AArch64FunctionInfo>()->getSMEFnAttrs();5196 if (CallerAttrs.hasZAState() || CallerAttrs.hasZT0State() ||5197 CallerAttrs.hasStreamingInterfaceOrBody() ||5198 CallerAttrs.hasStreamingCompatibleInterface() ||5199 CallerAttrs.hasAgnosticZAInterface())5200 return nullptr;5201 return new AArch64FastISel(FuncInfo, LibInfo);5202}5203