1#ifndef LLVM_INTRINSIC_OPS 2#define LLVM_INTRINSIC_OPS 3 4include "mlir/IR/OpBase.td" 5include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td" 6include "mlir/Dialect/LLVMIR/LLVMEnums.td" 7include "mlir/Dialect/LLVMIR/LLVMOpBase.td" 8include "mlir/Interfaces/InferTypeOpInterface.td" 9include "mlir/Interfaces/MemorySlotInterfaces.td" 10 11// Operations that correspond to LLVM intrinsics. With MLIR operation set being 12// extendable, there is no reason to introduce a hard boundary between "core" 13// operations and intrinsics. However, we systematically prefix them with 14// "intr." to avoid potential name clashes. 15 16class LLVM_UnaryIntrOpBase<string func, Type element, 17 list<Trait> traits = [], bit requiresFastmath = 0> : 18 LLVM_OneResultIntrOp<func, [], [0], 19 !listconcat([Pure, SameOperandsAndResultType], traits), 20 requiresFastmath> { 21 dag commonArgs = (ins LLVM_ScalarOrVectorOf<element>:$in); 22 let assemblyFormat = "`(` operands `)` attr-dict `:` " 23 "functional-type(operands, results)"; 24} 25 26class LLVM_UnaryIntrOpI<string func, list<Trait> traits = []> : 27 LLVM_UnaryIntrOpBase<func, AnySignlessInteger, traits> { 28 let arguments = commonArgs; 29} 30 31class LLVM_UnaryIntrOpF<string func, list<Trait> traits = []> : 32 LLVM_UnaryIntrOpBase<func, LLVM_AnyFloat, traits, /*requiresFastmath=*/1> { 33 dag fmfArg = ( 34 ins DefaultValuedAttr<LLVM_FastmathFlagsAttr, "{}">:$fastmathFlags); 35 let arguments = !con(commonArgs, fmfArg); 36} 37 38class LLVM_BinarySameArgsIntrOpBase<string func, Type element, 39 list<Trait> traits = [], bit requiresFastmath = 0> : 40 LLVM_OneResultIntrOp<func, [], [0], 41 !listconcat([Pure, SameOperandsAndResultType], traits), 42 requiresFastmath> { 43 dag commonArgs = (ins LLVM_ScalarOrVectorOf<element>:$a, 44 LLVM_ScalarOrVectorOf<element>:$b); 45 let assemblyFormat = "`(` operands `)` attr-dict `:` " 46 "functional-type(operands, results)"; 47} 48 49class LLVM_BinarySameArgsIntrOpI<string func, list<Trait> traits = []> : 50 LLVM_BinarySameArgsIntrOpBase<func, AnySignlessInteger, traits> { 51 let arguments = commonArgs; 52} 53 54class LLVM_BinarySameArgsIntrOpF<string func, list<Trait> traits = []> : 55 LLVM_BinarySameArgsIntrOpBase<func, LLVM_AnyFloat, traits, 56 /*requiresFastmath=*/1> { 57 dag fmfArg = ( 58 ins DefaultValuedAttr<LLVM_FastmathFlagsAttr, "{}">:$fastmathFlags); 59 let arguments = !con(commonArgs, fmfArg); 60} 61 62class LLVM_TernarySameArgsIntrOpBase<string func, Type element, 63 list<Trait> traits = [], bit requiresFastmath = 0> : 64 LLVM_OneResultIntrOp<func, [], [0], 65 !listconcat([Pure, SameOperandsAndResultType], traits), 66 requiresFastmath> { 67 dag commonArgs = (ins LLVM_ScalarOrVectorOf<element>:$a, 68 LLVM_ScalarOrVectorOf<element>:$b, 69 LLVM_ScalarOrVectorOf<element>:$c); 70 let assemblyFormat = "`(` operands `)` attr-dict `:` " 71 "functional-type(operands, results)"; 72} 73 74class LLVM_TernarySameArgsIntrOpI<string func, list<Trait> traits = []> : 75 LLVM_TernarySameArgsIntrOpBase<func, AnySignlessInteger, traits> { 76 let arguments = commonArgs; 77} 78 79class LLVM_TernarySameArgsIntrOpF<string func, list<Trait> traits = []> : 80 LLVM_TernarySameArgsIntrOpBase<func, LLVM_AnyFloat, traits, 81 /*requiresFastmath=*/1> { 82 dag fmfArg = ( 83 ins DefaultValuedAttr<LLVM_FastmathFlagsAttr, "{}">:$fastmathFlags); 84 let arguments = !con(commonArgs, fmfArg); 85} 86 87class LLVM_CountZerosIntrOp<string func, list<Trait> traits = []> : 88 LLVM_OneResultIntrOp<func, [], [0], 89 !listconcat([Pure], traits), 90 /*requiresFastmath=*/0, 91 /*immArgPositions=*/[1], /*immArgAttrNames=*/["is_zero_poison"]> { 92 let arguments = (ins LLVM_ScalarOrVectorOf<AnySignlessInteger>:$in, 93 I1Attr:$is_zero_poison); 94} 95 96def LLVM_AbsOp : LLVM_OneResultIntrOp<"abs", [], [0], [Pure], 97 /*requiresFastmath=*/0, 98 /*immArgPositions=*/[1], /*immArgAttrNames=*/["is_int_min_poison"]> { 99 let arguments = (ins LLVM_ScalarOrVectorOf<AnySignlessInteger>:$in, 100 I1Attr:$is_int_min_poison); 101} 102 103def LLVM_IsFPClass : LLVM_OneResultIntrOp<"is.fpclass", [], [0], [Pure], 104 /*requiresFastmath=*/0, 105 /*immArgPositions=*/[1], /*immArgAttrNames=*/["bit"]> { 106 let arguments = (ins LLVM_ScalarOrVectorOf<LLVM_AnyFloat>:$in, I32Attr:$bit); 107} 108 109def LLVM_CopySignOp : LLVM_BinarySameArgsIntrOpF<"copysign">; 110def LLVM_CosOp : LLVM_UnaryIntrOpF<"cos">; 111def LLVM_ExpOp : LLVM_UnaryIntrOpF<"exp">; 112def LLVM_Exp2Op : LLVM_UnaryIntrOpF<"exp2">; 113def LLVM_FAbsOp : LLVM_UnaryIntrOpF<"fabs">; 114def LLVM_FCeilOp : LLVM_UnaryIntrOpF<"ceil">; 115def LLVM_FFloorOp : LLVM_UnaryIntrOpF<"floor">; 116def LLVM_FMAOp : LLVM_TernarySameArgsIntrOpF<"fma">; 117def LLVM_FMulAddOp : LLVM_TernarySameArgsIntrOpF<"fmuladd">; 118def LLVM_Log10Op : LLVM_UnaryIntrOpF<"log10">; 119def LLVM_Log2Op : LLVM_UnaryIntrOpF<"log2">; 120def LLVM_LogOp : LLVM_UnaryIntrOpF<"log">; 121def LLVM_Prefetch : LLVM_ZeroResultIntrOp<"prefetch", [0], 122 /*traits=*/[], /*requiresAccessGroup=*/0, /*requiresAliasAnalysis=*/0, 123 /*requiresOpBundles=*/0, /*immArgPositions=*/[1, 2, 3], 124 /*immArgAttrNames=*/["rw", "hint", "cache"] 125> { 126 let arguments = (ins LLVM_AnyPointer:$addr, I32Attr:$rw, I32Attr:$hint, I32Attr:$cache); 127} 128def LLVM_SinOp : LLVM_UnaryIntrOpF<"sin">; 129def LLVM_RoundEvenOp : LLVM_UnaryIntrOpF<"roundeven">; 130def LLVM_RoundOp : LLVM_UnaryIntrOpF<"round">; 131def LLVM_FTruncOp : LLVM_UnaryIntrOpF<"trunc">; 132def LLVM_SqrtOp : LLVM_UnaryIntrOpF<"sqrt">; 133def LLVM_PowOp : LLVM_BinarySameArgsIntrOpF<"pow">; 134def LLVM_PowIOp : LLVM_OneResultIntrOp<"powi", [], [0,1], 135 [Pure], /*requiresFastmath=*/1> { 136 let arguments = 137 (ins LLVM_ScalarOrVectorOf<LLVM_AnyFloat>:$val, 138 AnySignlessInteger:$power, 139 DefaultValuedAttr<LLVM_FastmathFlagsAttr, "{}">:$fastmathFlags); 140 let assemblyFormat = "`(` operands `)` attr-dict `:` " 141 "functional-type(operands, results)"; 142} 143def LLVM_RintOp : LLVM_UnaryIntrOpF<"rint">; 144def LLVM_NearbyintOp : LLVM_UnaryIntrOpF<"nearbyint">; 145class LLVM_IntRoundIntrOpBase<string func> : 146 LLVM_OneResultIntrOp<func, [0], [0], [Pure]> { 147 let arguments = (ins LLVM_AnyFloat:$val); 148 let assemblyFormat = "`(` operands `)` attr-dict `:` " 149 "functional-type(operands, results)"; 150} 151def LLVM_LroundOp : LLVM_IntRoundIntrOpBase<"lround">; 152def LLVM_LlroundOp : LLVM_IntRoundIntrOpBase<"llround">; 153def LLVM_LrintOp : LLVM_IntRoundIntrOpBase<"lrint">; 154def LLVM_LlrintOp : LLVM_IntRoundIntrOpBase<"llrint">; 155def LLVM_BitReverseOp : LLVM_UnaryIntrOpI<"bitreverse">; 156def LLVM_ByteSwapOp : LLVM_UnaryIntrOpI<"bswap">; 157def LLVM_CountLeadingZerosOp : LLVM_CountZerosIntrOp<"ctlz">; 158def LLVM_CountTrailingZerosOp : LLVM_CountZerosIntrOp<"cttz">; 159def LLVM_CtPopOp : LLVM_UnaryIntrOpI<"ctpop">; 160def LLVM_FshlOp : LLVM_TernarySameArgsIntrOpI<"fshl">; 161def LLVM_FshrOp : LLVM_TernarySameArgsIntrOpI<"fshr">; 162def LLVM_MaxNumOp : LLVM_BinarySameArgsIntrOpF<"maxnum">; 163def LLVM_MinNumOp : LLVM_BinarySameArgsIntrOpF<"minnum">; 164def LLVM_MaximumOp : LLVM_BinarySameArgsIntrOpF<"maximum">; 165def LLVM_MinimumOp : LLVM_BinarySameArgsIntrOpF<"minimum">; 166def LLVM_SMaxOp : LLVM_BinarySameArgsIntrOpI<"smax">; 167def LLVM_SMinOp : LLVM_BinarySameArgsIntrOpI<"smin">; 168def LLVM_UMaxOp : LLVM_BinarySameArgsIntrOpI<"umax">; 169def LLVM_UMinOp : LLVM_BinarySameArgsIntrOpI<"umin">; 170def LLVM_SinhOp : LLVM_UnaryIntrOpF<"sinh">; 171def LLVM_CoshOp : LLVM_UnaryIntrOpF<"cosh">; 172def LLVM_TanhOp : LLVM_UnaryIntrOpF<"tanh">; 173 174class LLVM_MemcpyIntrOpBase<string name> : 175 LLVM_ZeroResultIntrOp<name, [0, 1, 2], 176 [DeclareOpInterfaceMethods<PromotableMemOpInterface>, 177 DeclareOpInterfaceMethods<DestructurableAccessorOpInterface>, 178 DeclareOpInterfaceMethods<SafeMemorySlotAccessOpInterface>], 179 /*requiresAccessGroup=*/1, /*requiresAliasAnalysis=*/1, 180 /*requiresOpBundles=*/0, /*immArgPositions=*/[3], 181 /*immArgAttrNames=*/["isVolatile"]> { 182 dag args = (ins Arg<LLVM_AnyPointer,"",[MemWrite]>:$dst, 183 Arg<LLVM_AnyPointer,"",[MemRead]>:$src, 184 AnySignlessInteger:$len, I1Attr:$isVolatile); 185 // Append the alias attributes defined by LLVM_IntrOpBase. 186 let arguments = !con(args, aliasAttrs); 187 let builders = [ 188 OpBuilder<(ins "Value":$dst, "Value":$src, "Value":$len, 189 "bool":$isVolatile), [{ 190 build($_builder, $_state, dst, src, len, 191 $_builder.getBoolAttr(isVolatile)); 192 }]>, 193 OpBuilder<(ins "Value":$dst, "Value":$src, "Value":$len, 194 "IntegerAttr":$isVolatile), [{ 195 build($_builder, $_state, dst, src, len, isVolatile, 196 /*access_groups=*/nullptr, /*alias_scopes=*/nullptr, 197 /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr); 198 }]> 199 ]; 200} 201 202def LLVM_MemcpyOp : LLVM_MemcpyIntrOpBase<"memcpy">; 203def LLVM_MemmoveOp : LLVM_MemcpyIntrOpBase<"memmove">; 204 205def LLVM_MemcpyInlineOp : 206 LLVM_ZeroResultIntrOp<"memcpy.inline", [0, 1, 2], 207 [DeclareOpInterfaceMethods<PromotableMemOpInterface>, 208 DeclareOpInterfaceMethods<DestructurableAccessorOpInterface>, 209 DeclareOpInterfaceMethods<SafeMemorySlotAccessOpInterface>], 210 /*requiresAccessGroup=*/1, /*requiresAliasAnalysis=*/1, 211 /*requiresOpBundles=*/0, /*immArgPositions=*/[2, 3], 212 /*immArgAttrNames=*/["len", "isVolatile"]> { 213 dag args = (ins Arg<LLVM_AnyPointer,"",[MemWrite]>:$dst, 214 Arg<LLVM_AnyPointer,"",[MemRead]>:$src, 215 APIntAttr:$len, I1Attr:$isVolatile); 216 // Append the alias attributes defined by LLVM_IntrOpBase. 217 let arguments = !con(args, aliasAttrs); 218 let builders = [ 219 OpBuilder<(ins "Value":$dst, "Value":$src, "IntegerAttr":$len, 220 "bool":$isVolatile), [{ 221 build($_builder, $_state, dst, src, len, 222 $_builder.getBoolAttr(isVolatile)); 223 }]>, 224 OpBuilder<(ins "Value":$dst, "Value":$src, "IntegerAttr":$len, 225 "IntegerAttr":$isVolatile), [{ 226 build($_builder, $_state, dst, src, len, isVolatile, 227 /*access_groups=*/nullptr, /*alias_scopes=*/nullptr, 228 /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr); 229 }]> 230 ]; 231} 232 233def LLVM_MemsetOp : LLVM_ZeroResultIntrOp<"memset", [0, 2], 234 [DeclareOpInterfaceMethods<PromotableMemOpInterface>, 235 DeclareOpInterfaceMethods<DestructurableAccessorOpInterface>, 236 DeclareOpInterfaceMethods<SafeMemorySlotAccessOpInterface>], 237 /*requiresAccessGroup=*/1, /*requiresAliasAnalysis=*/1, 238 /*requiresOpBundles=*/0, /*immArgPositions=*/[3], 239 /*immArgAttrNames=*/["isVolatile"]> { 240 dag args = (ins Arg<LLVM_AnyPointer,"",[MemWrite]>:$dst, 241 I8:$val, AnySignlessInteger:$len, I1Attr:$isVolatile); 242 // Append the alias attributes defined by LLVM_IntrOpBase. 243 let arguments = !con(args, aliasAttrs); 244 let builders = [ 245 OpBuilder<(ins "Value":$dst, "Value":$val, "Value":$len, 246 "bool":$isVolatile), [{ 247 build($_builder, $_state, dst, val, len, 248 $_builder.getBoolAttr(isVolatile)); 249 }]>, 250 OpBuilder<(ins "Value":$dst, "Value":$val, "Value":$len, 251 "IntegerAttr":$isVolatile), [{ 252 build($_builder, $_state, dst, val, len, isVolatile, 253 /*access_groups=*/nullptr, /*alias_scopes=*/nullptr, 254 /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr); 255 }]> 256 ]; 257} 258 259def LLVM_MemsetInlineOp : LLVM_ZeroResultIntrOp<"memset.inline", [0, 2], 260 [DeclareOpInterfaceMethods<PromotableMemOpInterface>, 261 DeclareOpInterfaceMethods<DestructurableAccessorOpInterface>, 262 DeclareOpInterfaceMethods<SafeMemorySlotAccessOpInterface>], 263 /*requiresAccessGroup=*/1, /*requiresAliasAnalysis=*/1, 264 /*requiresOpBundles=*/0, /*immArgPositions=*/[2, 3], 265 /*immArgAttrNames=*/["len", "isVolatile"]> { 266 dag args = (ins Arg<LLVM_AnyPointer,"",[MemWrite]>:$dst, 267 I8:$val, APIntAttr:$len, I1Attr:$isVolatile); 268 // Append the alias attributes defined by LLVM_IntrOpBase. 269 let arguments = !con(args, aliasAttrs); 270 let builders = [ 271 OpBuilder<(ins "Value":$dst, "Value":$val, "IntegerAttr":$len, 272 "bool":$isVolatile), [{ 273 build($_builder, $_state, dst, val, len, 274 $_builder.getBoolAttr(isVolatile)); 275 }]>, 276 OpBuilder<(ins "Value":$dst, "Value":$val, "IntegerAttr":$len, 277 "IntegerAttr":$isVolatile), [{ 278 build($_builder, $_state, dst, val, len, isVolatile, 279 /*access_groups=*/nullptr, /*alias_scopes=*/nullptr, 280 /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr); 281 }]> 282 ]; 283} 284 285def LLVM_NoAliasScopeDeclOp 286 : LLVM_ZeroResultIntrOp<"experimental.noalias.scope.decl"> { 287 let arguments = (ins LLVM_AliasScopeAttr:$scope); 288 string llvmBuilder = [{ 289 // Wrap the scope argument into a list since the LLVM IR intrinsic takes 290 // a list containing exactly one scope rather than a scope itself. 291 llvm::MDNode* node = moduleTranslation.getOrCreateAliasScopes({$scope}); 292 builder.CreateNoAliasScopeDeclaration(node); 293 }]; 294 string mlirBuilder = [{ 295 FailureOr<SmallVector<LLVM::AliasScopeAttr>> scopeAttrs = 296 moduleImport.matchAliasScopeAttrs(llvmOperands[0]); 297 // Drop the intrinsic if the alias scope translation fails since the scope 298 // is not used by an aliasing operation, such as a load or store, that is 299 // used to convert the alias scope metadata. 300 if (failed(scopeAttrs)) 301 return success(); 302 if (scopeAttrs->size() != 1) 303 return failure(); 304 $_op = $_builder.create<LLVM::NoAliasScopeDeclOp>( 305 $_location, (*scopeAttrs)[0]); 306 }]; 307 let assemblyFormat = "$scope attr-dict"; 308} 309 310// 311// Memory marker intrinsics. 312// 313 314/// Base operation for lifetime markers. The LLVM intrinsics require the size 315/// operand to be an immediate. In MLIR it is encoded as an attribute. 316class LLVM_LifetimeBaseOp<string opName> : LLVM_ZeroResultIntrOp<opName, [1], 317 [DeclareOpInterfaceMethods<PromotableOpInterface>], 318 /*requiresAccessGroup=*/0, /*requiresAliasAnalysis=*/0, 319 /*requiresOpBundles=*/0, /*immArgPositions=*/[0], 320 /*immArgAttrNames=*/["size"]> { 321 let arguments = (ins I64Attr:$size, LLVM_AnyPointer:$ptr); 322 let assemblyFormat = "$size `,` $ptr attr-dict `:` qualified(type($ptr))"; 323} 324 325def LLVM_LifetimeStartOp : LLVM_LifetimeBaseOp<"lifetime.start">; 326def LLVM_LifetimeEndOp : LLVM_LifetimeBaseOp<"lifetime.end">; 327 328def LLVM_InvariantStartOp : LLVM_OneResultIntrOp<"invariant.start", [], [1], 329 [DeclareOpInterfaceMethods<PromotableOpInterface>], 330 /*requiresFastmath=*/0, /*immArgPositions=*/[0], 331 /*immArgAttrNames=*/["size"]> { 332 let arguments = (ins I64Attr:$size, LLVM_AnyPointer:$ptr); 333 let results = (outs LLVM_DefaultPointer:$res); 334 let assemblyFormat = "$size `,` $ptr attr-dict `:` qualified(type($ptr))"; 335} 336 337def LLVM_InvariantEndOp : LLVM_ZeroResultIntrOp<"invariant.end", [2], 338 [DeclareOpInterfaceMethods<PromotableOpInterface>], 339 /*requiresAccessGroup=*/0, /*requiresAliasAnalysis=*/0, 340 /*requiresOpBundles=*/0, /*immArgPositions=*/[1], 341 /*immArgAttrNames=*/["size"]> { 342 let arguments = (ins LLVM_DefaultPointer:$start, 343 I64Attr:$size, 344 LLVM_AnyPointer:$ptr); 345 let assemblyFormat = "$start `,` $size `,` $ptr attr-dict `:` " 346 "qualified(type($ptr))"; 347} 348 349def LLVM_LaunderInvariantGroupOp 350 : LLVM_OneResultIntrOp<"launder.invariant.group", [], [0], 351 [DeclareOpInterfaceMethods<PromotableOpInterface>, 352 SameOperandsAndResultType]> { 353 let arguments = (ins LLVM_AnyPointer:$ptr); 354 let results = (outs LLVM_AnyPointer:$res); 355 let assemblyFormat = "$ptr attr-dict `:` qualified(type($ptr))"; 356} 357 358def LLVM_StripInvariantGroupOp 359 : LLVM_OneResultIntrOp<"strip.invariant.group", [], [0], 360 [DeclareOpInterfaceMethods<PromotableOpInterface>, 361 SameOperandsAndResultType]> { 362 let arguments = (ins LLVM_AnyPointer:$ptr); 363 let results = (outs LLVM_AnyPointer:$res); 364 let assemblyFormat = "$ptr attr-dict `:` qualified(type($ptr))"; 365} 366 367// Constrained Floating-Point Intrinsics. 368 369class LLVM_ConstrainedIntr<string mnem, int numArgs, 370 bit overloadedResult, list<int> overloadedOperands, 371 bit hasRoundingMode> 372 : LLVM_OneResultIntrOp<"experimental.constrained." # mnem, 373 /*overloadedResults=*/ 374 !cond(!gt(overloadedResult, 0) : [0], 375 true : []), 376 overloadedOperands, 377 /*traits=*/[Pure, DeclareOpInterfaceMethods<FPExceptionBehaviorOpInterface>] 378 # !cond( 379 !gt(hasRoundingMode, 0) : [DeclareOpInterfaceMethods<RoundingModeOpInterface>], 380 true : []), 381 /*requiresFastmath=*/0, 382 /*immArgPositions=*/[], 383 /*immArgAttrNames=*/[]> { 384 dag regularArgs = !dag(ins, !listsplat(LLVM_Type, numArgs), !foreach(i, !range(numArgs), "arg_" #i)); 385 dag attrArgs = !con(!cond(!gt(hasRoundingMode, 0) : (ins ValidRoundingModeAttr:$roundingmode), 386 true : (ins)), 387 (ins FPExceptionBehaviorAttr:$fpExceptionBehavior)); 388 let arguments = !con(regularArgs, attrArgs); 389 let llvmBuilder = [{ 390 SmallVector<llvm::Value *> args = 391 moduleTranslation.lookupValues(opInst.getOperands()); 392 SmallVector<llvm::Type *> overloadedTypes; }] # 393 !cond(!gt(overloadedResult, 0) : [{ 394 // Take into account overloaded result type. 395 overloadedTypes.push_back($_resultType); }], 396 // No overloaded result type. 397 true : "") # [{ 398 llvm::transform(ArrayRef<unsigned>}] # overloadedOperandsCpp # [{, 399 std::back_inserter(overloadedTypes), 400 [&args](unsigned index) { return args[index]->getType(); }); 401 llvm::Module *module = builder.GetInsertBlock()->getModule(); 402 llvm::Function *callee = 403 llvm::Intrinsic::getOrInsertDeclaration(module, 404 llvm::Intrinsic::experimental_constrained_}] # 405 mnem # [{, overloadedTypes); }] # 406 !cond(!gt(hasRoundingMode, 0) : [{ 407 // Get rounding mode using interface. 408 llvm::RoundingMode rounding = 409 moduleTranslation.translateRoundingMode($roundingmode); }], 410 true : [{ 411 // No rounding mode. 412 std::optional<llvm::RoundingMode> rounding; }]) # [{ 413 llvm::fp::ExceptionBehavior except = 414 moduleTranslation.translateFPExceptionBehavior($fpExceptionBehavior); 415 $res = builder.CreateConstrainedFPCall(callee, args, "", rounding, except); 416 }]; 417 let mlirBuilder = [{ 418 SmallVector<Value> mlirOperands; 419 SmallVector<NamedAttribute> mlirAttrs; 420 if (failed(moduleImport.convertIntrinsicArguments( 421 llvmOperands.take_front( }] # numArgs # [{), {}, false, 422 {}, {}, mlirOperands, mlirAttrs))) { 423 return failure(); 424 } 425 426 FPExceptionBehaviorAttr fpExceptionBehaviorAttr = 427 $_fpExceptionBehavior_attr($fpExceptionBehavior); 428 mlirAttrs.push_back( 429 $_builder.getNamedAttr( 430 $_qualCppClassName::getFPExceptionBehaviorAttrName(), 431 fpExceptionBehaviorAttr)); }] # 432 !cond(!gt(hasRoundingMode, 0) : [{ 433 RoundingModeAttr roundingModeAttr = $_roundingMode_attr($roundingmode); 434 mlirAttrs.push_back( 435 $_builder.getNamedAttr($_qualCppClassName::getRoundingModeAttrName(), 436 roundingModeAttr)); 437 }], true : "") # [{ 438 $res = $_builder.create<$_qualCppClassName>($_location, 439 $_resultType, mlirOperands, mlirAttrs); 440 }]; 441} 442 443def LLVM_ConstrainedFPTruncIntr 444 : LLVM_ConstrainedIntr<"fptrunc", /*numArgs=*/1, 445 /*overloadedResult=*/1, /*overloadedOperands=*/[0], 446 /*hasRoundingMode=*/1> { 447 let assemblyFormat = [{ 448 $arg_0 $roundingmode $fpExceptionBehavior attr-dict `:` type($arg_0) `to` type(results) 449 }]; 450} 451 452// Intrinsics with multiple returns. 453 454class LLVM_ArithWithOverflowOp<string mnem> 455 : LLVM_IntrOp<mnem, [0], [], [Pure, SameOperandsElementType], 2>, 456 Arguments<(ins LLVM_ScalarOrVectorOf<AnySignlessInteger>, 457 LLVM_ScalarOrVectorOf<AnySignlessInteger>)>; 458 459def LLVM_SAddWithOverflowOp : LLVM_ArithWithOverflowOp<"sadd.with.overflow">; 460def LLVM_UAddWithOverflowOp : LLVM_ArithWithOverflowOp<"uadd.with.overflow">; 461def LLVM_SSubWithOverflowOp : LLVM_ArithWithOverflowOp<"ssub.with.overflow">; 462def LLVM_USubWithOverflowOp : LLVM_ArithWithOverflowOp<"usub.with.overflow">; 463def LLVM_SMulWithOverflowOp : LLVM_ArithWithOverflowOp<"smul.with.overflow">; 464def LLVM_UMulWithOverflowOp : LLVM_ArithWithOverflowOp<"umul.with.overflow">; 465 466// 467// Saturation Arithmetic Intrinsics. 468// 469 470def LLVM_SAddSat : LLVM_BinarySameArgsIntrOpI<"sadd.sat">; 471def LLVM_UAddSat : LLVM_BinarySameArgsIntrOpI<"uadd.sat">; 472def LLVM_SSubSat : LLVM_BinarySameArgsIntrOpI<"ssub.sat">; 473def LLVM_USubSat : LLVM_BinarySameArgsIntrOpI<"usub.sat">; 474def LLVM_SSHLSat : LLVM_BinarySameArgsIntrOpI<"sshl.sat">; 475def LLVM_USHLSat : LLVM_BinarySameArgsIntrOpI<"ushl.sat">; 476 477// 478// Optimization hint intrinsics. 479// 480 481def LLVM_AssumeOp 482 : LLVM_ZeroResultIntrOp<"assume", /*overloadedOperands=*/[], /*traits=*/[], 483 /*requiresAccessGroup=*/0, 484 /*requiresAliasAnalysis=*/0, 485 /*requiresOpBundles=*/1> { 486 dag args = (ins I1:$cond); 487 let arguments = !con(args, opBundleArgs); 488 489 let assemblyFormat = [{ 490 $cond 491 ( custom<OpBundles>($op_bundle_operands, type($op_bundle_operands), 492 $op_bundle_tags)^ )? 493 `:` type($cond) attr-dict 494 }]; 495 496 let builders = [ 497 OpBuilder<(ins "Value":$cond)>, 498 OpBuilder<(ins "Value":$cond, 499 "ArrayRef<llvm::OperandBundleDefT<Value>>":$opBundles)>, 500 OpBuilder<(ins "Value":$cond, "llvm::StringRef":$tag, "ValueRange":$args)>, 501 OpBuilder<(ins "Value":$cond, "AssumeAlignTag":$tag, "Value":$ptr, 502 "Value":$align)>, 503 OpBuilder<(ins "Value":$cond, "AssumeSeparateStorageTag":$tag, 504 "Value":$ptr1, "Value":$ptr2)> 505 ]; 506 507 let hasVerifier = 1; 508} 509 510def LLVM_SSACopyOp : LLVM_OneResultIntrOp<"ssa.copy", [], [0], 511 [Pure, SameOperandsAndResultType]> { 512 let arguments = (ins AnyType:$operand); 513 514 let assemblyFormat = "$operand attr-dict `:` type($operand)"; 515} 516 517def LLVM_IsConstantOp : LLVM_IntrOp<"is.constant", [], [0], [Pure], 1> { 518 let arguments = (ins LLVM_Type:$val); 519 let results = (outs I1:$res); 520} 521 522def LLVM_ExpectOp 523 : LLVM_OneResultIntrOp<"expect", [], [0], 524 [Pure, SameOperandsAndResultType]> { 525 let arguments = (ins AnySignlessInteger:$val, 526 AnySignlessInteger:$expected); 527 let assemblyFormat = "$val `,` $expected attr-dict `:` type($val)"; 528} 529 530def LLVM_ExpectWithProbabilityOp 531 : LLVM_OneResultIntrOp<"expect.with.probability", [], [0], 532 [Pure, AllTypesMatch<["val", "expected", "res"]>], 533 /*requiresFastmath=*/0, 534 /*immArgPositions=*/[2], /*immArgAttrNames=*/["prob"]> { 535 let arguments = (ins AnySignlessInteger:$val, 536 AnySignlessInteger:$expected, 537 F64Attr:$prob); 538 let assemblyFormat = "$val `,` $expected `,` $prob attr-dict `:` type($val)"; 539} 540 541def LLVM_ThreadlocalAddressOp : LLVM_OneResultIntrOp<"threadlocal.address", [], 542 [0], [Pure]> { 543 let arguments = (ins LLVM_AnyPointer:$global); 544} 545 546// 547// Coroutine intrinsics. 548// 549 550def LLVM_CoroIdOp : LLVM_IntrOp<"coro.id", [], [], [], 1> { 551 let arguments = (ins I32:$align, 552 LLVM_AnyPointer:$promise, 553 LLVM_AnyPointer:$coroaddr, 554 LLVM_AnyPointer:$fnaddrs); 555 let assemblyFormat = "$align `,` $promise `,` $coroaddr `,` $fnaddrs" 556 " attr-dict `:` functional-type(operands, results)"; 557} 558 559def LLVM_CoroBeginOp : LLVM_IntrOp<"coro.begin", [], [], [], 1> { 560 let arguments = (ins LLVM_TokenType:$token, 561 LLVM_AnyPointer:$mem); 562 let assemblyFormat = "$token `,` $mem attr-dict `:` functional-type(operands, results)"; 563} 564 565def LLVM_CoroSizeOp : LLVM_IntrOp<"coro.size", [0], [], [], 1> { 566 let assemblyFormat = "attr-dict `:` type($res)"; 567} 568 569def LLVM_CoroAlignOp : LLVM_IntrOp<"coro.align", [0], [], [], 1> { 570 let assemblyFormat = "attr-dict `:` type($res)"; 571} 572 573def LLVM_CoroSaveOp : LLVM_IntrOp<"coro.save", [], [], [], 1> { 574 let arguments = (ins LLVM_AnyPointer:$handle); 575 let assemblyFormat = "$handle attr-dict `:` functional-type(operands, results)"; 576} 577 578def LLVM_CoroSuspendOp : LLVM_IntrOp<"coro.suspend", [], [], [], 1> { 579 let arguments = (ins LLVM_TokenType:$save, 580 I1:$final); 581 let assemblyFormat = "$save `,` $final attr-dict `:` type($res)"; 582} 583 584def LLVM_CoroEndOp : LLVM_IntrOp<"coro.end", [], [], [], 1> { 585 let arguments = (ins LLVM_AnyPointer:$handle, 586 I1:$unwind, 587 LLVM_TokenType:$retvals); 588 let assemblyFormat = "$handle `,` $unwind `,` $retvals attr-dict `:` functional-type(operands, results)"; 589} 590 591def LLVM_CoroFreeOp : LLVM_IntrOp<"coro.free", [], [], [], 1> { 592 let arguments = (ins LLVM_TokenType:$id, 593 LLVM_AnyPointer:$handle); 594 let assemblyFormat = "$id `,` $handle attr-dict `:` functional-type(operands, results)"; 595} 596 597def LLVM_CoroResumeOp : LLVM_IntrOp<"coro.resume", [], [], [], 0> { 598 let arguments = (ins LLVM_AnyPointer:$handle); 599 let assemblyFormat = "$handle attr-dict `:` qualified(type($handle))"; 600} 601 602def LLVM_CoroPromiseOp : LLVM_IntrOp<"coro.promise", [], [], [], 1> { 603 let arguments = (ins LLVM_AnyPointer:$handle, 604 I32:$align, 605 I1:$from); 606 let results = (outs LLVM_AnyPointer:$res); 607 let assemblyFormat = "$handle `,` $align `,` $from attr-dict `:` functional-type(operands, results)"; 608} 609 610// 611// Debug function intrinsics. 612// 613 614class LLVM_DbgIntrOp<string name, string argName, list<Trait> traits = []> 615 : LLVM_IntrOp<name, [], [], traits, 0> { 616 let llvmBuilder = [{ 617 // Debug intrinsics without debug locations are invalid. 618 if(!builder.getCurrentDebugLocation()) 619 return success(); 620 llvm::Module *module = builder.GetInsertBlock()->getModule(); 621 llvm::LLVMContext &ctx = module->getContext(); 622 llvm::Function *fn = 623 llvm::Intrinsic::getOrInsertDeclaration(module, llvm::Intrinsic::}] 624 # !subst(".", "_", name) # [{); 625 builder.CreateCall(fn, { 626 llvm::MetadataAsValue::get(ctx, 627 llvm::ValueAsMetadata::get(moduleTranslation.lookupValue(opInst.getOperand(0)))), 628 llvm::MetadataAsValue::get(ctx, moduleTranslation.translateDebugInfo($varInfo)), 629 llvm::MetadataAsValue::get(ctx, moduleTranslation.translateExpression($locationExpr)), 630 }); 631 }]; 632 let mlirBuilder = [{ 633 // Add debug intrindic to the list of intrinsics that need to be converted once the 634 // full function was converted. 635 moduleImport.addDebugIntrinsic(inst); 636 return success(); 637 }]; 638 let assemblyFormat = [{ 639 qualified($varInfo) (qualified($locationExpr)^)? `=` $}] # argName # 640 [{ `:` qualified(type($}] # argName # [{)) attr-dict 641 }]; 642} 643 644def LLVM_DbgDeclareOp : LLVM_DbgIntrOp<"dbg.declare", "addr", [ 645 DeclareOpInterfaceMethods<PromotableOpInterface, [ 646 "requiresReplacedValues", "visitReplacedValues" 647 ]>]> { 648 let summary = "Describes how the address relates to a source language variable."; 649 let arguments = (ins 650 LLVM_AnyPointer:$addr, 651 LLVM_DILocalVariableAttr:$varInfo, 652 DefaultValuedAttr<LLVM_DIExpressionAttr, "{}">:$locationExpr 653 ); 654} 655 656def LLVM_DbgValueOp : LLVM_DbgIntrOp<"dbg.value", "value", 657 [DeclareOpInterfaceMethods<PromotableOpInterface>]> { 658 let summary = "Describes how the value relates to a source language variable."; 659 let arguments = (ins 660 LLVM_Type:$value, 661 LLVM_DILocalVariableAttr:$varInfo, 662 DefaultValuedAttr<LLVM_DIExpressionAttr, "{}">:$locationExpr 663 ); 664} 665 666def LLVM_DbgLabelOp : LLVM_IntrOp<"dbg.label", [], [], [], 0> { 667 let summary = "Relates the program to a debug information label."; 668 let arguments = (ins LLVM_DILabelAttr:$label); 669 let llvmBuilder = [{ 670 // Debug intrinsics without debug locations are invalid. 671 if(!builder.getCurrentDebugLocation()) 672 return success(); 673 llvm::Module *module = builder.GetInsertBlock()->getModule(); 674 llvm::LLVMContext &ctx = module->getContext(); 675 llvm::Function *fn = 676 llvm::Intrinsic::getOrInsertDeclaration(module, llvm::Intrinsic::dbg_label); 677 builder.CreateCall(fn, { 678 llvm::MetadataAsValue::get(ctx, moduleTranslation.translateDebugInfo($label)) 679 }); 680 }]; 681 let mlirBuilder = [{ 682 DILabelAttr labelAttr = $_label_attr($label); 683 // Drop the intrinsic if the label translation fails due to cylic metadata. 684 if (!labelAttr) 685 return success(); 686 $_op = $_builder.create<$_qualCppClassName>($_location, labelAttr); 687 }]; 688 let assemblyFormat = "$label attr-dict"; 689} 690 691// 692// Variadic function intrinsics. 693// 694 695def LLVM_VaStartOp : LLVM_ZeroResultIntrOp<"vastart", [0]>, 696 Arguments<(ins LLVM_AnyPointer:$arg_list)> { 697 let assemblyFormat = "$arg_list attr-dict `:` qualified(type($arg_list))"; 698 let summary = "Initializes `arg_list` for subsequent variadic argument extractions."; 699} 700 701def LLVM_VaCopyOp : LLVM_ZeroResultIntrOp<"vacopy", [0]>, 702 Arguments<(ins LLVM_AnyPointer:$dest_list, LLVM_AnyPointer:$src_list)> { 703 let assemblyFormat = "$src_list `to` $dest_list attr-dict `:` type(operands)"; 704 let summary = "Copies the current argument position from `src_list` to `dest_list`."; 705} 706 707def LLVM_VaEndOp : LLVM_ZeroResultIntrOp<"vaend", [0]>, 708 Arguments<(ins LLVM_AnyPointer:$arg_list)> { 709 let assemblyFormat = "$arg_list attr-dict `:` qualified(type($arg_list))"; 710 let summary = "Destroys `arg_list`, which has been initialized by `intr.vastart` or `intr.vacopy`."; 711} 712 713// 714// Exception handling intrinsics. 715// 716 717def LLVM_EhTypeidForOp : LLVM_OneResultIntrOp<"eh.typeid.for", [], [0]> { 718 let arguments = (ins LLVM_AnyPointer:$type_info); 719 let assemblyFormat = "$type_info attr-dict `:` functional-type(operands, results)"; 720} 721 722// 723// Stack save/restore intrinsics. 724// 725 726def LLVM_StackSaveOp : LLVM_OneResultIntrOp<"stacksave", [0]> { 727 let assemblyFormat = "attr-dict `:` qualified(type($res))"; 728} 729 730def LLVM_StackRestoreOp : LLVM_ZeroResultIntrOp<"stackrestore", [0]> { 731 let arguments = (ins LLVM_AnyPointer:$ptr); 732 let assemblyFormat = "$ptr attr-dict `:` qualified(type($ptr))"; 733} 734 735// 736// Vector Reductions. 737// 738 739// LLVM vector reduction over a single vector. 740class LLVM_VecReductionBase<string mnem, Type element, bit requiresFastmath=0> 741 : LLVM_OneResultIntrOp<"vector.reduce." # mnem, [], [0], 742 [Pure, SameOperandsAndResultElementType], 743 requiresFastmath> { 744 dag commonArgs = (ins LLVM_VectorOf<element>:$in); 745} 746 747class LLVM_VecReductionF<string mnem> 748 : LLVM_VecReductionBase<mnem, AnyFloat, /*requiresFastmath=*/1> { 749 dag fmfArg = ( 750 ins DefaultValuedAttr<LLVM_FastmathFlagsAttr, "{}">:$fastmathFlags); 751 let arguments = !con(commonArgs, fmfArg); 752 753 let assemblyFormat = "`(` operands `)` attr-dict `:` " 754 "functional-type(operands, results)"; 755} 756 757class LLVM_VecReductionI<string mnem> 758 : LLVM_VecReductionBase<mnem, AnySignlessInteger> { 759 let arguments = commonArgs; 760} 761 762// LLVM vector reduction over a single vector, with an initial value, 763// and with permission to reassociate the reduction operations. 764class LLVM_VecReductionAccBase<string mnem, Type element> 765 : LLVM_OneResultIntrOp</*mnem=*/"vector.reduce." # mnem, 766 /*overloadedResults=*/[], 767 /*overloadedOperands=*/[1], 768 /*traits=*/[Pure, SameOperandsAndResultElementType], 769 /*equiresFastmath=*/1>, 770 Arguments<(ins element:$start_value, 771 LLVM_VectorOf<element>:$input, 772 DefaultValuedAttr<LLVM_FastmathFlagsAttr, "{}">:$fastmathFlags)>; 773 774class LLVM_VecReductionAccF<string mnem> 775 : LLVM_VecReductionAccBase<mnem, AnyFloat>; 776 777def LLVM_vector_reduce_add : LLVM_VecReductionI<"add">; 778def LLVM_vector_reduce_and : LLVM_VecReductionI<"and">; 779def LLVM_vector_reduce_mul : LLVM_VecReductionI<"mul">; 780def LLVM_vector_reduce_or : LLVM_VecReductionI<"or">; 781def LLVM_vector_reduce_smax : LLVM_VecReductionI<"smax">; 782def LLVM_vector_reduce_smin : LLVM_VecReductionI<"smin">; 783def LLVM_vector_reduce_umax : LLVM_VecReductionI<"umax">; 784def LLVM_vector_reduce_umin : LLVM_VecReductionI<"umin">; 785def LLVM_vector_reduce_xor : LLVM_VecReductionI<"xor">; 786 787def LLVM_vector_reduce_fmax : LLVM_VecReductionF<"fmax">; 788def LLVM_vector_reduce_fmin : LLVM_VecReductionF<"fmin">; 789def LLVM_vector_reduce_fmaximum : LLVM_VecReductionF<"fmaximum">; 790def LLVM_vector_reduce_fminimum : LLVM_VecReductionF<"fminimum">; 791 792def LLVM_vector_reduce_fadd : LLVM_VecReductionAccF<"fadd">; 793def LLVM_vector_reduce_fmul : LLVM_VecReductionAccF<"fmul">; 794 795// 796// LLVM Matrix operations. 797// 798 799/// Create a column major, strided 2-D matrix load, as specified in the LLVM 800/// MatrixBuilder. 801/// data - Start address of the matrix read 802/// rows - Number of rows in matrix (must be a constant) 803/// isVolatile - True if the load operation is marked as volatile. 804/// columns - Number of columns in matrix (must be a constant) 805/// stride - Space between columns 806def LLVM_MatrixColumnMajorLoadOp : LLVM_OneResultIntrOp<"matrix.column.major.load"> { 807 let arguments = (ins LLVM_AnyPointer:$data, AnySignlessInteger:$stride, I1Attr:$isVolatile, 808 I32Attr:$rows, I32Attr:$columns); 809 let results = (outs LLVM_AnyVector:$res); 810 let builders = [LLVM_OneResultOpBuilder]; 811 let assemblyFormat = "$data `,` `<` `stride` `=` $stride `>` attr-dict" 812 "`:` type($res) `from` qualified(type($data)) `stride` type($stride)"; 813 814 string llvmBuilder = [{ 815 llvm::MatrixBuilder mb(builder); 816 const llvm::DataLayout &dl = 817 builder.GetInsertBlock()->getModule()->getDataLayout(); 818 llvm::Type *ElemTy = moduleTranslation.convertType( 819 getVectorElementType(op.getType())); 820 llvm::Align align = dl.getABITypeAlign(ElemTy); 821 $res = mb.CreateColumnMajorLoad( 822 ElemTy, $data, align, $stride, $isVolatile, $rows, 823 $columns); 824 }]; 825 string mlirBuilder = [{ 826 $res = $_builder.create<LLVM::MatrixColumnMajorLoadOp>( 827 $_location, $_resultType, $data, $stride, 828 $_int_attr($isVolatile), $_int_attr($rows), $_int_attr($columns)); 829 }]; 830} 831 832/// Create a column major, strided 2-D matrix store, as specified in the LLVM 833/// MatrixBuilder. 834/// matrix - Matrix to store 835/// ptr - Pointer to write back to 836/// isVolatile - True if the load operation is marked as volatile. 837/// rows - Number of rows in matrix (must be a constant) 838/// columns - Number of columns in matrix (must be a constant) 839/// stride - Space between columns 840def LLVM_MatrixColumnMajorStoreOp : LLVM_ZeroResultIntrOp<"matrix.column.major.store"> { 841 let arguments = (ins LLVM_AnyVector:$matrix, LLVM_AnyPointer:$data, 842 AnySignlessInteger:$stride, I1Attr:$isVolatile, I32Attr:$rows, 843 I32Attr:$columns); 844 let builders = [LLVM_VoidResultTypeOpBuilder, LLVM_ZeroResultOpBuilder]; 845 let assemblyFormat = "$matrix `,` $data `,` `<` `stride` `=` $stride `>` " 846 "attr-dict`:` type($matrix) `to` qualified(type($data)) `stride` type($stride)"; 847 848 string llvmBuilder = [{ 849 llvm::MatrixBuilder mb(builder); 850 const llvm::DataLayout &dl = 851 builder.GetInsertBlock()->getModule()->getDataLayout(); 852 Type elementType = getVectorElementType(op.getMatrix().getType()); 853 llvm::Align align = dl.getABITypeAlign( 854 moduleTranslation.convertType(elementType)); 855 mb.CreateColumnMajorStore( 856 $matrix, $data, align, $stride, $isVolatile, 857 $rows, $columns); 858 }]; 859 string mlirBuilder = [{ 860 $_op = $_builder.create<LLVM::MatrixColumnMajorStoreOp>( 861 $_location, $matrix, $data, $stride, 862 $_int_attr($isVolatile), $_int_attr($rows), $_int_attr($columns)); 863 }]; 864} 865 866/// Create a llvm.matrix.multiply call, multiplying 2-D matrices LHS and RHS, as 867/// specified in the LLVM MatrixBuilder. 868def LLVM_MatrixMultiplyOp : LLVM_OneResultIntrOp<"matrix.multiply"> { 869 let arguments = (ins LLVM_AnyVector:$lhs, LLVM_AnyVector:$rhs, I32Attr:$lhs_rows, 870 I32Attr:$lhs_columns, I32Attr:$rhs_columns); 871 let results = (outs LLVM_AnyVector:$res); 872 let builders = [LLVM_OneResultOpBuilder]; 873 let assemblyFormat = "$lhs `,` $rhs attr-dict " 874 "`:` `(` type($lhs) `,` type($rhs) `)` `->` type($res)"; 875 876 string llvmBuilder = [{ 877 llvm::MatrixBuilder mb(builder); 878 $res = mb.CreateMatrixMultiply( 879 $lhs, $rhs, $lhs_rows, $lhs_columns, 880 $rhs_columns); 881 }]; 882 string mlirBuilder = [{ 883 $res = $_builder.create<LLVM::MatrixMultiplyOp>( 884 $_location, $_resultType, $lhs, $rhs, 885 $_int_attr($lhs_rows), $_int_attr($lhs_columns), $_int_attr($rhs_columns)); 886 }]; 887} 888 889/// Create a llvm.matrix.transpose call, transposing a `rows` x `columns` 2-D 890/// `matrix`, as specified in the LLVM MatrixBuilder. 891def LLVM_MatrixTransposeOp : LLVM_OneResultIntrOp<"matrix.transpose"> { 892 let arguments = (ins LLVM_AnyVector:$matrix, I32Attr:$rows, I32Attr:$columns); 893 let results = (outs LLVM_AnyVector:$res); 894 let builders = [LLVM_OneResultOpBuilder]; 895 let assemblyFormat = "$matrix attr-dict `:` type($matrix) `into` type($res)"; 896 897 string llvmBuilder = [{ 898 llvm::MatrixBuilder mb(builder); 899 $res = mb.CreateMatrixTranspose( 900 $matrix, $rows, $columns); 901 }]; 902 string mlirBuilder = [{ 903 $res = $_builder.create<LLVM::MatrixTransposeOp>( 904 $_location, $_resultType, $matrix, 905 $_int_attr($rows), $_int_attr($columns)); 906 }]; 907} 908 909// 910// LLVM masked operations. 911// 912 913/// Create a llvm.get.active.lane.mask to set a mask up to a given position. 914def LLVM_GetActiveLaneMaskOp 915 : LLVM_OneResultIntrOp<"get.active.lane.mask", [0], [0], [Pure]> { 916 let arguments = (ins AnySignlessInteger:$base, AnySignlessInteger:$n); 917 let assemblyFormat = "$base `,` $n attr-dict `:` " 918 "type($base) `,` type($n) `to` type($res)"; 919} 920 921/// Create a call to Masked Load intrinsic. 922def LLVM_MaskedLoadOp : LLVM_OneResultIntrOp<"masked.load"> { 923 let arguments = (ins LLVM_AnyPointer:$data, LLVM_VectorOf<I1>:$mask, 924 Variadic<LLVM_AnyVector>:$pass_thru, I32Attr:$alignment, 925 UnitAttr:$nontemporal); 926 let results = (outs LLVM_AnyVector:$res); 927 let assemblyFormat = 928 "operands attr-dict `:` functional-type(operands, results)"; 929 930 string llvmBuilder = [{ 931 auto *inst = $pass_thru.empty() ? builder.CreateMaskedLoad( 932 $_resultType, $data, llvm::Align($alignment), $mask) : 933 builder.CreateMaskedLoad( 934 $_resultType, $data, llvm::Align($alignment), $mask, $pass_thru[0]); 935 $res = inst; 936 }] #setNonTemporalMetadataCode; 937 string mlirBuilder = [{ 938 auto *intrinInst = dyn_cast<llvm::IntrinsicInst>(inst); 939 bool nontemporal = intrinInst->hasMetadata(llvm::LLVMContext::MD_nontemporal); 940 $res = $_builder.create<LLVM::MaskedLoadOp>($_location, 941 $_resultType, $data, $mask, $pass_thru, $_int_attr($alignment), 942 nontemporal ? $_builder.getUnitAttr() : nullptr); 943 }]; 944 list<int> llvmArgIndices = [0, 2, 3, 1, -1]; 945} 946 947/// Create a call to Masked Store intrinsic. 948def LLVM_MaskedStoreOp : LLVM_ZeroResultIntrOp<"masked.store"> { 949 let arguments = (ins LLVM_AnyVector:$value, LLVM_AnyPointer:$data, 950 LLVM_VectorOf<I1>:$mask, I32Attr:$alignment); 951 let builders = [LLVM_VoidResultTypeOpBuilder, LLVM_ZeroResultOpBuilder]; 952 let assemblyFormat = "$value `,` $data `,` $mask attr-dict `:` " 953 "type($value) `,` type($mask) `into` qualified(type($data))"; 954 955 string llvmBuilder = [{ 956 builder.CreateMaskedStore( 957 $value, $data, llvm::Align($alignment), $mask); 958 }]; 959 string mlirBuilder = [{ 960 $_op = $_builder.create<LLVM::MaskedStoreOp>($_location, 961 $value, $data, $mask, $_int_attr($alignment)); 962 }]; 963 list<int> llvmArgIndices = [0, 1, 3, 2]; 964} 965 966/// Create a call to Masked Gather intrinsic. 967def LLVM_masked_gather : LLVM_OneResultIntrOp<"masked.gather"> { 968 let arguments = (ins LLVM_VectorOf<LLVM_AnyPointer>:$ptrs, 969 LLVM_VectorOf<I1>:$mask, Variadic<LLVM_AnyVector>:$pass_thru, 970 I32Attr:$alignment); 971 let results = (outs LLVM_AnyVector:$res); 972 let builders = [LLVM_OneResultOpBuilder]; 973 let assemblyFormat = 974 "operands attr-dict `:` functional-type(operands, results)"; 975 976 string llvmBuilder = [{ 977 $res = $pass_thru.empty() ? builder.CreateMaskedGather( 978 $_resultType, $ptrs, llvm::Align($alignment), $mask) : 979 builder.CreateMaskedGather( 980 $_resultType, $ptrs, llvm::Align($alignment), $mask, $pass_thru[0]); 981 }]; 982 string mlirBuilder = [{ 983 $res = $_builder.create<LLVM::masked_gather>($_location, 984 $_resultType, $ptrs, $mask, $pass_thru, $_int_attr($alignment)); 985 }]; 986 list<int> llvmArgIndices = [0, 2, 3, 1]; 987 988 let hasVerifier = 1; 989} 990 991/// Create a call to Masked Scatter intrinsic. 992def LLVM_masked_scatter : LLVM_ZeroResultIntrOp<"masked.scatter"> { 993 let arguments = (ins LLVM_AnyVector:$value, LLVM_VectorOf<LLVM_AnyPointer>:$ptrs, 994 LLVM_VectorOf<I1>:$mask, I32Attr:$alignment); 995 let builders = [LLVM_VoidResultTypeOpBuilder, LLVM_ZeroResultOpBuilder]; 996 let assemblyFormat = "$value `,` $ptrs `,` $mask attr-dict `:` " 997 "type($value) `,` type($mask) `into` type($ptrs)"; 998 999 string llvmBuilder = [{ 1000 builder.CreateMaskedScatter( 1001 $value, $ptrs, llvm::Align($alignment), $mask); 1002 }]; 1003 string mlirBuilder = [{ 1004 $_op = $_builder.create<LLVM::masked_scatter>($_location, 1005 $value, $ptrs, $mask, $_int_attr($alignment)); 1006 }]; 1007 list<int> llvmArgIndices = [0, 1, 3, 2]; 1008 1009 let hasVerifier = 1; 1010} 1011 1012/// Create a call to Masked Expand Load intrinsic. 1013def LLVM_masked_expandload : LLVM_IntrOp<"masked.expandload", [0], [], [], 1> { 1014 let arguments = (ins LLVM_AnyPointer, LLVM_VectorOf<I1>, LLVM_AnyVector); 1015} 1016 1017/// Create a call to Masked Compress Store intrinsic. 1018def LLVM_masked_compressstore 1019 : LLVM_IntrOp<"masked.compressstore", [], [0], [], 0> { 1020 let arguments = (ins LLVM_AnyVector, LLVM_AnyPointer, LLVM_VectorOf<I1>); 1021} 1022 1023// 1024// Annotate intrinsics. 1025// 1026 1027def LLVM_VarAnnotation 1028 : LLVM_ZeroResultIntrOp<"var.annotation", [0, 1], 1029 [AllTypesMatch<["annotation", "fileName", "attr"]>]> { 1030 let arguments = (ins LLVM_AnyPointer:$val, 1031 LLVM_AnyPointer:$annotation, 1032 LLVM_AnyPointer:$fileName, 1033 I32:$line, 1034 LLVM_AnyPointer:$attr); 1035} 1036 1037def LLVM_PtrAnnotation 1038 : LLVM_OneResultIntrOp<"ptr.annotation", [0], [2], 1039 [AllTypesMatch<["res", "ptr"]>, 1040 AllTypesMatch<["annotation", "fileName", "attr"]>]> { 1041 let arguments = (ins LLVM_AnyPointer:$ptr, 1042 LLVM_AnyPointer:$annotation, 1043 LLVM_AnyPointer:$fileName, 1044 I32:$line, 1045 LLVM_AnyPointer:$attr); 1046 let results = (outs LLVM_AnyPointer:$res); 1047} 1048 1049def LLVM_Annotation 1050 : LLVM_OneResultIntrOp<"annotation", [0], [2], 1051 [AllTypesMatch<["res", "integer"]>, 1052 AllTypesMatch<["annotation", "fileName"]>]> { 1053 let arguments = (ins AnySignlessInteger:$integer, 1054 LLVM_AnyPointer:$annotation, 1055 LLVM_AnyPointer:$fileName, 1056 I32:$line); 1057 let results = (outs AnySignlessInteger:$res); 1058} 1059 1060// 1061// Trap intrinsics. 1062// 1063 1064def LLVM_Trap : LLVM_ZeroResultIntrOp<"trap">; 1065 1066def LLVM_DebugTrap : LLVM_ZeroResultIntrOp<"debugtrap">; 1067 1068def LLVM_UBSanTrap : LLVM_ZeroResultIntrOp<"ubsantrap", 1069 /*overloadedOperands=*/[], /*traits=*/[], 1070 /*requiresAccessGroup=*/0, /*requiresAliasAnalysis=*/0, 1071 /*requiresOpBundles=*/0, /*immArgPositions=*/[0], 1072 /*immArgAttrNames=*/["failureKind"]> { 1073 let arguments = (ins I8Attr:$failureKind); 1074} 1075 1076/// Create a call to vscale intrinsic. 1077def LLVM_vscale : LLVM_IntrOp<"vscale", [0], [], [], 1>; 1078 1079/// Create a call to stepvector intrinsic. 1080def LLVM_StepVectorOp 1081 : LLVM_IntrOp<"stepvector", [0], [], [Pure], 1> { 1082 let arguments = (ins); 1083 let results = (outs LLVM_VectorOf<AnySignlessInteger>:$res); 1084 let assemblyFormat = "attr-dict `:` type($res)"; 1085} 1086 1087/// Create a call to vector.insert intrinsic 1088def LLVM_vector_insert 1089 : LLVM_OneResultIntrOp<"vector.insert", 1090 /*overloadedResults=*/[0], /*overloadedOperands=*/[1], 1091 /*traits=*/[Pure, AllTypesMatch<["dstvec", "res"]>, 1092 PredOpTrait<"vectors are not bigger than 2^17 bits.", And<[ 1093 CPred<"getSrcVectorBitWidth() <= 131072">, 1094 CPred<"getDstVectorBitWidth() <= 131072"> 1095 ]>>, 1096 PredOpTrait<"it is not inserting scalable into fixed-length vectors.", 1097 CPred<"!isScalableVectorType($srcvec.getType()) || " 1098 "isScalableVectorType($dstvec.getType())">>], 1099 /*requiresFastmath=*/0, 1100 /*immArgPositions=*/[2], /*immArgAttrNames=*/["pos"]> { 1101 let arguments = (ins LLVM_AnyVector:$dstvec, LLVM_AnyVector:$srcvec, 1102 I64Attr:$pos); 1103 let results = (outs LLVM_AnyVector:$res); 1104 let assemblyFormat = "$srcvec `,` $dstvec `[` $pos `]` attr-dict `:` " 1105 "type($srcvec) `into` type($res)"; 1106 let extraClassDeclaration = [{ 1107 uint64_t getVectorBitWidth(Type vector) { 1108 return getVectorNumElements(vector).getKnownMinValue() * 1109 getVectorElementType(vector).getIntOrFloatBitWidth(); 1110 } 1111 uint64_t getSrcVectorBitWidth() { 1112 return getVectorBitWidth(getSrcvec().getType()); 1113 } 1114 uint64_t getDstVectorBitWidth() { 1115 return getVectorBitWidth(getDstvec().getType()); 1116 } 1117 }]; 1118} 1119 1120/// Create a call to vector.extract intrinsic 1121def LLVM_vector_extract 1122 : LLVM_OneResultIntrOp<"vector.extract", 1123 /*overloadedResults=*/[0], /*overloadedOperands=*/[0], 1124 /*traits=*/[Pure, 1125 PredOpTrait<"vectors are not bigger than 2^17 bits.", And<[ 1126 CPred<"getSrcVectorBitWidth() <= 131072">, 1127 CPred<"getResVectorBitWidth() <= 131072"> 1128 ]>>, 1129 PredOpTrait<"it is not extracting scalable from fixed-length vectors.", 1130 CPred<"!isScalableVectorType($res.getType()) || " 1131 "isScalableVectorType($srcvec.getType())">>], 1132 /*requiresFastmath=*/0, 1133 /*immArgPositions=*/[1], /*immArgAttrNames=*/["pos"]> { 1134 let arguments = (ins LLVM_AnyVector:$srcvec, I64Attr:$pos); 1135 let results = (outs LLVM_AnyVector:$res); 1136 let assemblyFormat = "$srcvec `[` $pos `]` attr-dict `:` " 1137 "type($res) `from` type($srcvec)"; 1138 let extraClassDeclaration = [{ 1139 uint64_t getVectorBitWidth(Type vector) { 1140 return getVectorNumElements(vector).getKnownMinValue() * 1141 getVectorElementType(vector).getIntOrFloatBitWidth(); 1142 } 1143 uint64_t getSrcVectorBitWidth() { 1144 return getVectorBitWidth(getSrcvec().getType()); 1145 } 1146 uint64_t getResVectorBitWidth() { 1147 return getVectorBitWidth(getRes().getType()); 1148 } 1149 }]; 1150} 1151 1152def LLVM_vector_interleave2 1153 : LLVM_OneResultIntrOp<"vector.interleave2", 1154 /*overloadedResults=*/[0], /*overloadedOperands=*/[], 1155 /*traits=*/[ 1156 Pure, AllTypesMatch<["vec1", "vec2"]>, 1157 PredOpTrait< 1158 "result has twice as many elements as 'vec1'", 1159 And<[CPred<"getVectorNumElements($res.getType()) == " 1160 "getVectorNumElements($vec1.getType()) * 2">, 1161 CPred<"getVectorElementType($vec1.getType()) == " 1162 "getVectorElementType($res.getType())">]>>, 1163 ]>, 1164 Arguments<(ins LLVM_AnyVector:$vec1, LLVM_AnyVector:$vec2)>; 1165 1166def LLVM_vector_deinterleave2 1167 : LLVM_OneResultIntrOp<"vector.deinterleave2", 1168 /*overloadedResults=*/[], /*overloadedOperands=*/[0], 1169 /*traits=*/[Pure]>, 1170 Arguments<(ins LLVM_AnyVector:$vec)>; 1171 1172// 1173// LLVM Vector Predication operations. 1174// 1175 1176class LLVM_VPBinaryBase<string mnem, Type element> 1177 : LLVM_OneResultIntrOp<"vp." # mnem, [0], [], [Pure]>, 1178 Arguments<(ins LLVM_VectorOf<element>:$lhs, LLVM_VectorOf<element>:$rhs, 1179 LLVM_VectorOf<I1>:$mask, I32:$evl)>; 1180 1181class LLVM_VPBinaryI<string mnem> : LLVM_VPBinaryBase<mnem, AnySignlessInteger>; 1182 1183class LLVM_VPBinaryF<string mnem> : LLVM_VPBinaryBase<mnem, AnyFloat>; 1184 1185class LLVM_VPUnaryBase<string mnem, Type element> 1186 : LLVM_OneResultIntrOp<"vp." # mnem, [0], [], [Pure]>, 1187 Arguments<(ins LLVM_VectorOf<element>:$op, 1188 LLVM_VectorOf<I1>:$mask, I32:$evl)>; 1189 1190class LLVM_VPUnaryF<string mnem> : LLVM_VPUnaryBase<mnem, AnyFloat>; 1191 1192class LLVM_VPTernaryBase<string mnem, Type element> 1193 : LLVM_OneResultIntrOp<"vp." # mnem, [0], [], [Pure]>, 1194 Arguments<(ins LLVM_VectorOf<element>:$op1, LLVM_VectorOf<element>:$op2, 1195 LLVM_VectorOf<element>:$op3, LLVM_VectorOf<I1>:$mask, 1196 I32:$evl)>; 1197 1198class LLVM_VPTernaryF<string mnem> : LLVM_VPTernaryBase<mnem, AnyFloat>; 1199 1200class LLVM_VPReductionBase<string mnem, Type element> 1201 : LLVM_OneResultIntrOp<"vp.reduce." # mnem, [], [1], [Pure]>, 1202 Arguments<(ins element:$satrt_value, LLVM_VectorOf<element>:$val, 1203 LLVM_VectorOf<I1>:$mask, I32:$evl)>; 1204 1205class LLVM_VPReductionI<string mnem> : LLVM_VPReductionBase<mnem, AnySignlessInteger>; 1206 1207class LLVM_VPReductionF<string mnem> : LLVM_VPReductionBase<mnem, AnyFloat>; 1208 1209class LLVM_VPSelectBase<string mnem> 1210 : LLVM_OneResultIntrOp<"vp." # mnem, [], [1], [Pure]>, 1211 Arguments<(ins LLVM_VectorOf<I1>:$cond, LLVM_AnyVector:$true_val, 1212 LLVM_AnyVector:$false_val, I32:$evl)>; 1213 1214class LLVM_VPCastBase<string mnem, Type element> 1215 : LLVM_OneResultIntrOp<"vp." # mnem, [0], [0], [Pure]>, 1216 Arguments<(ins LLVM_VectorOf<element>:$src, 1217 LLVM_VectorOf<I1>:$mask, I32:$evl)>; 1218 1219class LLVM_VPCastI<string mnem> : LLVM_VPCastBase<mnem, AnySignlessInteger>; 1220 1221class LLVM_VPCastF<string mnem> : LLVM_VPCastBase<mnem, AnyFloat>; 1222 1223class LLVM_VPCastPtr<string mnem> : LLVM_VPCastBase<mnem, LLVM_AnyPointer>; 1224 1225// Integer Binary 1226def LLVM_VPAddOp : LLVM_VPBinaryI<"add">; 1227def LLVM_VPSubOp : LLVM_VPBinaryI<"sub">; 1228def LLVM_VPMulOp : LLVM_VPBinaryI<"mul">; 1229def LLVM_VPSDivOp : LLVM_VPBinaryI<"sdiv">; 1230def LLVM_VPUDivOp : LLVM_VPBinaryI<"udiv">; 1231def LLVM_VPSRemOp : LLVM_VPBinaryI<"srem">; 1232def LLVM_VPURemOp : LLVM_VPBinaryI<"urem">; 1233def LLVM_VPAShrOp : LLVM_VPBinaryI<"ashr">; 1234def LLVM_VPLShrOp : LLVM_VPBinaryI<"lshr">; 1235def LLVM_VPShlOp : LLVM_VPBinaryI<"shl">; 1236def LLVM_VPOrOp : LLVM_VPBinaryI<"or">; 1237def LLVM_VPAndOp : LLVM_VPBinaryI<"and">; 1238def LLVM_VPXorOp : LLVM_VPBinaryI<"xor">; 1239def LLVM_VPSMaxOp : LLVM_VPBinaryI<"smax">; 1240def LLVM_VPSMinOp : LLVM_VPBinaryI<"smin">; 1241def LLVM_VPUMaxOp : LLVM_VPBinaryI<"umax">; 1242def LLVM_VPUMinOp : LLVM_VPBinaryI<"umin">; 1243 1244// Float Binary 1245def LLVM_VPFAddOp : LLVM_VPBinaryF<"fadd">; 1246def LLVM_VPFSubOp : LLVM_VPBinaryF<"fsub">; 1247def LLVM_VPFMulOp : LLVM_VPBinaryF<"fmul">; 1248def LLVM_VPFDivOp : LLVM_VPBinaryF<"fdiv">; 1249def LLVM_VPFRemOp : LLVM_VPBinaryF<"frem">; 1250 1251// Float Unary 1252def LLVM_VPFNegOp : LLVM_VPUnaryF<"fneg">; 1253 1254// Float Ternary 1255def LLVM_VPFMulAddOp : LLVM_VPTernaryF<"fmuladd">; 1256def LLVM_VPFmaOp : LLVM_VPTernaryF<"fma">; 1257 1258// Integer Reduction 1259def LLVM_VPReduceAddOp : LLVM_VPReductionI<"add">; 1260def LLVM_VPReduceMulOp : LLVM_VPReductionI<"mul">; 1261def LLVM_VPReduceAndOp : LLVM_VPReductionI<"and">; 1262def LLVM_VPReduceOrOp : LLVM_VPReductionI<"or">; 1263def LLVM_VPReduceXorOp : LLVM_VPReductionI<"xor">; 1264def LLVM_VPReduceSMaxOp : LLVM_VPReductionI<"smax">; 1265def LLVM_VPReduceSMinOp : LLVM_VPReductionI<"smin">; 1266def LLVM_VPReduceUMaxOp : LLVM_VPReductionI<"umax">; 1267def LLVM_VPReduceUMinOp : LLVM_VPReductionI<"umin">; 1268 1269// Float Reduction 1270def LLVM_VPReduceFAddOp : LLVM_VPReductionF<"fadd">; 1271def LLVM_VPReduceFMulOp : LLVM_VPReductionF<"fmul">; 1272def LLVM_VPReduceFMaxOp : LLVM_VPReductionF<"fmax">; 1273def LLVM_VPReduceFMinOp : LLVM_VPReductionF<"fmin">; 1274 1275def LLVM_VPSelectMinOp : LLVM_VPSelectBase<"select">; 1276def LLVM_VPMergeMinOp : LLVM_VPSelectBase<"merge">; 1277 1278// Load/store 1279def LLVM_VPLoadOp 1280 : LLVM_OneResultIntrOp<"vp.load", [0], [0], []>, 1281 Arguments<(ins LLVM_AnyPointer:$ptr, 1282 LLVM_VectorOf<I1>:$mask, I32:$evl)>; 1283 1284def LLVM_VPStoreOp 1285 : LLVM_ZeroResultIntrOp<"vp.store", [0, 1], []>, 1286 Arguments<(ins LLVM_AnyVector:$val, 1287 LLVM_AnyPointer:$ptr, 1288 LLVM_VectorOf<I1>:$mask, I32:$evl)>; 1289 1290// Strided load/store 1291def LLVM_VPStridedLoadOp 1292 : LLVM_OneResultIntrOp<"experimental.vp.strided.load", [0], [0, 1], []>, 1293 Arguments<(ins LLVM_AnyPointer:$ptr, AnySignlessInteger:$stride, 1294 LLVM_VectorOf<I1>:$mask, I32:$evl)>; 1295 1296def LLVM_VPStridedStoreOp 1297 : LLVM_ZeroResultIntrOp<"experimental.vp.strided.store",[0, 1, 2], []>, 1298 Arguments<(ins LLVM_AnyVector:$val, LLVM_AnyPointer:$ptr, 1299 AnySignlessInteger:$stride, LLVM_VectorOf<I1>:$mask, I32:$evl)>; 1300 1301def LLVM_VPTruncOp : LLVM_VPCastI<"trunc">; 1302def LLVM_VPZExtOp : LLVM_VPCastI<"zext">; 1303def LLVM_VPSExtOp : LLVM_VPCastI<"sext">; 1304 1305def LLVM_VPFPTruncOp : LLVM_VPCastF<"fptrunc">; 1306def LLVM_VPFPExtOp : LLVM_VPCastF<"fpext">; 1307 1308def LLVM_VPFPToUIOp : LLVM_VPCastF<"fptoui">; 1309def LLVM_VPFPToSIOp : LLVM_VPCastF<"fptosi">; 1310 1311def LLVM_VPUIToFPOp : LLVM_VPCastI<"uitofp">; 1312def LLVM_VPSIToFPOp : LLVM_VPCastI<"sitofp">; 1313 1314def LLVM_VPPtrToIntOp : LLVM_VPCastPtr<"ptrtoint">; 1315def LLVM_VPIntToPtrOp : LLVM_VPCastI<"inttoptr">; 1316 1317#endif // LLVM_INTRINSIC_OP 1318