627 lines · c
1//===-- HexagonISelLowering.h - Hexagon DAG Lowering Interface --*- C++ -*-===//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 interfaces that Hexagon uses to lower LLVM code into a10// selection DAG.11//12//===----------------------------------------------------------------------===//13 14#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONISELLOWERING_H15#define LLVM_LIB_TARGET_HEXAGON_HEXAGONISELLOWERING_H16 17#include "Hexagon.h"18#include "MCTargetDesc/HexagonMCTargetDesc.h"19#include "llvm/ADT/StringRef.h"20#include "llvm/CodeGen/ISDOpcodes.h"21#include "llvm/CodeGen/SelectionDAGNodes.h"22#include "llvm/CodeGen/TargetLowering.h"23#include "llvm/CodeGen/ValueTypes.h"24#include "llvm/CodeGenTypes/MachineValueType.h"25#include "llvm/IR/CallingConv.h"26#include "llvm/IR/InlineAsm.h"27#include <cstdint>28#include <utility>29 30namespace llvm {31 32namespace HexagonISD {33 34// clang-format off35enum NodeType : unsigned {36 OP_BEGIN = ISD::BUILTIN_OP_END,37 38 CONST32 = OP_BEGIN,39 CONST32_GP, // For marking data present in GP.40 ADDC, // Add with carry: (X, Y, Cin) -> (X+Y, Cout).41 SUBC, // Sub with carry: (X, Y, Cin) -> (X+~Y+Cin, Cout).42 ALLOCA,43 44 AT_GOT, // Index in GOT.45 AT_PCREL, // Offset relative to PC.46 47 CALL, // Function call.48 CALLnr, // Function call that does not return.49 CALLR,50 51 RET_GLUE, // Return with a glue operand.52 BARRIER, // Memory barrier.53 JT, // Jump table.54 CP, // Constant pool.55 56 COMBINE,57 VASL, // Vector shifts by a scalar value58 VASR,59 VLSR,60 MFSHL, // Funnel shifts with the shift amount guaranteed to be61 MFSHR, // within the range of the bit width of the element.62 63 SSAT, // Signed saturate.64 USAT, // Unsigned saturate.65 SMUL_LOHI, // Same as ISD::SMUL_LOHI, but opaque to the combiner.66 UMUL_LOHI, // Same as ISD::UMUL_LOHI, but opaque to the combiner.67 // We want to legalize MULH[SU] to [SU]MUL_LOHI, but the68 // combiner will keep rewriting it back to MULH[SU].69 USMUL_LOHI, // Like SMUL_LOHI, but unsigned*signed.70 71 TSTBIT,72 INSERT,73 EXTRACTU,74 VEXTRACTW,75 VINSERTW0,76 VROR,77 TC_RETURN,78 EH_RETURN,79 DCFETCH,80 READCYCLE,81 READTIMER,82 THREAD_POINTER,83 PTRUE,84 PFALSE,85 D2P, // Convert 8-byte value to 8-bit predicate register. [*]86 P2D, // Convert 8-bit predicate register to 8-byte value. [*]87 V2Q, // Convert HVX vector to a vector predicate reg. [*]88 Q2V, // Convert vector predicate to an HVX vector. [*]89 // [*] The equivalence is defined as "Q <=> (V != 0)",90 // where the != operation compares bytes.91 // Note: V != 0 is implemented as V >u 0.92 QCAT,93 QTRUE,94 QFALSE,95 96 TL_EXTEND, // Wrappers for ISD::*_EXTEND and ISD::TRUNCATE to prevent DAG97 TL_TRUNCATE, // from auto-folding operations, e.g.98 // (i32 ext (i16 ext i8)) would be folded to (i32 ext i8).99 // To simplify the type legalization, we want to keep these100 // single steps separate during type legalization.101 // TL_[EXTEND|TRUNCATE] Inp, i128 _, i32 Opc102 // * Inp is the original input to extend/truncate,103 // * _ is a dummy operand with an illegal type (can be undef),104 // * Opc is the original opcode.105 // The legalization process (in Hexagon lowering code) will106 // first deal with the "real" types (i.e. Inp and the result),107 // and once all of them are processed, the wrapper node will108 // be replaced with the original ISD node. The dummy illegal109 // operand is there to make sure that the legalization hooks110 // are called again after everything else is legal, giving111 // us the opportunity to undo the wrapping.112 113 TYPECAST, // No-op that's used to convert between different legal114 // types in a register.115 VALIGN, // Align two vectors (in Op0, Op1) to one that would have116 // been loaded from address in Op2.117 VALIGNADDR, // Align vector address: Op0 & -Op1, except when it is118 // an address in a vector load, then it's a no-op.119 ISEL, // Marker for nodes that were created during ISel, and120 // which need explicit selection (would have been left121 // unselected otherwise).122 OP_END123};124 125} // end namespace HexagonISD126// clang-format on127 128class HexagonSubtarget;129 130class HexagonTargetLowering : public TargetLowering {131 int VarArgsFrameOffset; // Frame offset to start of varargs area.132 const HexagonTargetMachine &HTM;133 const HexagonSubtarget &Subtarget;134 135public:136 explicit HexagonTargetLowering(const TargetMachine &TM,137 const HexagonSubtarget &ST);138 139 /// IsEligibleForTailCallOptimization - Check whether the call is eligible140 /// for tail call optimization. Targets which want to do tail call141 /// optimization should implement this function.142 bool IsEligibleForTailCallOptimization(SDValue Callee,143 CallingConv::ID CalleeCC, bool isVarArg, bool isCalleeStructRet,144 bool isCallerStructRet, const SmallVectorImpl<ISD::OutputArg> &Outs,145 const SmallVectorImpl<SDValue> &OutVals,146 const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG& DAG) const;147 148 bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I,149 MachineFunction &MF,150 unsigned Intrinsic) const override;151 152 bool isTruncateFree(Type *Ty1, Type *Ty2) const override;153 bool isTruncateFree(EVT VT1, EVT VT2) const override;154 155 bool isCheapToSpeculateCttz(Type *) const override { return true; }156 bool isCheapToSpeculateCtlz(Type *) const override { return true; }157 bool isCtlzFast() const override { return true; }158 159 bool hasBitTest(SDValue X, SDValue Y) const override;160 161 bool allowTruncateForTailCall(Type *Ty1, Type *Ty2) const override;162 163 bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override;164 165 bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override;166 167 /// Return true if an FMA operation is faster than a pair of mul and add168 /// instructions. fmuladd intrinsics will be expanded to FMAs when this169 /// method returns true (and FMAs are legal), otherwise fmuladd is170 /// expanded to mul + add.171 bool isFMAFasterThanFMulAndFAdd(const MachineFunction &,172 EVT) const override;173 174 // Should we expand the build vector with shuffles?175 bool shouldExpandBuildVectorWithShuffles(EVT VT,176 unsigned DefinedValues) const override;177 bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT,178 unsigned Index) const override;179 180 bool isTargetCanonicalConstantNode(SDValue Op) const override;181 182 bool isShuffleMaskLegal(ArrayRef<int> Mask, EVT VT) const override;183 LegalizeTypeAction getPreferredVectorAction(MVT VT) const override;184 LegalizeAction getCustomOperationAction(SDNode &Op) const override;185 186 SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;187 void LowerOperationWrapper(SDNode *N, SmallVectorImpl<SDValue> &Results,188 SelectionDAG &DAG) const override;189 void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,190 SelectionDAG &DAG) const override;191 192 const char *getTargetNodeName(unsigned Opcode) const override;193 std::pair<MVT, unsigned>194 handleMaskRegisterForCallingConv(const HexagonSubtarget &Subtarget,195 EVT VT) const;196 197 SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const;198 SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const;199 SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;200 SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG) const;201 SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;202 SDValue LowerINSERT_SUBVECTOR(SDValue Op, SelectionDAG &DAG) const;203 SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const;204 SDValue LowerVECTOR_SHIFT(SDValue Op, SelectionDAG &DAG) const;205 SDValue LowerROTL(SDValue Op, SelectionDAG &DAG) const;206 SDValue LowerBITCAST(SDValue Op, SelectionDAG &DAG) const;207 SDValue LowerANY_EXTEND(SDValue Op, SelectionDAG &DAG) const;208 SDValue LowerSIGN_EXTEND(SDValue Op, SelectionDAG &DAG) const;209 SDValue LowerZERO_EXTEND(SDValue Op, SelectionDAG &DAG) const;210 SDValue LowerLoad(SDValue Op, SelectionDAG &DAG) const;211 SDValue LowerStore(SDValue Op, SelectionDAG &DAG) const;212 SDValue LowerUnalignedLoad(SDValue Op, SelectionDAG &DAG) const;213 SDValue LowerUAddSubO(SDValue Op, SelectionDAG &DAG) const;214 SDValue LowerUAddSubOCarry(SDValue Op, SelectionDAG &DAG) const;215 216 SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;217 SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const;218 SDValue LowerFDIV(SDValue Op, SelectionDAG &DAG) const;219 SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG) const;220 SDValue LowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const;221 SDValue LowerREADSTEADYCOUNTER(SDValue Op, SelectionDAG &DAG) const;222 SDValue LowerEH_LABEL(SDValue Op, SelectionDAG &DAG) const;223 SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;224 SDValue225 LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,226 const SmallVectorImpl<ISD::InputArg> &Ins,227 const SDLoc &dl, SelectionDAG &DAG,228 SmallVectorImpl<SDValue> &InVals) const override;229 SDValue LowerGLOBALADDRESS(SDValue Op, SelectionDAG &DAG) const;230 SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;231 SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;232 SDValue LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA,233 SelectionDAG &DAG) const;234 SDValue LowerToTLSInitialExecModel(GlobalAddressSDNode *GA,235 SelectionDAG &DAG) const;236 SDValue LowerToTLSLocalExecModel(GlobalAddressSDNode *GA,237 SelectionDAG &DAG) const;238 SDValue GetDynamicTLSAddr(SelectionDAG &DAG, SDValue Chain,239 GlobalAddressSDNode *GA, SDValue InGlue, EVT PtrVT,240 unsigned ReturnReg, unsigned char OperandGlues) const;241 SDValue LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG) const;242 243 SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,244 SmallVectorImpl<SDValue> &InVals) const override;245 SDValue LowerCallResult(SDValue Chain, SDValue InGlue,246 CallingConv::ID CallConv, bool isVarArg,247 const SmallVectorImpl<ISD::InputArg> &Ins,248 const SDLoc &dl, SelectionDAG &DAG,249 SmallVectorImpl<SDValue> &InVals,250 const SmallVectorImpl<SDValue> &OutVals,251 SDValue Callee) const;252 253 SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;254 SDValue LowerVSELECT(SDValue Op, SelectionDAG &DAG) const;255 SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;256 SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const;257 SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;258 259 bool CanLowerReturn(CallingConv::ID CallConv,260 MachineFunction &MF, bool isVarArg,261 const SmallVectorImpl<ISD::OutputArg> &Outs,262 LLVMContext &Context, const Type *RetTy) const override;263 264 SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,265 const SmallVectorImpl<ISD::OutputArg> &Outs,266 const SmallVectorImpl<SDValue> &OutVals,267 const SDLoc &dl, SelectionDAG &DAG) const override;268 269 SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;270 271 bool mayBeEmittedAsTailCall(const CallInst *CI) const override;272 273 Register getRegisterByName(const char* RegName, LLT VT,274 const MachineFunction &MF) const override;275 276 unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context,277 CallingConv::ID CC, EVT VT,278 EVT &IntermediateVT,279 unsigned &NumIntermediates,280 MVT &RegisterVT) const override;281 282 MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC,283 EVT VT) const override;284 /// If a physical register, this returns the register that receives the285 /// exception address on entry to an EH pad.286 Register287 getExceptionPointerRegister(const Constant *PersonalityFn) const override {288 return Hexagon::R0;289 }290 291 /// If a physical register, this returns the register that receives the292 /// exception typeid on entry to a landing pad.293 Register294 getExceptionSelectorRegister(const Constant *PersonalityFn) const override {295 return Hexagon::R1;296 }297 298 SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;299 SDValue LowerVACOPY(SDValue Op, SelectionDAG &DAG) const;300 SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;301 SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;302 303 EVT getSetCCResultType(const DataLayout &, LLVMContext &C,304 EVT VT) const override {305 if (!VT.isVector())306 return MVT::i1;307 else308 return EVT::getVectorVT(C, MVT::i1, VT.getVectorNumElements());309 }310 311 bool getPostIndexedAddressParts(SDNode *N, SDNode *Op,312 SDValue &Base, SDValue &Offset,313 ISD::MemIndexedMode &AM,314 SelectionDAG &DAG) const override;315 316 ConstraintType getConstraintType(StringRef Constraint) const override;317 318 std::pair<unsigned, const TargetRegisterClass *>319 getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,320 StringRef Constraint, MVT VT) const override;321 322 // Intrinsics323 SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;324 SDValue LowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;325 /// isLegalAddressingMode - Return true if the addressing mode represented326 /// by AM is legal for this target, for a load/store of the specified type.327 /// The type may be VoidTy, in which case only return true if the addressing328 /// mode is legal for a load/store of any legal type.329 /// TODO: Handle pre/postinc as well.330 bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM,331 Type *Ty, unsigned AS,332 Instruction *I = nullptr) const override;333 /// Return true if folding a constant offset with the given GlobalAddress334 /// is legal. It is frequently not legal in PIC relocation models.335 bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;336 337 bool isFPImmLegal(const APFloat &Imm, EVT VT,338 bool ForCodeSize) const override;339 340 /// isLegalICmpImmediate - Return true if the specified immediate is legal341 /// icmp immediate, that is the target has icmp instructions which can342 /// compare a register against the immediate without having to materialize343 /// the immediate into a register.344 bool isLegalICmpImmediate(int64_t Imm) const override;345 346 EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op,347 const AttributeList &FuncAttributes) const override;348 349 bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT,350 unsigned AddrSpace, Align Alignment,351 MachineMemOperand::Flags Flags,352 unsigned *Fast) const override;353 354 bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace,355 Align Alignment,356 MachineMemOperand::Flags Flags,357 unsigned *Fast) const override;358 359 /// Returns relocation base for the given PIC jumptable.360 SDValue getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG)361 const override;362 363 /// Returns true if it is beneficial to convert a load of a constant364 /// to just the constant itself.365 bool shouldConvertConstantLoadToIntImm(const APInt &Imm,366 Type *Ty) const override;367 368 bool shouldReduceLoadWidth(SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT,369 std::optional<unsigned> ByteOffset) const override;370 371 void AdjustInstrPostInstrSelection(MachineInstr &MI,372 SDNode *Node) const override;373 374 // Handling of atomic RMW instructions.375 Value *emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr,376 AtomicOrdering Ord) const override;377 Value *emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr,378 AtomicOrdering Ord) const override;379 AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override;380 AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override;381 AtomicExpansionKind382 shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const override;383 384 AtomicExpansionKind385 shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override {386 return AtomicExpansionKind::LLSC;387 }388 bool softPromoteHalfType() const override { return true; }389 390private:391 void initializeHVXLowering();392 unsigned getPreferredHvxVectorAction(MVT VecTy) const;393 unsigned getCustomHvxOperationAction(SDNode &Op) const;394 395 bool validateConstPtrAlignment(SDValue Ptr, Align NeedAlign, const SDLoc &dl,396 SelectionDAG &DAG) const;397 SDValue replaceMemWithUndef(SDValue Op, SelectionDAG &DAG) const;398 399 std::pair<SDValue,int> getBaseAndOffset(SDValue Addr) const;400 401 bool getBuildVectorConstInts(ArrayRef<SDValue> Values, MVT VecTy,402 SelectionDAG &DAG,403 MutableArrayRef<ConstantInt*> Consts) const;404 SDValue buildVector32(ArrayRef<SDValue> Elem, const SDLoc &dl, MVT VecTy,405 SelectionDAG &DAG) const;406 SDValue buildVector64(ArrayRef<SDValue> Elem, const SDLoc &dl, MVT VecTy,407 SelectionDAG &DAG) const;408 SDValue extractVector(SDValue VecV, SDValue IdxV, const SDLoc &dl,409 MVT ValTy, MVT ResTy, SelectionDAG &DAG) const;410 SDValue extractVectorPred(SDValue VecV, SDValue IdxV, const SDLoc &dl,411 MVT ValTy, MVT ResTy, SelectionDAG &DAG) const;412 SDValue insertVector(SDValue VecV, SDValue ValV, SDValue IdxV,413 const SDLoc &dl, MVT ValTy, SelectionDAG &DAG) const;414 SDValue insertVectorPred(SDValue VecV, SDValue ValV, SDValue IdxV,415 const SDLoc &dl, MVT ValTy, SelectionDAG &DAG) const;416 SDValue expandPredicate(SDValue Vec32, const SDLoc &dl,417 SelectionDAG &DAG) const;418 SDValue contractPredicate(SDValue Vec64, const SDLoc &dl,419 SelectionDAG &DAG) const;420 SDValue getSplatValue(SDValue Op, SelectionDAG &DAG) const;421 SDValue getVectorShiftByInt(SDValue Op, SelectionDAG &DAG) const;422 SDValue appendUndef(SDValue Val, MVT ResTy, SelectionDAG &DAG) const;423 SDValue getCombine(SDValue Hi, SDValue Lo, const SDLoc &dl, MVT ResTy,424 SelectionDAG &DAG) const;425 426 bool isUndef(SDValue Op) const {427 if (Op.isMachineOpcode())428 return Op.getMachineOpcode() == TargetOpcode::IMPLICIT_DEF;429 return Op.getOpcode() == ISD::UNDEF;430 }431 SDValue getInstr(unsigned MachineOpc, const SDLoc &dl, MVT Ty,432 ArrayRef<SDValue> Ops, SelectionDAG &DAG) const {433 SDNode *N = DAG.getMachineNode(MachineOpc, dl, Ty, Ops);434 return SDValue(N, 0);435 }436 SDValue getZero(const SDLoc &dl, MVT Ty, SelectionDAG &DAG) const;437 438 using VectorPair = std::pair<SDValue, SDValue>;439 using TypePair = std::pair<MVT, MVT>;440 441 SDValue getInt(unsigned IntId, MVT ResTy, ArrayRef<SDValue> Ops,442 const SDLoc &dl, SelectionDAG &DAG) const;443 444 MVT ty(SDValue Op) const {445 return Op.getValueType().getSimpleVT();446 }447 TypePair ty(const VectorPair &Ops) const {448 return { Ops.first.getValueType().getSimpleVT(),449 Ops.second.getValueType().getSimpleVT() };450 }451 MVT tyScalar(MVT Ty) const {452 if (!Ty.isVector())453 return Ty;454 return MVT::getIntegerVT(Ty.getSizeInBits());455 }456 MVT tyVector(MVT Ty, MVT ElemTy) const {457 if (Ty.isVector() && Ty.getVectorElementType() == ElemTy)458 return Ty;459 unsigned TyWidth = Ty.getSizeInBits();460 unsigned ElemWidth = ElemTy.getSizeInBits();461 assert((TyWidth % ElemWidth) == 0);462 return MVT::getVectorVT(ElemTy, TyWidth/ElemWidth);463 }464 465 MVT typeJoin(const TypePair &Tys) const;466 TypePair typeSplit(MVT Ty) const;467 MVT typeExtElem(MVT VecTy, unsigned Factor) const;468 MVT typeTruncElem(MVT VecTy, unsigned Factor) const;469 TypePair typeExtendToWider(MVT Ty0, MVT Ty1) const;470 TypePair typeWidenToWider(MVT Ty0, MVT Ty1) const;471 MVT typeLegalize(MVT Ty, SelectionDAG &DAG) const;472 MVT typeWidenToHvx(MVT Ty) const;473 474 SDValue opJoin(const VectorPair &Ops, const SDLoc &dl,475 SelectionDAG &DAG) const;476 VectorPair opSplit(SDValue Vec, const SDLoc &dl, SelectionDAG &DAG) const;477 SDValue opCastElem(SDValue Vec, MVT ElemTy, SelectionDAG &DAG) const;478 479 SDValue LoHalf(SDValue V, SelectionDAG &DAG) const {480 MVT Ty = ty(V);481 const SDLoc &dl(V);482 if (!Ty.isVector()) {483 assert(Ty.getSizeInBits() == 64);484 return DAG.getTargetExtractSubreg(Hexagon::isub_lo, dl, MVT::i32, V);485 }486 MVT HalfTy = typeSplit(Ty).first;487 SDValue Idx = getZero(dl, MVT::i32, DAG);488 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, HalfTy, V, Idx);489 }490 SDValue HiHalf(SDValue V, SelectionDAG &DAG) const {491 MVT Ty = ty(V);492 const SDLoc &dl(V);493 if (!Ty.isVector()) {494 assert(Ty.getSizeInBits() == 64);495 return DAG.getTargetExtractSubreg(Hexagon::isub_hi, dl, MVT::i32, V);496 }497 MVT HalfTy = typeSplit(Ty).first;498 SDValue Idx = DAG.getConstant(HalfTy.getVectorNumElements(), dl, MVT::i32);499 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, HalfTy, V, Idx);500 }501 502 bool allowsHvxMemoryAccess(MVT VecTy, MachineMemOperand::Flags Flags,503 unsigned *Fast) const;504 bool allowsHvxMisalignedMemoryAccesses(MVT VecTy,505 MachineMemOperand::Flags Flags,506 unsigned *Fast) const;507 void AdjustHvxInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const;508 509 bool isHvxSingleTy(MVT Ty) const;510 bool isHvxPairTy(MVT Ty) const;511 bool isHvxBoolTy(MVT Ty) const;512 SDValue convertToByteIndex(SDValue ElemIdx, MVT ElemTy,513 SelectionDAG &DAG) const;514 SDValue getIndexInWord32(SDValue Idx, MVT ElemTy, SelectionDAG &DAG) const;515 SDValue getByteShuffle(const SDLoc &dl, SDValue Op0, SDValue Op1,516 ArrayRef<int> Mask, SelectionDAG &DAG) const;517 518 SDValue buildHvxVectorReg(ArrayRef<SDValue> Values, const SDLoc &dl,519 MVT VecTy, SelectionDAG &DAG) const;520 SDValue buildHvxVectorPred(ArrayRef<SDValue> Values, const SDLoc &dl,521 MVT VecTy, SelectionDAG &DAG) const;522 SDValue createHvxPrefixPred(SDValue PredV, const SDLoc &dl,523 unsigned BitBytes, bool ZeroFill,524 SelectionDAG &DAG) const;525 SDValue extractHvxElementReg(SDValue VecV, SDValue IdxV, const SDLoc &dl,526 MVT ResTy, SelectionDAG &DAG) const;527 SDValue extractHvxElementPred(SDValue VecV, SDValue IdxV, const SDLoc &dl,528 MVT ResTy, SelectionDAG &DAG) const;529 SDValue insertHvxElementReg(SDValue VecV, SDValue IdxV, SDValue ValV,530 const SDLoc &dl, SelectionDAG &DAG) const;531 SDValue insertHvxElementPred(SDValue VecV, SDValue IdxV, SDValue ValV,532 const SDLoc &dl, SelectionDAG &DAG) const;533 SDValue extractHvxSubvectorReg(SDValue OrigOp, SDValue VecV, SDValue IdxV,534 const SDLoc &dl, MVT ResTy, SelectionDAG &DAG)535 const;536 SDValue extractHvxSubvectorPred(SDValue VecV, SDValue IdxV, const SDLoc &dl,537 MVT ResTy, SelectionDAG &DAG) const;538 SDValue insertHvxSubvectorReg(SDValue VecV, SDValue SubV, SDValue IdxV,539 const SDLoc &dl, SelectionDAG &DAG) const;540 SDValue insertHvxSubvectorPred(SDValue VecV, SDValue SubV, SDValue IdxV,541 const SDLoc &dl, SelectionDAG &DAG) const;542 SDValue extendHvxVectorPred(SDValue VecV, const SDLoc &dl, MVT ResTy,543 bool ZeroExt, SelectionDAG &DAG) const;544 SDValue compressHvxPred(SDValue VecQ, const SDLoc &dl, MVT ResTy,545 SelectionDAG &DAG) const;546 SDValue resizeToWidth(SDValue VecV, MVT ResTy, bool Signed, const SDLoc &dl,547 SelectionDAG &DAG) const;548 SDValue extractSubvector(SDValue Vec, MVT SubTy, unsigned SubIdx,549 SelectionDAG &DAG) const;550 VectorPair emitHvxAddWithOverflow(SDValue A, SDValue B, const SDLoc &dl,551 bool Signed, SelectionDAG &DAG) const;552 VectorPair emitHvxShiftRightRnd(SDValue Val, unsigned Amt, bool Signed,553 SelectionDAG &DAG) const;554 SDValue emitHvxMulHsV60(SDValue A, SDValue B, const SDLoc &dl,555 SelectionDAG &DAG) const;556 SDValue emitHvxMulLoHiV60(SDValue A, bool SignedA, SDValue B, bool SignedB,557 const SDLoc &dl, SelectionDAG &DAG) const;558 SDValue emitHvxMulLoHiV62(SDValue A, bool SignedA, SDValue B, bool SignedB,559 const SDLoc &dl, SelectionDAG &DAG) const;560 561 SDValue LowerHvxBuildVector(SDValue Op, SelectionDAG &DAG) const;562 SDValue LowerHvxSplatVector(SDValue Op, SelectionDAG &DAG) const;563 SDValue LowerHvxConcatVectors(SDValue Op, SelectionDAG &DAG) const;564 SDValue LowerHvxExtractElement(SDValue Op, SelectionDAG &DAG) const;565 SDValue LowerHvxInsertElement(SDValue Op, SelectionDAG &DAG) const;566 SDValue LowerHvxExtractSubvector(SDValue Op, SelectionDAG &DAG) const;567 SDValue LowerHvxInsertSubvector(SDValue Op, SelectionDAG &DAG) const;568 SDValue LowerHvxBitcast(SDValue Op, SelectionDAG &DAG) const;569 SDValue LowerHvxAnyExt(SDValue Op, SelectionDAG &DAG) const;570 SDValue LowerHvxSignExt(SDValue Op, SelectionDAG &DAG) const;571 SDValue LowerHvxZeroExt(SDValue Op, SelectionDAG &DAG) const;572 SDValue LowerHvxCttz(SDValue Op, SelectionDAG &DAG) const;573 SDValue LowerHvxMulh(SDValue Op, SelectionDAG &DAG) const;574 SDValue LowerHvxMulLoHi(SDValue Op, SelectionDAG &DAG) const;575 SDValue LowerHvxExtend(SDValue Op, SelectionDAG &DAG) const;576 SDValue LowerHvxSelect(SDValue Op, SelectionDAG &DAG) const;577 SDValue LowerHvxShift(SDValue Op, SelectionDAG &DAG) const;578 SDValue LowerHvxFunnelShift(SDValue Op, SelectionDAG &DAG) const;579 SDValue LowerHvxIntrinsic(SDValue Op, SelectionDAG &DAG) const;580 SDValue LowerHvxMaskedOp(SDValue Op, SelectionDAG &DAG) const;581 SDValue LowerHvxFpExtend(SDValue Op, SelectionDAG &DAG) const;582 SDValue LowerHvxFpToInt(SDValue Op, SelectionDAG &DAG) const;583 SDValue LowerHvxIntToFp(SDValue Op, SelectionDAG &DAG) const;584 SDValue LowerHvxPred32ToFp(SDValue Op, SelectionDAG &DAG) const;585 SDValue LowerHvxPred64ToFp(SDValue Op, SelectionDAG &DAG) const;586 SDValue ExpandHvxFpToInt(SDValue Op, SelectionDAG &DAG) const;587 SDValue ExpandHvxIntToFp(SDValue Op, SelectionDAG &DAG) const;588 589 VectorPair SplitVectorOp(SDValue Op, SelectionDAG &DAG) const;590 591 SDValue SplitHvxMemOp(SDValue Op, SelectionDAG &DAG) const;592 SDValue WidenHvxLoad(SDValue Op, SelectionDAG &DAG) const;593 SDValue WidenHvxStore(SDValue Op, SelectionDAG &DAG) const;594 SDValue WidenHvxSetCC(SDValue Op, SelectionDAG &DAG) const;595 SDValue LegalizeHvxResize(SDValue Op, SelectionDAG &DAG) const;596 SDValue ExpandHvxResizeIntoSteps(SDValue Op, SelectionDAG &DAG) const;597 SDValue EqualizeFpIntConversion(SDValue Op, SelectionDAG &DAG) const;598 599 SDValue CreateTLWrapper(SDValue Op, SelectionDAG &DAG) const;600 SDValue RemoveTLWrapper(SDValue Op, SelectionDAG &DAG) const;601 602 std::pair<const TargetRegisterClass*, uint8_t>603 findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT)604 const override;605 606 bool shouldSplitToHvx(MVT Ty, SelectionDAG &DAG) const;607 bool shouldWidenToHvx(MVT Ty, SelectionDAG &DAG) const;608 bool isHvxOperation(SDNode *N, SelectionDAG &DAG) const;609 SDValue LowerHvxOperation(SDValue Op, SelectionDAG &DAG) const;610 void LowerHvxOperationWrapper(SDNode *N, SmallVectorImpl<SDValue> &Results,611 SelectionDAG &DAG) const;612 void ReplaceHvxNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,613 SelectionDAG &DAG) const;614 615 SDValue combineTruncateBeforeLegal(SDValue Op, DAGCombinerInfo &DCI) const;616 SDValue combineConcatVectorsBeforeLegal(SDValue Op, DAGCombinerInfo & DCI)617 const;618 SDValue combineVectorShuffleBeforeLegal(SDValue Op, DAGCombinerInfo & DCI)619 const;620 621 SDValue PerformHvxDAGCombine(SDNode * N, DAGCombinerInfo & DCI) const;622};623 624} // end namespace llvm625 626#endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONISELLOWERING_H627