diff --git a/mlir/examples/standalone/CMakeLists.txt b/mlir/examples/standalone/CMakeLists.txt --- a/mlir/examples/standalone/CMakeLists.txt +++ b/mlir/examples/standalone/CMakeLists.txt @@ -3,7 +3,7 @@ set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON) -set(CMAKE_CXX_STANDARD 14 CACHE STRING "C++ standard to conform to") +set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to") find_package(MLIR REQUIRED CONFIG) diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h --- a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h +++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h @@ -52,10 +52,8 @@ template <typename... DialectTs> void allowDialect() { // The following expands a call to allowDialectImpl for each dialect - // in 'DialectTs'. This magic is necessary due to a limitation in the places - // that a parameter pack can be expanded in c++11. - // FIXME: In c++17 this can be simplified by using 'fold expressions'. - (void)std::initializer_list<int>{0, (allowDialectImpl<DialectTs>(), 0)...}; + // in 'DialectTs'. + (allowDialectImpl<DialectTs>(), ...); } /// Deny the given dialects. @@ -63,8 +61,7 @@ /// This function adds one or multiple DENY entries. template <typename... DialectTs> void denyDialect() { - // FIXME: In c++17 this can be simplified by using 'fold expressions'. - (void)std::initializer_list<int>{0, (denyDialectImpl<DialectTs>(), 0)...}; + (denyDialectImpl<DialectTs>(), ...); } /// Allow the given dialect. @@ -82,8 +79,7 @@ /// This function adds one or multiple ALLOW entries. template <typename... OpTys> void allowOperation() { - // FIXME: In c++17 this can be simplified by using 'fold expressions'. - (void)std::initializer_list<int>{0, (allowOperationImpl<OpTys>(), 0)...}; + (allowOperationImpl<OpTys>(), ...); } /// Deny the given ops. @@ -91,8 +87,7 @@ /// This function adds one or multiple DENY entries. template <typename... OpTys> void denyOperation() { - // FIXME: In c++17 this can be simplified by using 'fold expressions'. - (void)std::initializer_list<int>{0, (denyOperationImpl<OpTys>(), 0)...}; + (denyOperationImpl<OpTys>(), ...); } /// Allow the given op. diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.td b/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.td --- a/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.td +++ b/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.td @@ -334,13 +334,10 @@ /// dialect. Checks that they implement the required interfaces. template <typename... OpTys> void addOperationsChecked() { - (void)std::initializer_list<int>{(addOperationIfNotRegistered<OpTys>(), - 0)...}; + (addOperationIfNotRegistered<OpTys>(),...); #ifndef NDEBUG - (void)std::initializer_list<int>{ - (detail::checkImplementsTransformInterface<OpTys>(getContext()), - 0)...}; + (detail::checkImplementsTransformInterface<OpTys>(getContext()),...); #endif // NDEBUG } diff --git a/mlir/include/mlir/ExecutionEngine/ExecutionEngine.h b/mlir/include/mlir/ExecutionEngine/ExecutionEngine.h --- a/mlir/include/mlir/ExecutionEngine/ExecutionEngine.h +++ b/mlir/include/mlir/ExecutionEngine/ExecutionEngine.h @@ -172,9 +172,7 @@ llvm::SmallVector<void *> argsArray; // Pack every arguments in an array of pointers. Delegate the packing to a // trait so that it can be overridden per argument type. - // TODO: replace with a fold expression when migrating to C++17. - int dummy[] = {0, ((void)Argument<Args>::pack(argsArray, args), 0)...}; - (void)dummy; + (Argument<Args>::pack(argsArray, args), ...); return invokePacked(adapterName, argsArray); } diff --git a/mlir/include/mlir/IR/BuiltinAttributes.h b/mlir/include/mlir/IR/BuiltinAttributes.h --- a/mlir/include/mlir/IR/BuiltinAttributes.h +++ b/mlir/include/mlir/IR/BuiltinAttributes.h @@ -84,7 +84,6 @@ /// Type trait used to check if the given type T is a potentially valid C++ /// floating point type that can be used to access the underlying element /// types of a DenseElementsAttr. - // TODO: Use std::disjunction when C++17 is supported. template <typename T> struct is_valid_cpp_fp_type { /// The type is a valid floating point type if it is a builtin floating diff --git a/mlir/include/mlir/IR/BuiltinTypes.td b/mlir/include/mlir/IR/BuiltinTypes.td --- a/mlir/include/mlir/IR/BuiltinTypes.td +++ b/mlir/include/mlir/IR/BuiltinTypes.td @@ -262,7 +262,7 @@ /// Integer representation maximal bitwidth. /// Note: This is aligned with the maximum width of llvm::IntegerType. - static constexpr unsigned kMaxWidth = (1 << 24) - 1; + static constexpr inline unsigned kMaxWidth = (1 << 24) - 1; }]; } diff --git a/mlir/include/mlir/IR/Dialect.h b/mlir/include/mlir/IR/Dialect.h --- a/mlir/include/mlir/IR/Dialect.h +++ b/mlir/include/mlir/IR/Dialect.h @@ -186,8 +186,7 @@ /// Register a set of dialect interfaces with this dialect instance. template <typename... Args> void addInterfaces() { - (void)std::initializer_list<int>{ - 0, (addInterface(std::make_unique<Args>(this)), 0)...}; + (addInterface(std::make_unique<Args>(this)), ...); } template <typename InterfaceT, typename... Args> InterfaceT &addInterface(Args &&...args) { @@ -210,6 +209,10 @@ /// template <typename... Args> void addOperations() { + // This initializer_list argument pack expansion is essentially equal to + // using a fold expression with a comma operator. Clang however, refuses + // to compile a fold expression with a depth of more than 256 by default. + // There seem to be no such limitations for initializer_list. (void)std::initializer_list<int>{ 0, (RegisteredOperationName::insert<Args>(*this), 0)...}; } @@ -217,7 +220,7 @@ /// Register a set of type classes with this dialect. template <typename... Args> void addTypes() { - (void)std::initializer_list<int>{0, (addType<Args>(), 0)...}; + (addType<Args>(), ...); } /// Register a type instance with this dialect. @@ -228,7 +231,7 @@ /// Register a set of attribute classes with this dialect. template <typename... Args> void addAttributes() { - (void)std::initializer_list<int>{0, (addAttribute<Args>(), 0)...}; + (addAttribute<Args>(), ...); } /// Register an attribute instance with this dialect. diff --git a/mlir/include/mlir/IR/DialectRegistry.h b/mlir/include/mlir/IR/DialectRegistry.h --- a/mlir/include/mlir/IR/DialectRegistry.h +++ b/mlir/include/mlir/IR/DialectRegistry.h @@ -175,8 +175,7 @@ /// Add the given extensions to the registry. template <typename... ExtensionsT> void addExtensions() { - (void)std::initializer_list<int>{ - (addExtension(std::make_unique<ExtensionsT>()), 0)...}; + (addExtension(std::make_unique<ExtensionsT>()), ...); } /// Add an extension function that requires the given dialects. diff --git a/mlir/include/mlir/IR/Matchers.h b/mlir/include/mlir/IR/Matchers.h --- a/mlir/include/mlir/IR/Matchers.h +++ b/mlir/include/mlir/IR/Matchers.h @@ -224,10 +224,9 @@ template <typename TupleT, class CallbackT, std::size_t... Is> constexpr void enumerateImpl(TupleT &&tuple, CallbackT &&callback, std::index_sequence<Is...>) { - (void)std::initializer_list<int>{ - 0, - (callback(std::integral_constant<std::size_t, Is>{}, std::get<Is>(tuple)), - 0)...}; + + (callback(std::integral_constant<std::size_t, Is>{}, std::get<Is>(tuple)), + ...); } template <typename... Tys, typename CallbackT> diff --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h --- a/mlir/include/mlir/IR/OpDefinition.h +++ b/mlir/include/mlir/IR/OpDefinition.h @@ -1492,12 +1492,10 @@ template <typename T> using detect_has_fold_trait = llvm::is_detected<has_fold_trait, T>; /// Trait to check if T provides any `foldTrait` method. -/// NOTE: This should use std::disjunction when C++17 is available. template <typename T> using detect_has_any_fold_trait = - std::conditional_t<bool(detect_has_fold_trait<T>::value), - detect_has_fold_trait<T>, - detect_has_single_result_fold_trait<T>>; + std::disjunction<detect_has_fold_trait<T>, + detect_has_single_result_fold_trait<T>>; /// Returns the result of folding a trait that implements a `foldTrait` function /// that is specialized for operations that have a single result. @@ -1543,10 +1541,7 @@ template <typename... Ts> static LogicalResult foldTraits(Operation *op, ArrayRef<Attribute> operands, SmallVectorImpl<OpFoldResult> &results) { - bool anyFolded = false; - (void)std::initializer_list<int>{ - (anyFolded |= succeeded(foldTrait<Ts>(op, operands, results)), 0)...}; - return success(anyFolded); + return success((succeeded(foldTrait<Ts>(op, operands, results)) | ...)); } //===----------------------------------------------------------------------===// @@ -1581,10 +1576,7 @@ /// Given a set of traits, return the result of verifying the given operation. template <typename... Ts> LogicalResult verifyTraits(Operation *op) { - LogicalResult result = success(); - (void)std::initializer_list<int>{ - (result = succeeded(result) ? verifyTrait<Ts>(op) : failure(), 0)...}; - return result; + return success((succeeded(verifyTrait<Ts>(op)) && ...)); } /// Verify the given trait if it provides a region verifier. @@ -1604,12 +1596,7 @@ /// given operation. template <typename... Ts> LogicalResult verifyRegionTraits(Operation *op) { - (void)op; - LogicalResult result = success(); - (void)std::initializer_list<int>{ - (result = succeeded(result) ? verifyRegionTrait<Ts>(op) : failure(), - 0)...}; - return result; + return success((succeeded(verifyRegionTrait<Ts>(op)) && ...)); } } // namespace op_definition_impl @@ -1695,7 +1682,7 @@ llvm::report_fatal_error( "Attempting to attach an interface to an unregistered operation " + ConcreteType::getOperationName() + "."); - (void)std::initializer_list<int>{(checkInterfaceTarget<Models>(), 0)...}; + (checkInterfaceTarget<Models>(), ...); info->attachInterface<Models...>(); } diff --git a/mlir/include/mlir/IR/PatternMatch.h b/mlir/include/mlir/IR/PatternMatch.h --- a/mlir/include/mlir/IR/PatternMatch.h +++ b/mlir/include/mlir/IR/PatternMatch.h @@ -1079,15 +1079,10 @@ auto errorFn = [&](const Twine &msg) { return rewriter.notifyMatchFailure(rewriter.getUnknownLoc(), msg); }; - LogicalResult result = success(); - (void)std::initializer_list<int>{ - (result = - succeeded(result) - ? ProcessPDLValue<typename FnTraitsT::template arg_t<I + 1>>:: - verifyAsArg(errorFn, values[I], I) - : failure(), - 0)...}; - return result; + return success( + (succeeded(ProcessPDLValue<typename FnTraitsT::template arg_t<I + 1>>:: + verifyAsArg(errorFn, values[I], I)) && + ...)); } /// Assert that the given PDLValues match the constraints defined by the @@ -1102,10 +1097,10 @@ auto errorFn = [&](const Twine &msg) -> LogicalResult { llvm::report_fatal_error(msg); }; - (void)std::initializer_list<int>{ - (assert(succeeded(ProcessPDLValue<typename FnTraitsT::template arg_t< - I + 1>>::verifyAsArg(errorFn, values[I], I))), - 0)...}; + (assert(succeeded( + ProcessPDLValue<typename FnTraitsT::template arg_t<I + 1>>::verifyAsArg( + errorFn, values[I], I))), + ...); #endif } @@ -1134,10 +1129,7 @@ static void processResults(PatternRewriter &rewriter, PDLResultList &results, std::tuple<Ts...> &&tuple) { auto applyFn = [&](auto &&...args) { - // TODO: Use proper fold expressions when we have C++17. For now we use a - // bogus std::initializer_list to work around C++14 limitations. - (void)std::initializer_list<int>{ - (processResults(rewriter, results, std::move(args)), 0)...}; + (processResults(rewriter, results, std::move(args)), ...); }; llvm::apply_tuple(applyFn, std::move(tuple)); } @@ -1412,14 +1404,10 @@ typename = std::enable_if_t<sizeof...(Ts) != 0>> RewritePatternSet &add(ConstructorArg &&arg, ConstructorArgs &&...args) { // The following expands a call to emplace_back for each of the pattern - // types 'Ts'. This magic is necessary due to a limitation in the places - // that a parameter pack can be expanded in c++11. - // FIXME: In c++17 this can be simplified by using 'fold expressions'. - (void)std::initializer_list<int>{ - 0, (addImpl<Ts>(/*debugLabels=*/llvm::None, - std::forward<ConstructorArg>(arg), - std::forward<ConstructorArgs>(args)...), - 0)...}; + // types 'Ts'. + (addImpl<Ts>(/*debugLabels=*/llvm::None, std::forward<ConstructorArg>(arg), + std::forward<ConstructorArgs>(args)...), + ...); return *this; } /// An overload of the above `add` method that allows for attaching a set @@ -1433,11 +1421,8 @@ ConstructorArg &&arg, ConstructorArgs &&...args) { // The following expands a call to emplace_back for each of the pattern - // types 'Ts'. This magic is necessary due to a limitation in the places - // that a parameter pack can be expanded in c++11. - // FIXME: In c++17 this can be simplified by using 'fold expressions'. - (void)std::initializer_list<int>{ - 0, (addImpl<Ts>(debugLabels, arg, args...), 0)...}; + // types 'Ts'. + (addImpl<Ts>(debugLabels, arg, args...), ...); return *this; } @@ -1445,7 +1430,7 @@ /// `this` for chaining insertions. template <typename... Ts> RewritePatternSet &add() { - (void)std::initializer_list<int>{0, (addImpl<Ts>(), 0)...}; + (addImpl<Ts>(), ...); return *this; } @@ -1498,11 +1483,8 @@ typename = std::enable_if_t<sizeof...(Ts) != 0>> RewritePatternSet &insert(ConstructorArg &&arg, ConstructorArgs &&...args) { // The following expands a call to emplace_back for each of the pattern - // types 'Ts'. This magic is necessary due to a limitation in the places - // that a parameter pack can be expanded in c++11. - // FIXME: In c++17 this can be simplified by using 'fold expressions'. - (void)std::initializer_list<int>{ - 0, (addImpl<Ts>(/*debugLabels=*/llvm::None, arg, args...), 0)...}; + // types 'Ts'. + (addImpl<Ts>(/*debugLabels=*/llvm::None, arg, args...), ...); return *this; } @@ -1510,7 +1492,7 @@ /// `this` for chaining insertions. template <typename... Ts> RewritePatternSet &insert() { - (void)std::initializer_list<int>{0, (addImpl<Ts>(), 0)...}; + (addImpl<Ts>(), ...); return *this; } diff --git a/mlir/include/mlir/IR/StorageUniquerSupport.h b/mlir/include/mlir/IR/StorageUniquerSupport.h --- a/mlir/include/mlir/IR/StorageUniquerSupport.h +++ b/mlir/include/mlir/IR/StorageUniquerSupport.h @@ -138,8 +138,8 @@ if (!abstract) llvm::report_fatal_error("Registering an interface for an attribute/type " "that is not itself registered."); - (void)std::initializer_list<int>{ - (checkInterfaceTarget<IfaceModels>(), 0)...}; + + (checkInterfaceTarget<IfaceModels>(), ...); abstract->interfaceMap.template insert<IfaceModels...>(); } diff --git a/mlir/include/mlir/Support/InterfaceSupport.h b/mlir/include/mlir/Support/InterfaceSupport.h --- a/mlir/include/mlir/Support/InterfaceSupport.h +++ b/mlir/include/mlir/Support/InterfaceSupport.h @@ -191,16 +191,14 @@ /// do not represent interfaces are not added to the interface map. template <typename... Types> static InterfaceMap get() { - // TODO: Use constexpr if here in C++17. constexpr size_t numInterfaces = num_interface_types_t<Types...>::value; - if (numInterfaces == 0) + if constexpr (numInterfaces == 0) return InterfaceMap(); std::array<std::pair<TypeID, void *>, numInterfaces> elements; std::pair<TypeID, void *> *elementIt = elements.data(); (void)elementIt; - (void)std::initializer_list<int>{ - 0, (addModelAndUpdateIterator<Types>(elementIt), 0)...}; + (addModelAndUpdateIterator<Types>(elementIt), ...); return InterfaceMap(elements); } diff --git a/mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp b/mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp --- a/mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp +++ b/mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp @@ -178,15 +178,12 @@ } /// The minimum alignment to use with aligned_alloc (has to be a power of 2). - static constexpr uint64_t kMinAlignedAllocAlignment = 16UL; + static inline constexpr uint64_t kMinAlignedAllocAlignment = 16UL; /// Default layout to use in absence of the corresponding analysis. DataLayout defaultLayout; }; -// Out of line definition, required till C++17. -constexpr uint64_t AlignedAllocOpLowering::kMinAlignedAllocAlignment; - struct AllocaOpLowering : public AllocLikeOpLLVMLowering { AllocaOpLowering(LLVMTypeConverter &converter) : AllocLikeOpLLVMLowering(memref::AllocaOp::getOperationName(), diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgDialect.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgDialect.cpp --- a/mlir/lib/Dialect/Linalg/IR/LinalgDialect.cpp +++ b/mlir/lib/Dialect/Linalg/IR/LinalgDialect.cpp @@ -96,8 +96,7 @@ template <typename... OpTypes> void addNamedOpBuilders( llvm::StringMap<LinalgDialect::RegionBuilderFunType> &map) { - (void)std::initializer_list<int>{0, - (addNamedOpBuilderImpl<OpTypes>(map), 0)...}; + (addNamedOpBuilderImpl<OpTypes>(map), ...); } void mlir::linalg::LinalgDialect::initialize() { diff --git a/mlir/lib/Dialect/Linalg/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Linalg/Transforms/BufferizableOpInterfaceImpl.cpp --- a/mlir/lib/Dialect/Linalg/Transforms/BufferizableOpInterfaceImpl.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/BufferizableOpInterfaceImpl.cpp @@ -137,8 +137,7 @@ template <typename... Ops> struct LinalgOpInterfaceHelper { static void registerOpInterface(MLIRContext *ctx) { - (void)std::initializer_list<int>{ - 0, (Ops::template attachInterface<LinalgOpInterface<Ops>>(*ctx), 0)...}; + (Ops::template attachInterface<LinalgOpInterface<Ops>>(*ctx), ...); } }; } // namespace diff --git a/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp b/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp --- a/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp @@ -263,8 +263,7 @@ /// Variadic helper function. template <typename... OpTypes> static void registerAll(MLIRContext *ctx) { - // FIXME: In c++17 this can be simplified by using 'fold expressions'. - (void)std::initializer_list<int>{0, (registerOne<OpTypes>(ctx), 0)...}; + (registerOne<OpTypes>(ctx), ...); } #define GET_OP_LIST diff --git a/mlir/lib/Dialect/Tosa/Transforms/TosaLayerwiseConstantFoldPass.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaLayerwiseConstantFoldPass.cpp --- a/mlir/lib/Dialect/Tosa/Transforms/TosaLayerwiseConstantFoldPass.cpp +++ b/mlir/lib/Dialect/Tosa/Transforms/TosaLayerwiseConstantFoldPass.cpp @@ -23,8 +23,7 @@ template <typename... Args> void addOpsCanonicalizations(MLIRContext *ctx, RewritePatternSet &patterns) { - (void)std::initializer_list<int>{ - 0, (Args::getCanonicalizationPatterns(patterns, ctx), 0)...}; + (Args::getCanonicalizationPatterns(patterns, ctx), ...); } void populateTosaOpsCanonicalizationPatterns(MLIRContext *ctx, diff --git a/mlir/lib/IR/BuiltinTypes.cpp b/mlir/lib/IR/BuiltinTypes.cpp --- a/mlir/lib/IR/BuiltinTypes.cpp +++ b/mlir/lib/IR/BuiltinTypes.cpp @@ -60,9 +60,6 @@ // Integer Type //===----------------------------------------------------------------------===// -// static constexpr must have a definition (until in C++17 and inline variable). -constexpr unsigned IntegerType::kMaxWidth; - /// Verify the construction of an integer type. LogicalResult IntegerType::verify(function_ref<InFlightDiagnostic()> emitError, unsigned width,