diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td @@ -10,32 +10,47 @@ #define LLVMIR_ATTRDEFS include "mlir/IR/AttrTypeBase.td" +include "mlir/Dialect/LLVMIR/LLVMEnums.td" include "mlir/Dialect/LLVMIR/LLVMOpBase.td" // All of the attributes will extend this class. -class LLVM_Attr : AttrDef; - -// Attribute definition for the LLVM Linkage enum. -def LinkageAttr : LLVM_Attr<"Linkage"> { - let mnemonic = "linkage"; - let parameters = (ins - "linkage::Linkage":$linkage - ); - let assemblyFormat = "`<` $linkage `>`"; +class LLVM_Attr + : AttrDef { + let mnemonic = attrMnemonic; } -// Attribute definition for the LLVM Linkage enum. -def CConvAttr : LLVM_Attr<"CConv"> { - let mnemonic = "cconv"; - let parameters = (ins - "CConv":$CallingConv - ); +//===----------------------------------------------------------------------===// +// CConvAttr +//===----------------------------------------------------------------------===// + +def CConvAttr : LLVM_Attr<"CConv", "cconv"> { + let parameters = (ins "CConv":$CallingConv); let assemblyFormat = "`<` $CallingConv `>`"; } -def LoopOptionsAttr : LLVM_Attr<"LoopOptions"> { - let mnemonic = "loopopts"; +//===----------------------------------------------------------------------===// +// FastmathFlagsAttr +//===----------------------------------------------------------------------===// + +def LLVM_FastmathFlagsAttr : + EnumAttr { + let assemblyFormat = "`<` $value `>`"; +} + +//===----------------------------------------------------------------------===// +// LinkageAttr +//===----------------------------------------------------------------------===// + +def LinkageAttr : LLVM_Attr<"Linkage", "linkage"> { + let parameters = (ins "linkage::Linkage":$linkage); + let assemblyFormat = "`<` $linkage `>`"; +} + +//===----------------------------------------------------------------------===// +// LoopOptionsAttr +//===----------------------------------------------------------------------===// +def LoopOptionsAttr : LLVM_Attr<"LoopOptions", "loopopts"> { let description = [{ This attributes encapsulates "loop options". It is means to decorate branches that are "latches" (loop backedges) and maps to the `!llvm.loop` @@ -45,7 +60,6 @@ example). }]; - // List of type parameters. let parameters = (ins ArrayRefParameter<"std::pair", "">:$options ); diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h @@ -0,0 +1,89 @@ +//===- LLVMDialect.h - MLIR LLVM IR dialect ---------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the LLVM IR dialect in MLIR, containing LLVM operations and +// LLVM type system. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_LLVMIR_LLVMATTRS_H_ +#define MLIR_DIALECT_LLVMIR_LLVMATTRS_H_ + +#include "mlir/Dialect/LLVMIR/LLVMTypes.h" +#include "mlir/IR/OpImplementation.h" + +#include "mlir/Dialect/LLVMIR/LLVMOpsEnums.h.inc" + +namespace mlir { +namespace LLVM { +class LoopOptionsAttrBuilder; + +// Inline the LLVM generated Linkage enum and utility. +// This is only necessary to isolate the "enum generated code" from the +// attribute definition itself. +// TODO: this shouldn't be needed after we unify the attribute generation, i.e. +// --gen-attr-* and --gen-attrdef-*. +using cconv::CConv; +using linkage::Linkage; +} // namespace LLVM +} // namespace mlir + +#define GET_ATTRDEF_CLASSES +#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.h.inc" + +namespace mlir { +namespace LLVM { + +/// Builder class for LoopOptionsAttr. This helper class allows to progressively +/// build a LoopOptionsAttr one option at a time, and pay the price of attribute +/// creation once all the options are in place. +class LoopOptionsAttrBuilder { +public: + /// Construct a empty builder. + LoopOptionsAttrBuilder() = default; + + /// Construct a builder with an initial list of options from an existing + /// LoopOptionsAttr. + LoopOptionsAttrBuilder(LoopOptionsAttr attr); + + /// Set the `disable_licm` option to the provided value. If no value + /// is provided the option is deleted. + LoopOptionsAttrBuilder &setDisableLICM(Optional value); + + /// Set the `interleave_count` option to the provided value. If no value + /// is provided the option is deleted. + LoopOptionsAttrBuilder &setInterleaveCount(Optional count); + + /// Set the `disable_unroll` option to the provided value. If no value + /// is provided the option is deleted. + LoopOptionsAttrBuilder &setDisableUnroll(Optional value); + + /// Set the `disable_pipeline` option to the provided value. If no value + /// is provided the option is deleted. + LoopOptionsAttrBuilder &setDisablePipeline(Optional value); + + /// Set the `pipeline_initiation_interval` option to the provided value. + /// If no value is provided the option is deleted. + LoopOptionsAttrBuilder & + setPipelineInitiationInterval(Optional count); + + /// Returns true if any option has been set. + bool empty() { return options.empty(); } + +private: + template + LoopOptionsAttrBuilder &setOption(LoopOptionCase tag, Optional value); + + friend class LoopOptionsAttr; + SmallVector options; +}; + +} // namespace LLVM +} // namespace mlir + +#endif // MLIR_DIALECT_LLVMIR_LLVMATTRS_H_ diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h @@ -14,6 +14,7 @@ #ifndef MLIR_DIALECT_LLVMIR_LLVMDIALECT_H_ #define MLIR_DIALECT_LLVMIR_LLVMDIALECT_H_ +#include "mlir/Dialect/LLVMIR/LLVMAttrs.h" #include "mlir/Dialect/LLVMIR/LLVMTypes.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/Dialect.h" @@ -33,20 +34,6 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" -#include "mlir/Dialect/LLVMIR/LLVMOpsEnums.h.inc" - -namespace mlir { -namespace LLVM { -// Inline the LLVM generated Linkage enum and utility. -// This is only necessary to isolate the "enum generated code" from the -// attribute definition itself. -// TODO: this shouldn't be needed after we unify the attribute generation, i.e. -// --gen-attr-* and --gen-attrdef-*. -using cconv::CConv; -using linkage::Linkage; -} // namespace LLVM -} // namespace mlir - #include "mlir/Dialect/LLVMIR/LLVMOpsInterfaces.h.inc" namespace llvm { @@ -70,9 +57,6 @@ } // namespace LLVM } // namespace mlir -#define GET_ATTRDEF_CLASSES -#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.h.inc" - namespace mlir { namespace LLVM { template @@ -232,50 +216,6 @@ /// function confirms that the Operation has the desired properties. bool satisfiesLLVMModule(Operation *op); -/// Builder class for LoopOptionsAttr. This helper class allows to progressively -/// build a LoopOptionsAttr one option at a time, and pay the price of attribute -/// creation once all the options are in place. -class LoopOptionsAttrBuilder { -public: - /// Construct a empty builder. - LoopOptionsAttrBuilder() = default; - - /// Construct a builder with an initial list of options from an existing - /// LoopOptionsAttr. - LoopOptionsAttrBuilder(LoopOptionsAttr attr); - - /// Set the `disable_licm` option to the provided value. If no value - /// is provided the option is deleted. - LoopOptionsAttrBuilder &setDisableLICM(Optional value); - - /// Set the `interleave_count` option to the provided value. If no value - /// is provided the option is deleted. - LoopOptionsAttrBuilder &setInterleaveCount(Optional count); - - /// Set the `disable_unroll` option to the provided value. If no value - /// is provided the option is deleted. - LoopOptionsAttrBuilder &setDisableUnroll(Optional value); - - /// Set the `disable_pipeline` option to the provided value. If no value - /// is provided the option is deleted. - LoopOptionsAttrBuilder &setDisablePipeline(Optional value); - - /// Set the `pipeline_initiation_interval` option to the provided value. - /// If no value is provided the option is deleted. - LoopOptionsAttrBuilder & - setPipelineInitiationInterval(Optional count); - - /// Returns true if any option has been set. - bool empty() { return options.empty(); } - -private: - template - LoopOptionsAttrBuilder &setOption(LoopOptionCase tag, Optional value); - - friend class LoopOptionsAttr; - SmallVector options; -}; - /// Convert an array of integer attributes to a vector of integers that can be /// used as indices in LLVM operations. template diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td @@ -0,0 +1,378 @@ +//===-- LLVMEnums.td - LLVM IR dialect enum file -----------*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVMIR_ENUMS_TD +#define LLVMIR_ENUMS_TD + +include "mlir/Dialect/LLVMIR/LLVMOpBase.td" + +//===----------------------------------------------------------------------===// +// AsmDialect +//===----------------------------------------------------------------------===// + +def AsmATT : LLVM_EnumAttrCase< + /*string cppSym=*/"AD_ATT", /*string irSym=*/"att", + /*string llvmSym=*/"AD_ATT", /*int val=*/0>; +def AsmIntel : LLVM_EnumAttrCase< + /*string cppSym=*/"AD_Intel", /*string irSym=*/"intel", + /*string llvmSym=*/"AD_Intel", /*int val=*/1>; +def AsmATTOrIntel : LLVM_EnumAttr< + /*string name=*/"AsmDialect", + /*string llvmName=*/"::llvm::InlineAsm::AsmDialect", + /*string description=*/"ATT (0) or Intel (1) asm dialect", + /*list cases=*/[AsmATT, AsmIntel]> { + let cppNamespace = "::mlir::LLVM"; +} + +//===----------------------------------------------------------------------===// +// Atomic Operations +//===----------------------------------------------------------------------===// + +def AtomicBinOpXchg : I64EnumAttrCase<"xchg", 0>; +def AtomicBinOpAdd : I64EnumAttrCase<"add", 1>; +def AtomicBinOpSub : I64EnumAttrCase<"sub", 2>; +def AtomicBinOpAnd : I64EnumAttrCase<"_and", 3>; +def AtomicBinOpNand : I64EnumAttrCase<"nand", 4>; +def AtomicBinOpOr : I64EnumAttrCase<"_or", 5>; +def AtomicBinOpXor : I64EnumAttrCase<"_xor", 6>; +def AtomicBinOpMax : I64EnumAttrCase<"max", 7>; +def AtomicBinOpMin : I64EnumAttrCase<"min", 8>; +def AtomicBinOpUMax : I64EnumAttrCase<"umax", 9>; +def AtomicBinOpUMin : I64EnumAttrCase<"umin", 10>; +def AtomicBinOpFAdd : I64EnumAttrCase<"fadd", 11>; +def AtomicBinOpFSub : I64EnumAttrCase<"fsub", 12>; +def AtomicBinOp : I64EnumAttr< + "AtomicBinOp", + "llvm.atomicrmw binary operations", + [AtomicBinOpXchg, AtomicBinOpAdd, AtomicBinOpSub, AtomicBinOpAnd, + AtomicBinOpNand, AtomicBinOpOr, AtomicBinOpXor, AtomicBinOpMax, + AtomicBinOpMin, AtomicBinOpUMax, AtomicBinOpUMin, AtomicBinOpFAdd, + AtomicBinOpFSub]> { + let cppNamespace = "::mlir::LLVM"; +} + +def AtomicOrderingNotAtomic : I64EnumAttrCase<"not_atomic", 0>; +def AtomicOrderingUnordered : I64EnumAttrCase<"unordered", 1>; +def AtomicOrderingMonotonic : I64EnumAttrCase<"monotonic", 2>; +def AtomicOrderingAcquire : I64EnumAttrCase<"acquire", 4>; +def AtomicOrderingRelease : I64EnumAttrCase<"release", 5>; +def AtomicOrderingAcquireRelease : I64EnumAttrCase<"acq_rel", 6>; +def AtomicOrderingSequentiallyConsistent : I64EnumAttrCase<"seq_cst", 7>; +def AtomicOrdering : I64EnumAttr< + "AtomicOrdering", + "Atomic ordering for LLVM's memory model", + [AtomicOrderingNotAtomic, AtomicOrderingUnordered, AtomicOrderingMonotonic, + AtomicOrderingAcquire, AtomicOrderingRelease, AtomicOrderingAcquireRelease, + AtomicOrderingSequentiallyConsistent]> { + let cppNamespace = "::mlir::LLVM"; +} + +//===----------------------------------------------------------------------===// +// CallingConvention +//===----------------------------------------------------------------------===// + +// These values must match llvm::CallingConv ones. +// See https://llvm.org/doxygen/namespacellvm_1_1CallingConv.html for full list +// of supported calling conventions. +def CConvC : LLVM_EnumAttrCase<"C", "ccc", "C", 0>; +def CConvFast : LLVM_EnumAttrCase<"Fast", "fastcc", "Fast", 8>; +def CConvCold : LLVM_EnumAttrCase<"Cold", "coldcc", "Cold", 9>; +def CConvGHC : LLVM_EnumAttrCase<"GHC", "cc_10", "GHC", 10>; +def CConvHiPE : LLVM_EnumAttrCase<"HiPE", "cc_11", "HiPE", 11>; +def CConvWebKitJS : LLVM_EnumAttrCase<"WebKit_JS", "webkit_jscc", + "WebKit_JS", 12>; +def CConvAnyReg : LLVM_EnumAttrCase<"AnyReg", "anyregcc", "AnyReg", 13>; +def CConvPreserveMost : LLVM_EnumAttrCase<"PreserveMost", "preserve_mostcc", + "PreserveMost", 14>; +def CConvPreserveAll : LLVM_EnumAttrCase<"PreserveAll", "preserve_allcc", + "PreserveAll", 15>; +def CConvSwift : LLVM_EnumAttrCase<"Swift", "swiftcc", "Swift", 16>; +def CConvCXXFastTLS : LLVM_EnumAttrCase<"CXX_FAST_TLS", "cxx_fast_tlscc", + "CXX_FAST_TLS", 17>; +def CConvTail : LLVM_EnumAttrCase<"Tail", "tailcc", "Tail", 18>; +def CConvCFGuard_Check : LLVM_EnumAttrCase<"CFGuard_Check", + "cfguard_checkcc", + "CFGuard_Check", 19>; +def CConvSwiftTail : LLVM_EnumAttrCase<"SwiftTail", "swifttailcc", + "SwiftTail", 20>; +def CConvX86_StdCall : LLVM_EnumAttrCase<"X86_StdCall", "x86_stdcallcc", + "X86_StdCall", 64>; +def CConvX86_FastCall : LLVM_EnumAttrCase<"X86_FastCall", "x86_fastcallcc", + "X86_FastCall", 65>; +def CConvARM_APCS : LLVM_EnumAttrCase<"ARM_APCS", "arm_apcscc", "ARM_APCS", 66>; +def CConvARM_AAPCS : LLVM_EnumAttrCase<"ARM_AAPCS", "arm_aapcscc", "ARM_AAPCS", + 67>; +def CConvARM_AAPCS_VFP : LLVM_EnumAttrCase<"ARM_AAPCS_VFP", "arm_aapcs_vfpcc", + "ARM_AAPCS_VFP", 68>; +def CConvMSP430_INTR : LLVM_EnumAttrCase<"MSP430_INTR", "msp430_intrcc", + "MSP430_INTR", 69>; +def CConvX86_ThisCall : LLVM_EnumAttrCase<"X86_ThisCall", "x86_thiscallcc", + "X86_ThisCall", 70>; +def CConvPTX_Kernel : LLVM_EnumAttrCase<"PTX_Kernel", "ptx_kernelcc", + "PTX_Kernel", 71>; +def CConvPTX_Device : LLVM_EnumAttrCase<"PTX_Device", "ptx_devicecc", + "PTX_Device", 72>; +def CConvSPIR_FUNC : LLVM_EnumAttrCase<"SPIR_FUNC", "spir_funccc", + "SPIR_FUNC", 75>; +def CConvSPIR_KERNEL : LLVM_EnumAttrCase<"SPIR_KERNEL", "spir_kernelcc", + "SPIR_KERNEL", 76>; +def CConvIntel_OCL_BI : LLVM_EnumAttrCase<"Intel_OCL_BI", "intel_ocl_bicc", + "Intel_OCL_BI", 77>; +def CConvX86_64_SysV : LLVM_EnumAttrCase<"X86_64_SysV", "x86_64_sysvcc", + "X86_64_SysV", 78>; +def CConvWin64 : LLVM_EnumAttrCase<"Win64", "win64cc", "Win64", 79>; +def CConvX86_VectorCall : LLVM_EnumAttrCase<"X86_VectorCall", + "x86_vectorcallcc", + "X86_VectorCall", 80>; +def CConvHHVM : LLVM_EnumAttrCase<"HHVM", "hhvmcc", "HHVM", 81>; +def CConvHHVM_C : LLVM_EnumAttrCase<"HHVM_C", "hhvm_ccc", "HHVM_C", 82>; +def CConvX86_INTR : LLVM_EnumAttrCase<"X86_INTR", "x86_intrcc", "X86_INTR", 83>; +def CConvAVR_INTR : LLVM_EnumAttrCase<"AVR_INTR", "avr_intrcc", "AVR_INTR", 84>; +def CConvAVR_SIGNAL : LLVM_EnumAttrCase<"AVR_SIGNAL", "avr_signalcc", + "AVR_SIGNAL", 85>; +def CConvAVR_BUILTIN : LLVM_EnumAttrCase<"AVR_BUILTIN", "avr_builtincc", + "AVR_BUILTIN", 86>; +def CConvAMDGPU_VS : LLVM_EnumAttrCase<"AMDGPU_VS", "amdgpu_vscc", "AMDGPU_VS", + 87>; +def CConvAMDGPU_GS : LLVM_EnumAttrCase<"AMDGPU_GS", "amdgpu_gscc", "AMDGPU_GS", + 88>; +def CConvAMDGPU_PS : LLVM_EnumAttrCase<"AMDGPU_PS", "amdgpu_pscc", "AMDGPU_PS", + 89>; +def CConvAMDGPU_CS : LLVM_EnumAttrCase<"AMDGPU_CS", "amdgpu_cscc", "AMDGPU_CS", + 90>; +def CConvAMDGPU_KERNEL : LLVM_EnumAttrCase<"AMDGPU_KERNEL", "amdgpu_kernelcc", + "AMDGPU_KERNEL", 91>; +def CConvX86_RegCall : LLVM_EnumAttrCase<"X86_RegCall", "x86_regcallcc", + "X86_RegCall", 92>; +def CConvAMDGPU_HS : LLVM_EnumAttrCase<"AMDGPU_HS", "amdgpu_hscc", "AMDGPU_HS", + 93>; +def CConvMSP430_BUILTIN : LLVM_EnumAttrCase<"MSP430_BUILTIN", + "msp430_builtincc", + "MSP430_BUILTIN", 94>; +def CConvAMDGPU_LS : LLVM_EnumAttrCase<"AMDGPU_LS", "amdgpu_lscc", "AMDGPU_LS", + 95>; +def CConvAMDGPU_ES : LLVM_EnumAttrCase<"AMDGPU_ES", "amdgpu_escc", "AMDGPU_ES", + 96>; +def CConvAArch64_VectorCall : LLVM_EnumAttrCase<"AArch64_VectorCall", + "aarch64_vectorcallcc", + "AArch64_VectorCall", 97>; +def CConvAArch64_SVE_VectorCall : LLVM_EnumAttrCase<"AArch64_SVE_VectorCall", + "aarch64_sve_vectorcallcc", + "AArch64_SVE_VectorCall", + 98>; +def CConvWASM_EmscriptenInvoke : LLVM_EnumAttrCase<"WASM_EmscriptenInvoke", + "wasm_emscripten_invokecc", + "WASM_EmscriptenInvoke", 99>; +def CConvAMDGPU_Gfx : LLVM_EnumAttrCase<"AMDGPU_Gfx", "amdgpu_gfxcc", + "AMDGPU_Gfx", 100>; +def CConvM68k_INTR : LLVM_EnumAttrCase<"M68k_INTR", "m68k_intrcc", "M68k_INTR", + 101>; + +def CConvEnum : LLVM_CEnumAttr< + "CConv", + "::llvm::CallingConv", + "Calling Conventions", + [CConvC, CConvFast, CConvCold, CConvGHC, CConvHiPE, CConvWebKitJS, + CConvAnyReg, CConvPreserveMost, CConvPreserveAll, CConvSwift, + CConvCXXFastTLS, CConvTail, CConvCFGuard_Check, CConvSwiftTail, + CConvX86_StdCall, CConvX86_FastCall, CConvARM_APCS, + CConvARM_AAPCS, CConvARM_AAPCS_VFP, CConvMSP430_INTR, CConvX86_ThisCall, + CConvPTX_Kernel, CConvPTX_Device, CConvSPIR_FUNC, CConvSPIR_KERNEL, + CConvIntel_OCL_BI, CConvX86_64_SysV, CConvWin64, CConvX86_VectorCall, + CConvHHVM, CConvHHVM_C, CConvX86_INTR, CConvAVR_INTR, CConvAVR_BUILTIN, + CConvAMDGPU_VS, CConvAMDGPU_GS, CConvAMDGPU_CS, CConvAMDGPU_KERNEL, + CConvX86_RegCall, CConvAMDGPU_HS, CConvMSP430_BUILTIN, CConvAMDGPU_LS, + CConvAMDGPU_ES, CConvAArch64_VectorCall, CConvAArch64_SVE_VectorCall, + CConvWASM_EmscriptenInvoke, CConvAMDGPU_Gfx, CConvM68k_INTR + ]> { + let cppNamespace = "::mlir::LLVM::cconv"; +} + +def CConv : DialectAttr< + LLVM_Dialect, + CPred<"$_self.isa<::mlir::LLVM::CConvAttr>()">, + "LLVM Calling Convention specification"> { + let storageType = "::mlir::LLVM::CConvAttr"; + let returnType = "::mlir::LLVM::cconv::CConv"; + let convertFromStorage = "$_self.getCallingConv()"; + let constBuilderCall = + "::mlir::LLVM::CConvAttr::get($_builder.getContext(), $0)"; +} + +//===----------------------------------------------------------------------===// +// FastmathFlags +//===----------------------------------------------------------------------===// + +def FMFnone : I32BitEnumAttrCaseNone<"none">; +def FMFnnan : I32BitEnumAttrCaseBit<"nnan", 0>; +def FMFninf : I32BitEnumAttrCaseBit<"ninf", 1>; +def FMFnsz : I32BitEnumAttrCaseBit<"nsz", 2>; +def FMFarcp : I32BitEnumAttrCaseBit<"arcp", 3>; +def FMFcontract : I32BitEnumAttrCaseBit<"contract", 4>; +def FMFafn : I32BitEnumAttrCaseBit<"afn", 5>; +def FMFreassoc : I32BitEnumAttrCaseBit<"reassoc", 6>; +def FMFfast : I32BitEnumAttrCaseGroup<"fast", + [ FMFnnan, FMFninf, FMFnsz, FMFarcp, FMFcontract, FMFafn, FMFreassoc]>; + +def FastmathFlags : I32BitEnumAttr< + "FastmathFlags", + "LLVM fastmath flags", + [FMFnone, FMFnnan, FMFninf, FMFnsz, FMFarcp, FMFcontract, FMFafn, + FMFreassoc, FMFfast]> { + let separator = ", "; + let cppNamespace = "::mlir::LLVM"; + let genSpecializedAttr = 0; + let printBitEnumPrimaryGroups = 1; +} + +//===----------------------------------------------------------------------===// +// FCmp Predicates +//===----------------------------------------------------------------------===// + +// Predicate for float comparisons +def FCmpPredicateFALSE : I64EnumAttrCase<"_false", 0>; +def FCmpPredicateOEQ : I64EnumAttrCase<"oeq", 1>; +def FCmpPredicateOGT : I64EnumAttrCase<"ogt", 2>; +def FCmpPredicateOGE : I64EnumAttrCase<"oge", 3>; +def FCmpPredicateOLT : I64EnumAttrCase<"olt", 4>; +def FCmpPredicateOLE : I64EnumAttrCase<"ole", 5>; +def FCmpPredicateONE : I64EnumAttrCase<"one", 6>; +def FCmpPredicateORD : I64EnumAttrCase<"ord", 7>; +def FCmpPredicateUEQ : I64EnumAttrCase<"ueq", 8>; +def FCmpPredicateUGT : I64EnumAttrCase<"ugt", 9>; +def FCmpPredicateUGE : I64EnumAttrCase<"uge", 10>; +def FCmpPredicateULT : I64EnumAttrCase<"ult", 11>; +def FCmpPredicateULE : I64EnumAttrCase<"ule", 12>; +def FCmpPredicateUNE : I64EnumAttrCase<"une", 13>; +def FCmpPredicateUNO : I64EnumAttrCase<"uno", 14>; +def FCmpPredicateTRUE : I64EnumAttrCase<"_true", 15>; + +def FCmpPredicate : I64EnumAttr< + "FCmpPredicate", + "llvm.fcmp comparison predicate", + [FCmpPredicateFALSE, FCmpPredicateOEQ, FCmpPredicateOGT, FCmpPredicateOGE, + FCmpPredicateOLT, FCmpPredicateOLE, FCmpPredicateONE, FCmpPredicateORD, + FCmpPredicateUEQ, FCmpPredicateUGT, FCmpPredicateUGE, FCmpPredicateULT, + FCmpPredicateULE, FCmpPredicateUNE, FCmpPredicateUNO, FCmpPredicateTRUE + ]> { + let cppNamespace = "::mlir::LLVM"; +} + +//===----------------------------------------------------------------------===// +// ICmp Predicates +//===----------------------------------------------------------------------===// + +// Predicate for integer comparisons. +def ICmpPredicateEQ : I64EnumAttrCase<"eq", 0>; +def ICmpPredicateNE : I64EnumAttrCase<"ne", 1>; +def ICmpPredicateSLT : I64EnumAttrCase<"slt", 2>; +def ICmpPredicateSLE : I64EnumAttrCase<"sle", 3>; +def ICmpPredicateSGT : I64EnumAttrCase<"sgt", 4>; +def ICmpPredicateSGE : I64EnumAttrCase<"sge", 5>; +def ICmpPredicateULT : I64EnumAttrCase<"ult", 6>; +def ICmpPredicateULE : I64EnumAttrCase<"ule", 7>; +def ICmpPredicateUGT : I64EnumAttrCase<"ugt", 8>; +def ICmpPredicateUGE : I64EnumAttrCase<"uge", 9>; +def ICmpPredicate : I64EnumAttr< + "ICmpPredicate", + "llvm.icmp comparison predicate", + [ICmpPredicateEQ, ICmpPredicateNE, ICmpPredicateSLT, ICmpPredicateSLE, + ICmpPredicateSGT, ICmpPredicateSGE, ICmpPredicateULT, ICmpPredicateULE, + ICmpPredicateUGT, ICmpPredicateUGE]> { + let cppNamespace = "::mlir::LLVM"; +} + +//===----------------------------------------------------------------------===// +// Linkage +//===----------------------------------------------------------------------===// + +// Linkage attribute is used on functions and globals. The order follows that of +// https://llvm.org/docs/LangRef.html#linkage-types. The names are equivalent to +// visible names in the IR rather than to enum values names in llvm::GlobalValue +// since the latter is easier to change. +def LinkagePrivate + : LLVM_EnumAttrCase<"Private", "private", "PrivateLinkage", 0>; +def LinkageInternal + : LLVM_EnumAttrCase<"Internal", "internal", "InternalLinkage", 1>; +def LinkageAvailableExternally + : LLVM_EnumAttrCase<"AvailableExternally", "available_externally", + "AvailableExternallyLinkage", 2>; +def LinkageLinkonce + : LLVM_EnumAttrCase<"Linkonce", "linkonce", "LinkOnceAnyLinkage", 3>; +def LinkageWeak + : LLVM_EnumAttrCase<"Weak", "weak", "WeakAnyLinkage", 4>; +def LinkageCommon + : LLVM_EnumAttrCase<"Common", "common", "CommonLinkage", 5>; +def LinkageAppending + : LLVM_EnumAttrCase<"Appending", "appending", "AppendingLinkage", 6>; +def LinkageExternWeak + : LLVM_EnumAttrCase<"ExternWeak", "extern_weak", "ExternalWeakLinkage", 7>; +def LinkageLinkonceODR + : LLVM_EnumAttrCase<"LinkonceODR", "linkonce_odr", "LinkOnceODRLinkage", 8>; +def LinkageWeakODR + : LLVM_EnumAttrCase<"WeakODR", "weak_odr", "WeakODRLinkage", 9>; +def LinkageExternal + : LLVM_EnumAttrCase<"External", "external", "ExternalLinkage", 10>; + +def LinkageEnum : LLVM_EnumAttr< + "Linkage", + "::llvm::GlobalValue::LinkageTypes", + "LLVM linkage types", + [LinkagePrivate, LinkageInternal, LinkageAvailableExternally, + LinkageLinkonce, LinkageWeak, LinkageCommon, LinkageAppending, + LinkageExternWeak, LinkageLinkonceODR, LinkageWeakODR, LinkageExternal]> { + let cppNamespace = "::mlir::LLVM::linkage"; +} + +def Linkage : DialectAttr< + LLVM_Dialect, + CPred<"$_self.isa<::mlir::LLVM::LinkageAttr>()">, + "LLVM Linkage specification"> { + let storageType = "::mlir::LLVM::LinkageAttr"; + let returnType = "::mlir::LLVM::Linkage"; + let convertFromStorage = "$_self.getLinkage()"; + let constBuilderCall = + "::mlir::LLVM::LinkageAttr::get($_builder.getContext(), $0)"; +} + +//===----------------------------------------------------------------------===// +// LoopOptions +//===----------------------------------------------------------------------===// + +def LOptDisableUnroll : I32EnumAttrCase<"disable_unroll", 1>; +def LOptDisableLICM : I32EnumAttrCase<"disable_licm", 2>; +def LOptInterleaveCount : I32EnumAttrCase<"interleave_count", 3>; +def LOptDisablePipeline : I32EnumAttrCase<"disable_pipeline", 4>; +def LOptPipelineInitiationInterval : I32EnumAttrCase<"pipeline_initiation_interval", 5>; + +def LoopOptionCase : I32EnumAttr< + "LoopOptionCase", + "LLVM loop option", + [LOptDisableUnroll, LOptDisableLICM, LOptInterleaveCount, + LOptDisablePipeline, LOptPipelineInitiationInterval + ]> { + let cppNamespace = "::mlir::LLVM"; +} + +//===----------------------------------------------------------------------===// +// UnnamedAddr +//===----------------------------------------------------------------------===// + +def UnnamedAddrNone : LLVM_EnumAttrCase<"None", "", "None", 0>; +def UnnamedAddrLocal : LLVM_EnumAttrCase<"Local", "local_unnamed_addr", "Local", 1>; +def UnnamedAddrGlobal : LLVM_EnumAttrCase<"Global", "unnamed_addr", "Global", 2>; + +def UnnamedAddr : LLVM_EnumAttr< + "UnnamedAddr", + "::llvm::GlobalValue::UnnamedAddr", + "LLVM GlobalValue UnnamedAddr", + [UnnamedAddrNone, UnnamedAddrLocal, UnnamedAddrGlobal]> { + let cppNamespace = "::mlir::LLVM"; +} + +#endif // LLVMIR_ENUMS_TD diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td @@ -87,6 +87,9 @@ /// can save us lots of verification time if there are many occurrences /// of some deeply-nested aggregate types in the program. ThreadLocalCache> compatibleTypes; + + /// Register the attributes of this dialect. + void registerAttributes(); }]; } diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -23,177 +23,6 @@ include "mlir/Interfaces/InferTypeOpInterface.td" include "mlir/Interfaces/SideEffectInterfaces.td" -def FMFnone : I32BitEnumAttrCaseNone<"none">; -def FMFnnan : I32BitEnumAttrCaseBit<"nnan", 0>; -def FMFninf : I32BitEnumAttrCaseBit<"ninf", 1>; -def FMFnsz : I32BitEnumAttrCaseBit<"nsz", 2>; -def FMFarcp : I32BitEnumAttrCaseBit<"arcp", 3>; -def FMFcontract : I32BitEnumAttrCaseBit<"contract", 4>; -def FMFafn : I32BitEnumAttrCaseBit<"afn", 5>; -def FMFreassoc : I32BitEnumAttrCaseBit<"reassoc", 6>; -def FMFfast : I32BitEnumAttrCaseGroup<"fast", - [ FMFnnan, FMFninf, FMFnsz, FMFarcp, FMFcontract, FMFafn, FMFreassoc]>; - -def FastmathFlags : I32BitEnumAttr< - "FastmathFlags", - "LLVM fastmath flags", - [FMFnone, FMFnnan, FMFninf, FMFnsz, FMFarcp, FMFcontract, FMFafn, - FMFreassoc, FMFfast]> { - let separator = ", "; - let cppNamespace = "::mlir::LLVM"; - let genSpecializedAttr = 0; - let printBitEnumPrimaryGroups = 1; -} - -// The "FastMath" flags associated with floating point LLVM instructions. -def LLVM_FastmathFlagsAttr : - EnumAttr { - let assemblyFormat = "`<` $value `>`"; -} - -def LOptDisableUnroll : I32EnumAttrCase<"disable_unroll", 1>; -def LOptDisableLICM : I32EnumAttrCase<"disable_licm", 2>; -def LOptInterleaveCount : I32EnumAttrCase<"interleave_count", 3>; -def LOptDisablePipeline : I32EnumAttrCase<"disable_pipeline", 4>; -def LOptPipelineInitiationInterval : I32EnumAttrCase<"pipeline_initiation_interval", 5>; - -def LoopOptionCase : I32EnumAttr< - "LoopOptionCase", - "LLVM loop option", - [LOptDisableUnroll, LOptDisableLICM, LOptInterleaveCount, - LOptDisablePipeline, LOptPipelineInitiationInterval - ]> { - let cppNamespace = "::mlir::LLVM"; -} - -// These values must match llvm::CallingConv ones. -// See https://llvm.org/doxygen/namespacellvm_1_1CallingConv.html for full list -// of supported calling conventions. -def CConvC : LLVM_EnumAttrCase<"C", "ccc", "C", 0>; -def CConvFast : LLVM_EnumAttrCase<"Fast", "fastcc", "Fast", 8>; -def CConvCold : LLVM_EnumAttrCase<"Cold", "coldcc", "Cold", 9>; -def CConvGHC : LLVM_EnumAttrCase<"GHC", "cc_10", "GHC", 10>; -def CConvHiPE : LLVM_EnumAttrCase<"HiPE", "cc_11", "HiPE", 11>; -def CConvWebKitJS : LLVM_EnumAttrCase<"WebKit_JS", "webkit_jscc", - "WebKit_JS", 12>; -def CConvAnyReg : LLVM_EnumAttrCase<"AnyReg", "anyregcc", "AnyReg", 13>; -def CConvPreserveMost : LLVM_EnumAttrCase<"PreserveMost", "preserve_mostcc", - "PreserveMost", 14>; -def CConvPreserveAll : LLVM_EnumAttrCase<"PreserveAll", "preserve_allcc", - "PreserveAll", 15>; -def CConvSwift : LLVM_EnumAttrCase<"Swift", "swiftcc", "Swift", 16>; -def CConvCXXFastTLS : LLVM_EnumAttrCase<"CXX_FAST_TLS", "cxx_fast_tlscc", - "CXX_FAST_TLS", 17>; -def CConvTail : LLVM_EnumAttrCase<"Tail", "tailcc", "Tail", 18>; -def CConvCFGuard_Check : LLVM_EnumAttrCase<"CFGuard_Check", - "cfguard_checkcc", - "CFGuard_Check", 19>; -def CConvSwiftTail : LLVM_EnumAttrCase<"SwiftTail", "swifttailcc", - "SwiftTail", 20>; -def CConvX86_StdCall : LLVM_EnumAttrCase<"X86_StdCall", "x86_stdcallcc", - "X86_StdCall", 64>; -def CConvX86_FastCall : LLVM_EnumAttrCase<"X86_FastCall", "x86_fastcallcc", - "X86_FastCall", 65>; -def CConvARM_APCS : LLVM_EnumAttrCase<"ARM_APCS", "arm_apcscc", "ARM_APCS", 66>; -def CConvARM_AAPCS : LLVM_EnumAttrCase<"ARM_AAPCS", "arm_aapcscc", "ARM_AAPCS", - 67>; -def CConvARM_AAPCS_VFP : LLVM_EnumAttrCase<"ARM_AAPCS_VFP", "arm_aapcs_vfpcc", - "ARM_AAPCS_VFP", 68>; -def CConvMSP430_INTR : LLVM_EnumAttrCase<"MSP430_INTR", "msp430_intrcc", - "MSP430_INTR", 69>; -def CConvX86_ThisCall : LLVM_EnumAttrCase<"X86_ThisCall", "x86_thiscallcc", - "X86_ThisCall", 70>; -def CConvPTX_Kernel : LLVM_EnumAttrCase<"PTX_Kernel", "ptx_kernelcc", - "PTX_Kernel", 71>; -def CConvPTX_Device : LLVM_EnumAttrCase<"PTX_Device", "ptx_devicecc", - "PTX_Device", 72>; -def CConvSPIR_FUNC : LLVM_EnumAttrCase<"SPIR_FUNC", "spir_funccc", - "SPIR_FUNC", 75>; -def CConvSPIR_KERNEL : LLVM_EnumAttrCase<"SPIR_KERNEL", "spir_kernelcc", - "SPIR_KERNEL", 76>; -def CConvIntel_OCL_BI : LLVM_EnumAttrCase<"Intel_OCL_BI", "intel_ocl_bicc", - "Intel_OCL_BI", 77>; -def CConvX86_64_SysV : LLVM_EnumAttrCase<"X86_64_SysV", "x86_64_sysvcc", - "X86_64_SysV", 78>; -def CConvWin64 : LLVM_EnumAttrCase<"Win64", "win64cc", "Win64", 79>; -def CConvX86_VectorCall : LLVM_EnumAttrCase<"X86_VectorCall", - "x86_vectorcallcc", - "X86_VectorCall", 80>; -def CConvHHVM : LLVM_EnumAttrCase<"HHVM", "hhvmcc", "HHVM", 81>; -def CConvHHVM_C : LLVM_EnumAttrCase<"HHVM_C", "hhvm_ccc", "HHVM_C", 82>; -def CConvX86_INTR : LLVM_EnumAttrCase<"X86_INTR", "x86_intrcc", "X86_INTR", 83>; -def CConvAVR_INTR : LLVM_EnumAttrCase<"AVR_INTR", "avr_intrcc", "AVR_INTR", 84>; -def CConvAVR_SIGNAL : LLVM_EnumAttrCase<"AVR_SIGNAL", "avr_signalcc", - "AVR_SIGNAL", 85>; -def CConvAVR_BUILTIN : LLVM_EnumAttrCase<"AVR_BUILTIN", "avr_builtincc", - "AVR_BUILTIN", 86>; -def CConvAMDGPU_VS : LLVM_EnumAttrCase<"AMDGPU_VS", "amdgpu_vscc", "AMDGPU_VS", - 87>; -def CConvAMDGPU_GS : LLVM_EnumAttrCase<"AMDGPU_GS", "amdgpu_gscc", "AMDGPU_GS", - 88>; -def CConvAMDGPU_PS : LLVM_EnumAttrCase<"AMDGPU_PS", "amdgpu_pscc", "AMDGPU_PS", - 89>; -def CConvAMDGPU_CS : LLVM_EnumAttrCase<"AMDGPU_CS", "amdgpu_cscc", "AMDGPU_CS", - 90>; -def CConvAMDGPU_KERNEL : LLVM_EnumAttrCase<"AMDGPU_KERNEL", "amdgpu_kernelcc", - "AMDGPU_KERNEL", 91>; -def CConvX86_RegCall : LLVM_EnumAttrCase<"X86_RegCall", "x86_regcallcc", - "X86_RegCall", 92>; -def CConvAMDGPU_HS : LLVM_EnumAttrCase<"AMDGPU_HS", "amdgpu_hscc", "AMDGPU_HS", - 93>; -def CConvMSP430_BUILTIN : LLVM_EnumAttrCase<"MSP430_BUILTIN", - "msp430_builtincc", - "MSP430_BUILTIN", 94>; -def CConvAMDGPU_LS : LLVM_EnumAttrCase<"AMDGPU_LS", "amdgpu_lscc", "AMDGPU_LS", - 95>; -def CConvAMDGPU_ES : LLVM_EnumAttrCase<"AMDGPU_ES", "amdgpu_escc", "AMDGPU_ES", - 96>; -def CConvAArch64_VectorCall : LLVM_EnumAttrCase<"AArch64_VectorCall", - "aarch64_vectorcallcc", - "AArch64_VectorCall", 97>; -def CConvAArch64_SVE_VectorCall : LLVM_EnumAttrCase<"AArch64_SVE_VectorCall", - "aarch64_sve_vectorcallcc", - "AArch64_SVE_VectorCall", - 98>; -def CConvWASM_EmscriptenInvoke : LLVM_EnumAttrCase<"WASM_EmscriptenInvoke", - "wasm_emscripten_invokecc", - "WASM_EmscriptenInvoke", 99>; -def CConvAMDGPU_Gfx : LLVM_EnumAttrCase<"AMDGPU_Gfx", "amdgpu_gfxcc", - "AMDGPU_Gfx", 100>; -def CConvM68k_INTR : LLVM_EnumAttrCase<"M68k_INTR", "m68k_intrcc", "M68k_INTR", - 101>; - -def CConvEnum : LLVM_CEnumAttr< - "CConv", - "::llvm::CallingConv", - "Calling Conventions", - [CConvC, CConvFast, CConvCold, CConvGHC, CConvHiPE, CConvWebKitJS, - CConvAnyReg, CConvPreserveMost, CConvPreserveAll, CConvSwift, - CConvCXXFastTLS, CConvTail, CConvCFGuard_Check, CConvSwiftTail, - CConvX86_StdCall, CConvX86_FastCall, CConvARM_APCS, - CConvARM_AAPCS, CConvARM_AAPCS_VFP, CConvMSP430_INTR, CConvX86_ThisCall, - CConvPTX_Kernel, CConvPTX_Device, CConvSPIR_FUNC, CConvSPIR_KERNEL, - CConvIntel_OCL_BI, CConvX86_64_SysV, CConvWin64, CConvX86_VectorCall, - CConvHHVM, CConvHHVM_C, CConvX86_INTR, CConvAVR_INTR, CConvAVR_BUILTIN, - CConvAMDGPU_VS, CConvAMDGPU_GS, CConvAMDGPU_CS, CConvAMDGPU_KERNEL, - CConvX86_RegCall, CConvAMDGPU_HS, CConvMSP430_BUILTIN, CConvAMDGPU_LS, - CConvAMDGPU_ES, CConvAArch64_VectorCall, CConvAArch64_SVE_VectorCall, - CConvWASM_EmscriptenInvoke, CConvAMDGPU_Gfx, CConvM68k_INTR - ]> { - let cppNamespace = "::mlir::LLVM::cconv"; -} - -def CConv : DialectAttr< - LLVM_Dialect, - CPred<"$_self.isa<::mlir::LLVM::CConvAttr>()">, - "LLVM Calling Convention specification"> { - let storageType = "::mlir::LLVM::CConvAttr"; - let returnType = "::mlir::LLVM::cconv::CConv"; - let convertFromStorage = "$_self.getCallingConv()"; - let constBuilderCall = - "::mlir::LLVM::CConvAttr::get($_builder.getContext(), $0)"; -} - class LLVM_Builder { string llvmBuilder = builder; } @@ -266,26 +95,6 @@ def LLVM_LShrOp : LLVM_IntArithmeticOp<"lshr", "LShr">; def LLVM_AShrOp : LLVM_IntArithmeticOp<"ashr", "AShr">; -// Predicate for integer comparisons. -def ICmpPredicateEQ : I64EnumAttrCase<"eq", 0>; -def ICmpPredicateNE : I64EnumAttrCase<"ne", 1>; -def ICmpPredicateSLT : I64EnumAttrCase<"slt", 2>; -def ICmpPredicateSLE : I64EnumAttrCase<"sle", 3>; -def ICmpPredicateSGT : I64EnumAttrCase<"sgt", 4>; -def ICmpPredicateSGE : I64EnumAttrCase<"sge", 5>; -def ICmpPredicateULT : I64EnumAttrCase<"ult", 6>; -def ICmpPredicateULE : I64EnumAttrCase<"ule", 7>; -def ICmpPredicateUGT : I64EnumAttrCase<"ugt", 8>; -def ICmpPredicateUGE : I64EnumAttrCase<"uge", 9>; -def ICmpPredicate : I64EnumAttr< - "ICmpPredicate", - "llvm.icmp comparison predicate", - [ICmpPredicateEQ, ICmpPredicateNE, ICmpPredicateSLT, ICmpPredicateSLE, - ICmpPredicateSGT, ICmpPredicateSGE, ICmpPredicateULT, ICmpPredicateULE, - ICmpPredicateUGT, ICmpPredicateUGE]> { - let cppNamespace = "::mlir::LLVM"; -} - // Base class for compare operations. A compare operation takes two operands // of the same type and returns a boolean result. If the operands are // vectors, then the result has to be a boolean vector of the same shape. @@ -321,35 +130,6 @@ list llvmArgIndices = [-1, 0, 1]; } -// Predicate for float comparisons -def FCmpPredicateFALSE : I64EnumAttrCase<"_false", 0>; -def FCmpPredicateOEQ : I64EnumAttrCase<"oeq", 1>; -def FCmpPredicateOGT : I64EnumAttrCase<"ogt", 2>; -def FCmpPredicateOGE : I64EnumAttrCase<"oge", 3>; -def FCmpPredicateOLT : I64EnumAttrCase<"olt", 4>; -def FCmpPredicateOLE : I64EnumAttrCase<"ole", 5>; -def FCmpPredicateONE : I64EnumAttrCase<"one", 6>; -def FCmpPredicateORD : I64EnumAttrCase<"ord", 7>; -def FCmpPredicateUEQ : I64EnumAttrCase<"ueq", 8>; -def FCmpPredicateUGT : I64EnumAttrCase<"ugt", 9>; -def FCmpPredicateUGE : I64EnumAttrCase<"uge", 10>; -def FCmpPredicateULT : I64EnumAttrCase<"ult", 11>; -def FCmpPredicateULE : I64EnumAttrCase<"ule", 12>; -def FCmpPredicateUNE : I64EnumAttrCase<"une", 13>; -def FCmpPredicateUNO : I64EnumAttrCase<"uno", 14>; -def FCmpPredicateTRUE : I64EnumAttrCase<"_true", 15>; - -def FCmpPredicate : I64EnumAttr< - "FCmpPredicate", - "llvm.fcmp comparison predicate", - [FCmpPredicateFALSE, FCmpPredicateOEQ, FCmpPredicateOGT, FCmpPredicateOGE, - FCmpPredicateOLT, FCmpPredicateOLE, FCmpPredicateONE, FCmpPredicateORD, - FCmpPredicateUEQ, FCmpPredicateUGT, FCmpPredicateUGE, FCmpPredicateULT, - FCmpPredicateULE, FCmpPredicateUNE, FCmpPredicateUNO, FCmpPredicateTRUE - ]> { - let cppNamespace = "::mlir::LLVM"; -} - // Other floating-point operations. def LLVM_FCmpOp : LLVM_ArithmeticCmpOp<"fcmp", [ Pure, DeclareOpInterfaceMethods]> { @@ -1108,68 +888,6 @@ // to work correctly). //////////////////////////////////////////////////////////////////////////////// -// Linkage attribute is used on functions and globals. The order follows that of -// https://llvm.org/docs/LangRef.html#linkage-types. The names are equivalent to -// visible names in the IR rather than to enum values names in llvm::GlobalValue -// since the latter is easier to change. -def LinkagePrivate - : LLVM_EnumAttrCase<"Private", "private", "PrivateLinkage", 0>; -def LinkageInternal - : LLVM_EnumAttrCase<"Internal", "internal", "InternalLinkage", 1>; -def LinkageAvailableExternally - : LLVM_EnumAttrCase<"AvailableExternally", "available_externally", - "AvailableExternallyLinkage", 2>; -def LinkageLinkonce - : LLVM_EnumAttrCase<"Linkonce", "linkonce", "LinkOnceAnyLinkage", 3>; -def LinkageWeak - : LLVM_EnumAttrCase<"Weak", "weak", "WeakAnyLinkage", 4>; -def LinkageCommon - : LLVM_EnumAttrCase<"Common", "common", "CommonLinkage", 5>; -def LinkageAppending - : LLVM_EnumAttrCase<"Appending", "appending", "AppendingLinkage", 6>; -def LinkageExternWeak - : LLVM_EnumAttrCase<"ExternWeak", "extern_weak", "ExternalWeakLinkage", 7>; -def LinkageLinkonceODR - : LLVM_EnumAttrCase<"LinkonceODR", "linkonce_odr", "LinkOnceODRLinkage", 8>; -def LinkageWeakODR - : LLVM_EnumAttrCase<"WeakODR", "weak_odr", "WeakODRLinkage", 9>; -def LinkageExternal - : LLVM_EnumAttrCase<"External", "external", "ExternalLinkage", 10>; - -def LinkageEnum : LLVM_EnumAttr< - "Linkage", - "::llvm::GlobalValue::LinkageTypes", - "LLVM linkage types", - [LinkagePrivate, LinkageInternal, LinkageAvailableExternally, - LinkageLinkonce, LinkageWeak, LinkageCommon, LinkageAppending, - LinkageExternWeak, LinkageLinkonceODR, LinkageWeakODR, LinkageExternal]> { - let cppNamespace = "::mlir::LLVM::linkage"; -} - -def Linkage : DialectAttr< - LLVM_Dialect, - CPred<"$_self.isa<::mlir::LLVM::LinkageAttr>()">, - "LLVM Linkage specification"> { - let storageType = "::mlir::LLVM::LinkageAttr"; - let returnType = "::mlir::LLVM::Linkage"; - let convertFromStorage = "$_self.getLinkage()"; - let constBuilderCall = - "::mlir::LLVM::LinkageAttr::get($_builder.getContext(), $0)"; -} - - -def UnnamedAddrNone : LLVM_EnumAttrCase<"None", "", "None", 0>; -def UnnamedAddrLocal : LLVM_EnumAttrCase<"Local", "local_unnamed_addr", "Local", 1>; -def UnnamedAddrGlobal : LLVM_EnumAttrCase<"Global", "unnamed_addr", "Global", 2>; - -def UnnamedAddr : LLVM_EnumAttr< - "UnnamedAddr", - "::llvm::GlobalValue::UnnamedAddr", - "LLVM GlobalValue UnnamedAddr", - [UnnamedAddrNone, UnnamedAddrLocal, UnnamedAddrGlobal]> { - let cppNamespace = "::mlir::LLVM"; -} - def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof", [Pure, DeclareOpInterfaceMethods]> { let arguments = (ins FlatSymbolRefAttr:$global_name); @@ -1743,45 +1461,6 @@ // Atomic operations. // -def AtomicBinOpXchg : I64EnumAttrCase<"xchg", 0>; -def AtomicBinOpAdd : I64EnumAttrCase<"add", 1>; -def AtomicBinOpSub : I64EnumAttrCase<"sub", 2>; -def AtomicBinOpAnd : I64EnumAttrCase<"_and", 3>; -def AtomicBinOpNand : I64EnumAttrCase<"nand", 4>; -def AtomicBinOpOr : I64EnumAttrCase<"_or", 5>; -def AtomicBinOpXor : I64EnumAttrCase<"_xor", 6>; -def AtomicBinOpMax : I64EnumAttrCase<"max", 7>; -def AtomicBinOpMin : I64EnumAttrCase<"min", 8>; -def AtomicBinOpUMax : I64EnumAttrCase<"umax", 9>; -def AtomicBinOpUMin : I64EnumAttrCase<"umin", 10>; -def AtomicBinOpFAdd : I64EnumAttrCase<"fadd", 11>; -def AtomicBinOpFSub : I64EnumAttrCase<"fsub", 12>; -def AtomicBinOp : I64EnumAttr< - "AtomicBinOp", - "llvm.atomicrmw binary operations", - [AtomicBinOpXchg, AtomicBinOpAdd, AtomicBinOpSub, AtomicBinOpAnd, - AtomicBinOpNand, AtomicBinOpOr, AtomicBinOpXor, AtomicBinOpMax, - AtomicBinOpMin, AtomicBinOpUMax, AtomicBinOpUMin, AtomicBinOpFAdd, - AtomicBinOpFSub]> { - let cppNamespace = "::mlir::LLVM"; -} - -def AtomicOrderingNotAtomic : I64EnumAttrCase<"not_atomic", 0>; -def AtomicOrderingUnordered : I64EnumAttrCase<"unordered", 1>; -def AtomicOrderingMonotonic : I64EnumAttrCase<"monotonic", 2>; -def AtomicOrderingAcquire : I64EnumAttrCase<"acquire", 4>; -def AtomicOrderingRelease : I64EnumAttrCase<"release", 5>; -def AtomicOrderingAcquireRelease : I64EnumAttrCase<"acq_rel", 6>; -def AtomicOrderingSequentiallyConsistent : I64EnumAttrCase<"seq_cst", 7>; -def AtomicOrdering : I64EnumAttr< - "AtomicOrdering", - "Atomic ordering for LLVM's memory model", - [AtomicOrderingNotAtomic, AtomicOrderingUnordered, AtomicOrderingMonotonic, - AtomicOrderingAcquire, AtomicOrderingRelease, AtomicOrderingAcquireRelease, - AtomicOrderingSequentiallyConsistent]> { - let cppNamespace = "::mlir::LLVM"; -} - def LLVM_AtomicRMWType : AnyTypeOf<[LLVM_AnyFloat, AnyInteger]>; // FIXME: Need to add alignment and syncscope attribute to MLIR atomicrmw @@ -1866,20 +1545,6 @@ let hasVerifier = 1; } -def AsmATT : LLVM_EnumAttrCase< - /*string cppSym=*/"AD_ATT", /*string irSym=*/"att", - /*string llvmSym=*/"AD_ATT", /*int val=*/0>; -def AsmIntel : LLVM_EnumAttrCase< - /*string cppSym=*/"AD_Intel", /*string irSym=*/"intel", - /*string llvmSym=*/"AD_Intel", /*int val=*/1>; -def AsmATTOrIntel : LLVM_EnumAttr< - /*string name=*/"AsmDialect", - /*string llvmName=*/"::llvm::InlineAsm::AsmDialect", - /*string description=*/"ATT (0) or Intel (1) asm dialect", - /*list cases=*/[AsmATT, AsmIntel]> { - let cppNamespace = "::mlir::LLVM"; -} - def LLVM_InlineAsmOp : LLVM_Op<"inline_asm", []> { let description = [{ The InlineAsmOp mirrors the underlying LLVM semantics with a notable diff --git a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt --- a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt +++ b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt @@ -2,6 +2,7 @@ add_mlir_dialect_library(MLIRLLVMDialect IR/FunctionCallUtils.cpp + IR/LLVMAttrs.cpp IR/LLVMDialect.cpp IR/LLVMIntrinsicOps.cpp IR/LLVMTypes.cpp diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp new file mode 100644 --- /dev/null +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp @@ -0,0 +1,206 @@ +//===- LLVMAttrs.cpp - LLVM Attributes registration -----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the attribute details for the LLVM IR dialect in MLIR. +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/LLVMIR/LLVMAttrs.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/DialectImplementation.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/TypeSwitch.h" + +using namespace mlir; +using namespace mlir::LLVM; + +#include "mlir/Dialect/LLVMIR/LLVMOpsEnums.cpp.inc" +#define GET_ATTRDEF_CLASSES +#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc" + +//===----------------------------------------------------------------------===// +// LLVMDialect registration +//===----------------------------------------------------------------------===// + +void LLVMDialect::registerAttributes() { + addAttributes< +#define GET_ATTRDEF_LIST +#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc" + >(); +} + +//===----------------------------------------------------------------------===// +// LoopOptionsAttrBuilder +//===----------------------------------------------------------------------===// + +LoopOptionsAttrBuilder::LoopOptionsAttrBuilder(LoopOptionsAttr attr) + : options(attr.getOptions().begin(), attr.getOptions().end()) {} + +template +LoopOptionsAttrBuilder &LoopOptionsAttrBuilder::setOption(LoopOptionCase tag, + Optional value) { + auto option = llvm::find_if( + options, [tag](auto option) { return option.first == tag; }); + if (option != options.end()) { + if (value) + option->second = *value; + else + options.erase(option); + } else { + options.push_back(LoopOptionsAttr::OptionValuePair(tag, *value)); + } + return *this; +} + +LoopOptionsAttrBuilder & +LoopOptionsAttrBuilder::setDisableLICM(Optional value) { + return setOption(LoopOptionCase::disable_licm, value); +} + +/// Set the `interleave_count` option to the provided value. If no value +/// is provided the option is deleted. +LoopOptionsAttrBuilder & +LoopOptionsAttrBuilder::setInterleaveCount(Optional count) { + return setOption(LoopOptionCase::interleave_count, count); +} + +/// Set the `disable_unroll` option to the provided value. If no value +/// is provided the option is deleted. +LoopOptionsAttrBuilder & +LoopOptionsAttrBuilder::setDisableUnroll(Optional value) { + return setOption(LoopOptionCase::disable_unroll, value); +} + +/// Set the `disable_pipeline` option to the provided value. If no value +/// is provided the option is deleted. +LoopOptionsAttrBuilder & +LoopOptionsAttrBuilder::setDisablePipeline(Optional value) { + return setOption(LoopOptionCase::disable_pipeline, value); +} + +/// Set the `pipeline_initiation_interval` option to the provided value. +/// If no value is provided the option is deleted. +LoopOptionsAttrBuilder &LoopOptionsAttrBuilder::setPipelineInitiationInterval( + Optional count) { + return setOption(LoopOptionCase::pipeline_initiation_interval, count); +} + +//===----------------------------------------------------------------------===// +// LoopOptionsAttr +//===----------------------------------------------------------------------===// + +template +static Optional +getOption(ArrayRef> options, + LoopOptionCase option) { + auto it = + lower_bound(options, option, [](auto optionPair, LoopOptionCase option) { + return optionPair.first < option; + }); + if (it == options.end()) + return {}; + return static_cast(it->second); +} + +Optional LoopOptionsAttr::disableUnroll() { + return getOption(getOptions(), LoopOptionCase::disable_unroll); +} + +Optional LoopOptionsAttr::disableLICM() { + return getOption(getOptions(), LoopOptionCase::disable_licm); +} + +Optional LoopOptionsAttr::interleaveCount() { + return getOption(getOptions(), LoopOptionCase::interleave_count); +} + +/// Build the LoopOptions Attribute from a sorted array of individual options. +LoopOptionsAttr LoopOptionsAttr::get( + MLIRContext *context, + ArrayRef> sortedOptions) { + assert(llvm::is_sorted(sortedOptions, llvm::less_first()) && + "LoopOptionsAttr ctor expects a sorted options array"); + return Base::get(context, sortedOptions); +} + +/// Build the LoopOptions Attribute from a sorted array of individual options. +LoopOptionsAttr LoopOptionsAttr::get(MLIRContext *context, + LoopOptionsAttrBuilder &optionBuilders) { + llvm::sort(optionBuilders.options, llvm::less_first()); + return Base::get(context, optionBuilders.options); +} + +void LoopOptionsAttr::print(AsmPrinter &printer) const { + printer << "<"; + llvm::interleaveComma(getOptions(), printer, [&](auto option) { + printer << stringifyEnum(option.first) << " = "; + switch (option.first) { + case LoopOptionCase::disable_licm: + case LoopOptionCase::disable_unroll: + case LoopOptionCase::disable_pipeline: + printer << (option.second ? "true" : "false"); + break; + case LoopOptionCase::interleave_count: + case LoopOptionCase::pipeline_initiation_interval: + printer << option.second; + break; + } + }); + printer << ">"; +} + +Attribute LoopOptionsAttr::parse(AsmParser &parser, Type type) { + if (failed(parser.parseLess())) + return {}; + + SmallVector> options; + llvm::SmallDenseSet seenOptions; + auto parseLoopOptions = [&]() -> ParseResult { + StringRef optionName; + if (parser.parseKeyword(&optionName)) + return failure(); + + auto option = symbolizeLoopOptionCase(optionName); + if (!option) + return parser.emitError(parser.getNameLoc(), "unknown loop option: ") + << optionName; + if (!seenOptions.insert(*option).second) + return parser.emitError(parser.getNameLoc(), "loop option present twice"); + if (failed(parser.parseEqual())) + return failure(); + + int64_t value; + switch (*option) { + case LoopOptionCase::disable_licm: + case LoopOptionCase::disable_unroll: + case LoopOptionCase::disable_pipeline: + if (succeeded(parser.parseOptionalKeyword("true"))) + value = 1; + else if (succeeded(parser.parseOptionalKeyword("false"))) + value = 0; + else { + return parser.emitError(parser.getNameLoc(), + "expected boolean value 'true' or 'false'"); + } + break; + case LoopOptionCase::interleave_count: + case LoopOptionCase::pipeline_initiation_interval: + if (failed(parser.parseInteger(value))) + return parser.emitError(parser.getNameLoc(), "expected integer value"); + break; + } + options.push_back(std::make_pair(*option, value)); + return success(); + }; + if (parser.parseCommaSeparatedList(parseLoopOptions) || parser.parseGreater()) + return {}; + + llvm::sort(options, llvm::less_first()); + return get(parser.getContext(), options); +} diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -45,10 +45,7 @@ static constexpr const char kNonTemporalAttrName[] = "nontemporal"; static constexpr const char kElemTypeAttrName[] = "elem_type"; -#include "mlir/Dialect/LLVMIR/LLVMOpsEnums.cpp.inc" #include "mlir/Dialect/LLVMIR/LLVMOpsInterfaces.cpp.inc" -#define GET_ATTRDEF_CLASSES -#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc" static auto processFMFAttr(ArrayRef attrs) { SmallVector filteredAttrs( @@ -2564,7 +2561,7 @@ //===----------------------------------------------------------------------===// void LLVMDialect::initialize() { - addAttributes(); + registerAttributes(); // clang-format off addTypeshasTrait() && op->hasTrait(); } - -LoopOptionsAttrBuilder::LoopOptionsAttrBuilder(LoopOptionsAttr attr) - : options(attr.getOptions().begin(), attr.getOptions().end()) {} - -template -LoopOptionsAttrBuilder &LoopOptionsAttrBuilder::setOption(LoopOptionCase tag, - Optional value) { - auto option = llvm::find_if( - options, [tag](auto option) { return option.first == tag; }); - if (option != options.end()) { - if (value) - option->second = *value; - else - options.erase(option); - } else { - options.push_back(LoopOptionsAttr::OptionValuePair(tag, *value)); - } - return *this; -} - -LoopOptionsAttrBuilder & -LoopOptionsAttrBuilder::setDisableLICM(Optional value) { - return setOption(LoopOptionCase::disable_licm, value); -} - -/// Set the `interleave_count` option to the provided value. If no value -/// is provided the option is deleted. -LoopOptionsAttrBuilder & -LoopOptionsAttrBuilder::setInterleaveCount(Optional count) { - return setOption(LoopOptionCase::interleave_count, count); -} - -/// Set the `disable_unroll` option to the provided value. If no value -/// is provided the option is deleted. -LoopOptionsAttrBuilder & -LoopOptionsAttrBuilder::setDisableUnroll(Optional value) { - return setOption(LoopOptionCase::disable_unroll, value); -} - -/// Set the `disable_pipeline` option to the provided value. If no value -/// is provided the option is deleted. -LoopOptionsAttrBuilder & -LoopOptionsAttrBuilder::setDisablePipeline(Optional value) { - return setOption(LoopOptionCase::disable_pipeline, value); -} - -/// Set the `pipeline_initiation_interval` option to the provided value. -/// If no value is provided the option is deleted. -LoopOptionsAttrBuilder &LoopOptionsAttrBuilder::setPipelineInitiationInterval( - Optional count) { - return setOption(LoopOptionCase::pipeline_initiation_interval, count); -} - -template -static Optional -getOption(ArrayRef> options, - LoopOptionCase option) { - auto it = - lower_bound(options, option, [](auto optionPair, LoopOptionCase option) { - return optionPair.first < option; - }); - if (it == options.end()) - return {}; - return static_cast(it->second); -} - -Optional LoopOptionsAttr::disableUnroll() { - return getOption(getOptions(), LoopOptionCase::disable_unroll); -} - -Optional LoopOptionsAttr::disableLICM() { - return getOption(getOptions(), LoopOptionCase::disable_licm); -} - -Optional LoopOptionsAttr::interleaveCount() { - return getOption(getOptions(), LoopOptionCase::interleave_count); -} - -/// Build the LoopOptions Attribute from a sorted array of individual options. -LoopOptionsAttr LoopOptionsAttr::get( - MLIRContext *context, - ArrayRef> sortedOptions) { - assert(llvm::is_sorted(sortedOptions, llvm::less_first()) && - "LoopOptionsAttr ctor expects a sorted options array"); - return Base::get(context, sortedOptions); -} - -/// Build the LoopOptions Attribute from a sorted array of individual options. -LoopOptionsAttr LoopOptionsAttr::get(MLIRContext *context, - LoopOptionsAttrBuilder &optionBuilders) { - llvm::sort(optionBuilders.options, llvm::less_first()); - return Base::get(context, optionBuilders.options); -} - -void LoopOptionsAttr::print(AsmPrinter &printer) const { - printer << "<"; - llvm::interleaveComma(getOptions(), printer, [&](auto option) { - printer << stringifyEnum(option.first) << " = "; - switch (option.first) { - case LoopOptionCase::disable_licm: - case LoopOptionCase::disable_unroll: - case LoopOptionCase::disable_pipeline: - printer << (option.second ? "true" : "false"); - break; - case LoopOptionCase::interleave_count: - case LoopOptionCase::pipeline_initiation_interval: - printer << option.second; - break; - } - }); - printer << ">"; -} - -Attribute LoopOptionsAttr::parse(AsmParser &parser, Type type) { - if (failed(parser.parseLess())) - return {}; - - SmallVector> options; - llvm::SmallDenseSet seenOptions; - auto parseLoopOptions = [&]() -> ParseResult { - StringRef optionName; - if (parser.parseKeyword(&optionName)) - return failure(); - - auto option = symbolizeLoopOptionCase(optionName); - if (!option) - return parser.emitError(parser.getNameLoc(), "unknown loop option: ") - << optionName; - if (!seenOptions.insert(*option).second) - return parser.emitError(parser.getNameLoc(), "loop option present twice"); - if (failed(parser.parseEqual())) - return failure(); - - int64_t value; - switch (*option) { - case LoopOptionCase::disable_licm: - case LoopOptionCase::disable_unroll: - case LoopOptionCase::disable_pipeline: - if (succeeded(parser.parseOptionalKeyword("true"))) - value = 1; - else if (succeeded(parser.parseOptionalKeyword("false"))) - value = 0; - else { - return parser.emitError(parser.getNameLoc(), - "expected boolean value 'true' or 'false'"); - } - break; - case LoopOptionCase::interleave_count: - case LoopOptionCase::pipeline_initiation_interval: - if (failed(parser.parseInteger(value))) - return parser.emitError(parser.getNameLoc(), "expected integer value"); - break; - } - options.push_back(std::make_pair(*option, value)); - return success(); - }; - if (parser.parseCommaSeparatedList(parseLoopOptions) || parser.parseGreater()) - return {}; - - llvm::sort(options, llvm::less_first()); - return get(parser.getContext(), options); -}