xref: /freebsd/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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