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