[Mlir-commits] [mlir] 0a81ace - [mlir] Use std::optional instead of llvm::Optional (NFC)

Kazu Hirata llvmlistbot at llvm.org
Sat Jan 14 01:26:07 PST 2023


Author: Kazu Hirata
Date: 2023-01-14T01:25:58-08:00
New Revision: 0a81ace0047a2de93e71c82cdf0977fc989660df

URL: https://github.com/llvm/llvm-project/commit/0a81ace0047a2de93e71c82cdf0977fc989660df
DIFF: https://github.com/llvm/llvm-project/commit/0a81ace0047a2de93e71c82cdf0977fc989660df.diff

LOG: [mlir] Use std::optional instead of llvm::Optional (NFC)

This patch replaces (llvm::|)Optional< with std::optional<.  I'll post
a separate patch to remove #include "llvm/ADT/Optional.h".

This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716

Added: 
    

Modified: 
    mlir/examples/toy/Ch1/include/toy/AST.h
    mlir/examples/toy/Ch1/include/toy/Parser.h
    mlir/examples/toy/Ch2/include/toy/AST.h
    mlir/examples/toy/Ch2/include/toy/Parser.h
    mlir/examples/toy/Ch3/include/toy/AST.h
    mlir/examples/toy/Ch3/include/toy/Parser.h
    mlir/examples/toy/Ch4/include/toy/AST.h
    mlir/examples/toy/Ch4/include/toy/Parser.h
    mlir/examples/toy/Ch5/include/toy/AST.h
    mlir/examples/toy/Ch5/include/toy/Parser.h
    mlir/examples/toy/Ch6/include/toy/AST.h
    mlir/examples/toy/Ch6/include/toy/Parser.h
    mlir/examples/toy/Ch7/include/toy/AST.h
    mlir/examples/toy/Ch7/include/toy/Parser.h
    mlir/examples/toy/Ch7/mlir/MLIRGen.cpp
    mlir/include/mlir/Analysis/DataFlow/ConstantPropagationAnalysis.h
    mlir/include/mlir/Analysis/DataFlow/DeadCodeAnalysis.h
    mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
    mlir/include/mlir/Analysis/Presburger/PWMAFunction.h
    mlir/include/mlir/Analysis/Presburger/PresburgerRelation.h
    mlir/include/mlir/Analysis/Presburger/Simplex.h
    mlir/include/mlir/Analysis/Presburger/Utils.h
    mlir/include/mlir/Conversion/MathToLibm/MathToLibm.h
    mlir/include/mlir/Dialect/Affine/Analysis/AffineAnalysis.h
    mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h
    mlir/include/mlir/Dialect/Affine/Analysis/LoopAnalysis.h
    mlir/include/mlir/Dialect/Affine/Analysis/Utils.h
    mlir/include/mlir/Dialect/Affine/LoopUtils.h
    mlir/include/mlir/Dialect/Affine/Utils.h
    mlir/include/mlir/Dialect/Async/IR/AsyncOps.td
    mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
    mlir/include/mlir/Dialect/CommonFolders.h
    mlir/include/mlir/Dialect/Func/Transforms/DecomposeCallGraphTypes.h
    mlir/include/mlir/Dialect/GPU/IR/GPUOps.td
    mlir/include/mlir/Dialect/GPU/Transforms/Passes.h
    mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
    mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
    mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
    mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h
    mlir/include/mlir/Dialect/Linalg/Analysis/DependenceAnalysis.h
    mlir/include/mlir/Dialect/Linalg/IR/Linalg.h
    mlir/include/mlir/Dialect/Linalg/Utils/Utils.h
    mlir/include/mlir/Dialect/MemRef/IR/MemRef.h
    mlir/include/mlir/Dialect/PDL/IR/PDLOps.td
    mlir/include/mlir/Dialect/SCF/Utils/Utils.h
    mlir/include/mlir/Dialect/SPIRV/IR/SPIRVControlFlowOps.td
    mlir/include/mlir/Dialect/SPIRV/IR/TargetAndABI.h
    mlir/include/mlir/Dialect/SparseTensor/Utils/Merger.h
    mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
    mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h
    mlir/include/mlir/Dialect/Transform/IR/TransformDialect.h
    mlir/include/mlir/Dialect/Transform/Utils/DiagnosedSilenceableFailure.h
    mlir/include/mlir/Dialect/Utils/IndexingUtils.h
    mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h
    mlir/include/mlir/Dialect/Vector/Transforms/VectorRewritePatterns.h
    mlir/include/mlir/ExecutionEngine/ExecutionEngine.h
    mlir/include/mlir/ExecutionEngine/MemRefUtils.h
    mlir/include/mlir/IR/AffineMap.h
    mlir/include/mlir/IR/Builders.h
    mlir/include/mlir/IR/BuiltinAttributeInterfaces.h
    mlir/include/mlir/IR/BuiltinAttributeInterfaces.td
    mlir/include/mlir/IR/BuiltinAttributes.h
    mlir/include/mlir/IR/BuiltinAttributes.td
    mlir/include/mlir/IR/Diagnostics.h
    mlir/include/mlir/IR/DialectResourceBlobManager.h
    mlir/include/mlir/IR/OpDefinition.h
    mlir/include/mlir/IR/OpImplementation.h
    mlir/include/mlir/IR/Operation.h
    mlir/include/mlir/IR/OperationSupport.h
    mlir/include/mlir/IR/PatternMatch.h
    mlir/include/mlir/IR/SubElementInterfaces.h
    mlir/include/mlir/IR/ValueRange.h
    mlir/include/mlir/Interfaces/InferIntRangeInterface.h
    mlir/include/mlir/Pass/AnalysisManager.h
    mlir/include/mlir/Pass/Pass.h
    mlir/include/mlir/Pass/PassInstrumentation.h
    mlir/include/mlir/Pass/PassManager.h
    mlir/include/mlir/Pass/PassRegistry.h
    mlir/include/mlir/Support/LogicalResult.h
    mlir/include/mlir/Support/Timing.h
    mlir/include/mlir/Tools/PDLL/AST/Diagnostic.h
    mlir/include/mlir/Tools/PDLL/AST/Nodes.h
    mlir/include/mlir/Tools/PDLL/AST/Types.h
    mlir/include/mlir/Tools/PDLL/Parser/CodeComplete.h
    mlir/include/mlir/Tools/mlir-translate/Translation.h
    mlir/include/mlir/Transforms/InliningUtils.h
    mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp
    mlir/lib/Analysis/DataFlow/IntegerRangeAnalysis.cpp
    mlir/lib/Analysis/Presburger/IntegerRelation.cpp
    mlir/lib/Analysis/Presburger/PWMAFunction.cpp
    mlir/lib/Analysis/Presburger/PresburgerRelation.cpp
    mlir/lib/Analysis/Presburger/Simplex.cpp
    mlir/lib/Analysis/Presburger/Utils.cpp
    mlir/lib/AsmParser/AsmParserImpl.h
    mlir/lib/AsmParser/AttributeParser.cpp
    mlir/lib/AsmParser/Parser.cpp
    mlir/lib/AsmParser/Parser.h
    mlir/lib/AsmParser/Token.cpp
    mlir/lib/AsmParser/Token.h
    mlir/lib/AsmParser/TypeParser.cpp
    mlir/lib/Bindings/Python/DialectSparseTensor.cpp
    mlir/lib/Bindings/Python/Globals.h
    mlir/lib/Bindings/Python/IRAttributes.cpp
    mlir/lib/Bindings/Python/IRCore.cpp
    mlir/lib/Bindings/Python/IRInterfaces.cpp
    mlir/lib/Bindings/Python/IRModule.cpp
    mlir/lib/Bindings/Python/IRModule.h
    mlir/lib/Bindings/Python/IRTypes.cpp
    mlir/lib/Bytecode/Reader/BytecodeReader.cpp
    mlir/lib/CAPI/IR/IR.cpp
    mlir/lib/CAPI/IR/Pass.cpp
    mlir/lib/CAPI/Interfaces/Interfaces.cpp
    mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp
    mlir/lib/Conversion/GPUToSPIRV/GPUToSPIRV.cpp
    mlir/lib/Conversion/MathToLibm/MathToLibm.cpp
    mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp
    mlir/lib/Conversion/SCFToGPU/SCFToGPU.cpp
    mlir/lib/Conversion/VectorToSCF/VectorToSCF.cpp
    mlir/lib/Dialect/AMDGPU/IR/AMDGPUDialect.cpp
    mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp
    mlir/lib/Dialect/Affine/Analysis/AffineStructures.cpp
    mlir/lib/Dialect/Affine/Analysis/LoopAnalysis.cpp
    mlir/lib/Dialect/Affine/Analysis/Utils.cpp
    mlir/lib/Dialect/Affine/Transforms/AffineDataCopyGeneration.cpp
    mlir/lib/Dialect/Affine/Transforms/LoopFusion.cpp
    mlir/lib/Dialect/Affine/Transforms/LoopTiling.cpp
    mlir/lib/Dialect/Affine/Transforms/LoopUnroll.cpp
    mlir/lib/Dialect/Affine/Transforms/LoopUnrollAndJam.cpp
    mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp
    mlir/lib/Dialect/Affine/Utils/LoopFusionUtils.cpp
    mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp
    mlir/lib/Dialect/Affine/Utils/Utils.cpp
    mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp
    mlir/lib/Dialect/Async/Transforms/AsyncToAsyncRuntime.cpp
    mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
    mlir/lib/Dialect/Bufferization/Transforms/BufferUtils.cpp
    mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp
    mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
    mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
    mlir/lib/Dialect/GPU/IR/InferIntRangeInterfaceImpls.cpp
    mlir/lib/Dialect/GPU/Transforms/LowerMemorySpaceAttributes.cpp
    mlir/lib/Dialect/GPU/Transforms/SerializeToBlob.cpp
    mlir/lib/Dialect/GPU/Transforms/SerializeToHsaco.cpp
    mlir/lib/Dialect/Index/IR/IndexOps.cpp
    mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
    mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
    mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp
    mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
    mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
    mlir/lib/Dialect/Linalg/Transforms/ConstantFold.cpp
    mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp
    mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp
    mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp
    mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp
    mlir/lib/Dialect/Linalg/Transforms/FusionOnTensors.cpp
    mlir/lib/Dialect/Linalg/Transforms/SplitReduction.cpp
    mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp
    mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
    mlir/lib/Dialect/Linalg/Utils/Utils.cpp
    mlir/lib/Dialect/Math/IR/MathOps.cpp
    mlir/lib/Dialect/MemRef/IR/MemRefDialect.cpp
    mlir/lib/Dialect/MemRef/Transforms/ExpandStridedMetadata.cpp
    mlir/lib/Dialect/PDL/IR/PDL.cpp
    mlir/lib/Dialect/SCF/Transforms/StructuralTypeConversions.cpp
    mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp
    mlir/lib/Dialect/SPIRV/IR/TargetAndABI.cpp
    mlir/lib/Dialect/SPIRV/Transforms/UpdateVCEPass.cpp
    mlir/lib/Dialect/SparseTensor/Transforms/CodegenEnv.cpp
    mlir/lib/Dialect/SparseTensor/Transforms/CodegenEnv.h
    mlir/lib/Dialect/SparseTensor/Transforms/CodegenUtils.cpp
    mlir/lib/Dialect/SparseTensor/Transforms/SparseStorageSpecifierToLLVM.cpp
    mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp
    mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp
    mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp
    mlir/lib/Dialect/Tensor/IR/TensorOps.cpp
    mlir/lib/Dialect/Traits.cpp
    mlir/lib/Dialect/Utils/IndexingUtils.cpp
    mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp
    mlir/lib/Dialect/Vector/Transforms/VectorTransferSplitRewritePatterns.cpp
    mlir/lib/Dialect/Vector/Transforms/VectorUnroll.cpp
    mlir/lib/ExecutionEngine/JitRunner.cpp
    mlir/lib/IR/AffineExpr.cpp
    mlir/lib/IR/AffineMap.cpp
    mlir/lib/IR/AsmPrinter.cpp
    mlir/lib/IR/BuiltinAttributes.cpp
    mlir/lib/IR/Diagnostics.cpp
    mlir/lib/IR/DialectResourceBlobManager.cpp
    mlir/lib/IR/MLIRContext.cpp
    mlir/lib/IR/OperationSupport.cpp
    mlir/lib/IR/SubElementInterfaces.cpp
    mlir/lib/IR/SymbolTable.cpp
    mlir/lib/IR/Verifier.cpp
    mlir/lib/Interfaces/InferIntRangeInterface.cpp
    mlir/lib/Pass/Pass.cpp
    mlir/lib/Pass/PassRegistry.cpp
    mlir/lib/Pass/PassTiming.cpp
    mlir/lib/Rewrite/ByteCode.cpp
    mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
    mlir/lib/Support/Timing.cpp
    mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
    mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
    mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp
    mlir/lib/Target/SPIRV/Deserialization/Deserializer.h
    mlir/lib/Target/SPIRV/Serialization/Serializer.cpp
    mlir/lib/Tools/PDLL/AST/NodePrinter.cpp
    mlir/lib/Tools/PDLL/AST/Nodes.cpp
    mlir/lib/Tools/PDLL/AST/Types.cpp
    mlir/lib/Tools/PDLL/CodeGen/CPPGen.cpp
    mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp
    mlir/lib/Tools/PDLL/Parser/Parser.cpp
    mlir/lib/Tools/lsp-server-support/Protocol.h
    mlir/lib/Tools/lsp-server-support/SourceMgrUtils.cpp
    mlir/lib/Tools/lsp-server-support/SourceMgrUtils.h
    mlir/lib/Tools/lsp-server-support/Transport.cpp
    mlir/lib/Tools/mlir-lsp-server/LSPServer.cpp
    mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp
    mlir/lib/Tools/mlir-lsp-server/MLIRServer.h
    mlir/lib/Tools/mlir-pdll-lsp-server/LSPServer.cpp
    mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.cpp
    mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.h
    mlir/lib/Tools/mlir-translate/Translation.cpp
    mlir/lib/Tools/tblgen-lsp-server/LSPServer.cpp
    mlir/lib/Tools/tblgen-lsp-server/TableGenServer.cpp
    mlir/lib/Tools/tblgen-lsp-server/TableGenServer.h
    mlir/lib/Transforms/LocationSnapshot.cpp
    mlir/lib/Transforms/Utils/InliningUtils.cpp
    mlir/lib/Transforms/ViewOpGraph.cpp
    mlir/test/lib/Analysis/DataFlow/TestDenseDataFlowAnalysis.cpp
    mlir/test/lib/Analysis/TestDataFlowFramework.cpp
    mlir/test/lib/Dialect/Shape/TestShapeMappingAnalysis.cpp
    mlir/test/lib/Dialect/Test/TestDialect.cpp
    mlir/test/lib/Dialect/Test/TestTypeDefs.td
    mlir/test/lib/Dialect/Test/TestTypes.cpp
    mlir/test/lib/Dialect/Test/TestTypes.h
    mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp
    mlir/test/lib/Interfaces/TilingInterface/TestTilingInterface.cpp
    mlir/test/lib/Transforms/TestIntRangeInference.cpp
    mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp
    mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp
    mlir/unittests/Analysis/Presburger/IntegerPolyhedronTest.cpp
    mlir/unittests/Analysis/Presburger/PresburgerSetTest.cpp
    mlir/unittests/Analysis/Presburger/SimplexTest.cpp
    mlir/unittests/Analysis/Presburger/Utils.h
    mlir/unittests/IR/AttributeTest.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/examples/toy/Ch1/include/toy/AST.h b/mlir/examples/toy/Ch1/include/toy/AST.h
index 3b332314d4f7d..d2ba101dea5a4 100644
--- a/mlir/examples/toy/Ch1/include/toy/AST.h
+++ b/mlir/examples/toy/Ch1/include/toy/AST.h
@@ -129,13 +129,13 @@ class VarDeclExprAST : public ExprAST {
 
 /// Expression class for a return operator.
 class ReturnExprAST : public ExprAST {
-  llvm::Optional<std::unique_ptr<ExprAST>> expr;
+  std::optional<std::unique_ptr<ExprAST>> expr;
 
 public:
-  ReturnExprAST(Location loc, llvm::Optional<std::unique_ptr<ExprAST>> expr)
+  ReturnExprAST(Location loc, std::optional<std::unique_ptr<ExprAST>> expr)
       : ExprAST(Expr_Return, std::move(loc)), expr(std::move(expr)) {}
 
-  llvm::Optional<ExprAST *> getExpr() {
+  std::optional<ExprAST *> getExpr() {
     if (expr.has_value())
       return expr->get();
     return std::nullopt;

diff  --git a/mlir/examples/toy/Ch1/include/toy/Parser.h b/mlir/examples/toy/Ch1/include/toy/Parser.h
index 652258e649817..9b0906da34b69 100644
--- a/mlir/examples/toy/Ch1/include/toy/Parser.h
+++ b/mlir/examples/toy/Ch1/include/toy/Parser.h
@@ -67,7 +67,7 @@ class Parser {
     lexer.consume(tok_return);
 
     // return takes an optional argument
-    llvm::Optional<std::unique_ptr<ExprAST>> expr;
+    std::optional<std::unique_ptr<ExprAST>> expr;
     if (lexer.getCurToken() != ';') {
       expr = parseExpression();
       if (!expr)

diff  --git a/mlir/examples/toy/Ch2/include/toy/AST.h b/mlir/examples/toy/Ch2/include/toy/AST.h
index 3b332314d4f7d..d2ba101dea5a4 100644
--- a/mlir/examples/toy/Ch2/include/toy/AST.h
+++ b/mlir/examples/toy/Ch2/include/toy/AST.h
@@ -129,13 +129,13 @@ class VarDeclExprAST : public ExprAST {
 
 /// Expression class for a return operator.
 class ReturnExprAST : public ExprAST {
-  llvm::Optional<std::unique_ptr<ExprAST>> expr;
+  std::optional<std::unique_ptr<ExprAST>> expr;
 
 public:
-  ReturnExprAST(Location loc, llvm::Optional<std::unique_ptr<ExprAST>> expr)
+  ReturnExprAST(Location loc, std::optional<std::unique_ptr<ExprAST>> expr)
       : ExprAST(Expr_Return, std::move(loc)), expr(std::move(expr)) {}
 
-  llvm::Optional<ExprAST *> getExpr() {
+  std::optional<ExprAST *> getExpr() {
     if (expr.has_value())
       return expr->get();
     return std::nullopt;

diff  --git a/mlir/examples/toy/Ch2/include/toy/Parser.h b/mlir/examples/toy/Ch2/include/toy/Parser.h
index 652258e649817..9b0906da34b69 100644
--- a/mlir/examples/toy/Ch2/include/toy/Parser.h
+++ b/mlir/examples/toy/Ch2/include/toy/Parser.h
@@ -67,7 +67,7 @@ class Parser {
     lexer.consume(tok_return);
 
     // return takes an optional argument
-    llvm::Optional<std::unique_ptr<ExprAST>> expr;
+    std::optional<std::unique_ptr<ExprAST>> expr;
     if (lexer.getCurToken() != ';') {
       expr = parseExpression();
       if (!expr)

diff  --git a/mlir/examples/toy/Ch3/include/toy/AST.h b/mlir/examples/toy/Ch3/include/toy/AST.h
index 3b332314d4f7d..d2ba101dea5a4 100644
--- a/mlir/examples/toy/Ch3/include/toy/AST.h
+++ b/mlir/examples/toy/Ch3/include/toy/AST.h
@@ -129,13 +129,13 @@ class VarDeclExprAST : public ExprAST {
 
 /// Expression class for a return operator.
 class ReturnExprAST : public ExprAST {
-  llvm::Optional<std::unique_ptr<ExprAST>> expr;
+  std::optional<std::unique_ptr<ExprAST>> expr;
 
 public:
-  ReturnExprAST(Location loc, llvm::Optional<std::unique_ptr<ExprAST>> expr)
+  ReturnExprAST(Location loc, std::optional<std::unique_ptr<ExprAST>> expr)
       : ExprAST(Expr_Return, std::move(loc)), expr(std::move(expr)) {}
 
-  llvm::Optional<ExprAST *> getExpr() {
+  std::optional<ExprAST *> getExpr() {
     if (expr.has_value())
       return expr->get();
     return std::nullopt;

diff  --git a/mlir/examples/toy/Ch3/include/toy/Parser.h b/mlir/examples/toy/Ch3/include/toy/Parser.h
index 652258e649817..9b0906da34b69 100644
--- a/mlir/examples/toy/Ch3/include/toy/Parser.h
+++ b/mlir/examples/toy/Ch3/include/toy/Parser.h
@@ -67,7 +67,7 @@ class Parser {
     lexer.consume(tok_return);
 
     // return takes an optional argument
-    llvm::Optional<std::unique_ptr<ExprAST>> expr;
+    std::optional<std::unique_ptr<ExprAST>> expr;
     if (lexer.getCurToken() != ';') {
       expr = parseExpression();
       if (!expr)

diff  --git a/mlir/examples/toy/Ch4/include/toy/AST.h b/mlir/examples/toy/Ch4/include/toy/AST.h
index 3b332314d4f7d..d2ba101dea5a4 100644
--- a/mlir/examples/toy/Ch4/include/toy/AST.h
+++ b/mlir/examples/toy/Ch4/include/toy/AST.h
@@ -129,13 +129,13 @@ class VarDeclExprAST : public ExprAST {
 
 /// Expression class for a return operator.
 class ReturnExprAST : public ExprAST {
-  llvm::Optional<std::unique_ptr<ExprAST>> expr;
+  std::optional<std::unique_ptr<ExprAST>> expr;
 
 public:
-  ReturnExprAST(Location loc, llvm::Optional<std::unique_ptr<ExprAST>> expr)
+  ReturnExprAST(Location loc, std::optional<std::unique_ptr<ExprAST>> expr)
       : ExprAST(Expr_Return, std::move(loc)), expr(std::move(expr)) {}
 
-  llvm::Optional<ExprAST *> getExpr() {
+  std::optional<ExprAST *> getExpr() {
     if (expr.has_value())
       return expr->get();
     return std::nullopt;

diff  --git a/mlir/examples/toy/Ch4/include/toy/Parser.h b/mlir/examples/toy/Ch4/include/toy/Parser.h
index 652258e649817..9b0906da34b69 100644
--- a/mlir/examples/toy/Ch4/include/toy/Parser.h
+++ b/mlir/examples/toy/Ch4/include/toy/Parser.h
@@ -67,7 +67,7 @@ class Parser {
     lexer.consume(tok_return);
 
     // return takes an optional argument
-    llvm::Optional<std::unique_ptr<ExprAST>> expr;
+    std::optional<std::unique_ptr<ExprAST>> expr;
     if (lexer.getCurToken() != ';') {
       expr = parseExpression();
       if (!expr)

diff  --git a/mlir/examples/toy/Ch5/include/toy/AST.h b/mlir/examples/toy/Ch5/include/toy/AST.h
index 3b332314d4f7d..d2ba101dea5a4 100644
--- a/mlir/examples/toy/Ch5/include/toy/AST.h
+++ b/mlir/examples/toy/Ch5/include/toy/AST.h
@@ -129,13 +129,13 @@ class VarDeclExprAST : public ExprAST {
 
 /// Expression class for a return operator.
 class ReturnExprAST : public ExprAST {
-  llvm::Optional<std::unique_ptr<ExprAST>> expr;
+  std::optional<std::unique_ptr<ExprAST>> expr;
 
 public:
-  ReturnExprAST(Location loc, llvm::Optional<std::unique_ptr<ExprAST>> expr)
+  ReturnExprAST(Location loc, std::optional<std::unique_ptr<ExprAST>> expr)
       : ExprAST(Expr_Return, std::move(loc)), expr(std::move(expr)) {}
 
-  llvm::Optional<ExprAST *> getExpr() {
+  std::optional<ExprAST *> getExpr() {
     if (expr.has_value())
       return expr->get();
     return std::nullopt;

diff  --git a/mlir/examples/toy/Ch5/include/toy/Parser.h b/mlir/examples/toy/Ch5/include/toy/Parser.h
index 652258e649817..9b0906da34b69 100644
--- a/mlir/examples/toy/Ch5/include/toy/Parser.h
+++ b/mlir/examples/toy/Ch5/include/toy/Parser.h
@@ -67,7 +67,7 @@ class Parser {
     lexer.consume(tok_return);
 
     // return takes an optional argument
-    llvm::Optional<std::unique_ptr<ExprAST>> expr;
+    std::optional<std::unique_ptr<ExprAST>> expr;
     if (lexer.getCurToken() != ';') {
       expr = parseExpression();
       if (!expr)

diff  --git a/mlir/examples/toy/Ch6/include/toy/AST.h b/mlir/examples/toy/Ch6/include/toy/AST.h
index 3b332314d4f7d..d2ba101dea5a4 100644
--- a/mlir/examples/toy/Ch6/include/toy/AST.h
+++ b/mlir/examples/toy/Ch6/include/toy/AST.h
@@ -129,13 +129,13 @@ class VarDeclExprAST : public ExprAST {
 
 /// Expression class for a return operator.
 class ReturnExprAST : public ExprAST {
-  llvm::Optional<std::unique_ptr<ExprAST>> expr;
+  std::optional<std::unique_ptr<ExprAST>> expr;
 
 public:
-  ReturnExprAST(Location loc, llvm::Optional<std::unique_ptr<ExprAST>> expr)
+  ReturnExprAST(Location loc, std::optional<std::unique_ptr<ExprAST>> expr)
       : ExprAST(Expr_Return, std::move(loc)), expr(std::move(expr)) {}
 
-  llvm::Optional<ExprAST *> getExpr() {
+  std::optional<ExprAST *> getExpr() {
     if (expr.has_value())
       return expr->get();
     return std::nullopt;

diff  --git a/mlir/examples/toy/Ch6/include/toy/Parser.h b/mlir/examples/toy/Ch6/include/toy/Parser.h
index 652258e649817..9b0906da34b69 100644
--- a/mlir/examples/toy/Ch6/include/toy/Parser.h
+++ b/mlir/examples/toy/Ch6/include/toy/Parser.h
@@ -67,7 +67,7 @@ class Parser {
     lexer.consume(tok_return);
 
     // return takes an optional argument
-    llvm::Optional<std::unique_ptr<ExprAST>> expr;
+    std::optional<std::unique_ptr<ExprAST>> expr;
     if (lexer.getCurToken() != ';') {
       expr = parseExpression();
       if (!expr)

diff  --git a/mlir/examples/toy/Ch7/include/toy/AST.h b/mlir/examples/toy/Ch7/include/toy/AST.h
index e5bd0690d2753..42d64ed853add 100644
--- a/mlir/examples/toy/Ch7/include/toy/AST.h
+++ b/mlir/examples/toy/Ch7/include/toy/AST.h
@@ -149,13 +149,13 @@ class VarDeclExprAST : public ExprAST {
 
 /// Expression class for a return operator.
 class ReturnExprAST : public ExprAST {
-  llvm::Optional<std::unique_ptr<ExprAST>> expr;
+  std::optional<std::unique_ptr<ExprAST>> expr;
 
 public:
-  ReturnExprAST(Location loc, llvm::Optional<std::unique_ptr<ExprAST>> expr)
+  ReturnExprAST(Location loc, std::optional<std::unique_ptr<ExprAST>> expr)
       : ExprAST(Expr_Return, std::move(loc)), expr(std::move(expr)) {}
 
-  llvm::Optional<ExprAST *> getExpr() {
+  std::optional<ExprAST *> getExpr() {
     if (expr.has_value())
       return expr->get();
     return std::nullopt;

diff  --git a/mlir/examples/toy/Ch7/include/toy/Parser.h b/mlir/examples/toy/Ch7/include/toy/Parser.h
index 90b1edaf6748f..abfd2f5635f1f 100644
--- a/mlir/examples/toy/Ch7/include/toy/Parser.h
+++ b/mlir/examples/toy/Ch7/include/toy/Parser.h
@@ -82,7 +82,7 @@ class Parser {
     lexer.consume(tok_return);
 
     // return takes an optional argument
-    llvm::Optional<std::unique_ptr<ExprAST>> expr;
+    std::optional<std::unique_ptr<ExprAST>> expr;
     if (lexer.getCurToken() != ';') {
       expr = parseExpression();
       if (!expr)

diff  --git a/mlir/examples/toy/Ch7/mlir/MLIRGen.cpp b/mlir/examples/toy/Ch7/mlir/MLIRGen.cpp
index d5035babe5c35..7f2a4c29ca6b5 100644
--- a/mlir/examples/toy/Ch7/mlir/MLIRGen.cpp
+++ b/mlir/examples/toy/Ch7/mlir/MLIRGen.cpp
@@ -271,7 +271,7 @@ class MLIRGenImpl {
   }
 
   /// Return the numeric member index of the given struct access expression.
-  llvm::Optional<size_t> getMemberIndex(BinaryExprAST &accessOp) {
+  std::optional<size_t> getMemberIndex(BinaryExprAST &accessOp) {
     assert(accessOp.getOp() == '.' && "expected access operation");
 
     // Lookup the struct node for the LHS.
@@ -313,7 +313,7 @@ class MLIRGenImpl {
 
     // If this is an access operation, handle it immediately.
     if (binop.getOp() == '.') {
-      llvm::Optional<size_t> accessIndex = getMemberIndex(binop);
+      std::optional<size_t> accessIndex = getMemberIndex(binop);
       if (!accessIndex) {
         emitError(location, "invalid access into struct expression");
         return nullptr;

diff  --git a/mlir/include/mlir/Analysis/DataFlow/ConstantPropagationAnalysis.h b/mlir/include/mlir/Analysis/DataFlow/ConstantPropagationAnalysis.h
index 3f5fc6bc4c98b..715eae1d61b2a 100644
--- a/mlir/include/mlir/Analysis/DataFlow/ConstantPropagationAnalysis.h
+++ b/mlir/include/mlir/Analysis/DataFlow/ConstantPropagationAnalysis.h
@@ -83,7 +83,7 @@ class ConstantValue {
 
 private:
   /// The constant value.
-  Optional<Attribute> constant;
+  std::optional<Attribute> constant;
   /// A dialect instance that can be used to materialize the constant.
   Dialect *dialect = nullptr;
 };

diff  --git a/mlir/include/mlir/Analysis/DataFlow/DeadCodeAnalysis.h b/mlir/include/mlir/Analysis/DataFlow/DeadCodeAnalysis.h
index 6028b5b4d6838..311b81ae90104 100644
--- a/mlir/include/mlir/Analysis/DataFlow/DeadCodeAnalysis.h
+++ b/mlir/include/mlir/Analysis/DataFlow/DeadCodeAnalysis.h
@@ -221,7 +221,7 @@ class DeadCodeAnalysis : public DataFlowAnalysis {
 
   /// Get the constant values of the operands of the operation. Returns none if
   /// any of the operand lattices are uninitialized.
-  Optional<SmallVector<Attribute>> getOperandValues(Operation *op);
+  std::optional<SmallVector<Attribute>> getOperandValues(Operation *op);
 
   /// The top-level operation the analysis is running on. This is used to detect
   /// if a callable is outside the scope of the analysis and thus must be

diff  --git a/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h b/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
index 031fb02c77314..527faf3d41812 100644
--- a/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
+++ b/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
@@ -362,12 +362,12 @@ class IntegerRelation {
   ///
   /// Returns an integer sample point if one exists, or an empty Optional
   /// otherwise. The returned value also includes values of local ids.
-  Optional<SmallVector<MPInt, 8>> findIntegerSample() const;
+  std::optional<SmallVector<MPInt, 8>> findIntegerSample() const;
 
   /// Compute an overapproximation of the number of integer points in the
   /// relation. Symbol vars currently not supported. If the computed
   /// overapproximation is infinite, an empty optional is returned.
-  Optional<MPInt> computeVolume() const;
+  std::optional<MPInt> computeVolume() const;
 
   /// Returns true if the given point satisfies the constraints, or false
   /// otherwise. Takes the values of all vars including locals.
@@ -377,9 +377,9 @@ class IntegerRelation {
   }
   /// Given the values of non-local vars, return a satisfying assignment to the
   /// local if one exists, or an empty optional otherwise.
-  Optional<SmallVector<MPInt, 8>>
+  std::optional<SmallVector<MPInt, 8>>
   containsPointNoLocal(ArrayRef<MPInt> point) const;
-  Optional<SmallVector<MPInt, 8>>
+  std::optional<SmallVector<MPInt, 8>>
   containsPointNoLocal(ArrayRef<int64_t> point) const {
     return containsPointNoLocal(getMPIntVec(point));
   }
@@ -473,20 +473,20 @@ class IntegerRelation {
   /// equality). Ex: if the lower bound is [(s0 + s2 - 1) floordiv 32] for a
   /// system with three symbolic variables, *lb = [1, 0, 1], lbDivisor = 32. See
   /// comments at function definition for examples.
-  Optional<MPInt> getConstantBoundOnDimSize(
+  std::optional<MPInt> getConstantBoundOnDimSize(
       unsigned pos, SmallVectorImpl<MPInt> *lb = nullptr,
       MPInt *boundFloorDivisor = nullptr, SmallVectorImpl<MPInt> *ub = nullptr,
       unsigned *minLbPos = nullptr, unsigned *minUbPos = nullptr) const;
   /// The same, but casts to int64_t. This is unsafe and will assert-fail if the
   /// value does not fit in an int64_t.
-  Optional<int64_t> getConstantBoundOnDimSize64(
+  std::optional<int64_t> getConstantBoundOnDimSize64(
       unsigned pos, SmallVectorImpl<int64_t> *lb = nullptr,
       int64_t *boundFloorDivisor = nullptr,
       SmallVectorImpl<int64_t> *ub = nullptr, unsigned *minLbPos = nullptr,
       unsigned *minUbPos = nullptr) const {
     SmallVector<MPInt, 8> ubMPInt, lbMPInt;
     MPInt boundFloorDivisorMPInt;
-    Optional<MPInt> result = getConstantBoundOnDimSize(
+    std::optional<MPInt> result = getConstantBoundOnDimSize(
         pos, &lbMPInt, &boundFloorDivisorMPInt, &ubMPInt, minLbPos, minUbPos);
     if (lb)
       *lb = getInt64Vec(lbMPInt);
@@ -499,10 +499,11 @@ class IntegerRelation {
 
   /// Returns the constant bound for the pos^th variable if there is one;
   /// std::nullopt otherwise.
-  Optional<MPInt> getConstantBound(BoundType type, unsigned pos) const;
+  std::optional<MPInt> getConstantBound(BoundType type, unsigned pos) const;
   /// The same, but casts to int64_t. This is unsafe and will assert-fail if the
   /// value does not fit in an int64_t.
-  Optional<int64_t> getConstantBound64(BoundType type, unsigned pos) const {
+  std::optional<int64_t> getConstantBound64(BoundType type,
+                                            unsigned pos) const {
     return llvm::transformOptional(getConstantBound(type, pos), int64FromMPInt);
   }
 
@@ -683,11 +684,11 @@ class IntegerRelation {
   /// Returns the constant lower bound bound if isLower is true, and the upper
   /// bound if isLower is false.
   template <bool isLower>
-  Optional<MPInt> computeConstantLowerOrUpperBound(unsigned pos);
+  std::optional<MPInt> computeConstantLowerOrUpperBound(unsigned pos);
   /// The same, but casts to int64_t. This is unsafe and will assert-fail if the
   /// value does not fit in an int64_t.
   template <bool isLower>
-  Optional<int64_t> computeConstantLowerOrUpperBound64(unsigned pos) {
+  std::optional<int64_t> computeConstantLowerOrUpperBound64(unsigned pos) {
     return computeConstantLowerOrUpperBound<isLower>(pos).map(int64FromMPInt);
   }
 

diff  --git a/mlir/include/mlir/Analysis/Presburger/PWMAFunction.h b/mlir/include/mlir/Analysis/Presburger/PWMAFunction.h
index 566baca625d4b..4ba0f44cbc82a 100644
--- a/mlir/include/mlir/Analysis/Presburger/PWMAFunction.h
+++ b/mlir/include/mlir/Analysis/Presburger/PWMAFunction.h
@@ -176,8 +176,8 @@ class PWMAFunction {
   PresburgerSet getDomain() const;
 
   /// Return the output of the function at the given point.
-  Optional<SmallVector<MPInt, 8>> valueAt(ArrayRef<MPInt> point) const;
-  Optional<SmallVector<MPInt, 8>> valueAt(ArrayRef<int64_t> point) const {
+  std::optional<SmallVector<MPInt, 8>> valueAt(ArrayRef<MPInt> point) const;
+  std::optional<SmallVector<MPInt, 8>> valueAt(ArrayRef<int64_t> point) const {
     return valueAt(getMPIntVec(point));
   }
 

diff  --git a/mlir/include/mlir/Analysis/Presburger/PresburgerRelation.h b/mlir/include/mlir/Analysis/Presburger/PresburgerRelation.h
index 189b52c428bc2..57ffbd38bd5c4 100644
--- a/mlir/include/mlir/Analysis/Presburger/PresburgerRelation.h
+++ b/mlir/include/mlir/Analysis/Presburger/PresburgerRelation.h
@@ -121,7 +121,7 @@ class PresburgerRelation {
   /// This currently just sums up the overapproximations of the volumes of the
   /// disjuncts, so the approximation might be far from the true volume in the
   /// case when there is a lot of overlap between disjuncts.
-  Optional<MPInt> computeVolume() const;
+  std::optional<MPInt> computeVolume() const;
 
   /// Simplifies the representation of a PresburgerRelation.
   ///

diff  --git a/mlir/include/mlir/Analysis/Presburger/Simplex.h b/mlir/include/mlir/Analysis/Presburger/Simplex.h
index 4ef4e622e2bf8..5a562da36a20b 100644
--- a/mlir/include/mlir/Analysis/Presburger/Simplex.h
+++ b/mlir/include/mlir/Analysis/Presburger/Simplex.h
@@ -264,7 +264,7 @@ class SimplexBase {
   /// Returns an empty optional if no pivot is possible, which happens only when
   /// the column unknown is a variable and no constraint has a non-zero
   /// coefficient for it.
-  Optional<unsigned> findAnyPivotRow(unsigned col);
+  std::optional<unsigned> findAnyPivotRow(unsigned col);
 
   /// Swap the row with the column in the tableau's data structures but not the
   /// tableau itself. This is used by pivot.
@@ -523,11 +523,11 @@ class LexSimplex : public LexSimplexBase {
 
   /// Get a constraint row that is violated, if one exists.
   /// Otherwise, return an empty optional.
-  Optional<unsigned> maybeGetViolatedRow() const;
+  std::optional<unsigned> maybeGetViolatedRow() const;
 
   /// Get a row corresponding to a var that has a non-integral sample value, if
   /// one exists. Otherwise, return an empty optional.
-  Optional<unsigned> maybeGetNonIntegralVarRow() const;
+  std::optional<unsigned> maybeGetNonIntegralVarRow() const;
 };
 
 /// Represents the result of a symbolic lexicographic minimization computation.
@@ -634,11 +634,11 @@ class SymbolicLexSimplex : public LexSimplexBase {
   LogicalResult doNonBranchingPivots();
 
   /// Get a row that is always violated in the current domain, if one exists.
-  Optional<unsigned> maybeGetAlwaysViolatedRow();
+  std::optional<unsigned> maybeGetAlwaysViolatedRow();
 
   /// Get a row corresponding to a variable with non-integral sample value, if
   /// one exists.
-  Optional<unsigned> maybeGetNonIntegralVarRow();
+  std::optional<unsigned> maybeGetNonIntegralVarRow();
 
   /// Given a row that has a non-integer sample value, cut away this fractional
   /// sample value witahout removing any integer points, i.e., the integer
@@ -782,7 +782,7 @@ class Simplex : public SimplexBase {
 
   /// Returns an integer sample point if one exists, or std::nullopt
   /// otherwise. This should only be called for bounded sets.
-  Optional<SmallVector<MPInt, 8>> findIntegerSample();
+  std::optional<SmallVector<MPInt, 8>> findIntegerSample();
 
   enum class IneqType { Redundant, Cut, Separate };
 
@@ -806,11 +806,11 @@ class Simplex : public SimplexBase {
 
   /// Returns the current sample point if it is integral. Otherwise, returns
   /// std::nullopt.
-  Optional<SmallVector<MPInt, 8>> getSamplePointIfIntegral() const;
+  std::optional<SmallVector<MPInt, 8>> getSamplePointIfIntegral() const;
 
   /// Returns the current sample point, which may contain non-integer (rational)
   /// coordinates. Returns an empty optional when the tableau is empty.
-  Optional<SmallVector<Fraction, 8>> getRationalSample() const;
+  std::optional<SmallVector<Fraction, 8>> getRationalSample() const;
 
 private:
   friend class GBRSimplex;
@@ -829,7 +829,7 @@ class Simplex : public SimplexBase {
   ///
   /// Returns a (row, col) pair denoting a pivot, or an empty Optional if
   /// no valid pivot exists.
-  Optional<Pivot> findPivot(int row, Direction direction) const;
+  std::optional<Pivot> findPivot(int row, Direction direction) const;
 
   /// Find a row that can be used to pivot the column in the specified
   /// direction. If skipRow is not null, then this row is excluded
@@ -839,8 +839,8 @@ class Simplex : public SimplexBase {
   ///
   /// Returns the row to pivot to, or an empty Optional if the column
   /// is unbounded in the specified direction.
-  Optional<unsigned> findPivotRow(Optional<unsigned> skipRow,
-                                  Direction direction, unsigned col) const;
+  std::optional<unsigned> findPivotRow(std::optional<unsigned> skipRow,
+                                       Direction direction, unsigned col) const;
 
   /// Undo the addition of the last constraint while preserving tableau
   /// consistency.

diff  --git a/mlir/include/mlir/Analysis/Presburger/Utils.h b/mlir/include/mlir/Analysis/Presburger/Utils.h
index 775d954207769..592782d564497 100644
--- a/mlir/include/mlir/Analysis/Presburger/Utils.h
+++ b/mlir/include/mlir/Analysis/Presburger/Utils.h
@@ -53,7 +53,7 @@ class MaybeOptimum {
   bool isUnbounded() const { return kind == OptimumKind::Unbounded; }
   bool isEmpty() const { return kind == OptimumKind::Empty; }
 
-  Optional<T> getOptimumIfBounded() const { return optimum; }
+  std::optional<T> getOptimumIfBounded() const { return optimum; }
   const T &getBoundedOptimum() const {
     assert(kind == OptimumKind::Bounded &&
            "This should be called only for bounded optima");
@@ -143,7 +143,7 @@ class DivisionRepr {
   // For a given point containing values for each variable other than the
   // division variables, try to find the values for each division variable from
   // their division representation.
-  SmallVector<Optional<MPInt>, 4> divValuesAt(ArrayRef<MPInt> point) const;
+  SmallVector<std::optional<MPInt>, 4> divValuesAt(ArrayRef<MPInt> point) const;
 
   // Get the `i^th` denominator.
   MPInt &getDenom(unsigned i) { return denoms[i]; }

diff  --git a/mlir/include/mlir/Conversion/MathToLibm/MathToLibm.h b/mlir/include/mlir/Conversion/MathToLibm/MathToLibm.h
index dfb45df8c2da1..cd79e8e491d98 100644
--- a/mlir/include/mlir/Conversion/MathToLibm/MathToLibm.h
+++ b/mlir/include/mlir/Conversion/MathToLibm/MathToLibm.h
@@ -22,7 +22,7 @@ class OperationPass;
 /// If log1pBenefit is present, use it instead of benefit for the Log1p op.
 void populateMathToLibmConversionPatterns(
     RewritePatternSet &patterns, PatternBenefit benefit,
-    llvm::Optional<PatternBenefit> log1pBenefit = std::nullopt);
+    std::optional<PatternBenefit> log1pBenefit = std::nullopt);
 
 /// Create a pass to convert Math operations to libm calls.
 std::unique_ptr<OperationPass<ModuleOp>> createConvertMathToLibmPass();

diff  --git a/mlir/include/mlir/Dialect/Affine/Analysis/AffineAnalysis.h b/mlir/include/mlir/Dialect/Affine/Analysis/AffineAnalysis.h
index 02a58e9c04849..b19315e170974 100644
--- a/mlir/include/mlir/Dialect/Affine/Analysis/AffineAnalysis.h
+++ b/mlir/include/mlir/Dialect/Affine/Analysis/AffineAnalysis.h
@@ -141,9 +141,9 @@ struct DependenceComponent {
   // The AffineForOp Operation associated with this dependence component.
   Operation *op = nullptr;
   // The lower bound of the dependence distance.
-  Optional<int64_t> lb;
+  std::optional<int64_t> lb;
   // The upper bound of the dependence distance (inclusive).
-  Optional<int64_t> ub;
+  std::optional<int64_t> ub;
   DependenceComponent() : lb(std::nullopt), ub(std::nullopt) {}
 };
 

diff  --git a/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h b/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h
index de69fb8e94bef..0282d2ea7fff1 100644
--- a/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h
+++ b/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h
@@ -48,7 +48,7 @@ class FlatAffineValueConstraints : public presburger::IntegerPolyhedron {
                              unsigned numReservedEqualities,
                              unsigned numReservedCols, unsigned numDims,
                              unsigned numSymbols, unsigned numLocals,
-                             ArrayRef<Optional<Value>> valArgs = {})
+                             ArrayRef<std::optional<Value>> valArgs = {})
       : IntegerPolyhedron(numReservedInequalities, numReservedEqualities,
                           numReservedCols,
                           presburger::PresburgerSpace::getSetSpace(
@@ -66,7 +66,7 @@ class FlatAffineValueConstraints : public presburger::IntegerPolyhedron {
   /// dimensions and symbols.
   FlatAffineValueConstraints(unsigned numDims = 0, unsigned numSymbols = 0,
                              unsigned numLocals = 0,
-                             ArrayRef<Optional<Value>> valArgs = {})
+                             ArrayRef<std::optional<Value>> valArgs = {})
       : FlatAffineValueConstraints(/*numReservedInequalities=*/0,
                                    /*numReservedEqualities=*/0,
                                    /*numReservedCols=*/numDims + numSymbols +
@@ -74,7 +74,7 @@ class FlatAffineValueConstraints : public presburger::IntegerPolyhedron {
                                    numDims, numSymbols, numLocals, valArgs) {}
 
   FlatAffineValueConstraints(const IntegerPolyhedron &fac,
-                             ArrayRef<Optional<Value>> valArgs = {})
+                             ArrayRef<std::optional<Value>> valArgs = {})
       : IntegerPolyhedron(fac) {
     assert(valArgs.empty() || valArgs.size() == getNumDimAndSymbolVars());
     if (valArgs.empty())
@@ -437,11 +437,11 @@ class FlatAffineValueConstraints : public presburger::IntegerPolyhedron {
     getValues(0, getNumDimAndSymbolVars(), values);
   }
 
-  inline ArrayRef<Optional<Value>> getMaybeValues() const {
+  inline ArrayRef<std::optional<Value>> getMaybeValues() const {
     return {values.data(), values.size()};
   }
 
-  inline ArrayRef<Optional<Value>>
+  inline ArrayRef<std::optional<Value>>
   getMaybeValues(presburger::VarKind kind) const {
     assert(kind != VarKind::Local &&
            "Local variables do not have any value attached to them.");
@@ -511,7 +511,7 @@ class FlatAffineValueConstraints : public presburger::IntegerPolyhedron {
   /// constraint system appearing in the order the variables correspond to
   /// columns. Variables that aren't associated with any Value are set to
   /// None.
-  SmallVector<Optional<Value>, 8> values;
+  SmallVector<std::optional<Value>, 8> values;
 };
 
 /// A FlatAffineRelation represents a set of ordered pairs (domain -> range)
@@ -525,7 +525,7 @@ class FlatAffineRelation : public FlatAffineValueConstraints {
                      unsigned numReservedEqualities, unsigned numReservedCols,
                      unsigned numDomainDims, unsigned numRangeDims,
                      unsigned numSymbols, unsigned numLocals,
-                     ArrayRef<Optional<Value>> valArgs = {})
+                     ArrayRef<std::optional<Value>> valArgs = {})
       : FlatAffineValueConstraints(
             numReservedInequalities, numReservedEqualities, numReservedCols,
             numDomainDims + numRangeDims, numSymbols, numLocals, valArgs),

diff  --git a/mlir/include/mlir/Dialect/Affine/Analysis/LoopAnalysis.h b/mlir/include/mlir/Dialect/Affine/Analysis/LoopAnalysis.h
index 6f95f08987d7f..d0ac1a24b0b89 100644
--- a/mlir/include/mlir/Dialect/Affine/Analysis/LoopAnalysis.h
+++ b/mlir/include/mlir/Dialect/Affine/Analysis/LoopAnalysis.h
@@ -41,7 +41,7 @@ void getTripCountMapAndOperands(AffineForOp forOp, AffineMap *map,
 /// Returns the trip count of the loop if it's a constant, std::nullopt
 /// otherwise. This uses affine expression analysis and is able to determine
 /// constant trip count in non-trivial cases.
-Optional<uint64_t> getConstantTripCount(AffineForOp forOp);
+std::optional<uint64_t> getConstantTripCount(AffineForOp forOp);
 
 /// Returns the greatest known integral divisor of the trip count. Affine
 /// expression analysis is used (indirectly through getTripCount), and

diff  --git a/mlir/include/mlir/Dialect/Affine/Analysis/Utils.h b/mlir/include/mlir/Dialect/Affine/Analysis/Utils.h
index 62a8b0e2e5813..72850bf9ab517 100644
--- a/mlir/include/mlir/Dialect/Affine/Analysis/Utils.h
+++ b/mlir/include/mlir/Dialect/Affine/Analysis/Utils.h
@@ -115,7 +115,7 @@ struct ComputationSliceState {
   /// cannot determine if the slice is maximal or not.
   // TODO: Cache 'isMaximal' so that we don't recompute it when the slice
   // information hasn't changed.
-  Optional<bool> isMaximal() const;
+  std::optional<bool> isMaximal() const;
 
   /// Checks the validity of the slice computed. This is done using the
   /// following steps:
@@ -131,7 +131,7 @@ struct ComputationSliceState {
   /// return false as it implies that the effective fusion results in at least
   /// one iteration of the slice that was not originally in the source's domain.
   /// If the validity cannot be determined, returns std::nullopt.
-  Optional<bool> isSliceValid();
+  std::optional<bool> isSliceValid();
 
   void dump() const;
 
@@ -141,7 +141,7 @@ struct ComputationSliceState {
   /// and the dst loops for those dimensions have the same bounds. Returns false
   /// if both the src and the dst loops don't have the same bounds. Returns
   /// std::nullopt if none of the above can be proven.
-  Optional<bool> isSliceMaximalFastCheck() const;
+  std::optional<bool> isSliceMaximalFastCheck() const;
 };
 
 /// Computes the computation slice loop bounds for one loop nest as affine maps
@@ -303,7 +303,7 @@ struct MemRefRegion {
   /// int64_t. `lbs` are set to the lower bounds for each of the rank
   /// dimensions, and lbDivisors contains the corresponding denominators for
   /// floorDivs.
-  Optional<int64_t> getConstantBoundingSizeAndShape(
+  std::optional<int64_t> getConstantBoundingSizeAndShape(
       SmallVectorImpl<int64_t> *shape = nullptr,
       std::vector<SmallVector<int64_t, 4>> *lbs = nullptr,
       SmallVectorImpl<int64_t> *lbDivisors = nullptr) const;
@@ -317,7 +317,7 @@ struct MemRefRegion {
   /// 'pos' corresponds to the position of the memref shape's dimension (major
   /// to minor) which matches 1:1 with the dimensional variable positions in
   /// 'cst'.
-  Optional<int64_t>
+  std::optional<int64_t>
   getConstantBoundOnDimSize(unsigned pos,
                             SmallVectorImpl<int64_t> *lb = nullptr,
                             int64_t *lbFloorDivisor = nullptr) const {
@@ -326,7 +326,7 @@ struct MemRefRegion {
   }
 
   /// Returns the size of this MemRefRegion in bytes.
-  Optional<int64_t> getRegionSize();
+  std::optional<int64_t> getRegionSize();
 
   // Wrapper around FlatAffineValueConstraints::unionBoundingBox.
   LogicalResult unionBoundingBox(const MemRefRegion &other);
@@ -357,7 +357,7 @@ struct MemRefRegion {
 
 /// Returns the size of memref data in bytes if it's statically shaped,
 /// std::nullopt otherwise.
-Optional<uint64_t> getMemRefSizeInBytes(MemRefType memRefType);
+std::optional<uint64_t> getMemRefSizeInBytes(MemRefType memRefType);
 
 /// Checks a load or store op for an out of bound access; returns failure if the
 /// access is out of bounds along any of the dimensions, success otherwise.
@@ -371,8 +371,8 @@ unsigned getNumCommonSurroundingLoops(Operation &a, Operation &b);
 
 /// Gets the memory footprint of all data touched in the specified memory space
 /// in bytes; if the memory space is unspecified, considers all memory spaces.
-Optional<int64_t> getMemoryFootprintBytes(AffineForOp forOp,
-                                          int memorySpace = -1);
+std::optional<int64_t> getMemoryFootprintBytes(AffineForOp forOp,
+                                               int memorySpace = -1);
 
 /// Simplify the integer set by simplifying the underlying affine expressions by
 /// flattening and some simple inference. Also, drop any duplicate constraints.

diff  --git a/mlir/include/mlir/Dialect/Affine/LoopUtils.h b/mlir/include/mlir/Dialect/Affine/LoopUtils.h
index c13cd8cc371e4..2e3a5876ee62c 100644
--- a/mlir/include/mlir/Dialect/Affine/LoopUtils.h
+++ b/mlir/include/mlir/Dialect/Affine/LoopUtils.h
@@ -186,14 +186,14 @@ struct AffineCopyOptions {
 /// encountered.
 LogicalResult affineDataCopyGenerate(Block::iterator begin, Block::iterator end,
                                      const AffineCopyOptions &copyOptions,
-                                     Optional<Value> filterMemRef,
+                                     std::optional<Value> filterMemRef,
                                      DenseSet<Operation *> &copyNests);
 
 /// A convenience version of affineDataCopyGenerate for all ops in the body of
 /// an AffineForOp.
 LogicalResult affineDataCopyGenerate(AffineForOp forOp,
                                      const AffineCopyOptions &copyOptions,
-                                     Optional<Value> filterMemRef,
+                                     std::optional<Value> filterMemRef,
                                      DenseSet<Operation *> &copyNests);
 
 /// Result for calling generateCopyForMemRegion.

diff  --git a/mlir/include/mlir/Dialect/Affine/Utils.h b/mlir/include/mlir/Dialect/Affine/Utils.h
index 1ea6507e104ba..b6e60b064cca4 100644
--- a/mlir/include/mlir/Dialect/Affine/Utils.h
+++ b/mlir/include/mlir/Dialect/Affine/Utils.h
@@ -301,10 +301,10 @@ Value expandAffineExpr(OpBuilder &builder, Location loc, AffineExpr expr,
 
 /// Create a sequence of operations that implement the `affineMap` applied to
 /// the given `operands` (as it it were an AffineApplyOp).
-Optional<SmallVector<Value, 8>> expandAffineMap(OpBuilder &builder,
-                                                Location loc,
-                                                AffineMap affineMap,
-                                                ValueRange operands);
+std::optional<SmallVector<Value, 8>> expandAffineMap(OpBuilder &builder,
+                                                     Location loc,
+                                                     AffineMap affineMap,
+                                                     ValueRange operands);
 
 /// Holds the result of (div a, b)  and (mod a, b).
 struct DivModValue {

diff  --git a/mlir/include/mlir/Dialect/Async/IR/AsyncOps.td b/mlir/include/mlir/Dialect/Async/IR/AsyncOps.td
index 14146cd10ac63..9db2167de7baa 100644
--- a/mlir/include/mlir/Dialect/Async/IR/AsyncOps.td
+++ b/mlir/include/mlir/Dialect/Async/IR/AsyncOps.td
@@ -333,7 +333,7 @@ def Async_AwaitOp : Async_Op<"await"> {
   ];
 
   let extraClassDeclaration = [{
-    Optional<Type> getResultType() {
+    std::optional<Type> getResultType() {
       if (getResultTypes().empty()) return std::nullopt;
       return getResultTypes()[0];
     }

diff  --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
index 2eef942f6191d..0ca2086281880 100644
--- a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
+++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
@@ -204,9 +204,9 @@ struct BufferizationOptions {
   bool isOpAllowed(Operation *op) const;
 
   /// Helper functions for allocation, deallocation, memory copying.
-  Optional<AllocationFn> allocationFn;
-  Optional<DeallocationFn> deallocationFn;
-  Optional<MemCpyFn> memCpyFn;
+  std::optional<AllocationFn> allocationFn;
+  std::optional<DeallocationFn> deallocationFn;
+  std::optional<MemCpyFn> memCpyFn;
 
   /// Create a memref allocation with the given type and dynamic extents.
   FailureOr<Value> createAlloc(OpBuilder &b, Location loc, MemRefType type,
@@ -233,7 +233,7 @@ struct BufferizationOptions {
   /// The default memory space that should be used when it cannot be inferred
   /// from the context. If case of std::nullopt, bufferization fails when the
   /// memory space cannot be inferred at any point.
-  Optional<Attribute> defaultMemorySpace = Attribute();
+  std::optional<Attribute> defaultMemorySpace = Attribute();
 
   /// Certain ops have aliasing OpOperand/OpResult invariants (e.g., scf.for).
   /// If this flag is set to `false`, those invariants are no longer enforced

diff  --git a/mlir/include/mlir/Dialect/CommonFolders.h b/mlir/include/mlir/Dialect/CommonFolders.h
index a8f0a070c3f5c..425a8c2686adb 100644
--- a/mlir/include/mlir/Dialect/CommonFolders.h
+++ b/mlir/include/mlir/Dialect/CommonFolders.h
@@ -24,10 +24,10 @@
 namespace mlir {
 /// Performs constant folding `calculate` with element-wise behavior on the two
 /// attributes in `operands` and returns the result if possible.
-template <
-    class AttrElementT, class ElementValueT = typename AttrElementT::ValueType,
-    class CalculationT =
-        function_ref<Optional<ElementValueT>(ElementValueT, ElementValueT)>>
+template <class AttrElementT,
+          class ElementValueT = typename AttrElementT::ValueType,
+          class CalculationT = function_ref<
+              std::optional<ElementValueT>(ElementValueT, ElementValueT)>>
 Attribute constFoldBinaryOpConditional(ArrayRef<Attribute> operands,
                                        const CalculationT &calculate) {
   assert(operands.size() == 2 && "binary op takes two operands");
@@ -96,16 +96,17 @@ Attribute constFoldBinaryOp(ArrayRef<Attribute> operands,
                             const CalculationT &calculate) {
   return constFoldBinaryOpConditional<AttrElementT>(
       operands,
-      [&](ElementValueT a, ElementValueT b) -> Optional<ElementValueT> {
+      [&](ElementValueT a, ElementValueT b) -> std::optional<ElementValueT> {
         return calculate(a, b);
       });
 }
 
 /// Performs constant folding `calculate` with element-wise behavior on the one
 /// attributes in `operands` and returns the result if possible.
-template <
-    class AttrElementT, class ElementValueT = typename AttrElementT::ValueType,
-    class CalculationT = function_ref<Optional<ElementValueT>(ElementValueT)>>
+template <class AttrElementT,
+          class ElementValueT = typename AttrElementT::ValueType,
+          class CalculationT =
+              function_ref<std::optional<ElementValueT>(ElementValueT)>>
 Attribute constFoldUnaryOpConditional(ArrayRef<Attribute> operands,
                                       const CalculationT &&calculate) {
   assert(operands.size() == 1 && "unary op takes one operands");
@@ -154,8 +155,9 @@ template <class AttrElementT,
 Attribute constFoldUnaryOp(ArrayRef<Attribute> operands,
                            const CalculationT &&calculate) {
   return constFoldUnaryOpConditional<AttrElementT>(
-      operands,
-      [&](ElementValueT a) -> Optional<ElementValueT> { return calculate(a); });
+      operands, [&](ElementValueT a) -> std::optional<ElementValueT> {
+        return calculate(a);
+      });
 }
 
 template <

diff  --git a/mlir/include/mlir/Dialect/Func/Transforms/DecomposeCallGraphTypes.h b/mlir/include/mlir/Dialect/Func/Transforms/DecomposeCallGraphTypes.h
index 6e740f3a35206..6f27cbb3a59fe 100644
--- a/mlir/include/mlir/Dialect/Func/Transforms/DecomposeCallGraphTypes.h
+++ b/mlir/include/mlir/Dialect/Func/Transforms/DecomposeCallGraphTypes.h
@@ -61,20 +61,22 @@ class ValueDecomposer {
   }
 
 private:
-  using DecomposeValueConversionCallFn = std::function<Optional<LogicalResult>(
-      OpBuilder &, Location, Type, Value, SmallVectorImpl<Value> &)>;
+  using DecomposeValueConversionCallFn =
+      std::function<std::optional<LogicalResult>(
+          OpBuilder &, Location, Type, Value, SmallVectorImpl<Value> &)>;
 
   /// Generate a wrapper for the given decompose value conversion callback.
   template <typename T, typename FnT>
   DecomposeValueConversionCallFn
   wrapDecomposeValueConversionCallback(FnT &&callback) {
-    return [callback = std::forward<FnT>(callback)](
-               OpBuilder &builder, Location loc, Type type, Value value,
-               SmallVectorImpl<Value> &newValues) -> Optional<LogicalResult> {
-      if (T derivedType = type.dyn_cast<T>())
-        return callback(builder, loc, derivedType, value, newValues);
-      return std::nullopt;
-    };
+    return
+        [callback = std::forward<FnT>(callback)](
+            OpBuilder &builder, Location loc, Type type, Value value,
+            SmallVectorImpl<Value> &newValues) -> std::optional<LogicalResult> {
+          if (T derivedType = type.dyn_cast<T>())
+            return callback(builder, loc, derivedType, value, newValues);
+          return std::nullopt;
+        };
   }
 
   SmallVector<DecomposeValueConversionCallFn, 2> decomposeValueConversions;

diff  --git a/mlir/include/mlir/Dialect/GPU/IR/GPUOps.td b/mlir/include/mlir/Dialect/GPU/IR/GPUOps.td
index 44423078ff924..650ebe4b2b109 100644
--- a/mlir/include/mlir/Dialect/GPU/IR/GPUOps.td
+++ b/mlir/include/mlir/Dialect/GPU/IR/GPUOps.td
@@ -330,7 +330,7 @@ def GPU_GPUFuncOp : GPU_Op<"func", [
     /// Returns the block size this kernel will be launched with along
     /// dimension `dim` if known. The value of gpu.thread_id dim will be strictly
     /// less than this size.
-    Optional<uint32_t> getKnownBlockSize(gpu::Dimension dim) {
+    std::optional<uint32_t> getKnownBlockSize(gpu::Dimension dim) {
       if (auto array =
         (*this)->getAttrOfType<DenseI32ArrayAttr>(getKnownBlockSizeAttrName())) {
         return array[static_cast<uint32_t>(dim)];
@@ -341,7 +341,7 @@ def GPU_GPUFuncOp : GPU_Op<"func", [
     /// Returns the grid size this kernel will be launched with along
     /// dimension `dim` if known. The value of gpu.block_id dim will be strictly
     /// less than this size.
-    Optional<uint32_t> getKnownGridSize(gpu::Dimension dim) {
+    std::optional<uint32_t> getKnownGridSize(gpu::Dimension dim) {
       if (auto array =
         (*this)->getAttrOfType<DenseI32ArrayAttr>(getKnownGridSizeAttrName())) {
         return array[static_cast<uint32_t>(dim)];

diff  --git a/mlir/include/mlir/Dialect/GPU/Transforms/Passes.h b/mlir/include/mlir/Dialect/GPU/Transforms/Passes.h
index 049dd04b0a40c..594d8be0838b7 100644
--- a/mlir/include/mlir/Dialect/GPU/Transforms/Passes.h
+++ b/mlir/include/mlir/Dialect/GPU/Transforms/Passes.h
@@ -107,8 +107,8 @@ class SerializeToBlobPass : public OperationPass<gpu::GPUModuleOp> {
   std::unique_ptr<llvm::TargetMachine> createTargetMachine();
 
   /// Translates the module to ISA
-  Optional<std::string> translateToISA(llvm::Module &llvmModule,
-                                       llvm::TargetMachine &targetMachine);
+  std::optional<std::string> translateToISA(llvm::Module &llvmModule,
+                                            llvm::TargetMachine &targetMachine);
 
   /// Serializes the target ISA to binary form.
   virtual std::unique_ptr<std::vector<char>>

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 733d57375e05c..4963bc948f8be 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -70,9 +70,9 @@ def LoopOptionsAttr : LLVM_Attr<"LoopOptions", "loopopts"> {
   let extraClassDeclaration = [{
     using OptionValuePair = std::pair<LoopOptionCase, int64_t>;
     using OptionsArray = ArrayRef<std::pair<LoopOptionCase, int64_t>>;
-    Optional<bool> disableUnroll();
-    Optional<bool> disableLICM();
-    Optional<int64_t> interleaveCount();
+    std::optional<bool> disableUnroll();
+    std::optional<bool> disableLICM();
+    std::optional<int64_t> interleaveCount();
   }];
 
   let builders = [

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
index 20203a49892b6..fd2d184e45202 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
@@ -81,31 +81,31 @@ class LoopOptionsAttrBuilder {
 
   /// Set the `disable_licm` option to the provided value. If no value
   /// is provided the option is deleted.
-  LoopOptionsAttrBuilder &setDisableLICM(Optional<bool> value);
+  LoopOptionsAttrBuilder &setDisableLICM(std::optional<bool> value);
 
   /// Set the `interleave_count` option to the provided value. If no value
   /// is provided the option is deleted.
-  LoopOptionsAttrBuilder &setInterleaveCount(Optional<uint64_t> count);
+  LoopOptionsAttrBuilder &setInterleaveCount(std::optional<uint64_t> count);
 
   /// Set the `disable_unroll` option to the provided value. If no value
   /// is provided the option is deleted.
-  LoopOptionsAttrBuilder &setDisableUnroll(Optional<bool> value);
+  LoopOptionsAttrBuilder &setDisableUnroll(std::optional<bool> value);
 
   /// Set the `disable_pipeline` option to the provided value. If no value
   /// is provided the option is deleted.
-  LoopOptionsAttrBuilder &setDisablePipeline(Optional<bool> value);
+  LoopOptionsAttrBuilder &setDisablePipeline(std::optional<bool> value);
 
   /// Set the `pipeline_initiation_interval` option to the provided value.
   /// If no value is provided the option is deleted.
   LoopOptionsAttrBuilder &
-  setPipelineInitiationInterval(Optional<uint64_t> count);
+  setPipelineInitiationInterval(std::optional<uint64_t> count);
 
   /// Returns true if any option has been set.
   bool empty() { return options.empty(); }
 
 private:
   template <typename T>
-  LoopOptionsAttrBuilder &setOption(LoopOptionCase tag, Optional<T> value);
+  LoopOptionsAttrBuilder &setOption(LoopOptionCase tag, std::optional<T> value);
 
   friend class LoopOptionsAttr;
   SmallVector<LoopOptionsAttr::OptionValuePair> options;

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 5f96a4682107e..e01c6bb81e89a 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -787,7 +787,7 @@ def LLVM_CondBrOp : LLVM_TerminatorOp<"cond_br",
     OpBuilder<(ins "Value":$condition, "Block *":$trueDest,
       "ValueRange":$trueOperands, "Block *":$falseDest,
       "ValueRange":$falseOperands,
-      CArg<"Optional<std::pair<uint32_t, uint32_t>>", "{}">:$weights),
+      CArg<"std::optional<std::pair<uint32_t, uint32_t>>", "{}">:$weights),
     [{
         ElementsAttr weightsAttr;
         if (weights) {
@@ -1500,7 +1500,7 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [
       CArg<"CConv", "CConv::C">:$cconv,
       CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs,
       CArg<"ArrayRef<DictionaryAttr>", "{}">:$argAttrs,
-      CArg<"Optional<uint64_t>", "{}">:$functionEntryCount)>
+      CArg<"std::optional<uint64_t>", "{}">:$functionEntryCount)>
   ];
 
   let extraClassDeclaration = [{

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h
index 8cccfefc25e6a..3251f2c5ec4f5 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h
@@ -286,7 +286,8 @@ enum class PtrDLEntryPos { Size = 0, Abi = 1, Preferred = 2, Index = 3 };
 /// Returns `std::nullopt` if `pos` is not present in the entry.
 /// Currently only `PtrDLEntryPos::Index` is optional, and all other positions
 /// may be assumed to be present.
-Optional<unsigned> extractPointerSpecValue(Attribute attr, PtrDLEntryPos pos);
+std::optional<unsigned> extractPointerSpecValue(Attribute attr,
+                                                PtrDLEntryPos pos);
 
 } // namespace LLVM
 } // namespace mlir

diff  --git a/mlir/include/mlir/Dialect/Linalg/Analysis/DependenceAnalysis.h b/mlir/include/mlir/Dialect/Linalg/Analysis/DependenceAnalysis.h
index f6490f0d064a6..09ed596ac9143 100644
--- a/mlir/include/mlir/Dialect/Linalg/Analysis/DependenceAnalysis.h
+++ b/mlir/include/mlir/Dialect/Linalg/Analysis/DependenceAnalysis.h
@@ -78,7 +78,7 @@ class LinalgDependenceGraph {
     }
     // Return the indexing map of the operand/result in `opView` specified in
     // the owning LinalgOp. If the owner is not a LinalgOp returns std::nullopt.
-    static Optional<AffineMap> getIndexingMap(OpView opView) {
+    static std::optional<AffineMap> getIndexingMap(OpView opView) {
       auto owner = dyn_cast<LinalgOp>(getOwner(opView));
       if (!owner)
         return std::nullopt;
@@ -89,14 +89,14 @@ class LinalgDependenceGraph {
     }
     // Return the operand number if the `opView` is an OpOperand *. Otherwise
     // return std::nullopt.
-    static Optional<unsigned> getOperandNumber(OpView opView) {
+    static std::optional<unsigned> getOperandNumber(OpView opView) {
       if (OpOperand *operand = opView.dyn_cast<OpOperand *>())
         return operand->getOperandNumber();
       return std::nullopt;
     }
     // Return the result number if the `opView` is an OpResult. Otherwise return
     // std::nullopt.
-    static Optional<unsigned> getResultNumber(OpView opView) {
+    static std::optional<unsigned> getResultNumber(OpView opView) {
       if (OpResult result = opView.dyn_cast<Value>().cast<OpResult>())
         return result.getResultNumber();
       return std::nullopt;
@@ -116,37 +116,37 @@ class LinalgDependenceGraph {
 
     // If the dependent OpView is an operand, return operand number. Return
     // std::nullopt otherwise.
-    Optional<unsigned> getDependentOpViewOperandNum() const {
+    std::optional<unsigned> getDependentOpViewOperandNum() const {
       return getOperandNumber(dependentOpView);
     }
 
     // If the indexing OpView is an operand, return operand number. Return
     // std::nullopt otherwise.
-    Optional<unsigned> getIndexingOpViewOperandNum() const {
+    std::optional<unsigned> getIndexingOpViewOperandNum() const {
       return getOperandNumber(indexingOpView);
     }
 
     // If the dependent OpView is a result value, return the result
     // number. Return std::nullopt otherwise.
-    Optional<unsigned> getDependentOpViewResultNum() const {
+    std::optional<unsigned> getDependentOpViewResultNum() const {
       return getResultNumber(dependentOpView);
     }
 
     // If the dependent OpView is a result value, return the result
     // number. Return std::nullopt otherwise.
-    Optional<unsigned> getIndexingOpViewResultNum() const {
+    std::optional<unsigned> getIndexingOpViewResultNum() const {
       return getResultNumber(indexingOpView);
     }
 
     // Return the indexing map of the operand/result in the dependent OpView as
     // specified in the owner of the OpView.
-    Optional<AffineMap> getDependentOpViewIndexingMap() const {
+    std::optional<AffineMap> getDependentOpViewIndexingMap() const {
       return getIndexingMap(dependentOpView);
     }
 
     // Return the indexing map of the operand/result in the indexing OpView as
     // specified in the owner of the OpView.
-    Optional<AffineMap> getIndexingOpViewIndexingMap() const {
+    std::optional<AffineMap> getIndexingOpViewIndexingMap() const {
       return getIndexingMap(indexingOpView);
     }
   };

diff  --git a/mlir/include/mlir/Dialect/Linalg/IR/Linalg.h b/mlir/include/mlir/Dialect/Linalg/IR/Linalg.h
index 179a1c14ed806..4b628054c4929 100644
--- a/mlir/include/mlir/Dialect/Linalg/IR/Linalg.h
+++ b/mlir/include/mlir/Dialect/Linalg/IR/Linalg.h
@@ -64,7 +64,7 @@ SmallVector<AffineExpr, 4> makeAffineDimExprs(unsigned num, unsigned &startIdx,
 
 /// Returns `maybeMap.get()` if `maybeMap` is set, otherwise returns the
 /// symbol-less identity map of `rank`.
-AffineMap extractOrIdentityMap(Optional<AffineMap> maybeMap, unsigned rank,
+AffineMap extractOrIdentityMap(std::optional<AffineMap> maybeMap, unsigned rank,
                                MLIRContext *context);
 
 /// Return the vector that is the concatenation of `a` and `b`.

diff  --git a/mlir/include/mlir/Dialect/Linalg/Utils/Utils.h b/mlir/include/mlir/Dialect/Linalg/Utils/Utils.h
index f0ed6d5a05cb6..580620cdbd868 100644
--- a/mlir/include/mlir/Dialect/Linalg/Utils/Utils.h
+++ b/mlir/include/mlir/Dialect/Linalg/Utils/Utils.h
@@ -135,12 +135,12 @@ GenericOp makeMemRefCopyOp(OpBuilder &b, Location loc, Value from, Value to);
 /// and offset is 0. Strictly speaking the offset 0 is not required in general,
 /// but non-zero offsets are not handled by SPIR-V backend at this point (and
 /// potentially cannot be handled).
-Optional<SmallVector<ReassociationIndices>>
+std::optional<SmallVector<ReassociationIndices>>
 getReassociationMapForFoldingUnitDims(ArrayRef<OpFoldResult> mixedSizes);
 
 /// Return the identity numeric value associated to the give op. Return
 /// std::nullopt if there is no known neutral element.
-Optional<Attribute> getNeutralElement(Operation *op);
+std::optional<Attribute> getNeutralElement(Operation *op);
 
 //===----------------------------------------------------------------------===//
 // Fusion / Tiling utilities
@@ -224,7 +224,7 @@ computeSliceParameters(OpBuilder &builder, Location loc, Value valueToTile,
 ///
 /// Some of the `valuesToTile` won't be affected by tiling. For these values,
 /// std::nullopt will be returned.
-SmallVector<Optional<SliceParameters>>
+SmallVector<std::optional<SliceParameters>>
 computeAllSliceParameters(OpBuilder &builder, Location loc, LinalgOp linalgOp,
                           ValueRange valuesToTile, ArrayRef<OpFoldResult> ivs,
                           ArrayRef<OpFoldResult> tileSizes,
@@ -397,7 +397,7 @@ class TileLoopNest {
   LogicalResult
   tileRootOp(OpBuilder &b, ArrayRef<int64_t> tileSizes,
              ArrayRef<int64_t> tileInterchange,
-             Optional<LinalgLoopDistributionOptions> tileDistribution);
+             std::optional<LinalgLoopDistributionOptions> tileDistribution);
 
   /// Fuse the producer of `consumerOpOperand` into the tile loop nest. Returns
   /// the fused producer or fails if fusion is not possible.
@@ -467,7 +467,7 @@ struct RegionMatcher {
   ///     linalg.yield %0: <scalar-type>
   /// }
   /// ```
-  static Optional<BinaryOpKind> matchAsScalarBinaryOp(GenericOp op);
+  static std::optional<BinaryOpKind> matchAsScalarBinaryOp(GenericOp op);
 };
 
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/include/mlir/Dialect/MemRef/IR/MemRef.h b/mlir/include/mlir/Dialect/MemRef/IR/MemRef.h
index f330a54922e3d..b599c3c56ca78 100644
--- a/mlir/include/mlir/Dialect/MemRef/IR/MemRef.h
+++ b/mlir/include/mlir/Dialect/MemRef/IR/MemRef.h
@@ -53,7 +53,7 @@ Type getTensorTypeFromMemRefType(Type type);
 /// Finds a single dealloc operation for the given allocated value. If there
 /// are > 1 deallocates for `allocValue`, returns std::nullopt, else returns the
 /// single deallocate if it exists or nullptr.
-Optional<Operation *> findDealloc(Value allocValue);
+std::optional<Operation *> findDealloc(Value allocValue);
 
 /// Return the dimensions of the given memref value.
 SmallVector<OpFoldResult> getMixedSizes(OpBuilder &builder, Location loc,

diff  --git a/mlir/include/mlir/Dialect/PDL/IR/PDLOps.td b/mlir/include/mlir/Dialect/PDL/IR/PDLOps.td
index 6e589cb380d03..d5b5d2be1c6a3 100644
--- a/mlir/include/mlir/Dialect/PDL/IR/PDLOps.td
+++ b/mlir/include/mlir/Dialect/PDL/IR/PDLOps.td
@@ -354,7 +354,7 @@ def PDL_OperationOp : PDL_Op<"operation", [AttrSizedOperandSegments]> {
   }];
 
   let builders = [
-    OpBuilder<(ins CArg<"Optional<StringRef>", "std::nullopt">:$name,
+    OpBuilder<(ins CArg<"std::optional<StringRef>", "std::nullopt">:$name,
       CArg<"ValueRange", "std::nullopt">:$operandValues,
       CArg<"ArrayRef<StringRef>", "std::nullopt">:$attrNames,
       CArg<"ValueRange", "std::nullopt">:$attrValues,
@@ -419,8 +419,8 @@ def PDL_PatternOp : PDL_Op<"pattern", [
   }];
 
   let builders = [
-    OpBuilder<(ins CArg<"Optional<uint16_t>", "1">:$benefit,
-                   CArg<"Optional<StringRef>", "std::nullopt">:$name)>,
+    OpBuilder<(ins CArg<"std::optional<uint16_t>", "1">:$benefit,
+                   CArg<"std::optional<StringRef>", "std::nullopt">:$name)>,
   ];
   let extraClassDeclaration = [{
     //===------------------------------------------------------------------===//

diff  --git a/mlir/include/mlir/Dialect/SCF/Utils/Utils.h b/mlir/include/mlir/Dialect/SCF/Utils/Utils.h
index 594124d60af1b..a7fada76ac5ba 100644
--- a/mlir/include/mlir/Dialect/SCF/Utils/Utils.h
+++ b/mlir/include/mlir/Dialect/SCF/Utils/Utils.h
@@ -113,7 +113,7 @@ bool getInnermostParallelLoops(Operation *rootOp,
 /// from scf.for or scf.parallel loop.
 /// if `loopFilter` is passed, the filter determines which loop to consider.
 /// Other induction variables are ignored.
-Optional<std::pair<AffineExpr, AffineExpr>>
+std::optional<std::pair<AffineExpr, AffineExpr>>
 getSCFMinMaxExpr(Value value, SmallVectorImpl<Value> &dims,
                  SmallVectorImpl<Value> &symbols,
                  llvm::function_ref<bool(Operation *)> loopFilter = nullptr);

diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVControlFlowOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVControlFlowOps.td
index 21a83bf290397..e9b3a42206120 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVControlFlowOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVControlFlowOps.td
@@ -134,7 +134,7 @@ def SPIRV_BranchConditionalOp : SPIRV_Op<"BranchConditional", [
     OpBuilder<(ins "Value":$condition, "Block *":$trueBlock,
       "ValueRange":$trueArguments, "Block *":$falseBlock,
       "ValueRange":$falseArguments,
-      CArg<"Optional<std::pair<uint32_t, uint32_t>>", "{}">:$weights),
+      CArg<"std::optional<std::pair<uint32_t, uint32_t>>", "{}">:$weights),
     [{
       ArrayAttr weightsAttr;
       if (weights) {

diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/TargetAndABI.h b/mlir/include/mlir/Dialect/SPIRV/IR/TargetAndABI.h
index ce3bc94fac2cb..f2e12d3993c12 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/TargetAndABI.h
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/TargetAndABI.h
@@ -36,13 +36,13 @@ class TargetEnv {
   bool allows(Capability) const;
   /// Returns the first allowed one if any of the given capabilities is allowed.
   /// Returns std::nullopt otherwise.
-  Optional<Capability> allows(ArrayRef<Capability>) const;
+  std::optional<Capability> allows(ArrayRef<Capability>) const;
 
   /// Returns true if the given extension is allowed.
   bool allows(Extension) const;
   /// Returns the first allowed one if any of the given extensions is allowed.
   /// Returns std::nullopt otherwise.
-  Optional<Extension> allows(ArrayRef<Extension>) const;
+  std::optional<Extension> allows(ArrayRef<Extension>) const;
 
   /// Returns the vendor ID.
   Vendor getVendorID() const;

diff  --git a/mlir/include/mlir/Dialect/SparseTensor/Utils/Merger.h b/mlir/include/mlir/Dialect/SparseTensor/Utils/Merger.h
index 7c0f3e1529d24..c96f76ee1c094 100644
--- a/mlir/include/mlir/Dialect/SparseTensor/Utils/Merger.h
+++ b/mlir/include/mlir/Dialect/SparseTensor/Utils/Merger.h
@@ -296,19 +296,19 @@ class Merger {
     return getDimLevelType(tensor(b), index(b));
   }
 
-  Optional<unsigned> getLoopIdx(unsigned t, unsigned dim) const {
+  std::optional<unsigned> getLoopIdx(unsigned t, unsigned dim) const {
     assert(t < numTensors && dim < numLoops);
     return dimToLoopIdx[t][dim];
   }
 
   /// Gets the dimension number of the the `t`th tensor on `i`th loop.
-  Optional<unsigned> getDimNum(unsigned t, unsigned i) const {
+  std::optional<unsigned> getDimNum(unsigned t, unsigned i) const {
     assert(t < numTensors && i < numLoops);
     return loopIdxToDim[t][i];
   }
 
   /// Gets the dimension number of `b`.
-  Optional<unsigned> getDimNum(unsigned b) const {
+  std::optional<unsigned> getDimNum(unsigned b) const {
     return getDimNum(tensor(b), index(b));
   }
 
@@ -327,7 +327,7 @@ class Merger {
   // corresponding tensor dimension and invokes the callback.
   void foreachTidDimPairInBits(
       const BitVector &bits,
-      function_ref<void(unsigned b, unsigned tid, Optional<unsigned> dim,
+      function_ref<void(unsigned b, unsigned tid, std::optional<unsigned> dim,
                         DimLevelType dlt)>
           cb) {
     for (unsigned b : bits.set_bits())
@@ -360,7 +360,7 @@ class Merger {
 
   /// Builds a tensor expression from the given Linalg operation.
   /// Returns index of the root expression on success.
-  Optional<unsigned> buildTensorExpFromLinalg(linalg::GenericOp op);
+  std::optional<unsigned> buildTensorExpFromLinalg(linalg::GenericOp op);
 
   /// Rebuilds SSA format from a tensor expression.
   Value buildExp(RewriterBase &rewriter, Location loc, unsigned e, Value v0,
@@ -373,7 +373,7 @@ class Merger {
   Type inferType(unsigned e, Value src);
 
   /// Traverses the SSA tree (possibly a DAG) to build a tensor expression.
-  Optional<unsigned> buildTensorExp(linalg::GenericOp op, Value v);
+  std::optional<unsigned> buildTensorExp(linalg::GenericOp op, Value v);
 
   /// Merger data structures.
   const unsigned outTensor;
@@ -389,10 +389,10 @@ class Merger {
 
   // Map that converts pair<tensor id, loop id> to the corresponding
   // dimension.
-  std::vector<std::vector<Optional<unsigned>>> loopIdxToDim;
+  std::vector<std::vector<std::optional<unsigned>>> loopIdxToDim;
 
   // Map that converts pair<tensor id, dim> to the corresponding loop id.
-  std::vector<std::vector<Optional<unsigned>>> dimToLoopIdx;
+  std::vector<std::vector<std::optional<unsigned>>> dimToLoopIdx;
 
   llvm::SmallVector<TensorExp> tensorExps;
   llvm::SmallVector<LatPoint> latPoints;

diff  --git a/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td b/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
index ccd53b7f0bf51..f0f12388186a5 100644
--- a/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
+++ b/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
@@ -1761,7 +1761,7 @@ def Tensor_PackOp : Tensor_RelayoutOp<"pack", [
     OpBuilder<(ins "Value":$source, "Value":$dest,
       "ArrayRef<int64_t>":$innerDimsPos,
       "ArrayRef<OpFoldResult>":$innerTiles,
-      CArg<"Optional<Value>", "std::nullopt">:$paddingValue,
+      CArg<"std::optional<Value>", "std::nullopt">:$paddingValue,
       CArg<"ArrayRef<int64_t>", "{}">:$outerDimsPerm)>
   ];
 

diff  --git a/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h b/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h
index fd4574abe5401..b36e40bb8a9ff 100644
--- a/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h
+++ b/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h
@@ -45,9 +45,9 @@ bool validIntegerRange(IntegerType ty, int64_t value);
 // Checks for a dynamic batch dim in any of the passed parameters of an op.
 // The batch dimention must be #0 and the rest of the dimensions must be static.
 template <typename Op>
-Optional<SmallVector<Value>> checkHasDynamicBatchDims(PatternRewriter &rewriter,
-                                                      Op op,
-                                                      ArrayRef<Value> params) {
+std::optional<SmallVector<Value>>
+checkHasDynamicBatchDims(PatternRewriter &rewriter, Op op,
+                         ArrayRef<Value> params) {
   SmallVector<ShapedType> dynTypes;
   SmallVector<Value> dynamicDims;
   for (const Value &param : params) {

diff  --git a/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.h b/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.h
index 0abc006144eb9..41f3da05f888b 100644
--- a/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.h
+++ b/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.h
@@ -190,7 +190,7 @@ class TransformDialectExtension
 template <typename OpTy>
 void TransformDialect::addOperationIfNotRegistered() {
   StringRef name = OpTy::getOperationName();
-  Optional<RegisteredOperationName> opName =
+  std::optional<RegisteredOperationName> opName =
       RegisteredOperationName::lookup(name, getContext());
   if (!opName) {
     addOperations<OpTy>();

diff  --git a/mlir/include/mlir/Dialect/Transform/Utils/DiagnosedSilenceableFailure.h b/mlir/include/mlir/Dialect/Transform/Utils/DiagnosedSilenceableFailure.h
index de4bce061a2aa..fcf422a0b6aa3 100644
--- a/mlir/include/mlir/Dialect/Transform/Utils/DiagnosedSilenceableFailure.h
+++ b/mlir/include/mlir/Dialect/Transform/Utils/DiagnosedSilenceableFailure.h
@@ -137,7 +137,7 @@ class [[nodiscard]] DiagnosedSilenceableFailure {
 
   /// Attaches a note to the last diagnostic.
   /// Expects this object to be a silenceable failure.
-  Diagnostic &attachNote(Optional<Location> loc = std::nullopt) {
+  Diagnostic &attachNote(std::optional<Location> loc = std::nullopt) {
     assert(isSilenceableFailure() &&
            "can only attach notes to silenceable failures");
     return diagnostics.back().attachNote(loc);
@@ -201,7 +201,7 @@ class DiagnosedDefiniteFailure {
   }
 
   /// Attaches a note to the error.
-  Diagnostic &attachNote(Optional<Location> loc = std::nullopt) {
+  Diagnostic &attachNote(std::optional<Location> loc = std::nullopt) {
     return diag.attachNote(loc);
   }
 

diff  --git a/mlir/include/mlir/Dialect/Utils/IndexingUtils.h b/mlir/include/mlir/Dialect/Utils/IndexingUtils.h
index 3b4584c918865..64eea7eded92b 100644
--- a/mlir/include/mlir/Dialect/Utils/IndexingUtils.h
+++ b/mlir/include/mlir/Dialect/Utils/IndexingUtils.h
@@ -57,8 +57,8 @@ SmallVector<int64_t> computeElementwiseMul(ArrayRef<int64_t> v1,
 ///     derived as {42(leading shape dim), 2/2, 10/5, 32/2}.
 ///   - shapeRatio({42, 2, 11, 32}, {2, 5, 2}) returns std::nullopt  which is
 ///     derived as {42(leading shape dim), 2/2, 11/5(not divisible), 32/2}.
-Optional<SmallVector<int64_t>> computeShapeRatio(ArrayRef<int64_t> shape,
-                                                 ArrayRef<int64_t> subShape);
+std::optional<SmallVector<int64_t>>
+computeShapeRatio(ArrayRef<int64_t> shape, ArrayRef<int64_t> subShape);
 
 /// Return the number of elements of basis (i.e. the max linear index).
 /// Return `0` if `basis` is empty.

diff  --git a/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h b/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h
index b69cc1beeb50b..a6cb78b8a2f1e 100644
--- a/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h
+++ b/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h
@@ -42,7 +42,7 @@ constexpr StringRef getReassociationAttrName() { return "reassociation"; }
 /// is folded into
 ///
 ///   result = [[0, 1, 2], [3, 4]].
-Optional<SmallVector<ReassociationIndices>> composeReassociationIndices(
+std::optional<SmallVector<ReassociationIndices>> composeReassociationIndices(
     ArrayRef<ReassociationIndices> producerReassociations,
     ArrayRef<ReassociationIndices> consumerReassociations,
     MLIRContext *context);
@@ -67,12 +67,12 @@ SmallVector<ReassociationIndices, 2> convertReassociationMapsToIndices(
 /// Return the reassociations maps to use to reshape given the source type and
 /// the target type when possible. Return std::nullopt when this computation
 /// failed.
-Optional<SmallVector<ReassociationIndices>>
+std::optional<SmallVector<ReassociationIndices>>
 getReassociationIndicesForReshape(ShapedType sourceType, ShapedType targetType);
 
 /// Returns the reassociation maps to collapse `sourceShape` to `targetShape` if
 /// possible.
-Optional<SmallVector<ReassociationIndices>>
+std::optional<SmallVector<ReassociationIndices>>
 getReassociationIndicesForCollapse(ArrayRef<int64_t> sourceShape,
                                    ArrayRef<int64_t> targetShape);
 
@@ -186,7 +186,7 @@ struct ComposeReassociativeReshapeOps : public OpRewritePattern<ReshapeOpTy> {
         hasNonIdentityLayout(reshapeOp.getResult().getType()))
       return failure();
 
-    Optional<SmallVector<ReassociationIndices>> reassociationIndices =
+    std::optional<SmallVector<ReassociationIndices>> reassociationIndices =
         composeReassociationIndices(srcReshapeOp.getReassociationIndices(),
                                     reshapeOp.getReassociationIndices(),
                                     rewriter.getContext());
@@ -341,7 +341,7 @@ struct ComposeExpandOfCollapseOp : public OpRewritePattern<ExpandOpTy> {
 private:
   // Attempts to find a way to collapse `srcShape` to `resultShape` by
   // collapsing subshapes defined by the reassociation indices.
-  Optional<SmallVector<ReassociationIndices>> findCollapsingReassociation(
+  std::optional<SmallVector<ReassociationIndices>> findCollapsingReassociation(
       ArrayRef<ReassociationIndices> srcReassociation,
       ArrayRef<ReassociationIndices> resultReassociation,
       ArrayRef<int64_t> srcShape, ArrayRef<int64_t> resultShape) const {
@@ -476,7 +476,7 @@ struct CollapseShapeRankReducingSliceSimplificationInfo {
   RankedTensorType sliceResultType;
   /// The reassociation indices for the new collapse shape op, if required. If
   /// `None`, the slice should replace the collapse shape op.
-  Optional<SmallVector<ReassociationIndices>> newReassociationIndices;
+  std::optional<SmallVector<ReassociationIndices>> newReassociationIndices;
 };
 
 /// A collapsing reshape operation can sometimes be simplified or eliminated by

diff  --git a/mlir/include/mlir/Dialect/Vector/Transforms/VectorRewritePatterns.h b/mlir/include/mlir/Dialect/Vector/Transforms/VectorRewritePatterns.h
index b11369662e0da..cd49eb1514c9d 100644
--- a/mlir/include/mlir/Dialect/Vector/Transforms/VectorRewritePatterns.h
+++ b/mlir/include/mlir/Dialect/Vector/Transforms/VectorRewritePatterns.h
@@ -112,7 +112,7 @@ struct UnrollVectorOptions {
   }
 
   using NativeShapeFnType =
-      std::function<Optional<SmallVector<int64_t>>(Operation *op)>;
+      std::function<std::optional<SmallVector<int64_t>>(Operation *op)>;
   /// Function that returns the shape of the vector to unroll to for a given
   /// operation. The unrolling is aborted if the function returns
   /// `std::nullopt`.
@@ -125,7 +125,7 @@ struct UnrollVectorOptions {
   /// Set the native shape to use for unrolling.
   UnrollVectorOptions &setNativeShape(ArrayRef<int64_t> shape) {
     SmallVector<int64_t> tsShape(shape.begin(), shape.end());
-    nativeShape = [=](Operation *) -> Optional<SmallVector<int64_t>> {
+    nativeShape = [=](Operation *) -> std::optional<SmallVector<int64_t>> {
       return tsShape;
     };
     return *this;
@@ -136,7 +136,7 @@ struct UnrollVectorOptions {
   /// be used when unrolling the given operation into units of the native vector
   /// size.
   using UnrollTraversalOrderFnType =
-      std::function<Optional<SmallVector<int64_t>>(Operation *op)>;
+      std::function<std::optional<SmallVector<int64_t>>(Operation *op)>;
   UnrollTraversalOrderFnType traversalOrderCallback = nullptr;
   UnrollVectorOptions &
   setUnrollTraversalOrderFn(UnrollTraversalOrderFnType traversalOrderFn) {

diff  --git a/mlir/include/mlir/ExecutionEngine/ExecutionEngine.h b/mlir/include/mlir/ExecutionEngine/ExecutionEngine.h
index 48ff26cea0f27..957a4b99899a6 100644
--- a/mlir/include/mlir/ExecutionEngine/ExecutionEngine.h
+++ b/mlir/include/mlir/ExecutionEngine/ExecutionEngine.h
@@ -68,7 +68,7 @@ struct ExecutionEngineOptions {
 
   /// `jitCodeGenOptLevel`, when provided, is used as the optimization level for
   /// target code generation.
-  Optional<llvm::CodeGenOpt::Level> jitCodeGenOptLevel = std::nullopt;
+  std::optional<llvm::CodeGenOpt::Level> jitCodeGenOptLevel = std::nullopt;
 
   /// If `sharedLibPaths` are provided, the underlying JIT-compilation will
   /// open and link the shared libraries for symbol resolution.

diff  --git a/mlir/include/mlir/ExecutionEngine/MemRefUtils.h b/mlir/include/mlir/ExecutionEngine/MemRefUtils.h
index 9240aae01b12b..bba002f3621fa 100644
--- a/mlir/include/mlir/ExecutionEngine/MemRefUtils.h
+++ b/mlir/include/mlir/ExecutionEngine/MemRefUtils.h
@@ -102,7 +102,7 @@ makeStridedMemRefDescriptor(T *ptr, T *alignedPtr, ArrayRef<int64_t> shape = {},
 template <typename T>
 std::pair<T *, T *>
 allocAligned(size_t nElements, AllocFunType allocFun = &::malloc,
-             llvm::Optional<uint64_t> alignment = llvm::Optional<uint64_t>()) {
+             std::optional<uint64_t> alignment = std::optional<uint64_t>()) {
   assert(sizeof(T) <= UINT_MAX && "Elemental type overflows");
   auto size = nElements * sizeof(T);
   auto desiredAlignment = alignment.value_or(nextPowerOf2(sizeof(T)));
@@ -147,7 +147,7 @@ class OwningMemRef {
   OwningMemRef(
       ArrayRef<int64_t> shape, ArrayRef<int64_t> shapeAlloc = {},
       ElementWiseVisitor<T> init = {},
-      llvm::Optional<uint64_t> alignment = llvm::Optional<uint64_t>(),
+      std::optional<uint64_t> alignment = std::optional<uint64_t>(),
       AllocFunType allocFun = &::malloc,
       std::function<void(StridedMemRefType<T, Rank>)> freeFun =
           [](StridedMemRefType<T, Rank> descriptor) {

diff  --git a/mlir/include/mlir/IR/AffineMap.h b/mlir/include/mlir/IR/AffineMap.h
index 1c0f1b22c8f92..0f4c7469497a1 100644
--- a/mlir/include/mlir/IR/AffineMap.h
+++ b/mlir/include/mlir/IR/AffineMap.h
@@ -174,7 +174,7 @@ class AffineMap {
   /// Extracts the first result position where `input` dimension resides.
   /// Returns `std::nullopt` if `input` is not a dimension expression or cannot
   /// be found in results.
-  Optional<unsigned> getResultPosition(AffineExpr input) const;
+  std::optional<unsigned> getResultPosition(AffineExpr input) const;
 
   /// Return true if any affine expression involves AffineDimExpr `position`.
   bool isFunctionOfDim(unsigned position) const {

diff  --git a/mlir/include/mlir/IR/Builders.h b/mlir/include/mlir/IR/Builders.h
index 6c7c519323bd8..e0d33dd9271f0 100644
--- a/mlir/include/mlir/IR/Builders.h
+++ b/mlir/include/mlir/IR/Builders.h
@@ -440,7 +440,7 @@ class OpBuilder : public Builder {
   /// Helper for sanity checking preconditions for create* methods below.
   template <typename OpT>
   RegisteredOperationName getCheckRegisteredInfo(MLIRContext *ctx) {
-    Optional<RegisteredOperationName> opName =
+    std::optional<RegisteredOperationName> opName =
         RegisteredOperationName::lookup(OpT::getOperationName(), ctx);
     if (LLVM_UNLIKELY(!opName)) {
       llvm::report_fatal_error(

diff  --git a/mlir/include/mlir/IR/BuiltinAttributeInterfaces.h b/mlir/include/mlir/IR/BuiltinAttributeInterfaces.h
index b7deea2ec8f4f..e164ef84cbd59 100644
--- a/mlir/include/mlir/IR/BuiltinAttributeInterfaces.h
+++ b/mlir/include/mlir/IR/BuiltinAttributeInterfaces.h
@@ -300,7 +300,7 @@ auto ElementsAttrRange<IteratorT>::operator[](ArrayRef<uint64_t> index) const
 /// Return the elements of this attribute as a value of type 'T'.
 template <typename T>
 auto ElementsAttr::value_begin() const -> DefaultValueCheckT<T, iterator<T>> {
-  if (Optional<iterator<T>> iterator = try_value_begin<T>())
+  if (std::optional<iterator<T>> iterator = try_value_begin<T>())
     return std::move(*iterator);
   llvm::errs()
       << "ElementsAttr does not provide iteration facilities for type `"
@@ -309,7 +309,7 @@ auto ElementsAttr::value_begin() const -> DefaultValueCheckT<T, iterator<T>> {
 }
 template <typename T>
 auto ElementsAttr::try_value_begin() const
-    -> DefaultValueCheckT<T, Optional<iterator<T>>> {
+    -> DefaultValueCheckT<T, std::optional<iterator<T>>> {
   FailureOr<detail::ElementsAttrIndexer> indexer =
       getValuesImpl(TypeID::get<T>());
   if (failed(indexer))

diff  --git a/mlir/include/mlir/IR/BuiltinAttributeInterfaces.td b/mlir/include/mlir/IR/BuiltinAttributeInterfaces.td
index 72cba52ed26ec..19336e0483860 100644
--- a/mlir/include/mlir/IR/BuiltinAttributeInterfaces.td
+++ b/mlir/include/mlir/IR/BuiltinAttributeInterfaces.td
@@ -395,18 +395,18 @@ def ElementsAttrInterface : AttrInterface<"ElementsAttr"> {
     /// If this attribute supports iterating over element values of type `T`,
     /// return the iterable range. Otherwise, return std::nullopt.
     template <typename T>
-    DefaultValueCheckT<T, Optional<iterator_range<T>>> tryGetValues() const {
-      if (Optional<iterator<T>> beginIt = try_value_begin<T>())
+    DefaultValueCheckT<T, std::optional<iterator_range<T>>> tryGetValues() const {
+      if (std::optional<iterator<T>> beginIt = try_value_begin<T>())
         return iterator_range<T>(getType(), *beginIt, value_end<T>());
       return std::nullopt;
     }
     template <typename T>
-    DefaultValueCheckT<T, Optional<iterator<T>>> try_value_begin() const;
+    DefaultValueCheckT<T, std::optional<iterator<T>>> try_value_begin() const;
 
     /// If this attribute supports iterating over element values of type `T`,
     /// return the iterable range. Otherwise, return std::nullopt.
     template <typename T, typename = DerivedAttrValueCheckT<T>>
-    Optional<DerivedAttrValueIteratorRange<T>> tryGetValues() const {
+    std::optional<DerivedAttrValueIteratorRange<T>> tryGetValues() const {
       auto values = tryGetValues<Attribute>();
       if (!values)
         return std::nullopt;
@@ -418,7 +418,7 @@ def ElementsAttrInterface : AttrInterface<"ElementsAttr"> {
       );
     }
     template <typename T, typename = DerivedAttrValueCheckT<T>>
-    Optional<DerivedAttrValueIterator<T>> try_value_begin() const {
+    std::optional<DerivedAttrValueIterator<T>> try_value_begin() const {
       if (auto values = tryGetValues<T>())
         return values->begin();
       return std::nullopt;

diff  --git a/mlir/include/mlir/IR/BuiltinAttributes.h b/mlir/include/mlir/IR/BuiltinAttributes.h
index 3247da996c6b8..a23da78a48d64 100644
--- a/mlir/include/mlir/IR/BuiltinAttributes.h
+++ b/mlir/include/mlir/IR/BuiltinAttributes.h
@@ -786,7 +786,7 @@ class DenseResourceElementsAttrBase : public DenseResourceElementsAttr {
 
   /// Return the data of this attribute as an ArrayRef<T> if it is present,
   /// returns std::nullopt otherwise.
-  Optional<ArrayRef<T>> tryGetAsArrayRef() const;
+  std::optional<ArrayRef<T>> tryGetAsArrayRef() const;
 
   /// Support for isa<>/cast<>.
   static bool classof(Attribute attr);

diff  --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td
index 2f2d9f4a89edd..0e7b5012b082e 100644
--- a/mlir/include/mlir/IR/BuiltinAttributes.td
+++ b/mlir/include/mlir/IR/BuiltinAttributes.td
@@ -531,8 +531,8 @@ def Builtin_DictionaryAttr : Builtin_Attr<"Dictionary", [
     Attribute get(StringAttr name) const;
 
     /// Return the specified named attribute if present, std::nullopt otherwise.
-    Optional<NamedAttribute> getNamed(StringRef name) const;
-    Optional<NamedAttribute> getNamed(StringAttr name) const;
+    std::optional<NamedAttribute> getNamed(StringRef name) const;
+    std::optional<NamedAttribute> getNamed(StringAttr name) const;
 
     /// Return whether the specified attribute is present.
     bool contains(StringRef name) const;
@@ -560,7 +560,7 @@ def Builtin_DictionaryAttr : Builtin_Attr<"Dictionary", [
     /// Returns an entry with a duplicate name in `array`, if it exists, else
     /// returns std::nullopt. If `isSorted` is true, the array is assumed to be
     /// sorted else it will be sorted in place before finding the duplicate entry.
-    static Optional<NamedAttribute>
+    static std::optional<NamedAttribute>
     findDuplicate(SmallVectorImpl<NamedAttribute> &array, bool isSorted);
 
     /// Return the specified attribute if present and is an instance of

diff  --git a/mlir/include/mlir/IR/Diagnostics.h b/mlir/include/mlir/IR/Diagnostics.h
index 68292a8bae48c..205c5d9274226 100644
--- a/mlir/include/mlir/IR/Diagnostics.h
+++ b/mlir/include/mlir/IR/Diagnostics.h
@@ -245,7 +245,7 @@ class Diagnostic {
   /// Attaches a note to this diagnostic. A new location may be optionally
   /// provided, if not, then the location defaults to the one specified for this
   /// diagnostic. Notes may not be attached to other notes.
-  Diagnostic &attachNote(Optional<Location> noteLoc = std::nullopt);
+  Diagnostic &attachNote(std::optional<Location> noteLoc = std::nullopt);
 
   using note_iterator = llvm::pointee_iterator<NoteVector::iterator>;
   using const_note_iterator =
@@ -343,7 +343,7 @@ class InFlightDiagnostic {
   }
 
   /// Attaches a note to this diagnostic.
-  Diagnostic &attachNote(Optional<Location> noteLoc = std::nullopt) {
+  Diagnostic &attachNote(std::optional<Location> noteLoc = std::nullopt) {
     assert(isActive() && "diagnostic not active");
     return impl->attachNote(noteLoc);
   }
@@ -394,7 +394,7 @@ class InFlightDiagnostic {
   DiagnosticEngine *owner = nullptr;
 
   /// The raw diagnostic that is inflight to be reported.
-  Optional<Diagnostic> impl;
+  std::optional<Diagnostic> impl;
 };
 
 //===----------------------------------------------------------------------===//
@@ -596,7 +596,7 @@ class SourceMgrDiagnosticHandler : public ScopedDiagnosticHandler {
 
   /// Given a location, returns the first nested location (including 'loc') that
   /// can be shown to the user.
-  Optional<Location> findLocToShow(Location loc);
+  std::optional<Location> findLocToShow(Location loc);
 
   /// The maximum depth that a call stack will be printed.
   /// TODO: This should be a tunable flag.

diff  --git a/mlir/include/mlir/IR/DialectResourceBlobManager.h b/mlir/include/mlir/IR/DialectResourceBlobManager.h
index 92f90cfd81396..e3f32b7a9ab5f 100644
--- a/mlir/include/mlir/IR/DialectResourceBlobManager.h
+++ b/mlir/include/mlir/IR/DialectResourceBlobManager.h
@@ -53,7 +53,7 @@ class DialectResourceBlobManager {
     BlobEntry &operator=(BlobEntry &&) = delete;
 
     /// Initialize this entry with the given key and blob.
-    void initialize(StringRef newKey, Optional<AsmResourceBlob> newBlob) {
+    void initialize(StringRef newKey, std::optional<AsmResourceBlob> newBlob) {
       key = newKey;
       blob = std::move(newBlob);
     }
@@ -62,7 +62,7 @@ class DialectResourceBlobManager {
     StringRef key;
 
     /// The blob that is referenced by this entry if it is valid.
-    Optional<AsmResourceBlob> blob;
+    std::optional<AsmResourceBlob> blob;
 
     /// Allow access to the constructors.
     friend DialectResourceBlobManager;
@@ -83,12 +83,12 @@ class DialectResourceBlobManager {
   /// Insert a new entry with the provided name and optional blob data. The name
   /// may be modified during insertion if another entry already exists with that
   /// name. Returns the inserted entry.
-  BlobEntry &insert(StringRef name, Optional<AsmResourceBlob> blob = {});
+  BlobEntry &insert(StringRef name, std::optional<AsmResourceBlob> blob = {});
   /// Insertion method that returns a dialect specific handle to the inserted
   /// entry.
   template <typename HandleT>
   HandleT insert(typename HandleT::Dialect *dialect, StringRef name,
-                 Optional<AsmResourceBlob> blob = {}) {
+                 std::optional<AsmResourceBlob> blob = {}) {
     BlobEntry &entry = insert(name, std::move(blob));
     return HandleT(&entry, dialect);
   }
@@ -154,7 +154,7 @@ class ResourceBlobManagerDialectInterfaceBase
   /// data. The name may be modified during insertion if another entry already
   /// exists with that name. Returns a dialect specific handle to the inserted
   /// entry.
-  HandleT insert(StringRef name, Optional<AsmResourceBlob> blob = {}) {
+  HandleT insert(StringRef name, std::optional<AsmResourceBlob> blob = {}) {
     return getBlobManager().template insert<HandleT>(
         cast<typename HandleT::Dialect>(getDialect()), name, std::move(blob));
   }

diff  --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h
index b5c35e7ab87e8..385597cc9a510 100644
--- a/mlir/include/mlir/IR/OpDefinition.h
+++ b/mlir/include/mlir/IR/OpDefinition.h
@@ -52,7 +52,7 @@ class OptionalParseResult {
   ParseResult operator*() const { return value(); }
 
 private:
-  Optional<ParseResult> impl;
+  std::optional<ParseResult> impl;
 };
 
 // These functions are out-of-line utilities, which avoids them being template
@@ -1673,8 +1673,9 @@ class Op : public OpState, public Traits<ConcreteType>... {
   /// interfaces for the concrete operation.
   template <typename... Models>
   static void attachInterface(MLIRContext &context) {
-    Optional<RegisteredOperationName> info = RegisteredOperationName::lookup(
-        ConcreteType::getOperationName(), &context);
+    std::optional<RegisteredOperationName> info =
+        RegisteredOperationName::lookup(ConcreteType::getOperationName(),
+                                        &context);
     if (!info)
       llvm::report_fatal_error(
           "Attempting to attach an interface to an unregistered operation " +
@@ -1907,7 +1908,8 @@ class OpInterface
     OperationName name = op->getName();
 
     // Access the raw interface from the operation info.
-    if (Optional<RegisteredOperationName> rInfo = name.getRegisteredInfo()) {
+    if (std::optional<RegisteredOperationName> rInfo =
+            name.getRegisteredInfo()) {
       if (auto *opIface = rInfo->getInterface<ConcreteType>())
         return opIface;
       // Fallback to the dialect to provide it with a chance to implement this

diff  --git a/mlir/include/mlir/IR/OpImplementation.h b/mlir/include/mlir/IR/OpImplementation.h
index 2cf9ed9c34d50..92f4c610a9031 100644
--- a/mlir/include/mlir/IR/OpImplementation.h
+++ b/mlir/include/mlir/IR/OpImplementation.h
@@ -757,7 +757,7 @@ class AsmParser {
     StringRef keyword;
 
     /// The result of the switch statement or none if currently unknown.
-    Optional<ResultT> result;
+    std::optional<ResultT> result;
   };
 
   /// Parse a given keyword.
@@ -1286,7 +1286,7 @@ class OpAsmParser : public AsmParser {
   /// which case an OpaqueLoc is set and will be resolved when parsing
   /// completes.
   virtual ParseResult
-  parseOptionalLocationSpecifier(Optional<Location> &result) = 0;
+  parseOptionalLocationSpecifier(std::optional<Location> &result) = 0;
 
   /// Return the name of the specified result in the specified syntax, as well
   /// as the sub-element in the name.  It returns an empty string and ~0U for
@@ -1340,12 +1340,13 @@ class OpAsmParser : public AsmParser {
   /// skip parsing that component.
   virtual ParseResult parseGenericOperationAfterOpName(
       OperationState &result,
-      Optional<ArrayRef<UnresolvedOperand>> parsedOperandType = std::nullopt,
-      Optional<ArrayRef<Block *>> parsedSuccessors = std::nullopt,
-      Optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions =
+      std::optional<ArrayRef<UnresolvedOperand>> parsedOperandType =
           std::nullopt,
-      Optional<ArrayRef<NamedAttribute>> parsedAttributes = std::nullopt,
-      Optional<FunctionType> parsedFnType = std::nullopt) = 0;
+      std::optional<ArrayRef<Block *>> parsedSuccessors = std::nullopt,
+      std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions =
+          std::nullopt,
+      std::optional<ArrayRef<NamedAttribute>> parsedAttributes = std::nullopt,
+      std::optional<FunctionType> parsedFnType = std::nullopt) = 0;
 
   /// Parse a single SSA value operand name along with a result number if
   /// `allowResultNumber` is true.
@@ -1452,7 +1453,7 @@ class OpAsmParser : public AsmParser {
     UnresolvedOperand ssaName;    // SourceLoc, SSA name, result #.
     Type type;                    // Type.
     DictionaryAttr attrs;         // Attributes if present.
-    Optional<Location> sourceLoc; // Source location specifier if present.
+    std::optional<Location> sourceLoc; // Source location specifier if present.
   };
 
   /// Parse a single argument with the following syntax:

diff  --git a/mlir/include/mlir/IR/Operation.h b/mlir/include/mlir/IR/Operation.h
index ca7fed442e477..59d450ea97bb8 100644
--- a/mlir/include/mlir/IR/Operation.h
+++ b/mlir/include/mlir/IR/Operation.h
@@ -95,7 +95,7 @@ class alignas(8) Operation final
 
   /// If this operation has a registered operation description, return it.
   /// Otherwise return std::nullopt.
-  Optional<RegisteredOperationName> getRegisteredInfo() {
+  std::optional<RegisteredOperationName> getRegisteredInfo() {
     return getName().getRegisteredInfo();
   }
 

diff  --git a/mlir/include/mlir/IR/OperationSupport.h b/mlir/include/mlir/IR/OperationSupport.h
index 230df19715ae0..8ec11c1c4e632 100644
--- a/mlir/include/mlir/IR/OperationSupport.h
+++ b/mlir/include/mlir/IR/OperationSupport.h
@@ -172,7 +172,7 @@ class OperationName {
 
   /// If this operation is registered, returns the registered information,
   /// std::nullopt otherwise.
-  Optional<RegisteredOperationName> getRegisteredInfo() const;
+  std::optional<RegisteredOperationName> getRegisteredInfo() const;
 
   /// This hook implements a generalized folder for this operation. Operations
   /// can implement this to provide simplifications rules that are applied by
@@ -412,8 +412,8 @@ class RegisteredOperationName : public OperationName {
 
   /// Lookup the registered operation information for the given operation.
   /// Returns std::nullopt if the operation isn't registered.
-  static Optional<RegisteredOperationName> lookup(StringRef name,
-                                                  MLIRContext *ctx);
+  static std::optional<RegisteredOperationName> lookup(StringRef name,
+                                                       MLIRContext *ctx);
 
   /// Register a new operation in a Dialect object.
   /// This constructor is used by Dialect objects when they register the list
@@ -446,10 +446,10 @@ class RegisteredOperationName : public OperationName {
   friend OperationName;
 };
 
-inline Optional<RegisteredOperationName>
+inline std::optional<RegisteredOperationName>
 OperationName::getRegisteredInfo() const {
   return isRegistered() ? RegisteredOperationName(impl)
-                        : Optional<RegisteredOperationName>();
+                        : std::optional<RegisteredOperationName>();
 }
 
 //===----------------------------------------------------------------------===//
@@ -518,10 +518,10 @@ Attribute getAttrFromSortedRange(IteratorT first, IteratorT last, NameT name) {
 /// Get an attribute from a sorted range of named attributes. Returns
 /// std::nullopt if the attribute was not found.
 template <typename IteratorT, typename NameT>
-Optional<NamedAttribute>
+std::optional<NamedAttribute>
 getNamedAttrFromSortedRange(IteratorT first, IteratorT last, NameT name) {
   std::pair<IteratorT, bool> result = findAttrSorted(first, last, name);
-  return result.second ? *result.first : Optional<NamedAttribute>();
+  return result.second ? *result.first : std::optional<NamedAttribute>();
 }
 
 } // namespace impl
@@ -606,7 +606,7 @@ class NamedAttrList {
 
   /// Returns an entry with a duplicate name the list, if it exists, else
   /// returns std::nullopt.
-  Optional<NamedAttribute> findDuplicate() const;
+  std::optional<NamedAttribute> findDuplicate() const;
 
   /// Return a dictionary attribute for the underlying dictionary. This will
   /// return an empty dictionary attribute if empty rather than null.
@@ -620,8 +620,8 @@ class NamedAttrList {
   Attribute get(StringRef name) const;
 
   /// Return the specified named attribute if present, std::nullopt otherwise.
-  Optional<NamedAttribute> getNamed(StringRef name) const;
-  Optional<NamedAttribute> getNamed(StringAttr name) const;
+  std::optional<NamedAttribute> getNamed(StringRef name) const;
+  std::optional<NamedAttribute> getNamed(StringAttr name) const;
 
   /// If the an attribute exists with the specified name, change it to the new
   /// value. Otherwise, add a new attribute with the specified name/value.
@@ -844,7 +844,7 @@ class OpPrintingFlags {
   bool shouldElideElementsAttr(ElementsAttr attr) const;
 
   /// Return the size limit for printing large ElementsAttr.
-  Optional<int64_t> getLargeElementsAttrLimit() const;
+  std::optional<int64_t> getLargeElementsAttrLimit() const;
 
   /// Return if debug information should be printed.
   bool shouldPrintDebugInfo() const;
@@ -867,7 +867,7 @@ class OpPrintingFlags {
 private:
   /// Elide large elements attributes if the number of elements is larger than
   /// the upper limit.
-  Optional<int64_t> elementsAttrElementLimit;
+  std::optional<int64_t> elementsAttrElementLimit;
 
   /// Print debug information.
   bool printDebugInfoFlag : 1;

diff  --git a/mlir/include/mlir/IR/PatternMatch.h b/mlir/include/mlir/IR/PatternMatch.h
index 08e249c979902..5c7c96f5761bd 100644
--- a/mlir/include/mlir/IR/PatternMatch.h
+++ b/mlir/include/mlir/IR/PatternMatch.h
@@ -99,7 +99,7 @@ class Pattern {
   /// Return the interface ID used to match the root operation of this pattern.
   /// If the pattern does not use an interface ID for deciding the root match,
   /// this returns std::nullopt.
-  Optional<TypeID> getRootInterfaceID() const {
+  std::optional<TypeID> getRootInterfaceID() const {
     if (rootKind == RootKind::InterfaceID)
       return TypeID::getFromOpaquePointer(rootValue);
     return std::nullopt;
@@ -108,7 +108,7 @@ class Pattern {
   /// Return the trait ID used to match the root operation of this pattern.
   /// If the pattern does not use a trait ID for deciding the root match, this
   /// returns std::nullopt.
-  Optional<TypeID> getRootTraitID() const {
+  std::optional<TypeID> getRootTraitID() const {
     if (rootKind == RootKind::TraitID)
       return TypeID::getFromOpaquePointer(rootValue);
     return std::nullopt;
@@ -655,7 +655,7 @@ class PDLValue {
   /// value is not an instance of `T`.
   template <typename T,
             typename ResultT = std::conditional_t<
-                std::is_convertible<T, bool>::value, T, Optional<T>>>
+                std::is_convertible<T, bool>::value, T, std::optional<T>>>
   ResultT dyn_cast() const {
     return isa<T>() ? castImpl<T>() : ResultT();
   }

diff  --git a/mlir/include/mlir/IR/SubElementInterfaces.h b/mlir/include/mlir/IR/SubElementInterfaces.h
index 85a6ba7d104d3..935d7fcd59cf9 100644
--- a/mlir/include/mlir/IR/SubElementInterfaces.h
+++ b/mlir/include/mlir/IR/SubElementInterfaces.h
@@ -61,7 +61,7 @@ class AttrTypeReplacer {
   /// signal the element wasn't handled), or a pair of the replacement element
   /// and a WalkResult.
   template <typename T>
-  using ReplaceFnResult = Optional<std::pair<T, WalkResult>>;
+  using ReplaceFnResult = std::optional<std::pair<T, WalkResult>>;
   template <typename T>
   using ReplaceFn = std::function<ReplaceFnResult<T>(T)>;
 
@@ -70,13 +70,13 @@ class AttrTypeReplacer {
   /// forms(where `T` is a class derived from `Type` or `Attribute`, and `BaseT`
   /// is either `Type` or `Attribute` respectively):
   ///
-  ///   * Optional<BaseT>(T)
+  ///   * std::optional<BaseT>(T)
   ///     - This either returns a valid Attribute/Type in the case of success,
   ///       nullptr in the case of failure, or `std::nullopt` to signify that
   ///       additional replacement functions may be applied (i.e. this function
   ///       doesn't handle that instance).
   ///
-  ///   * Optional<std::pair<BaseT, WalkResult>>(T)
+  ///   * std::optional<std::pair<BaseT, WalkResult>>(T)
   ///     - Similar to the above, but also allows specifying a WalkResult to
   ///       control the replacement of sub elements of a given attribute or
   ///       type. Returning a `skip` result, for example, will not recursively
@@ -106,8 +106,8 @@ class AttrTypeReplacer {
     addReplacement([callback = std::forward<FnT>(callback)](
                        BaseT base) -> ReplaceFnResult<BaseT> {
       if (auto derived = dyn_cast<T>(base)) {
-        if constexpr (std::is_convertible_v<ResultT, Optional<BaseT>>) {
-          Optional<BaseT> result = callback(derived);
+        if constexpr (std::is_convertible_v<ResultT, std::optional<BaseT>>) {
+          std::optional<BaseT> result = callback(derived);
           return result ? std::make_pair(*result, WalkResult::advance())
                         : ReplaceFnResult<BaseT>();
         } else {

diff  --git a/mlir/include/mlir/IR/ValueRange.h b/mlir/include/mlir/IR/ValueRange.h
index a39e50d291ee0..8873260736d16 100644
--- a/mlir/include/mlir/IR/ValueRange.h
+++ b/mlir/include/mlir/IR/ValueRange.h
@@ -129,7 +129,7 @@ class MutableOperandRange {
   /// Slice this range into a sub range, with the additional operand segment.
   MutableOperandRange
   slice(unsigned subStart, unsigned subLen,
-        Optional<OperandSegment> segment = std::nullopt) const;
+        std::optional<OperandSegment> segment = std::nullopt) const;
 
   /// Append the given values to the range.
   void append(ValueRange values);

diff  --git a/mlir/include/mlir/Interfaces/InferIntRangeInterface.h b/mlir/include/mlir/Interfaces/InferIntRangeInterface.h
index 48a3264e07ce7..7df4cc87c2e10 100644
--- a/mlir/include/mlir/Interfaces/InferIntRangeInterface.h
+++ b/mlir/include/mlir/Interfaces/InferIntRangeInterface.h
@@ -94,7 +94,7 @@ class ConstantIntRanges {
   /// If either the signed or unsigned interpretations of the range
   /// indicate that the value it bounds is a constant, return that constant
   /// value.
-  Optional<APInt> getConstantValue() const;
+  std::optional<APInt> getConstantValue() const;
 
   friend raw_ostream &operator<<(raw_ostream &os,
                                  const ConstantIntRanges &range);

diff  --git a/mlir/include/mlir/Pass/AnalysisManager.h b/mlir/include/mlir/Pass/AnalysisManager.h
index fb8375a12d066..9821a6817466f 100644
--- a/mlir/include/mlir/Pass/AnalysisManager.h
+++ b/mlir/include/mlir/Pass/AnalysisManager.h
@@ -169,7 +169,7 @@ class AnalysisMap {
 
   /// Get a cached analysis instance if one exists, otherwise return null.
   template <typename AnalysisT>
-  Optional<std::reference_wrapper<AnalysisT>> getCachedAnalysis() const {
+  std::optional<std::reference_wrapper<AnalysisT>> getCachedAnalysis() const {
     auto res = analyses.find(TypeID::get<AnalysisT>());
     if (res == analyses.end())
       return std::nullopt;
@@ -302,7 +302,7 @@ class AnalysisManager {
   /// Query for a cached analysis on the given parent operation. The analysis
   /// may not exist and if it does it may be out-of-date.
   template <typename AnalysisT>
-  Optional<std::reference_wrapper<AnalysisT>>
+  std::optional<std::reference_wrapper<AnalysisT>>
   getCachedParentAnalysis(Operation *parentOp) const {
     const detail::NestedAnalysisMap *curParent = impl;
     while (auto *parentAM = curParent->getParent()) {
@@ -329,7 +329,7 @@ class AnalysisManager {
 
   /// Query for a cached entry of the given analysis on the current operation.
   template <typename AnalysisT>
-  Optional<std::reference_wrapper<AnalysisT>> getCachedAnalysis() const {
+  std::optional<std::reference_wrapper<AnalysisT>> getCachedAnalysis() const {
     return impl->analyses.getCachedAnalysis<AnalysisT>();
   }
 
@@ -348,7 +348,7 @@ class AnalysisManager {
 
   /// Query for a cached analysis of a child operation, or return null.
   template <typename AnalysisT>
-  Optional<std::reference_wrapper<AnalysisT>>
+  std::optional<std::reference_wrapper<AnalysisT>>
   getCachedChildAnalysis(Operation *op) const {
     assert(op->getParentOp() == impl->getOperation());
     auto it = impl->childAnalyses.find(op);

diff  --git a/mlir/include/mlir/Pass/Pass.h b/mlir/include/mlir/Pass/Pass.h
index 3eace7d4d5429..714667c239a8a 100644
--- a/mlir/include/mlir/Pass/Pass.h
+++ b/mlir/include/mlir/Pass/Pass.h
@@ -83,7 +83,7 @@ class Pass {
 
   /// Returns the name of the operation that this pass operates on, or
   /// std::nullopt if this is a generic OperationPass.
-  Optional<StringRef> getOpName() const { return opName; }
+  std::optional<StringRef> getOpName() const { return opName; }
 
   //===--------------------------------------------------------------------===//
   // Options
@@ -160,7 +160,7 @@ class Pass {
   }
 
 protected:
-  explicit Pass(TypeID passID, Optional<StringRef> opName = std::nullopt)
+  explicit Pass(TypeID passID, std::optional<StringRef> opName = std::nullopt)
       : passID(passID), opName(opName) {}
   Pass(const Pass &other) : Pass(other.passID, other.opName) {}
 
@@ -228,7 +228,7 @@ class Pass {
   /// Query a cached instance of an analysis for the current ir unit if one
   /// exists.
   template <typename AnalysisT>
-  Optional<std::reference_wrapper<AnalysisT>> getCachedAnalysis() {
+  std::optional<std::reference_wrapper<AnalysisT>> getCachedAnalysis() {
     return getAnalysisManager().getCachedAnalysis<AnalysisT>();
   }
 
@@ -248,21 +248,21 @@ class Pass {
 
   /// Returns the analysis for the given parent operation if it exists.
   template <typename AnalysisT>
-  Optional<std::reference_wrapper<AnalysisT>>
+  std::optional<std::reference_wrapper<AnalysisT>>
   getCachedParentAnalysis(Operation *parent) {
     return getAnalysisManager().getCachedParentAnalysis<AnalysisT>(parent);
   }
 
   /// Returns the analysis for the parent operation if it exists.
   template <typename AnalysisT>
-  Optional<std::reference_wrapper<AnalysisT>> getCachedParentAnalysis() {
+  std::optional<std::reference_wrapper<AnalysisT>> getCachedParentAnalysis() {
     return getAnalysisManager().getCachedParentAnalysis<AnalysisT>(
         getOperation()->getParentOp());
   }
 
   /// Returns the analysis for the given child operation if it exists.
   template <typename AnalysisT>
-  Optional<std::reference_wrapper<AnalysisT>>
+  std::optional<std::reference_wrapper<AnalysisT>>
   getCachedChildAnalysis(Operation *child) {
     return getAnalysisManager().getCachedChildAnalysis<AnalysisT>(child);
   }
@@ -303,10 +303,10 @@ class Pass {
 
   /// The name of the operation that this pass operates on, or std::nullopt if
   /// this is a generic OperationPass.
-  Optional<StringRef> opName;
+  std::optional<StringRef> opName;
 
   /// The current execution state for the pass.
-  Optional<detail::PassExecutionState> passState;
+  std::optional<detail::PassExecutionState> passState;
 
   /// The set of statistics held by this pass.
   std::vector<Statistic *> statistics;

diff  --git a/mlir/include/mlir/Pass/PassInstrumentation.h b/mlir/include/mlir/Pass/PassInstrumentation.h
index 8db982e5364a8..917bac4b22288 100644
--- a/mlir/include/mlir/Pass/PassInstrumentation.h
+++ b/mlir/include/mlir/Pass/PassInstrumentation.h
@@ -45,14 +45,14 @@ class PassInstrumentation {
   /// the name of the operation type being operated on, or std::nullopt if the
   /// pipeline is op-agnostic, and information related to the parent that
   /// spawned this pipeline.
-  virtual void runBeforePipeline(Optional<OperationName> name,
+  virtual void runBeforePipeline(std::optional<OperationName> name,
                                  const PipelineParentInfo &parentInfo);
 
   /// A callback to run after a pass pipeline has executed. This function takes
   /// the name of the operation type being operated on, or std::nullopt if the
   /// pipeline is op-agnostic, and information related to the parent that
   /// spawned this pipeline.
-  virtual void runAfterPipeline(Optional<OperationName> name,
+  virtual void runAfterPipeline(std::optional<OperationName> name,
                                 const PipelineParentInfo &parentInfo);
 
   /// A callback to run before a pass is executed. This function takes a pointer
@@ -93,12 +93,12 @@ class PassInstrumentor {
 
   /// See PassInstrumentation::runBeforePipeline for details.
   void
-  runBeforePipeline(Optional<OperationName> name,
+  runBeforePipeline(std::optional<OperationName> name,
                     const PassInstrumentation::PipelineParentInfo &parentInfo);
 
   /// See PassInstrumentation::runAfterPipeline for details.
   void
-  runAfterPipeline(Optional<OperationName> name,
+  runAfterPipeline(std::optional<OperationName> name,
                    const PassInstrumentation::PipelineParentInfo &parentInfo);
 
   /// See PassInstrumentation::runBeforePass for details.

diff  --git a/mlir/include/mlir/Pass/PassManager.h b/mlir/include/mlir/Pass/PassManager.h
index 877b8672ee25d..62dc532587a5f 100644
--- a/mlir/include/mlir/Pass/PassManager.h
+++ b/mlir/include/mlir/Pass/PassManager.h
@@ -128,11 +128,11 @@ class OpPassManager {
 
   /// Return the operation name that this pass manager operates on, or
   /// std::nullopt if this is an op-agnostic pass manager.
-  Optional<OperationName> getOpName(MLIRContext &context) const;
+  std::optional<OperationName> getOpName(MLIRContext &context) const;
 
   /// Return the operation name that this pass manager operates on, or
   /// std::nullopt if this is an op-agnostic pass manager.
-  Optional<StringRef> getOpName() const;
+  std::optional<StringRef> getOpName() const;
 
   /// Return the name used to anchor this pass manager. This is either the name
   /// of an operation, or the result of `getAnyOpAnchorName()` in the case of an
@@ -429,7 +429,7 @@ class PassManager : public OpPassManager {
   MLIRContext *context;
 
   /// Flag that specifies if pass statistics should be dumped.
-  Optional<PassDisplayMode> passStatisticsMode;
+  std::optional<PassDisplayMode> passStatisticsMode;
 
   /// A manager for pass instrumentations.
   std::unique_ptr<PassInstrumentor> instrumentor;

diff  --git a/mlir/include/mlir/Pass/PassRegistry.h b/mlir/include/mlir/Pass/PassRegistry.h
index c454152592365..db6d9dcfed672 100644
--- a/mlir/include/mlir/Pass/PassRegistry.h
+++ b/mlir/include/mlir/Pass/PassRegistry.h
@@ -260,7 +260,7 @@ class PassPipelineCLParser {
   std::unique_ptr<detail::PassPipelineCLParserImpl> impl;
 
   llvm::cl::opt<std::string> passPipeline;
-  Optional<llvm::cl::alias> passPipelineAlias;
+  std::optional<llvm::cl::alias> passPipelineAlias;
 };
 
 /// This class implements a command-line parser specifically for MLIR pass
@@ -296,9 +296,9 @@ struct PassReproducerOptions {
   LogicalResult apply(PassManager &pm) const;
 
 private:
-  Optional<std::string> pipeline;
-  Optional<bool> verifyEach;
-  Optional<bool> disableThreading;
+  std::optional<std::string> pipeline;
+  std::optional<bool> verifyEach;
+  std::optional<bool> disableThreading;
 };
 
 } // namespace mlir

diff  --git a/mlir/include/mlir/Support/LogicalResult.h b/mlir/include/mlir/Support/LogicalResult.h
index fa7bd6e565592..ebb14643cda73 100644
--- a/mlir/include/mlir/Support/LogicalResult.h
+++ b/mlir/include/mlir/Support/LogicalResult.h
@@ -76,7 +76,7 @@ inline bool failed(LogicalResult result) { return result.failed(); }
 /// value of type `T`. This allows for integrating with LogicalResult, while
 /// also providing a value on the success path.
 template <typename T>
-class [[nodiscard]] FailureOr : public Optional<T> {
+class [[nodiscard]] FailureOr : public std::optional<T> {
 public:
   /// Allow constructing from a LogicalResult. The result *must* be a failure.
   /// Success results should use a proper instance of type `T`.
@@ -85,19 +85,20 @@ class [[nodiscard]] FailureOr : public Optional<T> {
            "success should be constructed with an instance of 'T'");
   }
   FailureOr() : FailureOr(failure()) {}
-  FailureOr(T &&y) : Optional<T>(std::forward<T>(y)) {}
-  FailureOr(const T &y) : Optional<T>(y) {}
+  FailureOr(T &&y) : std::optional<T>(std::forward<T>(y)) {}
+  FailureOr(const T &y) : std::optional<T>(y) {}
   template <typename U,
             std::enable_if_t<std::is_constructible<T, U>::value> * = nullptr>
   FailureOr(const FailureOr<U> &other)
-      : Optional<T>(failed(other) ? Optional<T>() : Optional<T>(*other)) {}
+      : std::optional<T>(failed(other) ? std::optional<T>()
+                                       : std::optional<T>(*other)) {}
 
   operator LogicalResult() const { return success(this->has_value()); }
 
 private:
   /// Hide the bool conversion as it easily creates confusion.
-  using Optional<T>::operator bool;
-  using Optional<T>::has_value;
+  using std::optional<T>::operator bool;
+  using std::optional<T>::has_value;
 };
 
 /// Wrap a value on the success path in a FailureOr of the same value type.

diff  --git a/mlir/include/mlir/Support/Timing.h b/mlir/include/mlir/Support/Timing.h
index 3c7335c278dc1..bc3a642ba3222 100644
--- a/mlir/include/mlir/Support/Timing.h
+++ b/mlir/include/mlir/Support/Timing.h
@@ -141,7 +141,7 @@ class TimingManager {
   /// collection of timing samples is disabled. This will cause the timers
   /// constructed from the manager to be tombstones which can be skipped
   /// quickly.
-  virtual Optional<void *> rootTimer() = 0;
+  virtual std::optional<void *> rootTimer() = 0;
 
   /// Start the timer with the given handle.
   virtual void startTimer(void *handle) = 0;
@@ -399,7 +399,7 @@ class DefaultTimingManager : public TimingManager {
 
 protected:
   // `TimingManager` callbacks
-  Optional<void *> rootTimer() override;
+  std::optional<void *> rootTimer() override;
   void startTimer(void *handle) override;
   void stopTimer(void *handle) override;
   void *nestTimer(void *handle, const void *id,

diff  --git a/mlir/include/mlir/Tools/PDLL/AST/Diagnostic.h b/mlir/include/mlir/Tools/PDLL/AST/Diagnostic.h
index 896767a026189..a8bae327d2cdc 100644
--- a/mlir/include/mlir/Tools/PDLL/AST/Diagnostic.h
+++ b/mlir/include/mlir/Tools/PDLL/AST/Diagnostic.h
@@ -45,7 +45,7 @@ class Diagnostic {
 
   /// Attach a note to this diagnostic.
   Diagnostic &attachNote(const Twine &msg,
-                         Optional<SMRange> noteLoc = std::nullopt) {
+                         std::optional<SMRange> noteLoc = std::nullopt) {
     assert(getSeverity() != Severity::DK_Note &&
            "cannot attach a Note to a Note");
     notes.emplace_back(
@@ -129,7 +129,7 @@ class InFlightDiagnostic {
   DiagnosticEngine *owner = nullptr;
 
   /// The raw diagnostic that is inflight to be reported.
-  Optional<Diagnostic> impl;
+  std::optional<Diagnostic> impl;
 };
 
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/include/mlir/Tools/PDLL/AST/Nodes.h b/mlir/include/mlir/Tools/PDLL/AST/Nodes.h
index 51092d5a84347..8a07cf9f87acd 100644
--- a/mlir/include/mlir/Tools/PDLL/AST/Nodes.h
+++ b/mlir/include/mlir/Tools/PDLL/AST/Nodes.h
@@ -510,7 +510,7 @@ class OperationExpr final
                                ArrayRef<NamedAttributeDecl *> attributes);
 
   /// Return the name of the operation, or std::nullopt if there isn't one.
-  Optional<StringRef> getName() const;
+  std::optional<StringRef> getName() const;
 
   /// Return the declaration of the operation name.
   const OpNameDecl *getNameDecl() const { return nameDecl; }
@@ -670,7 +670,7 @@ class Decl : public Node {
 
   /// Return the documentation comment attached to this decl if it has been set.
   /// Otherwise, returns std::nullopt.
-  Optional<StringRef> getDocComment() const { return docComment; }
+  std::optional<StringRef> getDocComment() const { return docComment; }
 
 protected:
   Decl(TypeID typeID, SMRange loc, const Name *name = nullptr)
@@ -683,7 +683,7 @@ class Decl : public Node {
 
   /// The documentation comment attached to this decl. Defaults to None if
   /// the comment is unset/unknown.
-  Optional<StringRef> docComment;
+  std::optional<StringRef> docComment;
 };
 
 //===----------------------------------------------------------------------===//
@@ -766,7 +766,7 @@ class OpConstraintDecl
                                   const OpNameDecl *nameDecl = nullptr);
 
   /// Return the name of the operation, or std::nullopt if there isn't one.
-  Optional<StringRef> getName() const;
+  std::optional<StringRef> getName() const;
 
   /// Return the declaration of the operation name.
   const OpNameDecl *getNameDecl() const { return nameDecl; }
@@ -875,8 +875,9 @@ class UserConstraintDecl final
   /// Create a native constraint with the given optional code block.
   static UserConstraintDecl *
   createNative(Context &ctx, const Name &name, ArrayRef<VariableDecl *> inputs,
-               ArrayRef<VariableDecl *> results, Optional<StringRef> codeBlock,
-               Type resultType, ArrayRef<StringRef> nativeInputTypes = {}) {
+               ArrayRef<VariableDecl *> results,
+               std::optional<StringRef> codeBlock, Type resultType,
+               ArrayRef<StringRef> nativeInputTypes = {}) {
     return createImpl(ctx, name, inputs, nativeInputTypes, results, codeBlock,
                       /*body=*/nullptr, resultType);
   }
@@ -904,7 +905,7 @@ class UserConstraintDecl final
 
   /// Return the explicit native type to use for the given input. Returns
   /// std::nullopt if no explicit type was set.
-  Optional<StringRef> getNativeInputType(unsigned index) const;
+  std::optional<StringRef> getNativeInputType(unsigned index) const;
 
   /// Return the explicit results of the constraint declaration. May be empty,
   /// even if the constraint has results (e.g. in the case of inferred results).
@@ -917,7 +918,7 @@ class UserConstraintDecl final
 
   /// Return the optional code block of this constraint, if this is a native
   /// constraint with a provided implementation.
-  Optional<StringRef> getCodeBlock() const { return codeBlock; }
+  std::optional<StringRef> getCodeBlock() const { return codeBlock; }
 
   /// Return the body of this constraint if this constraint is a PDLL
   /// constraint, otherwise returns nullptr.
@@ -932,16 +933,18 @@ class UserConstraintDecl final
 private:
   /// Create either a PDLL constraint or a native constraint with the given
   /// components.
-  static UserConstraintDecl *
-  createImpl(Context &ctx, const Name &name, ArrayRef<VariableDecl *> inputs,
-             ArrayRef<StringRef> nativeInputTypes,
-             ArrayRef<VariableDecl *> results, Optional<StringRef> codeBlock,
-             const CompoundStmt *body, Type resultType);
+  static UserConstraintDecl *createImpl(Context &ctx, const Name &name,
+                                        ArrayRef<VariableDecl *> inputs,
+                                        ArrayRef<StringRef> nativeInputTypes,
+                                        ArrayRef<VariableDecl *> results,
+                                        std::optional<StringRef> codeBlock,
+                                        const CompoundStmt *body,
+                                        Type resultType);
 
   UserConstraintDecl(const Name &name, unsigned numInputs,
                      bool hasNativeInputTypes, unsigned numResults,
-                     Optional<StringRef> codeBlock, const CompoundStmt *body,
-                     Type resultType)
+                     std::optional<StringRef> codeBlock,
+                     const CompoundStmt *body, Type resultType)
       : Base(name.getLoc(), &name), numInputs(numInputs),
         numResults(numResults), codeBlock(codeBlock), constraintBody(body),
         resultType(resultType), hasNativeInputTypes(hasNativeInputTypes) {}
@@ -953,7 +956,7 @@ class UserConstraintDecl final
   unsigned numResults;
 
   /// The optional code block of this constraint.
-  Optional<StringRef> codeBlock;
+  std::optional<StringRef> codeBlock;
 
   /// The optional body of this constraint.
   const CompoundStmt *constraintBody;
@@ -1007,9 +1010,9 @@ class OpNameDecl : public Node::NodeBase<OpNameDecl, Decl> {
   static OpNameDecl *create(Context &ctx, SMRange loc);
 
   /// Return the name of this operation, or none if the name is unknown.
-  Optional<StringRef> getName() const {
+  std::optional<StringRef> getName() const {
     const Name *name = Decl::getName();
-    return name ? Optional<StringRef>(name->getName()) : std::nullopt;
+    return name ? std::optional<StringRef>(name->getName()) : std::nullopt;
   }
 
 private:
@@ -1025,12 +1028,12 @@ class OpNameDecl : public Node::NodeBase<OpNameDecl, Decl> {
 class PatternDecl : public Node::NodeBase<PatternDecl, Decl> {
 public:
   static PatternDecl *create(Context &ctx, SMRange location, const Name *name,
-                             Optional<uint16_t> benefit,
+                             std::optional<uint16_t> benefit,
                              bool hasBoundedRecursion,
                              const CompoundStmt *body);
 
   /// Return the benefit of this pattern if specified, or std::nullopt.
-  Optional<uint16_t> getBenefit() const { return benefit; }
+  std::optional<uint16_t> getBenefit() const { return benefit; }
 
   /// Return if this pattern has bounded rewrite recursion.
   bool hasBoundedRewriteRecursion() const { return hasBoundedRecursion; }
@@ -1044,13 +1047,13 @@ class PatternDecl : public Node::NodeBase<PatternDecl, Decl> {
   }
 
 private:
-  PatternDecl(SMRange loc, const Name *name, Optional<uint16_t> benefit,
+  PatternDecl(SMRange loc, const Name *name, std::optional<uint16_t> benefit,
               bool hasBoundedRecursion, const CompoundStmt *body)
       : Base(loc, name), benefit(benefit),
         hasBoundedRecursion(hasBoundedRecursion), patternBody(body) {}
 
   /// The benefit of the pattern if it was explicitly specified, None otherwise.
-  Optional<uint16_t> benefit;
+  std::optional<uint16_t> benefit;
 
   /// If the pattern has properly bounded rewrite recursion or not.
   bool hasBoundedRecursion;
@@ -1082,7 +1085,7 @@ class UserRewriteDecl final
   static UserRewriteDecl *createNative(Context &ctx, const Name &name,
                                        ArrayRef<VariableDecl *> inputs,
                                        ArrayRef<VariableDecl *> results,
-                                       Optional<StringRef> codeBlock,
+                                       std::optional<StringRef> codeBlock,
                                        Type resultType) {
     return createImpl(ctx, name, inputs, results, codeBlock, /*body=*/nullptr,
                       resultType);
@@ -1120,7 +1123,7 @@ class UserRewriteDecl final
 
   /// Return the optional code block of this rewrite, if this is a native
   /// rewrite with a provided implementation.
-  Optional<StringRef> getCodeBlock() const { return codeBlock; }
+  std::optional<StringRef> getCodeBlock() const { return codeBlock; }
 
   /// Return the body of this rewrite if this rewrite is a PDLL rewrite,
   /// otherwise returns nullptr.
@@ -1138,11 +1141,11 @@ class UserRewriteDecl final
   static UserRewriteDecl *createImpl(Context &ctx, const Name &name,
                                      ArrayRef<VariableDecl *> inputs,
                                      ArrayRef<VariableDecl *> results,
-                                     Optional<StringRef> codeBlock,
+                                     std::optional<StringRef> codeBlock,
                                      const CompoundStmt *body, Type resultType);
 
   UserRewriteDecl(const Name &name, unsigned numInputs, unsigned numResults,
-                  Optional<StringRef> codeBlock, const CompoundStmt *body,
+                  std::optional<StringRef> codeBlock, const CompoundStmt *body,
                   Type resultType)
       : Base(name.getLoc(), &name), numInputs(numInputs),
         numResults(numResults), codeBlock(codeBlock), rewriteBody(body),
@@ -1155,7 +1158,7 @@ class UserRewriteDecl final
   unsigned numResults;
 
   /// The optional code block of this rewrite.
-  Optional<StringRef> codeBlock;
+  std::optional<StringRef> codeBlock;
 
   /// The optional body of this rewrite.
   const CompoundStmt *rewriteBody;
@@ -1207,7 +1210,7 @@ class CallableDecl : public Decl {
 
   /// Return the optional code block of this callable, if this is a native
   /// callable with a provided implementation.
-  Optional<StringRef> getCodeBlock() const {
+  std::optional<StringRef> getCodeBlock() const {
     if (const auto *cst = dyn_cast<UserConstraintDecl>(this))
       return cst->getCodeBlock();
     return cast<UserRewriteDecl>(this)->getCodeBlock();

diff  --git a/mlir/include/mlir/Tools/PDLL/AST/Types.h b/mlir/include/mlir/Tools/PDLL/AST/Types.h
index e9f5259c76f99..03252e9f6620c 100644
--- a/mlir/include/mlir/Tools/PDLL/AST/Types.h
+++ b/mlir/include/mlir/Tools/PDLL/AST/Types.h
@@ -162,12 +162,12 @@ class OperationType : public Type::TypeBase<detail::OperationTypeStorage> {
   /// Return an instance of the Operation type with an optional operation name.
   /// If no name is provided, this type may refer to any operation.
   static OperationType get(Context &context,
-                           Optional<StringRef> name = std::nullopt,
+                           std::optional<StringRef> name = std::nullopt,
                            const ods::Operation *odsOp = nullptr);
 
   /// Return the name of this operation type, or std::nullopt if it doesn't have
   /// on.
-  Optional<StringRef> getName() const;
+  std::optional<StringRef> getName() const;
 
   /// Return the ODS operation that this type refers to, or nullptr if the ODS
   /// operation is unknown.

diff  --git a/mlir/include/mlir/Tools/PDLL/Parser/CodeComplete.h b/mlir/include/mlir/Tools/PDLL/Parser/CodeComplete.h
index 237aed1af85b0..3c6d941354317 100644
--- a/mlir/include/mlir/Tools/PDLL/Parser/CodeComplete.h
+++ b/mlir/include/mlir/Tools/PDLL/Parser/CodeComplete.h
@@ -77,12 +77,12 @@ class CodeCompleteContext {
 
   /// Signal code completion for the signature of an operation's operands.
   virtual void
-  codeCompleteOperationOperandsSignature(Optional<StringRef> opName,
+  codeCompleteOperationOperandsSignature(std::optional<StringRef> opName,
                                          unsigned currentNumOperands) {}
 
   /// Signal code completion for the signature of an operation's results.
   virtual void
-  codeCompleteOperationResultsSignature(Optional<StringRef> opName,
+  codeCompleteOperationResultsSignature(std::optional<StringRef> opName,
                                         unsigned currentNumResults) {}
 
 protected:

diff  --git a/mlir/include/mlir/Tools/mlir-translate/Translation.h b/mlir/include/mlir/Tools/mlir-translate/Translation.h
index d80d53818b260..88c94a138715d 100644
--- a/mlir/include/mlir/Tools/mlir-translate/Translation.h
+++ b/mlir/include/mlir/Tools/mlir-translate/Translation.h
@@ -62,7 +62,7 @@ class Translation {
 public:
   Translation() = default;
   Translation(TranslateFunction function, StringRef description,
-              Optional<llvm::Align> inputAlignment)
+              std::optional<llvm::Align> inputAlignment)
       : function(std::move(function)), description(description),
         inputAlignment(inputAlignment) {}
 
@@ -70,7 +70,9 @@ class Translation {
   StringRef getDescription() const { return description; }
 
   /// Return the optional alignment desired for the input of the translation.
-  Optional<llvm::Align> getInputAlignment() const { return inputAlignment; }
+  std::optional<llvm::Align> getInputAlignment() const {
+    return inputAlignment;
+  }
 
   /// Invoke the translation function with the given input and output streams.
   LogicalResult operator()(const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
@@ -87,7 +89,7 @@ class Translation {
   StringRef description;
 
   /// An optional alignment desired for the input of the translation.
-  Optional<llvm::Align> inputAlignment;
+  std::optional<llvm::Align> inputAlignment;
 };
 
 /// Use Translate[ToMLIR|FromMLIR]Registration as an initializer that
@@ -111,19 +113,19 @@ struct TranslateToMLIRRegistration {
       const TranslateSourceMgrToMLIRFunction &function,
       const DialectRegistrationFunction &dialectRegistration =
           [](DialectRegistry &) {},
-      Optional<llvm::Align> inputAlignment = std::nullopt);
+      std::optional<llvm::Align> inputAlignment = std::nullopt);
   TranslateToMLIRRegistration(
       llvm::StringRef name, llvm::StringRef description,
       const TranslateRawSourceMgrToMLIRFunction &function,
       const DialectRegistrationFunction &dialectRegistration =
           [](DialectRegistry &) {},
-      Optional<llvm::Align> inputAlignment = std::nullopt);
+      std::optional<llvm::Align> inputAlignment = std::nullopt);
   TranslateToMLIRRegistration(
       llvm::StringRef name, llvm::StringRef description,
       const TranslateStringRefToMLIRFunction &function,
       const DialectRegistrationFunction &dialectRegistration =
           [](DialectRegistry &) {},
-      Optional<llvm::Align> inputAlignment = std::nullopt);
+      std::optional<llvm::Align> inputAlignment = std::nullopt);
 };
 
 struct TranslateFromMLIRRegistration {

diff  --git a/mlir/include/mlir/Transforms/InliningUtils.h b/mlir/include/mlir/Transforms/InliningUtils.h
index c388f14af04e6..241983ef8c3dc 100644
--- a/mlir/include/mlir/Transforms/InliningUtils.h
+++ b/mlir/include/mlir/Transforms/InliningUtils.h
@@ -209,13 +209,13 @@ LogicalResult inlineRegion(InlinerInterface &interface, Region *src,
                            Operation *inlinePoint, IRMapping &mapper,
                            ValueRange resultsToReplace,
                            TypeRange regionResultTypes,
-                           Optional<Location> inlineLoc = std::nullopt,
+                           std::optional<Location> inlineLoc = std::nullopt,
                            bool shouldCloneInlinedRegion = true);
 LogicalResult inlineRegion(InlinerInterface &interface, Region *src,
                            Block *inlineBlock, Block::iterator inlinePoint,
                            IRMapping &mapper, ValueRange resultsToReplace,
                            TypeRange regionResultTypes,
-                           Optional<Location> inlineLoc = std::nullopt,
+                           std::optional<Location> inlineLoc = std::nullopt,
                            bool shouldCloneInlinedRegion = true);
 
 /// This function is an overload of the above 'inlineRegion' that allows for
@@ -224,13 +224,13 @@ LogicalResult inlineRegion(InlinerInterface &interface, Region *src,
 LogicalResult inlineRegion(InlinerInterface &interface, Region *src,
                            Operation *inlinePoint, ValueRange inlinedOperands,
                            ValueRange resultsToReplace,
-                           Optional<Location> inlineLoc = std::nullopt,
+                           std::optional<Location> inlineLoc = std::nullopt,
                            bool shouldCloneInlinedRegion = true);
 LogicalResult inlineRegion(InlinerInterface &interface, Region *src,
                            Block *inlineBlock, Block::iterator inlinePoint,
                            ValueRange inlinedOperands,
                            ValueRange resultsToReplace,
-                           Optional<Location> inlineLoc = std::nullopt,
+                           std::optional<Location> inlineLoc = std::nullopt,
                            bool shouldCloneInlinedRegion = true);
 
 /// This function inlines a given region, 'src', of a callable operation,

diff  --git a/mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp b/mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp
index 6ccc6b8e9318a..2415ff48144bc 100644
--- a/mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp
+++ b/mlir/lib/Analysis/DataFlow/DeadCodeAnalysis.cpp
@@ -311,7 +311,7 @@ void DeadCodeAnalysis::visitCallOperation(CallOpInterface call) {
 /// Get the constant values of the operands of an operation. If any of the
 /// constant value lattices are uninitialized, return none to indicate the
 /// analysis should bail out.
-static Optional<SmallVector<Attribute>> getOperandValuesImpl(
+static std::optional<SmallVector<Attribute>> getOperandValuesImpl(
     Operation *op,
     function_ref<const Lattice<ConstantValue> *(Value)> getLattice) {
   SmallVector<Attribute> operands;
@@ -326,7 +326,7 @@ static Optional<SmallVector<Attribute>> getOperandValuesImpl(
   return operands;
 }
 
-Optional<SmallVector<Attribute>>
+std::optional<SmallVector<Attribute>>
 DeadCodeAnalysis::getOperandValues(Operation *op) {
   return getOperandValuesImpl(op, [&](Value value) {
     auto *lattice = getOrCreate<Lattice<ConstantValue>>(value);
@@ -337,7 +337,7 @@ DeadCodeAnalysis::getOperandValues(Operation *op) {
 
 void DeadCodeAnalysis::visitBranchOperation(BranchOpInterface branch) {
   // Try to deduce a single successor for the branch.
-  Optional<SmallVector<Attribute>> operands = getOperandValues(branch);
+  std::optional<SmallVector<Attribute>> operands = getOperandValues(branch);
   if (!operands)
     return;
 
@@ -353,7 +353,7 @@ void DeadCodeAnalysis::visitBranchOperation(BranchOpInterface branch) {
 void DeadCodeAnalysis::visitRegionBranchOperation(
     RegionBranchOpInterface branch) {
   // Try to deduce which regions are executable.
-  Optional<SmallVector<Attribute>> operands = getOperandValues(branch);
+  std::optional<SmallVector<Attribute>> operands = getOperandValues(branch);
   if (!operands)
     return;
 
@@ -377,7 +377,7 @@ void DeadCodeAnalysis::visitRegionBranchOperation(
 
 void DeadCodeAnalysis::visitRegionTerminator(Operation *op,
                                              RegionBranchOpInterface branch) {
-  Optional<SmallVector<Attribute>> operands = getOperandValues(op);
+  std::optional<SmallVector<Attribute>> operands = getOperandValues(op);
   if (!operands)
     return;
 

diff  --git a/mlir/lib/Analysis/DataFlow/IntegerRangeAnalysis.cpp b/mlir/lib/Analysis/DataFlow/IntegerRangeAnalysis.cpp
index 95a8c611e066e..2823f27053040 100644
--- a/mlir/lib/Analysis/DataFlow/IntegerRangeAnalysis.cpp
+++ b/mlir/lib/Analysis/DataFlow/IntegerRangeAnalysis.cpp
@@ -40,7 +40,7 @@ void IntegerValueRangeLattice::onUpdate(DataFlowSolver *solver) const {
 
   // If the integer range can be narrowed to a constant, update the constant
   // value of the SSA value.
-  Optional<APInt> constant = getValue().getValue().getConstantValue();
+  std::optional<APInt> constant = getValue().getValue().getConstantValue();
   auto value = point.get<Value>();
   auto *cv = solver->getOrCreateState<Lattice<ConstantValue>>(value);
   if (!constant)

diff  --git a/mlir/lib/Analysis/Presburger/IntegerRelation.cpp b/mlir/lib/Analysis/Presburger/IntegerRelation.cpp
index 7423744e04454..f421d05fa310e 100644
--- a/mlir/lib/Analysis/Presburger/IntegerRelation.cpp
+++ b/mlir/lib/Analysis/Presburger/IntegerRelation.cpp
@@ -764,7 +764,8 @@ bool IntegerRelation::isIntegerEmpty() const { return !findIntegerSample(); }
 ///
 /// Concatenating the samples from B and C gives a sample v in S*T, so the
 /// returned sample T*v is a sample in S.
-Optional<SmallVector<MPInt, 8>> IntegerRelation::findIntegerSample() const {
+std::optional<SmallVector<MPInt, 8>>
+IntegerRelation::findIntegerSample() const {
   // First, try the GCD test heuristic.
   if (isEmptyByGCDTest())
     return {};
@@ -803,7 +804,7 @@ Optional<SmallVector<MPInt, 8>> IntegerRelation::findIntegerSample() const {
   boundedSet.removeVarRange(numBoundedDims, boundedSet.getNumVars());
 
   // 3) Try to obtain a sample from the bounded set.
-  Optional<SmallVector<MPInt, 8>> boundedSample =
+  std::optional<SmallVector<MPInt, 8>> boundedSample =
       Simplex(boundedSet).findIntegerSample();
   if (!boundedSample)
     return {};
@@ -902,7 +903,7 @@ bool IntegerRelation::containsPoint(ArrayRef<MPInt> point) const {
 /// compute the values of the locals that have division representations and
 /// only use the integer emptiness check for the locals that don't have this.
 /// Handling this correctly requires ordering the divs, though.
-Optional<SmallVector<MPInt, 8>>
+std::optional<SmallVector<MPInt, 8>>
 IntegerRelation::containsPointNoLocal(ArrayRef<MPInt> point) const {
   assert(point.size() == getNumVars() - getNumLocalVars() &&
          "Point should contain all vars except locals!");
@@ -1081,7 +1082,7 @@ void IntegerRelation::removeRedundantConstraints() {
   equalities.resizeVertically(pos);
 }
 
-Optional<MPInt> IntegerRelation::computeVolume() const {
+std::optional<MPInt> IntegerRelation::computeVolume() const {
   assert(getNumSymbolVars() == 0 && "Symbols are not yet supported!");
 
   Simplex simplex(*this);
@@ -1391,7 +1392,7 @@ void IntegerRelation::constantFoldVarRange(unsigned pos, unsigned num) {
 //       s0 + s1 + 16 <= d0 <= s0 + s1 + 31, returns 16.
 //       s0 - 7 <= 8*j <= s0 returns 1 with lb = s0, lbDivisor = 8 (since lb =
 //       ceil(s0 - 7 / 8) = floor(s0 / 8)).
-Optional<MPInt> IntegerRelation::getConstantBoundOnDimSize(
+std::optional<MPInt> IntegerRelation::getConstantBoundOnDimSize(
     unsigned pos, SmallVectorImpl<MPInt> *lb, MPInt *boundFloorDivisor,
     SmallVectorImpl<MPInt> *ub, unsigned *minLbPos, unsigned *minUbPos) const {
   assert(pos < getNumDimVars() && "Invalid variable position");
@@ -1456,7 +1457,7 @@ Optional<MPInt> IntegerRelation::getConstantBoundOnDimSize(
                                /*eqIndices=*/nullptr, /*offset=*/0,
                                /*num=*/getNumDimVars());
 
-  Optional<MPInt> minDiff;
+  std::optional<MPInt> minDiff;
   unsigned minLbPosition = 0, minUbPosition = 0;
   for (auto ubPos : ubIndices) {
     for (auto lbPos : lbIndices) {
@@ -1517,7 +1518,7 @@ Optional<MPInt> IntegerRelation::getConstantBoundOnDimSize(
 }
 
 template <bool isLower>
-Optional<MPInt>
+std::optional<MPInt>
 IntegerRelation::computeConstantLowerOrUpperBound(unsigned pos) {
   assert(pos < getNumVars() && "invalid position");
   // Project to 'pos'.
@@ -1539,7 +1540,7 @@ IntegerRelation::computeConstantLowerOrUpperBound(unsigned pos) {
     // If it doesn't, there isn't a bound on it.
     return std::nullopt;
 
-  Optional<MPInt> minOrMaxConst;
+  std::optional<MPInt> minOrMaxConst;
 
   // Take the max across all const lower bounds (or min across all constant
   // upper bounds).
@@ -1574,8 +1575,8 @@ IntegerRelation::computeConstantLowerOrUpperBound(unsigned pos) {
   return minOrMaxConst;
 }
 
-Optional<MPInt> IntegerRelation::getConstantBound(BoundType type,
-                                                  unsigned pos) const {
+std::optional<MPInt> IntegerRelation::getConstantBound(BoundType type,
+                                                       unsigned pos) const {
   if (type == BoundType::LB)
     return IntegerRelation(*this)
         .computeConstantLowerOrUpperBound</*isLower=*/true>(pos);
@@ -1584,13 +1585,13 @@ Optional<MPInt> IntegerRelation::getConstantBound(BoundType type,
         .computeConstantLowerOrUpperBound</*isLower=*/false>(pos);
 
   assert(type == BoundType::EQ && "expected EQ");
-  Optional<MPInt> lb =
+  std::optional<MPInt> lb =
       IntegerRelation(*this).computeConstantLowerOrUpperBound</*isLower=*/true>(
           pos);
-  Optional<MPInt> ub =
+  std::optional<MPInt> ub =
       IntegerRelation(*this)
           .computeConstantLowerOrUpperBound</*isLower=*/false>(pos);
-  return (lb && ub && *lb == *ub) ? Optional<MPInt>(*ub) : std::nullopt;
+  return (lb && ub && *lb == *ub) ? std::optional<MPInt>(*ub) : std::nullopt;
 }
 
 // A simple (naive and conservative) check for hyper-rectangularity.

diff  --git a/mlir/lib/Analysis/Presburger/PWMAFunction.cpp b/mlir/lib/Analysis/Presburger/PWMAFunction.cpp
index 413d9a0db255b..c31d50ad29ff4 100644
--- a/mlir/lib/Analysis/Presburger/PWMAFunction.cpp
+++ b/mlir/lib/Analysis/Presburger/PWMAFunction.cpp
@@ -63,11 +63,11 @@ MultiAffineFunction::valueAt(ArrayRef<MPInt> point) const {
 
   SmallVector<MPInt, 8> pointHomogenous{llvm::to_vector(point)};
   // Get the division values at this point.
-  SmallVector<Optional<MPInt>, 8> divValues = divs.divValuesAt(point);
+  SmallVector<std::optional<MPInt>, 8> divValues = divs.divValuesAt(point);
   // The given point didn't include the values of the divs which the output is a
   // function of; we have computed one possible set of values and use them here.
   pointHomogenous.reserve(pointHomogenous.size() + divValues.size());
-  for (const Optional<MPInt> &divVal : divValues)
+  for (const std::optional<MPInt> &divVal : divValues)
     pointHomogenous.push_back(*divVal);
   // The matrix `output` has an affine expression in the ith row, corresponding
   // to the expression for the ith value in the output vector. The last column
@@ -424,7 +424,7 @@ void PWMAFunction::removeOutputs(unsigned start, unsigned end) {
     piece.output.removeOutputs(start, end);
 }
 
-Optional<SmallVector<MPInt, 8>>
+std::optional<SmallVector<MPInt, 8>>
 PWMAFunction::valueAt(ArrayRef<MPInt> point) const {
   assert(point.size() == getNumDomainVars() + getNumSymbolVars());
 

diff  --git a/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp b/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp
index 37fdf388441eb..9c956709d8c36 100644
--- a/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp
+++ b/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp
@@ -463,7 +463,8 @@ bool PresburgerRelation::isIntegerEmpty() const {
 bool PresburgerRelation::findIntegerSample(SmallVectorImpl<MPInt> &sample) {
   // A sample exists iff any of the disjuncts contains a sample.
   for (const IntegerRelation &disjunct : disjuncts) {
-    if (Optional<SmallVector<MPInt, 8>> opt = disjunct.findIntegerSample()) {
+    if (std::optional<SmallVector<MPInt, 8>> opt =
+            disjunct.findIntegerSample()) {
       sample = std::move(*opt);
       return true;
     }
@@ -471,13 +472,13 @@ bool PresburgerRelation::findIntegerSample(SmallVectorImpl<MPInt> &sample) {
   return false;
 }
 
-Optional<MPInt> PresburgerRelation::computeVolume() const {
+std::optional<MPInt> PresburgerRelation::computeVolume() const {
   assert(getNumSymbolVars() == 0 && "Symbols are not yet supported!");
   // The sum of the volumes of the disjuncts is a valid overapproximation of the
   // volume of their union, even if they overlap.
   MPInt result(0);
   for (const IntegerRelation &disjunct : disjuncts) {
-    Optional<MPInt> volume = disjunct.computeVolume();
+    std::optional<MPInt> volume = disjunct.computeVolume();
     if (!volume)
       return {};
     result += *volume;

diff  --git a/mlir/lib/Analysis/Presburger/Simplex.cpp b/mlir/lib/Analysis/Presburger/Simplex.cpp
index 0bcc8ee18b819..228f04160c731 100644
--- a/mlir/lib/Analysis/Presburger/Simplex.cpp
+++ b/mlir/lib/Analysis/Presburger/Simplex.cpp
@@ -272,7 +272,7 @@ LogicalResult LexSimplexBase::addCut(unsigned row) {
   return moveRowUnknownToColumn(cutRow);
 }
 
-Optional<unsigned> LexSimplex::maybeGetNonIntegralVarRow() const {
+std::optional<unsigned> LexSimplex::maybeGetNonIntegralVarRow() const {
   for (const Unknown &u : var) {
     if (u.orientation == Orientation::Column)
       continue;
@@ -292,7 +292,7 @@ MaybeOptimum<SmallVector<MPInt, 8>> LexSimplex::findIntegerLexMin() {
     return OptimumKind::Empty;
 
   // Then, if the sample value is integral, we are done.
-  while (Optional<unsigned> maybeRow = maybeGetNonIntegralVarRow()) {
+  while (std::optional<unsigned> maybeRow = maybeGetNonIntegralVarRow()) {
     // Otherwise, for the variable whose row has a non-integral sample value,
     // we add a cut, a constraint that remove this rational point
     // while preserving all integer points, thus keeping the lexmin the same.
@@ -478,7 +478,7 @@ void SymbolicLexSimplex::recordOutput(SymbolicLexMin &result) const {
        MultiAffineFunction(funcSpace, output, domainPoly.getLocalReprs())});
 }
 
-Optional<unsigned> SymbolicLexSimplex::maybeGetAlwaysViolatedRow() {
+std::optional<unsigned> SymbolicLexSimplex::maybeGetAlwaysViolatedRow() {
   // First look for rows that are clearly violated just from the big M
   // coefficient, without needing to perform any simplex queries on the domain.
   for (unsigned row = 0, e = getNumRows(); row < e; ++row)
@@ -496,7 +496,7 @@ Optional<unsigned> SymbolicLexSimplex::maybeGetAlwaysViolatedRow() {
   return {};
 }
 
-Optional<unsigned> SymbolicLexSimplex::maybeGetNonIntegralVarRow() {
+std::optional<unsigned> SymbolicLexSimplex::maybeGetNonIntegralVarRow() {
   for (const Unknown &u : var) {
     if (u.orientation == Orientation::Column)
       continue;
@@ -510,7 +510,7 @@ Optional<unsigned> SymbolicLexSimplex::maybeGetNonIntegralVarRow() {
 /// The non-branching pivots are just the ones moving the rows
 /// that are always violated in the symbol domain.
 LogicalResult SymbolicLexSimplex::doNonBranchingPivots() {
-  while (Optional<unsigned> row = maybeGetAlwaysViolatedRow())
+  while (std::optional<unsigned> row = maybeGetAlwaysViolatedRow())
     if (moveRowUnknownToColumn(*row).failed())
       return failure();
   return success();
@@ -612,7 +612,7 @@ SymbolicLexMin SymbolicLexSimplex::computeSymbolicIntegerLexMin() {
 
       // The tableau is rationally consistent for the current domain.
       // Now we look for non-integral sample values and add cuts for them.
-      if (Optional<unsigned> row = maybeGetNonIntegralVarRow()) {
+      if (std::optional<unsigned> row = maybeGetNonIntegralVarRow()) {
         if (addSymbolicCut(*row).failed()) {
           // No integral points; return.
           --level;
@@ -675,7 +675,7 @@ bool LexSimplex::rowIsViolated(unsigned row) const {
   return false;
 }
 
-Optional<unsigned> LexSimplex::maybeGetViolatedRow() const {
+std::optional<unsigned> LexSimplex::maybeGetViolatedRow() const {
   for (unsigned row = 0, e = getNumRows(); row < e; ++row)
     if (rowIsViolated(row))
       return row;
@@ -688,7 +688,7 @@ Optional<unsigned> LexSimplex::maybeGetViolatedRow() const {
 LogicalResult LexSimplex::restoreRationalConsistency() {
   if (empty)
     return failure();
-  while (Optional<unsigned> maybeViolatedRow = maybeGetViolatedRow())
+  while (std::optional<unsigned> maybeViolatedRow = maybeGetViolatedRow())
     if (moveRowUnknownToColumn(*maybeViolatedRow).failed())
       return failure();
   return success();
@@ -865,8 +865,8 @@ unsigned LexSimplexBase::getLexMinPivotColumn(unsigned row, unsigned colA,
 ///
 /// If multiple columns are valid, we break ties by considering a lexicographic
 /// ordering where we prefer unknowns with lower index.
-Optional<SimplexBase::Pivot> Simplex::findPivot(int row,
-                                                Direction direction) const {
+std::optional<SimplexBase::Pivot>
+Simplex::findPivot(int row, Direction direction) const {
   std::optional<unsigned> col;
   for (unsigned j = 2, e = getNumColumns(); j < e; ++j) {
     MPInt elem = tableau(row, j);
@@ -885,7 +885,7 @@ Optional<SimplexBase::Pivot> Simplex::findPivot(int row,
 
   Direction newDirection =
       tableau(row, *col) < 0 ? flippedDirection(direction) : direction;
-  Optional<unsigned> maybePivotRow = findPivotRow(row, newDirection, *col);
+  std::optional<unsigned> maybePivotRow = findPivotRow(row, newDirection, *col);
   return Pivot{maybePivotRow.value_or(row), *col};
 }
 
@@ -977,7 +977,7 @@ LogicalResult Simplex::restoreRow(Unknown &u) {
          "unknown should be in row position");
 
   while (tableau(u.pos, 1) < 0) {
-    Optional<Pivot> maybePivot = findPivot(u.pos, Direction::Up);
+    std::optional<Pivot> maybePivot = findPivot(u.pos, Direction::Up);
     if (!maybePivot)
       break;
 
@@ -1010,10 +1010,10 @@ LogicalResult Simplex::restoreRow(Unknown &u) {
 /// 0 and hence saturates the bound it imposes. We break ties between rows that
 /// impose the same bound by considering a lexicographic ordering where we
 /// prefer unknowns with lower index value.
-Optional<unsigned> Simplex::findPivotRow(Optional<unsigned> skipRow,
-                                         Direction direction,
-                                         unsigned col) const {
-  Optional<unsigned> retRow;
+std::optional<unsigned> Simplex::findPivotRow(std::optional<unsigned> skipRow,
+                                              Direction direction,
+                                              unsigned col) const {
+  std::optional<unsigned> retRow;
   // Initialize these to zero in order to silence a warning about retElem and
   // retConst being used uninitialized in the initialization of `
diff ` below. In
   // reality, these are always initialized when that line is reached since these
@@ -1152,7 +1152,7 @@ void SimplexBase::removeLastConstraintRowOrientation() {
 //
 // If we have a variable, then the column has zero coefficients for every row
 // iff no constraints have been added with a non-zero coefficient for this row.
-Optional<unsigned> SimplexBase::findAnyPivotRow(unsigned col) {
+std::optional<unsigned> SimplexBase::findAnyPivotRow(unsigned col) {
   for (unsigned row = nRedundant, e = getNumRows(); row < e; ++row)
     if (tableau(row, col) != 0)
       return row;
@@ -1173,13 +1173,14 @@ void Simplex::undoLastConstraint() {
     // coefficient for the column. findAnyPivotRow will always be able to
     // find such a row for a constraint.
     unsigned column = con.back().pos;
-    if (Optional<unsigned> maybeRow = findPivotRow({}, Direction::Up, column)) {
+    if (std::optional<unsigned> maybeRow =
+            findPivotRow({}, Direction::Up, column)) {
       pivot(*maybeRow, column);
-    } else if (Optional<unsigned> maybeRow =
+    } else if (std::optional<unsigned> maybeRow =
                    findPivotRow({}, Direction::Down, column)) {
       pivot(*maybeRow, column);
     } else {
-      Optional<unsigned> row = findAnyPivotRow(column);
+      std::optional<unsigned> row = findAnyPivotRow(column);
       assert(row && "Pivot should always exist for a constraint!");
       pivot(*row, column);
     }
@@ -1198,7 +1199,7 @@ void LexSimplexBase::undoLastConstraint() {
     // snapshot, so what pivots we perform while undoing doesn't matter as
     // long as we get the unknown to row orientation and remove it.
     unsigned column = con.back().pos;
-    Optional<unsigned> row = findAnyPivotRow(column);
+    std::optional<unsigned> row = findAnyPivotRow(column);
     assert(row && "Pivot should always exist for a constraint!");
     pivot(*row, column);
   }
@@ -1324,7 +1325,7 @@ void SimplexBase::intersectIntegerRelation(const IntegerRelation &rel) {
 MaybeOptimum<Fraction> Simplex::computeRowOptimum(Direction direction,
                                                   unsigned row) {
   // Keep trying to find a pivot for the row in the specified direction.
-  while (Optional<Pivot> maybePivot = findPivot(row, direction)) {
+  while (std::optional<Pivot> maybePivot = findPivot(row, direction)) {
     // If findPivot returns a pivot involving the row itself, then the optimum
     // is unbounded, so we return std::nullopt.
     if (maybePivot->row == row)
@@ -1357,7 +1358,7 @@ MaybeOptimum<Fraction> Simplex::computeOptimum(Direction direction,
     return OptimumKind::Empty;
   if (u.orientation == Orientation::Column) {
     unsigned column = u.pos;
-    Optional<unsigned> pivotRow = findPivotRow({}, direction, column);
+    std::optional<unsigned> pivotRow = findPivotRow({}, direction, column);
     // If no pivot is returned, the constraint is unbounded in the specified
     // direction.
     if (!pivotRow)
@@ -1424,7 +1425,8 @@ void Simplex::detectRedundant(unsigned offset, unsigned count) {
     Unknown &u = con[offset + i];
     if (u.orientation == Orientation::Column) {
       unsigned column = u.pos;
-      Optional<unsigned> pivotRow = findPivotRow({}, Direction::Down, column);
+      std::optional<unsigned> pivotRow =
+          findPivotRow({}, Direction::Down, column);
       // If no downward pivot is returned, the constraint is unbounded below
       // and hence not redundant.
       if (!pivotRow)
@@ -1546,7 +1548,7 @@ Simplex Simplex::makeProduct(const Simplex &a, const Simplex &b) {
   return result;
 }
 
-Optional<SmallVector<Fraction, 8>> Simplex::getRationalSample() const {
+std::optional<SmallVector<Fraction, 8>> Simplex::getRationalSample() const {
   if (empty)
     return {};
 
@@ -1601,7 +1603,7 @@ MaybeOptimum<SmallVector<Fraction, 8>> LexSimplex::getRationalSample() const {
   return sample;
 }
 
-Optional<SmallVector<MPInt, 8>> Simplex::getSamplePointIfIntegral() const {
+std::optional<SmallVector<MPInt, 8>> Simplex::getSamplePointIfIntegral() const {
   // If the tableau is empty, no sample point exists.
   if (empty)
     return {};
@@ -1969,7 +1971,7 @@ void Simplex::reduceBasis(Matrix &basis, unsigned level) {
 ///
 /// To avoid potentially arbitrarily large recursion depths leading to stack
 /// overflows, this algorithm is implemented iteratively.
-Optional<SmallVector<MPInt, 8>> Simplex::findIntegerSample() {
+std::optional<SmallVector<MPInt, 8>> Simplex::findIntegerSample() {
   if (empty)
     return {};
 

diff  --git a/mlir/lib/Analysis/Presburger/Utils.cpp b/mlir/lib/Analysis/Presburger/Utils.cpp
index d397744eb23ec..89ccc4f263290 100644
--- a/mlir/lib/Analysis/Presburger/Utils.cpp
+++ b/mlir/lib/Analysis/Presburger/Utils.cpp
@@ -378,11 +378,11 @@ SmallVector<MPInt, 8> presburger::getComplementIneq(ArrayRef<MPInt> ineq) {
   return coeffs;
 }
 
-SmallVector<Optional<MPInt>, 4>
+SmallVector<std::optional<MPInt>, 4>
 DivisionRepr::divValuesAt(ArrayRef<MPInt> point) const {
   assert(point.size() == getNumNonDivs() && "Incorrect point size");
 
-  SmallVector<Optional<MPInt>, 4> divValues(getNumDivs(), std::nullopt);
+  SmallVector<std::optional<MPInt>, 4> divValues(getNumDivs(), std::nullopt);
   bool changed = true;
   while (changed) {
     changed = false;

diff  --git a/mlir/lib/AsmParser/AsmParserImpl.h b/mlir/lib/AsmParser/AsmParserImpl.h
index 0463929d52ed4..26e1f4f122ec1 100644
--- a/mlir/lib/AsmParser/AsmParserImpl.h
+++ b/mlir/lib/AsmParser/AsmParserImpl.h
@@ -287,7 +287,7 @@ class AsmParserImpl : public BaseT {
 
     // Check for a hexadecimal float value.
     if (curTok.is(Token::integer)) {
-      Optional<APFloat> apResult;
+      std::optional<APFloat> apResult;
       if (failed(parser.parseFloatFromIntegerLiteral(
               apResult, curTok, isNegative, APFloat::IEEEdouble(),
               /*typeSizeInBits=*/64)))

diff  --git a/mlir/lib/AsmParser/AttributeParser.cpp b/mlir/lib/AsmParser/AttributeParser.cpp
index 1668341399912..16e86e687d552 100644
--- a/mlir/lib/AsmParser/AttributeParser.cpp
+++ b/mlir/lib/AsmParser/AttributeParser.cpp
@@ -356,8 +356,8 @@ Attribute Parser::parseFloatAttr(Type type, bool isNegative) {
 
 /// Construct an APint from a parsed value, a known attribute type and
 /// sign.
-static Optional<APInt> buildAttributeAPInt(Type type, bool isNegative,
-                                           StringRef spelling) {
+static std::optional<APInt> buildAttributeAPInt(Type type, bool isNegative,
+                                                StringRef spelling) {
   // Parse the integer value into an APInt that is big enough to hold the value.
   APInt result;
   bool isHex = spelling.size() > 1 && spelling[1] == 'x';
@@ -417,7 +417,7 @@ Attribute Parser::parseDecOrHexAttr(Type type, bool isNegative) {
   }
 
   if (auto floatType = type.dyn_cast<FloatType>()) {
-    Optional<APFloat> result;
+    std::optional<APFloat> result;
     if (failed(parseFloatFromIntegerLiteral(result, tok, isNegative,
                                             floatType.getFloatSemantics(),
                                             floatType.getWidth())))
@@ -435,7 +435,7 @@ Attribute Parser::parseDecOrHexAttr(Type type, bool isNegative) {
     return nullptr;
   }
 
-  Optional<APInt> apInt = buildAttributeAPInt(type, isNegative, spelling);
+  std::optional<APInt> apInt = buildAttributeAPInt(type, isNegative, spelling);
   if (!apInt)
     return emitError(loc, "integer constant out of range for attribute"),
            nullptr;
@@ -450,7 +450,7 @@ Attribute Parser::parseDecOrHexAttr(Type type, bool isNegative) {
 /// stored into 'result'.
 static ParseResult parseElementAttrHexValues(Parser &parser, Token tok,
                                              std::string &result) {
-  if (Optional<std::string> value = tok.getHexStringValue()) {
+  if (std::optional<std::string> value = tok.getHexStringValue()) {
     result = std::move(*value);
     return success();
   }
@@ -636,7 +636,7 @@ TensorLiteralParser::getIntAttrElements(SMLoc loc, Type eltTy,
     }
 
     // Create APInt values for each element with the correct bitwidth.
-    Optional<APInt> apInt =
+    std::optional<APInt> apInt =
         buildAttributeAPInt(eltTy, isNegative, token.getSpelling());
     if (!apInt)
       return p.emitError(tokenLoc, "integer constant out of range for type");
@@ -656,7 +656,7 @@ TensorLiteralParser::getFloatAttrElements(SMLoc loc, FloatType eltTy,
 
     // Handle hexadecimal float literals.
     if (token.is(Token::integer) && token.getSpelling().startswith("0x")) {
-      Optional<APFloat> result;
+      std::optional<APFloat> result;
       if (failed(p.parseFloatFromIntegerLiteral(result, token, isNegative,
                                                 eltTy.getFloatSemantics(),
                                                 eltTy.getWidth())))
@@ -880,7 +880,7 @@ ParseResult DenseArrayElementParser::parseIntegerElement(Parser &p) {
   bool isNegative = p.consumeIf(Token::minus);
 
   // Parse an integer literal as an APInt.
-  Optional<APInt> value;
+  std::optional<APInt> value;
   StringRef spelling = p.getToken().getSpelling();
   if (p.getToken().isAny(Token::kw_true, Token::kw_false)) {
     if (!type.isInteger(1))
@@ -903,7 +903,7 @@ ParseResult DenseArrayElementParser::parseFloatElement(Parser &p) {
   bool isNegative = p.consumeIf(Token::minus);
 
   Token token = p.getToken();
-  Optional<APFloat> result;
+  std::optional<APFloat> result;
   auto floatType = type.cast<FloatType>();
   if (p.consumeIf(Token::integer)) {
     // Parse an integer literal as a float.
@@ -913,7 +913,7 @@ ParseResult DenseArrayElementParser::parseFloatElement(Parser &p) {
       return failure();
   } else if (p.consumeIf(Token::floatliteral)) {
     // Parse a floating point literal.
-    Optional<double> val = token.getFloatingPointValue();
+    std::optional<double> val = token.getFloatingPointValue();
     if (!val)
       return failure();
     result = APFloat(isNegative ? -*val : *val);
@@ -1150,7 +1150,7 @@ Attribute Parser::parseStridedLayoutAttr() {
   // Parses either an integer token or a question mark token. Reports an error
   // and returns std::nullopt if the current token is neither. The integer token
   // must fit into int64_t limits.
-  auto parseStrideOrOffset = [&]() -> Optional<int64_t> {
+  auto parseStrideOrOffset = [&]() -> std::optional<int64_t> {
     if (consumeIf(Token::question))
       return ShapedType::kDynamic;
 
@@ -1163,7 +1163,7 @@ Attribute Parser::parseStridedLayoutAttr() {
     bool negative = consumeIf(Token::minus);
 
     if (getToken().is(Token::integer)) {
-      Optional<uint64_t> value = getToken().getUInt64IntegerValue();
+      std::optional<uint64_t> value = getToken().getUInt64IntegerValue();
       if (!value ||
           *value > static_cast<uint64_t>(std::numeric_limits<int64_t>::max()))
         return emitWrongTokenError();
@@ -1182,7 +1182,7 @@ Attribute Parser::parseStridedLayoutAttr() {
   SmallVector<int64_t> strides;
   if (!getToken().is(Token::r_square)) {
     do {
-      Optional<int64_t> stride = parseStrideOrOffset();
+      std::optional<int64_t> stride = parseStrideOrOffset();
       if (!stride)
         return nullptr;
       strides.push_back(*stride);
@@ -1205,7 +1205,7 @@ Attribute Parser::parseStridedLayoutAttr() {
       failed(parseToken(Token::colon, "expected ':' after 'offset'")))
     return nullptr;
 
-  Optional<int64_t> offset = parseStrideOrOffset();
+  std::optional<int64_t> offset = parseStrideOrOffset();
   if (!offset || failed(parseToken(Token::greater, "expected '>'")))
     return nullptr;
 

diff  --git a/mlir/lib/AsmParser/Parser.cpp b/mlir/lib/AsmParser/Parser.cpp
index aad6b450ec038..c56befe7b5e28 100644
--- a/mlir/lib/AsmParser/Parser.cpp
+++ b/mlir/lib/AsmParser/Parser.cpp
@@ -276,7 +276,7 @@ OptionalParseResult Parser::parseOptionalInteger(APInt &result) {
 
 /// Parse a floating point value from an integer literal token.
 ParseResult Parser::parseFloatFromIntegerLiteral(
-    Optional<APFloat> &result, const Token &tok, bool isNegative,
+    std::optional<APFloat> &result, const Token &tok, bool isNegative,
     const llvm::fltSemantics &semantics, size_t typeSizeInBits) {
   SMLoc loc = tok.getLoc();
   StringRef spelling = tok.getSpelling();
@@ -292,7 +292,7 @@ ParseResult Parser::parseFloatFromIntegerLiteral(
                           "leading minus");
   }
 
-  Optional<uint64_t> value = tok.getUInt64IntegerValue();
+  std::optional<uint64_t> value = tok.getUInt64IntegerValue();
   if (!value)
     return emitError(loc, "hexadecimal float constant out of range for type");
 
@@ -534,12 +534,13 @@ class OperationParser : public Parser {
   /// skip parsing that component.
   ParseResult parseGenericOperationAfterOpName(
       OperationState &result,
-      Optional<ArrayRef<UnresolvedOperand>> parsedOperandUseInfo = std::nullopt,
-      Optional<ArrayRef<Block *>> parsedSuccessors = std::nullopt,
-      Optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions =
+      std::optional<ArrayRef<UnresolvedOperand>> parsedOperandUseInfo =
           std::nullopt,
-      Optional<ArrayRef<NamedAttribute>> parsedAttributes = std::nullopt,
-      Optional<FunctionType> parsedFnType = std::nullopt);
+      std::optional<ArrayRef<Block *>> parsedSuccessors = std::nullopt,
+      std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions =
+          std::nullopt,
+      std::optional<ArrayRef<NamedAttribute>> parsedAttributes = std::nullopt,
+      std::optional<FunctionType> parsedFnType = std::nullopt);
 
   /// Parse an operation instance that is in the generic form and insert it at
   /// the provided insertion point.
@@ -1250,11 +1251,11 @@ struct CleanupOpStateRegions {
 
 ParseResult OperationParser::parseGenericOperationAfterOpName(
     OperationState &result,
-    Optional<ArrayRef<UnresolvedOperand>> parsedOperandUseInfo,
-    Optional<ArrayRef<Block *>> parsedSuccessors,
-    Optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
-    Optional<ArrayRef<NamedAttribute>> parsedAttributes,
-    Optional<FunctionType> parsedFnType) {
+    std::optional<ArrayRef<UnresolvedOperand>> parsedOperandUseInfo,
+    std::optional<ArrayRef<Block *>> parsedSuccessors,
+    std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
+    std::optional<ArrayRef<NamedAttribute>> parsedAttributes,
+    std::optional<FunctionType> parsedFnType) {
 
   // Parse the operand list, if not explicitly provided.
   SmallVector<UnresolvedOperand, 8> opInfo;
@@ -1436,7 +1437,8 @@ class CustomOpAsmParser : public AsmParserImpl<OpAsmParser> {
     // This can happen if an attribute set during parsing is also specified in
     // the attribute dictionary in the assembly, or the attribute is set
     // multiple during parsing.
-    Optional<NamedAttribute> duplicate = opState.attributes.findDuplicate();
+    std::optional<NamedAttribute> duplicate =
+        opState.attributes.findDuplicate();
     if (duplicate)
       return emitError(getNameLoc(), "attribute '")
              << duplicate->getName().getValue()
@@ -1455,11 +1457,11 @@ class CustomOpAsmParser : public AsmParserImpl<OpAsmParser> {
 
   ParseResult parseGenericOperationAfterOpName(
       OperationState &result,
-      Optional<ArrayRef<UnresolvedOperand>> parsedUnresolvedOperands,
-      Optional<ArrayRef<Block *>> parsedSuccessors,
-      Optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
-      Optional<ArrayRef<NamedAttribute>> parsedAttributes,
-      Optional<FunctionType> parsedFnType) final {
+      std::optional<ArrayRef<UnresolvedOperand>> parsedUnresolvedOperands,
+      std::optional<ArrayRef<Block *>> parsedSuccessors,
+      std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
+      std::optional<ArrayRef<NamedAttribute>> parsedAttributes,
+      std::optional<FunctionType> parsedFnType) final {
     return parser.parseGenericOperationAfterOpName(
         result, parsedUnresolvedOperands, parsedSuccessors, parsedRegions,
         parsedAttributes, parsedFnType);
@@ -1777,7 +1779,7 @@ class CustomOpAsmParser : public AsmParserImpl<OpAsmParser> {
 
   /// Parse a loc(...) specifier if present, filling in result if so.
   ParseResult
-  parseOptionalLocationSpecifier(Optional<Location> &result) override {
+  parseOptionalLocationSpecifier(std::optional<Location> &result) override {
     // If there is a 'loc' we parse a trailing location.
     if (!parser.consumeIf(Token::kw_loc))
       return success();
@@ -1825,7 +1827,7 @@ FailureOr<OperationName> OperationParser::parseCustomOperationName() {
   consumeToken();
 
   // Check to see if this operation name is already registered.
-  Optional<RegisteredOperationName> opInfo =
+  std::optional<RegisteredOperationName> opInfo =
       RegisteredOperationName::lookup(opName, getContext());
   if (opInfo)
     return *opInfo;
@@ -2395,7 +2397,7 @@ class ParsedResourceEntry : public AsmParsedResourceEntry {
     // Blob data within then textual format is represented as a hex string.
     // TODO: We could avoid an additional alloc+copy here if we pre-allocated
     // the buffer to use during hex processing.
-    Optional<std::string> blobData =
+    std::optional<std::string> blobData =
         value.is(Token::string) ? value.getHexStringValue() : std::nullopt;
     if (!blobData)
       return p.emitError(value.getLoc(),

diff  --git a/mlir/lib/AsmParser/Parser.h b/mlir/lib/AsmParser/Parser.h
index e5cbd8bbf86f5..c5e32975bb399 100644
--- a/mlir/lib/AsmParser/Parser.h
+++ b/mlir/lib/AsmParser/Parser.h
@@ -140,7 +140,7 @@ class Parser {
   OptionalParseResult parseOptionalInteger(APInt &result);
 
   /// Parse a floating point value from an integer literal token.
-  ParseResult parseFloatFromIntegerLiteral(Optional<APFloat> &result,
+  ParseResult parseFloatFromIntegerLiteral(std::optional<APFloat> &result,
                                            const Token &tok, bool isNegative,
                                            const llvm::fltSemantics &semantics,
                                            size_t typeSizeInBits);

diff  --git a/mlir/lib/AsmParser/Token.cpp b/mlir/lib/AsmParser/Token.cpp
index dd392b4121a43..2e36bfb029f15 100644
--- a/mlir/lib/AsmParser/Token.cpp
+++ b/mlir/lib/AsmParser/Token.cpp
@@ -26,7 +26,7 @@ SMRange Token::getLocRange() const { return SMRange(getLoc(), getEndLoc()); }
 
 /// For an integer token, return its value as an unsigned.  If it doesn't fit,
 /// return std::nullopt.
-Optional<unsigned> Token::getUnsignedIntegerValue() const {
+std::optional<unsigned> Token::getUnsignedIntegerValue() const {
   bool isHex = spelling.size() > 1 && spelling[1] == 'x';
 
   unsigned result = 0;
@@ -37,7 +37,7 @@ Optional<unsigned> Token::getUnsignedIntegerValue() const {
 
 /// For an integer token, return its value as a uint64_t.  If it doesn't fit,
 /// return std::nullopt.
-Optional<uint64_t> Token::getUInt64IntegerValue(StringRef spelling) {
+std::optional<uint64_t> Token::getUInt64IntegerValue(StringRef spelling) {
   bool isHex = spelling.size() > 1 && spelling[1] == 'x';
 
   uint64_t result = 0;
@@ -48,7 +48,7 @@ Optional<uint64_t> Token::getUInt64IntegerValue(StringRef spelling) {
 
 /// For a floatliteral, return its value as a double. Return std::nullopt if the
 /// value underflows or overflows.
-Optional<double> Token::getFloatingPointValue() const {
+std::optional<double> Token::getFloatingPointValue() const {
   double result = 0;
   if (spelling.getAsDouble(result))
     return std::nullopt;
@@ -56,7 +56,7 @@ Optional<double> Token::getFloatingPointValue() const {
 }
 
 /// For an inttype token, return its bitwidth.
-Optional<unsigned> Token::getIntTypeBitwidth() const {
+std::optional<unsigned> Token::getIntTypeBitwidth() const {
   assert(getKind() == inttype);
   unsigned bitwidthStart = (spelling[0] == 'i' ? 1 : 2);
   unsigned result = 0;
@@ -65,7 +65,7 @@ Optional<unsigned> Token::getIntTypeBitwidth() const {
   return result;
 }
 
-Optional<bool> Token::getIntTypeSignedness() const {
+std::optional<bool> Token::getIntTypeSignedness() const {
   assert(getKind() == inttype);
   if (spelling[0] == 'i')
     return std::nullopt;
@@ -127,7 +127,7 @@ std::string Token::getStringValue() const {
 
 /// Given a token containing a hex string literal, return its value or
 /// std::nullopt if the token does not contain a valid hex string.
-Optional<std::string> Token::getHexStringValue() const {
+std::optional<std::string> Token::getHexStringValue() const {
   assert(getKind() == string);
 
   // Get the internal string data, without the quotes.
@@ -158,7 +158,7 @@ std::string Token::getSymbolReference() const {
 /// Given a hash_identifier token like #123, try to parse the number out of
 /// the identifier, returning std::nullopt if it is a named identifier like #x
 /// or if the integer doesn't fit.
-Optional<unsigned> Token::getHashIdentifierNumber() const {
+std::optional<unsigned> Token::getHashIdentifierNumber() const {
   assert(getKind() == hash_identifier);
   unsigned result = 0;
   if (spelling.drop_front().getAsInteger(10, result))

diff  --git a/mlir/lib/AsmParser/Token.h b/mlir/lib/AsmParser/Token.h
index 3f4db2ea927e7..4640e03883615 100644
--- a/mlir/lib/AsmParser/Token.h
+++ b/mlir/lib/AsmParser/Token.h
@@ -76,31 +76,31 @@ class Token {
 
   /// For an integer token, return its value as an unsigned.  If it doesn't fit,
   /// return std::nullopt.
-  Optional<unsigned> getUnsignedIntegerValue() const;
+  std::optional<unsigned> getUnsignedIntegerValue() const;
 
   /// For an integer token, return its value as an uint64_t.  If it doesn't fit,
   /// return std::nullopt.
-  static Optional<uint64_t> getUInt64IntegerValue(StringRef spelling);
-  Optional<uint64_t> getUInt64IntegerValue() const {
+  static std::optional<uint64_t> getUInt64IntegerValue(StringRef spelling);
+  std::optional<uint64_t> getUInt64IntegerValue() const {
     return getUInt64IntegerValue(getSpelling());
   }
 
   /// For a floatliteral token, return its value as a double. Returns
   /// std::nullopt in the case of underflow or overflow.
-  Optional<double> getFloatingPointValue() const;
+  std::optional<double> getFloatingPointValue() const;
 
   /// For an inttype token, return its bitwidth.
-  Optional<unsigned> getIntTypeBitwidth() const;
+  std::optional<unsigned> getIntTypeBitwidth() const;
 
   /// For an inttype token, return its signedness semantics: std::nullopt means
   /// no signedness semantics; true means signed integer type; false means
   /// unsigned integer type.
-  Optional<bool> getIntTypeSignedness() const;
+  std::optional<bool> getIntTypeSignedness() const;
 
   /// Given a hash_identifier token like #123, try to parse the number out of
   /// the identifier, returning std::nullopt if it is a named identifier like #x
   /// or if the integer doesn't fit.
-  Optional<unsigned> getHashIdentifierNumber() const;
+  std::optional<unsigned> getHashIdentifierNumber() const;
 
   /// Given a token containing a string literal, return its value, including
   /// removing the quote characters and unescaping the contents of the string.
@@ -110,7 +110,7 @@ class Token {
   /// std::nullopt if the token does not contain a valid hex string. A hex
   /// string literal is a string starting with `0x` and only containing hex
   /// digits.
-  Optional<std::string> getHexStringValue() const;
+  std::optional<std::string> getHexStringValue() const;
 
   /// Given a token containing a symbol reference, return the unescaped string
   /// value.

diff  --git a/mlir/lib/AsmParser/TypeParser.cpp b/mlir/lib/AsmParser/TypeParser.cpp
index cf20ae8f65f5e..fab7244d1b72f 100644
--- a/mlir/lib/AsmParser/TypeParser.cpp
+++ b/mlir/lib/AsmParser/TypeParser.cpp
@@ -281,7 +281,7 @@ Type Parser::parseNonFunctionType() {
     }
 
     IntegerType::SignednessSemantics signSemantics = IntegerType::Signless;
-    if (Optional<bool> signedness = getToken().getIntTypeSignedness())
+    if (std::optional<bool> signedness = getToken().getIntTypeSignedness())
       signSemantics = *signedness ? IntegerType::Signed : IntegerType::Unsigned;
 
     consumeToken(Token::inttype);
@@ -561,7 +561,7 @@ ParseResult Parser::parseIntegerInDimensionList(int64_t &value) {
     consumeToken();
   } else {
     // Make sure this integer value is in bound and valid.
-    Optional<uint64_t> dimension = getToken().getUInt64IntegerValue();
+    std::optional<uint64_t> dimension = getToken().getUInt64IntegerValue();
     if (!dimension ||
         *dimension > (uint64_t)std::numeric_limits<int64_t>::max())
       return emitError("invalid dimension");

diff  --git a/mlir/lib/Bindings/Python/DialectSparseTensor.cpp b/mlir/lib/Bindings/Python/DialectSparseTensor.cpp
index 6885ef9cf2ceb..da44141e28a2a 100644
--- a/mlir/lib/Bindings/Python/DialectSparseTensor.cpp
+++ b/mlir/lib/Bindings/Python/DialectSparseTensor.cpp
@@ -34,8 +34,8 @@ static void populateDialectSparseTensorSubmodule(const py::module &m) {
           "get",
           [](py::object cls,
              std::vector<MlirSparseTensorDimLevelType> dimLevelTypes,
-             llvm::Optional<MlirAffineMap> dimOrdering,
-             llvm::Optional<MlirAffineMap> higherOrdering, int pointerBitWidth,
+             std::optional<MlirAffineMap> dimOrdering,
+             std::optional<MlirAffineMap> higherOrdering, int pointerBitWidth,
              int indexBitWidth, MlirContext context) {
             return cls(mlirSparseTensorEncodingAttrGet(
                 context, dimLevelTypes.size(), dimLevelTypes.data(),
@@ -60,7 +60,7 @@ static void populateDialectSparseTensorSubmodule(const py::module &m) {
           })
       .def_property_readonly(
           "dim_ordering",
-          [](MlirAttribute self) -> llvm::Optional<MlirAffineMap> {
+          [](MlirAttribute self) -> std::optional<MlirAffineMap> {
             MlirAffineMap ret =
                 mlirSparseTensorEncodingAttrGetDimOrdering(self);
             if (mlirAffineMapIsNull(ret))
@@ -69,7 +69,7 @@ static void populateDialectSparseTensorSubmodule(const py::module &m) {
           })
       .def_property_readonly(
           "higher_ordering",
-          [](MlirAttribute self) -> llvm::Optional<MlirAffineMap> {
+          [](MlirAttribute self) -> std::optional<MlirAffineMap> {
             MlirAffineMap ret =
                 mlirSparseTensorEncodingAttrGetHigherOrdering(self);
             if (mlirAffineMapIsNull(ret))

diff  --git a/mlir/lib/Bindings/Python/Globals.h b/mlir/lib/Bindings/Python/Globals.h
index fbe51a753d36d..f3370a4f59a0a 100644
--- a/mlir/lib/Bindings/Python/Globals.h
+++ b/mlir/lib/Bindings/Python/Globals.h
@@ -84,12 +84,12 @@ class PyGlobals {
 
   /// Looks up a registered dialect class by namespace. Note that this may
   /// trigger loading of the defining module and can arbitrarily re-enter.
-  llvm::Optional<pybind11::object>
+  std::optional<pybind11::object>
   lookupDialectClass(const std::string &dialectNamespace);
 
   /// Looks up a registered raw OpView class by operation name. Note that this
   /// may trigger a load of the dialect, which can arbitrarily re-enter.
-  llvm::Optional<pybind11::object>
+  std::optional<pybind11::object>
   lookupRawOpViewClass(llvm::StringRef operationName);
 
 private:

diff  --git a/mlir/lib/Bindings/Python/IRAttributes.cpp b/mlir/lib/Bindings/Python/IRAttributes.cpp
index c598aee7b32f9..a29f16397bd8d 100644
--- a/mlir/lib/Bindings/Python/IRAttributes.cpp
+++ b/mlir/lib/Bindings/Python/IRAttributes.cpp
@@ -546,8 +546,9 @@ class PyDenseElementsAttribute
   using PyConcreteAttribute::PyConcreteAttribute;
 
   static PyDenseElementsAttribute
-  getFromBuffer(py::buffer array, bool signless, Optional<PyType> explicitType,
-                Optional<std::vector<int64_t>> explicitShape,
+  getFromBuffer(py::buffer array, bool signless,
+                std::optional<PyType> explicitType,
+                std::optional<std::vector<int64_t>> explicitShape,
                 DefaultingPyMlirContext contextWrapper) {
     // Request a contiguous view. In exotic cases, this will cause a copy.
     int flags = PyBUF_C_CONTIGUOUS | PyBUF_FORMAT;
@@ -573,7 +574,7 @@ class PyDenseElementsAttribute
     // Notably, this excludes, bool (which needs to be bit-packed) and
     // other exotics which do not have a direct representation in the buffer
     // protocol (i.e. complex, etc).
-    Optional<MlirType> bulkLoadElementType;
+    std::optional<MlirType> bulkLoadElementType;
     if (explicitType) {
       bulkLoadElementType = *explicitType;
     } else if (arrayInfo.format == "f") {

diff  --git a/mlir/lib/Bindings/Python/IRCore.cpp b/mlir/lib/Bindings/Python/IRCore.cpp
index 7a9e8eb3a6c54..eb7d18f9842c3 100644
--- a/mlir/lib/Bindings/Python/IRCore.cpp
+++ b/mlir/lib/Bindings/Python/IRCore.cpp
@@ -1066,7 +1066,7 @@ void PyOperation::checkValid() const {
 }
 
 void PyOperationBase::print(py::object fileObject, bool binary,
-                            llvm::Optional<int64_t> largeElementsLimit,
+                            std::optional<int64_t> largeElementsLimit,
                             bool enableDebugInfo, bool prettyDebugInfo,
                             bool printGenericOpForm, bool useLocalScope,
                             bool assumeVerified) {
@@ -1112,7 +1112,7 @@ void PyOperationBase::writeBytecode(const py::object &fileObject) {
 }
 
 py::object PyOperationBase::getAsm(bool binary,
-                                   llvm::Optional<int64_t> largeElementsLimit,
+                                   std::optional<int64_t> largeElementsLimit,
                                    bool enableDebugInfo, bool prettyDebugInfo,
                                    bool printGenericOpForm, bool useLocalScope,
                                    bool assumeVerified) {
@@ -1151,7 +1151,7 @@ void PyOperationBase::moveBefore(PyOperationBase &other) {
   operation.parentKeepAlive = otherOp.parentKeepAlive;
 }
 
-llvm::Optional<PyOperationRef> PyOperation::getParentOperation() {
+std::optional<PyOperationRef> PyOperation::getParentOperation() {
   checkValid();
   if (!isAttached())
     throw SetPyError(PyExc_ValueError, "Detached operations have no parent");
@@ -1163,7 +1163,7 @@ llvm::Optional<PyOperationRef> PyOperation::getParentOperation() {
 
 PyBlock PyOperation::getBlock() {
   checkValid();
-  llvm::Optional<PyOperationRef> parentOperation = getParentOperation();
+  std::optional<PyOperationRef> parentOperation = getParentOperation();
   MlirBlock block = mlirOperationGetBlock(get());
   assert(!mlirBlockIsNull(block) && "Attached operation has null parent");
   assert(parentOperation && "Operation has no parent");
@@ -1199,12 +1199,13 @@ static void maybeInsertOperation(PyOperationRef &op,
   }
 }
 
-py::object PyOperation::create(
-    const std::string &name, llvm::Optional<std::vector<PyType *>> results,
-    llvm::Optional<std::vector<PyValue *>> operands,
-    llvm::Optional<py::dict> attributes,
-    llvm::Optional<std::vector<PyBlock *>> successors, int regions,
-    DefaultingPyLocation location, const py::object &maybeIp) {
+py::object PyOperation::create(const std::string &name,
+                               std::optional<std::vector<PyType *>> results,
+                               std::optional<std::vector<PyValue *>> operands,
+                               std::optional<py::dict> attributes,
+                               std::optional<std::vector<PyBlock *>> successors,
+                               int regions, DefaultingPyLocation location,
+                               const py::object &maybeIp) {
   llvm::SmallVector<MlirValue, 4> mlirOperands;
   llvm::SmallVector<MlirType, 4> mlirResults;
   llvm::SmallVector<MlirBlock, 4> mlirSuccessors;
@@ -1357,12 +1358,13 @@ void PyOperation::erase() {
 // PyOpView
 //------------------------------------------------------------------------------
 
-py::object PyOpView::buildGeneric(
-    const py::object &cls, py::list resultTypeList, py::list operandList,
-    llvm::Optional<py::dict> attributes,
-    llvm::Optional<std::vector<PyBlock *>> successors,
-    llvm::Optional<int> regions, DefaultingPyLocation location,
-    const py::object &maybeIp) {
+py::object
+PyOpView::buildGeneric(const py::object &cls, py::list resultTypeList,
+                       py::list operandList, std::optional<py::dict> attributes,
+                       std::optional<std::vector<PyBlock *>> successors,
+                       std::optional<int> regions,
+                       DefaultingPyLocation location,
+                       const py::object &maybeIp) {
   PyMlirContextRef context = location->getContext();
   // Class level operation construction metadata.
   std::string name = py::cast<std::string>(cls.attr("OPERATION_NAME"));
@@ -2518,7 +2520,7 @@ void mlir::python::populateIRCore(py::module &m) {
       .def_static(
           "fused",
           [](const std::vector<PyLocation> &pyLocations,
-             llvm::Optional<PyAttribute> metadata,
+             std::optional<PyAttribute> metadata,
              DefaultingPyMlirContext context) {
             llvm::SmallVector<MlirLocation, 4> locations;
             locations.reserve(pyLocations.size());
@@ -2533,7 +2535,7 @@ void mlir::python::populateIRCore(py::module &m) {
           py::arg("context") = py::none(), kContextGetFusedLocationDocstring)
       .def_static(
           "name",
-          [](std::string name, llvm::Optional<PyLocation> childLoc,
+          [](std::string name, std::optional<PyLocation> childLoc,
              DefaultingPyMlirContext context) {
             return PyLocation(
                 context->getRef(),

diff  --git a/mlir/lib/Bindings/Python/IRInterfaces.cpp b/mlir/lib/Bindings/Python/IRInterfaces.cpp
index f3e4e73c1a41c..fed8a5066fe66 100644
--- a/mlir/lib/Bindings/Python/IRInterfaces.cpp
+++ b/mlir/lib/Bindings/Python/IRInterfaces.cpp
@@ -185,9 +185,9 @@ class PyInferTypeOpInterface
   /// Given the arguments required to build an operation, attempts to infer its
   /// return types. Throws value_error on faliure.
   std::vector<PyType>
-  inferReturnTypes(llvm::Optional<std::vector<PyValue>> operands,
-                   llvm::Optional<PyAttribute> attributes,
-                   llvm::Optional<std::vector<PyRegion>> regions,
+  inferReturnTypes(std::optional<std::vector<PyValue>> operands,
+                   std::optional<PyAttribute> attributes,
+                   std::optional<std::vector<PyRegion>> regions,
                    DefaultingPyMlirContext context,
                    DefaultingPyLocation location) {
     llvm::SmallVector<MlirValue> mlirOperands;

diff  --git a/mlir/lib/Bindings/Python/IRModule.cpp b/mlir/lib/Bindings/Python/IRModule.cpp
index 3614360fc08a2..e3b8ef1893940 100644
--- a/mlir/lib/Bindings/Python/IRModule.cpp
+++ b/mlir/lib/Bindings/Python/IRModule.cpp
@@ -112,7 +112,7 @@ PyGlobals::lookupAttributeBuilder(const std::string &attributeKind) {
   return std::nullopt;
 }
 
-llvm::Optional<py::object>
+std::optional<py::object>
 PyGlobals::lookupDialectClass(const std::string &dialectNamespace) {
   loadDialectModule(dialectNamespace);
   // Fast match against the class map first (common case).
@@ -129,7 +129,7 @@ PyGlobals::lookupDialectClass(const std::string &dialectNamespace) {
   return std::nullopt;
 }
 
-llvm::Optional<pybind11::object>
+std::optional<pybind11::object>
 PyGlobals::lookupRawOpViewClass(llvm::StringRef operationName) {
   {
     auto foundIt = rawOpViewClassMapCache.find(operationName);

diff  --git a/mlir/lib/Bindings/Python/IRModule.h b/mlir/lib/Bindings/Python/IRModule.h
index b198b4b652fd6..d26fa2077a4d2 100644
--- a/mlir/lib/Bindings/Python/IRModule.h
+++ b/mlir/lib/Bindings/Python/IRModule.h
@@ -347,7 +347,7 @@ class PyDiagnosticHandler {
 private:
   MlirContext context;
   pybind11::object callback;
-  llvm::Optional<MlirDiagnosticHandlerID> registeredID;
+  std::optional<MlirDiagnosticHandlerID> registeredID;
   bool hadError = false;
   friend class PyMlirContext;
 };
@@ -504,11 +504,11 @@ class PyOperationBase {
   virtual ~PyOperationBase() = default;
   /// Implements the bound 'print' method and helps with others.
   void print(pybind11::object fileObject, bool binary,
-             llvm::Optional<int64_t> largeElementsLimit, bool enableDebugInfo,
+             std::optional<int64_t> largeElementsLimit, bool enableDebugInfo,
              bool prettyDebugInfo, bool printGenericOpForm, bool useLocalScope,
              bool assumeVerified);
   pybind11::object getAsm(bool binary,
-                          llvm::Optional<int64_t> largeElementsLimit,
+                          std::optional<int64_t> largeElementsLimit,
                           bool enableDebugInfo, bool prettyDebugInfo,
                           bool printGenericOpForm, bool useLocalScope,
                           bool assumeVerified);
@@ -586,7 +586,7 @@ class PyOperation : public PyOperationBase, public BaseContextObject {
 
   /// Gets the parent operation or raises an exception if the operation has
   /// no parent.
-  llvm::Optional<PyOperationRef> getParentOperation();
+  std::optional<PyOperationRef> getParentOperation();
 
   /// Gets a capsule wrapping the void* within the MlirOperation.
   pybind11::object getCapsule();
@@ -598,10 +598,10 @@ class PyOperation : public PyOperationBase, public BaseContextObject {
 
   /// Creates an operation. See corresponding python docstring.
   static pybind11::object
-  create(const std::string &name, llvm::Optional<std::vector<PyType *>> results,
-         llvm::Optional<std::vector<PyValue *>> operands,
-         llvm::Optional<pybind11::dict> attributes,
-         llvm::Optional<std::vector<PyBlock *>> successors, int regions,
+  create(const std::string &name, std::optional<std::vector<PyType *>> results,
+         std::optional<std::vector<PyValue *>> operands,
+         std::optional<pybind11::dict> attributes,
+         std::optional<std::vector<PyBlock *>> successors, int regions,
          DefaultingPyLocation location, const pybind11::object &ip);
 
   /// Creates an OpView suitable for this operation.
@@ -656,9 +656,9 @@ class PyOpView : public PyOperationBase {
   static pybind11::object
   buildGeneric(const pybind11::object &cls, pybind11::list resultTypeList,
                pybind11::list operandList,
-               llvm::Optional<pybind11::dict> attributes,
-               llvm::Optional<std::vector<PyBlock *>> successors,
-               llvm::Optional<int> regions, DefaultingPyLocation location,
+               std::optional<pybind11::dict> attributes,
+               std::optional<std::vector<PyBlock *>> successors,
+               std::optional<int> regions, DefaultingPyLocation location,
                const pybind11::object &maybeIp);
 
 private:
@@ -738,10 +738,10 @@ class PyInsertionPoint {
 private:
   // Trampoline constructor that avoids null initializing members while
   // looking up parents.
-  PyInsertionPoint(PyBlock block, llvm::Optional<PyOperationRef> refOperation)
+  PyInsertionPoint(PyBlock block, std::optional<PyOperationRef> refOperation)
       : refOperation(std::move(refOperation)), block(std::move(block)) {}
 
-  llvm::Optional<PyOperationRef> refOperation;
+  std::optional<PyOperationRef> refOperation;
   PyBlock block;
 };
 /// Wrapper around the generic MlirType.

diff  --git a/mlir/lib/Bindings/Python/IRTypes.cpp b/mlir/lib/Bindings/Python/IRTypes.cpp
index ad46e52b31624..3cc226d7aa2c4 100644
--- a/mlir/lib/Bindings/Python/IRTypes.cpp
+++ b/mlir/lib/Bindings/Python/IRTypes.cpp
@@ -401,8 +401,7 @@ class PyRankedTensorType
     c.def_static(
         "get",
         [](std::vector<int64_t> shape, PyType &elementType,
-           llvm::Optional<PyAttribute> &encodingAttr,
-           DefaultingPyLocation loc) {
+           std::optional<PyAttribute> &encodingAttr, DefaultingPyLocation loc) {
           MlirType t = mlirRankedTensorTypeGetChecked(
               loc, shape.size(), shape.data(), elementType,
               encodingAttr ? encodingAttr->get() : mlirAttributeGetNull());
@@ -423,8 +422,7 @@ class PyRankedTensorType
         py::arg("encoding") = py::none(), py::arg("loc") = py::none(),
         "Create a ranked tensor type");
     c.def_property_readonly(
-        "encoding",
-        [](PyRankedTensorType &self) -> llvm::Optional<PyAttribute> {
+        "encoding", [](PyRankedTensorType &self) -> std::optional<PyAttribute> {
           MlirAttribute encoding = mlirRankedTensorTypeGetEncoding(self.get());
           if (mlirAttributeIsNull(encoding))
             return std::nullopt;

diff  --git a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
index 5860fd42a2bb8..8dded643a45cd 100644
--- a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
+++ b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
@@ -1121,8 +1121,8 @@ class BytecodeReader {
   // Resource Section
 
   LogicalResult
-  parseResourceSection(Optional<ArrayRef<uint8_t>> resourceData,
-                       Optional<ArrayRef<uint8_t>> resourceOffsetData);
+  parseResourceSection(std::optional<ArrayRef<uint8_t>> resourceData,
+                       std::optional<ArrayRef<uint8_t>> resourceOffsetData);
 
   //===--------------------------------------------------------------------===//
   // IR Section
@@ -1269,7 +1269,8 @@ LogicalResult BytecodeReader::read(llvm::MemoryBufferRef buffer, Block *block) {
   });
 
   // Parse the raw data for each of the top-level sections of the bytecode.
-  Optional<ArrayRef<uint8_t>> sectionDatas[bytecode::Section::kNumSections];
+  std::optional<ArrayRef<uint8_t>>
+      sectionDatas[bytecode::Section::kNumSections];
   while (!reader.empty()) {
     // Read the next section from the bytecode.
     bytecode::Section::ID sectionID;
@@ -1389,8 +1390,8 @@ FailureOr<OperationName> BytecodeReader::parseOpName(EncodingReader &reader) {
 // Resource Section
 
 LogicalResult BytecodeReader::parseResourceSection(
-    Optional<ArrayRef<uint8_t>> resourceData,
-    Optional<ArrayRef<uint8_t>> resourceOffsetData) {
+    std::optional<ArrayRef<uint8_t>> resourceData,
+    std::optional<ArrayRef<uint8_t>> resourceOffsetData) {
   // Ensure both sections are either present or not.
   if (resourceData.has_value() != resourceOffsetData.has_value()) {
     if (resourceOffsetData)

diff  --git a/mlir/lib/CAPI/IR/IR.cpp b/mlir/lib/CAPI/IR/IR.cpp
index 13e8d2034ac74..68563a69c9f94 100644
--- a/mlir/lib/CAPI/IR/IR.cpp
+++ b/mlir/lib/CAPI/IR/IR.cpp
@@ -289,7 +289,7 @@ void mlirOperationStateEnableResultTypeInference(MlirOperationState *state) {
 
 static LogicalResult inferOperationTypes(OperationState &state) {
   MLIRContext *context = state.getContext();
-  Optional<RegisteredOperationName> info = state.name.getRegisteredInfo();
+  std::optional<RegisteredOperationName> info = state.name.getRegisteredInfo();
   if (!info) {
     emitError(state.location)
         << "type inference was requested for the operation " << state.name

diff  --git a/mlir/lib/CAPI/IR/Pass.cpp b/mlir/lib/CAPI/IR/Pass.cpp
index 9ae425fe50adf..b921154111c22 100644
--- a/mlir/lib/CAPI/IR/Pass.cpp
+++ b/mlir/lib/CAPI/IR/Pass.cpp
@@ -112,7 +112,7 @@ namespace mlir {
 class ExternalPass : public Pass {
 public:
   ExternalPass(TypeID passID, StringRef name, StringRef argument,
-               StringRef description, Optional<StringRef> opName,
+               StringRef description, std::optional<StringRef> opName,
                ArrayRef<MlirDialectHandle> dependentDialects,
                MlirExternalPassCallbacks callbacks, void *userData)
       : Pass(passID, opName), id(passID), name(name), argument(argument),
@@ -143,7 +143,7 @@ class ExternalPass : public Pass {
   }
 
   bool canScheduleOn(RegisteredOperationName opName) const override {
-    if (Optional<StringRef> specifiedOpName = getOpName())
+    if (std::optional<StringRef> specifiedOpName = getOpName())
       return opName.getStringRef() == specifiedOpName;
     return true;
   }
@@ -179,7 +179,8 @@ MlirPass mlirCreateExternalPass(MlirTypeID passID, MlirStringRef name,
                                 void *userData) {
   return wrap(static_cast<mlir::Pass *>(new mlir::ExternalPass(
       unwrap(passID), unwrap(name), unwrap(argument), unwrap(description),
-      opName.length > 0 ? Optional<StringRef>(unwrap(opName)) : std::nullopt,
+      opName.length > 0 ? std::optional<StringRef>(unwrap(opName))
+                        : std::nullopt,
       {dependentDialects, static_cast<size_t>(nDependentDialects)}, callbacks,
       userData)));
 }

diff  --git a/mlir/lib/CAPI/Interfaces/Interfaces.cpp b/mlir/lib/CAPI/Interfaces/Interfaces.cpp
index 61f1c9542884f..5adccbdaf06b5 100644
--- a/mlir/lib/CAPI/Interfaces/Interfaces.cpp
+++ b/mlir/lib/CAPI/Interfaces/Interfaces.cpp
@@ -19,7 +19,7 @@ using namespace mlir;
 
 bool mlirOperationImplementsInterface(MlirOperation operation,
                                       MlirTypeID interfaceTypeID) {
-  Optional<RegisteredOperationName> info =
+  std::optional<RegisteredOperationName> info =
       unwrap(operation)->getRegisteredInfo();
   return info && info->hasInterface(unwrap(interfaceTypeID));
 }
@@ -27,7 +27,7 @@ bool mlirOperationImplementsInterface(MlirOperation operation,
 bool mlirOperationImplementsInterfaceStatic(MlirStringRef operationName,
                                             MlirContext context,
                                             MlirTypeID interfaceTypeID) {
-  Optional<RegisteredOperationName> info = RegisteredOperationName::lookup(
+  std::optional<RegisteredOperationName> info = RegisteredOperationName::lookup(
       StringRef(operationName.data, operationName.length), unwrap(context));
   return info && info->hasInterface(unwrap(interfaceTypeID));
 }
@@ -42,7 +42,7 @@ MlirLogicalResult mlirInferTypeOpInterfaceInferReturnTypes(
     intptr_t nRegions, MlirRegion *regions, MlirTypesCallback callback,
     void *userData) {
   StringRef name(opName.data, opName.length);
-  Optional<RegisteredOperationName> info =
+  std::optional<RegisteredOperationName> info =
       RegisteredOperationName::lookup(name, unwrap(context));
   if (!info)
     return mlirLogicalResultFailure();

diff  --git a/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp b/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp
index d924231e4f501..c1f720ff5d00b 100644
--- a/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp
+++ b/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp
@@ -312,7 +312,8 @@ static Value mfmaConcatIfNeeded(ConversionPatternRewriter &rewriter,
 /// Return the `rocdl` intrinsic corresponding to a MFMA operation `mfma`
 /// if one exists. This includes checking to ensure the intrinsic is supported
 /// on the architecture you are compiling for.
-static Optional<StringRef> mfmaOpToIntrinsic(MFMAOp mfma, Chipset chipset) {
+static std::optional<StringRef> mfmaOpToIntrinsic(MFMAOp mfma,
+                                                  Chipset chipset) {
   uint32_t m = mfma.getM(), n = mfma.getN(), k = mfma.getK(),
            b = mfma.getBlocks();
   Type sourceElem = mfma.getSourceA().getType();
@@ -428,7 +429,7 @@ struct MFMAOpLowering : public ConvertOpToLLVMPattern<MFMAOp> {
       getBlgpField |=
           op.getNegateA() | (op.getNegateB() << 1) | (op.getNegateC() << 2);
     }
-    Optional<StringRef> maybeIntrinsic = mfmaOpToIntrinsic(op, chipset);
+    std::optional<StringRef> maybeIntrinsic = mfmaOpToIntrinsic(op, chipset);
     if (!maybeIntrinsic.has_value())
       return op.emitOpError("no intrinsic matching MFMA size on given chipset");
     OperationState loweredOp(loc, *maybeIntrinsic);

diff  --git a/mlir/lib/Conversion/GPUToSPIRV/GPUToSPIRV.cpp b/mlir/lib/Conversion/GPUToSPIRV/GPUToSPIRV.cpp
index 5c21708f53d10..bd20f66b2d1fa 100644
--- a/mlir/lib/Conversion/GPUToSPIRV/GPUToSPIRV.cpp
+++ b/mlir/lib/Conversion/GPUToSPIRV/GPUToSPIRV.cpp
@@ -448,10 +448,10 @@ static Value createGroupReduceOpImpl(OpBuilder &builder, Location loc,
       .getResult();
 }
 
-static llvm::Optional<Value> createGroupReduceOp(OpBuilder &builder,
-                                                 Location loc, Value arg,
-                                                 gpu::AllReduceOperation opType,
-                                                 bool isGroup, bool isUniform) {
+static std::optional<Value> createGroupReduceOp(OpBuilder &builder,
+                                                Location loc, Value arg,
+                                                gpu::AllReduceOperation opType,
+                                                bool isGroup, bool isUniform) {
   using FuncT = Value (*)(OpBuilder &, Location, Value, bool, bool);
   struct OpHandler {
     gpu::AllReduceOperation type;

diff  --git a/mlir/lib/Conversion/MathToLibm/MathToLibm.cpp b/mlir/lib/Conversion/MathToLibm/MathToLibm.cpp
index 8918e50a5d271..93b58e2ab7d1d 100644
--- a/mlir/lib/Conversion/MathToLibm/MathToLibm.cpp
+++ b/mlir/lib/Conversion/MathToLibm/MathToLibm.cpp
@@ -154,7 +154,7 @@ ScalarOpToLibmCall<Op>::matchAndRewrite(Op op,
 
 void mlir::populateMathToLibmConversionPatterns(
     RewritePatternSet &patterns, PatternBenefit benefit,
-    llvm::Optional<PatternBenefit> log1pBenefit) {
+    std::optional<PatternBenefit> log1pBenefit) {
   patterns.add<VecOpToScalarOp<math::Atan2Op>, VecOpToScalarOp<math::CbrtOp>,
                VecOpToScalarOp<math::ExpM1Op>, VecOpToScalarOp<math::TanhOp>,
                VecOpToScalarOp<math::CosOp>, VecOpToScalarOp<math::SinOp>,

diff  --git a/mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp b/mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp
index 7960b95fef581..c6ce3f11a6737 100644
--- a/mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp
+++ b/mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp
@@ -116,7 +116,7 @@ static bool isAllocationSupported(Operation *allocOp, MemRefType type) {
 /// Returns the scope to use for atomic operations use for emulating store
 /// operations of unsupported integer bitwidths, based on the memref
 /// type. Returns std::nullopt on failure.
-static Optional<spirv::Scope> getAtomicOpScope(MemRefType type) {
+static std::optional<spirv::Scope> getAtomicOpScope(MemRefType type) {
   auto sc = type.getMemorySpace().dyn_cast_or_null<spirv::StorageClassAttr>();
   switch (sc.getValue()) {
   case spirv::StorageClass::StorageBuffer:
@@ -530,7 +530,7 @@ IntStoreOpPattern::matchAndRewrite(memref::StoreOp storeOp, OpAdaptor adaptor,
   storeVal = shiftValue(loc, storeVal, offset, mask, dstBits, rewriter);
   Value adjustedPtr = adjustAccessChainForBitwidth(typeConverter, accessChainOp,
                                                    srcBits, dstBits, rewriter);
-  Optional<spirv::Scope> scope = getAtomicOpScope(memrefType);
+  std::optional<spirv::Scope> scope = getAtomicOpScope(memrefType);
   if (!scope)
     return failure();
   Value result = rewriter.create<spirv::AtomicAndOp>(

diff  --git a/mlir/lib/Conversion/SCFToGPU/SCFToGPU.cpp b/mlir/lib/Conversion/SCFToGPU/SCFToGPU.cpp
index 55729de3113a2..03cf661c8899e 100644
--- a/mlir/lib/Conversion/SCFToGPU/SCFToGPU.cpp
+++ b/mlir/lib/Conversion/SCFToGPU/SCFToGPU.cpp
@@ -153,7 +153,8 @@ namespace {
 // Helper structure that holds common state of the loop to GPU kernel
 // conversion.
 struct AffineLoopToGpuConverter {
-  Optional<AffineForOp> collectBounds(AffineForOp forOp, unsigned numLoops);
+  std::optional<AffineForOp> collectBounds(AffineForOp forOp,
+                                           unsigned numLoops);
 
   void createLaunch(AffineForOp rootForOp, AffineForOp innermostForOp,
                     unsigned numBlockDims, unsigned numThreadDims);
@@ -181,7 +182,7 @@ static bool isConstantOne(Value value) {
 // This may fail if the IR for computing loop bounds cannot be constructed, for
 // example if an affine loop uses semi-affine maps. Return the last loop to be
 // mapped on success, std::nullopt on failure.
-Optional<AffineForOp>
+std::optional<AffineForOp>
 AffineLoopToGpuConverter::collectBounds(AffineForOp forOp, unsigned numLoops) {
   OpBuilder builder(forOp.getOperation());
   dims.reserve(numLoops);

diff  --git a/mlir/lib/Conversion/VectorToSCF/VectorToSCF.cpp b/mlir/lib/Conversion/VectorToSCF/VectorToSCF.cpp
index e9b0ec515dc3f..dfaa8b35671e6 100644
--- a/mlir/lib/Conversion/VectorToSCF/VectorToSCF.cpp
+++ b/mlir/lib/Conversion/VectorToSCF/VectorToSCF.cpp
@@ -55,7 +55,7 @@ struct VectorToSCFPattern : public OpRewritePattern<OpTy> {
 /// memref should be unpacked in the next application of TransferOpConversion.
 /// A return value of std::nullopt indicates a broadcast.
 template <typename OpTy>
-static Optional<int64_t> unpackedDim(OpTy xferOp) {
+static std::optional<int64_t> unpackedDim(OpTy xferOp) {
   // TODO: support 0-d corner case.
   assert(xferOp.getTransferRank() > 0 && "unexpected 0-d transfer");
   auto map = xferOp.getPermutationMap();
@@ -159,7 +159,7 @@ static Value generateMaskCheck(OpBuilder &b, OpTy xferOp, Value iv) {
 /// `resultTypes`.
 template <typename OpTy>
 static Value generateInBoundsCheck(
-    OpBuilder &b, OpTy xferOp, Value iv, Optional<int64_t> dim,
+    OpBuilder &b, OpTy xferOp, Value iv, std::optional<int64_t> dim,
     TypeRange resultTypes,
     function_ref<Value(OpBuilder &, Location)> inBoundsCase,
     function_ref<Value(OpBuilder &, Location)> outOfBoundsCase = nullptr) {
@@ -217,7 +217,7 @@ static Value generateInBoundsCheck(
 /// a return value. Consequently, this function does not have a return value.
 template <typename OpTy>
 static void generateInBoundsCheck(
-    OpBuilder &b, OpTy xferOp, Value iv, Optional<int64_t> dim,
+    OpBuilder &b, OpTy xferOp, Value iv, std::optional<int64_t> dim,
     function_ref<void(OpBuilder &, Location)> inBoundsCase,
     function_ref<void(OpBuilder &, Location)> outOfBoundsCase = nullptr) {
   generateInBoundsCheck(
@@ -1093,7 +1093,7 @@ namespace lowering_1_d {
 /// the transfer is operating. A return value of std::nullopt indicates a
 /// broadcast.
 template <typename OpTy>
-static Optional<int64_t>
+static std::optional<int64_t>
 get1dMemrefIndices(OpBuilder &b, OpTy xferOp, Value iv,
                    SmallVector<Value, 8> &memrefIndices) {
   auto indices = xferOp.getIndices();

diff  --git a/mlir/lib/Dialect/AMDGPU/IR/AMDGPUDialect.cpp b/mlir/lib/Dialect/AMDGPU/IR/AMDGPUDialect.cpp
index c082088c58ceb..ee73672947368 100644
--- a/mlir/lib/Dialect/AMDGPU/IR/AMDGPUDialect.cpp
+++ b/mlir/lib/Dialect/AMDGPU/IR/AMDGPUDialect.cpp
@@ -68,7 +68,7 @@ LogicalResult RawBufferAtomicFaddOp::verify() {
   return verifyRawBufferOp(*this);
 }
 
-static Optional<uint32_t> getConstantUint32(Value v) {
+static std::optional<uint32_t> getConstantUint32(Value v) {
   APInt cst;
   if (!v.getType().isInteger(32))
     return std::nullopt;
@@ -90,7 +90,7 @@ static bool staticallyOutOfBounds(OpType op) {
     return false;
   int64_t result = offset + op.getIndexOffset().value_or(0);
   if (op.getSgprOffset()) {
-    Optional<uint32_t> sgprOffset = getConstantUint32(op.getSgprOffset());
+    std::optional<uint32_t> sgprOffset = getConstantUint32(op.getSgprOffset());
     if (!sgprOffset)
       return false;
     result += *sgprOffset;
@@ -101,7 +101,7 @@ static bool staticallyOutOfBounds(OpType op) {
   for (auto pair : llvm::zip(strides, op.getIndices())) {
     int64_t stride = std::get<0>(pair);
     Value idx = std::get<1>(pair);
-    Optional<uint32_t> idxVal = getConstantUint32(idx);
+    std::optional<uint32_t> idxVal = getConstantUint32(idx);
     if (!idxVal)
       return false;
     indexVal += stride * *idxVal;

diff  --git a/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp b/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp
index e9fc4e58c2112..6e730140a3b94 100644
--- a/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp
+++ b/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp
@@ -51,8 +51,8 @@ static Value getSupportedReduction(AffineForOp forOp, unsigned pos,
     return nullptr;
 
   Operation *combinerOp = combinerOps.back();
-  Optional<arith::AtomicRMWKind> maybeKind =
-      TypeSwitch<Operation *, Optional<arith::AtomicRMWKind>>(combinerOp)
+  std::optional<arith::AtomicRMWKind> maybeKind =
+      TypeSwitch<Operation *, std::optional<arith::AtomicRMWKind>>(combinerOp)
           .Case([](arith::AddFOp) { return arith::AtomicRMWKind::addf; })
           .Case([](arith::MulFOp) { return arith::AtomicRMWKind::mulf; })
           .Case([](arith::AddIOp) { return arith::AtomicRMWKind::addi; })
@@ -65,7 +65,7 @@ static Value getSupportedReduction(AffineForOp forOp, unsigned pos,
           .Case([](arith::MaxSIOp) { return arith::AtomicRMWKind::maxs; })
           .Case([](arith::MinUIOp) { return arith::AtomicRMWKind::minu; })
           .Case([](arith::MaxUIOp) { return arith::AtomicRMWKind::maxu; })
-          .Default([](Operation *) -> Optional<arith::AtomicRMWKind> {
+          .Default([](Operation *) -> std::optional<arith::AtomicRMWKind> {
             // TODO: AtomicRMW supports other kinds of reductions this is
             // currently not detecting, add those when the need arises.
             return std::nullopt;

diff  --git a/mlir/lib/Dialect/Affine/Analysis/AffineStructures.cpp b/mlir/lib/Dialect/Affine/Analysis/AffineStructures.cpp
index 1ecbca59869da..56743424b95ef 100644
--- a/mlir/lib/Dialect/Affine/Analysis/AffineStructures.cpp
+++ b/mlir/lib/Dialect/Affine/Analysis/AffineStructures.cpp
@@ -258,7 +258,7 @@ void FlatAffineValueConstraints::reset(
     unsigned newNumLocals, ArrayRef<Value> valArgs) {
   assert(newNumReservedCols >= newNumDims + newNumSymbols + newNumLocals + 1 &&
          "minimum 1 column");
-  SmallVector<Optional<Value>, 8> newVals;
+  SmallVector<std::optional<Value>, 8> newVals;
   if (!valArgs.empty())
     newVals.assign(valArgs.begin(), valArgs.end());
 
@@ -318,7 +318,7 @@ unsigned FlatAffineValueConstraints::insertVar(VarKind kind, unsigned pos,
   // If a Value is provided, insert it; otherwise use None.
   for (unsigned i = 0; i < num; ++i)
     values.insert(values.begin() + absolutePos + i,
-                  vals[i] ? Optional<Value>(vals[i]) : std::nullopt);
+                  vals[i] ? std::optional<Value>(vals[i]) : std::nullopt);
 
   assert(values.size() == getNumDimAndSymbolVars());
   return absolutePos;
@@ -326,7 +326,7 @@ unsigned FlatAffineValueConstraints::insertVar(VarKind kind, unsigned pos,
 
 bool FlatAffineValueConstraints::hasValues() const {
   return llvm::any_of(
-      values, [](const Optional<Value> &var) { return var.has_value(); });
+      values, [](const std::optional<Value> &var) { return var.has_value(); });
 }
 
 /// Checks if two constraint systems are in the same space, i.e., if they are
@@ -359,9 +359,9 @@ static bool LLVM_ATTRIBUTE_UNUSED areVarsUnique(
     return true;
 
   SmallPtrSet<Value, 8> uniqueVars;
-  ArrayRef<Optional<Value>> maybeValues =
+  ArrayRef<std::optional<Value>> maybeValues =
       cst.getMaybeValues().slice(start, end - start);
-  for (Optional<Value> val : maybeValues) {
+  for (std::optional<Value> val : maybeValues) {
     if (val && !uniqueVars.insert(*val).second)
       return false;
   }
@@ -403,13 +403,13 @@ static void mergeAndAlignVars(unsigned offset, FlatAffineValueConstraints *a,
   assert(areVarsUnique(*a) && "A's values aren't unique");
   assert(areVarsUnique(*b) && "B's values aren't unique");
 
-  assert(
-      llvm::all_of(llvm::drop_begin(a->getMaybeValues(), offset),
-                   [](const Optional<Value> &var) { return var.has_value(); }));
+  assert(llvm::all_of(
+      llvm::drop_begin(a->getMaybeValues(), offset),
+      [](const std::optional<Value> &var) { return var.has_value(); }));
 
-  assert(
-      llvm::all_of(llvm::drop_begin(b->getMaybeValues(), offset),
-                   [](const Optional<Value> &var) { return var.has_value(); }));
+  assert(llvm::all_of(
+      llvm::drop_begin(b->getMaybeValues(), offset),
+      [](const std::optional<Value> &var) { return var.has_value(); }));
 
   SmallVector<Value, 4> aDimValues;
   a->getValues(offset, a->getNumDimVars(), &aDimValues);
@@ -1370,7 +1370,7 @@ bool FlatAffineValueConstraints::findVar(Value val, unsigned *pos) const {
 }
 
 bool FlatAffineValueConstraints::containsVar(Value val) const {
-  return llvm::any_of(values, [&](const Optional<Value> &mayBeVar) {
+  return llvm::any_of(values, [&](const std::optional<Value> &mayBeVar) {
     return mayBeVar && *mayBeVar == val;
   });
 }
@@ -1431,7 +1431,7 @@ void FlatAffineValueConstraints::clearAndCopyFrom(
 
 void FlatAffineValueConstraints::fourierMotzkinEliminate(
     unsigned pos, bool darkShadow, bool *isResultIntegerExact) {
-  SmallVector<Optional<Value>, 8> newVals = values;
+  SmallVector<std::optional<Value>, 8> newVals = values;
   if (getVarKindAt(pos) != VarKind::Local)
     newVals.erase(newVals.begin() + pos);
   // Note: Base implementation discards all associated Values.

diff  --git a/mlir/lib/Dialect/Affine/Analysis/LoopAnalysis.cpp b/mlir/lib/Dialect/Affine/Analysis/LoopAnalysis.cpp
index d13aa06c45476..81d06552aaef2 100644
--- a/mlir/lib/Dialect/Affine/Analysis/LoopAnalysis.cpp
+++ b/mlir/lib/Dialect/Affine/Analysis/LoopAnalysis.cpp
@@ -83,7 +83,7 @@ void mlir::getTripCountMapAndOperands(
 /// otherwise. This method uses affine expression analysis (in turn using
 /// getTripCount) and is able to determine constant trip count in non-trivial
 /// cases.
-Optional<uint64_t> mlir::getConstantTripCount(AffineForOp forOp) {
+std::optional<uint64_t> mlir::getConstantTripCount(AffineForOp forOp) {
   SmallVector<Value, 4> operands;
   AffineMap map;
   getTripCountMapAndOperands(forOp, &map, &operands);
@@ -92,7 +92,7 @@ Optional<uint64_t> mlir::getConstantTripCount(AffineForOp forOp) {
     return std::nullopt;
 
   // Take the min if all trip counts are constant.
-  Optional<uint64_t> tripCount;
+  std::optional<uint64_t> tripCount;
   for (auto resultExpr : map.getResults()) {
     if (auto constExpr = resultExpr.dyn_cast<AffineConstantExpr>()) {
       if (tripCount.has_value())

diff  --git a/mlir/lib/Dialect/Affine/Analysis/Utils.cpp b/mlir/lib/Dialect/Affine/Analysis/Utils.cpp
index 4ab91ba4bf08c..ff88acdf8f19f 100644
--- a/mlir/lib/Dialect/Affine/Analysis/Utils.cpp
+++ b/mlir/lib/Dialect/Affine/Analysis/Utils.cpp
@@ -147,7 +147,7 @@ void ComputationSliceState::dump() const {
 /// and the dst loops for those dimensions have the same bounds. Returns false
 /// if both the src and the dst loops don't have the same bounds. Returns
 /// std::nullopt if none of the above can be proven.
-Optional<bool> ComputationSliceState::isSliceMaximalFastCheck() const {
+std::optional<bool> ComputationSliceState::isSliceMaximalFastCheck() const {
   assert(lbs.size() == ubs.size() && !lbs.empty() && !ivs.empty() &&
          "Unexpected number of lbs, ubs and ivs in slice");
 
@@ -215,7 +215,7 @@ Optional<bool> ComputationSliceState::isSliceMaximalFastCheck() const {
 /// Returns true if it is deterministically verified that the original iteration
 /// space of the slice is contained within the new iteration space that is
 /// created after fusing 'this' slice into its destination.
-Optional<bool> ComputationSliceState::isSliceValid() {
+std::optional<bool> ComputationSliceState::isSliceValid() {
   // Fast check to determine if the slice is valid. If the following conditions
   // are verified to be true, slice is declared valid by the fast check:
   // 1. Each slice loop is a single iteration loop bound in terms of a single
@@ -226,7 +226,7 @@ Optional<bool> ComputationSliceState::isSliceValid() {
   // expensive analysis.
   // TODO: Store the result of the fast check, as it might be used again in
   // `canRemoveSrcNodeAfterFusion`.
-  Optional<bool> isValidFastCheck = isSliceMaximalFastCheck();
+  std::optional<bool> isValidFastCheck = isSliceMaximalFastCheck();
   if (isValidFastCheck && *isValidFastCheck)
     return true;
 
@@ -285,10 +285,10 @@ Optional<bool> ComputationSliceState::isSliceValid() {
 /// Returns true if the computation slice encloses all the iterations of the
 /// sliced loop nest. Returns false if it does not. Returns std::nullopt if it
 /// cannot determine if the slice is maximal or not.
-Optional<bool> ComputationSliceState::isMaximal() const {
+std::optional<bool> ComputationSliceState::isMaximal() const {
   // Fast check to determine if the computation slice is maximal. If the result
   // is inconclusive, we proceed with a more expensive analysis.
-  Optional<bool> isMaximalFastCheck = isSliceMaximalFastCheck();
+  std::optional<bool> isMaximalFastCheck = isSliceMaximalFastCheck();
   if (isMaximalFastCheck)
     return isMaximalFastCheck;
 
@@ -339,7 +339,7 @@ unsigned MemRefRegion::getRank() const {
   return memref.getType().cast<MemRefType>().getRank();
 }
 
-Optional<int64_t> MemRefRegion::getConstantBoundingSizeAndShape(
+std::optional<int64_t> MemRefRegion::getConstantBoundingSizeAndShape(
     SmallVectorImpl<int64_t> *shape, std::vector<SmallVector<int64_t, 4>> *lbs,
     SmallVectorImpl<int64_t> *lbDivisors) const {
   auto memRefType = memref.getType().cast<MemRefType>();
@@ -370,7 +370,7 @@ Optional<int64_t> MemRefRegion::getConstantBoundingSizeAndShape(
   int64_t lbDivisor;
   for (unsigned d = 0; d < rank; d++) {
     SmallVector<int64_t, 4> lb;
-    Optional<int64_t> 
diff  =
+    std::optional<int64_t> 
diff  =
         cstWithShapeBounds.getConstantBoundOnDimSize64(d, &lb, &lbDivisor);
     if (
diff .has_value()) {
       
diff Constant = *
diff ;
@@ -611,7 +611,7 @@ static unsigned getMemRefEltSizeInBytes(MemRefType memRefType) {
 }
 
 // Returns the size of the region.
-Optional<int64_t> MemRefRegion::getRegionSize() {
+std::optional<int64_t> MemRefRegion::getRegionSize() {
   auto memRefType = memref.getType().cast<MemRefType>();
 
   if (!memRefType.getLayout().isIdentity()) {
@@ -626,7 +626,7 @@ Optional<int64_t> MemRefRegion::getRegionSize() {
   SmallVector<Value, 4> bufIndices;
 
   // Compute the extents of the buffer.
-  Optional<int64_t> numElements = getConstantBoundingSizeAndShape();
+  std::optional<int64_t> numElements = getConstantBoundingSizeAndShape();
   if (!numElements) {
     LLVM_DEBUG(llvm::dbgs() << "Dynamic shapes not yet supported\n");
     return std::nullopt;
@@ -638,7 +638,7 @@ Optional<int64_t> MemRefRegion::getRegionSize() {
 /// std::nullopt otherwise.  If the element of the memref has vector type, takes
 /// into account size of the vector as well.
 //  TODO: improve/complete this when we have target data.
-Optional<uint64_t> mlir::getMemRefSizeInBytes(MemRefType memRefType) {
+std::optional<uint64_t> mlir::getMemRefSizeInBytes(MemRefType memRefType) {
   if (!memRefType.hasStaticShape())
     return std::nullopt;
   auto elementType = memRefType.getElementType();
@@ -956,7 +956,7 @@ mlir::computeSliceUnion(ArrayRef<Operation *> opsA, ArrayRef<Operation *> opsB,
 
   // Check if the slice computed is valid. Return success only if it is verified
   // that the slice is valid, otherwise return appropriate failure status.
-  Optional<bool> isSliceValid = sliceUnion->isSliceValid();
+  std::optional<bool> isSliceValid = sliceUnion->isSliceValid();
   if (!isSliceValid) {
     LLVM_DEBUG(llvm::dbgs() << "Cannot determine if the slice is valid\n");
     return SliceComputationResult::GenericFailure;
@@ -968,7 +968,8 @@ mlir::computeSliceUnion(ArrayRef<Operation *> opsA, ArrayRef<Operation *> opsB,
 }
 
 // TODO: extend this to handle multiple result maps.
-static Optional<uint64_t> getConstDifference(AffineMap lbMap, AffineMap ubMap) {
+static std::optional<uint64_t> getConstDifference(AffineMap lbMap,
+                                                  AffineMap ubMap) {
   assert(lbMap.getNumResults() == 1 && "expected single result bound map");
   assert(ubMap.getNumResults() == 1 && "expected single result bound map");
   assert(lbMap.getNumDims() == ubMap.getNumDims());
@@ -1008,14 +1009,14 @@ bool mlir::buildSliceTripCountMap(
             forOp.getConstantUpperBound() - forOp.getConstantLowerBound();
         continue;
       }
-      Optional<uint64_t> maybeConstTripCount = getConstantTripCount(forOp);
+      std::optional<uint64_t> maybeConstTripCount = getConstantTripCount(forOp);
       if (maybeConstTripCount.has_value()) {
         (*tripCountMap)[op] = *maybeConstTripCount;
         continue;
       }
       return false;
     }
-    Optional<uint64_t> tripCount = getConstDifference(lbMap, ubMap);
+    std::optional<uint64_t> tripCount = getConstDifference(lbMap, ubMap);
     // Slice bounds are created with a constant ub - lb 
diff erence.
     if (!tripCount.has_value())
       return false;
@@ -1129,7 +1130,7 @@ void mlir::getComputationSliceState(
     //    1. Slice is  single trip count.
     //    2. Loop bounds of the source and destination match.
     //    3. Is being inserted at the innermost insertion point.
-    Optional<bool> isMaximal = sliceState->isMaximal();
+    std::optional<bool> isMaximal = sliceState->isMaximal();
     if (isLoopParallelAndContainsReduction(getSliceLoop(i)) &&
         isInnermostInsertion() && srcIsUnitSlice() && isMaximal && *isMaximal)
       continue;
@@ -1297,10 +1298,10 @@ unsigned mlir::getNumCommonSurroundingLoops(Operation &a, Operation &b) {
   return numCommonLoops;
 }
 
-static Optional<int64_t> getMemoryFootprintBytes(Block &block,
-                                                 Block::iterator start,
-                                                 Block::iterator end,
-                                                 int memorySpace) {
+static std::optional<int64_t> getMemoryFootprintBytes(Block &block,
+                                                      Block::iterator start,
+                                                      Block::iterator end,
+                                                      int memorySpace) {
   SmallDenseMap<Value, std::unique_ptr<MemRefRegion>, 4> regions;
 
   // Walk this 'affine.for' operation to gather all memory regions.
@@ -1333,7 +1334,7 @@ static Optional<int64_t> getMemoryFootprintBytes(Block &block,
 
   int64_t totalSizeInBytes = 0;
   for (const auto &region : regions) {
-    Optional<int64_t> size = region.second->getRegionSize();
+    std::optional<int64_t> size = region.second->getRegionSize();
     if (!size.has_value())
       return std::nullopt;
     totalSizeInBytes += *size;
@@ -1341,8 +1342,8 @@ static Optional<int64_t> getMemoryFootprintBytes(Block &block,
   return totalSizeInBytes;
 }
 
-Optional<int64_t> mlir::getMemoryFootprintBytes(AffineForOp forOp,
-                                                int memorySpace) {
+std::optional<int64_t> mlir::getMemoryFootprintBytes(AffineForOp forOp,
+                                                     int memorySpace) {
   auto *forInst = forOp.getOperation();
   return ::getMemoryFootprintBytes(
       *forInst->getBlock(), Block::iterator(forInst),
@@ -1380,11 +1381,12 @@ IntegerSet mlir::simplifyIntegerSet(IntegerSet set) {
   return simplifiedSet;
 }
 
-static void unpackOptionalValues(ArrayRef<Optional<Value>> source,
+static void unpackOptionalValues(ArrayRef<std::optional<Value>> source,
                                  SmallVector<Value> &target) {
-  target = llvm::to_vector<4>(llvm::map_range(source, [](Optional<Value> val) {
-    return val.has_value() ? *val : Value();
-  }));
+  target =
+      llvm::to_vector<4>(llvm::map_range(source, [](std::optional<Value> val) {
+        return val.has_value() ? *val : Value();
+      }));
 }
 
 /// Bound an identifier `pos` in a given FlatAffineValueConstraints with

diff  --git a/mlir/lib/Dialect/Affine/Transforms/AffineDataCopyGeneration.cpp b/mlir/lib/Dialect/Affine/Transforms/AffineDataCopyGeneration.cpp
index cc658f1ddd822..0d84d384012c2 100644
--- a/mlir/lib/Dialect/Affine/Transforms/AffineDataCopyGeneration.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/AffineDataCopyGeneration.cpp
@@ -146,7 +146,7 @@ void AffineDataCopyGeneration::runOnBlock(Block *block,
 
       // Returns true if the footprint is known to exceed capacity.
       auto exceedsCapacity = [&](AffineForOp forOp) {
-        Optional<int64_t> footprint =
+        std::optional<int64_t> footprint =
             getMemoryFootprintBytes(forOp,
                                     /*memorySpace=*/0);
         return (footprint.has_value() &&

diff  --git a/mlir/lib/Dialect/Affine/Transforms/LoopFusion.cpp b/mlir/lib/Dialect/Affine/Transforms/LoopFusion.cpp
index f836352ba24f8..656158798cbc7 100644
--- a/mlir/lib/Dialect/Affine/Transforms/LoopFusion.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/LoopFusion.cpp
@@ -651,7 +651,7 @@ static bool canRemoveSrcNodeAfterFusion(
   // escaping memref, we can only remove it if the fusion slice is maximal so
   // that all the dependences are preserved.
   if (hasOutDepsAfterFusion || !escapingMemRefs.empty()) {
-    Optional<bool> isMaximal = fusionSlice.isMaximal();
+    std::optional<bool> isMaximal = fusionSlice.isMaximal();
     if (!isMaximal) {
       LLVM_DEBUG(llvm::dbgs() << "Src loop can't be removed: can't determine "
                                  "if fusion is maximal\n");
@@ -926,7 +926,7 @@ static unsigned getMemRefEltSizeInBytes(MemRefType memRefType) {
 // this one.
 static Value createPrivateMemRef(AffineForOp forOp, Operation *srcStoreOpInst,
                                  unsigned dstLoopDepth,
-                                 Optional<unsigned> fastMemorySpace,
+                                 std::optional<unsigned> fastMemorySpace,
                                  uint64_t localBufSizeThreshold) {
   Operation *forInst = forOp.getOperation();
 
@@ -950,7 +950,7 @@ static Value createPrivateMemRef(AffineForOp forOp, Operation *srcStoreOpInst,
   lbs.reserve(rank);
   // Query 'region' for 'newShape' and lower bounds of MemRefRegion accessed
   // by 'srcStoreOpInst' at depth 'dstLoopDepth'.
-  Optional<int64_t> numElements =
+  std::optional<int64_t> numElements =
       region.getConstantBoundingSizeAndShape(&newShape, &lbs, &lbDivisors);
   assert(numElements && "non-constant number of elts in local buffer");
 
@@ -1176,7 +1176,7 @@ static bool isFusionProfitable(Operation *srcOpInst, Operation *srcStoreOpInst,
     return false;
   }
 
-  Optional<int64_t> maybeSrcWriteRegionSizeBytes =
+  std::optional<int64_t> maybeSrcWriteRegionSizeBytes =
       srcWriteRegion.getRegionSize();
   if (!maybeSrcWriteRegionSizeBytes.has_value())
     return false;
@@ -1218,7 +1218,7 @@ static bool isFusionProfitable(Operation *srcOpInst, Operation *srcStoreOpInst,
       continue;
     }
 
-    Optional<int64_t> maybeSliceWriteRegionSizeBytes =
+    std::optional<int64_t> maybeSliceWriteRegionSizeBytes =
         sliceWriteRegion.getRegionSize();
     if (!maybeSliceWriteRegionSizeBytes.has_value() ||
         *maybeSliceWriteRegionSizeBytes == 0) {
@@ -1398,7 +1398,7 @@ struct GreedyFusion {
   // Parameter for local buffer size threshold.
   unsigned localBufSizeThreshold;
   // Parameter for fast memory space.
-  Optional<unsigned> fastMemorySpace;
+  std::optional<unsigned> fastMemorySpace;
   // If true, ignore any additional (redundant) computation tolerance threshold
   // that would have prevented fusion.
   bool maximalFusion;
@@ -1409,7 +1409,7 @@ struct GreedyFusion {
   using Node = MemRefDependenceGraph::Node;
 
   GreedyFusion(MemRefDependenceGraph *mdg, unsigned localBufSizeThreshold,
-               Optional<unsigned> fastMemorySpace, bool maximalFusion,
+               std::optional<unsigned> fastMemorySpace, bool maximalFusion,
                double computeToleranceThreshold)
       : mdg(mdg), localBufSizeThreshold(localBufSizeThreshold),
         fastMemorySpace(fastMemorySpace), maximalFusion(maximalFusion),
@@ -2016,7 +2016,7 @@ void LoopFusion::runOnBlock(Block *block) {
   if (!g.init(block))
     return;
 
-  Optional<unsigned> fastMemorySpaceOpt;
+  std::optional<unsigned> fastMemorySpaceOpt;
   if (fastMemorySpace.hasValue())
     fastMemorySpaceOpt = fastMemorySpace;
   unsigned localBufSizeThresholdBytes = localBufSizeThreshold * 1024;

diff  --git a/mlir/lib/Dialect/Affine/Transforms/LoopTiling.cpp b/mlir/lib/Dialect/Affine/Transforms/LoopTiling.cpp
index ee5dd9870abb9..319982ba273cf 100644
--- a/mlir/lib/Dialect/Affine/Transforms/LoopTiling.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/LoopTiling.cpp
@@ -76,7 +76,7 @@ static void adjustToDivisorsOfTripCounts(ArrayRef<AffineForOp> band,
   assert(band.size() == tileSizes->size() && "invalid tile size count");
   for (unsigned i = 0, e = band.size(); i < e; i++) {
     unsigned &tSizeAdjusted = (*tileSizes)[i];
-    Optional<uint64_t> mayConst = getConstantTripCount(band[i]);
+    std::optional<uint64_t> mayConst = getConstantTripCount(band[i]);
     if (!mayConst)
       continue;
     // Adjust the tile size to largest factor of the trip count less than
@@ -122,7 +122,7 @@ void LoopTiling::getTileSizes(ArrayRef<AffineForOp> band,
   // the cache size. This is an approximation with the assumption that the
   // footprint increases with the tile size linearly in that dimension (i.e.,
   // assumes one-to-one access function).
-  Optional<int64_t> fp = getMemoryFootprintBytes(band[0], 0);
+  std::optional<int64_t> fp = getMemoryFootprintBytes(band[0], 0);
   if (!fp) {
     // Fill with default tile sizes if footprint is unknown.
     std::fill(tileSizes->begin(), tileSizes->end(),

diff  --git a/mlir/lib/Dialect/Affine/Transforms/LoopUnroll.cpp b/mlir/lib/Dialect/Affine/Transforms/LoopUnroll.cpp
index a1cbb9127df8e..825a36840bbf1 100644
--- a/mlir/lib/Dialect/Affine/Transforms/LoopUnroll.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/LoopUnroll.cpp
@@ -52,7 +52,7 @@ struct LoopUnroll : public impl::AffineLoopUnrollBase<LoopUnroll> {
 
       = default;
   explicit LoopUnroll(
-      Optional<unsigned> unrollFactor = std::nullopt,
+      std::optional<unsigned> unrollFactor = std::nullopt,
       bool unrollUpToFactor = false, bool unrollFull = false,
       const std::function<unsigned(AffineForOp)> &getUnrollFactor = nullptr)
       : getUnrollFactor(getUnrollFactor) {
@@ -100,7 +100,7 @@ void LoopUnroll::runOnOperation() {
     // so that loops are gathered from innermost to outermost (or else unrolling
     // an outer one may delete gathered inner ones).
     getOperation().walk([&](AffineForOp forOp) {
-      Optional<uint64_t> tripCount = getConstantTripCount(forOp);
+      std::optional<uint64_t> tripCount = getConstantTripCount(forOp);
       if (tripCount && *tripCount <= unrollFullThreshold)
         loops.push_back(forOp);
     });
@@ -146,6 +146,6 @@ std::unique_ptr<OperationPass<func::FuncOp>> mlir::createLoopUnrollPass(
     int unrollFactor, bool unrollUpToFactor, bool unrollFull,
     const std::function<unsigned(AffineForOp)> &getUnrollFactor) {
   return std::make_unique<LoopUnroll>(
-      unrollFactor == -1 ? std::nullopt : Optional<unsigned>(unrollFactor),
+      unrollFactor == -1 ? std::nullopt : std::optional<unsigned>(unrollFactor),
       unrollUpToFactor, unrollFull, getUnrollFactor);
 }

diff  --git a/mlir/lib/Dialect/Affine/Transforms/LoopUnrollAndJam.cpp b/mlir/lib/Dialect/Affine/Transforms/LoopUnrollAndJam.cpp
index 55d580b727826..a0fad4dc5b4f5 100644
--- a/mlir/lib/Dialect/Affine/Transforms/LoopUnrollAndJam.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/LoopUnrollAndJam.cpp
@@ -62,7 +62,8 @@ namespace {
 /// outer loop in a Function.
 struct LoopUnrollAndJam
     : public impl::AffineLoopUnrollAndJamBase<LoopUnrollAndJam> {
-  explicit LoopUnrollAndJam(Optional<unsigned> unrollJamFactor = std::nullopt) {
+  explicit LoopUnrollAndJam(
+      std::optional<unsigned> unrollJamFactor = std::nullopt) {
     if (unrollJamFactor)
       this->unrollJamFactor = *unrollJamFactor;
   }
@@ -75,7 +76,7 @@ std::unique_ptr<OperationPass<func::FuncOp>>
 mlir::createLoopUnrollAndJamPass(int unrollJamFactor) {
   return std::make_unique<LoopUnrollAndJam>(
       unrollJamFactor == -1 ? std::nullopt
-                            : Optional<unsigned>(unrollJamFactor));
+                            : std::optional<unsigned>(unrollJamFactor));
 }
 
 void LoopUnrollAndJam::runOnOperation() {

diff  --git a/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp b/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp
index a6503957748b9..30affbb8442d3 100644
--- a/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp
@@ -582,7 +582,7 @@ isVectorizableLoopPtrFactory(const DenseSet<Operation *> &parallelLoops,
 /// Up to 3-D patterns are supported.
 /// If the command line argument requests a pattern of higher order, returns an
 /// empty pattern list which will conservatively result in no vectorization.
-static Optional<NestedPattern>
+static std::optional<NestedPattern>
 makePattern(const DenseSet<Operation *> &parallelLoops, int vectorRank,
             ArrayRef<int64_t> fastestVaryingPattern) {
   using matcher::For;
@@ -1666,7 +1666,7 @@ static void vectorizeLoops(Operation *parentOp, DenseSet<Operation *> &loops,
          "Vectorizing reductions is supported only for 1-D vectors");
 
   // Compute 1-D, 2-D or 3-D loop pattern to be matched on the target loops.
-  Optional<NestedPattern> pattern =
+  std::optional<NestedPattern> pattern =
       makePattern(loops, vectorSizes.size(), fastestVaryingPattern);
   if (!pattern) {
     LLVM_DEBUG(dbgs() << "\n[early-vect] pattern couldn't be computed\n");

diff  --git a/mlir/lib/Dialect/Affine/Utils/LoopFusionUtils.cpp b/mlir/lib/Dialect/Affine/Utils/LoopFusionUtils.cpp
index 59fdeb8d440b4..366c090d0dcf4 100644
--- a/mlir/lib/Dialect/Affine/Utils/LoopFusionUtils.cpp
+++ b/mlir/lib/Dialect/Affine/Utils/LoopFusionUtils.cpp
@@ -358,7 +358,7 @@ FusionResult mlir::canFuseLoops(AffineForOp srcForOp, AffineForOp dstForOp,
 LogicalResult promoteSingleIterReductionLoop(AffineForOp forOp,
                                              bool siblingFusionUser) {
   // Check if the reduction loop is a single iteration loop.
-  Optional<uint64_t> tripCount = getConstantTripCount(forOp);
+  std::optional<uint64_t> tripCount = getConstantTripCount(forOp);
   if (!tripCount || *tripCount != 1)
     return failure();
   auto iterOperands = forOp.getIterOperands();
@@ -491,7 +491,7 @@ bool mlir::getLoopNestStats(AffineForOp forOpRoot, LoopNestStats *stats) {
 
     // Record trip count for 'forOp'. Set flag if trip count is not
     // constant.
-    Optional<uint64_t> maybeConstTripCount = getConstantTripCount(forOp);
+    std::optional<uint64_t> maybeConstTripCount = getConstantTripCount(forOp);
     if (!maybeConstTripCount) {
       // Currently only constant trip count loop nests are supported.
       LLVM_DEBUG(llvm::dbgs() << "Non-constant trip count unsupported\n");

diff  --git a/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp b/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp
index 9b3ec21f77971..5860086e588bc 100644
--- a/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp
+++ b/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp
@@ -130,7 +130,7 @@ static void replaceIterArgsAndYieldResults(AffineForOp forOp) {
 /// was known to have a single iteration.
 // TODO: extend this for arbitrary affine bounds.
 LogicalResult mlir::promoteIfSingleIteration(AffineForOp forOp) {
-  Optional<uint64_t> tripCount = getConstantTripCount(forOp);
+  std::optional<uint64_t> tripCount = getConstantTripCount(forOp);
   if (!tripCount || *tripCount != 1)
     return failure();
 
@@ -791,7 +791,8 @@ constructTiledIndexSetHyperRect(MutableArrayRef<AffineForOp> origLoops,
   // Bounds for intra-tile loops.
   for (unsigned i = 0; i < width; i++) {
     int64_t largestDiv = getLargestDivisorOfTripCount(origLoops[i]);
-    Optional<uint64_t> mayBeConstantCount = getConstantTripCount(origLoops[i]);
+    std::optional<uint64_t> mayBeConstantCount =
+        getConstantTripCount(origLoops[i]);
     // The lower bound is just the tile-space loop.
     AffineMap lbMap = b.getDimIdentityMap();
     newLoops[width + i].setLowerBound(
@@ -971,7 +972,7 @@ void mlir::getTileableBands(func::FuncOp f,
 
 /// Unrolls this loop completely.
 LogicalResult mlir::loopUnrollFull(AffineForOp forOp) {
-  Optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
+  std::optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
   if (mayBeConstantTripCount.has_value()) {
     uint64_t tripCount = *mayBeConstantTripCount;
     if (tripCount == 0)
@@ -987,7 +988,7 @@ LogicalResult mlir::loopUnrollFull(AffineForOp forOp) {
 /// whichever is lower.
 LogicalResult mlir::loopUnrollUpToFactor(AffineForOp forOp,
                                          uint64_t unrollFactor) {
-  Optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
+  std::optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
   if (mayBeConstantTripCount.has_value() &&
       *mayBeConstantTripCount < unrollFactor)
     return loopUnrollByFactor(forOp, *mayBeConstantTripCount);
@@ -1093,7 +1094,7 @@ LogicalResult mlir::loopUnrollByFactor(
     bool cleanUpUnroll) {
   assert(unrollFactor > 0 && "unroll factor should be positive");
 
-  Optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
+  std::optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
   if (unrollFactor == 1) {
     if (mayBeConstantTripCount && *mayBeConstantTripCount == 1 &&
         failed(promoteIfSingleIteration(forOp)))
@@ -1156,7 +1157,7 @@ LogicalResult mlir::loopUnrollByFactor(
 
 LogicalResult mlir::loopUnrollJamUpToFactor(AffineForOp forOp,
                                             uint64_t unrollJamFactor) {
-  Optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
+  std::optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
   if (mayBeConstantTripCount.has_value() &&
       *mayBeConstantTripCount < unrollJamFactor)
     return loopUnrollJamByFactor(forOp, *mayBeConstantTripCount);
@@ -1209,7 +1210,7 @@ LogicalResult mlir::loopUnrollJamByFactor(AffineForOp forOp,
                                           uint64_t unrollJamFactor) {
   assert(unrollJamFactor > 0 && "unroll jam factor should be positive");
 
-  Optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
+  std::optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);
   if (unrollJamFactor == 1) {
     if (mayBeConstantTripCount && *mayBeConstantTripCount == 1 &&
         failed(promoteIfSingleIteration(forOp)))
@@ -2095,7 +2096,7 @@ static LogicalResult generateCopy(
   std::vector<SmallVector<int64_t, 4>> lbs;
   SmallVector<int64_t, 8> lbDivisors;
   lbs.reserve(rank);
-  Optional<int64_t> numElements = region.getConstantBoundingSizeAndShape(
+  std::optional<int64_t> numElements = region.getConstantBoundingSizeAndShape(
       &fastBufferShape, &lbs, &lbDivisors);
   if (!numElements) {
     LLVM_DEBUG(llvm::dbgs() << "Non-constant region size not supported\n");
@@ -2376,7 +2377,7 @@ static bool getFullMemRefAsRegion(Operation *op, unsigned numParamLoopIVs,
 LogicalResult mlir::affineDataCopyGenerate(Block::iterator begin,
                                            Block::iterator end,
                                            const AffineCopyOptions &copyOptions,
-                                           Optional<Value> filterMemRef,
+                                           std::optional<Value> filterMemRef,
                                            DenseSet<Operation *> &copyNests) {
   if (begin == end)
     return success();
@@ -2565,7 +2566,7 @@ LogicalResult mlir::affineDataCopyGenerate(Block::iterator begin,
 // an AffineForOp.
 LogicalResult mlir::affineDataCopyGenerate(AffineForOp forOp,
                                            const AffineCopyOptions &copyOptions,
-                                           Optional<Value> filterMemRef,
+                                           std::optional<Value> filterMemRef,
                                            DenseSet<Operation *> &copyNests) {
   return affineDataCopyGenerate(forOp.getBody()->begin(),
                                 std::prev(forOp.getBody()->end()), copyOptions,

diff  --git a/mlir/lib/Dialect/Affine/Utils/Utils.cpp b/mlir/lib/Dialect/Affine/Utils/Utils.cpp
index 9140031e5d39f..180fef853e202 100644
--- a/mlir/lib/Dialect/Affine/Utils/Utils.cpp
+++ b/mlir/lib/Dialect/Affine/Utils/Utils.cpp
@@ -217,10 +217,9 @@ mlir::Value mlir::expandAffineExpr(OpBuilder &builder, Location loc,
 
 /// Create a sequence of operations that implement the `affineMap` applied to
 /// the given `operands` (as it it were an AffineApplyOp).
-Optional<SmallVector<Value, 8>> mlir::expandAffineMap(OpBuilder &builder,
-                                                      Location loc,
-                                                      AffineMap affineMap,
-                                                      ValueRange operands) {
+std::optional<SmallVector<Value, 8>>
+mlir::expandAffineMap(OpBuilder &builder, Location loc, AffineMap affineMap,
+                      ValueRange operands) {
   auto numDims = affineMap.getNumDims();
   auto expanded = llvm::to_vector<8>(
       llvm::map_range(affineMap.getResults(),
@@ -1817,7 +1816,7 @@ MemRefType mlir::normalizeMemRefType(MemRefType memrefType,
       newShape[d] = ShapedType::kDynamic;
     } else {
       // The lower bound for the shape is always zero.
-      Optional<int64_t> ubConst =
+      std::optional<int64_t> ubConst =
           fac.getConstantBound64(IntegerPolyhedron::UB, d);
       // For a static memref and an affine map with no symbols, this is
       // always bounded. However, when we have symbols, we may not be able to

diff  --git a/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp b/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp
index f56aefaea3579..10d6ef29756c6 100644
--- a/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp
+++ b/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp
@@ -20,7 +20,7 @@ using namespace mlir::arith;
 /// Function that evaluates the result of doing something on arithmetic
 /// constants and returns std::nullopt on overflow.
 using ConstArithFn =
-    function_ref<Optional<APInt>(const APInt &, const APInt &)>;
+    function_ref<std::optional<APInt>(const APInt &, const APInt &)>;
 
 /// Return the maxmially wide signed or unsigned range for a given bitwidth.
 
@@ -30,8 +30,8 @@ static ConstantIntRanges computeBoundsBy(ConstArithFn op, const APInt &minLeft,
                                          const APInt &minRight,
                                          const APInt &maxLeft,
                                          const APInt &maxRight, bool isSigned) {
-  Optional<APInt> maybeMin = op(minLeft, minRight);
-  Optional<APInt> maybeMax = op(maxLeft, maxRight);
+  std::optional<APInt> maybeMin = op(minLeft, minRight);
+  std::optional<APInt> maybeMax = op(maxLeft, maxRight);
   if (maybeMin && maybeMax)
     return ConstantIntRanges::range(*maybeMin, *maybeMax, isSigned);
   return ConstantIntRanges::maxRange(minLeft.getBitWidth());
@@ -48,7 +48,7 @@ static ConstantIntRanges minMaxBy(ConstArithFn op, ArrayRef<APInt> lhs,
       isSigned ? APInt::getSignedMinValue(width) : APInt::getZero(width);
   for (const APInt &left : lhs) {
     for (const APInt &right : rhs) {
-      Optional<APInt> maybeThisResult = op(left, right);
+      std::optional<APInt> maybeThisResult = op(left, right);
       if (!maybeThisResult)
         return ConstantIntRanges::maxRange(width);
       APInt result = std::move(*maybeThisResult);
@@ -79,15 +79,17 @@ void arith::ConstantOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
 void arith::AddIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
                                       SetIntRangeFn setResultRange) {
   const ConstantIntRanges &lhs = argRanges[0], &rhs = argRanges[1];
-  ConstArithFn uadd = [](const APInt &a, const APInt &b) -> Optional<APInt> {
+  ConstArithFn uadd = [](const APInt &a,
+                         const APInt &b) -> std::optional<APInt> {
     bool overflowed = false;
     APInt result = a.uadd_ov(b, overflowed);
-    return overflowed ? Optional<APInt>() : result;
+    return overflowed ? std::optional<APInt>() : result;
   };
-  ConstArithFn sadd = [](const APInt &a, const APInt &b) -> Optional<APInt> {
+  ConstArithFn sadd = [](const APInt &a,
+                         const APInt &b) -> std::optional<APInt> {
     bool overflowed = false;
     APInt result = a.sadd_ov(b, overflowed);
-    return overflowed ? Optional<APInt>() : result;
+    return overflowed ? std::optional<APInt>() : result;
   };
 
   ConstantIntRanges urange = computeBoundsBy(
@@ -105,15 +107,17 @@ void arith::SubIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
                                       SetIntRangeFn setResultRange) {
   const ConstantIntRanges &lhs = argRanges[0], &rhs = argRanges[1];
 
-  ConstArithFn usub = [](const APInt &a, const APInt &b) -> Optional<APInt> {
+  ConstArithFn usub = [](const APInt &a,
+                         const APInt &b) -> std::optional<APInt> {
     bool overflowed = false;
     APInt result = a.usub_ov(b, overflowed);
-    return overflowed ? Optional<APInt>() : result;
+    return overflowed ? std::optional<APInt>() : result;
   };
-  ConstArithFn ssub = [](const APInt &a, const APInt &b) -> Optional<APInt> {
+  ConstArithFn ssub = [](const APInt &a,
+                         const APInt &b) -> std::optional<APInt> {
     bool overflowed = false;
     APInt result = a.ssub_ov(b, overflowed);
-    return overflowed ? Optional<APInt>() : result;
+    return overflowed ? std::optional<APInt>() : result;
   };
   ConstantIntRanges urange = computeBoundsBy(
       usub, lhs.umin(), rhs.umax(), lhs.umax(), rhs.umin(), /*isSigned=*/false);
@@ -130,15 +134,17 @@ void arith::MulIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
                                       SetIntRangeFn setResultRange) {
   const ConstantIntRanges &lhs = argRanges[0], &rhs = argRanges[1];
 
-  ConstArithFn umul = [](const APInt &a, const APInt &b) -> Optional<APInt> {
+  ConstArithFn umul = [](const APInt &a,
+                         const APInt &b) -> std::optional<APInt> {
     bool overflowed = false;
     APInt result = a.umul_ov(b, overflowed);
-    return overflowed ? Optional<APInt>() : result;
+    return overflowed ? std::optional<APInt>() : result;
   };
-  ConstArithFn smul = [](const APInt &a, const APInt &b) -> Optional<APInt> {
+  ConstArithFn smul = [](const APInt &a,
+                         const APInt &b) -> std::optional<APInt> {
     bool overflowed = false;
     APInt result = a.smul_ov(b, overflowed);
-    return overflowed ? Optional<APInt>() : result;
+    return overflowed ? std::optional<APInt>() : result;
   };
 
   ConstantIntRanges urange =
@@ -157,7 +163,7 @@ void arith::MulIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
 
 /// Fix up division results (ex. for ceiling and floor), returning an APInt
 /// if there has been no overflow
-using DivisionFixupFn = function_ref<Optional<APInt>(
+using DivisionFixupFn = function_ref<std::optional<APInt>(
     const APInt &lhs, const APInt &rhs, const APInt &result)>;
 
 static ConstantIntRanges inferDivUIRange(const ConstantIntRanges &lhs,
@@ -167,7 +173,8 @@ static ConstantIntRanges inferDivUIRange(const ConstantIntRanges &lhs,
               &rhsMax = rhs.umax();
 
   if (!rhsMin.isZero()) {
-    auto udiv = [&fixup](const APInt &a, const APInt &b) -> Optional<APInt> {
+    auto udiv = [&fixup](const APInt &a,
+                         const APInt &b) -> std::optional<APInt> {
       return fixup(a, b, a.udiv(b));
     };
     return minMaxBy(udiv, {lhsMin, lhsMax}, {rhsMin, rhsMax},
@@ -197,10 +204,11 @@ static ConstantIntRanges inferDivSIRange(const ConstantIntRanges &lhs,
   bool canDivide = rhsMin.isStrictlyPositive() || rhsMax.isNegative();
 
   if (canDivide) {
-    auto sdiv = [&fixup](const APInt &a, const APInt &b) -> Optional<APInt> {
+    auto sdiv = [&fixup](const APInt &a,
+                         const APInt &b) -> std::optional<APInt> {
       bool overflowed = false;
       APInt result = a.sdiv_ov(b, overflowed);
-      return overflowed ? Optional<APInt>() : fixup(a, b, result);
+      return overflowed ? std::optional<APInt>() : fixup(a, b, result);
     };
     return minMaxBy(sdiv, {lhsMin, lhsMax}, {rhsMin, rhsMax},
                     /*isSigned=*/true);
@@ -224,13 +232,14 @@ void arith::CeilDivUIOp::inferResultRanges(
     ArrayRef<ConstantIntRanges> argRanges, SetIntRangeFn setResultRange) {
   const ConstantIntRanges &lhs = argRanges[0], &rhs = argRanges[1];
 
-  DivisionFixupFn ceilDivUIFix = [](const APInt &lhs, const APInt &rhs,
-                                    const APInt &result) -> Optional<APInt> {
+  DivisionFixupFn ceilDivUIFix =
+      [](const APInt &lhs, const APInt &rhs,
+         const APInt &result) -> std::optional<APInt> {
     if (!lhs.urem(rhs).isZero()) {
       bool overflowed = false;
       APInt corrected =
           result.uadd_ov(APInt(result.getBitWidth(), 1), overflowed);
-      return overflowed ? Optional<APInt>() : corrected;
+      return overflowed ? std::optional<APInt>() : corrected;
     }
     return result;
   };
@@ -245,13 +254,14 @@ void arith::CeilDivSIOp::inferResultRanges(
     ArrayRef<ConstantIntRanges> argRanges, SetIntRangeFn setResultRange) {
   const ConstantIntRanges &lhs = argRanges[0], &rhs = argRanges[1];
 
-  DivisionFixupFn ceilDivSIFix = [](const APInt &lhs, const APInt &rhs,
-                                    const APInt &result) -> Optional<APInt> {
+  DivisionFixupFn ceilDivSIFix =
+      [](const APInt &lhs, const APInt &rhs,
+         const APInt &result) -> std::optional<APInt> {
     if (!lhs.srem(rhs).isZero() && lhs.isNonNegative() == rhs.isNonNegative()) {
       bool overflowed = false;
       APInt corrected =
           result.sadd_ov(APInt(result.getBitWidth(), 1), overflowed);
-      return overflowed ? Optional<APInt>() : corrected;
+      return overflowed ? std::optional<APInt>() : corrected;
     }
     return result;
   };
@@ -266,13 +276,14 @@ void arith::FloorDivSIOp::inferResultRanges(
     ArrayRef<ConstantIntRanges> argRanges, SetIntRangeFn setResultRange) {
   const ConstantIntRanges &lhs = argRanges[0], &rhs = argRanges[1];
 
-  DivisionFixupFn floorDivSIFix = [](const APInt &lhs, const APInt &rhs,
-                                     const APInt &result) -> Optional<APInt> {
+  DivisionFixupFn floorDivSIFix =
+      [](const APInt &lhs, const APInt &rhs,
+         const APInt &result) -> std::optional<APInt> {
     if (!lhs.srem(rhs).isZero() && lhs.isNonNegative() != rhs.isNonNegative()) {
       bool overflowed = false;
       APInt corrected =
           result.ssub_ov(APInt(result.getBitWidth(), 1), overflowed);
-      return overflowed ? Optional<APInt>() : corrected;
+      return overflowed ? std::optional<APInt>() : corrected;
     }
     return result;
   };
@@ -371,7 +382,7 @@ void arith::AndIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
                                       SetIntRangeFn setResultRange) {
   auto [lhsZeros, lhsOnes] = widenBitwiseBounds(argRanges[0]);
   auto [rhsZeros, rhsOnes] = widenBitwiseBounds(argRanges[1]);
-  auto andi = [](const APInt &a, const APInt &b) -> Optional<APInt> {
+  auto andi = [](const APInt &a, const APInt &b) -> std::optional<APInt> {
     return a & b;
   };
   setResultRange(getResult(),
@@ -387,7 +398,7 @@ void arith::OrIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
                                      SetIntRangeFn setResultRange) {
   auto [lhsZeros, lhsOnes] = widenBitwiseBounds(argRanges[0]);
   auto [rhsZeros, rhsOnes] = widenBitwiseBounds(argRanges[1]);
-  auto ori = [](const APInt &a, const APInt &b) -> Optional<APInt> {
+  auto ori = [](const APInt &a, const APInt &b) -> std::optional<APInt> {
     return a | b;
   };
   setResultRange(getResult(),
@@ -403,7 +414,7 @@ void arith::XOrIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
                                       SetIntRangeFn setResultRange) {
   auto [lhsZeros, lhsOnes] = widenBitwiseBounds(argRanges[0]);
   auto [rhsZeros, rhsOnes] = widenBitwiseBounds(argRanges[1]);
-  auto xori = [](const APInt &a, const APInt &b) -> Optional<APInt> {
+  auto xori = [](const APInt &a, const APInt &b) -> std::optional<APInt> {
     return a ^ b;
   };
   setResultRange(getResult(),
@@ -604,8 +615,8 @@ bool isStaticallyTrue(arith::CmpIPredicate pred, const ConstantIntRanges &lhs,
   case arith::CmpIPredicate::ugt:
     return applyCmpPredicate(pred, lhs.umin(), rhs.umax());
   case arith::CmpIPredicate::eq: {
-    Optional<APInt> lhsConst = lhs.getConstantValue();
-    Optional<APInt> rhsConst = rhs.getConstantValue();
+    std::optional<APInt> lhsConst = lhs.getConstantValue();
+    std::optional<APInt> rhsConst = rhs.getConstantValue();
     return lhsConst && rhsConst && lhsConst == rhsConst;
   }
   case arith::CmpIPredicate::ne: {
@@ -644,7 +655,7 @@ void arith::CmpIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
 
 void arith::SelectOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
                                         SetIntRangeFn setResultRange) {
-  Optional<APInt> mbCondVal = argRanges[0].getConstantValue();
+  std::optional<APInt> mbCondVal = argRanges[0].getConstantValue();
 
   if (mbCondVal) {
     if (mbCondVal->isZero())
@@ -663,8 +674,9 @@ void arith::SelectOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
 void arith::ShLIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
                                       SetIntRangeFn setResultRange) {
   const ConstantIntRanges &lhs = argRanges[0], &rhs = argRanges[1];
-  ConstArithFn shl = [](const APInt &l, const APInt &r) -> Optional<APInt> {
-    return r.uge(r.getBitWidth()) ? Optional<APInt>() : l.shl(r);
+  ConstArithFn shl = [](const APInt &l,
+                        const APInt &r) -> std::optional<APInt> {
+    return r.uge(r.getBitWidth()) ? std::optional<APInt>() : l.shl(r);
   };
   ConstantIntRanges urange =
       minMaxBy(shl, {lhs.umin(), lhs.umax()}, {rhs.umin(), rhs.umax()},
@@ -683,8 +695,9 @@ void arith::ShRUIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
                                        SetIntRangeFn setResultRange) {
   const ConstantIntRanges &lhs = argRanges[0], &rhs = argRanges[1];
 
-  ConstArithFn lshr = [](const APInt &l, const APInt &r) -> Optional<APInt> {
-    return r.uge(r.getBitWidth()) ? Optional<APInt>() : l.lshr(r);
+  ConstArithFn lshr = [](const APInt &l,
+                         const APInt &r) -> std::optional<APInt> {
+    return r.uge(r.getBitWidth()) ? std::optional<APInt>() : l.lshr(r);
   };
   setResultRange(getResult(), minMaxBy(lshr, {lhs.umin(), lhs.umax()},
                                        {rhs.umin(), rhs.umax()},
@@ -699,8 +712,9 @@ void arith::ShRSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
                                        SetIntRangeFn setResultRange) {
   const ConstantIntRanges &lhs = argRanges[0], &rhs = argRanges[1];
 
-  ConstArithFn ashr = [](const APInt &l, const APInt &r) -> Optional<APInt> {
-    return r.uge(r.getBitWidth()) ? Optional<APInt>() : l.ashr(r);
+  ConstArithFn ashr = [](const APInt &l,
+                         const APInt &r) -> std::optional<APInt> {
+    return r.uge(r.getBitWidth()) ? std::optional<APInt>() : l.ashr(r);
   };
 
   setResultRange(getResult(),

diff  --git a/mlir/lib/Dialect/Async/Transforms/AsyncToAsyncRuntime.cpp b/mlir/lib/Dialect/Async/Transforms/AsyncToAsyncRuntime.cpp
index 92bc5ee7a8665..d07204d475b32 100644
--- a/mlir/lib/Dialect/Async/Transforms/AsyncToAsyncRuntime.cpp
+++ b/mlir/lib/Dialect/Async/Transforms/AsyncToAsyncRuntime.cpp
@@ -88,7 +88,7 @@ struct CoroMachinery {
   //     %0 = arith.constant ... : T
   //     async.yield %0 : T
   //   }
-  Optional<Value> asyncToken;               // returned completion token
+  std::optional<Value> asyncToken;          // returned completion token
   llvm::SmallVector<Value, 4> returnValues; // returned async values
 
   Value coroHandle; // coroutine handle (!async.coro.getHandle value)
@@ -163,7 +163,7 @@ static CoroMachinery setupCoroMachinery(func::FuncOp func) {
   // async computations
   bool isStateful = func.getCallableResults().front().isa<TokenType>();
 
-  Optional<Value> retToken;
+  std::optional<Value> retToken;
   if (isStateful)
     retToken.emplace(builder.create<RuntimeCreateOp>(TokenType::get(ctx)));
 

diff  --git a/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
index ca9aa6890a0e6..e6f93d62fb93d 100644
--- a/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
+++ b/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
@@ -485,12 +485,12 @@ struct SimplifyClones : public OpRewritePattern<CloneOp> {
                canonicalSource.getDefiningOp()))
       canonicalSource = iface.getViewSource();
 
-    llvm::Optional<Operation *> maybeCloneDeallocOp =
+    std::optional<Operation *> maybeCloneDeallocOp =
         memref::findDealloc(cloneOp.getOutput());
     // Skip if either of them has > 1 deallocate operations.
     if (!maybeCloneDeallocOp.has_value())
       return failure();
-    llvm::Optional<Operation *> maybeSourceDeallocOp =
+    std::optional<Operation *> maybeSourceDeallocOp =
         memref::findDealloc(canonicalSource);
     if (!maybeSourceDeallocOp.has_value())
       return failure();

diff  --git a/mlir/lib/Dialect/Bufferization/Transforms/BufferUtils.cpp b/mlir/lib/Dialect/Bufferization/Transforms/BufferUtils.cpp
index 49a600400d376..38d69194be1e8 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/BufferUtils.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/BufferUtils.cpp
@@ -79,7 +79,7 @@ void BufferPlacementAllocs::build(Operation *op) {
     // Get allocation result.
     Value allocValue = allocateResultEffects[0].getValue();
     // Find the associated dealloc value and register the allocation entry.
-    llvm::Optional<Operation *> dealloc = memref::findDealloc(allocValue);
+    std::optional<Operation *> dealloc = memref::findDealloc(allocValue);
     // If the allocation has > 1 dealloc associated with it, skip handling it.
     if (!dealloc)
       return;

diff  --git a/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp b/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp
index 1bc3968f357d9..48f192a4bd759 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp
@@ -277,7 +277,7 @@ struct OneShotBufferizePass
   }
 
 private:
-  llvm::Optional<OneShotBufferizationOptions> options;
+  std::optional<OneShotBufferizationOptions> options;
 };
 } // namespace
 

diff  --git a/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
index f67cde9616306..34cdf147ca439 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
@@ -127,9 +127,9 @@ static FuncOpAnalysisState getFuncOpAnalysisState(const AnalysisState &state,
 
 /// Return the index of the bbArg in the given FuncOp that is equivalent to the
 /// specified return value (if any).
-static Optional<int64_t> getEquivalentFuncArgIdx(FuncOp funcOp,
-                                                 const FuncAnalysisState &state,
-                                                 int64_t returnValIdx) {
+static std::optional<int64_t>
+getEquivalentFuncArgIdx(FuncOp funcOp, const FuncAnalysisState &state,
+                        int64_t returnValIdx) {
   auto funcOpIt = state.equivalentFuncArgs.find(funcOp);
   if (funcOpIt == state.equivalentFuncArgs.end())
     // No equivalence info stores for funcOp.
@@ -240,7 +240,7 @@ struct CallOpInterface
     }
 
     const FuncAnalysisState &funcState = getFuncAnalysisState(state);
-    Optional<int64_t> maybeEquiv =
+    std::optional<int64_t> maybeEquiv =
         getEquivalentFuncArgIdx(funcOp, funcState, opResult.getResultNumber());
     if (maybeEquiv) {
 #ifndef NDEBUG
@@ -274,7 +274,8 @@ struct CallOpInterface
     SmallVector<Value> replacementValues(numResults, Value());
     // For non-tensor results: A mapping from return val indices of the old
     // CallOp to return val indices of the bufferized CallOp.
-    SmallVector<Optional<unsigned>> retValMapping(numResults, std::nullopt);
+    SmallVector<std::optional<unsigned>> retValMapping(numResults,
+                                                       std::nullopt);
     // Operands of the bufferized CallOp.
     SmallVector<Value> newOperands(numOperands, Value());
 

diff  --git a/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
index 2ceb2bf338109..11ec6047b19e4 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
@@ -455,7 +455,7 @@ bool canUseOpDominance(const DenseSet<OpOperand *> &usesRead,
                        const DenseSet<OpOperand *> &usesWrite,
                        const AnalysisState &state) {
   const BufferizationOptions &options = state.getOptions();
-  Optional<Region *> commonEnclosingRegion = std::nullopt;
+  std::optional<Region *> commonEnclosingRegion = std::nullopt;
 
   // In case of a write, take the region in which the write takes place.
   for (OpOperand *uWrite : usesWrite) {

diff  --git a/mlir/lib/Dialect/GPU/IR/InferIntRangeInterfaceImpls.cpp b/mlir/lib/Dialect/GPU/IR/InferIntRangeInterfaceImpls.cpp
index aacd8d57d99bb..cb2d66d5b0d32 100644
--- a/mlir/lib/Dialect/GPU/IR/InferIntRangeInterfaceImpls.cpp
+++ b/mlir/lib/Dialect/GPU/IR/InferIntRangeInterfaceImpls.cpp
@@ -53,7 +53,7 @@ static Value valueByDim(KernelDim3 dims, Dimension dim) {
 static uint64_t zext(uint32_t arg) { return static_cast<uint64_t>(arg); }
 
 template <typename Op>
-static Optional<uint64_t> getKnownLaunchDim(Op op, LaunchDims type) {
+static std::optional<uint64_t> getKnownLaunchDim(Op op, LaunchDims type) {
   Dimension dim = op.getDimension();
   if (auto launch = op->template getParentOfType<LaunchOp>()) {
     KernelDim3 bounds;
@@ -84,7 +84,8 @@ static Optional<uint64_t> getKnownLaunchDim(Op op, LaunchDims type) {
 
 void BlockDimOp::inferResultRanges(ArrayRef<ConstantIntRanges>,
                                    SetIntRangeFn setResultRange) {
-  Optional<uint64_t> knownVal = getKnownLaunchDim(*this, LaunchDims::Block);
+  std::optional<uint64_t> knownVal =
+      getKnownLaunchDim(*this, LaunchDims::Block);
   if (knownVal)
     setResultRange(getResult(), getIndexRange(*knownVal, *knownVal));
   else
@@ -99,7 +100,7 @@ void BlockIdOp::inferResultRanges(ArrayRef<ConstantIntRanges>,
 
 void GridDimOp::inferResultRanges(ArrayRef<ConstantIntRanges>,
                                   SetIntRangeFn setResultRange) {
-  Optional<uint64_t> knownVal = getKnownLaunchDim(*this, LaunchDims::Grid);
+  std::optional<uint64_t> knownVal = getKnownLaunchDim(*this, LaunchDims::Grid);
   if (knownVal)
     setResultRange(getResult(), getIndexRange(*knownVal, *knownVal));
   else

diff  --git a/mlir/lib/Dialect/GPU/Transforms/LowerMemorySpaceAttributes.cpp b/mlir/lib/Dialect/GPU/Transforms/LowerMemorySpaceAttributes.cpp
index 40c2647e9ca6b..9579111bc618e 100644
--- a/mlir/lib/Dialect/GPU/Transforms/LowerMemorySpaceAttributes.cpp
+++ b/mlir/lib/Dialect/GPU/Transforms/LowerMemorySpaceAttributes.cpp
@@ -80,7 +80,7 @@ IntegerAttr wrapNumericMemorySpace(MLIRContext *ctx, unsigned space) {
 
 void mlir::gpu::populateMemorySpaceAttributeTypeConversions(
     TypeConverter &typeConverter, const MemorySpaceMapping &mapping) {
-  typeConverter.addConversion([mapping](Type type) -> Optional<Type> {
+  typeConverter.addConversion([mapping](Type type) -> std::optional<Type> {
     auto subElementType = type.dyn_cast_or_null<SubElementTypeInterface>();
     if (!subElementType)
       return type;

diff  --git a/mlir/lib/Dialect/GPU/Transforms/SerializeToBlob.cpp b/mlir/lib/Dialect/GPU/Transforms/SerializeToBlob.cpp
index 7520e85091f5d..3c4f005e8e123 100644
--- a/mlir/lib/Dialect/GPU/Transforms/SerializeToBlob.cpp
+++ b/mlir/lib/Dialect/GPU/Transforms/SerializeToBlob.cpp
@@ -36,7 +36,7 @@ gpu::SerializeToBlobPass::SerializeToBlobPass(TypeID passID)
 gpu::SerializeToBlobPass::SerializeToBlobPass(const SerializeToBlobPass &other)
     : OperationPass<gpu::GPUModuleOp>(other) {}
 
-Optional<std::string>
+std::optional<std::string>
 gpu::SerializeToBlobPass::translateToISA(llvm::Module &llvmModule,
                                          llvm::TargetMachine &targetMachine) {
   llvmModule.setDataLayout(targetMachine.createDataLayout());
@@ -73,7 +73,7 @@ void gpu::SerializeToBlobPass::runOnOperation() {
   if (!targetMachine)
     return signalPassFailure();
 
-  Optional<std::string> maybeTargetISA =
+  std::optional<std::string> maybeTargetISA =
       translateToISA(*llvmModule, *targetMachine);
 
   if (!maybeTargetISA.has_value())

diff  --git a/mlir/lib/Dialect/GPU/Transforms/SerializeToHsaco.cpp b/mlir/lib/Dialect/GPU/Transforms/SerializeToHsaco.cpp
index 63c9aac1a0263..42cb2461395f1 100644
--- a/mlir/lib/Dialect/GPU/Transforms/SerializeToHsaco.cpp
+++ b/mlir/lib/Dialect/GPU/Transforms/SerializeToHsaco.cpp
@@ -94,7 +94,7 @@ class SerializeToHsacoPass
   void getDependentDialects(DialectRegistry &registry) const override;
 
   // Loads LLVM bitcode libraries
-  Optional<SmallVector<std::unique_ptr<llvm::Module>, 3>>
+  std::optional<SmallVector<std::unique_ptr<llvm::Module>, 3>>
   loadLibraries(SmallVectorImpl<char> &path,
                 SmallVectorImpl<StringRef> &libraries,
                 llvm::LLVMContext &context);
@@ -146,7 +146,7 @@ void SerializeToHsacoPass::getDependentDialects(
   gpu::SerializeToBlobPass::getDependentDialects(registry);
 }
 
-Optional<SmallVector<std::unique_ptr<llvm::Module>, 3>>
+std::optional<SmallVector<std::unique_ptr<llvm::Module>, 3>>
 SerializeToHsacoPass::loadLibraries(SmallVectorImpl<char> &path,
                                     SmallVectorImpl<StringRef> &libraries,
                                     llvm::LLVMContext &context) {
@@ -278,7 +278,7 @@ SerializeToHsacoPass::translateToLLVMIR(llvm::LLVMContext &llvmContext) {
   if (needOckl)
     libraries.push_back("ockl.bc");
 
-  Optional<SmallVector<std::unique_ptr<llvm::Module>, 3>> mbModules;
+  std::optional<SmallVector<std::unique_ptr<llvm::Module>, 3>> mbModules;
   std::string theRocmPath = getRocmPath();
   llvm::SmallString<32> bitcodePath(theRocmPath);
   llvm::sys::path::append(bitcodePath, "amdgcn", "bitcode");

diff  --git a/mlir/lib/Dialect/Index/IR/IndexOps.cpp b/mlir/lib/Dialect/Index/IR/IndexOps.cpp
index 8033c13ba2ff3..7f7cc50528a79 100644
--- a/mlir/lib/Dialect/Index/IR/IndexOps.cpp
+++ b/mlir/lib/Dialect/Index/IR/IndexOps.cpp
@@ -64,14 +64,15 @@ Operation *IndexDialect::materializeConstant(OpBuilder &b, Attribute value,
 /// the integer result, which in turn must satisfy the above property.
 static OpFoldResult foldBinaryOpUnchecked(
     ArrayRef<Attribute> operands,
-    function_ref<Optional<APInt>(const APInt &, const APInt &)> calculate) {
+    function_ref<std::optional<APInt>(const APInt &, const APInt &)>
+        calculate) {
   assert(operands.size() == 2 && "binary operation expected 2 operands");
   auto lhs = dyn_cast_if_present<IntegerAttr>(operands[0]);
   auto rhs = dyn_cast_if_present<IntegerAttr>(operands[1]);
   if (!lhs || !rhs)
     return {};
 
-  Optional<APInt> result = calculate(lhs.getValue(), rhs.getValue());
+  std::optional<APInt> result = calculate(lhs.getValue(), rhs.getValue());
   if (!result)
     return {};
   assert(result->trunc(32) ==
@@ -89,7 +90,8 @@ static OpFoldResult foldBinaryOpUnchecked(
 /// not folded.
 static OpFoldResult foldBinaryOpChecked(
     ArrayRef<Attribute> operands,
-    function_ref<Optional<APInt>(const APInt &, const APInt &lhs)> calculate) {
+    function_ref<std::optional<APInt>(const APInt &, const APInt &lhs)>
+        calculate) {
   assert(operands.size() == 2 && "binary operation expected 2 operands");
   auto lhs = dyn_cast_if_present<IntegerAttr>(operands[0]);
   auto rhs = dyn_cast_if_present<IntegerAttr>(operands[1]);
@@ -98,10 +100,10 @@ static OpFoldResult foldBinaryOpChecked(
     return {};
 
   // Compute the 64-bit result and the 32-bit result.
-  Optional<APInt> result64 = calculate(lhs.getValue(), rhs.getValue());
+  std::optional<APInt> result64 = calculate(lhs.getValue(), rhs.getValue());
   if (!result64)
     return {};
-  Optional<APInt> result32 =
+  std::optional<APInt> result32 =
       calculate(lhs.getValue().trunc(32), rhs.getValue().trunc(32));
   if (!result32)
     return {};
@@ -149,7 +151,7 @@ OpFoldResult MulOp::fold(FoldAdaptor adaptor) {
 OpFoldResult DivSOp::fold(FoldAdaptor adaptor) {
   return foldBinaryOpChecked(
       adaptor.getOperands(),
-      [](const APInt &lhs, const APInt &rhs) -> Optional<APInt> {
+      [](const APInt &lhs, const APInt &rhs) -> std::optional<APInt> {
         // Don't fold division by zero.
         if (rhs.isZero())
           return std::nullopt;
@@ -164,7 +166,7 @@ OpFoldResult DivSOp::fold(FoldAdaptor adaptor) {
 OpFoldResult DivUOp::fold(FoldAdaptor adaptor) {
   return foldBinaryOpChecked(
       adaptor.getOperands(),
-      [](const APInt &lhs, const APInt &rhs) -> Optional<APInt> {
+      [](const APInt &lhs, const APInt &rhs) -> std::optional<APInt> {
         // Don't fold division by zero.
         if (rhs.isZero())
           return std::nullopt;
@@ -178,7 +180,7 @@ OpFoldResult DivUOp::fold(FoldAdaptor adaptor) {
 
 /// Compute `ceildivs(n, m)` as `x = m > 0 ? -1 : 1` and then
 /// `n*m > 0 ? (n+x)/m + 1 : -(-n/m)`.
-static Optional<APInt> calculateCeilDivS(const APInt &n, const APInt &m) {
+static std::optional<APInt> calculateCeilDivS(const APInt &n, const APInt &m) {
   // Don't fold division by zero.
   if (m.isZero())
     return std::nullopt;
@@ -211,7 +213,7 @@ OpFoldResult CeilDivUOp::fold(FoldAdaptor adaptor) {
   // Compute `ceildivu(n, m)` as `n == 0 ? 0 : (n-1)/m + 1`.
   return foldBinaryOpChecked(
       adaptor.getOperands(),
-      [](const APInt &n, const APInt &m) -> Optional<APInt> {
+      [](const APInt &n, const APInt &m) -> std::optional<APInt> {
         // Don't fold division by zero.
         if (m.isZero())
           return std::nullopt;
@@ -229,7 +231,7 @@ OpFoldResult CeilDivUOp::fold(FoldAdaptor adaptor) {
 
 /// Compute `floordivs(n, m)` as `x = m < 0 ? 1 : -1` and then
 /// `n*m < 0 ? -1 - (x-n)/m : n/m`.
-static Optional<APInt> calculateFloorDivS(const APInt &n, const APInt &m) {
+static std::optional<APInt> calculateFloorDivS(const APInt &n, const APInt &m) {
   // Don't fold division by zero.
   if (m.isZero())
     return std::nullopt;
@@ -322,7 +324,7 @@ OpFoldResult MinUOp::fold(FoldAdaptor adaptor) {
 OpFoldResult ShlOp::fold(FoldAdaptor adaptor) {
   return foldBinaryOpUnchecked(
       adaptor.getOperands(),
-      [](const APInt &lhs, const APInt &rhs) -> Optional<APInt> {
+      [](const APInt &lhs, const APInt &rhs) -> std::optional<APInt> {
         // We cannot fold if the RHS is greater than or equal to 32 because
         // this would be UB in 32-bit systems but not on 64-bit systems. RHS is
         // already treated as unsigned.
@@ -339,7 +341,7 @@ OpFoldResult ShlOp::fold(FoldAdaptor adaptor) {
 OpFoldResult ShrSOp::fold(FoldAdaptor adaptor) {
   return foldBinaryOpChecked(
       adaptor.getOperands(),
-      [](const APInt &lhs, const APInt &rhs) -> Optional<APInt> {
+      [](const APInt &lhs, const APInt &rhs) -> std::optional<APInt> {
         // Don't fold if RHS is greater than or equal to 32.
         if (rhs.uge(32))
           return {};
@@ -354,7 +356,7 @@ OpFoldResult ShrSOp::fold(FoldAdaptor adaptor) {
 OpFoldResult ShrUOp::fold(FoldAdaptor adaptor) {
   return foldBinaryOpChecked(
       adaptor.getOperands(),
-      [](const APInt &lhs, const APInt &rhs) -> Optional<APInt> {
+      [](const APInt &lhs, const APInt &rhs) -> std::optional<APInt> {
         // Don't fold if RHS is greater than or equal to 32.
         if (rhs.uge(32))
           return {};

diff  --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index ca5e93fbb2e24..2f06d92192ca9 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -93,8 +93,8 @@ LoopOptionsAttrBuilder::LoopOptionsAttrBuilder(LoopOptionsAttr attr)
     : options(attr.getOptions().begin(), attr.getOptions().end()) {}
 
 template <typename T>
-LoopOptionsAttrBuilder &LoopOptionsAttrBuilder::setOption(LoopOptionCase tag,
-                                                          Optional<T> value) {
+LoopOptionsAttrBuilder &
+LoopOptionsAttrBuilder::setOption(LoopOptionCase tag, std::optional<T> value) {
   auto option = llvm::find_if(
       options, [tag](auto option) { return option.first == tag; });
   if (option != options.end()) {
@@ -109,35 +109,35 @@ LoopOptionsAttrBuilder &LoopOptionsAttrBuilder::setOption(LoopOptionCase tag,
 }
 
 LoopOptionsAttrBuilder &
-LoopOptionsAttrBuilder::setDisableLICM(Optional<bool> value) {
+LoopOptionsAttrBuilder::setDisableLICM(std::optional<bool> 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<uint64_t> count) {
+LoopOptionsAttrBuilder::setInterleaveCount(std::optional<uint64_t> 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<bool> value) {
+LoopOptionsAttrBuilder::setDisableUnroll(std::optional<bool> 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<bool> value) {
+LoopOptionsAttrBuilder::setDisablePipeline(std::optional<bool> 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<uint64_t> count) {
+    std::optional<uint64_t> count) {
   return setOption(LoopOptionCase::pipeline_initiation_interval, count);
 }
 
@@ -146,7 +146,7 @@ LoopOptionsAttrBuilder &LoopOptionsAttrBuilder::setPipelineInitiationInterval(
 //===----------------------------------------------------------------------===//
 
 template <typename T>
-static Optional<T>
+static std::optional<T>
 getOption(ArrayRef<std::pair<LoopOptionCase, int64_t>> options,
           LoopOptionCase option) {
   auto it =
@@ -158,15 +158,15 @@ getOption(ArrayRef<std::pair<LoopOptionCase, int64_t>> options,
   return static_cast<T>(it->second);
 }
 
-Optional<bool> LoopOptionsAttr::disableUnroll() {
+std::optional<bool> LoopOptionsAttr::disableUnroll() {
   return getOption<bool>(getOptions(), LoopOptionCase::disable_unroll);
 }
 
-Optional<bool> LoopOptionsAttr::disableLICM() {
+std::optional<bool> LoopOptionsAttr::disableLICM() {
   return getOption<bool>(getOptions(), LoopOptionCase::disable_licm);
 }
 
-Optional<int64_t> LoopOptionsAttr::interleaveCount() {
+std::optional<int64_t> LoopOptionsAttr::interleaveCount() {
   return getOption<int64_t>(getOptions(), LoopOptionCase::interleave_count);
 }
 

diff  --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index ac3da6336c269..54cdf98b0c3f6 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -209,7 +209,7 @@ ParseResult AllocaOp::parse(OpAsmParser &parser, OperationState &result) {
       parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type))
     return failure();
 
-  Optional<NamedAttribute> alignmentAttr =
+  std::optional<NamedAttribute> alignmentAttr =
       result.attributes.getNamed("alignment");
   if (alignmentAttr.has_value()) {
     auto alignmentInt = alignmentAttr->getValue().dyn_cast<IntegerAttr>();
@@ -782,8 +782,8 @@ void LoadOp::print(OpAsmPrinter &p) {
 // Extract the pointee type from the LLVM pointer type wrapped in MLIR. Return
 // the resulting type if any, null type if opaque pointers are used, and
 // std::nullopt if the given type is not the pointer type.
-static Optional<Type> getLoadStoreElementType(OpAsmParser &parser, Type type,
-                                              SMLoc trailingTypeLoc) {
+static std::optional<Type>
+getLoadStoreElementType(OpAsmParser &parser, Type type, SMLoc trailingTypeLoc) {
   auto llvmTy = type.dyn_cast<LLVM::LLVMPointerType>();
   if (!llvmTy) {
     parser.emitError(trailingTypeLoc, "expected LLVM pointer type");
@@ -808,7 +808,7 @@ ParseResult LoadOp::parse(OpAsmParser &parser, OperationState &result) {
       parser.resolveOperand(addr, type, result.operands))
     return failure();
 
-  Optional<Type> elemTy =
+  std::optional<Type> elemTy =
       getLoadStoreElementType(parser, type, trailingTypeLoc);
   if (!elemTy)
     return failure();
@@ -877,7 +877,7 @@ ParseResult StoreOp::parse(OpAsmParser &parser, OperationState &result) {
     if (parser.parseType(type))
       return failure();
   } else {
-    Optional<Type> maybeOperandType =
+    std::optional<Type> maybeOperandType =
         getLoadStoreElementType(parser, type, trailingTypeLoc);
     if (!maybeOperandType)
       return failure();
@@ -1993,7 +1993,7 @@ void LLVMFuncOp::build(OpBuilder &builder, OperationState &result,
                        bool dsoLocal, CConv cconv,
                        ArrayRef<NamedAttribute> attrs,
                        ArrayRef<DictionaryAttr> argAttrs,
-                       Optional<uint64_t> functionEntryCount) {
+                       std::optional<uint64_t> functionEntryCount) {
   result.addRegion();
   result.addAttribute(SymbolTable::getSymbolAttrName(),
                       builder.getStringAttr(name));
@@ -2932,7 +2932,7 @@ LogicalResult LLVMDialect::verifyOperationAttribute(Operation *op,
     if (!loopAttr)
       return op->emitOpError() << "expected '" << LLVMDialect::getLoopAttrName()
                                << "' to be a dictionary attribute";
-    Optional<NamedAttribute> parallelAccessGroup =
+    std::optional<NamedAttribute> parallelAccessGroup =
         loopAttr.getNamed(LLVMDialect::getParallelAccessAttrName());
     if (parallelAccessGroup) {
       auto accessGroups = parallelAccessGroup->getValue().dyn_cast<ArrayAttr>();
@@ -2961,7 +2961,7 @@ LogicalResult LLVMDialect::verifyOperationAttribute(Operation *op,
       }
     }
 
-    Optional<NamedAttribute> loopOptions =
+    std::optional<NamedAttribute> loopOptions =
         loopAttr.getNamed(LLVMDialect::getLoopOptionsAttrName());
     if (loopOptions && !loopOptions->getValue().isa<LoopOptionsAttr>())
       return op->emitOpError()

diff  --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp
index 3d59a6378dec3..8c27ee974df3c 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp
@@ -267,8 +267,8 @@ LLVMPointerType::verify(function_ref<InFlightDiagnostic()> emitError,
 constexpr const static unsigned kDefaultPointerSizeBits = 64;
 constexpr const static unsigned kDefaultPointerAlignment = 8;
 
-Optional<unsigned> mlir::LLVM::extractPointerSpecValue(Attribute attr,
-                                                       PtrDLEntryPos pos) {
+std::optional<unsigned> mlir::LLVM::extractPointerSpecValue(Attribute attr,
+                                                            PtrDLEntryPos pos) {
   auto spec = attr.cast<DenseIntElementsAttr>();
   auto idx = static_cast<unsigned>(pos);
   if (idx >= spec.size())
@@ -280,7 +280,7 @@ Optional<unsigned> mlir::LLVM::extractPointerSpecValue(Attribute attr,
 /// given `type` by interpreting the list of entries `params`. For the pointer
 /// type in the default address space, returns the default value if the entries
 /// do not provide a custom one, for other address spaces returns std::nullopt.
-static Optional<unsigned>
+static std::optional<unsigned>
 getPointerDataLayoutEntry(DataLayoutEntryListRef params, LLVMPointerType type,
                           PtrDLEntryPos pos) {
   // First, look for the entry for the pointer in the current address space.
@@ -312,7 +312,7 @@ getPointerDataLayoutEntry(DataLayoutEntryListRef params, LLVMPointerType type,
 unsigned
 LLVMPointerType::getTypeSizeInBits(const DataLayout &dataLayout,
                                    DataLayoutEntryListRef params) const {
-  if (Optional<unsigned> size =
+  if (std::optional<unsigned> size =
           getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Size))
     return *size;
 
@@ -325,7 +325,7 @@ LLVMPointerType::getTypeSizeInBits(const DataLayout &dataLayout,
 
 unsigned LLVMPointerType::getABIAlignment(const DataLayout &dataLayout,
                                           DataLayoutEntryListRef params) const {
-  if (Optional<unsigned> alignment =
+  if (std::optional<unsigned> alignment =
           getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Abi))
     return *alignment;
 
@@ -337,7 +337,7 @@ unsigned LLVMPointerType::getABIAlignment(const DataLayout &dataLayout,
 unsigned
 LLVMPointerType::getPreferredAlignment(const DataLayout &dataLayout,
                                        DataLayoutEntryListRef params) const {
-  if (Optional<unsigned> alignment =
+  if (std::optional<unsigned> alignment =
           getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Preferred))
     return *alignment;
 
@@ -531,7 +531,7 @@ namespace {
 enum class StructDLEntryPos { Abi = 0, Preferred = 1 };
 } // namespace
 
-static Optional<unsigned>
+static std::optional<unsigned>
 getStructDataLayoutEntry(DataLayoutEntryListRef params, LLVMStructType type,
                          StructDLEntryPos pos) {
   const auto *currentEntry =
@@ -568,7 +568,7 @@ static unsigned calculateStructAlignment(const DataLayout &dataLayout,
   }
 
   // Entries are only allowed to be stricter than the required alignment
-  if (Optional<unsigned> entryResult =
+  if (std::optional<unsigned> entryResult =
           getStructDataLayoutEntry(params, type, pos))
     return std::max(*entryResult / kBitsInByte, structAlignment);
 

diff  --git a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
index 2e3355efc78e1..60d619732e9bc 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
@@ -314,7 +314,7 @@ ParseResult MmaOp::parse(OpAsmParser &parser, OperationState &result) {
                                  "multiplicandBPtxType"};
   for (unsigned idx = 0; idx < names.size(); idx++) {
     const auto &frag = frags[idx];
-    Optional<NamedAttribute> attr = namedAttributes.getNamed(names[idx]);
+    std::optional<NamedAttribute> attr = namedAttributes.getNamed(names[idx]);
     if (!frag.elemtype.has_value() && !attr.has_value()) {
       return parser.emitError(
           parser.getNameLoc(),

diff  --git a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
index a75813750d317..e411de66da067 100644
--- a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
+++ b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
@@ -95,7 +95,7 @@ static void fillStructuredOpRegion(OpBuilder &opBuilder, Region &region,
 /// The body of the operation is filled using `regionBuilder`. All ods-gen
 /// created structured operations use the method to implement their builders.
 static void buildStructuredOp(OpBuilder &b, OperationState &state,
-                              llvm::Optional<TypeRange> resultTensorTypes,
+                              std::optional<TypeRange> resultTensorTypes,
                               ValueRange inputs, ValueRange outputs,
                               ArrayRef<NamedAttribute> attributes,
                               RegionBuilderFn regionBuilder) {
@@ -1767,7 +1767,7 @@ LogicalResult IndexOp::verify() {
 #define GET_OP_CLASSES
 #include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.cpp.inc"
 
-AffineMap mlir::linalg::extractOrIdentityMap(Optional<AffineMap> maybeMap,
+AffineMap mlir::linalg::extractOrIdentityMap(std::optional<AffineMap> maybeMap,
                                              unsigned rank,
                                              MLIRContext *context) {
   if (maybeMap)

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/ConstantFold.cpp b/mlir/lib/Dialect/Linalg/Transforms/ConstantFold.cpp
index 6162387b99b4e..1a7d7a113b22b 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/ConstantFold.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/ConstantFold.cpp
@@ -40,8 +40,8 @@ template <typename ConcreteType>
 class FoldConstantBase : public OpRewritePattern<GenericOp> {
 public:
   struct APIntOrFloat {
-    Optional<APInt> apInt;
-    Optional<APFloat> apFloat;
+    std::optional<APInt> apInt;
+    std::optional<APFloat> apFloat;
   };
   struct APIntOrFloatArray {
     SmallVector<APInt> apInts;

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp b/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp
index 0c6e9fb74a352..48053545b638e 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp
@@ -44,13 +44,13 @@ struct PackInfo {
   llvm::DenseMap<int64_t, int64_t> tileToPointMapping;
   // The permutation of outer dims (on domain).
   SmallVector<int64_t> outerDimsOnDomainPerm;
-  Optional<Value> paddingValue;
+  std::optional<Value> paddingValue;
 };
 
 static PackInfo getPackingInfoFromConsumer(
     AffineMap indexingMap, ArrayRef<OpFoldResult> innerTileSizes,
     ArrayRef<int64_t> innerDimsPos, ArrayRef<int64_t> outerDimsPerm,
-    Optional<Value> paddingValue = std::nullopt) {
+    std::optional<Value> paddingValue = std::nullopt) {
   LLVM_DEBUG(
       { llvm::dbgs() << "--- Construct PackInfo From A Consumer ---\n"; });
   PackInfo packInfo;

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp b/mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp
index 56b44e9492672..1fe0ba48c9052 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp
@@ -162,7 +162,7 @@ DecomposeLinalgOp::createPeeledGenericOp(GenericOp genericOp,
     // If the result is yielded by the original op, use the operand, indexing
     // map and result type that correspond to the yielded value.
 
-    Optional<unsigned> resultNumber;
+    std::optional<unsigned> resultNumber;
     for (auto *user : scalarOpResult.getUsers()) {
       if (auto yieldOp = dyn_cast<YieldOp>(user)) {
         // Find the first use of the `scalarOpResult` in the yield op.

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp b/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp
index de501a6a3f00a..e9a8c8326fee2 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp
@@ -713,7 +713,7 @@ static void updateExpandedGenericOpRegion(PatternRewriter &rewriter,
 /// Implements the fusion of a tensor.collapse_shape or a tensor.expand_shape op
 /// and a generic op as explained in `isFusableWithReshapeByExpansion`. Assumes
 /// that those conditions have been satisfied.
-static Optional<SmallVector<Value>>
+static std::optional<SmallVector<Value>>
 fuseWithReshapeByExpansion(GenericOp genericOp, Operation *reshapeOp,
                            OpOperand *fusableOpOperand,
                            PatternRewriter &rewriter) {
@@ -876,7 +876,7 @@ class FoldWithProducerReshapeOpByExpansion
           (!controlFoldingReshapes(opOperand)))
         continue;
 
-      Optional<SmallVector<Value>> replacementValues =
+      std::optional<SmallVector<Value>> replacementValues =
           fuseWithReshapeByExpansion(genericOp, reshapeOp, opOperand, rewriter);
       if (!replacementValues)
         return failure();
@@ -928,9 +928,11 @@ struct FoldReshapeWithGenericOpByExpansion
                                          "fusion blocked by control function");
     }
 
-    Optional<SmallVector<Value>> replacementValues = fuseWithReshapeByExpansion(
-        producer, reshapeOp,
-        producer.getDpsInitOperand(producerResult.getResultNumber()), rewriter);
+    std::optional<SmallVector<Value>> replacementValues =
+        fuseWithReshapeByExpansion(
+            producer, reshapeOp,
+            producer.getDpsInitOperand(producerResult.getResultNumber()),
+            rewriter);
     if (!replacementValues) {
       return rewriter.notifyMatchFailure(reshapeOp,
                                          "fusion by expansion failed");
@@ -1539,7 +1541,7 @@ class FoldWithProducerReshapeOpByCollapsing
         continue;
       }
 
-      Optional<SmallVector<Value>> replacements =
+      std::optional<SmallVector<Value>> replacements =
           collapseGenericOpIterationDims(genericOp, collapsableIterationDims,
                                          rewriter);
       if (!replacements) {
@@ -1573,8 +1575,9 @@ class CollapseLinalgDimensions : public OpRewritePattern<GenericOp> {
     if (collapsableIterationDims.empty())
       return failure();
 
-    Optional<SmallVector<Value>> replacements = collapseGenericOpIterationDims(
-        genericOp, collapsableIterationDims, rewriter);
+    std::optional<SmallVector<Value>> replacements =
+        collapseGenericOpIterationDims(genericOp, collapsableIterationDims,
+                                       rewriter);
     if (!replacements) {
       return rewriter.notifyMatchFailure(genericOp,
                                          "failed to collapse dimensions");

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp b/mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp
index fa04cf503766d..e3b6e67b2d0fb 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp
@@ -299,7 +299,7 @@ findFusableProducer(OpOperand &consumerOpOperand,
                                        << elem.getIndexingValue() << " and "
                                        << elem.getDependentValue() << "\n");
                Value v = elem.getIndexingValue();
-               Optional<unsigned> operandNum =
+               std::optional<unsigned> operandNum =
                    elem.getIndexingOpViewOperandNum();
                return isa<LinalgOp>(elem.getDependentOp()) &&
                       v == consumerOpOperand.get() && operandNum &&
@@ -334,8 +334,8 @@ findFusableProducer(OpOperand &consumerOpOperand,
 FailureOr<FusionInfo>
 mlir::linalg::fuseProducerOfBuffer(OpBuilder &b, OpOperand &consumerOpOperand,
                                    const LinalgDependenceGraph &graph) {
-  Optional<LinalgDependenceGraph::LinalgDependenceGraphElem> fusableDependence =
-      findFusableProducer(consumerOpOperand, graph);
+  std::optional<LinalgDependenceGraph::LinalgDependenceGraphElem>
+      fusableDependence = findFusableProducer(consumerOpOperand, graph);
   if (!fusableDependence)
     return failure();
 
@@ -348,7 +348,7 @@ mlir::linalg::fuseProducerOfBuffer(OpBuilder &b, OpOperand &consumerOpOperand,
       fusableDependence->getDependentValue().getParentBlock())
     return failure();
 
-  Optional<AffineMap> producerMap =
+  std::optional<AffineMap> producerMap =
       fusableDependence->getDependentOpViewIndexingMap();
   if (!producerMap)
     return failure();

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/FusionOnTensors.cpp b/mlir/lib/Dialect/Linalg/Transforms/FusionOnTensors.cpp
index f6bd4de019d49..8fbf8b247a99a 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/FusionOnTensors.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/FusionOnTensors.cpp
@@ -275,7 +275,7 @@ bool TileLoopNest::hasOtherUses(BlockArgument bbArg,
 LogicalResult TileLoopNest::tileRootOp(
     OpBuilder &b, ArrayRef<int64_t> tileSizes,
     ArrayRef<int64_t> tileInterchange,
-    Optional<LinalgLoopDistributionOptions> tileDistribution) {
+    std::optional<LinalgLoopDistributionOptions> tileDistribution) {
   // Exit if all tile sizes are zero.
   if (tileSizes.size() == static_cast<size_t>(count(tileSizes, 0)))
     return success();

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/SplitReduction.cpp b/mlir/lib/Dialect/Linalg/Transforms/SplitReduction.cpp
index 3df9cad8a29b3..f597273204f24 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/SplitReduction.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/SplitReduction.cpp
@@ -65,7 +65,7 @@ FailureOr<SplitReductionResult> mlir::linalg::splitReduction(
     return b.notifyMatchFailure(op, "Cannot match the reduction pattern");
 
   Operation *reductionOp = combinerOps[0];
-  Optional<Attribute> identity = getNeutralElement(reductionOp);
+  std::optional<Attribute> identity = getNeutralElement(reductionOp);
   if (!identity.has_value())
     return b.notifyMatchFailure(op, "Unknown identity value for the reduction");
 
@@ -269,7 +269,7 @@ FailureOr<SplitReductionResult> mlir::linalg::splitReductionByScaling(
 
   SmallVector<Attribute> neutralElements;
   for (Operation *reductionOp : combinerOps) {
-    Optional<Attribute> neutralElement = getNeutralElement(reductionOp);
+    std::optional<Attribute> neutralElement = getNeutralElement(reductionOp);
     if (!neutralElement.has_value())
       return b.notifyMatchFailure(op, "cannot find neutral element.");
     neutralElements.push_back(*neutralElement);

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp b/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp
index b54275045ba29..4e6777ecfcb10 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp
@@ -268,7 +268,7 @@ struct LinalgOpPartialReductionInterface
       return op->emitOpError("Failed to anaysis the reduction operation.");
 
     Operation *reductionOp = combinerOps[0];
-    Optional<Attribute> identity = getNeutralElement(reductionOp);
+    std::optional<Attribute> identity = getNeutralElement(reductionOp);
     if (!identity.has_value())
       return op->emitOpError(
           "Failed to get an identity value for the reduction operation.");

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
index f421d9a72e278..0bb31e970aa63 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
@@ -78,9 +78,9 @@ struct VectorizationState {
   /// masking. Returns the masked operation or the original operation if masking
   /// is not needed. If provided, the canonical mask for this operation is
   /// permuted using `maybeMaskingMap`.
-  Operation *maskOperation(RewriterBase &rewriter, Operation *opToMask,
-                           LinalgOp linalgOp,
-                           Optional<AffineMap> maybeMaskingMap = std::nullopt);
+  Operation *
+  maskOperation(RewriterBase &rewriter, Operation *opToMask, LinalgOp linalgOp,
+                std::optional<AffineMap> maybeMaskingMap = std::nullopt);
 
 private:
   /// Initializes the iteration space static sizes using the Linalg op
@@ -101,7 +101,7 @@ struct VectorizationState {
   /// cached for future users.
   Value getOrCreateMaskFor(RewriterBase &rewriter, Operation *opToMask,
                            LinalgOp linalgOp,
-                           Optional<AffineMap> maybeMaskingMap);
+                           std::optional<AffineMap> maybeMaskingMap);
 
   // Holds the compile-time static sizes of the iteration space to vectorize.
   // Dynamic dimensions are represented using ShapedType::kDynamicSize.
@@ -200,7 +200,7 @@ VectorizationState::initState(RewriterBase &rewriter, LinalgOp linalgOp,
 /// future users.
 Value VectorizationState::getOrCreateMaskFor(
     RewriterBase &rewriter, Operation *opToMask, LinalgOp linalgOp,
-    Optional<AffineMap> maybeMaskingMap) {
+    std::optional<AffineMap> maybeMaskingMap) {
   // No mask is needed if the operation is not maskable.
   auto maskableOp = dyn_cast<vector::MaskableOpInterface>(opToMask);
   if (!maskableOp)
@@ -279,7 +279,7 @@ Value VectorizationState::getOrCreateMaskFor(
 Operation *
 VectorizationState::maskOperation(RewriterBase &rewriter, Operation *opToMask,
                                   LinalgOp linalgOp,
-                                  Optional<AffineMap> maybeMaskingMap) {
+                                  std::optional<AffineMap> maybeMaskingMap) {
   LDBG("Trying to mask: " << *opToMask << "\n");
 
   // Create or retrieve mask for this operation.

diff  --git a/mlir/lib/Dialect/Linalg/Utils/Utils.cpp b/mlir/lib/Dialect/Linalg/Utils/Utils.cpp
index 4c3608326e0ce..e02702a0ffa7b 100644
--- a/mlir/lib/Dialect/Linalg/Utils/Utils.cpp
+++ b/mlir/lib/Dialect/Linalg/Utils/Utils.cpp
@@ -103,7 +103,7 @@ static bool isTiled(AffineMap map, ArrayRef<OpFoldResult> tileSizes) {
   return false;
 }
 
-Optional<RegionMatcher::BinaryOpKind>
+std::optional<RegionMatcher::BinaryOpKind>
 RegionMatcher::matchAsScalarBinaryOp(GenericOp op) {
   auto &region = op.getRegion();
   if (!llvm::hasSingleElement(region))
@@ -930,7 +930,7 @@ SmallVector<Value> insertSlicesBack(OpBuilder &builder, Location loc,
   return tensorResults;
 }
 
-SmallVector<Optional<SliceParameters>>
+SmallVector<std::optional<SliceParameters>>
 computeAllSliceParameters(OpBuilder &builder, Location loc, LinalgOp linalgOp,
                           ValueRange valuesToTile, ArrayRef<OpFoldResult> ivs,
                           ArrayRef<OpFoldResult> tileSizes,
@@ -951,7 +951,7 @@ computeAllSliceParameters(OpBuilder &builder, Location loc, LinalgOp linalgOp,
   assert(static_cast<int64_t>(valuesToTile.size()) <=
              linalgOp->getNumOperands() &&
          "more value to tile than operands.");
-  SmallVector<Optional<SliceParameters>> allSliceParams;
+  SmallVector<std::optional<SliceParameters>> allSliceParams;
   allSliceParams.reserve(valuesToTile.size());
   for (auto [opOperand, val] :
        llvm::zip(linalgOp->getOpOperands(), valuesToTile)) {
@@ -988,13 +988,13 @@ SmallVector<Value> makeTiledShapes(OpBuilder &builder, Location loc,
                                    ArrayRef<OpFoldResult> tileSizes,
                                    ArrayRef<OpFoldResult> sizeBounds,
                                    bool omitPartialTileCheck) {
-  SmallVector<Optional<SliceParameters>> allSliceParameter =
+  SmallVector<std::optional<SliceParameters>> allSliceParameter =
       computeAllSliceParameters(builder, loc, linalgOp, valuesToTile, ivs,
                                 tileSizes, sizeBounds, omitPartialTileCheck);
   SmallVector<Value> tiledShapes;
   for (auto item : llvm::zip(valuesToTile, allSliceParameter)) {
     Value valueToTile = std::get<0>(item);
-    Optional<SliceParameters> sliceParams = std::get<1>(item);
+    std::optional<SliceParameters> sliceParams = std::get<1>(item);
     tiledShapes.push_back(
         sliceParams.has_value()
             ? materializeTiledShape(builder, loc, valueToTile, *sliceParams)
@@ -1038,7 +1038,7 @@ void offsetIndices(RewriterBase &b, LinalgOp linalgOp,
 /// and offset is 0. Strictly speaking the offset 0 is not required in general,
 /// but non-zero offsets are not handled by SPIR-V backend at this point (and
 /// potentially cannot be handled).
-Optional<SmallVector<ReassociationIndices>>
+std::optional<SmallVector<ReassociationIndices>>
 getReassociationMapForFoldingUnitDims(ArrayRef<OpFoldResult> mixedSizes) {
   SmallVector<ReassociationIndices> reassociation;
   ReassociationIndices curr;
@@ -1061,7 +1061,7 @@ getReassociationMapForFoldingUnitDims(ArrayRef<OpFoldResult> mixedSizes) {
 }
 
 /// Return the identity numeric value associated to the give op.
-Optional<Attribute> getNeutralElement(Operation *op) {
+std::optional<Attribute> getNeutralElement(Operation *op) {
   // Builder only used as helper for attribute creation.
   OpBuilder b(op->getContext());
   Type resultType = op->getResult(0).getType();

diff  --git a/mlir/lib/Dialect/Math/IR/MathOps.cpp b/mlir/lib/Dialect/Math/IR/MathOps.cpp
index f379b4c0c10ad..0dc041420e9e9 100644
--- a/mlir/lib/Dialect/Math/IR/MathOps.cpp
+++ b/mlir/lib/Dialect/Math/IR/MathOps.cpp
@@ -46,7 +46,7 @@ OpFoldResult math::AbsIOp::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::AtanOp::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         switch (a.getSizeInBits(a.getSemantics())) {
         case 64:
           return APFloat(atan(a.convertToDouble()));
@@ -65,7 +65,7 @@ OpFoldResult math::AtanOp::fold(FoldAdaptor adaptor) {
 OpFoldResult math::Atan2Op::fold(FoldAdaptor adaptor) {
   return constFoldBinaryOpConditional<FloatAttr>(
       adaptor.getOperands(),
-      [](const APFloat &a, const APFloat &b) -> Optional<APFloat> {
+      [](const APFloat &a, const APFloat &b) -> std::optional<APFloat> {
         if (a.isZero() && b.isZero())
           return llvm::APFloat::getNaN(a.getSemantics());
 
@@ -113,7 +113,7 @@ OpFoldResult math::CopySignOp::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::CosOp::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         switch (a.getSizeInBits(a.getSemantics())) {
         case 64:
           return APFloat(cos(a.convertToDouble()));
@@ -131,7 +131,7 @@ OpFoldResult math::CosOp::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::SinOp::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         switch (a.getSizeInBits(a.getSemantics())) {
         case 64:
           return APFloat(sin(a.convertToDouble()));
@@ -182,7 +182,7 @@ OpFoldResult math::CtPopOp::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::ErfOp::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         switch (a.getSizeInBits(a.getSemantics())) {
         case 64:
           return APFloat(erf(a.convertToDouble()));
@@ -201,7 +201,7 @@ OpFoldResult math::ErfOp::fold(FoldAdaptor adaptor) {
 OpFoldResult math::IPowIOp::fold(FoldAdaptor adaptor) {
   return constFoldBinaryOpConditional<IntegerAttr>(
       adaptor.getOperands(),
-      [](const APInt &base, const APInt &power) -> Optional<APInt> {
+      [](const APInt &base, const APInt &power) -> std::optional<APInt> {
         unsigned width = base.getBitWidth();
         auto zeroValue = APInt::getZero(width);
         APInt oneValue{width, 1ULL, /*isSigned=*/true};
@@ -251,7 +251,7 @@ OpFoldResult math::IPowIOp::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::LogOp::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         if (a.isNegative())
           return {};
 
@@ -271,7 +271,7 @@ OpFoldResult math::LogOp::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::Log2Op::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         if (a.isNegative())
           return {};
 
@@ -291,7 +291,7 @@ OpFoldResult math::Log2Op::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::Log10Op::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         if (a.isNegative())
           return {};
 
@@ -312,7 +312,7 @@ OpFoldResult math::Log10Op::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::Log1pOp::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         switch (a.getSizeInBits(a.getSemantics())) {
         case 64:
           if ((a + APFloat(1.0)).isNegative())
@@ -335,7 +335,7 @@ OpFoldResult math::Log1pOp::fold(FoldAdaptor adaptor) {
 OpFoldResult math::PowFOp::fold(FoldAdaptor adaptor) {
   return constFoldBinaryOpConditional<FloatAttr>(
       adaptor.getOperands(),
-      [](const APFloat &a, const APFloat &b) -> Optional<APFloat> {
+      [](const APFloat &a, const APFloat &b) -> std::optional<APFloat> {
         if (a.getSizeInBits(a.getSemantics()) == 64 &&
             b.getSizeInBits(b.getSemantics()) == 64)
           return APFloat(pow(a.convertToDouble(), b.convertToDouble()));
@@ -354,7 +354,7 @@ OpFoldResult math::PowFOp::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::SqrtOp::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         if (a.isNegative())
           return {};
 
@@ -375,7 +375,7 @@ OpFoldResult math::SqrtOp::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::ExpOp::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         switch (a.getSizeInBits(a.getSemantics())) {
         case 64:
           return APFloat(exp(a.convertToDouble()));
@@ -393,7 +393,7 @@ OpFoldResult math::ExpOp::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::Exp2Op::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         switch (a.getSizeInBits(a.getSemantics())) {
         case 64:
           return APFloat(exp2(a.convertToDouble()));
@@ -411,7 +411,7 @@ OpFoldResult math::Exp2Op::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::ExpM1Op::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         switch (a.getSizeInBits(a.getSemantics())) {
         case 64:
           return APFloat(expm1(a.convertToDouble()));
@@ -429,7 +429,7 @@ OpFoldResult math::ExpM1Op::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::TanOp::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         switch (a.getSizeInBits(a.getSemantics())) {
         case 64:
           return APFloat(tan(a.convertToDouble()));
@@ -447,7 +447,7 @@ OpFoldResult math::TanOp::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::TanhOp::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         switch (a.getSizeInBits(a.getSemantics())) {
         case 64:
           return APFloat(tanh(a.convertToDouble()));
@@ -491,7 +491,7 @@ OpFoldResult math::FloorOp::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::RoundOp::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         switch (a.getSizeInBits(a.getSemantics())) {
         case 64:
           return APFloat(round(a.convertToDouble()));
@@ -509,7 +509,7 @@ OpFoldResult math::RoundOp::fold(FoldAdaptor adaptor) {
 
 OpFoldResult math::TruncOp::fold(FoldAdaptor adaptor) {
   return constFoldUnaryOpConditional<FloatAttr>(
-      adaptor.getOperands(), [](const APFloat &a) -> Optional<APFloat> {
+      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
         switch (a.getSizeInBits(a.getSemantics())) {
         case 64:
           return APFloat(trunc(a.convertToDouble()));

diff  --git a/mlir/lib/Dialect/MemRef/IR/MemRefDialect.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefDialect.cpp
index 021f7ecfe2408..f5ddc94545985 100644
--- a/mlir/lib/Dialect/MemRef/IR/MemRefDialect.cpp
+++ b/mlir/lib/Dialect/MemRef/IR/MemRefDialect.cpp
@@ -44,7 +44,7 @@ void mlir::memref::MemRefDialect::initialize() {
 }
 
 /// Finds the unique dealloc operation (if one exists) for `allocValue`.
-llvm::Optional<Operation *> mlir::memref::findDealloc(Value allocValue) {
+std::optional<Operation *> mlir::memref::findDealloc(Value allocValue) {
   Operation *dealloc = nullptr;
   for (Operation *user : allocValue.getUsers()) {
     if (!hasEffect<MemoryEffects::Free>(user, allocValue))

diff  --git a/mlir/lib/Dialect/MemRef/Transforms/ExpandStridedMetadata.cpp b/mlir/lib/Dialect/MemRef/Transforms/ExpandStridedMetadata.cpp
index 06c9c657a34db..71c99e9174ea6 100644
--- a/mlir/lib/Dialect/MemRef/Transforms/ExpandStridedMetadata.cpp
+++ b/mlir/lib/Dialect/MemRef/Transforms/ExpandStridedMetadata.cpp
@@ -174,7 +174,7 @@ getExpandedSizes(memref::ExpandShapeOp expandShape, OpBuilder &builder,
   SmallVector<OpFoldResult> expandedSizes(groupSize);
 
   uint64_t productOfAllStaticSizes = 1;
-  Optional<unsigned> dynSizeIdx;
+  std::optional<unsigned> dynSizeIdx;
   MemRefType expandShapeType = expandShape.getResultType();
 
   // Fill up all the statically known sizes.
@@ -239,7 +239,7 @@ SmallVector<OpFoldResult> getExpandedStrides(memref::ExpandShapeOp expandShape,
   unsigned groupSize = reassocGroup.size();
   MemRefType expandShapeType = expandShape.getResultType();
 
-  Optional<int64_t> dynSizeIdx;
+  std::optional<int64_t> dynSizeIdx;
 
   // Fill up the expanded strides, with the information we can deduce from the
   // resulting shape.

diff  --git a/mlir/lib/Dialect/PDL/IR/PDL.cpp b/mlir/lib/Dialect/PDL/IR/PDL.cpp
index 511cae630bd5e..a450386fef722 100644
--- a/mlir/lib/Dialect/PDL/IR/PDL.cpp
+++ b/mlir/lib/Dialect/PDL/IR/PDL.cpp
@@ -207,7 +207,7 @@ static LogicalResult verifyResultTypesAreInferrable(OperationOp op,
     std::optional<StringRef> rawOpName = op.getOpName();
     if (!rawOpName)
       return success();
-    Optional<RegisteredOperationName> opName =
+    std::optional<RegisteredOperationName> opName =
         RegisteredOperationName::lookup(*rawOpName, op.getContext());
     if (!opName)
       return success();
@@ -382,7 +382,8 @@ LogicalResult PatternOp::verifyRegions() {
 }
 
 void PatternOp::build(OpBuilder &builder, OperationState &state,
-                      Optional<uint16_t> benefit, Optional<StringRef> name) {
+                      std::optional<uint16_t> benefit,
+                      std::optional<StringRef> name) {
   build(builder, state, builder.getI16IntegerAttr(benefit ? *benefit : 0),
         name ? builder.getStringAttr(*name) : StringAttr());
   state.regions[0]->emplaceBlock();

diff  --git a/mlir/lib/Dialect/SCF/Transforms/StructuralTypeConversions.cpp b/mlir/lib/Dialect/SCF/Transforms/StructuralTypeConversions.cpp
index e2454a0b9a755..487aa0d7cf6a5 100644
--- a/mlir/lib/Dialect/SCF/Transforms/StructuralTypeConversions.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/StructuralTypeConversions.cpp
@@ -48,7 +48,7 @@ class Structural1ToNConversionPattern : public OpConversionPattern<SourceOp> {
   // actual conversion. It should return std::nullopt upon conversion failure
   // and return the converted operation upon success.
   //
-  // Optional<SourceOp> convertSourceOp(SourceOp op, OpAdaptor adaptor,
+  // std::optional<SourceOp> convertSourceOp(SourceOp op, OpAdaptor adaptor,
   //                                    ConversionPatternRewriter &rewriter,
   //                                    TypeRange dstTypes) const;
 
@@ -66,7 +66,7 @@ class Structural1ToNConversionPattern : public OpConversionPattern<SourceOp> {
     }
 
     // Calls the actual converter implementation to convert the operation.
-    Optional<SourceOp> newOp =
+    std::optional<SourceOp> newOp =
         static_cast<const ConcretePattern *>(this)->convertSourceOp(
             op, adaptor, rewriter, dstTypes);
 
@@ -106,9 +106,9 @@ class ConvertForOpTypes
   using Structural1ToNConversionPattern::Structural1ToNConversionPattern;
 
   // The callback required by CRTP.
-  Optional<ForOp> convertSourceOp(ForOp op, OpAdaptor adaptor,
-                                  ConversionPatternRewriter &rewriter,
-                                  TypeRange dstTypes) const {
+  std::optional<ForOp> convertSourceOp(ForOp op, OpAdaptor adaptor,
+                                       ConversionPatternRewriter &rewriter,
+                                       TypeRange dstTypes) const {
     // Create a empty new op and inline the regions from the old op.
     //
     // This is a little bit tricky. We have two concerns here:
@@ -161,9 +161,9 @@ class ConvertIfOpTypes
 public:
   using Structural1ToNConversionPattern::Structural1ToNConversionPattern;
 
-  Optional<IfOp> convertSourceOp(IfOp op, OpAdaptor adaptor,
-                                 ConversionPatternRewriter &rewriter,
-                                 TypeRange dstTypes) const {
+  std::optional<IfOp> convertSourceOp(IfOp op, OpAdaptor adaptor,
+                                      ConversionPatternRewriter &rewriter,
+                                      TypeRange dstTypes) const {
 
     IfOp newOp = rewriter.create<IfOp>(op.getLoc(), dstTypes,
                                        adaptor.getCondition(), true);
@@ -190,9 +190,9 @@ class ConvertWhileOpTypes
 public:
   using Structural1ToNConversionPattern::Structural1ToNConversionPattern;
 
-  Optional<WhileOp> convertSourceOp(WhileOp op, OpAdaptor adaptor,
-                                    ConversionPatternRewriter &rewriter,
-                                    TypeRange dstTypes) const {
+  std::optional<WhileOp> convertSourceOp(WhileOp op, OpAdaptor adaptor,
+                                         ConversionPatternRewriter &rewriter,
+                                         TypeRange dstTypes) const {
     // Unpacked the iteration arguments.
     SmallVector<Value> flatArgs;
     for (Value arg : adaptor.getOperands())

diff  --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp
index 1fa45cbdf97d8..37b9051bfee9b 100644
--- a/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp
@@ -29,7 +29,7 @@ using namespace mlir;
 
 /// Returns the boolean value under the hood if the given `boolAttr` is a scalar
 /// or splat vector bool constant.
-static Optional<bool> getScalarOrSplatBoolAttr(Attribute attr) {
+static std::optional<bool> getScalarOrSplatBoolAttr(Attribute attr) {
   if (!attr)
     return std::nullopt;
 
@@ -237,7 +237,8 @@ OpFoldResult spirv::ISubOp::fold(FoldAdaptor adaptor) {
 //===----------------------------------------------------------------------===//
 
 OpFoldResult spirv::LogicalAndOp::fold(FoldAdaptor adaptor) {
-  if (Optional<bool> rhs = getScalarOrSplatBoolAttr(adaptor.getOperand2())) {
+  if (std::optional<bool> rhs =
+          getScalarOrSplatBoolAttr(adaptor.getOperand2())) {
     // x && true = x
     if (*rhs)
       return getOperand1();
@@ -255,7 +256,8 @@ OpFoldResult spirv::LogicalAndOp::fold(FoldAdaptor adaptor) {
 //===----------------------------------------------------------------------===//
 
 OpFoldResult spirv::LogicalNotEqualOp::fold(FoldAdaptor adaptor) {
-  if (Optional<bool> rhs = getScalarOrSplatBoolAttr(adaptor.getOperand2())) {
+  if (std::optional<bool> rhs =
+          getScalarOrSplatBoolAttr(adaptor.getOperand2())) {
     // x && false = x
     if (!rhs.value())
       return getOperand1();

diff  --git a/mlir/lib/Dialect/SPIRV/IR/TargetAndABI.cpp b/mlir/lib/Dialect/SPIRV/IR/TargetAndABI.cpp
index 42ded31b69022..74fb705c42ac1 100644
--- a/mlir/lib/Dialect/SPIRV/IR/TargetAndABI.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/TargetAndABI.cpp
@@ -48,7 +48,7 @@ bool spirv::TargetEnv::allows(spirv::Capability capability) const {
   return givenCapabilities.count(capability);
 }
 
-Optional<spirv::Capability>
+std::optional<spirv::Capability>
 spirv::TargetEnv::allows(ArrayRef<spirv::Capability> caps) const {
   const auto *chosen = llvm::find_if(caps, [this](spirv::Capability cap) {
     return givenCapabilities.count(cap);
@@ -62,7 +62,7 @@ bool spirv::TargetEnv::allows(spirv::Extension extension) const {
   return givenExtensions.count(extension);
 }
 
-Optional<spirv::Extension>
+std::optional<spirv::Extension>
 spirv::TargetEnv::allows(ArrayRef<spirv::Extension> exts) const {
   const auto *chosen = llvm::find_if(exts, [this](spirv::Extension ext) {
     return givenExtensions.count(ext);

diff  --git a/mlir/lib/Dialect/SPIRV/Transforms/UpdateVCEPass.cpp b/mlir/lib/Dialect/SPIRV/Transforms/UpdateVCEPass.cpp
index 027bfab19a473..6e09a848c494e 100644
--- a/mlir/lib/Dialect/SPIRV/Transforms/UpdateVCEPass.cpp
+++ b/mlir/lib/Dialect/SPIRV/Transforms/UpdateVCEPass.cpp
@@ -54,7 +54,7 @@ static LogicalResult checkAndUpdateExtensionRequirements(
     const spirv::SPIRVType::ExtensionArrayRefVector &candidates,
     SetVector<spirv::Extension> &deducedExtensions) {
   for (const auto &ors : candidates) {
-    if (Optional<spirv::Extension> chosen = targetEnv.allows(ors)) {
+    if (std::optional<spirv::Extension> chosen = targetEnv.allows(ors)) {
       deducedExtensions.insert(*chosen);
     } else {
       SmallVector<StringRef, 4> extStrings;
@@ -82,7 +82,7 @@ static LogicalResult checkAndUpdateCapabilityRequirements(
     const spirv::SPIRVType::CapabilityArrayRefVector &candidates,
     SetVector<spirv::Capability> &deducedCapabilities) {
   for (const auto &ors : candidates) {
-    if (Optional<spirv::Capability> chosen = targetEnv.allows(ors)) {
+    if (std::optional<spirv::Capability> chosen = targetEnv.allows(ors)) {
       deducedCapabilities.insert(*chosen);
     } else {
       SmallVector<StringRef, 4> capStrings;

diff  --git a/mlir/lib/Dialect/SparseTensor/Transforms/CodegenEnv.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/CodegenEnv.cpp
index d89f532250b69..d844999f553f3 100644
--- a/mlir/lib/Dialect/SparseTensor/Transforms/CodegenEnv.cpp
+++ b/mlir/lib/Dialect/SparseTensor/Transforms/CodegenEnv.cpp
@@ -45,8 +45,8 @@ void CodegenEnv::startEmit(OpOperand *so, unsigned lv) {
                          /*isSparseOut=*/sparseOut != nullptr, topSort);
 }
 
-Optional<Operation *> CodegenEnv::genLoopBoundary(
-    function_ref<Optional<Operation *>(MutableArrayRef<Value> parameters)>
+std::optional<Operation *> CodegenEnv::genLoopBoundary(
+    function_ref<std::optional<Operation *>(MutableArrayRef<Value> parameters)>
         callback) {
   SmallVector<Value> params;
   if (isReduc())

diff  --git a/mlir/lib/Dialect/SparseTensor/Transforms/CodegenEnv.h b/mlir/lib/Dialect/SparseTensor/Transforms/CodegenEnv.h
index 341cfb9dbb275..853ee4dc51fd1 100644
--- a/mlir/lib/Dialect/SparseTensor/Transforms/CodegenEnv.h
+++ b/mlir/lib/Dialect/SparseTensor/Transforms/CodegenEnv.h
@@ -53,9 +53,10 @@ class CodegenEnv {
 
   /// Generates loop boundary statements (entering/exiting loops). The function
   /// passes and updates the passed-in parameters.
-  Optional<Operation *> genLoopBoundary(
-      function_ref<Optional<Operation *>(MutableArrayRef<Value> parameters)>
-          callback);
+  std::optional<Operation *>
+  genLoopBoundary(function_ref<
+                  std::optional<Operation *>(MutableArrayRef<Value> parameters)>
+                      callback);
 
   //
   // Merger delegates.

diff  --git a/mlir/lib/Dialect/SparseTensor/Transforms/CodegenUtils.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/CodegenUtils.cpp
index fd91078e44ba0..9466f6f147538 100644
--- a/mlir/lib/Dialect/SparseTensor/Transforms/CodegenUtils.cpp
+++ b/mlir/lib/Dialect/SparseTensor/Transforms/CodegenUtils.cpp
@@ -25,7 +25,7 @@ using namespace mlir::sparse_tensor;
 
 /// If the tensor is a sparse constant, generates and returns the pair of
 /// the constants for the indices and the values.
-static Optional<std::pair<Value, Value>>
+static std::optional<std::pair<Value, Value>>
 genSplitSparseConstant(OpBuilder &builder, Location loc, Value tensor) {
   if (auto constOp = tensor.getDefiningOp<arith::ConstantOp>()) {
     if (auto attr = constOp.getValue().dyn_cast<SparseElementsAttr>()) {

diff  --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseStorageSpecifierToLLVM.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseStorageSpecifierToLLVM.cpp
index e900936f894b8..d5d9dab22fb45 100644
--- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseStorageSpecifierToLLVM.cpp
+++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseStorageSpecifierToLLVM.cpp
@@ -140,7 +140,7 @@ class SpecifierGetterSetterOpConverter : public OpConversionPattern<SourceOp> {
     } else {
       auto enc = op.getSpecifier().getType().getEncoding();
       StorageLayout layout(enc);
-      Optional<unsigned> dim = std::nullopt;
+      std::optional<unsigned> dim = std::nullopt;
       if (op.getDim())
         dim = op.getDim().value().getZExtValue();
       unsigned idx = layout.getMemRefFieldIndex(op.getSpecifierKind(), dim);

diff  --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp
index ab85c5fa2fb02..975403ee739e4 100644
--- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp
+++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp
@@ -134,8 +134,9 @@ Value sizeAtStoredDim(OpBuilder &builder, Location loc,
 
 static void createPushback(OpBuilder &builder, Location loc,
                            MutSparseTensorDescriptor desc,
-                           SparseTensorFieldKind kind, Optional<unsigned> dim,
-                           Value value, Value repeat = Value()) {
+                           SparseTensorFieldKind kind,
+                           std::optional<unsigned> dim, Value value,
+                           Value repeat = Value()) {
   Type etp = desc.getMemRefElementType(kind, dim);
   Value field = desc.getMemRefField(kind, dim);
   StorageSpecifierKind specFieldKind = toSpecifierKind(kind);

diff  --git a/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp
index 59f956f1f1106..719b1c68ed40d 100644
--- a/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp
+++ b/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp
@@ -346,8 +346,8 @@ static bool topSortOptimal(CodegenEnv &env, unsigned n,
 /// tidx < a = (i0 + i1) => tidx < i0, tidx < i1.
 static void addAffineOrderings(std::vector<std::vector<bool>> &adjM,
                                std::vector<unsigned> &inDegree, AffineExpr a,
-                               AffineExpr b, Optional<unsigned> fidx,
-                               Optional<unsigned> tidx) {
+                               AffineExpr b, std::optional<unsigned> fidx,
+                               std::optional<unsigned> tidx) {
   if (!a && !b) {
     // Recursion leaf.
     assert(fidx && tidx);
@@ -387,9 +387,9 @@ static void addAffineOrderings(std::vector<std::vector<bool>> &adjM,
 }
 
 static void tryLoosenAffineDenseConstraints(linalg::GenericOp op,
-                                            Optional<unsigned> &fldx,
+                                            std::optional<unsigned> &fldx,
                                             AffineExpr &fa,
-                                            Optional<unsigned> &tldx,
+                                            std::optional<unsigned> &tldx,
                                             AffineExpr &ta) {
   // We use a heuristic here to only pick one dim expression from each
   // compound affine expression to establish the order between two dense
@@ -449,7 +449,7 @@ static bool computeIterationGraph(CodegenEnv &env, unsigned mask,
     // on the loop indices if no explicit dimension ordering is given.
     for (unsigned d = 0, rank = map.getNumResults(); d < rank; d++) {
       AffineExpr ta = map.getResult(toOrigDim(enc, d));
-      Optional<unsigned> tldx =
+      std::optional<unsigned> tldx =
           env.merger().getLoopIdx(t.getOperandNumber(), d);
 
       // Filter loops should be constructed after all the dependent loops,
@@ -473,7 +473,7 @@ static bool computeIterationGraph(CodegenEnv &env, unsigned mask,
 
       if (d > 0) {
         AffineExpr fa = map.getResult(toOrigDim(enc, d - 1));
-        Optional<unsigned> fldx =
+        std::optional<unsigned> fldx =
             env.merger().getLoopIdx(t.getOperandNumber(), d - 1);
 
         // Applying order constraints on every pair of dimExpr between two
@@ -916,7 +916,7 @@ static void genInvariants(CodegenEnv &env, OpBuilder &builder, unsigned exp,
     auto enc = getSparseTensorEncoding(t.get().getType());
     for (unsigned d = 0, rank = map.getNumResults(); d < rank; d++) {
       AffineExpr a = map.getResult(toOrigDim(enc, d));
-      Optional<unsigned> sldx =
+      std::optional<unsigned> sldx =
           env.merger().getLoopIdx(t.getOperandNumber(), d);
       if (sldx && env.merger().isFilterLoop(*sldx)) {
         if (!env.getLoopIdxValue(*sldx))
@@ -1202,8 +1202,8 @@ static bool startLoopSeq(CodegenEnv &env, OpBuilder &builder, unsigned exp,
   SmallVector<size_t> tids;
   SmallVector<size_t> dims;
   env.merger().foreachTidDimPairInBits(
-      env.lat(l0).bits,
-      [&](unsigned b, unsigned tid, Optional<unsigned> dim, DimLevelType dlt) {
+      env.lat(l0).bits, [&](unsigned b, unsigned tid,
+                            std::optional<unsigned> dim, DimLevelType dlt) {
         assert(env.merger().index(b) == idx);
         if (isDenseDLT(dlt) || isUndefDLT(dlt)) {
           needsUniv = true;
@@ -1271,9 +1271,10 @@ static bool translateBitsToTidDimPairs(
 
   unsigned numloopCond = 0;
   // Converts bits to array + dim pair
-  env.merger().foreachTidDimPairInBits(all, [&, idx](unsigned b, unsigned tid,
-                                                     Optional<unsigned> dim,
-                                                     DimLevelType dlt) {
+  env.merger().foreachTidDimPairInBits(all, [&,
+                                             idx](unsigned b, unsigned tid,
+                                                  std::optional<unsigned> dim,
+                                                  DimLevelType dlt) {
     if (simple.test(b)) {
       if (isUndefDLT(dlt)) {
         // An undefined dlt in the lattices, we probably mean to iterate based
@@ -1528,7 +1529,7 @@ struct GenericOpSparsifier : public OpRewritePattern<linalg::GenericOp> {
       return failure();
 
     // Builds the tensor expression for the Linalg operation in SSA form.
-    Optional<unsigned> optExp = env.merger().buildTensorExpFromLinalg(op);
+    std::optional<unsigned> optExp = env.merger().buildTensorExpFromLinalg(op);
     if (!optExp)
       return failure();
     unsigned exp = *optExp;

diff  --git a/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp b/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp
index 1d06570e82778..a0892b25e2c7b 100644
--- a/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp
+++ b/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp
@@ -211,10 +211,10 @@ Merger::Merger(unsigned t, unsigned l, unsigned fl)
       numNativeLoops(l), numLoops(l + fl), hasSparseOut(false),
       dimTypes(numTensors,
                std::vector<DimLevelType>(numLoops, DimLevelType::Undef)),
-      loopIdxToDim(numTensors,
-                   std::vector<Optional<unsigned>>(numLoops, std::nullopt)),
-      dimToLoopIdx(numTensors,
-                   std::vector<Optional<unsigned>>(numLoops, std::nullopt)) {}
+      loopIdxToDim(numTensors, std::vector<std::optional<unsigned>>(
+                                   numLoops, std::nullopt)),
+      dimToLoopIdx(numTensors, std::vector<std::optional<unsigned>>(
+                                   numLoops, std::nullopt)) {}
 
 //===----------------------------------------------------------------------===//
 // Lattice methods.
@@ -958,7 +958,7 @@ unsigned Merger::buildLattices(unsigned e, unsigned i) {
   llvm_unreachable("unexpected expression kind");
 }
 
-Optional<unsigned> Merger::buildTensorExpFromLinalg(linalg::GenericOp op) {
+std::optional<unsigned> Merger::buildTensorExpFromLinalg(linalg::GenericOp op) {
   // Build the linalg semantics backward from yield.
   Operation *yield = op.getRegion().front().getTerminator();
   assert(isa<linalg::YieldOp>(yield));
@@ -1025,7 +1025,7 @@ static bool isAdmissibleBranch(Operation *op, Region &region) {
   return isAdmissibleBranchExp(op, &region.front(), yield->getOperand(0));
 }
 
-Optional<unsigned> Merger::buildTensorExp(linalg::GenericOp op, Value v) {
+std::optional<unsigned> Merger::buildTensorExp(linalg::GenericOp op, Value v) {
   if (auto arg = v.dyn_cast<BlockArgument>()) {
     unsigned argN = arg.getArgNumber();
     // Any argument of the generic op that is not marked as a scalar

diff  --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp
index 55e53644bf5ef..18ffbe32703dd 100644
--- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp
+++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp
@@ -3248,7 +3248,7 @@ void PackOp::getAsmResultNames(function_ref<void(Value, StringRef)> setNameFn) {
 void PackOp::build(OpBuilder &builder, OperationState &state, Value source,
                    Value dest, ArrayRef<int64_t> innerDimsPos,
                    ArrayRef<OpFoldResult> innerTiles,
-                   Optional<Value> paddingValue,
+                   std::optional<Value> paddingValue,
                    ArrayRef<int64_t> outerDimsPerm) {
   assert(innerDimsPos.size() == innerTiles.size() &&
          "number of tile sizes specified must match the specified number of "

diff  --git a/mlir/lib/Dialect/Traits.cpp b/mlir/lib/Dialect/Traits.cpp
index fb4374eae6432..a1a30325258cf 100644
--- a/mlir/lib/Dialect/Traits.cpp
+++ b/mlir/lib/Dialect/Traits.cpp
@@ -32,7 +32,7 @@ bool OpTrait::util::staticallyKnownBroadcastable(
   // We look backwards through every column of `shapes`.
   for (size_t i = 0; i != maxRank; ++i) {
     bool seenDynamic = false;
-    Optional<int64_t> nonOneDim;
+    std::optional<int64_t> nonOneDim;
     for (ArrayRef<int64_t> extent : shapes) {
       int64_t dim = i >= extent.size() ? 1 : extent[extent.size() - i - 1];
 
@@ -150,16 +150,16 @@ Type OpTrait::util::getBroadcastedType(Type type1, Type type2,
 
   // Returns the type kind if the given type is a vector or ranked tensor type.
   // Returns std::nullopt otherwise.
-  auto getCompositeTypeKind = [](Type type) -> Optional<TypeID> {
+  auto getCompositeTypeKind = [](Type type) -> std::optional<TypeID> {
     if (type.isa<VectorType, RankedTensorType>())
       return type.getTypeID();
     return std::nullopt;
   };
 
   // Make sure the composite type, if has, is consistent.
-  Optional<TypeID> compositeKind1 = getCompositeTypeKind(type1);
-  Optional<TypeID> compositeKind2 = getCompositeTypeKind(type2);
-  Optional<TypeID> resultCompositeKind;
+  std::optional<TypeID> compositeKind1 = getCompositeTypeKind(type1);
+  std::optional<TypeID> compositeKind2 = getCompositeTypeKind(type2);
+  std::optional<TypeID> resultCompositeKind;
 
   if (compositeKind1 && compositeKind2) {
     // Disallow mixing vector and tensor.

diff  --git a/mlir/lib/Dialect/Utils/IndexingUtils.cpp b/mlir/lib/Dialect/Utils/IndexingUtils.cpp
index 71ff38fffd99c..4563d74acfde4 100644
--- a/mlir/lib/Dialect/Utils/IndexingUtils.cpp
+++ b/mlir/lib/Dialect/Utils/IndexingUtils.cpp
@@ -32,7 +32,7 @@ SmallVector<int64_t> mlir::computeElementwiseMul(ArrayRef<int64_t> v1,
   return result;
 }
 
-Optional<SmallVector<int64_t>>
+std::optional<SmallVector<int64_t>>
 mlir::computeShapeRatio(ArrayRef<int64_t> shape, ArrayRef<int64_t> subShape) {
   if (shape.size() < subShape.size())
     return std::nullopt;

diff  --git a/mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp b/mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp
index 2e6499f7f3ba0..e022e5f47ea22 100644
--- a/mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp
+++ b/mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp
@@ -16,7 +16,7 @@
 
 using namespace mlir;
 
-Optional<SmallVector<ReassociationIndices>>
+std::optional<SmallVector<ReassociationIndices>>
 mlir::getReassociationIndicesForReshape(ShapedType sourceType,
                                         ShapedType targetType) {
   if (sourceType.getRank() > targetType.getRank())
@@ -28,7 +28,7 @@ mlir::getReassociationIndicesForReshape(ShapedType sourceType,
   return std::nullopt;
 }
 
-Optional<SmallVector<ReassociationIndices>>
+std::optional<SmallVector<ReassociationIndices>>
 mlir::getReassociationIndicesForCollapse(ArrayRef<int64_t> sourceShape,
                                          ArrayRef<int64_t> targetShape) {
   if (sourceShape.size() <= targetShape.size())
@@ -93,7 +93,8 @@ mlir::getReassociationIndicesForCollapse(ArrayRef<int64_t> sourceShape,
   return reassociationMap;
 }
 
-Optional<SmallVector<ReassociationIndices>> mlir::composeReassociationIndices(
+std::optional<SmallVector<ReassociationIndices>>
+mlir::composeReassociationIndices(
     ArrayRef<ReassociationIndices> producerReassociations,
     ArrayRef<ReassociationIndices> consumerReassociations,
     MLIRContext *context) {
@@ -356,10 +357,10 @@ SliceFromCollapseHelper::getInsertSliceParams(MLIRContext *ctx,
 /// Returns the index of the only non-unit dimension among `indices` of `shape`,
 /// if such a dimension exists and `indices` has more than one element.
 /// Otherwise, return none.
-static Optional<int64_t> getUniqueNonUnitDim(ArrayRef<int64_t> indices,
-                                             ArrayRef<int64_t> shape) {
+static std::optional<int64_t> getUniqueNonUnitDim(ArrayRef<int64_t> indices,
+                                                  ArrayRef<int64_t> shape) {
   // Return false if more than one of the dimensions in this group are not 1.
-  Optional<int64_t> dimIndex = std::nullopt;
+  std::optional<int64_t> dimIndex = std::nullopt;
   if (indices.size() < 2)
     return std::nullopt;
   for (int64_t idx : indices) {
@@ -375,10 +376,10 @@ static Optional<int64_t> getUniqueNonUnitDim(ArrayRef<int64_t> indices,
 // For each segment in the reassociation indices, check whether we can
 // simplify that segment with a rank-reducing extract slice. We can do this if
 // all but (exactly) one of the corresponding source dims is 1.
-static SmallVector<Optional<int64_t>> getCollapseShapeTrivialSegments(
+static SmallVector<std::optional<int64_t>> getCollapseShapeTrivialSegments(
     RankedTensorType sourceType,
     ArrayRef<ReassociationIndices> reassociationIndices) {
-  SmallVector<Optional<int64_t>> trivialSegments;
+  SmallVector<std::optional<int64_t>> trivialSegments;
   for (const auto &indices : reassociationIndices)
     trivialSegments.push_back(
         getUniqueNonUnitDim(indices, sourceType.getShape()));
@@ -387,13 +388,13 @@ static SmallVector<Optional<int64_t>> getCollapseShapeTrivialSegments(
 
 /// Returns true if any of the segments of the reassociation indices for a
 /// collapsing reshape can be simplified using a rank-reducing slice.
-static FailureOr<SmallVector<Optional<int64_t>>>
+static FailureOr<SmallVector<std::optional<int64_t>>>
 canCollapseShapeBeSimplifiedByRankReducingSlice(
     RankedTensorType sourceType,
     ArrayRef<ReassociationIndices> reassociationIndices) {
-  SmallVector<Optional<int64_t>> trivialSegments =
+  SmallVector<std::optional<int64_t>> trivialSegments =
       getCollapseShapeTrivialSegments(sourceType, reassociationIndices);
-  if (!llvm::any_of(trivialSegments, [](const Optional<int64_t> &idx) {
+  if (!llvm::any_of(trivialSegments, [](const std::optional<int64_t> &idx) {
         return idx.has_value();
       }))
     return failure();
@@ -404,7 +405,7 @@ FailureOr<CollapseShapeRankReducingSliceSimplificationInfo>
 mlir::getSimplifyCollapseShapeWithRankReducingSliceInfo(
     RankedTensorType sourceType,
     ArrayRef<ReassociationIndices> reassociationIndices) {
-  FailureOr<SmallVector<Optional<int64_t>>> trivialSegments =
+  FailureOr<SmallVector<std::optional<int64_t>>> trivialSegments =
       canCollapseShapeBeSimplifiedByRankReducingSlice(sourceType,
                                                       reassociationIndices);
   if (failed(trivialSegments))

diff  --git a/mlir/lib/Dialect/Vector/Transforms/VectorTransferSplitRewritePatterns.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorTransferSplitRewritePatterns.cpp
index 6e2e2d496ecc9..c4aad0f5cc97e 100644
--- a/mlir/lib/Dialect/Vector/Transforms/VectorTransferSplitRewritePatterns.cpp
+++ b/mlir/lib/Dialect/Vector/Transforms/VectorTransferSplitRewritePatterns.cpp
@@ -38,7 +38,7 @@
 using namespace mlir;
 using namespace mlir::vector;
 
-static Optional<int64_t> extractConstantIndex(Value v) {
+static std::optional<int64_t> extractConstantIndex(Value v) {
   if (auto cstOp = v.getDefiningOp<arith::ConstantIndexOp>())
     return cstOp.value();
   if (auto affineApplyOp = v.getDefiningOp<AffineApplyOp>())

diff  --git a/mlir/lib/Dialect/Vector/Transforms/VectorUnroll.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorUnroll.cpp
index 09ff4ddd2e364..0872d10ca204e 100644
--- a/mlir/lib/Dialect/Vector/Transforms/VectorUnroll.cpp
+++ b/mlir/lib/Dialect/Vector/Transforms/VectorUnroll.cpp
@@ -135,7 +135,7 @@ static Operation *cloneOpWithOperandsAndTypes(OpBuilder &builder, Location loc,
 
 /// Return the target shape for unrolling for the given `op`. Return
 /// std::nullopt if the op shouldn't be or cannot be unrolled.
-static Optional<SmallVector<int64_t>>
+static std::optional<SmallVector<int64_t>>
 getTargetShape(const vector::UnrollVectorOptions &options, Operation *op) {
   if (options.filterConstraint && failed(options.filterConstraint(op)))
     return std::nullopt;
@@ -148,7 +148,7 @@ getTargetShape(const vector::UnrollVectorOptions &options, Operation *op) {
   auto maybeUnrollShape = unrollableVectorOp.getShapeForUnroll();
   if (!maybeUnrollShape)
     return std::nullopt;
-  Optional<SmallVector<int64_t>> targetShape = options.nativeShape(op);
+  std::optional<SmallVector<int64_t>> targetShape = options.nativeShape(op);
   if (!targetShape)
     return std::nullopt;
   auto maybeShapeRatio = computeShapeRatio(*maybeUnrollShape, *targetShape);
@@ -164,7 +164,8 @@ getUnrollOrder(unsigned numLoops, Operation *op,
   SmallVector<int64_t> loopOrder =
       llvm::to_vector(llvm::seq<int64_t>(0, static_cast<int64_t>(numLoops)));
   if (options.traversalOrderCallback != nullptr) {
-    Optional<SmallVector<int64_t>> order = options.traversalOrderCallback(op);
+    std::optional<SmallVector<int64_t>> order =
+        options.traversalOrderCallback(op);
     if (order) {
       loopOrder = std::move(*order);
     }
@@ -414,7 +415,7 @@ struct UnrollMultiReductionPattern
 
   LogicalResult matchAndRewrite(vector::MultiDimReductionOp reductionOp,
                                 PatternRewriter &rewriter) const override {
-    Optional<SmallVector<int64_t>> targetShape =
+    std::optional<SmallVector<int64_t>> targetShape =
         getTargetShape(options, reductionOp);
     if (!targetShape)
       return failure();
@@ -549,7 +550,7 @@ struct UnrollReductionPattern : public OpRewritePattern<vector::ReductionOp> {
 
   LogicalResult matchAndRewrite(vector::ReductionOp reductionOp,
                                 PatternRewriter &rewriter) const override {
-    Optional<SmallVector<int64_t>> targetShape =
+    std::optional<SmallVector<int64_t>> targetShape =
         getTargetShape(options, reductionOp);
     if (!targetShape)
       return failure();

diff  --git a/mlir/lib/ExecutionEngine/JitRunner.cpp b/mlir/lib/ExecutionEngine/JitRunner.cpp
index dddecc4caf1b6..bd069a1ea760d 100644
--- a/mlir/lib/ExecutionEngine/JitRunner.cpp
+++ b/mlir/lib/ExecutionEngine/JitRunner.cpp
@@ -148,8 +148,8 @@ static inline Error makeStringError(const Twine &message) {
                                              llvm::inconvertibleErrorCode());
 }
 
-static Optional<unsigned> getCommandLineOptLevel(Options &options) {
-  Optional<unsigned> optLevel;
+static std::optional<unsigned> getCommandLineOptLevel(Options &options) {
+  std::optional<unsigned> optLevel;
   SmallVector<std::reference_wrapper<llvm::cl::opt<bool>>, 4> optFlags{
       options.optO0, options.optO1, options.optO2, options.optO3};
 
@@ -168,7 +168,7 @@ static Optional<unsigned> getCommandLineOptLevel(Options &options) {
 static Error compileAndExecute(Options &options, Operation *module,
                                StringRef entryPoint,
                                CompileAndExecuteConfig config, void **args) {
-  Optional<llvm::CodeGenOpt::Level> jitCodeGenOptLevel;
+  std::optional<llvm::CodeGenOpt::Level> jitCodeGenOptLevel;
   if (auto clOptLevel = getCommandLineOptLevel(options))
     jitCodeGenOptLevel = static_cast<llvm::CodeGenOpt::Level>(*clOptLevel);
 
@@ -352,7 +352,7 @@ int mlir::JitRunnerMain(int argc, char **argv, const DialectRegistry &registry,
     return 0;
   }
 
-  Optional<unsigned> optLevel = getCommandLineOptLevel(options);
+  std::optional<unsigned> optLevel = getCommandLineOptLevel(options);
   SmallVector<std::reference_wrapper<llvm::cl::opt<bool>>, 4> optFlags{
       options.optO0, options.optO1, options.optO2, options.optO3};
 

diff  --git a/mlir/lib/IR/AffineExpr.cpp b/mlir/lib/IR/AffineExpr.cpp
index 12af9d31a3f9a..554452cb265fd 100644
--- a/mlir/lib/IR/AffineExpr.cpp
+++ b/mlir/lib/IR/AffineExpr.cpp
@@ -566,7 +566,7 @@ static AffineExpr simplifyAdd(AffineExpr lhs, AffineExpr rhs) {
   // Detect "c1 * expr + c_2 * expr" as "(c1 + c2) * expr".
   // c1 is rRhsConst, c2 is rLhsConst; firstExpr, secondExpr are their
   // respective multiplicands.
-  Optional<int64_t> rLhsConst, rRhsConst;
+  std::optional<int64_t> rLhsConst, rRhsConst;
   AffineExpr firstExpr, secondExpr;
   AffineConstantExpr rLhsConstExpr;
   auto lBinOpExpr = lhs.dyn_cast<AffineBinaryOpExpr>();

diff  --git a/mlir/lib/IR/AffineMap.cpp b/mlir/lib/IR/AffineMap.cpp
index f25b1a12b1b73..90c546656ec84 100644
--- a/mlir/lib/IR/AffineMap.cpp
+++ b/mlir/lib/IR/AffineMap.cpp
@@ -41,7 +41,7 @@ class AffineExprConstantFolder {
   }
 
 private:
-  Optional<int64_t> constantFoldImpl(AffineExpr expr) {
+  std::optional<int64_t> constantFoldImpl(AffineExpr expr) {
     switch (expr.getKind()) {
     case AffineExprKind::Add:
       return constantFoldBinExpr(
@@ -76,8 +76,8 @@ class AffineExprConstantFolder {
   }
 
   // TODO: Change these to operate on APInts too.
-  Optional<int64_t> constantFoldBinExpr(AffineExpr expr,
-                                        int64_t (*op)(int64_t, int64_t)) {
+  std::optional<int64_t> constantFoldBinExpr(AffineExpr expr,
+                                             int64_t (*op)(int64_t, int64_t)) {
     auto binOpExpr = expr.cast<AffineBinaryOpExpr>();
     if (auto lhs = constantFoldImpl(binOpExpr.getLHS()))
       if (auto rhs = constantFoldImpl(binOpExpr.getRHS()))
@@ -341,7 +341,7 @@ unsigned AffineMap::getDimPosition(unsigned idx) const {
   return getResult(idx).cast<AffineDimExpr>().getPosition();
 }
 
-Optional<unsigned> AffineMap::getResultPosition(AffineExpr input) const {
+std::optional<unsigned> AffineMap::getResultPosition(AffineExpr input) const {
   if (!input.isa<AffineDimExpr>())
     return std::nullopt;
 

diff  --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp
index 5839e2bed4aa3..0981b3b1cbe27 100644
--- a/mlir/lib/IR/AsmPrinter.cpp
+++ b/mlir/lib/IR/AsmPrinter.cpp
@@ -252,7 +252,7 @@ bool OpPrintingFlags::shouldElideElementsAttr(ElementsAttr attr) const {
 }
 
 /// Return the size limit for printing large ElementsAttr.
-Optional<int64_t> OpPrintingFlags::getLargeElementsAttrLimit() const {
+std::optional<int64_t> OpPrintingFlags::getLargeElementsAttrLimit() const {
   return elementsAttrElementLimit;
 }
 
@@ -532,7 +532,7 @@ class AliasInitializer {
 
     /// The alias for the attribute or type, or std::nullopt if the value has no
     /// alias.
-    Optional<StringRef> alias;
+    std::optional<StringRef> alias;
     /// The alias depth of this attribute or type, i.e. an indication of the
     /// relative ordering of when to print this alias.
     unsigned aliasDepth : 30;
@@ -1214,7 +1214,7 @@ class SSANameState {
   /// 'lookupResultNo'. 'lookupResultNo' is only filled in if the result group
   /// has more than 1 result.
   void getResultIDAndNumber(OpResult result, Value &lookupValue,
-                            Optional<int> &lookupResultNo) const;
+                            std::optional<int> &lookupResultNo) const;
 
   /// Set a special value name for the given value.
   void setValueName(Value value, StringRef name);
@@ -1326,7 +1326,7 @@ void SSANameState::printValueID(Value value, bool printResultNo,
     return;
   }
 
-  Optional<int> resultNo;
+  std::optional<int> resultNo;
   auto lookupValue = value;
 
   // If this is an operation result, collect the head lookup value of the result
@@ -1514,8 +1514,9 @@ void SSANameState::numberValuesInOp(Operation &op) {
   }
 }
 
-void SSANameState::getResultIDAndNumber(OpResult result, Value &lookupValue,
-                                        Optional<int> &lookupResultNo) const {
+void SSANameState::getResultIDAndNumber(
+    OpResult result, Value &lookupValue,
+    std::optional<int> &lookupResultNo) const {
   Operation *owner = result.getOwner();
   if (owner->getNumResults() == 1)
     return;

diff  --git a/mlir/lib/IR/BuiltinAttributes.cpp b/mlir/lib/IR/BuiltinAttributes.cpp
index b5810ff5b9502..ff4aa65fc8887 100644
--- a/mlir/lib/IR/BuiltinAttributes.cpp
+++ b/mlir/lib/IR/BuiltinAttributes.cpp
@@ -94,9 +94,9 @@ static bool dictionaryAttrSort(ArrayRef<NamedAttribute> value,
 
 /// Returns an entry with a duplicate name from the given sorted array of named
 /// attributes. Returns std::nullopt if all elements have unique names.
-static Optional<NamedAttribute>
+static std::optional<NamedAttribute>
 findDuplicateElement(ArrayRef<NamedAttribute> value) {
-  const Optional<NamedAttribute> none{std::nullopt};
+  const std::optional<NamedAttribute> none{std::nullopt};
   if (value.size() < 2)
     return none;
 
@@ -125,7 +125,7 @@ bool DictionaryAttr::sortInPlace(SmallVectorImpl<NamedAttribute> &array) {
   return isSorted;
 }
 
-Optional<NamedAttribute>
+std::optional<NamedAttribute>
 DictionaryAttr::findDuplicate(SmallVectorImpl<NamedAttribute> &array,
                               bool isSorted) {
   if (!isSorted)
@@ -172,13 +172,13 @@ Attribute DictionaryAttr::get(StringAttr name) const {
 }
 
 /// Return the specified named attribute if present, std::nullopt otherwise.
-Optional<NamedAttribute> DictionaryAttr::getNamed(StringRef name) const {
+std::optional<NamedAttribute> DictionaryAttr::getNamed(StringRef name) const {
   auto it = impl::findAttrSorted(begin(), end(), name);
-  return it.second ? *it.first : Optional<NamedAttribute>();
+  return it.second ? *it.first : std::optional<NamedAttribute>();
 }
-Optional<NamedAttribute> DictionaryAttr::getNamed(StringAttr name) const {
+std::optional<NamedAttribute> DictionaryAttr::getNamed(StringAttr name) const {
   auto it = impl::findAttrSorted(begin(), end(), name);
-  return it.second ? *it.first : Optional<NamedAttribute>();
+  return it.second ? *it.first : std::optional<NamedAttribute>();
 }
 
 /// Return whether the specified attribute is present.
@@ -1552,7 +1552,7 @@ DenseResourceElementsAttrBase<T>::get(ShapedType type, StringRef blobName,
 }
 
 template <typename T>
-Optional<ArrayRef<T>>
+std::optional<ArrayRef<T>>
 DenseResourceElementsAttrBase<T>::tryGetAsArrayRef() const {
   if (AsmResourceBlob *blob = this->getRawHandle().getBlob())
     return blob->template getDataAs<T>();

diff  --git a/mlir/lib/IR/Diagnostics.cpp b/mlir/lib/IR/Diagnostics.cpp
index be1ec397107b8..5926f2e6953aa 100644
--- a/mlir/lib/IR/Diagnostics.cpp
+++ b/mlir/lib/IR/Diagnostics.cpp
@@ -174,7 +174,7 @@ std::string Diagnostic::str() const {
 /// Attaches a note to this diagnostic. A new location may be optionally
 /// provided, if not, then the location defaults to the one specified for this
 /// diagnostic. Notes may not be attached to other notes.
-Diagnostic &Diagnostic::attachNote(Optional<Location> noteLoc) {
+Diagnostic &Diagnostic::attachNote(std::optional<Location> noteLoc) {
   // We don't allow attaching notes to notes.
   assert(severity != DiagnosticSeverity::Note &&
          "cannot attach a note to a note");
@@ -391,7 +391,7 @@ struct SourceMgrDiagnosticHandlerImpl {
 } // namespace mlir
 
 /// Return a processable CallSiteLoc from the given location.
-static Optional<CallSiteLoc> getCallSiteLoc(Location loc) {
+static std::optional<CallSiteLoc> getCallSiteLoc(Location loc) {
   if (auto nameLoc = dyn_cast<NameLoc>(loc))
     return getCallSiteLoc(cast<NameLoc>(loc).getChildLoc());
   if (auto callLoc = dyn_cast<CallSiteLoc>(loc))
@@ -477,7 +477,7 @@ void SourceMgrDiagnosticHandler::emitDiagnostic(Location loc, Twine message,
 void SourceMgrDiagnosticHandler::emitDiagnostic(Diagnostic &diag) {
   SmallVector<std::pair<Location, StringRef>> locationStack;
   auto addLocToStack = [&](Location loc, StringRef locContext) {
-    if (Optional<Location> showableLoc = findLocToShow(loc))
+    if (std::optional<Location> showableLoc = findLocToShow(loc))
       locationStack.emplace_back(*showableLoc, locContext);
   };
 
@@ -527,36 +527,37 @@ SourceMgrDiagnosticHandler::getBufferForFile(StringRef filename) {
   return nullptr;
 }
 
-Optional<Location> SourceMgrDiagnosticHandler::findLocToShow(Location loc) {
+std::optional<Location>
+SourceMgrDiagnosticHandler::findLocToShow(Location loc) {
   if (!shouldShowLocFn)
     return loc;
   if (!shouldShowLocFn(loc))
     return std::nullopt;
 
   // Recurse into the child locations of some of location types.
-  return TypeSwitch<LocationAttr, Optional<Location>>(loc)
-      .Case([&](CallSiteLoc callLoc) -> Optional<Location> {
+  return TypeSwitch<LocationAttr, std::optional<Location>>(loc)
+      .Case([&](CallSiteLoc callLoc) -> std::optional<Location> {
         // We recurse into the callee of a call site, as the caller will be
         // emitted in a 
diff erent note on the main diagnostic.
         return findLocToShow(callLoc.getCallee());
       })
-      .Case([&](FileLineColLoc) -> Optional<Location> { return loc; })
-      .Case([&](FusedLoc fusedLoc) -> Optional<Location> {
+      .Case([&](FileLineColLoc) -> std::optional<Location> { return loc; })
+      .Case([&](FusedLoc fusedLoc) -> std::optional<Location> {
         // Fused location is unique in that we try to find a sub-location to
         // show, rather than the top-level location itself.
         for (Location childLoc : fusedLoc.getLocations())
-          if (Optional<Location> showableLoc = findLocToShow(childLoc))
+          if (std::optional<Location> showableLoc = findLocToShow(childLoc))
             return showableLoc;
         return std::nullopt;
       })
-      .Case([&](NameLoc nameLoc) -> Optional<Location> {
+      .Case([&](NameLoc nameLoc) -> std::optional<Location> {
         return findLocToShow(nameLoc.getChildLoc());
       })
-      .Case([&](OpaqueLoc opaqueLoc) -> Optional<Location> {
+      .Case([&](OpaqueLoc opaqueLoc) -> std::optional<Location> {
         // OpaqueLoc always falls back to a 
diff erent source location.
         return findLocToShow(opaqueLoc.getFallbackLocation());
       })
-      .Case([](UnknownLoc) -> Optional<Location> {
+      .Case([](UnknownLoc) -> std::optional<Location> {
         // Prefer not to show unknown locations.
         return std::nullopt;
       });
@@ -652,14 +653,15 @@ struct ExpectedDiag {
   StringRef substring;
   /// An optional regex matcher, if the expected diagnostic sub-string was a
   /// regex string.
-  Optional<llvm::Regex> substringRegex;
+  std::optional<llvm::Regex> substringRegex;
 };
 
 struct SourceMgrDiagnosticVerifierHandlerImpl {
   SourceMgrDiagnosticVerifierHandlerImpl() : status(success()) {}
 
   /// Returns the expected diagnostics for the given source file.
-  Optional<MutableArrayRef<ExpectedDiag>> getExpectedDiags(StringRef bufName);
+  std::optional<MutableArrayRef<ExpectedDiag>>
+  getExpectedDiags(StringRef bufName);
 
   /// Computes the expected diagnostics for the given source buffer.
   MutableArrayRef<ExpectedDiag>
@@ -695,7 +697,7 @@ static StringRef getDiagKindStr(DiagnosticSeverity kind) {
   llvm_unreachable("Unknown DiagnosticSeverity");
 }
 
-Optional<MutableArrayRef<ExpectedDiag>>
+std::optional<MutableArrayRef<ExpectedDiag>>
 SourceMgrDiagnosticVerifierHandlerImpl::getExpectedDiags(StringRef bufName) {
   auto expectedDiags = expectedDiagsPerFile.find(bufName);
   if (expectedDiags != expectedDiagsPerFile.end())

diff  --git a/mlir/lib/IR/DialectResourceBlobManager.cpp b/mlir/lib/IR/DialectResourceBlobManager.cpp
index a47fe9bfb8952..b83b31e30ef1f 100644
--- a/mlir/lib/IR/DialectResourceBlobManager.cpp
+++ b/mlir/lib/IR/DialectResourceBlobManager.cpp
@@ -31,7 +31,7 @@ void DialectResourceBlobManager::update(StringRef name,
 }
 
 auto DialectResourceBlobManager::insert(StringRef name,
-                                        Optional<AsmResourceBlob> blob)
+                                        std::optional<AsmResourceBlob> blob)
     -> BlobEntry & {
   llvm::sys::SmartScopedWriter<true> writer(blobMapLock);
 

diff  --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp
index a354eed67b17a..b0fe94f0c513a 100644
--- a/mlir/lib/IR/MLIRContext.cpp
+++ b/mlir/lib/IR/MLIRContext.cpp
@@ -785,7 +785,7 @@ OperationName::UnregisteredOpModel::verifyRegionInvariants(Operation *) {
 // RegisteredOperationName
 //===----------------------------------------------------------------------===//
 
-Optional<RegisteredOperationName>
+std::optional<RegisteredOperationName>
 RegisteredOperationName::lookup(StringRef name, MLIRContext *ctx) {
   auto &impl = ctx->getImpl();
   auto it = impl.registeredOperations.find(name);

diff  --git a/mlir/lib/IR/OperationSupport.cpp b/mlir/lib/IR/OperationSupport.cpp
index dc6b26dab961d..8f3d37976d2a8 100644
--- a/mlir/lib/IR/OperationSupport.cpp
+++ b/mlir/lib/IR/OperationSupport.cpp
@@ -42,8 +42,8 @@ NamedAttrList::NamedAttrList(const_iterator inStart, const_iterator inEnd) {
 
 ArrayRef<NamedAttribute> NamedAttrList::getAttrs() const { return attrs; }
 
-Optional<NamedAttribute> NamedAttrList::findDuplicate() const {
-  Optional<NamedAttribute> duplicate =
+std::optional<NamedAttribute> NamedAttrList::findDuplicate() const {
+  std::optional<NamedAttribute> duplicate =
       DictionaryAttr::findDuplicate(attrs, isSorted());
   // DictionaryAttr::findDuplicate will sort the list, so reset the sorted
   // state.
@@ -91,13 +91,13 @@ Attribute NamedAttrList::get(StringAttr name) const {
 }
 
 /// Return the specified named attribute if present, std::nullopt otherwise.
-Optional<NamedAttribute> NamedAttrList::getNamed(StringRef name) const {
+std::optional<NamedAttribute> NamedAttrList::getNamed(StringRef name) const {
   auto it = findAttr(*this, name);
-  return it.second ? *it.first : Optional<NamedAttribute>();
+  return it.second ? *it.first : std::optional<NamedAttribute>();
 }
-Optional<NamedAttribute> NamedAttrList::getNamed(StringAttr name) const {
+std::optional<NamedAttribute> NamedAttrList::getNamed(StringAttr name) const {
   auto it = findAttr(*this, name);
-  return it.second ? *it.first : Optional<NamedAttribute>();
+  return it.second ? *it.first : std::optional<NamedAttribute>();
 }
 
 /// If the an attribute exists with the specified name, change it to the new
@@ -423,7 +423,7 @@ MutableOperandRange::MutableOperandRange(Operation *owner)
 /// Slice this range into a sub range, with the additional operand segment.
 MutableOperandRange
 MutableOperandRange::slice(unsigned subStart, unsigned subLen,
-                           Optional<OperandSegment> segment) const {
+                           std::optional<OperandSegment> segment) const {
   assert((subStart + subLen) <= length && "invalid sub-range");
   MutableOperandRange subSlice(owner, start + subStart, subLen,
                                operandSegments);

diff  --git a/mlir/lib/IR/SubElementInterfaces.cpp b/mlir/lib/IR/SubElementInterfaces.cpp
index 9eeb7b4d7925a..528e0cadfa7c6 100644
--- a/mlir/lib/IR/SubElementInterfaces.cpp
+++ b/mlir/lib/IR/SubElementInterfaces.cpp
@@ -215,7 +215,7 @@ T AttrTypeReplacer::replaceImpl(T element, ReplaceFns &replaceFns,
   T result = element;
   WalkResult walkResult = WalkResult::advance();
   for (auto &replaceFn : llvm::reverse(replaceFns)) {
-    if (Optional<std::pair<T, WalkResult>> newRes = replaceFn(element)) {
+    if (std::optional<std::pair<T, WalkResult>> newRes = replaceFn(element)) {
       std::tie(result, walkResult) = *newRes;
       break;
     }

diff  --git a/mlir/lib/IR/SymbolTable.cpp b/mlir/lib/IR/SymbolTable.cpp
index bec7c0be7671f..4c3b3bb8be5ab 100644
--- a/mlir/lib/IR/SymbolTable.cpp
+++ b/mlir/lib/IR/SymbolTable.cpp
@@ -77,13 +77,13 @@ collectValidReferencesFor(Operation *symbol, StringAttr symbolName,
 /// Walk all of the operations within the given set of regions, without
 /// traversing into any nested symbol tables. Stops walking if the result of the
 /// callback is anything other than `WalkResult::advance`.
-static Optional<WalkResult>
+static std::optional<WalkResult>
 walkSymbolTable(MutableArrayRef<Region> regions,
-                function_ref<Optional<WalkResult>(Operation *)> callback) {
+                function_ref<std::optional<WalkResult>(Operation *)> callback) {
   SmallVector<Region *, 1> worklist(llvm::make_pointer_range(regions));
   while (!worklist.empty()) {
     for (Operation &op : worklist.pop_back_val()->getOps()) {
-      Optional<WalkResult> result = callback(&op);
+      std::optional<WalkResult> result = callback(&op);
       if (result != WalkResult::advance())
         return result;
 
@@ -101,10 +101,10 @@ walkSymbolTable(MutableArrayRef<Region> regions,
 /// Walk all of the operations nested under, and including, the given operation,
 /// without traversing into any nested symbol tables. Stops walking if the
 /// result of the callback is anything other than `WalkResult::advance`.
-static Optional<WalkResult>
+static std::optional<WalkResult>
 walkSymbolTable(Operation *op,
-                function_ref<Optional<WalkResult>(Operation *)> callback) {
-  Optional<WalkResult> result = callback(op);
+                function_ref<std::optional<WalkResult>(Operation *)> callback) {
+  std::optional<WalkResult> result = callback(op);
   if (result != WalkResult::advance() || op->hasTrait<OpTrait::SymbolTable>())
     return result;
   return walkSymbolTable(op->getRegions(), callback);
@@ -440,13 +440,13 @@ LogicalResult detail::verifySymbolTable(Operation *op) {
 
   // Verify any nested symbol user operations.
   SymbolTableCollection symbolTable;
-  auto verifySymbolUserFn = [&](Operation *op) -> Optional<WalkResult> {
+  auto verifySymbolUserFn = [&](Operation *op) -> std::optional<WalkResult> {
     if (SymbolUserOpInterface user = dyn_cast<SymbolUserOpInterface>(op))
       return WalkResult(user.verifySymbolUses(symbolTable));
     return WalkResult::advance();
   };
 
-  Optional<WalkResult> result =
+  std::optional<WalkResult> result =
       walkSymbolTable(op->getRegions(), verifySymbolUserFn);
   return success(result && !result->wasInterrupted());
 }
@@ -550,21 +550,23 @@ walkSymbolRefs(Operation *op,
 /// Walk all of the uses, for any symbol, that are nested within the given
 /// regions, invoking the provided callback for each. This does not traverse
 /// into any nested symbol tables.
-static Optional<WalkResult>
+static std::optional<WalkResult>
 walkSymbolUses(MutableArrayRef<Region> regions,
                function_ref<WalkResult(SymbolTable::SymbolUse)> callback) {
-  return walkSymbolTable(regions, [&](Operation *op) -> Optional<WalkResult> {
-    // Check that this isn't a potentially unknown symbol table.
-    if (isPotentiallyUnknownSymbolTable(op))
-      return std::nullopt;
-
-    return walkSymbolRefs(op, callback);
-  });
+  return walkSymbolTable(regions,
+                         [&](Operation *op) -> std::optional<WalkResult> {
+                           // Check that this isn't a potentially unknown symbol
+                           // table.
+                           if (isPotentiallyUnknownSymbolTable(op))
+                             return std::nullopt;
+
+                           return walkSymbolRefs(op, callback);
+                         });
 }
 /// Walk all of the uses, for any symbol, that are nested within the given
 /// operation 'from', invoking the provided callback for each. This does not
 /// traverse into any nested symbol tables.
-static Optional<WalkResult>
+static std::optional<WalkResult>
 walkSymbolUses(Operation *from,
                function_ref<WalkResult(SymbolTable::SymbolUse)> callback) {
   // If this operation has regions, and it, as well as its dialect, isn't
@@ -600,7 +602,7 @@ struct SymbolScope {
             std::enable_if_t<!std::is_same<
                 typename llvm::function_traits<CallbackT>::result_t,
                 void>::value> * = nullptr>
-  Optional<WalkResult> walk(CallbackT cback) {
+  std::optional<WalkResult> walk(CallbackT cback) {
     if (Region *region = limit.dyn_cast<Region *>())
       return walkSymbolUses(*region, cback);
     return walkSymbolUses(limit.get<Operation *>(), cback);
@@ -611,7 +613,7 @@ struct SymbolScope {
             std::enable_if_t<std::is_same<
                 typename llvm::function_traits<CallbackT>::result_t,
                 void>::value> * = nullptr>
-  Optional<WalkResult> walk(CallbackT cback) {
+  std::optional<WalkResult> walk(CallbackT cback) {
     return walk([=](SymbolTable::SymbolUse use) {
       return cback(use), WalkResult::advance();
     });
@@ -620,7 +622,7 @@ struct SymbolScope {
   /// Walk all of the operations nested under the current scope without
   /// traversing into any nested symbol tables.
   template <typename CallbackT>
-  Optional<WalkResult> walkSymbolTable(CallbackT &&cback) {
+  std::optional<WalkResult> walkSymbolTable(CallbackT &&cback) {
     if (Region *region = limit.dyn_cast<Region *>())
       return ::walkSymbolTable(*region, cback);
     return ::walkSymbolTable(limit.get<Operation *>(), cback);
@@ -878,7 +880,7 @@ replaceAllSymbolUsesImpl(SymbolT symbol, StringAttr newSymbol, IRUnitT *limit) {
           return {attr, WalkResult::skip()};
         });
 
-    auto walkFn = [&](Operation *op) -> Optional<WalkResult> {
+    auto walkFn = [&](Operation *op) -> std::optional<WalkResult> {
       replacer.replaceElementsIn(op);
       return WalkResult::advance();
     };

diff  --git a/mlir/lib/IR/Verifier.cpp b/mlir/lib/IR/Verifier.cpp
index 60fa3e13854bd..432d7bb28ae9b 100644
--- a/mlir/lib/IR/Verifier.cpp
+++ b/mlir/lib/IR/Verifier.cpp
@@ -183,7 +183,8 @@ LogicalResult OperationVerifier::verifyOperation(Operation &op) {
 
   // If we can get operation info for this, check the custom hook.
   OperationName opName = op.getName();
-  Optional<RegisteredOperationName> registeredInfo = opName.getRegisteredInfo();
+  std::optional<RegisteredOperationName> registeredInfo =
+      opName.getRegisteredInfo();
   if (registeredInfo && failed(registeredInfo->verifyInvariants(&op)))
     return failure();
 

diff  --git a/mlir/lib/Interfaces/InferIntRangeInterface.cpp b/mlir/lib/Interfaces/InferIntRangeInterface.cpp
index 212eea6de2926..9248b1149ff2f 100644
--- a/mlir/lib/Interfaces/InferIntRangeInterface.cpp
+++ b/mlir/lib/Interfaces/InferIntRangeInterface.cpp
@@ -113,7 +113,7 @@ ConstantIntRanges::intersection(const ConstantIntRanges &other) const {
   return {uminIntersect, umaxIntersect, sminIntersect, smaxIntersect};
 }
 
-Optional<APInt> ConstantIntRanges::getConstantValue() const {
+std::optional<APInt> ConstantIntRanges::getConstantValue() const {
   // Note: we need to exclude the trivially-equal width 0 values here.
   if (umin() == umax() && umin().getBitWidth() != 0)
     return umin();

diff  --git a/mlir/lib/Pass/Pass.cpp b/mlir/lib/Pass/Pass.cpp
index 2bb4f1ae186a4..8b5bd38845dca 100644
--- a/mlir/lib/Pass/Pass.cpp
+++ b/mlir/lib/Pass/Pass.cpp
@@ -128,13 +128,14 @@ struct OpPassManagerImpl {
   LogicalResult finalizePassList(MLIRContext *ctx);
 
   /// Return the operation name of this pass manager.
-  Optional<OperationName> getOpName(MLIRContext &context) {
+  std::optional<OperationName> getOpName(MLIRContext &context) {
     if (!name.empty() && !opName)
       opName = OperationName(name, &context);
     return opName;
   }
-  Optional<StringRef> getOpName() const {
-    return name.empty() ? Optional<StringRef>() : Optional<StringRef>(name);
+  std::optional<StringRef> getOpName() const {
+    return name.empty() ? std::optional<StringRef>()
+                        : std::optional<StringRef>(name);
   }
 
   /// Return the name used to anchor this pass manager. This is either the name
@@ -153,7 +154,7 @@ struct OpPassManagerImpl {
 
   /// The cached OperationName (internalized in the context) for the name of the
   /// operation that passes of this pass manager operate on.
-  Optional<OperationName> opName;
+  std::optional<OperationName> opName;
 
   /// The set of passes to run as part of this pass manager.
   std::vector<std::unique_ptr<Pass>> passes;
@@ -185,8 +186,8 @@ OpPassManager &OpPassManagerImpl::nest(OpPassManager &&nested) {
 void OpPassManagerImpl::addPass(std::unique_ptr<Pass> pass) {
   // If this pass runs on a 
diff erent operation than this pass manager, then
   // implicitly nest a pass manager for this operation if enabled.
-  Optional<StringRef> pmOpName = getOpName();
-  Optional<StringRef> passOpName = pass->getOpName();
+  std::optional<StringRef> pmOpName = getOpName();
+  std::optional<StringRef> passOpName = pass->getOpName();
   if (pmOpName && passOpName && *pmOpName != *passOpName) {
     if (nesting == OpPassManager::Nesting::Implicit)
       return nest(*passOpName).addPass(std::move(pass));
@@ -244,13 +245,14 @@ LogicalResult OpPassManagerImpl::finalizePassList(MLIRContext *ctx) {
   llvm::erase_if(passes, std::logical_not<std::unique_ptr<Pass>>());
 
   // If this is a op-agnostic pass manager, there is nothing left to do.
-  Optional<OperationName> rawOpName = getOpName(*ctx);
+  std::optional<OperationName> rawOpName = getOpName(*ctx);
   if (!rawOpName)
     return success();
 
   // Otherwise, verify that all of the passes are valid for the current
   // operation anchor.
-  Optional<RegisteredOperationName> opName = rawOpName->getRegisteredInfo();
+  std::optional<RegisteredOperationName> opName =
+      rawOpName->getRegisteredInfo();
   for (std::unique_ptr<Pass> &pass : passes) {
     if (opName && !pass->canScheduleOn(*opName)) {
       return emitError(UnknownLoc::get(ctx))
@@ -266,13 +268,14 @@ bool OpPassManagerImpl::canScheduleOn(MLIRContext &context,
                                       OperationName opName) {
   // If this pass manager is op-specific, we simply check if the provided
   // operation name is the same as this one.
-  Optional<OperationName> pmOpName = getOpName(context);
+  std::optional<OperationName> pmOpName = getOpName(context);
   if (pmOpName)
     return pmOpName == opName;
 
   // Otherwise, this is an op-agnostic pass manager. Check that the operation
   // can be scheduled on all passes within the manager.
-  Optional<RegisteredOperationName> registeredInfo = opName.getRegisteredInfo();
+  std::optional<RegisteredOperationName> registeredInfo =
+      opName.getRegisteredInfo();
   if (!registeredInfo ||
       !registeredInfo->hasTrait<OpTrait::IsIsolatedFromAbove>())
     return false;
@@ -343,12 +346,13 @@ size_t OpPassManager::size() const { return impl->passes.size(); }
 OpPassManagerImpl &OpPassManager::getImpl() { return *impl; }
 
 /// Return the operation name that this pass manager operates on.
-Optional<StringRef> OpPassManager::getOpName() const {
+std::optional<StringRef> OpPassManager::getOpName() const {
   return impl->getOpName();
 }
 
 /// Return the operation name that this pass manager operates on.
-Optional<OperationName> OpPassManager::getOpName(MLIRContext &context) const {
+std::optional<OperationName>
+OpPassManager::getOpName(MLIRContext &context) const {
   return impl->getOpName(context);
 }
 
@@ -418,7 +422,7 @@ LogicalResult OpPassManager::initialize(MLIRContext *context,
 LogicalResult OpToOpPassAdaptor::run(Pass *pass, Operation *op,
                                      AnalysisManager am, bool verifyPasses,
                                      unsigned parentInitGeneration) {
-  Optional<RegisteredOperationName> opInfo = op->getRegisteredInfo();
+  std::optional<RegisteredOperationName> opInfo = op->getRegisteredInfo();
   if (!opInfo)
     return op->emitOpError()
            << "trying to schedule a pass on an unregistered operation";
@@ -579,7 +583,7 @@ LogicalResult OpToOpPassAdaptor::tryMergeInto(MLIRContext *ctx,
       // If this is a non-generic pass manager, a conflict will arise if a
       // non-generic pass manager's operation name can be scheduled on the
       // generic passmanager.
-      if (Optional<OperationName> pmOpName = pm.getOpName(*ctx))
+      if (std::optional<OperationName> pmOpName = pm.getOpName(*ctx))
         return genericPM.getImpl().canScheduleOn(*ctx, *pmOpName);
       // Otherwise, this is a generic pass manager. We current can't determine
       // when generic pass managers can be merged, so conservatively assume they
@@ -618,8 +622,8 @@ LogicalResult OpToOpPassAdaptor::tryMergeInto(MLIRContext *ctx,
   // After coalescing, sort the pass managers within rhs by name.
   auto compareFn = [](const OpPassManager *lhs, const OpPassManager *rhs) {
     // Order op-specific pass managers first and op-agnostic pass managers last.
-    if (Optional<StringRef> lhsName = lhs->getOpName()) {
-      if (Optional<StringRef> rhsName = rhs->getOpName())
+    if (std::optional<StringRef> lhsName = lhs->getOpName()) {
+      if (std::optional<StringRef> rhsName = rhs->getOpName())
         return lhsName->compare(*rhsName);
       return -1; // lhs(op-specific) < rhs(op-agnostic)
     }
@@ -713,7 +717,7 @@ void OpToOpPassAdaptor::runOnOperationAsyncImpl(bool verifyPasses) {
   // execute over. This ensures that an analysis manager exists for each
   // operation, as well as providing a queue of operations to execute over.
   std::vector<OpPMInfo> opInfos;
-  DenseMap<OperationName, Optional<unsigned>> knownOpPMIdx;
+  DenseMap<OperationName, std::optional<unsigned>> knownOpPMIdx;
   for (auto &region : getOperation()->getRegions()) {
     for (Operation &op : region.getOps()) {
       // Get the pass manager index for this operation type.
@@ -778,7 +782,7 @@ void PassManager::enableVerifier(bool enabled) { verifyPasses = enabled; }
 /// Run the passes within this manager on the provided operation.
 LogicalResult PassManager::run(Operation *op) {
   MLIRContext *context = getContext();
-  Optional<OperationName> anchorOp = getOpName(*context);
+  std::optional<OperationName> anchorOp = getOpName(*context);
   if (anchorOp && anchorOp != op->getName())
     return emitError(op->getLoc())
            << "can't run '" << getOpAnchorName() << "' pass manager on '"
@@ -913,10 +917,10 @@ void detail::NestedAnalysisMap::invalidate(
 PassInstrumentation::~PassInstrumentation() = default;
 
 void PassInstrumentation::runBeforePipeline(
-    Optional<OperationName> name, const PipelineParentInfo &parentInfo) {}
+    std::optional<OperationName> name, const PipelineParentInfo &parentInfo) {}
 
 void PassInstrumentation::runAfterPipeline(
-    Optional<OperationName> name, const PipelineParentInfo &parentInfo) {}
+    std::optional<OperationName> name, const PipelineParentInfo &parentInfo) {}
 
 //===----------------------------------------------------------------------===//
 // PassInstrumentor
@@ -939,7 +943,7 @@ PassInstrumentor::~PassInstrumentor() = default;
 
 /// See PassInstrumentation::runBeforePipeline for details.
 void PassInstrumentor::runBeforePipeline(
-    Optional<OperationName> name,
+    std::optional<OperationName> name,
     const PassInstrumentation::PipelineParentInfo &parentInfo) {
   llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
   for (auto &instr : impl->instrumentations)
@@ -948,7 +952,7 @@ void PassInstrumentor::runBeforePipeline(
 
 /// See PassInstrumentation::runAfterPipeline for details.
 void PassInstrumentor::runAfterPipeline(
-    Optional<OperationName> name,
+    std::optional<OperationName> name,
     const PassInstrumentation::PipelineParentInfo &parentInfo) {
   llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
   for (auto &instr : llvm::reverse(impl->instrumentations))

diff  --git a/mlir/lib/Pass/PassRegistry.cpp b/mlir/lib/Pass/PassRegistry.cpp
index c286b3ac2a3eb..3d10fe14d43d9 100644
--- a/mlir/lib/Pass/PassRegistry.cpp
+++ b/mlir/lib/Pass/PassRegistry.cpp
@@ -41,8 +41,8 @@ buildDefaultRegistryFn(const PassAllocatorFunction &allocator) {
     std::unique_ptr<Pass> pass = allocator();
     LogicalResult result = pass->initializeOptions(options);
 
-    Optional<StringRef> pmOpName = pm.getOpName();
-    Optional<StringRef> passOpName = pass->getOpName();
+    std::optional<StringRef> pmOpName = pm.getOpName();
+    std::optional<StringRef> passOpName = pass->getOpName();
     if ((pm.getNesting() == OpPassManager::Nesting::Explicit) && pmOpName &&
         passOpName && *pmOpName != *passOpName) {
       return errorHandler(llvm::Twine("Can't add pass '") + pass->getName() +

diff  --git a/mlir/lib/Pass/PassTiming.cpp b/mlir/lib/Pass/PassTiming.cpp
index c0100cc52bbcf..9554c5dd9cb19 100644
--- a/mlir/lib/Pass/PassTiming.cpp
+++ b/mlir/lib/Pass/PassTiming.cpp
@@ -53,7 +53,7 @@ struct PassTiming : public PassInstrumentation {
   // Pipeline
   //===--------------------------------------------------------------------===//
 
-  void runBeforePipeline(Optional<OperationName> name,
+  void runBeforePipeline(std::optional<OperationName> name,
                          const PipelineParentInfo &parentInfo) override {
     auto tid = llvm::get_threadid();
     auto &activeTimers = activeThreadTimers[tid];
@@ -75,7 +75,7 @@ struct PassTiming : public PassInstrumentation {
     }));
   }
 
-  void runAfterPipeline(Optional<OperationName>,
+  void runAfterPipeline(std::optional<OperationName>,
                         const PipelineParentInfo &) override {
     auto &activeTimers = activeThreadTimers[llvm::get_threadid()];
     assert(!activeTimers.empty() && "expected active timer");

diff  --git a/mlir/lib/Rewrite/ByteCode.cpp b/mlir/lib/Rewrite/ByteCode.cpp
index 6b1122033c914..1ea4bef5402a7 100644
--- a/mlir/lib/Rewrite/ByteCode.cpp
+++ b/mlir/lib/Rewrite/ByteCode.cpp
@@ -487,13 +487,13 @@ struct ByteCodeLiveRange {
   std::unique_ptr<llvm::IntervalMap<uint64_t, char, 16>> liveness;
 
   /// The operation range storage index for this range.
-  Optional<unsigned> opRangeIndex;
+  std::optional<unsigned> opRangeIndex;
 
   /// The type range storage index for this range.
-  Optional<unsigned> typeRangeIndex;
+  std::optional<unsigned> typeRangeIndex;
 
   /// The value range storage index for this range.
-  Optional<unsigned> valueRangeIndex;
+  std::optional<unsigned> valueRangeIndex;
 };
 } // namespace
 
@@ -1107,7 +1107,7 @@ class ByteCodeExecutor {
   LogicalResult
   execute(PatternRewriter &rewriter,
           SmallVectorImpl<PDLByteCode::MatchResult> *matches = nullptr,
-          Optional<Location> mainRewriteLoc = {});
+          std::optional<Location> mainRewriteLoc = {});
 
 private:
   /// Internal implementation of executing each of the bytecode commands.
@@ -1450,11 +1450,11 @@ LogicalResult ByteCodeExecutor::executeApplyRewrite(PatternRewriter &rewriter) {
 
     // If the result is a range, we need to copy it over to the bytecodes
     // range memory.
-    if (Optional<TypeRange> typeRange = result.dyn_cast<TypeRange>()) {
+    if (std::optional<TypeRange> typeRange = result.dyn_cast<TypeRange>()) {
       unsigned rangeIndex = read();
       typeRangeMemory[rangeIndex] = *typeRange;
       memory[read()] = &typeRangeMemory[rangeIndex];
-    } else if (Optional<ValueRange> valueRange =
+    } else if (std::optional<ValueRange> valueRange =
                    result.dyn_cast<ValueRange>()) {
       unsigned rangeIndex = read();
       valueRangeMemory[rangeIndex] = *valueRange;
@@ -2110,7 +2110,7 @@ void ByteCodeExecutor::executeSwitchTypes() {
 LogicalResult
 ByteCodeExecutor::execute(PatternRewriter &rewriter,
                           SmallVectorImpl<PDLByteCode::MatchResult> *matches,
-                          Optional<Location> mainRewriteLoc) {
+                          std::optional<Location> mainRewriteLoc) {
   while (true) {
     // Print the location of the operation being executed.
     LLVM_DEBUG(llvm::dbgs() << readInline<Location>() << "\n");

diff  --git a/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp b/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
index 947bada34d5bc..0fa166844e105 100644
--- a/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
+++ b/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
@@ -106,13 +106,13 @@ FrozenRewritePatternSet::FrozenRewritePatternSet(
       impl->nativeOpSpecificPatternList.push_back(std::move(pat));
       continue;
     }
-    if (Optional<TypeID> interfaceID = pat->getRootInterfaceID()) {
+    if (std::optional<TypeID> interfaceID = pat->getRootInterfaceID()) {
       addToOpsWhen(pat, [&](RegisteredOperationName info) {
         return info.hasInterface(*interfaceID);
       });
       continue;
     }
-    if (Optional<TypeID> traitID = pat->getRootTraitID()) {
+    if (std::optional<TypeID> traitID = pat->getRootTraitID()) {
       addToOpsWhen(pat, [&](RegisteredOperationName info) {
         return info.hasTrait(*traitID);
       });

diff  --git a/mlir/lib/Support/Timing.cpp b/mlir/lib/Support/Timing.cpp
index 48eb1e84adf3c..844f629ded087 100644
--- a/mlir/lib/Support/Timing.cpp
+++ b/mlir/lib/Support/Timing.cpp
@@ -509,7 +509,7 @@ void DefaultTimingManager::dumpAsTree(raw_ostream &os) {
   impl->rootTimer->print(os, DisplayMode::Tree);
 }
 
-Optional<void *> DefaultTimingManager::rootTimer() {
+std::optional<void *> DefaultTimingManager::rootTimer() {
   if (impl->enabled)
     return impl->rootTimer.get();
   return std::nullopt;

diff  --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index c9ad8a8ff34aa..b5c1bef4d2718 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -57,7 +57,7 @@ using namespace mlir::LLVM::detail;
 static FailureOr<llvm::DataLayout>
 translateDataLayout(DataLayoutSpecInterface attribute,
                     const DataLayout &dataLayout,
-                    Optional<Location> loc = std::nullopt) {
+                    std::optional<Location> loc = std::nullopt) {
   if (!loc)
     loc = UnknownLoc::get(attribute.getContext());
 
@@ -120,7 +120,7 @@ translateDataLayout(DataLayoutSpecInterface attribute,
               unsigned preferred =
                   dataLayout.getTypePreferredAlignment(type) * 8u;
               layoutStream << size << ":" << abi << ":" << preferred;
-              if (Optional<unsigned> index = extractPointerSpecValue(
+              if (std::optional<unsigned> index = extractPointerSpecValue(
                       entry.getValue(), PtrDLEntryPos::Index))
                 layoutStream << ":" << *index;
               return success();

diff  --git a/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp b/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
index aa64af7651ccd..78afcc7003eff 100644
--- a/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
+++ b/mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
@@ -74,10 +74,9 @@ Value spirv::Deserializer::getValue(uint32_t id) {
   return valueMap.lookup(id);
 }
 
-LogicalResult
-spirv::Deserializer::sliceInstruction(spirv::Opcode &opcode,
-                                      ArrayRef<uint32_t> &operands,
-                                      Optional<spirv::Opcode> expectedOpcode) {
+LogicalResult spirv::Deserializer::sliceInstruction(
+    spirv::Opcode &opcode, ArrayRef<uint32_t> &operands,
+    std::optional<spirv::Opcode> expectedOpcode) {
   auto binarySize = binary.size();
   if (curOffset >= binarySize) {
     return emitError(unknownLoc, "expected ")

diff  --git a/mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp b/mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp
index 73af433099729..8b0581d8be04c 100644
--- a/mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp
+++ b/mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp
@@ -501,7 +501,7 @@ spirv::Deserializer::processFunctionEnd(ArrayRef<uint32_t> operands) {
   return success();
 }
 
-Optional<std::pair<Attribute, Type>>
+std::optional<std::pair<Attribute, Type>>
 spirv::Deserializer::getConstant(uint32_t id) {
   auto constIt = constantMap.find(id);
   if (constIt == constantMap.end())
@@ -509,7 +509,7 @@ spirv::Deserializer::getConstant(uint32_t id) {
   return constIt->getSecond();
 }
 
-Optional<spirv::SpecConstOperationMaterializationInfo>
+std::optional<spirv::SpecConstOperationMaterializationInfo>
 spirv::Deserializer::getSpecConstantOperation(uint32_t id) {
   auto constIt = specConstOperationMap.find(id);
   if (constIt == specConstOperationMap.end())
@@ -1513,7 +1513,7 @@ spirv::Deserializer::processBranchConditional(ArrayRef<uint32_t> operands) {
   auto *trueBlock = getOrCreateBlock(operands[1]);
   auto *falseBlock = getOrCreateBlock(operands[2]);
 
-  Optional<std::pair<uint32_t, uint32_t>> weights;
+  std::optional<std::pair<uint32_t, uint32_t>> weights;
   if (operands.size() == 5) {
     weights = std::make_pair(operands[3], operands[4]);
   }

diff  --git a/mlir/lib/Target/SPIRV/Deserialization/Deserializer.h b/mlir/lib/Target/SPIRV/Deserialization/Deserializer.h
index 72c68a865cd01..9d41166b0fb7a 100644
--- a/mlir/lib/Target/SPIRV/Deserialization/Deserializer.h
+++ b/mlir/lib/Target/SPIRV/Deserialization/Deserializer.h
@@ -186,11 +186,11 @@ class Deserializer {
   LogicalResult processFunctionEnd(ArrayRef<uint32_t> operands);
 
   /// Gets the constant's attribute and type associated with the given <id>.
-  Optional<std::pair<Attribute, Type>> getConstant(uint32_t id);
+  std::optional<std::pair<Attribute, Type>> getConstant(uint32_t id);
 
   /// Gets the info needed to materialize the spec constant operation op
   /// associated with the given <id>.
-  Optional<SpecConstOperationMaterializationInfo>
+  std::optional<SpecConstOperationMaterializationInfo>
   getSpecConstantOperation(uint32_t id);
 
   /// Gets the constant's integer attribute with the given <id>. Returns a
@@ -422,7 +422,7 @@ class Deserializer {
   /// compose the error message) or the next instruction is malformed.
   LogicalResult
   sliceInstruction(spirv::Opcode &opcode, ArrayRef<uint32_t> &operands,
-                   Optional<spirv::Opcode> expectedOpcode = std::nullopt);
+                   std::optional<spirv::Opcode> expectedOpcode = std::nullopt);
 
   /// Processes a SPIR-V instruction with the given `opcode` and `operands`.
   /// This method is the main entrance for handling SPIR-V instruction; it
@@ -483,7 +483,7 @@ class Deserializer {
 
   /// Contains the data of the OpLine instruction which precedes the current
   /// processing instruction.
-  llvm::Optional<DebugLine> debugLine;
+  std::optional<DebugLine> debugLine;
 
   /// The current word offset into the binary module.
   unsigned curOffset = 0;
@@ -498,7 +498,7 @@ class Deserializer {
   OwningOpRef<spirv::ModuleOp> module;
 
   /// The current function under construction.
-  Optional<spirv::FuncOp> curFunction;
+  std::optional<spirv::FuncOp> curFunction;
 
   /// The current block under construction.
   Block *curBlock = nullptr;

diff  --git a/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp b/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp
index 7a6a0479513ad..292ed97cfc066 100644
--- a/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp
+++ b/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp
@@ -1046,7 +1046,7 @@ LogicalResult Serializer::emitPhiForBlockArguments(Block *block) {
       predecessors.emplace_back(spirvPredecessor, branchOp.getOperands());
     } else if (auto branchCondOp =
                    dyn_cast<spirv::BranchConditionalOp>(terminator)) {
-      Optional<OperandRange> blockOperands;
+      std::optional<OperandRange> blockOperands;
       if (branchCondOp.getTrueTarget() == block) {
         blockOperands = branchCondOp.getTrueTargetOperands();
       } else {

diff  --git a/mlir/lib/Tools/PDLL/AST/NodePrinter.cpp b/mlir/lib/Tools/PDLL/AST/NodePrinter.cpp
index c2b8acaf473ca..4155fd69c5897 100644
--- a/mlir/lib/Tools/PDLL/AST/NodePrinter.cpp
+++ b/mlir/lib/Tools/PDLL/AST/NodePrinter.cpp
@@ -134,7 +134,7 @@ void NodePrinter::print(Type type) {
       .Case([&](ConstraintType) { os << "Constraint"; })
       .Case([&](OperationType type) {
         os << "Op";
-        if (Optional<StringRef> name = type.getName())
+        if (std::optional<StringRef> name = type.getName())
           os << "<" << *name << ">";
       })
       .Case([&](RangeType type) {
@@ -298,7 +298,7 @@ void NodePrinter::printImpl(const TypeRangeConstraintDecl *decl) {
 void NodePrinter::printImpl(const UserConstraintDecl *decl) {
   os << "UserConstraintDecl " << decl << " Name<" << decl->getName().getName()
      << "> ResultType<" << decl->getResultType() << ">";
-  if (Optional<StringRef> codeBlock = decl->getCodeBlock()) {
+  if (std::optional<StringRef> codeBlock = decl->getCodeBlock()) {
     os << " Code<";
     llvm::printEscapedString(*codeBlock, os);
     os << ">";
@@ -330,7 +330,7 @@ void NodePrinter::printImpl(const NamedAttributeDecl *decl) {
 
 void NodePrinter::printImpl(const OpNameDecl *decl) {
   os << "OpNameDecl " << decl;
-  if (Optional<StringRef> name = decl->getName())
+  if (std::optional<StringRef> name = decl->getName())
     os << " Name<" << *name << ">";
   os << "\n";
 }
@@ -339,7 +339,7 @@ void NodePrinter::printImpl(const PatternDecl *decl) {
   os << "PatternDecl " << decl;
   if (const Name *name = decl->getName())
     os << " Name<" << name->getName() << ">";
-  if (Optional<uint16_t> benefit = decl->getBenefit())
+  if (std::optional<uint16_t> benefit = decl->getBenefit())
     os << " Benefit<" << *benefit << ">";
   if (decl->hasBoundedRewriteRecursion())
     os << " Recursion";
@@ -351,7 +351,7 @@ void NodePrinter::printImpl(const PatternDecl *decl) {
 void NodePrinter::printImpl(const UserRewriteDecl *decl) {
   os << "UserRewriteDecl " << decl << " Name<" << decl->getName().getName()
      << "> ResultType<" << decl->getResultType() << ">";
-  if (Optional<StringRef> codeBlock = decl->getCodeBlock()) {
+  if (std::optional<StringRef> codeBlock = decl->getCodeBlock()) {
     os << " Code<";
     llvm::printEscapedString(*codeBlock, os);
     os << ">";

diff  --git a/mlir/lib/Tools/PDLL/AST/Nodes.cpp b/mlir/lib/Tools/PDLL/AST/Nodes.cpp
index 9842e39d89ebc..47556295b7cbe 100644
--- a/mlir/lib/Tools/PDLL/AST/Nodes.cpp
+++ b/mlir/lib/Tools/PDLL/AST/Nodes.cpp
@@ -326,7 +326,7 @@ OperationExpr::create(Context &ctx, SMRange loc, const ods::Operation *odsOp,
   return opExpr;
 }
 
-Optional<StringRef> OperationExpr::getName() const {
+std::optional<StringRef> OperationExpr::getName() const {
   return getNameDecl()->getName();
 }
 
@@ -405,7 +405,7 @@ OpConstraintDecl *OpConstraintDecl::create(Context &ctx, SMRange loc,
       OpConstraintDecl(loc, nameDecl);
 }
 
-Optional<StringRef> OpConstraintDecl::getName() const {
+std::optional<StringRef> OpConstraintDecl::getName() const {
   return getNameDecl()->getName();
 }
 
@@ -452,16 +452,17 @@ ValueRangeConstraintDecl::create(Context &ctx, SMRange loc, Expr *typeExpr) {
 // UserConstraintDecl
 //===----------------------------------------------------------------------===//
 
-Optional<StringRef>
+std::optional<StringRef>
 UserConstraintDecl::getNativeInputType(unsigned index) const {
   return hasNativeInputTypes ? getTrailingObjects<StringRef>()[index]
-                             : Optional<StringRef>();
+                             : std::optional<StringRef>();
 }
 
 UserConstraintDecl *UserConstraintDecl::createImpl(
     Context &ctx, const Name &name, ArrayRef<VariableDecl *> inputs,
     ArrayRef<StringRef> nativeInputTypes, ArrayRef<VariableDecl *> results,
-    Optional<StringRef> codeBlock, const CompoundStmt *body, Type resultType) {
+    std::optional<StringRef> codeBlock, const CompoundStmt *body,
+    Type resultType) {
   bool hasNativeInputTypes = !nativeInputTypes.empty();
   assert(!hasNativeInputTypes || nativeInputTypes.size() == inputs.size());
 
@@ -516,7 +517,7 @@ OpNameDecl *OpNameDecl::create(Context &ctx, SMRange loc) {
 //===----------------------------------------------------------------------===//
 
 PatternDecl *PatternDecl::create(Context &ctx, SMRange loc, const Name *name,
-                                 Optional<uint16_t> benefit,
+                                 std::optional<uint16_t> benefit,
                                  bool hasBoundedRecursion,
                                  const CompoundStmt *body) {
   return new (ctx.getAllocator().Allocate<PatternDecl>())
@@ -530,7 +531,7 @@ PatternDecl *PatternDecl::create(Context &ctx, SMRange loc, const Name *name,
 UserRewriteDecl *UserRewriteDecl::createImpl(Context &ctx, const Name &name,
                                              ArrayRef<VariableDecl *> inputs,
                                              ArrayRef<VariableDecl *> results,
-                                             Optional<StringRef> codeBlock,
+                                             std::optional<StringRef> codeBlock,
                                              const CompoundStmt *body,
                                              Type resultType) {
   unsigned allocSize = UserRewriteDecl::totalSizeToAlloc<VariableDecl *>(

diff  --git a/mlir/lib/Tools/PDLL/AST/Types.cpp b/mlir/lib/Tools/PDLL/AST/Types.cpp
index 4ee291391246b..fc4cb613dd22a 100644
--- a/mlir/lib/Tools/PDLL/AST/Types.cpp
+++ b/mlir/lib/Tools/PDLL/AST/Types.cpp
@@ -70,16 +70,18 @@ ConstraintType ConstraintType::get(Context &context) {
 // OperationType
 //===----------------------------------------------------------------------===//
 
-OperationType OperationType::get(Context &context, Optional<StringRef> name,
+OperationType OperationType::get(Context &context,
+                                 std::optional<StringRef> name,
                                  const ods::Operation *odsOp) {
   return context.getTypeUniquer().get<ImplTy>(
       /*initFn=*/function_ref<void(ImplTy *)>(),
       std::make_pair(name.value_or(""), odsOp));
 }
 
-Optional<StringRef> OperationType::getName() const {
+std::optional<StringRef> OperationType::getName() const {
   StringRef name = getImplAs<ImplTy>()->getValue().first;
-  return name.empty() ? Optional<StringRef>() : Optional<StringRef>(name);
+  return name.empty() ? std::optional<StringRef>()
+                      : std::optional<StringRef>(name);
 }
 
 const ods::Operation *OperationType::getODSOperation() const {

diff  --git a/mlir/lib/Tools/PDLL/CodeGen/CPPGen.cpp b/mlir/lib/Tools/PDLL/CodeGen/CPPGen.cpp
index 3c490dff7d2d7..b02edc6717510 100644
--- a/mlir/lib/Tools/PDLL/CodeGen/CPPGen.cpp
+++ b/mlir/lib/Tools/PDLL/CodeGen/CPPGen.cpp
@@ -191,7 +191,7 @@ StringRef CodeGen::getNativeTypeName(ast::VariableDecl *decl) {
   // Try to extract a type name from the variable's constraints.
   for (ast::ConstraintRef &cst : decl->getConstraints()) {
     if (auto *userCst = dyn_cast<ast::UserConstraintDecl>(cst.constraint)) {
-      if (Optional<StringRef> name = userCst->getNativeInputType(0))
+      if (std::optional<StringRef> name = userCst->getNativeInputType(0))
         return *name;
       return getNativeTypeName(userCst->getInputs()[0]);
     }

diff  --git a/mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp b/mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp
index 432c64964f7a4..8225680aac91e 100644
--- a/mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp
+++ b/mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp
@@ -283,7 +283,8 @@ void CodeGen::genImpl(const ast::PatternDecl *decl) {
   // here.
   pdl::PatternOp pattern = builder.create<pdl::PatternOp>(
       genLoc(decl->getLoc()), decl->getBenefit(),
-      name ? Optional<StringRef>(name->getName()) : Optional<StringRef>());
+      name ? std::optional<StringRef>(name->getName())
+           : std::optional<StringRef>());
 
   OpBuilder::InsertionGuard savedInsertPoint(builder);
   builder.setInsertionPointToStart(pattern.getBody());
@@ -496,7 +497,7 @@ Value CodeGen::genExprImpl(const ast::MemberAccessExpr *expr) {
 
 Value CodeGen::genExprImpl(const ast::OperationExpr *expr) {
   Location loc = genLoc(expr->getLoc());
-  Optional<StringRef> opName = expr->getName();
+  std::optional<StringRef> opName = expr->getName();
 
   // Operands.
   SmallVector<Value> operands;

diff  --git a/mlir/lib/Tools/PDLL/Parser/Parser.cpp b/mlir/lib/Tools/PDLL/Parser/Parser.cpp
index 61a1f47f02320..044aa612b67fb 100644
--- a/mlir/lib/Tools/PDLL/Parser/Parser.cpp
+++ b/mlir/lib/Tools/PDLL/Parser/Parser.cpp
@@ -131,7 +131,7 @@ class Parser {
 
   /// Lookup ODS information for the given operation, returns nullptr if no
   /// information is found.
-  const ods::Operation *lookupODSOperation(Optional<StringRef> opName) {
+  const ods::Operation *lookupODSOperation(std::optional<StringRef> opName) {
     return opName ? ctx.getODSContext().lookupOperation(*opName) : nullptr;
   }
 
@@ -186,13 +186,13 @@ class Parser {
 
   /// This structure contains the set of pattern metadata that may be parsed.
   struct ParsedPatternMetadata {
-    Optional<uint16_t> benefit;
+    std::optional<uint16_t> benefit;
     bool hasBoundedRecursion = false;
   };
 
   FailureOr<ast::Decl *> parseTopLevelDecl();
   FailureOr<ast::NamedAttributeDecl *>
-  parseNamedAttributeDecl(Optional<StringRef> parentOpName);
+  parseNamedAttributeDecl(std::optional<StringRef> parentOpName);
 
   /// Parse an argument variable as part of the signature of a
   /// UserConstraintDecl or UserRewriteDecl.
@@ -299,7 +299,7 @@ class Parser {
   /// that will be constrained by this constraint. `allowInlineTypeConstraints`
   /// allows the use of inline Type constraints, e.g. `Value<valueType: Type>`.
   FailureOr<ast::ConstraintRef>
-  parseConstraint(Optional<SMRange> &typeConstraint,
+  parseConstraint(std::optional<SMRange> &typeConstraint,
                   ArrayRef<ast::ConstraintRef> existingConstraints,
                   bool allowInlineTypeConstraints);
 
@@ -424,17 +424,18 @@ class Parser {
                       MutableArrayRef<ast::NamedAttributeDecl *> attributes,
                       SmallVectorImpl<ast::Expr *> &results);
   LogicalResult
-  validateOperationOperands(SMRange loc, Optional<StringRef> name,
+  validateOperationOperands(SMRange loc, std::optional<StringRef> name,
                             const ods::Operation *odsOp,
                             SmallVectorImpl<ast::Expr *> &operands);
-  LogicalResult validateOperationResults(SMRange loc, Optional<StringRef> name,
+  LogicalResult validateOperationResults(SMRange loc,
+                                         std::optional<StringRef> name,
                                          const ods::Operation *odsOp,
                                          SmallVectorImpl<ast::Expr *> &results);
   void checkOperationResultTypeInferrence(SMRange loc, StringRef name,
                                           const ods::Operation *odsOp);
   LogicalResult validateOperationOperandsOrResults(
-      StringRef groupName, SMRange loc, Optional<SMRange> odsOpLoc,
-      Optional<StringRef> name, SmallVectorImpl<ast::Expr *> &values,
+      StringRef groupName, SMRange loc, std::optional<SMRange> odsOpLoc,
+      std::optional<StringRef> name, SmallVectorImpl<ast::Expr *> &values,
       ArrayRef<ods::OperandOrResult> odsValues, ast::Type singleTy,
       ast::RangeType rangeTy);
   FailureOr<ast::TupleExpr *> createTupleExpr(SMRange loc,
@@ -461,7 +462,7 @@ class Parser {
   /// results.
 
   LogicalResult codeCompleteMemberAccess(ast::Expr *parentExpr);
-  LogicalResult codeCompleteAttributeName(Optional<StringRef> opName);
+  LogicalResult codeCompleteAttributeName(std::optional<StringRef> opName);
   LogicalResult codeCompleteConstraintName(ast::Type inferredType,
                                            bool allowInlineTypeConstraints);
   LogicalResult codeCompleteDialectName();
@@ -470,9 +471,9 @@ class Parser {
   LogicalResult codeCompleteIncludeFilename(StringRef curPath);
 
   void codeCompleteCallSignature(ast::Node *parent, unsigned currentNumArgs);
-  void codeCompleteOperationOperandsSignature(Optional<StringRef> opName,
+  void codeCompleteOperationOperandsSignature(std::optional<StringRef> opName,
                                               unsigned currentNumOperands);
-  void codeCompleteOperationResultsSignature(Optional<StringRef> opName,
+  void codeCompleteOperationResultsSignature(std::optional<StringRef> opName,
                                              unsigned currentNumResults);
 
   //===--------------------------------------------------------------------===//
@@ -1048,7 +1049,7 @@ FailureOr<ast::Decl *> Parser::parseTopLevelDecl() {
 }
 
 FailureOr<ast::NamedAttributeDecl *>
-Parser::parseNamedAttributeDecl(Optional<StringRef> parentOpName) {
+Parser::parseNamedAttributeDecl(std::optional<StringRef> parentOpName) {
   // Check for name code completion.
   if (curToken.is(Token::code_complete))
     return codeCompleteAttributeName(parentOpName);
@@ -1344,7 +1345,7 @@ FailureOr<T *> Parser::parseUserNativeConstraintOrRewriteDecl(
     ArrayRef<ast::VariableDecl *> results, ast::Type resultType) {
   // If followed by a string, the native code body has also been specified.
   std::string codeStrStorage;
-  Optional<StringRef> optCodeStr;
+  std::optional<StringRef> optCodeStr;
   if (curToken.isString()) {
     codeStrStorage = curToken.getStringValue();
     optCodeStr = codeStrStorage;
@@ -1528,8 +1529,8 @@ FailureOr<ast::Decl *> Parser::parsePatternDecl() {
 
 LogicalResult
 Parser::parsePatternDeclMetadata(ParsedPatternMetadata &metadata) {
-  Optional<SMRange> benefitLoc;
-  Optional<SMRange> hasBoundedRecursionLoc;
+  std::optional<SMRange> benefitLoc;
+  std::optional<SMRange> hasBoundedRecursionLoc;
 
   do {
     // Handle metadata code completion.
@@ -1641,7 +1642,7 @@ Parser::defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type,
 
 LogicalResult Parser::parseVariableDeclConstraintList(
     SmallVectorImpl<ast::ConstraintRef> &constraints) {
-  Optional<SMRange> typeConstraint;
+  std::optional<SMRange> typeConstraint;
   auto parseSingleConstraint = [&] {
     FailureOr<ast::ConstraintRef> constraint = parseConstraint(
         typeConstraint, constraints, /*allowInlineTypeConstraints=*/true);
@@ -1663,7 +1664,7 @@ LogicalResult Parser::parseVariableDeclConstraintList(
 }
 
 FailureOr<ast::ConstraintRef>
-Parser::parseConstraint(Optional<SMRange> &typeConstraint,
+Parser::parseConstraint(std::optional<SMRange> &typeConstraint,
                         ArrayRef<ast::ConstraintRef> existingConstraints,
                         bool allowInlineTypeConstraints) {
   auto parseTypeConstraint = [&](ast::Expr *&typeExpr) -> LogicalResult {
@@ -1783,7 +1784,7 @@ Parser::parseConstraint(Optional<SMRange> &typeConstraint,
 }
 
 FailureOr<ast::ConstraintRef> Parser::parseArgOrResultConstraint() {
-  Optional<SMRange> typeConstraint;
+  std::optional<SMRange> typeConstraint;
   return parseConstraint(typeConstraint, /*existingConstraints=*/std::nullopt,
                          /*allowInlineTypeConstraints=*/false);
 }
@@ -2029,7 +2030,7 @@ Parser::parseOperationExpr(OpResultTypeContext inputResultTypeContext) {
       parseWrappedOperationName(allowEmptyName);
   if (failed(opNameDecl))
     return failure();
-  Optional<StringRef> opName = (*opNameDecl)->getName();
+  std::optional<StringRef> opName = (*opNameDecl)->getName();
 
   // Functor used to create an implicit range variable, used for implicit "all"
   // operand or results variables.
@@ -2813,7 +2814,7 @@ FailureOr<ast::OperationExpr *> Parser::createOperationExpr(
     SmallVectorImpl<ast::Expr *> &operands,
     MutableArrayRef<ast::NamedAttributeDecl *> attributes,
     SmallVectorImpl<ast::Expr *> &results) {
-  Optional<StringRef> opNameRef = name->getName();
+  std::optional<StringRef> opNameRef = name->getName();
   const ods::Operation *odsOp = lookupODSOperation(opNameRef);
 
   // Verify the inputs operands.
@@ -2853,21 +2854,21 @@ FailureOr<ast::OperationExpr *> Parser::createOperationExpr(
 }
 
 LogicalResult
-Parser::validateOperationOperands(SMRange loc, Optional<StringRef> name,
+Parser::validateOperationOperands(SMRange loc, std::optional<StringRef> name,
                                   const ods::Operation *odsOp,
                                   SmallVectorImpl<ast::Expr *> &operands) {
   return validateOperationOperandsOrResults(
-      "operand", loc, odsOp ? odsOp->getLoc() : Optional<SMRange>(), name,
+      "operand", loc, odsOp ? odsOp->getLoc() : std::optional<SMRange>(), name,
       operands, odsOp ? odsOp->getOperands() : std::nullopt, valueTy,
       valueRangeTy);
 }
 
 LogicalResult
-Parser::validateOperationResults(SMRange loc, Optional<StringRef> name,
+Parser::validateOperationResults(SMRange loc, std::optional<StringRef> name,
                                  const ods::Operation *odsOp,
                                  SmallVectorImpl<ast::Expr *> &results) {
   return validateOperationOperandsOrResults(
-      "result", loc, odsOp ? odsOp->getLoc() : Optional<SMRange>(), name,
+      "result", loc, odsOp ? odsOp->getLoc() : std::optional<SMRange>(), name,
       results, odsOp ? odsOp->getResults() : std::nullopt, typeTy, typeRangeTy);
 }
 
@@ -2914,8 +2915,8 @@ void Parser::checkOperationResultTypeInferrence(SMRange loc, StringRef opName,
 }
 
 LogicalResult Parser::validateOperationOperandsOrResults(
-    StringRef groupName, SMRange loc, Optional<SMRange> odsOpLoc,
-    Optional<StringRef> name, SmallVectorImpl<ast::Expr *> &values,
+    StringRef groupName, SMRange loc, std::optional<SMRange> odsOpLoc,
+    std::optional<StringRef> name, SmallVectorImpl<ast::Expr *> &values,
     ArrayRef<ods::OperandOrResult> odsValues, ast::Type singleTy,
     ast::RangeType rangeTy) {
   // All operation types accept a single range parameter.
@@ -3111,7 +3112,8 @@ LogicalResult Parser::codeCompleteMemberAccess(ast::Expr *parentExpr) {
   return failure();
 }
 
-LogicalResult Parser::codeCompleteAttributeName(Optional<StringRef> opName) {
+LogicalResult
+Parser::codeCompleteAttributeName(std::optional<StringRef> opName) {
   if (opName)
     codeCompleteContext->codeCompleteOperationAttributeName(*opName);
   return failure();
@@ -3155,13 +3157,13 @@ void Parser::codeCompleteCallSignature(ast::Node *parent,
 }
 
 void Parser::codeCompleteOperationOperandsSignature(
-    Optional<StringRef> opName, unsigned currentNumOperands) {
+    std::optional<StringRef> opName, unsigned currentNumOperands) {
   codeCompleteContext->codeCompleteOperationOperandsSignature(
       opName, currentNumOperands);
 }
 
-void Parser::codeCompleteOperationResultsSignature(Optional<StringRef> opName,
-                                                   unsigned currentNumResults) {
+void Parser::codeCompleteOperationResultsSignature(
+    std::optional<StringRef> opName, unsigned currentNumResults) {
   codeCompleteContext->codeCompleteOperationResultsSignature(opName,
                                                              currentNumResults);
 }

diff  --git a/mlir/lib/Tools/lsp-server-support/Protocol.h b/mlir/lib/Tools/lsp-server-support/Protocol.h
index 0a001a03faacc..3112e9f4cd16a 100644
--- a/mlir/lib/Tools/lsp-server-support/Protocol.h
+++ b/mlir/lib/Tools/lsp-server-support/Protocol.h
@@ -528,7 +528,7 @@ struct Hover {
 
   /// An optional range is a range inside a text document that is used to
   /// visualize a hover, e.g. by changing the background color.
-  Optional<Range> range;
+  std::optional<Range> range;
 };
 
 /// Add support for JSON serialization.
@@ -931,7 +931,7 @@ struct ParameterInformation {
 
   /// Inclusive start and exclusive end offsets withing the containing signature
   /// label.
-  Optional<std::pair<unsigned, unsigned>> labelOffsets;
+  std::optional<std::pair<unsigned, unsigned>> labelOffsets;
 
   /// The documentation of this parameter. Optional.
   std::string documentation;
@@ -1184,13 +1184,13 @@ struct CodeAction {
 
   /// The kind of the code action.
   /// Used to filter code actions.
-  Optional<std::string> kind;
+  std::optional<std::string> kind;
   const static llvm::StringLiteral kQuickFix;
   const static llvm::StringLiteral kRefactor;
   const static llvm::StringLiteral kInfo;
 
   /// The diagnostics that this code action resolves.
-  Optional<std::vector<Diagnostic>> diagnostics;
+  std::optional<std::vector<Diagnostic>> diagnostics;
 
   /// Marks this as a preferred action. Preferred actions are used by the
   /// `auto fix` command and can be targeted by keybindings.
@@ -1200,7 +1200,7 @@ struct CodeAction {
   bool isPreferred = false;
 
   /// The workspace edit this code action performs.
-  Optional<WorkspaceEdit> edit;
+  std::optional<WorkspaceEdit> edit;
 };
 
 /// Add support for JSON serialization.

diff  --git a/mlir/lib/Tools/lsp-server-support/SourceMgrUtils.cpp b/mlir/lib/Tools/lsp-server-support/SourceMgrUtils.cpp
index d65f77c420787..122d4e02ddb51 100644
--- a/mlir/lib/Tools/lsp-server-support/SourceMgrUtils.cpp
+++ b/mlir/lib/Tools/lsp-server-support/SourceMgrUtils.cpp
@@ -66,8 +66,8 @@ SMRange lsp::convertTokenLocToRange(SMLoc loc) {
   return SMRange(loc, SMLoc::getFromPointer(curPtr));
 }
 
-Optional<std::string> lsp::extractSourceDocComment(llvm::SourceMgr &sourceMgr,
-                                                   SMLoc loc) {
+std::optional<std::string>
+lsp::extractSourceDocComment(llvm::SourceMgr &sourceMgr, SMLoc loc) {
   // This is a heuristic, and isn't intended to cover every case, but should
   // cover the most common. We essentially look for a comment preceding the
   // line, and if we find one, use that as the documentation.
@@ -81,7 +81,7 @@ Optional<std::string> lsp::extractSourceDocComment(llvm::SourceMgr &sourceMgr,
   StringRef buffer(bufferStart, loc.getPointer() - bufferStart);
 
   // Pop the last line from the buffer string.
-  auto popLastLine = [&]() -> Optional<StringRef> {
+  auto popLastLine = [&]() -> std::optional<StringRef> {
     size_t newlineOffset = buffer.find_last_of("\n");
     if (newlineOffset == StringRef::npos)
       return std::nullopt;
@@ -96,7 +96,7 @@ Optional<std::string> lsp::extractSourceDocComment(llvm::SourceMgr &sourceMgr,
 
   // Try to parse a comment string from the source file.
   SmallVector<StringRef> commentLines;
-  while (Optional<StringRef> line = popLastLine()) {
+  while (std::optional<StringRef> line = popLastLine()) {
     // Check for a comment at the beginning of the line.
     if (!line->startswith("//"))
       break;

diff  --git a/mlir/lib/Tools/lsp-server-support/SourceMgrUtils.h b/mlir/lib/Tools/lsp-server-support/SourceMgrUtils.h
index da57f3df3c8ef..523ef89cf0ecc 100644
--- a/mlir/lib/Tools/lsp-server-support/SourceMgrUtils.h
+++ b/mlir/lib/Tools/lsp-server-support/SourceMgrUtils.h
@@ -31,8 +31,8 @@ SMRange convertTokenLocToRange(SMLoc loc);
 
 /// Extract a documentation comment for the given location within the source
 /// manager. Returns std::nullopt if no comment could be computed.
-Optional<std::string> extractSourceDocComment(llvm::SourceMgr &sourceMgr,
-                                              SMLoc loc);
+std::optional<std::string> extractSourceDocComment(llvm::SourceMgr &sourceMgr,
+                                                   SMLoc loc);
 
 /// Returns true if the given range contains the given source location. Note
 /// that this has 
diff erent behavior than SMRange because it is inclusive of the

diff  --git a/mlir/lib/Tools/lsp-server-support/Transport.cpp b/mlir/lib/Tools/lsp-server-support/Transport.cpp
index a18603eb33a73..e5bceac1e907c 100644
--- a/mlir/lib/Tools/lsp-server-support/Transport.cpp
+++ b/mlir/lib/Tools/lsp-server-support/Transport.cpp
@@ -229,11 +229,11 @@ bool JSONTransport::handleMessage(llvm::json::Value msg,
   // Message must be an object with "jsonrpc":"2.0".
   llvm::json::Object *object = msg.getAsObject();
   if (!object ||
-      object->getString("jsonrpc") != llvm::Optional<StringRef>("2.0"))
+      object->getString("jsonrpc") != std::optional<StringRef>("2.0"))
     return false;
 
   // `id` may be any JSON value. If absent, this is a notification.
-  llvm::Optional<llvm::json::Value> id;
+  std::optional<llvm::json::Value> id;
   if (llvm::json::Value *i = object->get("id"))
     id = std::move(*i);
   std::optional<StringRef> method = object->getString("method");

diff  --git a/mlir/lib/Tools/mlir-lsp-server/LSPServer.cpp b/mlir/lib/Tools/mlir-lsp-server/LSPServer.cpp
index 81053c1003234..ab98729e57c13 100644
--- a/mlir/lib/Tools/mlir-lsp-server/LSPServer.cpp
+++ b/mlir/lib/Tools/mlir-lsp-server/LSPServer.cpp
@@ -172,7 +172,8 @@ void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams &params) {
   publishDiagnostics(diagParams);
 }
 void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams &params) {
-  Optional<int64_t> version = server.removeDocument(params.textDocument.uri);
+  std::optional<int64_t> version =
+      server.removeDocument(params.textDocument.uri);
   if (!version)
     return;
 

diff  --git a/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp b/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp
index 11015a3ff5a9f..3699b51f2de46 100644
--- a/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp
+++ b/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp
@@ -25,8 +25,8 @@ using namespace mlir;
 
 /// Returns a language server location from the given MLIR file location.
 /// `uriScheme` is the scheme to use when building new uris.
-static Optional<lsp::Location> getLocationFromLoc(StringRef uriScheme,
-                                                  FileLineColLoc loc) {
+static std::optional<lsp::Location> getLocationFromLoc(StringRef uriScheme,
+                                                       FileLineColLoc loc) {
   llvm::Expected<lsp::URIForFile> sourceURI =
       lsp::URIForFile::fromFile(loc.getFilename(), uriScheme);
   if (!sourceURI) {
@@ -46,16 +46,17 @@ static Optional<lsp::Location> getLocationFromLoc(StringRef uriScheme,
 /// std::nullopt if one couldn't be created. `uriScheme` is the scheme to use
 /// when building new uris. `uri` is an optional additional filter that, when
 /// present, is used to filter sub locations that do not share the same uri.
-static Optional<lsp::Location>
+static std::optional<lsp::Location>
 getLocationFromLoc(llvm::SourceMgr &sourceMgr, Location loc,
                    StringRef uriScheme, const lsp::URIForFile *uri = nullptr) {
-  Optional<lsp::Location> location;
+  std::optional<lsp::Location> location;
   loc->walk([&](Location nestedLoc) {
     FileLineColLoc fileLoc = nestedLoc.dyn_cast<FileLineColLoc>();
     if (!fileLoc)
       return WalkResult::advance();
 
-    Optional<lsp::Location> sourceLoc = getLocationFromLoc(uriScheme, fileLoc);
+    std::optional<lsp::Location> sourceLoc =
+        getLocationFromLoc(uriScheme, fileLoc);
     if (sourceLoc && (!uri || sourceLoc->uri == *uri)) {
       location = *sourceLoc;
       SMLoc loc = sourceMgr.FindLocForLineAndColumn(
@@ -64,7 +65,7 @@ getLocationFromLoc(llvm::SourceMgr &sourceMgr, Location loc,
       // Use range of potential identifier starting at location, else length 1
       // range.
       location->range.end.character += 1;
-      if (Optional<SMRange> range = lsp::convertTokenLocToRange(loc)) {
+      if (std::optional<SMRange> range = lsp::convertTokenLocToRange(loc)) {
         auto lineCol = sourceMgr.getLineAndColumn(range->End);
         location->range.end.character =
             std::max(fileLoc.getColumn() + 1, lineCol.second - 1);
@@ -87,7 +88,7 @@ static void collectLocationsFromLoc(Location loc,
     if (!fileLoc || !visitedLocs.insert(nestedLoc))
       return WalkResult::advance();
 
-    Optional<lsp::Location> sourceLoc =
+    std::optional<lsp::Location> sourceLoc =
         getLocationFromLoc(uri.scheme(), fileLoc);
     if (sourceLoc && sourceLoc->uri != uri)
       locations.push_back(*sourceLoc);
@@ -128,7 +129,7 @@ static bool isDefOrUse(const AsmParserState::SMDefinition &def, SMLoc loc,
 
 /// Given a location pointing to a result, return the result number it refers
 /// to or std::nullopt if it refers to all of the results.
-static Optional<unsigned> getResultNumberFromLoc(SMLoc loc) {
+static std::optional<unsigned> getResultNumberFromLoc(SMLoc loc) {
   // Skip all of the identifier characters.
   auto isIdentifierChar = [](char c) {
     return isalnum(c) || c == '%' || c == '$' || c == '.' || c == '_' ||
@@ -149,13 +150,13 @@ static Optional<unsigned> getResultNumberFromLoc(SMLoc loc) {
     ++curPtr;
   StringRef numberStr(numberStart, curPtr - numberStart);
   unsigned resultNumber = 0;
-  return numberStr.consumeInteger(10, resultNumber) ? Optional<unsigned>()
+  return numberStr.consumeInteger(10, resultNumber) ? std::optional<unsigned>()
                                                     : resultNumber;
 }
 
 /// Given a source location range, return the text covered by the given range.
 /// If the range is invalid, returns std::nullopt.
-static Optional<StringRef> getTextFromRange(SMRange range) {
+static std::optional<StringRef> getTextFromRange(SMRange range) {
   if (!range.isValid())
     return std::nullopt;
   const char *startPtr = range.Start.getPointer();
@@ -171,7 +172,7 @@ static unsigned getBlockNumber(Block *block) {
 /// given output stream.
 static void printDefBlockName(raw_ostream &os, Block *block, SMRange loc = {}) {
   // Try to extract a name from the source location.
-  Optional<StringRef> text = getTextFromRange(loc);
+  std::optional<StringRef> text = getTextFromRange(loc);
   if (text && text->startswith("^")) {
     os << *text;
     return;
@@ -200,7 +201,7 @@ static lsp::Diagnostic getLspDiagnoticFromDiag(llvm::SourceMgr &sourceMgr,
   // TODO: For simplicity, we just grab the first one. It may be likely that we
   // will need a more interesting heuristic here.'
   StringRef uriScheme = uri.scheme();
-  Optional<lsp::Location> lspLocation =
+  std::optional<lsp::Location> lspLocation =
       getLocationFromLoc(sourceMgr, diag.getLocation(), uriScheme, &uri);
   if (lspLocation)
     lspDiag.range = lspLocation->range;
@@ -225,7 +226,7 @@ static lsp::Diagnostic getLspDiagnoticFromDiag(llvm::SourceMgr &sourceMgr,
   std::vector<lsp::DiagnosticRelatedInformation> relatedDiags;
   for (Diagnostic &note : diag.getNotes()) {
     lsp::Location noteLoc;
-    if (Optional<lsp::Location> loc =
+    if (std::optional<lsp::Location> loc =
             getLocationFromLoc(sourceMgr, note.getLocation(), uriScheme))
       noteLoc = *loc;
     else
@@ -541,7 +542,7 @@ lsp::Hover MLIRDocument::buildHoverForOperationResult(SMRange hoverRange,
 
   // Check to see if the location points to a specific result within the
   // group.
-  if (Optional<unsigned> resultNumber = getResultNumberFromLoc(posLoc)) {
+  if (std::optional<unsigned> resultNumber = getResultNumberFromLoc(posLoc)) {
     if ((resultStart + *resultNumber) < resultEnd) {
       resultStart += *resultNumber;
       resultEnd = resultStart + 1;
@@ -1226,7 +1227,7 @@ void lsp::MLIRServer::addOrUpdateDocument(
       uri, contents, version, impl->registry, diagnostics);
 }
 
-Optional<int64_t> lsp::MLIRServer::removeDocument(const URIForFile &uri) {
+std::optional<int64_t> lsp::MLIRServer::removeDocument(const URIForFile &uri) {
   auto it = impl->files.find(uri.file());
   if (it == impl->files.end())
     return std::nullopt;

diff  --git a/mlir/lib/Tools/mlir-lsp-server/MLIRServer.h b/mlir/lib/Tools/mlir-lsp-server/MLIRServer.h
index 0224724af1c56..979be615b82cc 100644
--- a/mlir/lib/Tools/mlir-lsp-server/MLIRServer.h
+++ b/mlir/lib/Tools/mlir-lsp-server/MLIRServer.h
@@ -49,7 +49,7 @@ class MLIRServer {
   /// Remove the document with the given uri. Returns the version of the removed
   /// document, or std::nullopt if the uri did not have a corresponding document
   /// within the server.
-  Optional<int64_t> removeDocument(const URIForFile &uri);
+  std::optional<int64_t> removeDocument(const URIForFile &uri);
 
   /// Return the locations of the object pointed at by the given position.
   void getLocationsOf(const URIForFile &uri, const Position &defPos,

diff  --git a/mlir/lib/Tools/mlir-pdll-lsp-server/LSPServer.cpp b/mlir/lib/Tools/mlir-pdll-lsp-server/LSPServer.cpp
index 8be034f846652..c91dc89505433 100644
--- a/mlir/lib/Tools/mlir-pdll-lsp-server/LSPServer.cpp
+++ b/mlir/lib/Tools/mlir-pdll-lsp-server/LSPServer.cpp
@@ -175,7 +175,8 @@ void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams &params) {
   publishDiagnostics(diagParams);
 }
 void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams &params) {
-  Optional<int64_t> version = server.removeDocument(params.textDocument.uri);
+  std::optional<int64_t> version =
+      server.removeDocument(params.textDocument.uri);
   if (!version)
     return;
 

diff  --git a/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.cpp b/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.cpp
index 53afc8fb2437e..f209f2a62c24c 100644
--- a/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.cpp
+++ b/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.cpp
@@ -64,7 +64,7 @@ static lsp::Location getLocationFromLoc(llvm::SourceMgr &mgr, SMRange range,
 }
 
 /// Convert the given MLIR diagnostic to the LSP form.
-static Optional<lsp::Diagnostic>
+static std::optional<lsp::Diagnostic>
 getLspDiagnoticFromDiag(llvm::SourceMgr &sourceMgr, const ast::Diagnostic &diag,
                         const lsp::URIForFile &uri) {
   lsp::Diagnostic lspDiag;
@@ -112,10 +112,10 @@ getLspDiagnoticFromDiag(llvm::SourceMgr &sourceMgr, const ast::Diagnostic &diag,
 }
 
 /// Get or extract the documentation for the given decl.
-static Optional<std::string> getDocumentationFor(llvm::SourceMgr &sourceMgr,
-                                                 const ast::Decl *decl) {
+static std::optional<std::string>
+getDocumentationFor(llvm::SourceMgr &sourceMgr, const ast::Decl *decl) {
   // If the decl already had documentation set, use it.
-  if (Optional<StringRef> doc = decl->getDocComment())
+  if (std::optional<StringRef> doc = decl->getDocComment())
     return doc->str();
 
   // If the decl doesn't yet have documentation, try to extract it from the
@@ -216,7 +216,7 @@ void PDLIndex::initialize(const ast::Module &module,
   module.walk([&](const ast::Node *node) {
     // Handle references to PDL decls.
     if (const auto *decl = dyn_cast<ast::OpNameDecl>(node)) {
-      if (Optional<StringRef> name = decl->getName())
+      if (std::optional<StringRef> name = decl->getName())
         insertODSOpRef(*name, decl->getLoc());
     } else if (const ast::Decl *decl = dyn_cast<ast::Decl>(node)) {
       const ast::Name *name = decl->getName();
@@ -528,7 +528,7 @@ lsp::Hover PDLDocument::buildHoverForPattern(const ast::PatternDecl *decl,
     if (const ast::Name *name = decl->getName())
       hoverOS << ": `" << name->getName() << "`";
     hoverOS << "\n***\n";
-    if (Optional<uint16_t> benefit = decl->getBenefit())
+    if (std::optional<uint16_t> benefit = decl->getBenefit())
       hoverOS << "Benefit: " << *benefit << "\n";
     if (decl->hasBoundedRewriteRecursion())
       hoverOS << "HasBoundedRewriteRecursion\n";
@@ -536,7 +536,7 @@ lsp::Hover PDLDocument::buildHoverForPattern(const ast::PatternDecl *decl,
             << decl->getRootRewriteStmt()->getRootOpExpr()->getType() << "`\n";
 
     // Format the documentation for the decl.
-    if (Optional<std::string> doc = getDocumentationFor(sourceMgr, decl))
+    if (std::optional<std::string> doc = getDocumentationFor(sourceMgr, decl))
       hoverOS << "\n" << *doc << "\n";
   }
   return hover;
@@ -553,7 +553,7 @@ PDLDocument::buildHoverForCoreConstraint(const ast::CoreConstraintDecl *decl,
         .Case([&](const ast::AttrConstraintDecl *) { hoverOS << "Attr"; })
         .Case([&](const ast::OpConstraintDecl *opCst) {
           hoverOS << "Op";
-          if (Optional<StringRef> name = opCst->getName())
+          if (std::optional<StringRef> name = opCst->getName())
             hoverOS << "<" << *name << ">";
         })
         .Case([&](const ast::TypeConstraintDecl *) { hoverOS << "Type"; })
@@ -603,7 +603,7 @@ lsp::Hover PDLDocument::buildHoverForUserConstraintOrRewrite(
     }
 
     // Format the documentation for the decl.
-    if (Optional<std::string> doc = getDocumentationFor(sourceMgr, decl))
+    if (std::optional<std::string> doc = getDocumentationFor(sourceMgr, decl))
       hoverOS << "\n" << *doc << "\n";
   }
   return hover;
@@ -836,7 +836,8 @@ class LSPCodeCompleteContext : public CodeCompleteContext {
           }
 
           // Format the documentation for the constraint.
-          if (Optional<std::string> doc = getDocumentationFor(sourceMgr, cst)) {
+          if (std::optional<std::string> doc =
+                  getDocumentationFor(sourceMgr, cst)) {
             item.documentation =
                 lsp::MarkupContent{lsp::MarkupKind::Markdown, std::move(*doc)};
           }
@@ -1027,14 +1028,15 @@ class LSPSignatureHelpContext : public CodeCompleteContext {
     }
 
     // Format the documentation for the callable.
-    if (Optional<std::string> doc = getDocumentationFor(sourceMgr, callable))
+    if (std::optional<std::string> doc =
+            getDocumentationFor(sourceMgr, callable))
       signatureInfo.documentation = std::move(*doc);
 
     signatureHelp.signatures.emplace_back(std::move(signatureInfo));
   }
 
   void
-  codeCompleteOperationOperandsSignature(Optional<StringRef> opName,
+  codeCompleteOperationOperandsSignature(std::optional<StringRef> opName,
                                          unsigned currentNumOperands) final {
     const ods::Operation *odsOp =
         opName ? odsContext.lookupOperation(*opName) : nullptr;
@@ -1043,7 +1045,7 @@ class LSPSignatureHelpContext : public CodeCompleteContext {
         currentNumOperands, "operand", "Value");
   }
 
-  void codeCompleteOperationResultsSignature(Optional<StringRef> opName,
+  void codeCompleteOperationResultsSignature(std::optional<StringRef> opName,
                                              unsigned currentNumResults) final {
     const ods::Operation *odsOp =
         opName ? odsContext.lookupOperation(*opName) : nullptr;
@@ -1053,7 +1055,7 @@ class LSPSignatureHelpContext : public CodeCompleteContext {
   }
 
   void codeCompleteOperationOperandOrResultSignature(
-      Optional<StringRef> opName, const ods::Operation *odsOp,
+      std::optional<StringRef> opName, const ods::Operation *odsOp,
       ArrayRef<ods::OperandOrResult> values, unsigned currentValue,
       StringRef label, StringRef dataType) {
     signatureHelp.activeParameter = currentValue;
@@ -1731,7 +1733,7 @@ void lsp::PDLLServer::updateDocument(
     impl->files.erase(it);
 }
 
-Optional<int64_t> lsp::PDLLServer::removeDocument(const URIForFile &uri) {
+std::optional<int64_t> lsp::PDLLServer::removeDocument(const URIForFile &uri) {
   auto it = impl->files.find(uri.file());
   if (it == impl->files.end())
     return std::nullopt;

diff  --git a/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.h b/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.h
index 68c807fa8ef91..682c7b5ed2e2a 100644
--- a/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.h
+++ b/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.h
@@ -68,7 +68,7 @@ class PDLLServer {
   /// Remove the document with the given uri. Returns the version of the removed
   /// document, or std::nullopt if the uri did not have a corresponding document
   /// within the server.
-  Optional<int64_t> removeDocument(const URIForFile &uri);
+  std::optional<int64_t> removeDocument(const URIForFile &uri);
 
   /// Return the locations of the object pointed at by the given position.
   void getLocationsOf(const URIForFile &uri, const Position &defPos,

diff  --git a/mlir/lib/Tools/mlir-translate/Translation.cpp b/mlir/lib/Tools/mlir-translate/Translation.cpp
index 2f578186dfe4d..a39a4675c2762 100644
--- a/mlir/lib/Tools/mlir-translate/Translation.cpp
+++ b/mlir/lib/Tools/mlir-translate/Translation.cpp
@@ -50,7 +50,7 @@ static llvm::StringMap<Translation> &getTranslationRegistry() {
 
 /// Register the given translation.
 static void registerTranslation(StringRef name, StringRef description,
-                                Optional<llvm::Align> inputAlignment,
+                                std::optional<llvm::Align> inputAlignment,
                                 const TranslateFunction &function) {
   auto &registry = getTranslationRegistry();
   if (registry.count(name))
@@ -76,7 +76,7 @@ TranslateRegistration::TranslateRegistration(
 static void registerTranslateToMLIRFunction(
     StringRef name, StringRef description,
     const DialectRegistrationFunction &dialectRegistration,
-    Optional<llvm::Align> inputAlignment,
+    std::optional<llvm::Align> inputAlignment,
     const TranslateSourceMgrToMLIRFunction &function) {
   auto wrappedFn = [function, dialectRegistration](
                        const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
@@ -97,7 +97,7 @@ TranslateToMLIRRegistration::TranslateToMLIRRegistration(
     StringRef name, StringRef description,
     const TranslateSourceMgrToMLIRFunction &function,
     const DialectRegistrationFunction &dialectRegistration,
-    Optional<llvm::Align> inputAlignment) {
+    std::optional<llvm::Align> inputAlignment) {
   registerTranslateToMLIRFunction(name, description, dialectRegistration,
                                   inputAlignment, function);
 }
@@ -105,7 +105,7 @@ TranslateToMLIRRegistration::TranslateToMLIRRegistration(
     StringRef name, StringRef description,
     const TranslateRawSourceMgrToMLIRFunction &function,
     const DialectRegistrationFunction &dialectRegistration,
-    Optional<llvm::Align> inputAlignment) {
+    std::optional<llvm::Align> inputAlignment) {
   registerTranslateToMLIRFunction(
       name, description, dialectRegistration, inputAlignment,
       [function](const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
@@ -117,7 +117,7 @@ TranslateToMLIRRegistration::TranslateToMLIRRegistration(
     StringRef name, StringRef description,
     const TranslateStringRefToMLIRFunction &function,
     const DialectRegistrationFunction &dialectRegistration,
-    Optional<llvm::Align> inputAlignment) {
+    std::optional<llvm::Align> inputAlignment) {
   registerTranslateToMLIRFunction(
       name, description, dialectRegistration, inputAlignment,
       [function](const std::shared_ptr<llvm::SourceMgr> &sourceMgr,

diff  --git a/mlir/lib/Tools/tblgen-lsp-server/LSPServer.cpp b/mlir/lib/Tools/tblgen-lsp-server/LSPServer.cpp
index c8445adbe81d8..81fb5a015fa0a 100644
--- a/mlir/lib/Tools/tblgen-lsp-server/LSPServer.cpp
+++ b/mlir/lib/Tools/tblgen-lsp-server/LSPServer.cpp
@@ -127,7 +127,8 @@ void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams &params) {
   publishDiagnostics(diagParams);
 }
 void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams &params) {
-  Optional<int64_t> version = server.removeDocument(params.textDocument.uri);
+  std::optional<int64_t> version =
+      server.removeDocument(params.textDocument.uri);
   if (!version)
     return;
 

diff  --git a/mlir/lib/Tools/tblgen-lsp-server/TableGenServer.cpp b/mlir/lib/Tools/tblgen-lsp-server/TableGenServer.cpp
index 55a340271d4cf..33d20c94b820d 100644
--- a/mlir/lib/Tools/tblgen-lsp-server/TableGenServer.cpp
+++ b/mlir/lib/Tools/tblgen-lsp-server/TableGenServer.cpp
@@ -55,7 +55,7 @@ static lsp::Location getLocationFromLoc(llvm::SourceMgr &mgr, SMLoc loc,
 }
 
 /// Convert the given TableGen diagnostic to the LSP form.
-static Optional<lsp::Diagnostic>
+static std::optional<lsp::Diagnostic>
 getLspDiagnoticFromDiag(const llvm::SMDiagnostic &diag,
                         const lsp::URIForFile &uri) {
   auto *sourceMgr = const_cast<llvm::SourceMgr *>(diag.getSourceMgr());
@@ -583,7 +583,7 @@ lsp::Hover TableGenTextFile::buildHoverForRecord(const llvm::Record *record,
     printAndFormatField("description");
 
     // Check for documentation in the source file.
-    if (Optional<std::string> doc =
+    if (std::optional<std::string> doc =
             lsp::extractSourceDocComment(sourceMgr, record->getLoc().front())) {
       hoverOS << "\n" << *doc << "\n";
     }
@@ -618,7 +618,7 @@ lsp::Hover TableGenTextFile::buildHoverForField(const llvm::Record *record,
     hoverOS << "`\n***\n";
 
     // Check for documentation in the source file.
-    if (Optional<std::string> doc =
+    if (std::optional<std::string> doc =
             lsp::extractSourceDocComment(sourceMgr, value->getLoc())) {
       hoverOS << "\n" << *doc << "\n";
       hoverOS << "\n***\n";
@@ -628,7 +628,7 @@ lsp::Hover TableGenTextFile::buildHoverForField(const llvm::Record *record,
     // documentation.
     auto [baseRecord, baseValue] = getBaseValue(record, value);
     if (baseValue) {
-      if (Optional<std::string> doc =
+      if (std::optional<std::string> doc =
               lsp::extractSourceDocComment(sourceMgr, baseValue->getLoc())) {
         hoverOS << "\n *From `" << baseRecord->getName() << "`*:\n\n"
                 << *doc << "\n";
@@ -691,7 +691,8 @@ void lsp::TableGenServer::updateDocument(
     impl->files.erase(it);
 }
 
-Optional<int64_t> lsp::TableGenServer::removeDocument(const URIForFile &uri) {
+std::optional<int64_t>
+lsp::TableGenServer::removeDocument(const URIForFile &uri) {
   auto it = impl->files.find(uri.file());
   if (it == impl->files.end())
     return std::nullopt;

diff  --git a/mlir/lib/Tools/tblgen-lsp-server/TableGenServer.h b/mlir/lib/Tools/tblgen-lsp-server/TableGenServer.h
index d8c79e7dfff71..d749a4fcda2f9 100644
--- a/mlir/lib/Tools/tblgen-lsp-server/TableGenServer.h
+++ b/mlir/lib/Tools/tblgen-lsp-server/TableGenServer.h
@@ -60,7 +60,7 @@ class TableGenServer {
   /// Remove the document with the given uri. Returns the version of the removed
   /// document, or std::nullopt if the uri did not have a corresponding document
   /// within the server.
-  Optional<int64_t> removeDocument(const URIForFile &uri);
+  std::optional<int64_t> removeDocument(const URIForFile &uri);
 
   /// Return the locations of the object pointed at by the given position.
   void getLocationsOf(const URIForFile &uri, const Position &defPos,

diff  --git a/mlir/lib/Transforms/LocationSnapshot.cpp b/mlir/lib/Transforms/LocationSnapshot.cpp
index 44b0560b7ba3b..b85850acda91b 100644
--- a/mlir/lib/Transforms/LocationSnapshot.cpp
+++ b/mlir/lib/Transforms/LocationSnapshot.cpp
@@ -37,7 +37,7 @@ static void generateLocationsFromIR(raw_ostream &os, StringRef fileName,
   op->print(os, state);
 
   Builder builder(op->getContext());
-  Optional<StringAttr> tagIdentifier;
+  std::optional<StringAttr> tagIdentifier;
   if (!tag.empty())
     tagIdentifier = builder.getStringAttr(tag);
 

diff  --git a/mlir/lib/Transforms/Utils/InliningUtils.cpp b/mlir/lib/Transforms/Utils/InliningUtils.cpp
index e47ce0480ac1b..f9dc69caea472 100644
--- a/mlir/lib/Transforms/Utils/InliningUtils.cpp
+++ b/mlir/lib/Transforms/Utils/InliningUtils.cpp
@@ -145,8 +145,8 @@ static LogicalResult
 inlineRegionImpl(InlinerInterface &interface, Region *src, Block *inlineBlock,
                  Block::iterator inlinePoint, IRMapping &mapper,
                  ValueRange resultsToReplace, TypeRange regionResultTypes,
-                 Optional<Location> inlineLoc, bool shouldCloneInlinedRegion,
-                 Operation *call = nullptr) {
+                 std::optional<Location> inlineLoc,
+                 bool shouldCloneInlinedRegion, Operation *call = nullptr) {
   assert(resultsToReplace.size() == regionResultTypes.size());
   // We expect the region to have at least one block.
   if (src->empty())
@@ -233,7 +233,7 @@ inlineRegionImpl(InlinerInterface &interface, Region *src, Block *inlineBlock,
 static LogicalResult
 inlineRegionImpl(InlinerInterface &interface, Region *src, Block *inlineBlock,
                  Block::iterator inlinePoint, ValueRange inlinedOperands,
-                 ValueRange resultsToReplace, Optional<Location> inlineLoc,
+                 ValueRange resultsToReplace, std::optional<Location> inlineLoc,
                  bool shouldCloneInlinedRegion, Operation *call = nullptr) {
   // We expect the region to have at least one block.
   if (src->empty())
@@ -264,7 +264,7 @@ LogicalResult mlir::inlineRegion(InlinerInterface &interface, Region *src,
                                  Operation *inlinePoint, IRMapping &mapper,
                                  ValueRange resultsToReplace,
                                  TypeRange regionResultTypes,
-                                 Optional<Location> inlineLoc,
+                                 std::optional<Location> inlineLoc,
                                  bool shouldCloneInlinedRegion) {
   return inlineRegion(interface, src, inlinePoint->getBlock(),
                       ++inlinePoint->getIterator(), mapper, resultsToReplace,
@@ -275,7 +275,7 @@ LogicalResult mlir::inlineRegion(InlinerInterface &interface, Region *src,
                                  Block::iterator inlinePoint, IRMapping &mapper,
                                  ValueRange resultsToReplace,
                                  TypeRange regionResultTypes,
-                                 Optional<Location> inlineLoc,
+                                 std::optional<Location> inlineLoc,
                                  bool shouldCloneInlinedRegion) {
   return inlineRegionImpl(interface, src, inlineBlock, inlinePoint, mapper,
                           resultsToReplace, regionResultTypes, inlineLoc,
@@ -286,17 +286,19 @@ LogicalResult mlir::inlineRegion(InlinerInterface &interface, Region *src,
                                  Operation *inlinePoint,
                                  ValueRange inlinedOperands,
                                  ValueRange resultsToReplace,
-                                 Optional<Location> inlineLoc,
+                                 std::optional<Location> inlineLoc,
                                  bool shouldCloneInlinedRegion) {
   return inlineRegion(interface, src, inlinePoint->getBlock(),
                       ++inlinePoint->getIterator(), inlinedOperands,
                       resultsToReplace, inlineLoc, shouldCloneInlinedRegion);
 }
-LogicalResult
-mlir::inlineRegion(InlinerInterface &interface, Region *src, Block *inlineBlock,
-                   Block::iterator inlinePoint, ValueRange inlinedOperands,
-                   ValueRange resultsToReplace, Optional<Location> inlineLoc,
-                   bool shouldCloneInlinedRegion) {
+LogicalResult mlir::inlineRegion(InlinerInterface &interface, Region *src,
+                                 Block *inlineBlock,
+                                 Block::iterator inlinePoint,
+                                 ValueRange inlinedOperands,
+                                 ValueRange resultsToReplace,
+                                 std::optional<Location> inlineLoc,
+                                 bool shouldCloneInlinedRegion) {
   return inlineRegionImpl(interface, src, inlineBlock, inlinePoint,
                           inlinedOperands, resultsToReplace, inlineLoc,
                           shouldCloneInlinedRegion);

diff  --git a/mlir/lib/Transforms/ViewOpGraph.cpp b/mlir/lib/Transforms/ViewOpGraph.cpp
index 92505e58603d1..186118b2e067a 100644
--- a/mlir/lib/Transforms/ViewOpGraph.cpp
+++ b/mlir/lib/Transforms/ViewOpGraph.cpp
@@ -34,7 +34,8 @@ static const StringRef kShapeNone = "plain";
 /// Return the size limits for eliding large attributes.
 static int64_t getLargeAttributeSizeLimit() {
   // Use the default from the printer flags if possible.
-  if (Optional<int64_t> limit = OpPrintingFlags().getLargeElementsAttrLimit())
+  if (std::optional<int64_t> limit =
+          OpPrintingFlags().getLargeElementsAttrLimit())
     return *limit;
   return 16;
 }
@@ -70,11 +71,11 @@ namespace {
 /// cluster, an invisible "anchor" node is created.
 struct Node {
 public:
-  Node(int id = 0, Optional<int> clusterId = std::nullopt)
+  Node(int id = 0, std::optional<int> clusterId = std::nullopt)
       : id(id), clusterId(clusterId) {}
 
   int id;
-  Optional<int> clusterId;
+  std::optional<int> clusterId;
 };
 
 /// This pass generates a Graphviz dataflow visualization of an MLIR operation.
@@ -254,7 +255,7 @@ class PrintOpPass : public impl::ViewOpGraphBase<PrintOpPass> {
         valueToNode[blockArg] = emitNodeStmt(getLabel(blockArg));
 
       // Emit a node for each operation.
-      Optional<Node> prevNode;
+      std::optional<Node> prevNode;
       for (Operation &op : block) {
         Node nextNode = processOperation(&op);
         if (printControlFlowEdges && prevNode)

diff  --git a/mlir/test/lib/Analysis/DataFlow/TestDenseDataFlowAnalysis.cpp b/mlir/test/lib/Analysis/DataFlow/TestDenseDataFlowAnalysis.cpp
index e79e690cc5c3c..f88544032c21a 100644
--- a/mlir/test/lib/Analysis/DataFlow/TestDenseDataFlowAnalysis.cpp
+++ b/mlir/test/lib/Analysis/DataFlow/TestDenseDataFlowAnalysis.cpp
@@ -102,7 +102,7 @@ class LastModification : public AbstractDenseLattice {
 
   /// Get the last modifications of a value. Returns none if the last
   /// modifications are not known.
-  Optional<ArrayRef<Operation *>> getLastModifiers(Value value) const {
+  std::optional<ArrayRef<Operation *>> getLastModifiers(Value value) const {
     auto it = lastMods.find(value);
     if (it == lastMods.end())
       return {};
@@ -260,7 +260,7 @@ struct TestLastModifiedPass
           return solver.lookupState<UnderlyingValueLattice>(value);
         });
         assert(value && "expected an underlying value");
-        if (Optional<ArrayRef<Operation *>> lastMod =
+        if (std::optional<ArrayRef<Operation *>> lastMod =
                 lastMods->getLastModifiers(value)) {
           for (Operation *lastModifier : *lastMod) {
             if (auto tagName =

diff  --git a/mlir/test/lib/Analysis/TestDataFlowFramework.cpp b/mlir/test/lib/Analysis/TestDataFlowFramework.cpp
index ecacc36c479f5..00449249a7082 100644
--- a/mlir/test/lib/Analysis/TestDataFlowFramework.cpp
+++ b/mlir/test/lib/Analysis/TestDataFlowFramework.cpp
@@ -62,7 +62,7 @@ class FooState : public AnalysisState {
 
 private:
   /// An optional integer value.
-  Optional<uint64_t> state;
+  std::optional<uint64_t> state;
 };
 
 /// This analysis computes `FooState` across operations and control-flow edges.

diff  --git a/mlir/test/lib/Dialect/Shape/TestShapeMappingAnalysis.cpp b/mlir/test/lib/Dialect/Shape/TestShapeMappingAnalysis.cpp
index d3c5fa4e252ff..391cb50c4bd48 100644
--- a/mlir/test/lib/Dialect/Shape/TestShapeMappingAnalysis.cpp
+++ b/mlir/test/lib/Dialect/Shape/TestShapeMappingAnalysis.cpp
@@ -24,7 +24,7 @@ struct TestShapeMappingPass
     return "Print the contents of a constructed shape mapping information.";
   }
   void runOnOperation() override {
-    llvm::Optional<std::reference_wrapper<shape::ShapeMappingAnalysis>>
+    std::optional<std::reference_wrapper<shape::ShapeMappingAnalysis>>
         maybeAnalysis = getCachedAnalysis<shape::ShapeMappingAnalysis>();
     if (maybeAnalysis.has_value())
       maybeAnalysis->get().print(llvm::errs());

diff  --git a/mlir/test/lib/Dialect/Test/TestDialect.cpp b/mlir/test/lib/Dialect/Test/TestDialect.cpp
index 56e6bd22b9458..e62d5a81c84d0 100644
--- a/mlir/test/lib/Dialect/Test/TestDialect.cpp
+++ b/mlir/test/lib/Dialect/Test/TestDialect.cpp
@@ -956,7 +956,7 @@ ParseResult PrettyPrintedRegionOp::parse(OpAsmParser &parser,
   StringAttr innerOpName = parseOpNameInfo->getIdentifier();
 
   FunctionType opFntype;
-  Optional<Location> explicitLoc;
+  std::optional<Location> explicitLoc;
   if (parser.parseKeyword("end") || parser.parseColon() ||
       parser.parseType(opFntype) ||
       parser.parseOptionalLocationSpecifier(explicitLoc))
@@ -1059,7 +1059,7 @@ void PolyForOp::getAsmBlockArgumentNames(Region &region,
 //===----------------------------------------------------------------------===//
 
 static ParseResult parseOptionalLoc(OpAsmParser &p, Attribute &loc) {
-  Optional<Location> result;
+  std::optional<Location> result;
   SMLoc sourceLoc = p.getCurrentLocation();
   if (p.parseOptionalLocationSpecifier(result))
     return failure();

diff  --git a/mlir/test/lib/Dialect/Test/TestTypeDefs.td b/mlir/test/lib/Dialect/Test/TestTypeDefs.td
index 81280d8d533ce..72e857c122224 100644
--- a/mlir/test/lib/Dialect/Test/TestTypeDefs.td
+++ b/mlir/test/lib/Dialect/Test/TestTypeDefs.td
@@ -219,7 +219,7 @@ def TestTypeStructCaptureAll : Test_Type<"TestStructTypeCaptureAll"> {
 
 def TestTypeOptionalParam : Test_Type<"TestTypeOptionalParam"> {
   let parameters = (ins
-    OptionalParameter<"mlir::Optional<int>">:$a,
+    OptionalParameter<"std::optional<int>">:$a,
     "int":$b,
     DefaultValuedParameter<"std::optional<::mlir::Attribute>",
                            "std::nullopt">:$c
@@ -229,7 +229,7 @@ def TestTypeOptionalParam : Test_Type<"TestTypeOptionalParam"> {
 }
 
 def TestTypeOptionalParams : Test_Type<"TestTypeOptionalParams"> {
-  let parameters = (ins OptionalParameter<"mlir::Optional<int>">:$a,
+  let parameters = (ins OptionalParameter<"std::optional<int>">:$a,
                         StringRefParameter<>:$b);
   let mnemonic = "optional_params";
   let assemblyFormat = "`<` params `>`";
@@ -238,48 +238,48 @@ def TestTypeOptionalParams : Test_Type<"TestTypeOptionalParams"> {
 def TestTypeOptionalParamsAfterRequired
     : Test_Type<"TestTypeOptionalParamsAfterRequired"> {
   let parameters = (ins StringRefParameter<>:$a,
-                        OptionalParameter<"mlir::Optional<int>">:$b);
+                        OptionalParameter<"std::optional<int>">:$b);
   let mnemonic = "optional_params_after";
   let assemblyFormat = "`<` params `>`";
 }
 
 def TestTypeOptionalStruct : Test_Type<"TestTypeOptionalStruct"> {
-  let parameters = (ins OptionalParameter<"mlir::Optional<int>">:$a,
+  let parameters = (ins OptionalParameter<"std::optional<int>">:$a,
                         StringRefParameter<>:$b);
   let mnemonic = "optional_struct";
   let assemblyFormat = "`<` struct(params) `>`";
 }
 
 def TestTypeAllOptionalParams : Test_Type<"TestTypeAllOptionalParams"> {
-  let parameters = (ins OptionalParameter<"mlir::Optional<int>">:$a,
-                        OptionalParameter<"mlir::Optional<int>">:$b);
+  let parameters = (ins OptionalParameter<"std::optional<int>">:$a,
+                        OptionalParameter<"std::optional<int>">:$b);
   let mnemonic = "all_optional_params";
   let assemblyFormat = "`<` params `>`";
 }
 
 def TestTypeAllOptionalStruct : Test_Type<"TestTypeAllOptionalStruct"> {
-  let parameters = (ins OptionalParameter<"mlir::Optional<int>">:$a,
-                        OptionalParameter<"mlir::Optional<int>">:$b);
+  let parameters = (ins OptionalParameter<"std::optional<int>">:$a,
+                        OptionalParameter<"std::optional<int>">:$b);
   let mnemonic = "all_optional_struct";
   let assemblyFormat = "`<` struct(params) `>`";
 }
 
 def TestTypeOptionalGroup : Test_Type<"TestTypeOptionalGroup"> {
-  let parameters = (ins "int":$a, OptionalParameter<"mlir::Optional<int>">:$b);
+  let parameters = (ins "int":$a, OptionalParameter<"std::optional<int>">:$b);
   let mnemonic = "optional_group";
   let assemblyFormat = "`<` (`(` $b^ `)`) : (`x`)? $a `>`";
 }
 
 def TestTypeOptionalGroupParams : Test_Type<"TestTypeOptionalGroupParams"> {
-  let parameters = (ins DefaultValuedParameter<"mlir::Optional<int>", "10">:$a,
-                        OptionalParameter<"mlir::Optional<int>">:$b);
+  let parameters = (ins DefaultValuedParameter<"std::optional<int>", "10">:$a,
+                        OptionalParameter<"std::optional<int>">:$b);
   let mnemonic = "optional_group_params";
   let assemblyFormat = "`<` (`(` params^ `)`) : (`x`)? `>`";
 }
 
 def TestTypeOptionalGroupStruct : Test_Type<"TestTypeOptionalGroupStruct"> {
-  let parameters = (ins OptionalParameter<"mlir::Optional<int>">:$a,
-                        OptionalParameter<"mlir::Optional<int>">:$b);
+  let parameters = (ins OptionalParameter<"std::optional<int>">:$a,
+                        OptionalParameter<"std::optional<int>">:$b);
   let mnemonic = "optional_group_struct";
   let assemblyFormat = "`<` (`(` struct(params)^ `)`) : (`x`)? `>`";
 }
@@ -322,7 +322,7 @@ def TestTypeDefaultValuedType : Test_Type<"TestTypeDefaultValuedType"> {
 }
 
 def TestTypeCustom : Test_Type<"TestTypeCustom"> {
-  let parameters = (ins "int":$a, OptionalParameter<"mlir::Optional<int>">:$b);
+  let parameters = (ins "int":$a, OptionalParameter<"std::optional<int>">:$b);
   let mnemonic = "custom_type";
   let assemblyFormat = [{ `<` custom<CustomTypeA>($a) ``
                               custom<CustomTypeB>(ref($a), $b) `>` }];
@@ -343,14 +343,14 @@ def TestTypeCustomString : Test_Type<"TestTypeCustomString"> {
 }
 
 def TestTypeElseAnchor : Test_Type<"TestTypeElseAnchor"> {
-  let parameters = (ins OptionalParameter<"mlir::Optional<int>">:$a);
+  let parameters = (ins OptionalParameter<"std::optional<int>">:$a);
   let mnemonic = "else_anchor";
   let assemblyFormat = "`<` (`?`) : ($a^)? `>`";
 }
 
 def TestTypeElseAnchorStruct : Test_Type<"TestTypeElseAnchorStruct"> {
-  let parameters = (ins OptionalParameter<"mlir::Optional<int>">:$a,
-                        OptionalParameter<"mlir::Optional<int>">:$b);
+  let parameters = (ins OptionalParameter<"std::optional<int>">:$a,
+                        OptionalParameter<"std::optional<int>">:$b);
   let mnemonic = "else_anchor_struct";
   let assemblyFormat = "`<` (`?`) : (struct($a, $b)^)? `>`";
 }

diff  --git a/mlir/test/lib/Dialect/Test/TestTypes.cpp b/mlir/test/lib/Dialect/Test/TestTypes.cpp
index 067c9b203adc8..4d5c9b89957f2 100644
--- a/mlir/test/lib/Dialect/Test/TestTypes.cpp
+++ b/mlir/test/lib/Dialect/Test/TestTypes.cpp
@@ -98,7 +98,7 @@ static LogicalResult parseCustomTypeA(AsmParser &parser,
 static void printCustomTypeA(AsmPrinter &printer, int a) { printer << a; }
 
 static LogicalResult parseCustomTypeB(AsmParser &parser, int a,
-                                      FailureOr<Optional<int>> &bResult) {
+                                      FailureOr<std::optional<int>> &bResult) {
   if (a < 0)
     return success();
   for (int i : llvm::seq(0, a))
@@ -108,7 +108,7 @@ static LogicalResult parseCustomTypeB(AsmParser &parser, int a,
   return parser.parseInteger(**bResult);
 }
 
-static void printCustomTypeB(AsmPrinter &printer, int a, Optional<int> b) {
+static void printCustomTypeB(AsmPrinter &printer, int a, std::optional<int> b) {
   if (a < 0)
     return;
   printer << ' ';

diff  --git a/mlir/test/lib/Dialect/Test/TestTypes.h b/mlir/test/lib/Dialect/Test/TestTypes.h
index bb3751d281825..b6a7e275781a5 100644
--- a/mlir/test/lib/Dialect/Test/TestTypes.h
+++ b/mlir/test/lib/Dialect/Test/TestTypes.h
@@ -74,9 +74,9 @@ inline mlir::AsmPrinter &operator<<(mlir::AsmPrinter &printer,
 
 /// Overload the attribute parameter parser for optional integers.
 template <>
-struct FieldParser<Optional<int>> {
-  static FailureOr<Optional<int>> parse(AsmParser &parser) {
-    Optional<int> value;
+struct FieldParser<std::optional<int>> {
+  static FailureOr<std::optional<int>> parse(AsmParser &parser) {
+    std::optional<int> value;
     value.emplace();
     OptionalParseResult result = parser.parseOptionalInteger(*value);
     if (result.has_value()) {

diff  --git a/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp b/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp
index b0f11ffeafffd..68edea5efca09 100644
--- a/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp
+++ b/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp
@@ -73,7 +73,7 @@ struct TestVectorToVectorLowering
 
 private:
   // Return the target shape based on op type.
-  static Optional<SmallVector<int64_t>> getShape(Operation *op) {
+  static std::optional<SmallVector<int64_t>> getShape(Operation *op) {
     if (isa<arith::AddFOp, arith::SelectOp, arith::CmpFOp>(op))
       return SmallVector<int64_t>(2, 2);
     if (isa<vector::ContractionOp>(op))
@@ -315,7 +315,7 @@ struct TestVectorUnrollingPatterns
 
     if (unrollBasedOnType) {
       UnrollVectorOptions::NativeShapeFnType nativeShapeFn =
-          [](Operation *op) -> Optional<SmallVector<int64_t>> {
+          [](Operation *op) -> std::optional<SmallVector<int64_t>> {
         vector::ContractionOp contractOp = cast<vector::ContractionOp>(op);
         SmallVector<int64_t> nativeShape(contractOp.getIteratorTypes().size(),
                                          4);
@@ -330,17 +330,20 @@ struct TestVectorUnrollingPatterns
               [](Operation *op) { return success(isa<ContractionOp>(op)); });
 
       if (!unrollOrder.empty()) {
-        opts.setUnrollTraversalOrderFn([this](Operation *op)
-                                           -> Optional<SmallVector<int64_t>> {
-          vector::ContractionOp contractOp = cast<vector::ContractionOp>(op);
-          if (contractOp.getIteratorTypes().size() == unrollOrder.size())
-            return SmallVector<int64_t>(unrollOrder.begin(), unrollOrder.end());
-          return std::nullopt;
-        });
+        opts.setUnrollTraversalOrderFn(
+            [this](Operation *op) -> std::optional<SmallVector<int64_t>> {
+              vector::ContractionOp contractOp =
+                  cast<vector::ContractionOp>(op);
+              if (contractOp.getIteratorTypes().size() == unrollOrder.size())
+                return SmallVector<int64_t>(unrollOrder.begin(),
+                                            unrollOrder.end());
+              return std::nullopt;
+            });
       }
       populateVectorUnrollPatterns(patterns, opts);
     } else {
-      auto nativeShapeFn = [](Operation *op) -> Optional<SmallVector<int64_t>> {
+      auto nativeShapeFn =
+          [](Operation *op) -> std::optional<SmallVector<int64_t>> {
         auto contractOp = dyn_cast<ContractionOp>(op);
         if (!contractOp)
           return std::nullopt;
@@ -398,7 +401,7 @@ struct TestVectorTransferUnrollingPatterns
         });
     if (reverseUnrollOrder.getValue()) {
       opts.setUnrollTraversalOrderFn(
-          [](Operation *op) -> Optional<SmallVector<int64_t>> {
+          [](Operation *op) -> std::optional<SmallVector<int64_t>> {
             int64_t numLoops = 0;
             if (auto readOp = dyn_cast<vector::TransferReadOp>(op))
               numLoops = readOp.getVectorType().getRank();

diff  --git a/mlir/test/lib/Interfaces/TilingInterface/TestTilingInterface.cpp b/mlir/test/lib/Interfaces/TilingInterface/TestTilingInterface.cpp
index a7e90d4a977d0..d862d0b980c1e 100644
--- a/mlir/test/lib/Interfaces/TilingInterface/TestTilingInterface.cpp
+++ b/mlir/test/lib/Interfaces/TilingInterface/TestTilingInterface.cpp
@@ -51,11 +51,11 @@ struct LinalgTransformationFilter {
 
   explicit LinalgTransformationFilter(
       ArrayRef<StringAttr> matchDisjunction = {},
-      Optional<StringAttr> replacement = std::nullopt);
+      std::optional<StringAttr> replacement = std::nullopt);
 
   explicit LinalgTransformationFilter(
       const FilterFunction &f, ArrayRef<StringAttr> matchDisjunction = {},
-      Optional<StringAttr> replacement = std::nullopt);
+      std::optional<StringAttr> replacement = std::nullopt);
 
   LinalgTransformationFilter(LinalgTransformationFilter &&) = default;
   LinalgTransformationFilter(const LinalgTransformationFilter &) = default;
@@ -89,14 +89,15 @@ struct LinalgTransformationFilter {
 private:
   SmallVector<FilterFunction> filters;
   SmallVector<StringAttr> matchDisjunction;
-  Optional<StringAttr> replacement;
+  std::optional<StringAttr> replacement;
   /// When set to true, if the attribute is not set, it will be treated as
   /// a match. Default is false.
   bool matchByDefault;
 };
 
 LinalgTransformationFilter::LinalgTransformationFilter(
-    ArrayRef<StringAttr> matchDisjunction, Optional<StringAttr> replacement)
+    ArrayRef<StringAttr> matchDisjunction,
+    std::optional<StringAttr> replacement)
     : matchDisjunction(matchDisjunction.begin(), matchDisjunction.end()),
       replacement(replacement), matchByDefault(false) {}
 

diff  --git a/mlir/test/lib/Transforms/TestIntRangeInference.cpp b/mlir/test/lib/Transforms/TestIntRangeInference.cpp
index cb4ce7106d0e6..64ff4ce5b9e51 100644
--- a/mlir/test/lib/Transforms/TestIntRangeInference.cpp
+++ b/mlir/test/lib/Transforms/TestIntRangeInference.cpp
@@ -30,7 +30,7 @@ static LogicalResult replaceWithConstant(DataFlowSolver &solver, OpBuilder &b,
     return failure();
   const ConstantIntRanges &inferredRange =
       maybeInferredRange->getValue().getValue();
-  Optional<APInt> maybeConstValue = inferredRange.getConstantValue();
+  std::optional<APInt> maybeConstValue = inferredRange.getConstantValue();
   if (!maybeConstValue.has_value())
     return failure();
 

diff  --git a/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp b/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp
index d92c36795b2bd..fdb5c2a82364d 100644
--- a/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp
+++ b/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp
@@ -393,7 +393,7 @@ static std::string interleaveToString(Container &container,
   return result;
 }
 
-static Optional<int>
+static std::optional<int>
 findTensorDefArgIndex(StringRef name, SmallVectorImpl<LinalgOperandDef> &args) {
   for (const auto &it : llvm::enumerate(args)) {
     if (it.value().name == name)
@@ -403,7 +403,7 @@ findTensorDefArgIndex(StringRef name, SmallVectorImpl<LinalgOperandDef> &args) {
 }
 
 // Try to map the TypeVar to a predefined or an argument type.
-static Optional<std::string>
+static std::optional<std::string>
 findTypeValue(StringRef typeVar, SmallVectorImpl<LinalgOperandDef> &args) {
   // Handle all predefined types.
   if (typeVar == "I32")
@@ -1056,12 +1056,13 @@ if ({1}Iter != attrs.end()) {{
       ++generatedAssignmentCount;
 
       // Recursively generate the expression.
-      std::function<Optional<std::string>(ScalarExpression &)>
+      std::function<std::optional<std::string>(ScalarExpression &)>
           generateExpression =
-              [&](ScalarExpression &expression) -> Optional<std::string> {
+              [&](ScalarExpression &expression) -> std::optional<std::string> {
         if (expression.arg) {
           // Argument reference.
-          Optional<int> argIndex = findTensorDefArgIndex(*expression.arg, args);
+          std::optional<int> argIndex =
+              findTensorDefArgIndex(*expression.arg, args);
           if (!argIndex) {
             emitError(genContext.getLoc())
                 << "scalar argument not defined on the op: " << *expression.arg;
@@ -1111,7 +1112,7 @@ if ({1}Iter != attrs.end()) {{
           SmallVector<std::string> operandCppValues;
           if (expression.scalarFn->kind == ScalarFnKind::Type) {
             assert(expression.scalarFn->typeVar.has_value());
-            Optional<std::string> typeCppValue =
+            std::optional<std::string> typeCppValue =
                 findTypeValue(*expression.scalarFn->typeVar, args);
             if (!typeCppValue) {
               emitError(genContext.getLoc())
@@ -1141,7 +1142,8 @@ if ({1}Iter != attrs.end()) {{
         emitError(genContext.getLoc()) << "unknown ScalarExpression type";
         return std::nullopt;
       };
-      Optional<std::string> cppValue = generateExpression(assignment->value);
+      std::optional<std::string> cppValue =
+          generateExpression(assignment->value);
       if (!cppValue)
         return failure();
       stmts.push_back(llvm::formatv("yields.push_back({0});", *cppValue));

diff  --git a/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp b/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp
index 67c8b6d709638..abe4bc65142b7 100644
--- a/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp
+++ b/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp
@@ -925,7 +925,7 @@ static void emitOperandDeserialization(const Operator &op, ArrayRef<SMLoc> loc,
       if (valueArg->isVariableLength()) {
         if (i != e - 1) {
           PrintFatalError(loc, "SPIR-V ops can have Variadic<..> or "
-                               "Optional<...> arguments only if "
+                               "std::optional<...> arguments only if "
                                "it's the last argument");
         }
         os << tabs

diff  --git a/mlir/unittests/Analysis/Presburger/IntegerPolyhedronTest.cpp b/mlir/unittests/Analysis/Presburger/IntegerPolyhedronTest.cpp
index b3d6d54de782b..cc55b96d5b1a8 100644
--- a/mlir/unittests/Analysis/Presburger/IntegerPolyhedronTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/IntegerPolyhedronTest.cpp
@@ -60,7 +60,7 @@ static void dump(ArrayRef<MPInt> vec) {
 /// opposite of hasSample.
 static void checkSample(bool hasSample, const IntegerPolyhedron &poly,
                         TestFunction fn = TestFunction::Sample) {
-  Optional<SmallVector<MPInt, 8>> maybeSample;
+  std::optional<SmallVector<MPInt, 8>> maybeSample;
   MaybeOptimum<SmallVector<MPInt, 8>> maybeLexMin;
   switch (fn) {
   case TestFunction::Sample:
@@ -1404,8 +1404,8 @@ TEST(IntegerPolyhedronTest, findSymbolicIntegerLexMin) {
 
 static void
 expectComputedVolumeIsValidOverapprox(const IntegerPolyhedron &poly,
-                                      Optional<int64_t> trueVolume,
-                                      Optional<int64_t> resultBound) {
+                                      std::optional<int64_t> trueVolume,
+                                      std::optional<int64_t> resultBound) {
   expectComputedVolumeIsValidOverapprox(poly.computeVolume(), trueVolume,
                                         resultBound);
 }

diff  --git a/mlir/unittests/Analysis/Presburger/PresburgerSetTest.cpp b/mlir/unittests/Analysis/Presburger/PresburgerSetTest.cpp
index 17feea052da1c..25aa63fcaa044 100644
--- a/mlir/unittests/Analysis/Presburger/PresburgerSetTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/PresburgerSetTest.cpp
@@ -755,8 +755,8 @@ TEST(SetTest, coalesceDivOtherContained) {
 
 static void
 expectComputedVolumeIsValidOverapprox(const PresburgerSet &set,
-                                      Optional<int64_t> trueVolume,
-                                      Optional<int64_t> resultBound) {
+                                      std::optional<int64_t> trueVolume,
+                                      std::optional<int64_t> resultBound) {
   expectComputedVolumeIsValidOverapprox(set.computeVolume(), trueVolume,
                                         resultBound);
 }

diff  --git a/mlir/unittests/Analysis/Presburger/SimplexTest.cpp b/mlir/unittests/Analysis/Presburger/SimplexTest.cpp
index 8524826e5655c..2f4fa27138914 100644
--- a/mlir/unittests/Analysis/Presburger/SimplexTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/SimplexTest.cpp
@@ -572,7 +572,7 @@ TEST(SimplexTest, addDivisionVariable) {
   simplex.addDivisionVariable(getMPIntVec({1, 0}), MPInt(2));
   addInequality(simplex, {1, 0, -3}); // x >= 3.
   addInequality(simplex, {-1, 0, 9}); // x <= 9.
-  Optional<SmallVector<MPInt, 8>> sample = simplex.findIntegerSample();
+  std::optional<SmallVector<MPInt, 8>> sample = simplex.findIntegerSample();
   ASSERT_TRUE(sample.has_value());
   EXPECT_EQ((*sample)[0] / 2, (*sample)[1]);
 }

diff  --git a/mlir/unittests/Analysis/Presburger/Utils.h b/mlir/unittests/Analysis/Presburger/Utils.h
index e18f0ebd09dc2..c3246a09d5ae9 100644
--- a/mlir/unittests/Analysis/Presburger/Utils.h
+++ b/mlir/unittests/Analysis/Presburger/Utils.h
@@ -41,7 +41,8 @@ inline Matrix makeMatrix(unsigned numRow, unsigned numColumns,
 
 /// lhs and rhs represent non-negative integers or positive infinity. The
 /// infinity case corresponds to when the Optional is empty.
-inline bool infinityOrUInt64LE(Optional<MPInt> lhs, Optional<MPInt> rhs) {
+inline bool infinityOrUInt64LE(std::optional<MPInt> lhs,
+                               std::optional<MPInt> rhs) {
   // No constraint.
   if (!rhs)
     return true;
@@ -54,20 +55,19 @@ inline bool infinityOrUInt64LE(Optional<MPInt> lhs, Optional<MPInt> rhs) {
 /// Expect that the computed volume is a valid overapproximation of
 /// the true volume `trueVolume`, while also being at least as good an
 /// approximation as `resultBound`.
-inline void
-expectComputedVolumeIsValidOverapprox(const Optional<MPInt> &computedVolume,
-                                      const Optional<MPInt> &trueVolume,
-                                      const Optional<MPInt> &resultBound) {
+inline void expectComputedVolumeIsValidOverapprox(
+    const std::optional<MPInt> &computedVolume,
+    const std::optional<MPInt> &trueVolume,
+    const std::optional<MPInt> &resultBound) {
   assert(infinityOrUInt64LE(trueVolume, resultBound) &&
          "can't expect result to be less than the true volume");
   EXPECT_TRUE(infinityOrUInt64LE(trueVolume, computedVolume));
   EXPECT_TRUE(infinityOrUInt64LE(computedVolume, resultBound));
 }
 
-inline void
-expectComputedVolumeIsValidOverapprox(const Optional<MPInt> &computedVolume,
-                                      Optional<int64_t> trueVolume,
-                                      Optional<int64_t> resultBound) {
+inline void expectComputedVolumeIsValidOverapprox(
+    const std::optional<MPInt> &computedVolume,
+    std::optional<int64_t> trueVolume, std::optional<int64_t> resultBound) {
   expectComputedVolumeIsValidOverapprox(
       computedVolume, llvm::transformOptional(trueVolume, mpintFromInt64),
       llvm::transformOptional(resultBound, mpintFromInt64));

diff  --git a/mlir/unittests/IR/AttributeTest.cpp b/mlir/unittests/IR/AttributeTest.cpp
index c4af61bf944a8..13c7762563b16 100644
--- a/mlir/unittests/IR/AttributeTest.cpp
+++ b/mlir/unittests/IR/AttributeTest.cpp
@@ -272,7 +272,7 @@ static void checkNativeAccess(MLIRContext *ctx, ArrayRef<T> data,
                          UnmanagedAsmResourceBlob::allocateInferAlign(data));
 
   // Check that we can access and iterate the data properly.
-  Optional<ArrayRef<T>> attrData = attr.tryGetAsArrayRef();
+  std::optional<ArrayRef<T>> attrData = attr.tryGetAsArrayRef();
   EXPECT_TRUE(attrData.has_value());
   EXPECT_EQ(*attrData, data);
 


        


More information about the Mlir-commits mailing list