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