1 //==- llvm/CodeGen/SelectionDAGTargetInfo.h - SelectionDAG Info --*- 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 declares the SelectionDAGTargetInfo class, which targets can 10 // subclass to parameterize the SelectionDAG lowering and instruction 11 // selection process. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CODEGEN_SELECTIONDAGTARGETINFO_H 16 #define LLVM_CODEGEN_SELECTIONDAGTARGETINFO_H 17 18 #include "llvm/CodeGen/MachineMemOperand.h" 19 #include "llvm/CodeGen/SDNodeInfo.h" 20 #include "llvm/CodeGen/SelectionDAGNodes.h" 21 #include "llvm/Support/CodeGen.h" 22 #include <utility> 23 24 namespace llvm { 25 26 class SelectionDAG; 27 28 //===----------------------------------------------------------------------===// 29 /// Targets can subclass this to parameterize the 30 /// SelectionDAG lowering and instruction selection process. 31 /// 32 class SelectionDAGTargetInfo { 33 public: 34 explicit SelectionDAGTargetInfo() = default; 35 SelectionDAGTargetInfo(const SelectionDAGTargetInfo &) = delete; 36 SelectionDAGTargetInfo &operator=(const SelectionDAGTargetInfo &) = delete; 37 virtual ~SelectionDAGTargetInfo(); 38 39 /// Returns the name of the given target-specific opcode, suitable for 40 /// debug printing. getTargetNodeName(unsigned Opcode)41 virtual const char *getTargetNodeName(unsigned Opcode) const { 42 return nullptr; 43 } 44 45 /// Returns true if a node with the given target-specific opcode has 46 /// a memory operand. Nodes with such opcodes can only be created with 47 /// `SelectionDAG::getMemIntrinsicNode`. isTargetMemoryOpcode(unsigned Opcode)48 virtual bool isTargetMemoryOpcode(unsigned Opcode) const { return false; } 49 50 /// Returns true if a node with the given target-specific opcode has 51 /// strict floating-point semantics. isTargetStrictFPOpcode(unsigned Opcode)52 virtual bool isTargetStrictFPOpcode(unsigned Opcode) const { return false; } 53 54 /// Returns true if a node with the given target-specific opcode 55 /// may raise a floating-point exception. 56 virtual bool mayRaiseFPException(unsigned Opcode) const; 57 58 /// Checks that the given target-specific node is valid. Aborts if it is not. verifyTargetNode(const SelectionDAG & DAG,const SDNode * N)59 virtual void verifyTargetNode(const SelectionDAG &DAG, 60 const SDNode *N) const {} 61 62 /// Emit target-specific code that performs a memcpy. 63 /// This can be used by targets to provide code sequences for cases 64 /// that don't fit the target's parameters for simple loads/stores and can be 65 /// more efficient than using a library call. This function can return a null 66 /// SDValue if the target declines to use custom code and a different 67 /// lowering strategy should be used. 68 /// 69 /// If AlwaysInline is true, the size is constant and the target should not 70 /// emit any calls and is strongly encouraged to attempt to emit inline code 71 /// even if it is beyond the usual threshold because this intrinsic is being 72 /// expanded in a place where calls are not feasible (e.g. within the prologue 73 /// for another call). If the target chooses to decline an AlwaysInline 74 /// request here, legalize will resort to using simple loads and stores. EmitTargetCodeForMemcpy(SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Op1,SDValue Op2,SDValue Op3,Align Alignment,bool isVolatile,bool AlwaysInline,MachinePointerInfo DstPtrInfo,MachinePointerInfo SrcPtrInfo)75 virtual SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, const SDLoc &dl, 76 SDValue Chain, SDValue Op1, 77 SDValue Op2, SDValue Op3, 78 Align Alignment, bool isVolatile, 79 bool AlwaysInline, 80 MachinePointerInfo DstPtrInfo, 81 MachinePointerInfo SrcPtrInfo) const { 82 return SDValue(); 83 } 84 85 /// Emit target-specific code that performs a memmove. 86 /// This can be used by targets to provide code sequences for cases 87 /// that don't fit the target's parameters for simple loads/stores and can be 88 /// more efficient than using a library call. This function can return a null 89 /// SDValue if the target declines to use custom code and a different 90 /// lowering strategy should be used. EmitTargetCodeForMemmove(SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Op1,SDValue Op2,SDValue Op3,Align Alignment,bool isVolatile,MachinePointerInfo DstPtrInfo,MachinePointerInfo SrcPtrInfo)91 virtual SDValue EmitTargetCodeForMemmove( 92 SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Op1, 93 SDValue Op2, SDValue Op3, Align Alignment, bool isVolatile, 94 MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const { 95 return SDValue(); 96 } 97 98 /// Emit target-specific code that performs a memset. 99 /// This can be used by targets to provide code sequences for cases 100 /// that don't fit the target's parameters for simple stores and can be more 101 /// efficient than using a library call. This function can return a null 102 /// SDValue if the target declines to use custom code and a different 103 /// lowering strategy should be used. Note that if AlwaysInline is true the 104 /// function has to return a valid SDValue. EmitTargetCodeForMemset(SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Op1,SDValue Op2,SDValue Op3,Align Alignment,bool isVolatile,bool AlwaysInline,MachinePointerInfo DstPtrInfo)105 virtual SDValue EmitTargetCodeForMemset(SelectionDAG &DAG, const SDLoc &dl, 106 SDValue Chain, SDValue Op1, 107 SDValue Op2, SDValue Op3, 108 Align Alignment, bool isVolatile, 109 bool AlwaysInline, 110 MachinePointerInfo DstPtrInfo) const { 111 return SDValue(); 112 } 113 114 /// Emit target-specific code that performs a memcmp/bcmp, in cases where that is 115 /// faster than a libcall. The first returned SDValue is the result of the 116 /// memcmp and the second is the chain. Both SDValues can be null if a normal 117 /// libcall should be used. 118 virtual std::pair<SDValue, SDValue> EmitTargetCodeForMemcmp(SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Op1,SDValue Op2,SDValue Op3,MachinePointerInfo Op1PtrInfo,MachinePointerInfo Op2PtrInfo)119 EmitTargetCodeForMemcmp(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, 120 SDValue Op1, SDValue Op2, SDValue Op3, 121 MachinePointerInfo Op1PtrInfo, 122 MachinePointerInfo Op2PtrInfo) const { 123 return std::make_pair(SDValue(), SDValue()); 124 } 125 126 /// Emit target-specific code that performs a memchr, in cases where that is 127 /// faster than a libcall. The first returned SDValue is the result of the 128 /// memchr and the second is the chain. Both SDValues can be null if a normal 129 /// libcall should be used. 130 virtual std::pair<SDValue, SDValue> EmitTargetCodeForMemchr(SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Src,SDValue Char,SDValue Length,MachinePointerInfo SrcPtrInfo)131 EmitTargetCodeForMemchr(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, 132 SDValue Src, SDValue Char, SDValue Length, 133 MachinePointerInfo SrcPtrInfo) const { 134 return std::make_pair(SDValue(), SDValue()); 135 } 136 137 /// Emit target-specific code that performs a strcpy or stpcpy, in cases 138 /// where that is faster than a libcall. 139 /// The first returned SDValue is the result of the copy (the start 140 /// of the destination string for strcpy, a pointer to the null terminator 141 /// for stpcpy) and the second is the chain. Both SDValues can be null 142 /// if a normal libcall should be used. 143 virtual std::pair<SDValue, SDValue> EmitTargetCodeForStrcpy(SelectionDAG & DAG,const SDLoc & DL,SDValue Chain,SDValue Dest,SDValue Src,MachinePointerInfo DestPtrInfo,MachinePointerInfo SrcPtrInfo,bool isStpcpy)144 EmitTargetCodeForStrcpy(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, 145 SDValue Dest, SDValue Src, 146 MachinePointerInfo DestPtrInfo, 147 MachinePointerInfo SrcPtrInfo, bool isStpcpy) const { 148 return std::make_pair(SDValue(), SDValue()); 149 } 150 151 /// Emit target-specific code that performs a strcmp, in cases where that is 152 /// faster than a libcall. 153 /// The first returned SDValue is the result of the strcmp and the second is 154 /// the chain. Both SDValues can be null if a normal libcall should be used. 155 virtual std::pair<SDValue, SDValue> EmitTargetCodeForStrcmp(SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Op1,SDValue Op2,MachinePointerInfo Op1PtrInfo,MachinePointerInfo Op2PtrInfo)156 EmitTargetCodeForStrcmp(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, 157 SDValue Op1, SDValue Op2, 158 MachinePointerInfo Op1PtrInfo, 159 MachinePointerInfo Op2PtrInfo) const { 160 return std::make_pair(SDValue(), SDValue()); 161 } 162 163 virtual std::pair<SDValue, SDValue> EmitTargetCodeForStrlen(SelectionDAG & DAG,const SDLoc & DL,SDValue Chain,SDValue Src,MachinePointerInfo SrcPtrInfo)164 EmitTargetCodeForStrlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, 165 SDValue Src, MachinePointerInfo SrcPtrInfo) const { 166 return std::make_pair(SDValue(), SDValue()); 167 } 168 169 virtual std::pair<SDValue, SDValue> EmitTargetCodeForStrnlen(SelectionDAG & DAG,const SDLoc & DL,SDValue Chain,SDValue Src,SDValue MaxLength,MachinePointerInfo SrcPtrInfo)170 EmitTargetCodeForStrnlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, 171 SDValue Src, SDValue MaxLength, 172 MachinePointerInfo SrcPtrInfo) const { 173 return std::make_pair(SDValue(), SDValue()); 174 } 175 EmitTargetCodeForSetTag(SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Addr,SDValue Size,MachinePointerInfo DstPtrInfo,bool ZeroData)176 virtual SDValue EmitTargetCodeForSetTag(SelectionDAG &DAG, const SDLoc &dl, 177 SDValue Chain, SDValue Addr, 178 SDValue Size, 179 MachinePointerInfo DstPtrInfo, 180 bool ZeroData) const { 181 return SDValue(); 182 } 183 184 // Return true if the DAG Combiner should disable generic combines. disableGenericCombines(CodeGenOptLevel OptLevel)185 virtual bool disableGenericCombines(CodeGenOptLevel OptLevel) const { 186 return false; 187 } 188 }; 189 190 /// Proxy class that targets should inherit from if they wish to use 191 /// the generated node descriptions. 192 class SelectionDAGGenTargetInfo : public SelectionDAGTargetInfo { 193 protected: 194 const SDNodeInfo &GenNodeInfo; 195 SelectionDAGGenTargetInfo(const SDNodeInfo & GenNodeInfo)196 explicit SelectionDAGGenTargetInfo(const SDNodeInfo &GenNodeInfo) 197 : GenNodeInfo(GenNodeInfo) {} 198 199 public: 200 ~SelectionDAGGenTargetInfo() override; 201 getTargetNodeName(unsigned Opcode)202 const char *getTargetNodeName(unsigned Opcode) const override { 203 assert(GenNodeInfo.hasDesc(Opcode) && 204 "The name should be provided by the derived class"); 205 return GenNodeInfo.getName(Opcode).data(); 206 } 207 isTargetMemoryOpcode(unsigned Opcode)208 bool isTargetMemoryOpcode(unsigned Opcode) const override { 209 if (GenNodeInfo.hasDesc(Opcode)) 210 return GenNodeInfo.getDesc(Opcode).hasProperty(SDNPMemOperand); 211 return false; 212 } 213 isTargetStrictFPOpcode(unsigned Opcode)214 bool isTargetStrictFPOpcode(unsigned Opcode) const override { 215 if (GenNodeInfo.hasDesc(Opcode)) 216 return GenNodeInfo.getDesc(Opcode).hasFlag(SDNFIsStrictFP); 217 return false; 218 } 219 verifyTargetNode(const SelectionDAG & DAG,const SDNode * N)220 void verifyTargetNode(const SelectionDAG &DAG, 221 const SDNode *N) const override { 222 if (GenNodeInfo.hasDesc(N->getOpcode())) 223 GenNodeInfo.verifyNode(DAG, N); 224 } 225 }; 226 227 } // end namespace llvm 228 229 #endif // LLVM_CODEGEN_SELECTIONDAGTARGETINFO_H 230