• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//===-- LLVMOpBase.td - LLVM IR dialect shared definitions -*- tablegen -*-===//
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 contains shared definitions for the LLVM IR dialect and its
10// subdialects.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVMIR_OP_BASE
15#define LLVMIR_OP_BASE
16
17include "mlir/IR/OpBase.td"
18include "mlir/Interfaces/SideEffectInterfaces.td"
19
20//===----------------------------------------------------------------------===//
21// LLVM Dialect.
22//===----------------------------------------------------------------------===//
23
24def LLVM_Dialect : Dialect {
25  let name = "llvm";
26  let cppNamespace = "::mlir::LLVM";
27
28  let hasRegionArgAttrVerify = 1;
29  let hasOperationAttrVerify = 1;
30  let extraClassDeclaration = [{
31    /// Name of the data layout attributes.
32    static StringRef getDataLayoutAttrName() { return "llvm.data_layout"; }
33    static StringRef getAlignAttrName() { return "llvm.align"; }
34    static StringRef getNoAliasAttrName() { return "llvm.noalias"; }
35
36    /// Verifies if the given string is a well-formed data layout descriptor.
37    /// Uses `reportError` to report errors.
38    static LogicalResult verifyDataLayoutString(
39        StringRef descr, llvm::function_ref<void (const Twine &)> reportError);
40
41    /// Name of the target triple attribute.
42    static StringRef getTargetTripleAttrName() { return "llvm.target_triple"; }
43  }];
44}
45
46//===----------------------------------------------------------------------===//
47// LLVM dialect type constraints.
48//===----------------------------------------------------------------------===//
49
50// LLVM dialect type.
51def LLVM_Type : DialectType<LLVM_Dialect,
52                            CPred<"$_self.isa<::mlir::LLVM::LLVMType>()">,
53                            "LLVM dialect type">;
54
55// Type constraint accepting LLVM integer types.
56def LLVM_AnyInteger : Type<
57  CPred<"$_self.isa<::mlir::LLVM::LLVMIntegerType>()">,
58  "LLVM integer type">;
59
60// Type constraints accepting LLVM integer type of a specific width.
61class LLVM_IntBase<int width> :
62    Type<And<[
63        LLVM_AnyInteger.predicate,
64        CPred<"$_self.cast<::mlir::LLVM::LLVMIntegerType>().getBitWidth() == "
65              # width>]>,
66        "LLVM " # width # "-bit integer type">,
67    BuildableType<
68        "::mlir::LLVM::LLVMIntegerType::get($_builder.getContext(), "
69        # width # ")">;
70
71def LLVM_i1 : LLVM_IntBase<1>;
72def LLVM_i8 : LLVM_IntBase<8>;
73def LLVM_i32 : LLVM_IntBase<32>;
74
75// Type constraint accepting LLVM primitive types, i.e. all types except void
76// and function.
77def LLVM_PrimitiveType : Type<
78  And<[LLVM_Type.predicate,
79       CPred<"!$_self.isa<::mlir::LLVM::LLVMVoidType, "
80                         "::mlir::LLVM::LLVMFunctionType>()">]>,
81  "primitive LLVM type">;
82
83// Type constraint accepting any LLVM floating point type.
84def LLVM_AnyFloat : Type<
85  CPred<"$_self.isa<::mlir::LLVM::LLVMBFloatType, "
86                   "::mlir::LLVM::LLVMHalfType, "
87                   "::mlir::LLVM::LLVMFloatType, "
88                   "::mlir::LLVM::LLVMDoubleType, "
89                   "::mlir::LLVM::LLVMFP128Type, "
90                   "::mlir::LLVM::LLVMX86FP80Type>()">,
91  "floating point LLVM type">;
92
93// Type constraint accepting any LLVM pointer type.
94def LLVM_AnyPointer : Type<CPred<"$_self.isa<::mlir::LLVM::LLVMPointerType>()">,
95                          "LLVM pointer type">;
96
97// Type constraint accepting LLVM pointer type with an additional constraint
98// on the element type.
99class LLVM_PointerTo<Type pointee> : Type<
100  And<[LLVM_AnyPointer.predicate,
101       SubstLeaves<
102         "$_self",
103         "$_self.cast<::mlir::LLVM::LLVMPointerType>().getElementType()",
104         pointee.predicate>]>,
105  "LLVM pointer to " # pointee.description>;
106
107// Type constraint accepting any LLVM structure type.
108def LLVM_AnyStruct : Type<CPred<"$_self.isa<::mlir::LLVM::LLVMStructType>()">,
109                         "LLVM structure type">;
110
111// Type constraint accepting opaque LLVM structure type.
112def LLVM_OpaqueStruct : Type<
113  And<[LLVM_AnyStruct.predicate,
114       CPred<"$_self.cast<::mlir::LLVM::LLVMStructType>().isOpaque()">]>>;
115
116// Type constraint accepting any LLVM type that can be loaded or stored, i.e. a
117// type that has size (not void, function or opaque struct type).
118def LLVM_LoadableType : Type<
119  And<[LLVM_PrimitiveType.predicate, Neg<LLVM_OpaqueStruct.predicate>]>,
120  "LLVM type with size">;
121
122// Type constraint accepting any LLVM aggregate type, i.e. structure or array.
123def LLVM_AnyAggregate : Type<
124  CPred<"$_self.isa<::mlir::LLVM::LLVMStructType, "
125                   "::mlir::LLVM::LLVMArrayType>()">,
126  "LLVM aggregate type">;
127
128// Type constraint accepting any LLVM non-aggregate type, i.e. not structure or
129// array.
130def LLVM_AnyNonAggregate : Type<Neg<LLVM_AnyAggregate.predicate>,
131                               "LLVM non-aggregate type">;
132
133// Type constraint accepting any LLVM vector type.
134def LLVM_AnyVector : Type<CPred<"$_self.isa<::mlir::LLVM::LLVMVectorType>()">,
135                         "LLVM vector type">;
136
137// Type constraint accepting an LLVM vector type with an additional constraint
138// on the vector element type.
139class LLVM_VectorOf<Type element> : Type<
140  And<[LLVM_AnyVector.predicate,
141       SubstLeaves<
142         "$_self",
143         "$_self.cast<::mlir::LLVM::LLVMVectorType>().getElementType()",
144         element.predicate>]>,
145  "LLVM vector of " # element.description>;
146
147// Type constraint accepting a constrained type, or a vector of such types.
148class LLVM_ScalarOrVectorOf<Type element> :
149    AnyTypeOf<[element, LLVM_VectorOf<element>]>;
150
151// Base class for LLVM operations. Defines the interface to the llvm::IRBuilder
152// used to translate to LLVM IR proper.
153class LLVM_OpBase<Dialect dialect, string mnemonic, list<OpTrait> traits = []> :
154    Op<dialect, mnemonic, traits> {
155  // A pattern for constructing the LLVM IR Instruction (or other Value) that
156  // corresponds to this op.  This pattern can use `builder` to refer to an
157  // `llvm::IRBuilder<>` instance, $-names of arguments and results and the
158  // following special variable names:
159  //   - $_resultType - substituted with the LLVM IR type of the result;
160  //   - $_numOperands - substituted with the number of operands (including
161  //                     the variadic ones);
162  //   - $_hasResult - substituted with a check that a variadic-result op does
163  //                   have a result (LLVM ops can have 0 or 1 result);
164  //   - $_location - mlir::Location object of the instruction.
165  // Additionally, `$$` can be used to produce the dollar character.
166  string llvmBuilder = "";
167}
168
169//===----------------------------------------------------------------------===//
170// Base classes for LLVM dialect operations.
171//===----------------------------------------------------------------------===//
172
173// Base class for LLVM operations. All operations get an "llvm." prefix in
174// their name automatically. LLVM operations have either zero or one result,
175// this class is specialized below for both cases and should not be used
176// directly.
177class LLVM_Op<string mnemonic, list<OpTrait> traits = []> :
178    LLVM_OpBase<LLVM_Dialect, mnemonic, traits>;
179
180// Case of the LLVM enum attribute backed by I64Attr with customized string
181// representation that corresponds to what is visible in the textual IR form.
182// The parameters are as follows:
183//   - `cppSym`: name of the C++ enumerant for this case in MLIR API;
184//   - `irSym`: keyword used in the custom form of MLIR operation;
185//   - `llvmSym`: name of the C++ enumerant for this case in LLVM API.
186// For example, `LLVM_EnumAttrCase<"Weak", "weak", "WeakAnyLinkage">` is usable
187// as `<MlirEnumName>::Weak` in MLIR API, `WeakAnyLinkage` in LLVM API and
188// is printed/parsed as `weak` in MLIR custom textual format.
189class LLVM_EnumAttrCase<string cppSym, string irSym, string llvmSym, int val> :
190    I64EnumAttrCase<cppSym, val, irSym> {
191
192  // The name of the equivalent enumerant in LLVM.
193  string llvmEnumerant = llvmSym;
194}
195
196// LLVM enum attribute backed by I64Attr with string representation
197// corresponding to what is visible in the textual IR form.
198// The parameters are as follows:
199//   - `name`: name of the C++ enum class in MLIR API;
200//   - `llvmName`: name of the C++ enum in LLVM API;
201//   - `description`: textual description for documentation purposes;
202//   - `cases`: list of enum cases.
203// For example, `LLVM_EnumAttr<Linkage, "::llvm::GlobalValue::LinkageTypes`
204// produces `mlir::LLVM::Linkage` enum class in MLIR API that corresponds to (a
205// subset of) values in the `llvm::GlobalValue::LinkageTypes` in LLVM API.
206class LLVM_EnumAttr<string name, string llvmName, string description,
207                    list<LLVM_EnumAttrCase> cases> :
208    I64EnumAttr<name, description, cases> {
209
210  // The equivalent enum class name in LLVM.
211  string llvmClassName = llvmName;
212}
213
214// For every value in the list, substitutes the value in the place of "$0" in
215// "pattern" and stores the list of strings as "lst".
216class ListIntSubst<string pattern, list<int> values> {
217  list<string> lst = !foreach(x, values,
218                              !subst("$0", !cast<string>(x), pattern));
219}
220
221// Patterns with code obtaining the LLVM IR type of the given operand or result
222// of operation. "$0" is expected to be replaced by the position of the operand
223// or result in the operation.
224def LLVM_IntrPatterns {
225  string operand =
226    [{convertType(opInst.getOperand($0).getType().cast<LLVM::LLVMType>())}];
227  string result =
228    [{convertType(opInst.getResult($0).getType().cast<LLVM::LLVMType>())}];
229  string structResult =
230    [{convertType(opInst.getResult(0).getType().cast<LLVM::LLVMStructType>()
231                                                   .getBody()[$0])}];
232}
233
234
235// Base class for LLVM intrinsics operation. It is similar to LLVM_Op, but
236// provides the "llvmBuilder" field for constructing the intrinsic.
237// The builder relies on the contents of "overloadedResults" and
238// "overloadedOperands" lists that contain the positions of intrinsic results
239// and operands that are overloadable in the LLVM sense, that is their types
240// must be passed in during the construction of the intrinsic declaration to
241// differentiate between differently-typed versions of the intrinsic.
242// If the intrinsic has multiple results, this will eventually be packed into a
243// single struct result. In this case, the types of any overloaded results need
244// to be accessed via the LLVMStructType, instead of directly via the result.
245// "opName" contains the name of the operation to be associated with the
246// intrinsic and "enumName" contains the name of the intrinsic as appears in
247// `llvm::Intrinsic` enum; one usually wants these to be related.
248class LLVM_IntrOpBase<Dialect dialect, string opName, string enumName,
249                      list<int> overloadedResults, list<int> overloadedOperands,
250                      list<OpTrait> traits, int numResults>
251    : LLVM_OpBase<dialect, opName, traits>,
252      Results<!if(!gt(numResults, 0), (outs LLVM_Type:$res), (outs))> {
253  string resultPattern = !if(!gt(numResults, 1),
254                             LLVM_IntrPatterns.structResult,
255                             LLVM_IntrPatterns.result);
256  let llvmBuilder = [{
257    llvm::Module *module = builder.GetInsertBlock()->getModule();
258    llvm::Function *fn = llvm::Intrinsic::getDeclaration(
259        module,
260        llvm::Intrinsic::}] # enumName # [{,
261        { }] # StrJoin<!listconcat(
262            ListIntSubst<resultPattern, overloadedResults>.lst,
263            ListIntSubst<LLVM_IntrPatterns.operand,
264                         overloadedOperands>.lst)>.result # [{
265        });
266    auto operands = lookupValues(opInst.getOperands());
267    }] # !if(!gt(numResults, 0), "$res = ", "")
268       # [{builder.CreateCall(fn, operands);
269  }];
270}
271
272// Base class for LLVM intrinsic operations, should not be used directly. Places
273// the intrinsic into the LLVM dialect and prefixes its name with "intr.".
274class LLVM_IntrOp<string mnem, list<int> overloadedResults,
275                  list<int> overloadedOperands, list<OpTrait> traits,
276                  int numResults>
277    : LLVM_IntrOpBase<LLVM_Dialect, "intr." # mnem, !subst(".", "_", mnem),
278                      overloadedResults, overloadedOperands, traits,
279                      numResults>;
280
281// Base class for LLVM intrinsic operations returning no results. Places the
282// intrinsic into the LLVM dialect and prefixes its name with "intr.".
283//
284// Sample use: derive an entry from this class and populate the fields.
285//
286//    def LLVM_Name : LLVM_ZeroResultIntrOp<"name", [0], [NoSideEffect]>,
287//                    Arguments<(ins LLVM_Type, LLVM_Type)>;
288//
289// The mnemonic will be prefixed with "llvm.intr.", where the "llvm." part comes
290// from the LLVM dialect. The overloadedOperands list contains the indices of
291// the operands the type of which will be passed in the LLVM IR intrinsic
292// builder. In the example above, the Op has two arguments, but only the first
293// one (as indicated by `[0]`) is necessary to resolve the overloaded intrinsic.
294// The Op has no results.
295class LLVM_ZeroResultIntrOp<string mnem, list<int> overloadedOperands = [],
296                            list<OpTrait> traits = []>
297    : LLVM_IntrOp<mnem, [], overloadedOperands, traits, 0>;
298
299// Base class for LLVM intrinsic operations returning one result. Places the
300// intrinsic into the LLVM dialect and prefixes its name with "intr.". This is
301// similar to LLVM_ZeroResultIntrOp but allows one to define Ops returning one
302// result, called "res". Additionally, the overloadedResults list should contain
303// "0" if the result must be used to resolve overloaded intrinsics, or remain
304// empty otherwise.
305class LLVM_OneResultIntrOp<string mnem, list<int> overloadedResults = [],
306                           list<int> overloadedOperands = [],
307                           list<OpTrait> traits = []>
308    : LLVM_IntrOp<mnem, overloadedResults, overloadedOperands, traits, 1>;
309
310// LLVM vector reduction over a single vector.
311class LLVM_VectorReduction<string mnem>
312    : LLVM_OneResultIntrOp<"vector.reduce." # mnem,
313                           [], [0], [NoSideEffect]>,
314      Arguments<(ins LLVM_Type)>;
315
316// LLVM vector reduction over a single vector, with an initial value,
317// and with permission to reassociate the reduction operations.
318class LLVM_VectorReductionAcc<string mnem>
319    : LLVM_OpBase<LLVM_Dialect, "intr.vector.reduce." # mnem,
320                  [NoSideEffect]>,
321      Results<(outs LLVM_Type:$res)>,
322      Arguments<(ins LLVM_Type, LLVM_Type,
323                 DefaultValuedAttr<BoolAttr, "false">:$reassoc)> {
324  let llvmBuilder = [{
325    llvm::Module *module = builder.GetInsertBlock()->getModule();
326    llvm::Function *fn = llvm::Intrinsic::getDeclaration(
327        module,
328        llvm::Intrinsic::vector_reduce_}] # mnem # [{,
329        { }] # StrJoin<ListIntSubst<LLVM_IntrPatterns.operand, [1]>.lst>.result # [{
330        });
331    auto operands = lookupValues(opInst.getOperands());
332    llvm::FastMathFlags origFM = builder.getFastMathFlags();
333    llvm::FastMathFlags tempFM = origFM;
334    tempFM.setAllowReassoc($reassoc);
335    builder.setFastMathFlags(tempFM);  // set fastmath flag
336    $res = builder.CreateCall(fn, operands);
337    builder.setFastMathFlags(origFM);  // restore fastmath flag
338  }];
339}
340
341#endif  // LLVMIR_OP_BASE
342