[NFC] Update from deprecated llvm::Optional (#12734)

This is being deprecated in LLVM
(https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716).
This change was _mostly_ mechanically done via find/ripgrep/sed, with
exception of TableGen files which were more complicated (Optional in DAG
vs member function or C++ type usage and required checking manually).
diff --git a/compiler/src/iree/compiler/API/Internal/Diagnostics.cpp b/compiler/src/iree/compiler/API/Internal/Diagnostics.cpp
index a390d06..b33f5e0 100644
--- a/compiler/src/iree/compiler/API/Internal/Diagnostics.cpp
+++ b/compiler/src/iree/compiler/API/Internal/Diagnostics.cpp
@@ -21,7 +21,7 @@
 
 namespace {
 /// Return a processable CallSiteLoc from the given location.
-Optional<CallSiteLoc> getCallSiteLoc(Location loc) {
+std::optional<CallSiteLoc> getCallSiteLoc(Location loc) {
   if (auto callLoc = dyn_cast<CallSiteLoc>(loc)) return callLoc;
   if (auto nameLoc = dyn_cast<NameLoc>(loc))
     return getCallSiteLoc(cast<NameLoc>(loc).getChildLoc());
@@ -36,31 +36,31 @@
   return std::nullopt;
 }
 
-Optional<Location> findLocToShow(Location loc) {
+std::optional<Location> findLocToShow(Location loc) {
   // 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 different 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 different source location.
         return findLocToShow(opaqueLoc.getFallbackLocation());
       })
-      .Case([](UnknownLoc) -> Optional<Location> {
+      .Case([](UnknownLoc) -> std::optional<Location> {
         // Prefer not to show unknown locations.
         return std::nullopt;
       });
@@ -104,7 +104,7 @@
   // Assemble location fragments.
   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);
   };
 
diff --git a/compiler/src/iree/compiler/Codegen/Common/EncodingInfo.h b/compiler/src/iree/compiler/Codegen/Common/EncodingInfo.h
index 84ce9f2..9691993 100644
--- a/compiler/src/iree/compiler/Codegen/Common/EncodingInfo.h
+++ b/compiler/src/iree/compiler/Codegen/Common/EncodingInfo.h
@@ -27,12 +27,13 @@
 };
 
 /// Extracts encoding from the `tensorType` if specified.
-Optional<IREE::LinalgExt::TensorEncoding> getEncoding(
+std::optional<IREE::LinalgExt::TensorEncoding> getEncoding(
     RankedTensorType tensorType);
 
-Optional<MatmulType> getMatmulType(IREE::LinalgExt::TensorEncoding encoding);
+std::optional<MatmulType> getMatmulType(
+    IREE::LinalgExt::TensorEncoding encoding);
 
-Optional<MatmulOperandRole> getMatmulOperandRole(
+std::optional<MatmulOperandRole> getMatmulOperandRole(
     IREE::LinalgExt::TensorEncoding encoding);
 
 void adjustTileSizesToNarrowStaticShape(
diff --git a/compiler/src/iree/compiler/Codegen/Common/EraseHALDescriptorTypeFromMemRef.cpp b/compiler/src/iree/compiler/Codegen/Common/EraseHALDescriptorTypeFromMemRef.cpp
index 986f44b..cd90df4 100644
--- a/compiler/src/iree/compiler/Codegen/Common/EraseHALDescriptorTypeFromMemRef.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/EraseHALDescriptorTypeFromMemRef.cpp
@@ -35,7 +35,7 @@
     // Pass through for all other types.
     addConversion([](Type type) { return type; });
 
-    addConversion([](BaseMemRefType memRefType) -> Optional<Type> {
+    addConversion([](BaseMemRefType memRefType) -> std::optional<Type> {
       // Expect #hal.descriptor_type memory spaces.
       Attribute spaceAttr = memRefType.getMemorySpace();
       if (!spaceAttr) return std::nullopt;
diff --git a/compiler/src/iree/compiler/Codegen/Common/FlattenMemRefSubspanPass.cpp b/compiler/src/iree/compiler/Codegen/Common/FlattenMemRefSubspanPass.cpp
index b9b3403..1b62b7f 100644
--- a/compiler/src/iree/compiler/Codegen/Common/FlattenMemRefSubspanPass.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/FlattenMemRefSubspanPass.cpp
@@ -88,10 +88,10 @@
 struct FlattenMemRefTypeConverter final : public TypeConverter {
   FlattenMemRefTypeConverter() {
     // Allow all other types.
-    addConversion([](Type type) -> Optional<Type> { return type; });
+    addConversion([](Type type) -> std::optional<Type> { return type; });
 
     // Convert n-D MemRef to 1-D MemRef.
-    addConversion([](MemRefType type) -> Optional<Type> {
+    addConversion([](MemRefType type) -> std::optional<Type> {
       int64_t offset;
       SmallVector<int64_t> strides;
       if (failed(getStridesAndOffset(type, strides, offset))) {
@@ -663,7 +663,7 @@
 ///
 /// Note that this should be kept consistent with how the byte offset was
 /// calculated in the subspan ops!
-Optional<int64_t> getNumBytes(Type type) {
+std::optional<int64_t> getNumBytes(Type type) {
   if (type.isIntOrFloat()) return IREE::Util::getRoundedElementByteWidth(type);
   if (auto vectorType = type.dyn_cast<VectorType>()) {
     auto elementBytes = getNumBytes(vectorType.getElementType());
@@ -736,14 +736,15 @@
     // uniform buffers and dynamic for storage buffers. This matches how IREE
     // models runtime buffers nicely.
     FlattenMemRefTypeConverter interfaceTypeConverter;
-    interfaceTypeConverter.addConversion([](MemRefType type) -> Optional<Type> {
-      // 0-D MemRef types can be used to represent raw pointers for micro-kernel
-      // ABI purposes. Specially allow it.
-      if (isRankZeroMemRef(type)) return type;
+    interfaceTypeConverter.addConversion(
+        [](MemRefType type) -> std::optional<Type> {
+          // 0-D MemRef types can be used to represent raw pointers for
+          // micro-kernel ABI purposes. Specially allow it.
+          if (isRankZeroMemRef(type)) return type;
 
-      // Fall back to the default conversion flow.
-      return std::nullopt;
-    });
+          // Fall back to the default conversion flow.
+          return std::nullopt;
+        });
     flattenPatterns.add<FlattenBindingSubspan>(interfaceTypeConverter, context);
 
     // Other ops generate MemRef values representing internal allocations (e.g.,
@@ -751,13 +752,14 @@
     // kernel. We may not be able to go fully dynamic (e.g., memref::GlobalOp).
     // Still convert everything to 1-D though.
     FlattenMemRefTypeConverter internalTypeConverter;
-    internalTypeConverter.addConversion([](MemRefType type) -> Optional<Type> {
-      // 0-D or 1-D MemRef types are okay.
-      if (isRankZeroOrOneMemRef(type)) return type;
+    internalTypeConverter.addConversion(
+        [](MemRefType type) -> std::optional<Type> {
+          // 0-D or 1-D MemRef types are okay.
+          if (isRankZeroOrOneMemRef(type)) return type;
 
-      // Fall back to the default conversion flow.
-      return std::nullopt;
-    });
+          // Fall back to the default conversion flow.
+          return std::nullopt;
+        });
     flattenPatterns
         .add<FlattenAlloc<memref::AllocaOp>, FlattenAlloc<memref::AllocOp>,
              FlattenGlobal, FlattenGetGlobal, LinearizeLoadIndices,
diff --git a/compiler/src/iree/compiler/Codegen/Common/FoldAffineMinInDistributedLoops.cpp b/compiler/src/iree/compiler/Codegen/Common/FoldAffineMinInDistributedLoops.cpp
index 10ffb57..df927cb 100644
--- a/compiler/src/iree/compiler/Codegen/Common/FoldAffineMinInDistributedLoops.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/FoldAffineMinInDistributedLoops.cpp
@@ -88,7 +88,7 @@
       if (!loopInfo) return failure();
       LLVM_DEBUG(llvm::dbgs() << *loopInfo);
 
-      Optional<int64_t> untiledStep =
+      std::optional<int64_t> untiledStep =
           getConstantIntValue(loopInfo->untiledStep);
       // For IREE right now the original untiled loop should have step 1..
       if (!untiledStep || *untiledStep != 1) return failure();
diff --git a/compiler/src/iree/compiler/Codegen/Common/GPUDistributeSharedMemoryCopy.cpp b/compiler/src/iree/compiler/Codegen/Common/GPUDistributeSharedMemoryCopy.cpp
index 3314be9..599e77f 100644
--- a/compiler/src/iree/compiler/Codegen/Common/GPUDistributeSharedMemoryCopy.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/GPUDistributeSharedMemoryCopy.cpp
@@ -112,7 +112,7 @@
 
 /// Compute a tile size so that the numer of iteraton is equal to the flat
 /// workgroup size.
-static Optional<SmallVector<int64_t>> getTileToDistributableSize(
+static std::optional<SmallVector<int64_t>> getTileToDistributableSize(
     linalg::GenericOp copyOp, int64_t flatWorkgroupSize) {
   SmallVector<int64_t, 4> shape = copyOp.getStaticLoopRanges();
   unsigned bitWidth = copyOp.getDpsInitOperand(0)
@@ -148,7 +148,7 @@
         SmallVector<Value, 4> tileSizesVal;
         auto copyOp = dyn_cast<linalg::GenericOp>(operation);
         if (!copyOp) return tileSizesVal;
-        Optional<SmallVector<int64_t>> staticSize =
+        std::optional<SmallVector<int64_t>> staticSize =
             getTileToDistributableSize(copyOp, flatWorkgroupSize);
         for (int64_t dim : *staticSize) {
           tileSizesVal.push_back(
diff --git a/compiler/src/iree/compiler/Codegen/Common/IREEComprehensiveBufferizePass.cpp b/compiler/src/iree/compiler/Codegen/Common/IREEComprehensiveBufferizePass.cpp
index 9d5b3cc..f11cf14 100644
--- a/compiler/src/iree/compiler/Codegen/Common/IREEComprehensiveBufferizePass.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/IREEComprehensiveBufferizePass.cpp
@@ -60,10 +60,11 @@
     : public IREEComprehensiveBufferizeBase<IREEComprehensiveBufferizePass> {
  public:
   explicit IREEComprehensiveBufferizePass(
-      Optional<BufferizationOptions::AllocationFn> allocationFn = std::nullopt,
-      Optional<BufferizationOptions::DeallocationFn> deallocationFn =
+      std::optional<BufferizationOptions::AllocationFn> allocationFn =
           std::nullopt,
-      Optional<BufferizationOptions::MemCpyFn> memCpyFn = std::nullopt)
+      std::optional<BufferizationOptions::DeallocationFn> deallocationFn =
+          std::nullopt,
+      std::optional<BufferizationOptions::MemCpyFn> memCpyFn = std::nullopt)
       : allocationFn(allocationFn),
         deallocationFn(deallocationFn),
         memCpyFn(memCpyFn) {}
@@ -89,9 +90,9 @@
   void runOnOperation() override;
 
  private:
-  const Optional<BufferizationOptions::AllocationFn> allocationFn;
-  const Optional<BufferizationOptions::DeallocationFn> deallocationFn;
-  const Optional<BufferizationOptions::MemCpyFn> memCpyFn;
+  const std::optional<BufferizationOptions::AllocationFn> allocationFn;
+  const std::optional<BufferizationOptions::DeallocationFn> deallocationFn;
+  const std::optional<BufferizationOptions::MemCpyFn> memCpyFn;
 };
 }  // namespace
 
@@ -218,9 +219,9 @@
 }
 
 std::unique_ptr<OperationPass<ModuleOp>> createIREEComprehensiveBufferizePass(
-    Optional<BufferizationOptions::AllocationFn> allocationFn,
-    Optional<BufferizationOptions::DeallocationFn> deallocationFn,
-    Optional<BufferizationOptions::MemCpyFn> memCpyFn) {
+    std::optional<BufferizationOptions::AllocationFn> allocationFn,
+    std::optional<BufferizationOptions::DeallocationFn> deallocationFn,
+    std::optional<BufferizationOptions::MemCpyFn> memCpyFn) {
   if (!allocationFn) allocationFn = defaultAllocationFn;
   if (!deallocationFn) deallocationFn = defaultDeallocationFn;
   if (!memCpyFn) memCpyFn = defaultMemCpyFn;
@@ -241,9 +242,9 @@
 
 void addIREEComprehensiveBufferizePasses(
     OpPassManager &passManager,
-    Optional<BufferizationOptions::AllocationFn> allocationFn,
-    Optional<BufferizationOptions::DeallocationFn> deallocationFn,
-    Optional<BufferizationOptions::MemCpyFn> memCpyFn) {
+    std::optional<BufferizationOptions::AllocationFn> allocationFn,
+    std::optional<BufferizationOptions::DeallocationFn> deallocationFn,
+    std::optional<BufferizationOptions::MemCpyFn> memCpyFn) {
   passManager.addPass(createEliminateEmptyTensorsPass());
   passManager.addPass(bufferization::createEmptyTensorToAllocTensorPass());
   passManager.addPass(createIREEComprehensiveBufferizePass(
diff --git a/compiler/src/iree/compiler/Codegen/Common/MaterializeEncodingIntoPackUnPack.cpp b/compiler/src/iree/compiler/Codegen/Common/MaterializeEncodingIntoPackUnPack.cpp
index 289f7a5..08c0714 100644
--- a/compiler/src/iree/compiler/Codegen/Common/MaterializeEncodingIntoPackUnPack.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/MaterializeEncodingIntoPackUnPack.cpp
@@ -271,13 +271,13 @@
   return encodingInfo;
 }
 
-Optional<TensorEncoding> getEncoding(RankedTensorType tensorType) {
+std::optional<TensorEncoding> getEncoding(RankedTensorType tensorType) {
   auto encodingAttr = tensorType.getEncoding().dyn_cast_or_null<EncodingAttr>();
   if (!encodingAttr) return std::nullopt;
   return encodingAttr.getEncoding().getValue();
 }
 
-Optional<MatmulType> getMatmulType(TensorEncoding encoding) {
+std::optional<MatmulType> getMatmulType(TensorEncoding encoding) {
   switch (encoding) {
     case TensorEncoding::MATMUL_F32F32F32_LHS:
     case TensorEncoding::MATMUL_F32F32F32_RHS:
@@ -292,7 +292,7 @@
   }
 }
 
-Optional<MatmulOperandRole> getMatmulOperandRole(TensorEncoding encoding) {
+std::optional<MatmulOperandRole> getMatmulOperandRole(TensorEncoding encoding) {
   switch (encoding) {
     case TensorEncoding::MATMUL_F32F32F32_LHS:
     case TensorEncoding::MATMUL_I8I8I32_LHS:
@@ -334,7 +334,7 @@
 FailureOr<MaterializeEncodingValueInfo>
 chooseDynamicEncodingInfoVMVXMicrokernels(RankedTensorType tensorType,
                                           OpBuilder &builder, Location loc) {
-  Optional<TensorEncoding> encoding = getEncoding(tensorType);
+  std::optional<TensorEncoding> encoding = getEncoding(tensorType);
   if (!encoding) return failure();
   auto matmulType = getMatmulType(*encoding);
   auto matmulOperandRole = getMatmulOperandRole(*encoding);
diff --git a/compiler/src/iree/compiler/Codegen/Common/RemoveTrivialLoops.cpp b/compiler/src/iree/compiler/Codegen/Common/RemoveTrivialLoops.cpp
index c53e3d8..76b5b52 100644
--- a/compiler/src/iree/compiler/Codegen/Common/RemoveTrivialLoops.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/RemoveTrivialLoops.cpp
@@ -41,7 +41,7 @@
 /// If the value is a threadID return the range [0, workgroupSize-1].
 /// If the number of workgroup is known also return the range of workgroupId ad
 /// workgroupCount.
-static Optional<std::pair<AffineExpr, AffineExpr>> getWorkgroupRange(
+static std::optional<std::pair<AffineExpr, AffineExpr>> getWorkgroupRange(
     Value processorValue, SmallVectorImpl<Value> & /*dims*/,
     SmallVectorImpl<Value> & /*symbols*/, ArrayRef<int64_t> workgroupCount,
     ArrayRef<int64_t> workgroupSize) {
diff --git a/compiler/src/iree/compiler/Codegen/Common/TransformExtensions/CommonExtensions.cpp b/compiler/src/iree/compiler/Codegen/Common/TransformExtensions/CommonExtensions.cpp
index d8f2b59..0a186a0 100644
--- a/compiler/src/iree/compiler/Codegen/Common/TransformExtensions/CommonExtensions.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/TransformExtensions/CommonExtensions.cpp
@@ -280,7 +280,7 @@
                                 bool swapPaddingElideCornerCase) {
   patterns.add<linalg::ExtractSliceOfPadTensorSwapPattern>(
       patterns.getContext(),
-      [&](tensor::ExtractSliceOp) -> llvm::Optional<bool> {
+      [&](tensor::ExtractSliceOp) -> std::optional<bool> {
         return !swapPaddingElideCornerCase;
       });
 }
@@ -290,13 +290,13 @@
   scf::populateSCFForLoopCanonicalizationPatterns(patterns);
 }
 
-static Optional<SmallVector<int64_t>> getGPUTensorCoreNativeMmaSyncVectorSize(
-    Operation *op) {
+static std::optional<SmallVector<int64_t>>
+getGPUTensorCoreNativeMmaSyncVectorSize(Operation *op) {
   return getMmaNativeVectorSize(op);
 }
 
 static void addUnrollVectorsGpuMmaSyncPatterns(RewritePatternSet &patterns) {
-  auto unrollOrder = [](Operation *op) -> Optional<SmallVector<int64_t>> {
+  auto unrollOrder = [](Operation *op) -> std::optional<SmallVector<int64_t>> {
     auto contract = dyn_cast<vector::ContractionOp>(op);
     if (!contract) return std::nullopt;
     return mlir::iree_compiler::gpuMmaUnrollOrder(contract);
@@ -307,13 +307,13 @@
                     .setUnrollTraversalOrderFn(unrollOrder));
 }
 
-static Optional<SmallVector<int64_t>> getGPUTensorCoreNativeWmmaVectorSize(
+static std::optional<SmallVector<int64_t>> getGPUTensorCoreNativeWmmaVectorSize(
     Operation *op) {
   return getWmmaNativeVectorSize(op);
 }
 
 static void addUnrollVectorsGpuWmmaPatterns(RewritePatternSet &patterns) {
-  auto unrollOrder = [](Operation *op) -> Optional<SmallVector<int64_t>> {
+  auto unrollOrder = [](Operation *op) -> std::optional<SmallVector<int64_t>> {
     auto contract = dyn_cast<vector::ContractionOp>(op);
     if (!contract) return std::nullopt;
     return mlir::iree_compiler::gpuMmaUnrollOrder(contract);
@@ -851,7 +851,7 @@
 static LogicalResult lowerWorkgroupCountComputingRegion(
     transform::TransformState &state, RewriterBase &rewriter, Location loc,
     HAL::ExecutableExportOp exportOp, ArrayRef<OpFoldResult> numThreads,
-    ArrayRef<OpFoldResult> tileSizes, Optional<ArrayAttr> mapping) {
+    ArrayRef<OpFoldResult> tileSizes, std::optional<ArrayAttr> mapping) {
   Region &r = exportOp.getWorkgroupCount();
   if (!r.hasOneBlock()) {
     return rewriter.notifyMatchFailure(exportOp,
diff --git a/compiler/src/iree/compiler/Codegen/Common/TypePropagationPass.cpp b/compiler/src/iree/compiler/Codegen/Common/TypePropagationPass.cpp
index 1b0379a..68982b2 100644
--- a/compiler/src/iree/compiler/Codegen/Common/TypePropagationPass.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/TypePropagationPass.cpp
@@ -39,7 +39,7 @@
 
 /// Returns the legal element type to use instead of the passed in element type.
 /// If the type is already legal, returns std::nullopt.
-static Optional<Type> getLegalizedElementType(Type elementType) {
+static std::optional<Type> getLegalizedElementType(Type elementType) {
   if (auto intType = elementType.dyn_cast<IntegerType>()) {
     unsigned bitWidth = intType.getWidth();
     unsigned byteAlignedBitWidth =
@@ -69,10 +69,11 @@
 
 /// Legalizes the given type. If the type is already legal, returns
 /// std::nullopt.
-static Optional<Type> getLegalizedType(Type t) {
+static std::optional<Type> getLegalizedType(Type t) {
   if (auto shapedType = t.dyn_cast<RankedTensorType>()) {
     Type elementType = shapedType.getElementType();
-    Optional<Type> legalizedElementType = getLegalizedElementType(elementType);
+    std::optional<Type> legalizedElementType =
+        getLegalizedElementType(elementType);
     if (!legalizedElementType) return std::nullopt;
     return RankedTensorType::get(shapedType.getShape(),
                                  legalizedElementType.value(),
@@ -116,7 +117,7 @@
       return rewriter.notifyMatchFailure(
           constantOp, "expected attribute type to be shaped type");
     }
-    Optional<Type> legalizedElementType =
+    std::optional<Type> legalizedElementType =
         getLegalizedElementType(attrType.getElementType());
     if (!legalizedElementType) {
       return rewriter.notifyMatchFailure(constantOp,
@@ -223,7 +224,7 @@
         signatureConverter.addInputs(index, argType);
         continue;
       }
-      Optional<Type> legalizedArgType = getLegalizedElementType(argType);
+      std::optional<Type> legalizedArgType = getLegalizedElementType(argType);
       if (!legalizedArgType) {
         return genericOp.emitOpError("failed to get legalized type for arg ")
                << index;
@@ -268,7 +269,7 @@
           modifyYield = true;
           OpOperand *yieldOperand =
               modifiedOp.getMatchingYieldValue(modifiedOpOperand);
-          Optional<Type> legalizedType =
+          std::optional<Type> legalizedType =
               getLegalizedElementType(yieldOperand->get().getType());
           if (!legalizedType) {
             return genericOp.emitOpError(
@@ -298,7 +299,7 @@
       linalg::FillOp fillOp, OpAdaptor adaptor,
       ConversionPatternRewriter &rewriter) const final {
     Value value = adaptor.getInputs().front();
-    Optional<Type> legalizedElementType =
+    std::optional<Type> legalizedElementType =
         getLegalizedElementType(value.getType());
     if (!legalizedElementType) {
       return fillOp.emitOpError("failed to get legalized type for value");
diff --git a/compiler/src/iree/compiler/Codegen/Common/UserConfig.cpp b/compiler/src/iree/compiler/Codegen/Common/UserConfig.cpp
index 16cfcaf..64c8753 100644
--- a/compiler/src/iree/compiler/Codegen/Common/UserConfig.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/UserConfig.cpp
@@ -23,7 +23,7 @@
   if (failed(setTranslationInfo(entryPointFn, info))) return failure();
 
   SmallVector<int64_t> workgroupSize = compilationInfo.getWorkgroupSizeVals();
-  llvm::Optional<int64_t> subgroupSize = compilationInfo.getSubgroupSize();
+  std::optional<int64_t> subgroupSize = compilationInfo.getSubgroupSize();
   if (failed(setDispatchConfig(entryPointFn, workgroupSize, subgroupSize))) {
     return failure();
   }
diff --git a/compiler/src/iree/compiler/Codegen/Dialect/LoweringConfig.cpp b/compiler/src/iree/compiler/Codegen/Dialect/LoweringConfig.cpp
index 1660124..7cbbd1a 100644
--- a/compiler/src/iree/compiler/Codegen/Dialect/LoweringConfig.cpp
+++ b/compiler/src/iree/compiler/Codegen/Dialect/LoweringConfig.cpp
@@ -191,7 +191,7 @@
 CompilationInfoAttr CompilationInfoAttr::get(
     MLIRContext *context, LoweringConfigAttr configAttr,
     TranslationInfoAttr translationInfo, ArrayRef<int64_t> workgroupSize,
-    llvm::Optional<int64_t> subgroupSize) {
+    std::optional<int64_t> subgroupSize) {
   ArrayAttr workgroupSizeAttr = getI64IntegerArrayAttr(context, workgroupSize);
   return get(context, configAttr, translationInfo, workgroupSizeAttr,
              subgroupSize);
@@ -200,7 +200,7 @@
 LogicalResult CompilationInfoAttr::verify(
     function_ref<InFlightDiagnostic()> emitError,
     LoweringConfigAttr loweringConfig, TranslationInfoAttr translationInfo,
-    ArrayAttr workgroupSize, llvm::Optional<int64_t> subgroupSize) {
+    ArrayAttr workgroupSize, std::optional<int64_t> subgroupSize) {
   if (!loweringConfig) {
     return emitError() << "missing lowering config";
   }
@@ -259,14 +259,14 @@
 }
 
 SmallVector<int64_t> getWorkgroupSize(IREE::HAL::ExecutableExportOp exportOp) {
-  if (Optional<ArrayAttr> workgroupSizeAttrList = exportOp.getWorkgroupSize()) {
+  if (std::optional<ArrayAttr> workgroupSizeAttrList =
+          exportOp.getWorkgroupSize()) {
     return getIntegerVals(*workgroupSizeAttrList);
   }
   return {};
 }
 
-llvm::Optional<int64_t> getSubgroupSize(
-    IREE::HAL::ExecutableExportOp exportOp) {
+std::optional<int64_t> getSubgroupSize(IREE::HAL::ExecutableExportOp exportOp) {
   if (IntegerAttr attr = exportOp.getSubgroupSizeAttr()) {
     return attr.getValue().getSExtValue();
   }
@@ -275,7 +275,7 @@
 
 LogicalResult setDispatchConfig(func::FuncOp entryPoint,
                                 ArrayRef<int64_t> workgroupSize,
-                                llvm::Optional<int64_t> subgroupSize) {
+                                std::optional<int64_t> subgroupSize) {
   FailureOr<IREE::HAL::ExecutableExportOp> exportOp = getEntryPoint(entryPoint);
   if (failed(exportOp)) return failure();
   MLIRContext *context = exportOp->getContext();
diff --git a/compiler/src/iree/compiler/Codegen/Dialect/LoweringConfig.h b/compiler/src/iree/compiler/Codegen/Dialect/LoweringConfig.h
index 4e53c8c..5975e76 100644
--- a/compiler/src/iree/compiler/Codegen/Dialect/LoweringConfig.h
+++ b/compiler/src/iree/compiler/Codegen/Dialect/LoweringConfig.h
@@ -65,14 +65,14 @@
 SmallVector<int64_t> getWorkgroupSize(IREE::HAL::ExecutableExportOp exportOp);
 
 /// Returns the subgroup size specified on the `exportOp`.
-llvm::Optional<int64_t> getSubgroupSize(IREE::HAL::ExecutableExportOp exportOp);
+std::optional<int64_t> getSubgroupSize(IREE::HAL::ExecutableExportOp exportOp);
 
 /// Sets and overwrites the dispatch workgroup/subgroup size for the given entry
 /// point function. Returns failure if the given entry point is not exported via
 /// hal.executable.export.
 LogicalResult setDispatchConfig(func::FuncOp entryPoint,
                                 ArrayRef<int64_t> workgroupSize,
-                                llvm::Optional<int64_t> subgroupSize);
+                                std::optional<int64_t> subgroupSize);
 
 /// Sets and overwites the translate executable info for the given entry point.
 /// Returns failure if the given entry point is not exported via
@@ -127,7 +127,7 @@
     func::FuncOp entryPointFn, Operation *op, TileSizesListTypeRef tileSizes,
     IREE::Codegen::DispatchLoweringPassPipeline passPipeline,
     ArrayRef<int64_t> workgroupSize = {},
-    llvm::Optional<int64_t> subgroupSize = {},
+    std::optional<int64_t> subgroupSize = {},
     unsigned softwarePipelineDepth = 0,
     unsigned softwarePipelineStoreStage = 1) {
   MLIRContext *context = entryPointFn.getContext();
diff --git a/compiler/src/iree/compiler/Codegen/Dialect/LoweringConfig.td b/compiler/src/iree/compiler/Codegen/Dialect/LoweringConfig.td
index 30001b2..55ce459 100644
--- a/compiler/src/iree/compiler/Codegen/Dialect/LoweringConfig.td
+++ b/compiler/src/iree/compiler/Codegen/Dialect/LoweringConfig.td
@@ -216,7 +216,7 @@
     AttrParameter<"TranslationInfoAttr", "">:$translationInfo,
     DefaultValuedParameter<"ArrayAttr", "ArrayAttr::get($_ctxt, {})",
         "The workgroup size to use during translation.">:$workgroupSize,
-    OptionalParameter<"llvm::Optional<int64_t>",
+    OptionalParameter<"std::optional<int64_t>",
         "The subgroup size to use during translation.">:$subgroupSize
   );
 
@@ -231,7 +231,7 @@
     AttrBuilder<(ins "LoweringConfigAttr":$configAttr,
       "TranslationInfoAttr":$translationInfo,
       "ArrayRef<int64_t>":$workgroupSize,
-      "llvm::Optional<int64_t>":$subgroupSize
+      "std::optional<int64_t>":$subgroupSize
       )>,
   ];
   let extraClassDeclaration = [{
diff --git a/compiler/src/iree/compiler/Codegen/Interfaces/PartitionableLoopsInterface.cpp b/compiler/src/iree/compiler/Codegen/Interfaces/PartitionableLoopsInterface.cpp
index 274e11b..adf7618 100644
--- a/compiler/src/iree/compiler/Codegen/Interfaces/PartitionableLoopsInterface.cpp
+++ b/compiler/src/iree/compiler/Codegen/Interfaces/PartitionableLoopsInterface.cpp
@@ -32,8 +32,7 @@
 
 /// Returns the partitionable loops for all Linalg ops.
 llvm::SmallVector<unsigned> getPartitionableLoopsImpl(
-    linalg::LinalgOp linalgOp,
-    llvm::Optional<unsigned> maxNumPartitionedLoops) {
+    linalg::LinalgOp linalgOp, std::optional<unsigned> maxNumPartitionedLoops) {
   llvm::SmallVector<unsigned> parallelLoops;
   linalgOp.getParallelDims(parallelLoops);
   // Get the static loop ranges.
@@ -65,7 +64,7 @@
     : public PartitionableLoopsInterface::ExternalModel<
           LinalgOpPartitionableLoops<OpTy>, OpTy> {
   llvm::SmallVector<unsigned> getPartitionableLoops(
-      Operation *op, llvm::Optional<unsigned> maxNumPartitionedLoops) const {
+      Operation *op, std::optional<unsigned> maxNumPartitionedLoops) const {
     auto linalgOp = cast<linalg::LinalgOp>(op);
     return getPartitionableLoopsImpl(linalgOp, maxNumPartitionedLoops);
   }
@@ -76,7 +75,7 @@
     : public PartitionableLoopsInterface::ExternalModel<
           Mmt4DOpPartitionableLoops, linalg::Mmt4DOp> {
   llvm::SmallVector<unsigned> getPartitionableLoops(
-      Operation *op, llvm::Optional<unsigned> maxNumPartitionedLoops) const {
+      Operation *op, std::optional<unsigned> maxNumPartitionedLoops) const {
     return {0, 1};
   }
 };
@@ -88,7 +87,7 @@
     : public PartitionableLoopsInterface::ExternalModel<
           OuterParallelAsPartitionableLoops<OpTy>, OpTy> {
   llvm::SmallVector<unsigned> getPartitionableLoops(
-      Operation *op, llvm::Optional<unsigned> maxNumPartitionedLoops) const {
+      Operation *op, std::optional<unsigned> maxNumPartitionedLoops) const {
     // For now just return the loops that are returned by the
     // `TiledOpInterface`. This needs to be further pruned to remove unit-dim
     // loops, but that needs the interface to return the static sizes of the
@@ -120,7 +119,7 @@
 struct NoPartitionableLoops : public PartitionableLoopsInterface::ExternalModel<
                                   NoPartitionableLoops<OpTy>, OpTy> {
   llvm::SmallVector<unsigned> getPartitionableLoops(
-      Operation *op, llvm::Optional<unsigned> maxNumPartitionedLoops) const {
+      Operation *op, std::optional<unsigned> maxNumPartitionedLoops) const {
     return {};
   }
 };
@@ -130,7 +129,7 @@
     : public PartitionableLoopsInterface::ExternalModel<
           FftOpPartitionableLoops, IREE::LinalgExt::FftOp> {
   llvm::SmallVector<unsigned> getPartitionableLoops(
-      Operation *op, llvm::Optional<unsigned> maxNumPartitionedLoops) const {
+      Operation *op, std::optional<unsigned> maxNumPartitionedLoops) const {
     auto fftOp = cast<IREE::LinalgExt::FftOp>(op);
     auto range = llvm::seq<unsigned>(0, fftOp.getOperandRank());
     SmallVector<unsigned> partitionableLoops(range.begin(), range.end());
@@ -157,7 +156,7 @@
     : public PartitionableLoopsInterface::ExternalModel<
           AllParallelAsPartitionableLoops<OpTy>, OpTy> {
   llvm::SmallVector<unsigned> getPartitionableLoops(
-      Operation *op, llvm::Optional<unsigned> maxNumPartitionedLoops) const {
+      Operation *op, std::optional<unsigned> maxNumPartitionedLoops) const {
     SmallVector<unsigned> partitionableLoops;
     auto interfaceOp = cast<OpTy>(op);
     for (auto iteratorType :
diff --git a/compiler/src/iree/compiler/Codegen/Interfaces/PartitionableLoopsInterface.td b/compiler/src/iree/compiler/Codegen/Interfaces/PartitionableLoopsInterface.td
index 8e45778..a9c4b56 100644
--- a/compiler/src/iree/compiler/Codegen/Interfaces/PartitionableLoopsInterface.td
+++ b/compiler/src/iree/compiler/Codegen/Interfaces/PartitionableLoopsInterface.td
@@ -29,7 +29,7 @@
       }],
       /*retTy=*/"::llvm::SmallVector<unsigned>",
       /*methodName=*/"getPartitionableLoops",
-      /*args=*/(ins "llvm::Optional<unsigned>":$maxNumPartitionedLoops),
+      /*args=*/(ins "std::optional<unsigned>":$maxNumPartitionedLoops),
       /*methodBody=*/"",
       /*defaultImplementation*/"return {};"
     >,
diff --git a/compiler/src/iree/compiler/Codegen/LLVMCPU/ConvertToLLVM.cpp b/compiler/src/iree/compiler/Codegen/LLVMCPU/ConvertToLLVM.cpp
index b2c1bff..fbd1f2d 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMCPU/ConvertToLLVM.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMCPU/ConvertToLLVM.cpp
@@ -449,9 +449,9 @@
   }
 };
 
-static Optional<uint64_t> mapValueType(Type type) {
-  return TypeSwitch<Type, Optional<uint64_t>>(type)
-      .Case<IntegerType>([&](Type type) -> Optional<uint64_t> {
+static std::optional<uint64_t> mapValueType(Type type) {
+  return TypeSwitch<Type, std::optional<uint64_t>>(type)
+      .Case<IntegerType>([&](Type type) -> std::optional<uint64_t> {
         if (type.isUnsignedInteger()) {
           switch (type.getIntOrFloatBitWidth()) {
             case 8:
@@ -479,7 +479,7 @@
             return std::nullopt;
         }
       })
-      .Case<FloatType>([&](Type type) -> Optional<uint64_t> {
+      .Case<FloatType>([&](Type type) -> std::optional<uint64_t> {
         if (type.isBF16()) {
           return IREE_INSTRUMENT_DISPATCH_VALUE_TYPE_BFLOAT_16;
         }
@@ -494,10 +494,10 @@
             return std::nullopt;
         }
       })
-      .Case<IndexType>([&](Type type) -> Optional<uint64_t> {
+      .Case<IndexType>([&](Type type) -> std::optional<uint64_t> {
         return IREE_INSTRUMENT_DISPATCH_VALUE_TYPE_SINT_64;
       })
-      .Default([&](Type) -> Optional<uint64_t> { return std::nullopt; });
+      .Default([&](Type) -> std::optional<uint64_t> { return std::nullopt; });
 }
 
 struct ConvertHALInstrumentValueOp
@@ -510,7 +510,7 @@
     auto loc = instrumentOp.getLoc();
 
     // Only convert ops we can handle, otherwise warn and discard.
-    Optional<uint64_t> valueType;
+    std::optional<uint64_t> valueType;
     if (operands.getOperand().getType().isa<LLVM::LLVMPointerType>()) {
       valueType = IREE_INSTRUMENT_DISPATCH_VALUE_TYPE_POINTER;
     } else {
diff --git a/compiler/src/iree/compiler/Codegen/LLVMCPU/KernelDispatch.cpp b/compiler/src/iree/compiler/Codegen/LLVMCPU/KernelDispatch.cpp
index 722b43a..b89281b 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMCPU/KernelDispatch.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMCPU/KernelDispatch.cpp
@@ -227,7 +227,8 @@
 
 /// Looks for the `native_vector_size` attribute in the hal.executable.target
 /// looked up from this op.
-static Optional<int64_t> getNativeVectorSizeInBytes(func::FuncOp entryPointFn) {
+static std::optional<int64_t> getNativeVectorSizeInBytes(
+    func::FuncOp entryPointFn) {
   auto targetAttr = IREE::HAL::ExecutableTargetAttr::lookup(entryPointFn);
   auto nativeVectorSizeAttr =
       getConfigIntegerAttr(targetAttr, "native_vector_size");
@@ -241,7 +242,7 @@
 /// of elements that correspond to the native vector size. Returns 1 as the
 /// fallback.
 static int64_t getVectorSize(func::FuncOp entryPointFn, unsigned byteWidth) {
-  if (Optional<int64_t> nativeVectorSize =
+  if (std::optional<int64_t> nativeVectorSize =
           getNativeVectorSizeInBytes(entryPointFn)) {
     return nativeVectorSize.value() / byteWidth;
   }
@@ -1693,7 +1694,7 @@
   SmallVector<Range> iterationDomain =
       tilingInterfaceOp.getIterationDomain(builder);
   auto getStaticValue = [](OpFoldResult ofr) -> int64_t {
-    Optional<int64_t> intVal = getConstantIntValue(ofr);
+    std::optional<int64_t> intVal = getConstantIntValue(ofr);
     if (!intVal) return ShapedType::kDynamic;
     return intVal.value();
   };
diff --git a/compiler/src/iree/compiler/Codegen/LLVMCPU/LLVMCPULowerExecutableTarget.cpp b/compiler/src/iree/compiler/Codegen/LLVMCPU/LLVMCPULowerExecutableTarget.cpp
index 4fe3266..60251c7 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMCPU/LLVMCPULowerExecutableTarget.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMCPU/LLVMCPULowerExecutableTarget.cpp
@@ -143,7 +143,7 @@
     // is fine.
     llvm::StringMap<IREE::HAL::ExecutableExportOp> exportOps =
         getAllEntryPoints(moduleOp);
-    Optional<IREE::Codegen::TranslationInfoAttr> translationInfo;
+    std::optional<IREE::Codegen::TranslationInfoAttr> translationInfo;
     for (auto &it : exportOps) {
       auto exportOp = it.second;
       if (IREE::Codegen::TranslationInfoAttr currTranslationInfo =
diff --git a/compiler/src/iree/compiler/Codegen/LLVMCPU/LLVMCPUMaterializeEncodingPass.cpp b/compiler/src/iree/compiler/Codegen/LLVMCPU/LLVMCPUMaterializeEncodingPass.cpp
index c8c72e0..43d0f22 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMCPU/LLVMCPUMaterializeEncodingPass.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMCPU/LLVMCPUMaterializeEncodingPass.cpp
@@ -116,7 +116,7 @@
   MaterializeEncodingTypeConverter typeConverter(
       [targetAttr](
           RankedTensorType tensorType) -> FailureOr<MaterializeEncodingInfo> {
-        Optional<TensorEncoding> encoding = getEncoding(tensorType);
+        std::optional<TensorEncoding> encoding = getEncoding(tensorType);
         if (!encoding) return failure();
 
         auto matmulType = getMatmulType(*encoding);
diff --git a/compiler/src/iree/compiler/Codegen/LLVMCPU/LLVMCPUMmt4dVectorLowering.cpp b/compiler/src/iree/compiler/Codegen/LLVMCPU/LLVMCPUMmt4dVectorLowering.cpp
index d5bb14d..3cfbef6 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMCPU/LLVMCPUMmt4dVectorLowering.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMCPU/LLVMCPUMmt4dVectorLowering.cpp
@@ -42,7 +42,7 @@
   MLIRContext *context = &getContext();
   auto funcOp = getOperation();
 
-  Optional<int64_t> numLoops;
+  std::optional<int64_t> numLoops;
   funcOp.walk([&](vector::ContractionOp op) {
     if (numLoops) return signalPassFailure();
     numLoops = op.getIndexingMapsArray()[0].getNumDims();
diff --git a/compiler/src/iree/compiler/Codegen/LLVMCPU/Utils.cpp b/compiler/src/iree/compiler/Codegen/LLVMCPU/Utils.cpp
index 9569295..c026620 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMCPU/Utils.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMCPU/Utils.cpp
@@ -14,29 +14,30 @@
 namespace mlir {
 namespace iree_compiler {
 
-Optional<StringRef> getCpuFeatures(IREE::HAL::ExecutableTargetAttr targetAttr) {
+std::optional<StringRef> getCpuFeatures(
+    IREE::HAL::ExecutableTargetAttr targetAttr) {
   auto cpuFeatures = getConfigStringAttr(targetAttr, "cpu_features");
   if (!cpuFeatures) return std::nullopt;
   return cpuFeatures->getValue();
 }
 
 bool isX86(IREE::HAL::ExecutableTargetAttr targetAttr) {
-  Optional<llvm::Triple> triple = getTargetTriple(targetAttr);
+  std::optional<llvm::Triple> triple = getTargetTriple(targetAttr);
   return triple && triple.value().isX86();
 }
 
 bool isX86_64(IREE::HAL::ExecutableTargetAttr targetAttr) {
-  Optional<llvm::Triple> triple = getTargetTriple(targetAttr);
+  std::optional<llvm::Triple> triple = getTargetTriple(targetAttr);
   return triple && triple.value().getArch() == llvm::Triple::x86_64;
 }
 
 bool isAArch64(IREE::HAL::ExecutableTargetAttr targetAttr) {
-  Optional<llvm::Triple> triple = getTargetTriple(targetAttr);
+  std::optional<llvm::Triple> triple = getTargetTriple(targetAttr);
   return triple && triple.value().isAArch64();
 }
 
 bool isRISCV(IREE::HAL::ExecutableTargetAttr targetAttr) {
-  Optional<llvm::Triple> triple = getTargetTriple(targetAttr);
+  std::optional<llvm::Triple> triple = getTargetTriple(targetAttr);
   return triple && triple.value().isRISCV();
 }
 
@@ -51,7 +52,7 @@
 // over processed HAL information or keeping the TTI instance alive and query
 // subtarget features data structure.
 bool hasFeature(IREE::HAL::ExecutableTargetAttr targetAttr, StringRef feature) {
-  Optional<StringRef> features = getCpuFeatures(targetAttr);
+  std::optional<StringRef> features = getCpuFeatures(targetAttr);
   if (!features) {
     return false;
   }
diff --git a/compiler/src/iree/compiler/Codegen/LLVMCPU/Utils.h b/compiler/src/iree/compiler/Codegen/LLVMCPU/Utils.h
index f1af81b..2b1394b 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMCPU/Utils.h
+++ b/compiler/src/iree/compiler/Codegen/LLVMCPU/Utils.h
@@ -13,7 +13,8 @@
 namespace iree_compiler {
 
 /// Returns the CPU target features associated with the `targetAttr`, if set.
-Optional<StringRef> getCpuFeatures(IREE::HAL::ExecutableTargetAttr targetAttr);
+std::optional<StringRef> getCpuFeatures(
+    IREE::HAL::ExecutableTargetAttr targetAttr);
 
 /// Methods to get target information.
 bool isX86(IREE::HAL::ExecutableTargetAttr targetAttr);
diff --git a/compiler/src/iree/compiler/Codegen/LLVMGPU/ConvertToLLVM.cpp b/compiler/src/iree/compiler/Codegen/LLVMGPU/ConvertToLLVM.cpp
index 9fc68c1..78d001d 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMGPU/ConvertToLLVM.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMGPU/ConvertToLLVM.cpp
@@ -165,7 +165,7 @@
     }
 
     uint64_t alignement;
-    if (llvm::Optional<uint64_t> alignementInfo = allocOp.getAlignment()) {
+    if (std::optional<uint64_t> alignementInfo = allocOp.getAlignment()) {
       alignement = alignementInfo.value();
     } else {
       // If no alignment specified align at least to the size of an element.
diff --git a/compiler/src/iree/compiler/Codegen/LLVMGPU/KernelConfig.cpp b/compiler/src/iree/compiler/Codegen/LLVMGPU/KernelConfig.cpp
index e4c16b8..f6ab187 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMGPU/KernelConfig.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMGPU/KernelConfig.cpp
@@ -625,7 +625,7 @@
 // TODO: this should be part of LinalgOp interface, the equivalent member
 // function currently only support the case where all the dimensions are static
 // while we want to support dynamic shapes.
-static Optional<int64_t> getLinalgDimSize(linalg::LinalgOp op, int64_t d) {
+static std::optional<int64_t> getLinalgDimSize(linalg::LinalgOp op, int64_t d) {
   for (auto [mapIdx, map] : llvm::enumerate(op.getIndexingMapsArray())) {
     for (auto [dimIdx, dim] : llvm::enumerate(map.getResults())) {
       auto expr = dim.dyn_cast<AffineDimExpr>();
@@ -712,7 +712,7 @@
   }
   if (!foundSingleReductionOutput) return failure();
 
-  Optional<int64_t> dimSize = getLinalgDimSize(op, reductionDims[0]);
+  std::optional<int64_t> dimSize = getLinalgDimSize(op, reductionDims[0]);
   if (!dimSize || *dimSize % cudaWarpSize != 0) return failure();
 
   const Type elementType = op.getDpsInitOperand(0)
diff --git a/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPULowerExecutableTarget.cpp b/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPULowerExecutableTarget.cpp
index 5ce610f..dd12786 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPULowerExecutableTarget.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPULowerExecutableTarget.cpp
@@ -92,7 +92,8 @@
 static LogicalResult verifyEntryPoint(
     ModuleOp moduleOp, IREE::Codegen::TranslationInfoAttr translationInfo,
     IREE::HAL::ExecutableExportOp exportOp) {
-  Optional<mlir::ArrayAttr> workgroupSizeAttr = exportOp.getWorkgroupSize();
+  std::optional<mlir::ArrayAttr> workgroupSizeAttr =
+      exportOp.getWorkgroupSize();
 
   if (workgroupSizeAttr.has_value()) {
     std::array<int64_t, 3> workgroupSizes;
@@ -134,7 +135,7 @@
   // is fine.
   llvm::StringMap<IREE::HAL::ExecutableExportOp> exportOps =
       getAllEntryPoints(moduleOp);
-  Optional<IREE::Codegen::TranslationInfoAttr> translationInfo;
+  std::optional<IREE::Codegen::TranslationInfoAttr> translationInfo;
   for (auto &it : exportOps) {
     auto exportOp = it.second;
     if (IREE::Codegen::TranslationInfoAttr currTranslationInfo =
diff --git a/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTensorCoreVectorization.cpp b/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTensorCoreVectorization.cpp
index 8ea046a..edfff5e 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTensorCoreVectorization.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTensorCoreVectorization.cpp
@@ -45,7 +45,7 @@
 
 static void populateVectorUnrollPatterns(RewritePatternSet &patterns,
                                          bool useMmaSyncShape) {
-  auto unrollOrder = [](Operation *op) -> Optional<SmallVector<int64_t>> {
+  auto unrollOrder = [](Operation *op) -> std::optional<SmallVector<int64_t>> {
     auto contract = dyn_cast<vector::ContractionOp>(op);
     if (!contract) return std::nullopt;
     return gpuMmaUnrollOrder(contract);
diff --git a/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTensorPad.cpp b/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTensorPad.cpp
index 4c985a9..5c5a678 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTensorPad.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTensorPad.cpp
@@ -28,7 +28,7 @@
   SmallVector<int64_t> paddedShape(origShape.begin(), origShape.end());
   for (const auto &[index, size] :
        llvm::enumerate(tensorLoad.getMixedSizes())) {
-    if (Optional<int64_t> cst = getConstantIntValue(size)) {
+    if (std::optional<int64_t> cst = getConstantIntValue(size)) {
       paddedShape[index] = cst.value();
     } else {
       FailureOr<int64_t> upperBound =
diff --git a/compiler/src/iree/compiler/Codegen/LLVMGPU/TransformExtensions/LLVMGPUExtensions.cpp b/compiler/src/iree/compiler/Codegen/LLVMGPU/TransformExtensions/LLVMGPUExtensions.cpp
index 12ce13c..9090e3c 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMGPU/TransformExtensions/LLVMGPUExtensions.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMGPU/TransformExtensions/LLVMGPUExtensions.cpp
@@ -359,7 +359,7 @@
            << "export op is missing --- the transform is not applied";
   }
 
-  Optional<ArrayAttr> maybeAttr = exportOp.getWorkgroupSize();
+  std::optional<ArrayAttr> maybeAttr = exportOp.getWorkgroupSize();
   // TODO: Pervasive 3 constant in IREE.
   if (!maybeAttr || maybeAttr->size() != 3) {
     // Return a silenceable failure and set the expected 1 result to nullptr.
diff --git a/compiler/src/iree/compiler/Codegen/Passes.h b/compiler/src/iree/compiler/Codegen/Passes.h
index 75fa7db..505767b 100644
--- a/compiler/src/iree/compiler/Codegen/Passes.h
+++ b/compiler/src/iree/compiler/Codegen/Passes.h
@@ -44,10 +44,11 @@
 using bufferization::BufferizationOptions;
 void addIREEComprehensiveBufferizePasses(
     OpPassManager &passManager,
-    Optional<BufferizationOptions::AllocationFn> allocationFn = std::nullopt,
-    Optional<BufferizationOptions::DeallocationFn> deallocationFn =
+    std::optional<BufferizationOptions::AllocationFn> allocationFn =
         std::nullopt,
-    Optional<BufferizationOptions::MemCpyFn> memCpyFn = std::nullopt);
+    std::optional<BufferizationOptions::DeallocationFn> deallocationFn =
+        std::nullopt,
+    std::optional<BufferizationOptions::MemCpyFn> memCpyFn = std::nullopt);
 
 /// Pass to perform canonicalizations/cleanups related to HAL interface/buffer
 /// allocations and view operations.
@@ -100,10 +101,11 @@
 /// with the allocated MemRefType having no stride map (i.e. default row-major
 /// striding) and default memory space.
 std::unique_ptr<OperationPass<ModuleOp>> createIREEComprehensiveBufferizePass(
-    Optional<BufferizationOptions::AllocationFn> allocationFn = std::nullopt,
-    Optional<BufferizationOptions::DeallocationFn> deallocationFn =
+    std::optional<BufferizationOptions::AllocationFn> allocationFn =
         std::nullopt,
-    Optional<BufferizationOptions::MemCpyFn> memCpyFn = std::nullopt);
+    std::optional<BufferizationOptions::DeallocationFn> deallocationFn =
+        std::nullopt,
+    std::optional<BufferizationOptions::MemCpyFn> memCpyFn = std::nullopt);
 
 std::unique_ptr<OperationPass<func::FuncOp>>
 createHoistStaticallyBoundAllocationsPass();
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/ConvertToSPIRVPass.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/ConvertToSPIRVPass.cpp
index 6f36659..950d1b3 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/ConvertToSPIRVPass.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/ConvertToSPIRVPass.cpp
@@ -377,10 +377,10 @@
           "expected workgroup_size attribute to be set for SPIR-V lowering");
       return signalPassFailure();
     }
-    Optional<int64_t> subgroupSize = getSubgroupSize(exportOp);
+    std::optional<int64_t> subgroupSize = getSubgroupSize(exportOp);
     auto workgroupSize32 = llvm::to_vector<4>(llvm::map_range(
         workgroupSize, [](int64_t v) { return static_cast<int32_t>(v); }));
-    Optional<int> subgroupSize32;
+    std::optional<int> subgroupSize32;
     if (subgroupSize) subgroupSize32 = *subgroupSize;
     funcOp->setAttr(
         spirv::getEntryPointABIAttrName(),
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/KernelConfig.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/KernelConfig.cpp
index b35fe52..53e1896 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/KernelConfig.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/KernelConfig.cpp
@@ -694,7 +694,7 @@
 
 /// Returns the cooperative matrix (M, N, K) sizes that are supported by the
 /// target environment and match the given parameters.
-static Optional<CooperativeMatrixSize> getCooperativeMatrixSize(
+static std::optional<CooperativeMatrixSize> getCooperativeMatrixSize(
     spirv::ResourceLimitsAttr resourceLimits,
     const unsigned numSubgroupsPerWorkgroup,
     const unsigned numMNTilesPerSubgroup, Type aType, Type bType, Type cType,
@@ -837,7 +837,7 @@
   };
 
   spirv::ResourceLimitsAttr limits = targetEnv.getResourceLimits();
-  Optional<CooperativeMatrixSize> coopMatSize = getCooperativeMatrixSize(
+  std::optional<CooperativeMatrixSize> coopMatSize = getCooperativeMatrixSize(
       limits, numSubgroupsPerWorkgroup, numMNTilesPerSubgroup,
       getElementType(lhs), getElementType(rhs), getElementType(init), dimM,
       dimN, dimK);
@@ -846,11 +846,11 @@
   auto pipeline = IREE::Codegen::DispatchLoweringPassPipeline::
       SPIRVCooperativeMatrixVectorize;
 
-  Optional<int64_t> subgroupSize = limits.getSubgroupSize();
+  std::optional<int64_t> subgroupSize = limits.getSubgroupSize();
   // AMD RDNA architectures supports both wave32 and wave64 modes. Prefer to use
   // wave32 mode for better performance.
   if (targetEnv.getVendorID() == spirv::Vendor::AMD) {
-    if (Optional<int> minSize = limits.getMinSubgroupSize())
+    if (std::optional<int> minSize = limits.getMinSubgroupSize())
       subgroupSize = *minSize;
   }
 
@@ -1030,7 +1030,7 @@
   if (!foundSingleReductionOutput) return failure();
 
   const int subgroupSize = targetEnv.getResourceLimits().getSubgroupSize();
-  Optional<int64_t> dimSize = op.getStaticLoopRanges()[reductionDims[0]];
+  std::optional<int64_t> dimSize = op.getStaticLoopRanges()[reductionDims[0]];
   if (!dimSize || *dimSize % subgroupSize != 0) return failure();
 
   const Type elementType =
@@ -1185,7 +1185,8 @@
 
   // Distribute workload to the given `numThreads` by allowing a potental loss.
   auto distributeToThreads = [&](int64_t numThreads,
-                                 Optional<int64_t> lossFactor = std::nullopt) {
+                                 std::optional<int64_t> lossFactor =
+                                     std::nullopt) {
     LLVM_DEBUG(llvm::dbgs() << "\nLoss factor: " << lossFactor << "\n");
     initConfiguration();
     // If there are more than 3 parallel dim try to tile the extra higher level
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/Passes.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/Passes.cpp
index bb32745..5364123 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/Passes.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/Passes.cpp
@@ -71,7 +71,7 @@
                                                     MemRefType memRefType,
                                                     ValueRange dynamicSizes,
                                                     unsigned alignment) {
-  Optional<unsigned> space =
+  std::optional<unsigned> space =
       spirv::mapVulkanStorageClassToMemorySpace(spirv::StorageClass::Function);
   MemRefType allocType = MemRefType::get(
       memRefType.getShape(), memRefType.getElementType(), {}, *space);
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVCreateFastSlowPath.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVCreateFastSlowPath.cpp
index 1d8d9e9..a7238b4 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVCreateFastSlowPath.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVCreateFastSlowPath.cpp
@@ -36,7 +36,7 @@
 
 /// Returns true if the the given `attrOrValue` is a constant zero.
 static bool isZero(OpFoldResult attrOrValue) {
-  if (Optional<int64_t> val = getConstantIntValue(attrOrValue)) {
+  if (std::optional<int64_t> val = getConstantIntValue(attrOrValue)) {
     return val.value() == 0;
   }
   return false;
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVLowerExecutableTargetPass.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVLowerExecutableTargetPass.cpp
index 0887523..750cf7f 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVLowerExecutableTargetPass.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVLowerExecutableTargetPass.cpp
@@ -77,7 +77,8 @@
 static LogicalResult verifyEntryPoint(
     ModuleOp moduleOp, IREE::Codegen::TranslationInfoAttr translationInfo,
     IREE::HAL::ExecutableExportOp exportOp) {
-  Optional<mlir::ArrayAttr> workgroupSizeAttr = exportOp.getWorkgroupSize();
+  std::optional<mlir::ArrayAttr> workgroupSizeAttr =
+      exportOp.getWorkgroupSize();
 
   if (!workgroupSizeAttr || workgroupSizeAttr->size() != 3) {
     return moduleOp.emitError(
@@ -129,7 +130,7 @@
   // is fine.
   llvm::StringMap<IREE::HAL::ExecutableExportOp> exportOps =
       getAllEntryPoints(moduleOp);
-  Optional<IREE::Codegen::TranslationInfoAttr> translationInfo;
+  std::optional<IREE::Codegen::TranslationInfoAttr> translationInfo;
   for (auto &it : exportOps) {
     auto exportOp = it.second;
     if (IREE::Codegen::TranslationInfoAttr currTranslationInfo =
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVMapMemRefStorageClass.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVMapMemRefStorageClass.cpp
index 82fd5b4..a4155cf 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVMapMemRefStorageClass.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVMapMemRefStorageClass.cpp
@@ -22,7 +22,8 @@
 namespace iree_compiler {
 namespace {
 
-Optional<spirv::StorageClass> mapHALDescriptorTypeForVulkan(Attribute attr) {
+std::optional<spirv::StorageClass> mapHALDescriptorTypeForVulkan(
+    Attribute attr) {
   if (auto dtAttr = attr.dyn_cast_or_null<IREE::HAL::DescriptorTypeAttr>()) {
     switch (dtAttr.getValue()) {
       case IREE::HAL::DescriptorType::UniformBuffer:
@@ -44,7 +45,8 @@
   return spirv::mapMemorySpaceToVulkanStorageClass(attr);
 }
 
-Optional<spirv::StorageClass> mapHALDescriptorTypeForOpenCL(Attribute attr) {
+std::optional<spirv::StorageClass> mapHALDescriptorTypeForOpenCL(
+    Attribute attr) {
   if (auto dtAttr = attr.dyn_cast_or_null<IREE::HAL::DescriptorTypeAttr>()) {
     switch (dtAttr.getValue()) {
       case IREE::HAL::DescriptorType::UniformBuffer:
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndPromote.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndPromote.cpp
index 4e64e23..5e329b6 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndPromote.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndPromote.cpp
@@ -204,7 +204,7 @@
       exportOp->getWorkgroupSize().value(),
       [&](Attribute attr) { return attr.cast<IntegerAttr>().getInt(); }));
   int64_t totalThreads = workgroupSize[0] * workgroupSize[1] * workgroupSize[2];
-  Optional<int> subgroupSize = getSPIRVSubgroupSize(funcOp);
+  std::optional<int> subgroupSize = getSPIRVSubgroupSize(funcOp);
   if (!subgroupSize) {
     funcOp->emitError("failed to query subgroup size");
     return signalPassFailure();
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndVectorizeToCooperativeOps.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndVectorizeToCooperativeOps.cpp
index 15dd960..70497b6 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndVectorizeToCooperativeOps.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndVectorizeToCooperativeOps.cpp
@@ -149,7 +149,7 @@
 }
 
 template <typename ExtOpTy>
-Optional<SmallVector<int64_t>> getExtOpVectorShape(
+std::optional<SmallVector<int64_t>> getExtOpVectorShape(
     ExtOpTy op, ArrayRef<int64_t> nativeShape) {
   auto insert =
       op.getOperand().template getDefiningOp<vector::InsertStridedSliceOp>();
@@ -169,7 +169,7 @@
 
 /// Returns vector shape matching native cooperative op sizes for unrolling
 /// high-D vectors.
-Optional<SmallVector<int64_t>> getCooperativeOpVectorShape(
+std::optional<SmallVector<int64_t>> getCooperativeOpVectorShape(
     Operation *op, ArrayRef<int64_t> nativeShape) {
   // Unroll vector.contract ops according to native cooperative matrix size.
   if (auto contractOp = dyn_cast<vector::ContractionOp>(op)) {
@@ -333,7 +333,7 @@
     // Then tile and distribute to subgroups.
 
     {
-      Optional<int> subgroupSize = getSPIRVSubgroupSize(funcOp);
+      std::optional<int> subgroupSize = getSPIRVSubgroupSize(funcOp);
       if (!subgroupSize) {
         funcOp.emitError("failed to query subgroup size");
         return signalPassFailure();
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorize.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorize.cpp
index 0c3523f..47d386c 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorize.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorize.cpp
@@ -118,7 +118,7 @@
   return nativeSize;
 }
 
-Optional<SmallVector<int64_t>> getNativeVectorShape(Operation *op) {
+std::optional<SmallVector<int64_t>> getNativeVectorShape(Operation *op) {
   if (OpTrait::hasElementwiseMappableTraits(op) && op->getNumResults() == 1) {
     if (auto vecType = op->getResultTypes()[0].dyn_cast<VectorType>()) {
       SmallVector<int64_t> nativeSize(vecType.getRank(), 1);
@@ -127,7 +127,7 @@
     }
   }
 
-  return TypeSwitch<Operation *, Optional<SmallVector<int64_t>>>(op)
+  return TypeSwitch<Operation *, std::optional<SmallVector<int64_t>>>(op)
       .Case<VectorTransferOpInterface, vector::ContractionOp,
             vector::MultiDimReductionOp, vector::ReductionOp,
             vector::TransposeOp>(
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorizeLoadStore.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorizeLoadStore.cpp
index 0c155ae..d6c8df0 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorizeLoadStore.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorizeLoadStore.cpp
@@ -70,7 +70,7 @@
 }
 
 /// Returns the bitwidth of a scalar or vector type.
-static Optional<unsigned> getBitWidth(Type type) {
+static std::optional<unsigned> getBitWidth(Type type) {
   if (type.isIntOrFloat()) {
     return type.getIntOrFloatBitWidth();
   }
@@ -93,7 +93,8 @@
     }
     auto transferOp = dyn_cast<VectorTransferOpInterface>(op);
     if (!transferOp) return 0;
-    Optional<unsigned> transferSize = getBitWidth(transferOp.getVectorType());
+    std::optional<unsigned> transferSize =
+        getBitWidth(transferOp.getVectorType());
     if (!transferSize) return 0;
     minBits = std::min(minBits, *transferSize);
   }
@@ -115,7 +116,8 @@
     // The `leadingDimension` attributes specifies the stride (numer of
     // *elements*) over the memref for the leading dimension.
     auto memrefType = memrefVal.getType().cast<MemRefType>();
-    Optional<unsigned> elementBits = getBitWidth(memrefType.getElementType());
+    std::optional<unsigned> elementBits =
+        getBitWidth(memrefType.getElementType());
     if (!elementBits) return 0;
     int64_t strideBits = stride * *elementBits;
     // Make sure the stride is aligned with the planned vector bitwidth.
@@ -248,7 +250,7 @@
         memrefUsageAnalysis(memrefUsageAnalysis) {}
 
  protected:
-  Optional<MemRefType> getVectorizedMemRefType(
+  std::optional<MemRefType> getVectorizedMemRefType(
       ConversionPatternRewriter &rewriter, Value memRefValue) const;
 
   /// Adjusts indices for vector transfer / GPU MMA load/store ops to index into
@@ -294,9 +296,9 @@
     auto readVectorType = read.getVectorType();
     if (!scalarMemrefType || !vectorMemrefType) return failure();
 
-    Optional<unsigned> vectorMemrefElemSize =
+    std::optional<unsigned> vectorMemrefElemSize =
         getBitWidth(vectorMemrefType.getElementType());
-    Optional<unsigned> readVecSize = getBitWidth(readVectorType);
+    std::optional<unsigned> readVecSize = getBitWidth(readVectorType);
 
     auto indices = adjustIndices(scalarMemrefType, vectorMemrefType,
                                  adaptor.getIndices(), rewriter, loc);
@@ -346,9 +348,9 @@
     auto writeVectorType = write.getVectorType();
     if (!scalarMemrefType || !vectorMemrefType) return failure();
 
-    Optional<unsigned> vectorMemrefElemSize =
+    std::optional<unsigned> vectorMemrefElemSize =
         getBitWidth(vectorMemrefType.getElementType());
-    Optional<unsigned> writeVecSize = getBitWidth(writeVectorType);
+    std::optional<unsigned> writeVecSize = getBitWidth(writeVectorType);
 
     auto indices = adjustIndices(scalarMemrefType, vectorMemrefType,
                                  adaptor.getIndices(), rewriter, loc);
@@ -382,7 +384,8 @@
 /// * memref<1024xf16> vectorized with a size of 128bits will return
 /// memref<128xvec<4xf32>>
 template <typename OpTy>
-Optional<MemRefType> MemRefConversionPattern<OpTy>::getVectorizedMemRefType(
+std::optional<MemRefType>
+MemRefConversionPattern<OpTy>::getVectorizedMemRefType(
     ConversionPatternRewriter &rewriter, Value memRefValue) const {
   MemRefType type = memRefValue.getType().cast<MemRefType>();
   unsigned vectorNumBits =
@@ -416,9 +419,9 @@
     MemRefType scalarMemrefType, MemRefType vectorMemrefType,
     ValueRange indices, ConversionPatternRewriter &rewriter,
     Location loc) const {
-  Optional<unsigned> vectorMemrefElemSize =
+  std::optional<unsigned> vectorMemrefElemSize =
       getBitWidth(vectorMemrefType.getElementType());
-  Optional<unsigned> scalarMemrefElemSize =
+  std::optional<unsigned> scalarMemrefElemSize =
       getBitWidth(scalarMemrefType.getElementType());
   if (!vectorMemrefElemSize || !scalarMemrefElemSize) return failure();
 
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/Utils.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/Utils.cpp
index 2e0d495..cf9f676 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/Utils.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/Utils.cpp
@@ -47,7 +47,7 @@
   return false;
 }
 
-llvm::Optional<int> getSPIRVSubgroupSize(func::FuncOp funcOp) {
+std::optional<int> getSPIRVSubgroupSize(func::FuncOp funcOp) {
   auto moduleOp = funcOp->getParentOfType<ModuleOp>();
   llvm::StringMap<IREE::HAL::ExecutableExportOp> exportOps =
       getAllEntryPoints(moduleOp);
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/Utils.h b/compiler/src/iree/compiler/Codegen/SPIRV/Utils.h
index faf60e6..b2c3f69 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/Utils.h
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/Utils.h
@@ -27,7 +27,7 @@
 /// Given a FuncOp, returns the subgroup size to use for CodeGen, by first
 /// querying the hal.executable.export op, and then the SPIR-V target
 /// environment. Returns std::nullopt on failures.
-llvm::Optional<int> getSPIRVSubgroupSize(func::FuncOp funcOp);
+std::optional<int> getSPIRVSubgroupSize(func::FuncOp funcOp);
 
 /// Returns the attribute name carrying information about distribution.
 const char *getSPIRVDistributeAttrName();
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/Verifiers.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/Verifiers.cpp
index 99e49a3..3906f7b 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/Verifiers.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/Verifiers.cpp
@@ -53,7 +53,7 @@
   LLVM_DEBUG(llvm::dbgs() << "target environment: " << targetEnvAttr << "\n");
 
   auto funcOp = op->getParentOfType<func::FuncOp>();
-  const Optional<int> subgroupSize = getSPIRVSubgroupSize(funcOp);
+  const std::optional<int> subgroupSize = getSPIRVSubgroupSize(funcOp);
   if (!subgroupSize) return funcOp->emitError("failed to query subgroup size");
   const int maxSharedMemory = limits.getMaxComputeSharedMemorySize();
   const int maxThreads = limits.getMaxComputeWorkgroupInvocations();
@@ -188,7 +188,7 @@
   LLVM_DEBUG(llvm::dbgs() << "target environment: " << targetEnvAttr << "\n");
 
   auto funcOp = op->getParentOfType<func::FuncOp>();
-  const Optional<int> subgroupSize = getSPIRVSubgroupSize(funcOp);
+  const std::optional<int> subgroupSize = getSPIRVSubgroupSize(funcOp);
   if (!subgroupSize) return funcOp->emitError("failed to query subgroup size");
   const int maxSharedMemory = limits.getMaxComputeSharedMemorySize();
   const int maxThreads = limits.getMaxComputeWorkgroupInvocations();
diff --git a/compiler/src/iree/compiler/Codegen/Transforms/AffineMinDistributedSCFCanonicalization.cpp b/compiler/src/iree/compiler/Codegen/Transforms/AffineMinDistributedSCFCanonicalization.cpp
index 7900c10..deff449 100644
--- a/compiler/src/iree/compiler/Codegen/Transforms/AffineMinDistributedSCFCanonicalization.cpp
+++ b/compiler/src/iree/compiler/Codegen/Transforms/AffineMinDistributedSCFCanonicalization.cpp
@@ -136,7 +136,7 @@
 /// With N a compile time constant. This operations can be replace by
 /// `%cN = arith.constant N : index` if we can prove that %lb, %step and %ub are
 /// divisible by N.
-static Optional<int64_t> foldAffineMin(AffineMinOp minOp) {
+static std::optional<int64_t> foldAffineMin(AffineMinOp minOp) {
   AffineMap map = minOp.getAffineMap();
   int64_t constantResult = 0;
   for (AffineExpr result : map.getResults()) {
@@ -158,7 +158,7 @@
 
   mlir::LogicalResult matchAndRewrite(
       mlir::AffineMinOp minOp, mlir::PatternRewriter &rewriter) const override {
-    Optional<int64_t> cst = foldAffineMin(minOp);
+    std::optional<int64_t> cst = foldAffineMin(minOp);
     if (!cst) return failure();
     rewriter.replaceOpWithNewOp<arith::ConstantOp>(minOp,
                                                    rewriter.getIndexAttr(*cst));
diff --git a/compiler/src/iree/compiler/Codegen/Transforms/Transforms.cpp b/compiler/src/iree/compiler/Codegen/Transforms/Transforms.cpp
index e9c05d7..828b403 100644
--- a/compiler/src/iree/compiler/Codegen/Transforms/Transforms.cpp
+++ b/compiler/src/iree/compiler/Codegen/Transforms/Transforms.cpp
@@ -258,7 +258,7 @@
 
 // TODO(antigainst): enable dynamic shape support once they are needed.
 template <typename TensorReshapeOp>
-static Optional<Value> getStaticReshapeOpSrc(TensorReshapeOp reshapeOp) {
+static std::optional<Value> getStaticReshapeOpSrc(TensorReshapeOp reshapeOp) {
   auto reshapeSrcType =
       reshapeOp.getSrc().getType().template cast<ShapedType>();
   auto reshapeDstType = reshapeOp.getType().template cast<ShapedType>();
@@ -293,7 +293,7 @@
 
   LogicalResult matchAndRewrite(TensorReshapeOp reshapeOp,
                                 PatternRewriter &rewriter) const override {
-    Optional<Value> reshapeSrc =
+    std::optional<Value> reshapeSrc =
         getStaticReshapeOpSrc<TensorReshapeOp>(reshapeOp);
     if (!reshapeSrc) return failure();
 
@@ -370,7 +370,7 @@
       return failure();
 
     // Dynamic shapes are currently unsupported.
-    Optional<Value> reshapeSrc =
+    std::optional<Value> reshapeSrc =
         isa<tensor::CollapseShapeOp>(reshapeOp)
             ? getStaticReshapeOpSrc<tensor::CollapseShapeOp>(
                   cast<tensor::CollapseShapeOp>(reshapeOp))
diff --git a/compiler/src/iree/compiler/Codegen/Transforms/Transforms.h b/compiler/src/iree/compiler/Codegen/Transforms/Transforms.h
index 4e71a87..d775b4b 100644
--- a/compiler/src/iree/compiler/Codegen/Transforms/Transforms.h
+++ b/compiler/src/iree/compiler/Codegen/Transforms/Transforms.h
@@ -79,7 +79,7 @@
 void populateAffineMinSCFCanonicalizationPattern(RewritePatternSet &patterns);
 
 using GetMinMaxExprFn =
-    std::function<Optional<std::pair<AffineExpr, AffineExpr>>(
+    std::function<std::optional<std::pair<AffineExpr, AffineExpr>>(
         Value value, SmallVectorImpl<Value> &dims,
         SmallVectorImpl<Value> &symbols)>;
 
diff --git a/compiler/src/iree/compiler/Codegen/Utils/GPUUtils.cpp b/compiler/src/iree/compiler/Codegen/Utils/GPUUtils.cpp
index 650a730..5a35273 100644
--- a/compiler/src/iree/compiler/Codegen/Utils/GPUUtils.cpp
+++ b/compiler/src/iree/compiler/Codegen/Utils/GPUUtils.cpp
@@ -74,7 +74,7 @@
   std::array<int64_t, 3> workgroupSize;
   FailureOr<IREE::HAL::ExecutableExportOp> exportOp =
       mlir::iree_compiler::getEntryPoint(funcOp);
-  llvm::Optional<mlir::ArrayAttr> workgroupSizeAttr =
+  std::optional<mlir::ArrayAttr> workgroupSizeAttr =
       exportOp->getWorkgroupSize();
   assert(workgroupSizeAttr.has_value());
   for (auto [index, attr] : llvm::enumerate(workgroupSizeAttr.value())) {
@@ -116,7 +116,7 @@
 
 /// Pick an unrolling order that will allow tensorcore operation to reuse LHS
 /// register. This is needed to get good performance on sm_80 target.
-Optional<SmallVector<int64_t>> gpuMmaUnrollOrder(
+std::optional<SmallVector<int64_t>> gpuMmaUnrollOrder(
     vector::ContractionOp contract) {
   SmallVector<int64_t> order;
   // First make reduction the outer dimensions.
@@ -149,10 +149,10 @@
 // GPU workgroup memory
 //===----------------------------------------------------------------------===//
 
-Optional<Value> allocateWorkgroupMemory(OpBuilder &builder,
-                                        memref::SubViewOp subview,
-                                        ArrayRef<Value> sizeBounds,
-                                        DataLayout &) {
+std::optional<Value> allocateWorkgroupMemory(OpBuilder &builder,
+                                             memref::SubViewOp subview,
+                                             ArrayRef<Value> sizeBounds,
+                                             DataLayout &) {
   OpBuilder::InsertionGuard guard(builder);
 
   func::FuncOp funcOp = subview->getParentOfType<func::FuncOp>();
@@ -554,7 +554,7 @@
   return laneVal;
 }
 
-Optional<SmallVector<int64_t>> getWmmaNativeVectorSize(Operation *op) {
+std::optional<SmallVector<int64_t>> getWmmaNativeVectorSize(Operation *op) {
   // Currently hardcode the size of wmma operation. When more cases are
   // supported this should be picked based on what the backend supports.
   int64_t m = 16;
@@ -598,7 +598,7 @@
 // getMmaNativeVectorSize
 //===----------------------------------------------------------------------===//
 /// Returns vector::ContractionOp operand's index where the result is used.
-static Optional<int> getVectorContractOpOperandId(
+static std::optional<int> getVectorContractOpOperandId(
     vector::ContractionOp contractOp, OpResult result) {
   if (contractOp.getLhs() == result) return 0;
   if (contractOp.getRhs() == result) return 1;
@@ -609,7 +609,7 @@
 /// Returns vector::ContractionOp operand's index  where the
 /// vector::TransferReadOp is consumed either consumed directly or via
 /// vector::ExtractStridedSliceOp.
-static Optional<int> getVectorContractOpOperandIdForVectorReadOp(
+static std::optional<int> getVectorContractOpOperandIdForVectorReadOp(
     Operation *op) {
   vector::ContractionOp contractOp;
 
@@ -624,7 +624,7 @@
 }
 
 /// Helper function to return native size for MMA.SYNC-based operations.
-Optional<SmallVector<int64_t>> getMmaNativeVectorSize(Operation *op) {
+std::optional<SmallVector<int64_t>> getMmaNativeVectorSize(Operation *op) {
   // Shape of native Tensor Core GPU mma.sync operations.
   int64_t mmaShapeM = 16;
   int64_t mmaShapeN = 8;
@@ -665,7 +665,8 @@
     auto resultVectorType = readOp.getVector().getType().cast<VectorType>();
     Type resultElementType = resultVectorType.getElementType();
 
-    Optional<int> operandId = getVectorContractOpOperandIdForVectorReadOp(op);
+    std::optional<int> operandId =
+        getVectorContractOpOperandIdForVectorReadOp(op);
     if (!operandId) {
       op->emitError() << "Cannot determine operandId this "
                          "vector::TransferReadOp is used as in the "
diff --git a/compiler/src/iree/compiler/Codegen/Utils/GPUUtils.h b/compiler/src/iree/compiler/Codegen/Utils/GPUUtils.h
index dccd40e..3632e8d 100644
--- a/compiler/src/iree/compiler/Codegen/Utils/GPUUtils.h
+++ b/compiler/src/iree/compiler/Codegen/Utils/GPUUtils.h
@@ -50,7 +50,7 @@
 
 /// Pick an unrolling order that will allow tensorcore operation to reuse LHS
 /// register. This is needed to get good performance on sm_80 target.
-Optional<SmallVector<int64_t>> gpuMmaUnrollOrder(
+std::optional<SmallVector<int64_t>> gpuMmaUnrollOrder(
     vector::ContractionOp contract);
 
 //===----------------------------------------------------------------------===//
@@ -59,10 +59,10 @@
 
 /// Allocates GPU workgroup memory matching the given `subview`. If there are
 /// dynamic dimensions, the bounds are in `sizeBounds`.
-Optional<Value> allocateWorkgroupMemory(OpBuilder &builder,
-                                        memref::SubViewOp subview,
-                                        ArrayRef<Value> sizeBounds,
-                                        DataLayout &);
+std::optional<Value> allocateWorkgroupMemory(OpBuilder &builder,
+                                             memref::SubViewOp subview,
+                                             ArrayRef<Value> sizeBounds,
+                                             DataLayout &);
 
 /// Deallocates GPU workgroup memory behind `buffer`.
 LogicalResult deallocateWorkgroupMemory(OpBuilder &, Value buffer);
@@ -84,10 +84,10 @@
 
 /// Return the native size of an operation used in contraction calculation.
 // TODO: Make this take HW specific sizes.
-Optional<SmallVector<int64_t>> getWmmaNativeVectorSize(Operation *op);
+std::optional<SmallVector<int64_t>> getWmmaNativeVectorSize(Operation *op);
 
 /// Helper function to return native size for MMA.SYNC-based operations.
-Optional<SmallVector<int64_t>> getMmaNativeVectorSize(Operation *op);
+std::optional<SmallVector<int64_t>> getMmaNativeVectorSize(Operation *op);
 
 /// Return true if the given memref has workgroup memory space.
 bool hasSharedMemoryAddressSpace(MemRefType memrefType);
diff --git a/compiler/src/iree/compiler/Codegen/Utils/Utils.cpp b/compiler/src/iree/compiler/Codegen/Utils/Utils.cpp
index b5f5ab3..9caaa31 100644
--- a/compiler/src/iree/compiler/Codegen/Utils/Utils.cpp
+++ b/compiler/src/iree/compiler/Codegen/Utils/Utils.cpp
@@ -68,7 +68,7 @@
   return exportOps;
 }
 
-Optional<StringAttr> getConfigStringAttr(
+std::optional<StringAttr> getConfigStringAttr(
     IREE::HAL::ExecutableTargetAttr targetAttr, StringRef stringAttr) {
   if (!targetAttr) return std::nullopt;
   auto config = targetAttr.getConfiguration();
@@ -78,7 +78,7 @@
   return attr;
 }
 
-Optional<IntegerAttr> getConfigIntegerAttr(
+std::optional<IntegerAttr> getConfigIntegerAttr(
     IREE::HAL::ExecutableTargetAttr targetAttr, StringRef integerAttr) {
   if (!targetAttr) return std::nullopt;
   auto config = targetAttr.getConfiguration();
@@ -88,8 +88,8 @@
   return attr;
 }
 
-Optional<BoolAttr> getConfigBoolAttr(IREE::HAL::ExecutableTargetAttr targetAttr,
-                                     StringRef integerAttr) {
+std::optional<BoolAttr> getConfigBoolAttr(
+    IREE::HAL::ExecutableTargetAttr targetAttr, StringRef integerAttr) {
   if (!targetAttr) return std::nullopt;
   auto config = targetAttr.getConfiguration();
   if (!config) return std::nullopt;
@@ -98,7 +98,7 @@
   return attr;
 }
 
-Optional<llvm::Triple> getTargetTriple(
+std::optional<llvm::Triple> getTargetTriple(
     IREE::HAL::ExecutableTargetAttr targetAttr) {
   auto triple = getConfigStringAttr(targetAttr, "target_triple");
   if (!triple) return std::nullopt;
@@ -184,14 +184,14 @@
 /// Returns the dimension for any operation that implements processor op
 /// interfaces.
 template <typename T>
-static Optional<unsigned> getDimension(Operation *op) {
+static std::optional<unsigned> getDimension(Operation *op) {
   if (auto tOp = dyn_cast<T>(op)) {
     return tOp.getDimIndex();
   }
   return std::nullopt;
 }
 template <typename T1, typename T2, typename... T3>
-static Optional<unsigned> getDimension(Operation *op) {
+static std::optional<unsigned> getDimension(Operation *op) {
   if (!op) return std::nullopt;
   if (auto dimension = getDimension<T1>(op)) {
     return dimension;
@@ -205,8 +205,8 @@
 /// returns the dimension.  If `refDimension` is passed checks if the dimension
 /// matches the given value.
 template <typename... T>
-static Optional<unsigned> checkDimensions(
-    ArrayRef<Value> vals, Optional<unsigned> refDimension = std::nullopt) {
+static std::optional<unsigned> checkDimensions(
+    ArrayRef<Value> vals, std::optional<unsigned> refDimension = std::nullopt) {
   for (auto v : vals) {
     auto currDimension = getDimension<T...>(v.getDefiningOp());
     if (!currDimension) return std::nullopt;
@@ -268,7 +268,7 @@
 
   LogicalResult visitMulExpr(AffineBinaryOpExpr expr) {
     SmallVector<Value> vals;
-    Optional<unsigned> dimension;
+    std::optional<unsigned> dimension;
     // workgroupSizeOp may have been folded into a constant expression.
     if (auto wgSize = expr.getRHS().dyn_cast<AffineConstantExpr>()) {
       vals = getValuesForDimsOrSymbols(applyOp, {expr.getLHS()});
@@ -425,7 +425,7 @@
 }  // namespace
 
 template <typename OpTy>
-static Optional<unsigned> getInterfaceWorkgroupOpDim(Value value) {
+static std::optional<unsigned> getInterfaceWorkgroupOpDim(Value value) {
   if (auto op = value.getDefiningOp<OpTy>()) {
     return op.getDimension().getZExtValue();
   }
@@ -445,7 +445,7 @@
 ///     affine_map<(d0)[s0, s1] -> (d0 * s0 * s1)>(%step)[%id, %size]
 ///   scf.for %iv = %offset to %ub step %new_step { ... }
 /// ```
-Optional<LoopTilingAndDistributionInfo> isTiledAndDistributedLoop(
+std::optional<LoopTilingAndDistributionInfo> isTiledAndDistributedLoop(
     scf::ForOp forOp) {
   LoopTilingAndDistributionInfo loopInfo;
   loopInfo.loop = forOp;
@@ -457,13 +457,13 @@
   if (!lbApplyOp || !stepApplyOp) {
     // Try to see if this is a specical case where we have:
     //   scf.for %iv = %id to %ub step %count
-    Optional<unsigned> idDim;
+    std::optional<unsigned> idDim;
     if (auto ifx = dyn_cast_or_null<ProcessorIDInterface>(
             forOp.getLowerBound().getDefiningOp())) {
       idDim = ifx.getDimIndex();
     }
 
-    Optional<unsigned> countDim;
+    std::optional<unsigned> countDim;
     if (auto ifx = dyn_cast_or_null<ProcessorCountInterface>(
             forOp.getStep().getDefiningOp())) {
       countDim = ifx.getDimIndex();
diff --git a/compiler/src/iree/compiler/Codegen/Utils/Utils.h b/compiler/src/iree/compiler/Codegen/Utils/Utils.h
index 966926a..6e424f5 100644
--- a/compiler/src/iree/compiler/Codegen/Utils/Utils.h
+++ b/compiler/src/iree/compiler/Codegen/Utils/Utils.h
@@ -46,21 +46,21 @@
 
 /// Returns the StringAttr with the name `stringAttr` in the `targetAttr`, if
 /// found.
-Optional<StringAttr> getConfigStringAttr(
+std::optional<StringAttr> getConfigStringAttr(
     IREE::HAL::ExecutableTargetAttr targetAttr, StringRef stringAttr);
 
 /// Returns the IntegerAttr with the name `integerAttr` in the `targetAttr`, if
 /// found.
-Optional<IntegerAttr> getConfigIntegerAttr(
+std::optional<IntegerAttr> getConfigIntegerAttr(
     IREE::HAL::ExecutableTargetAttr targetAttr, StringRef integerAttr);
 
 /// Returns the BoolAttr with the name `integerAttr` in the `targetAttr`, if
 /// found.
-Optional<BoolAttr> getConfigBoolAttr(IREE::HAL::ExecutableTargetAttr targetAttr,
-                                     StringRef integerAttr);
+std::optional<BoolAttr> getConfigBoolAttr(
+    IREE::HAL::ExecutableTargetAttr targetAttr, StringRef integerAttr);
 
 /// Returns the LLVM Target triple associated with the `targetAttr`, if set.
-Optional<llvm::Triple> getTargetTriple(
+std::optional<llvm::Triple> getTargetTriple(
     IREE::HAL::ExecutableTargetAttr targetAttr);
 
 /// Methods to get target information.
@@ -112,7 +112,7 @@
   // The step for the original untiled loop.
   OpFoldResult untiledStep;
   // The tile size used to tile (and not distribute) the original untiled loop.
-  Optional<int64_t> tileSize;
+  std::optional<int64_t> tileSize;
   // The processor dimension this loop is distributed to.
   unsigned processorDistributionDim;
 };
@@ -139,7 +139,7 @@
 
 /// If the given `forOp` is a tiled and distributed loop, returns its tiling and
 /// distribution information.
-Optional<LoopTilingAndDistributionInfo> isTiledAndDistributedLoop(
+std::optional<LoopTilingAndDistributionInfo> isTiledAndDistributedLoop(
     scf::ForOp forOp);
 
 /// Collects information about loops matching tiled+distribute pattern.
diff --git a/compiler/src/iree/compiler/Codegen/VMVX/LowerLinalgMicrokernels.cpp b/compiler/src/iree/compiler/Codegen/VMVX/LowerLinalgMicrokernels.cpp
index 41068d6..74ce972 100644
--- a/compiler/src/iree/compiler/Codegen/VMVX/LowerLinalgMicrokernels.cpp
+++ b/compiler/src/iree/compiler/Codegen/VMVX/LowerLinalgMicrokernels.cpp
@@ -210,7 +210,7 @@
 
  private:
   Value buffer;
-  Optional<StridedBufferDescriptor> desc;
+  std::optional<StridedBufferDescriptor> desc;
 };
 
 /// Emits a vmvx binary op.
@@ -558,7 +558,8 @@
     // Returns an emitter for a generic binary compatible operation where
     // |binaryOp| has a 1:1 correspondance with |opcode|.
     auto configureGenericBinary =
-        [&](Operation *binaryOp, StringRef opcode) -> Optional<BinaryEmitter> {
+        [&](Operation *binaryOp,
+            StringRef opcode) -> std::optional<BinaryEmitter> {
       SmallVector<BinaryEmitter::Descriptor, 2> operands;
       // Make sure that the binary op has operands that map to the
       // ins and detect the order.
@@ -594,87 +595,87 @@
     // Emit from the iree_ukernel_x32b_opcode_t table.
     Type resultType = binaryOp->getResult(0).getType();
     if (!resultType.isIntOrFloat()) return failure();
-    Optional<BinaryEmitter> emitter =
-        TypeSwitch<Operation *, Optional<BinaryEmitter>>(binaryOp)
-            .Case([&](arith::AddFOp op) -> Optional<BinaryEmitter> {
+    std::optional<BinaryEmitter> emitter =
+        TypeSwitch<Operation *, std::optional<BinaryEmitter>>(binaryOp)
+            .Case([&](arith::AddFOp op) -> std::optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "add");
               }
               return std::nullopt;
             })
-            .Case([&](arith::AddIOp op) -> Optional<BinaryEmitter> {
+            .Case([&](arith::AddIOp op) -> std::optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "add");
               }
               return std::nullopt;
             })
-            .Case([&](arith::AndIOp op) -> Optional<BinaryEmitter> {
+            .Case([&](arith::AndIOp op) -> std::optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "and");
               }
               return std::nullopt;
             })
-            .Case([&](arith::DivFOp op) -> Optional<BinaryEmitter> {
+            .Case([&](arith::DivFOp op) -> std::optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "div");
               }
               return std::nullopt;
             })
-            .Case([&](arith::DivSIOp op) -> Optional<BinaryEmitter> {
+            .Case([&](arith::DivSIOp op) -> std::optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "divs");
               }
               return std::nullopt;
             })
-            .Case([&](arith::DivUIOp op) -> Optional<BinaryEmitter> {
+            .Case([&](arith::DivUIOp op) -> std::optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "divu");
               }
               return std::nullopt;
             })
-            .Case([&](arith::MulFOp op) -> Optional<BinaryEmitter> {
+            .Case([&](arith::MulFOp op) -> std::optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "mul");
               }
               return std::nullopt;
             })
-            .Case([&](arith::MulIOp op) -> Optional<BinaryEmitter> {
+            .Case([&](arith::MulIOp op) -> std::optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "mul");
               }
               return std::nullopt;
             })
-            .Case([&](arith::OrIOp op) -> Optional<BinaryEmitter> {
+            .Case([&](arith::OrIOp op) -> std::optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "or");
               }
               return std::nullopt;
             })
-            .Case([&](arith::ShLIOp op) -> Optional<BinaryEmitter> {
+            .Case([&](arith::ShLIOp op) -> std::optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "shl");
               }
               return std::nullopt;
             })
-            .Case([&](arith::ShRSIOp op) -> Optional<BinaryEmitter> {
+            .Case([&](arith::ShRSIOp op) -> std::optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "shrs");
               }
               return std::nullopt;
             })
-            .Case([&](arith::XOrIOp op) -> Optional<BinaryEmitter> {
+            .Case([&](arith::XOrIOp op) -> std::optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "xor");
               }
               return std::nullopt;
             })
-            .Case([&](arith::SubFOp op) -> Optional<BinaryEmitter> {
+            .Case([&](arith::SubFOp op) -> std::optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "sub");
               }
               return std::nullopt;
             })
-            .Case([&](arith::SubIOp op) -> Optional<BinaryEmitter> {
+            .Case([&](arith::SubIOp op) -> std::optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "sub");
               }
@@ -729,7 +730,8 @@
     // Returns an emitter for a generic binary compatible operation where
     // |binaryOp| has a 1:1 correspondance with |opcode|.
     auto configureGenericUnary =
-        [&](Operation *unaryOp, StringRef opcode) -> Optional<UnaryEmitter> {
+        [&](Operation *unaryOp,
+            StringRef opcode) -> std::optional<UnaryEmitter> {
       SmallVector<UnaryEmitter::Descriptor, 2> operands;
       // Make sure that the binary op has operands that map to the
       // ins and detect the order.
@@ -746,51 +748,52 @@
     // Emit from the iree_ukernel_x32b_opcode_t table.
     Type resultType = unaryOp->getResult(0).getType();
     if (!resultType.isIntOrFloat()) return failure();
-    Optional<UnaryEmitter> emitter =
-        TypeSwitch<Operation *, Optional<UnaryEmitter>>(unaryOp)
-            .Case([&](math::AbsFOp op) -> Optional<UnaryEmitter> {
+    std::optional<UnaryEmitter> emitter =
+        TypeSwitch<Operation *, std::optional<UnaryEmitter>>(unaryOp)
+            .Case([&](math::AbsFOp op) -> std::optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "abs");
               }
               return std::nullopt;
             })
-            .Case([&](math::CeilOp op) -> Optional<UnaryEmitter> {
+            .Case([&](math::CeilOp op) -> std::optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "ceil");
               }
               return std::nullopt;
             })
-            .Case([&](math::CountLeadingZerosOp op) -> Optional<UnaryEmitter> {
+            .Case([&](math::CountLeadingZerosOp op)
+                      -> std::optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "ctlz");
               }
               return std::nullopt;
             })
-            .Case([&](math::ExpOp op) -> Optional<UnaryEmitter> {
+            .Case([&](math::ExpOp op) -> std::optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "exp");
               }
               return std::nullopt;
             })
-            .Case([&](math::FloorOp op) -> Optional<UnaryEmitter> {
+            .Case([&](math::FloorOp op) -> std::optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "floor");
               }
               return std::nullopt;
             })
-            .Case([&](math::LogOp op) -> Optional<UnaryEmitter> {
+            .Case([&](math::LogOp op) -> std::optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "log");
               }
               return std::nullopt;
             })
-            .Case([&](arith::NegFOp op) -> Optional<UnaryEmitter> {
+            .Case([&](arith::NegFOp op) -> std::optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "neg");
               }
               return std::nullopt;
             })
-            .Case([&](math::RsqrtOp op) -> Optional<UnaryEmitter> {
+            .Case([&](math::RsqrtOp op) -> std::optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "rsqrt");
               }
diff --git a/compiler/src/iree/compiler/Codegen/VMVX/VMVXMaterializeEncodingPass.cpp b/compiler/src/iree/compiler/Codegen/VMVX/VMVXMaterializeEncodingPass.cpp
index 2c25454..09ed574 100644
--- a/compiler/src/iree/compiler/Codegen/VMVX/VMVXMaterializeEncodingPass.cpp
+++ b/compiler/src/iree/compiler/Codegen/VMVX/VMVXMaterializeEncodingPass.cpp
@@ -72,7 +72,7 @@
   MaterializeEncodingTypeConverter typeConverter(
       [targetAttr](
           RankedTensorType tensorType) -> FailureOr<MaterializeEncodingInfo> {
-        Optional<TensorEncoding> encoding = getEncoding(tensorType);
+        std::optional<TensorEncoding> encoding = getEncoding(tensorType);
         if (!encoding) return failure();
 
         auto matmulType = getMatmulType(*encoding);
diff --git a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOpFolders.cpp b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOpFolders.cpp
index 1abd377..4b84a99 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOpFolders.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOpFolders.cpp
@@ -332,7 +332,7 @@
   llvm::SmallBitVector droppedDims = op.getDroppedDims();
   for (auto size : llvm::enumerate(mixedSizes)) {
     if (droppedDims.test(size.index())) continue;
-    Optional<int64_t> staticSize = getConstantIntValue(size.value());
+    std::optional<int64_t> staticSize = getConstantIntValue(size.value());
     newShape.push_back(staticSize ? staticSize.value() : ShapedType::kDynamic);
   }
 
diff --git a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.cpp b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.cpp
index cc288ce..a7238e0 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.cpp
@@ -114,7 +114,7 @@
   }
   unsigned shapePos = 0;
   for (const auto &size : llvm::enumerate(mixedSizes)) {
-    Optional<int64_t> sizeVal = getConstantIntValue(size.value());
+    std::optional<int64_t> sizeVal = getConstantIntValue(size.value());
     // If the size is not 1, or if the current matched dimension of the result
     // is the same static shape as the size value (which is 1), then the
     // dimension is preserved.
@@ -129,7 +129,7 @@
 }
 
 /// Returns the `hal.interface.binding` a value comes from.
-static Optional<BlockArgument> getBindingArgument(Value v) {
+static std::optional<BlockArgument> getBindingArgument(Value v) {
   if (BlockArgument blockArg = v.dyn_cast<BlockArgument>()) {
     if (isa<IREE::Flow::DispatchWorkgroupsOp>(
             blockArg.getOwner()->getParentOp())) {
@@ -665,7 +665,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getSource());
 }
 
-::llvm::Optional<unsigned> DispatchTensorLoadOp::getTiedResultOperandIndex(
+::std::optional<unsigned> DispatchTensorLoadOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // source
 }
@@ -923,7 +923,7 @@
 }
 
 BlockArgument DispatchWorkgroupsOp::getOutputBlockArgument(unsigned idx) {
-  Optional<ArrayAttr> tiedOperands = getTiedOperands();
+  std::optional<ArrayAttr> tiedOperands = getTiedOperands();
   if (!tiedOperands.has_value() || tiedOperands->empty()) {
     unsigned numInputs = getArguments().size();
     return getWorkgroupBody().getArguments().drop_front(numInputs)[idx];
@@ -1411,7 +1411,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getSource());
 }
 
-::llvm::Optional<unsigned> TensorReshapeOp::getTiedResultOperandIndex(
+::std::optional<unsigned> TensorReshapeOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // source
 }
@@ -1449,7 +1449,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getTarget());
 }
 
-::llvm::Optional<unsigned> TensorUpdateOp::getTiedResultOperandIndex(
+::std::optional<unsigned> TensorUpdateOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // target
 }
@@ -1511,9 +1511,9 @@
 
     // Check that the `dest` of the `tensor.insert_slice` and target of the
     // `flow.dispatch.tensor.store` are the same interface binding.
-    Optional<BlockArgument> destBinding =
+    std::optional<BlockArgument> destBinding =
         getBindingArgument(insertSliceOp.getDest());
-    Optional<BlockArgument> targetBinding =
+    std::optional<BlockArgument> targetBinding =
         getBindingArgument(dispatchTensorStoreOp.getTarget());
     if (!destBinding || !targetBinding ||
         destBinding.value() != targetBinding.value()) {
@@ -1585,7 +1585,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getTarget());
 }
 
-::llvm::Optional<unsigned> CollectiveAllGatherOp::getTiedResultOperandIndex(
+::std::optional<unsigned> CollectiveAllGatherOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // target
 }
@@ -1612,7 +1612,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getTarget());
 }
 
-::llvm::Optional<unsigned> CollectiveAllReduceOp::getTiedResultOperandIndex(
+::std::optional<unsigned> CollectiveAllReduceOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // target
 }
@@ -1640,7 +1640,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getTarget());
 }
 
-::llvm::Optional<unsigned> CollectiveReduceScatterOp::getTiedResultOperandIndex(
+::std::optional<unsigned> CollectiveReduceScatterOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // target
 }
diff --git a/compiler/src/iree/compiler/Dialect/Flow/TransformExtensions/FlowExtensions.cpp b/compiler/src/iree/compiler/Dialect/Flow/TransformExtensions/FlowExtensions.cpp
index 456bac3..269af06 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/TransformExtensions/FlowExtensions.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/TransformExtensions/FlowExtensions.cpp
@@ -826,7 +826,7 @@
     Operation *target, transform::ApplyToEachResultList &results,
     transform::TransformState &state) {
   IRRewriter rewriter(target->getContext());
-  Optional<Flow::WorkloadBuilder> workloadBuilder = std::nullopt;
+  std::optional<Flow::WorkloadBuilder> workloadBuilder = std::nullopt;
   if (getGenerateWorkload()) {
     auto maybeBuilder = Flow::getWorkloadBuilder(rewriter, target);
     if (failed(maybeBuilder)) {
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertRegionToWorkgroups.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertRegionToWorkgroups.cpp
index f7d1db7..f4b58b3 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertRegionToWorkgroups.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertRegionToWorkgroups.cpp
@@ -47,7 +47,7 @@
 
 /// Follow the reverse SSA use-def chain of the given value (always taking the
 /// tied operand) and return the first value outside of `regionOp`.
-static Optional<Value> findFirstTiedValueOutsideOfRegionOp(
+static std::optional<Value> findFirstTiedValueOutsideOfRegionOp(
     Flow::DispatchRegionOp regionOp, Value value) {
   // Check if `v` is defined outside of `regionOp`.
   auto isOutside = [&](Value v) {
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/DumpDispatchGraph.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/DumpDispatchGraph.cpp
index 410f3fa..b55747d 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/DumpDispatchGraph.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/DumpDispatchGraph.cpp
@@ -53,7 +53,8 @@
 /// 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;
 }
@@ -118,11 +119,11 @@
 /// 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.
@@ -485,7 +486,7 @@
         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/compiler/src/iree/compiler/Dialect/Flow/Transforms/FormDispatchRegions.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/FormDispatchRegions.cpp
index d667bf7..01a8691 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/FormDispatchRegions.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/FormDispatchRegions.cpp
@@ -78,7 +78,7 @@
                              const SmallVector<tensor::DimOp> &dimOps) {
   for (tensor::DimOp dimOp : dimOps) {
     // Only DimOps with static indices are supported.
-    Optional<int64_t> idx = dimOp.getConstantIndex();
+    std::optional<int64_t> idx = dimOp.getConstantIndex();
     if (!idx.has_value()) continue;
     // Only DimOps with ranked tensors are supported.
     auto tensorType = dimOp.getSource().getType().dyn_cast<RankedTensorType>();
@@ -331,9 +331,8 @@
 }
 
 /// For all uses of an operation, finds the use that dominates all other uses.
-static Optional<OpOperand *> getFusableUse(Operation *op,
-                                           DominanceInfo const &dominanceInfo,
-                                           bool fuseMultiUse) {
+static std::optional<OpOperand *> getFusableUse(
+    Operation *op, DominanceInfo const &dominanceInfo, bool fuseMultiUse) {
   if (!fuseMultiUse && !op->hasOneUse()) return std::nullopt;
 
   for (auto &use : op->getUses()) {
@@ -496,7 +495,7 @@
         appendToFusionGroup(currRoot, rootNumber);
       };
 
-      Optional<OpOperand *> fusableUse =
+      std::optional<OpOperand *> fusableUse =
           getFusableUse(currRoot, dominanceInfo, /*fuseMultiUse=*/fuseMultiUse);
       if (!fusableUse) continue;
 
@@ -567,7 +566,7 @@
         continue;
       }
 
-      Optional<OpOperand *> fusableUse =
+      std::optional<OpOperand *> fusableUse =
           getFusableUse(producer, dominanceInfo, /*fuseMultiUse=*/fuseMultiUse);
       if (!fusableUse || fusableUse.value()->getOwner() != candidate) continue;
 
@@ -720,11 +719,11 @@
   // Step 2. Create a DispatchRegionOp for every fusion group.
   OpBuilder::InsertionGuard g(rewriter);
   SmallVector<Flow::DispatchRegionOp> regionOps;
-  DenseMap<Flow::DispatchRegionOp, Optional<Flow::WorkloadBuilder>>
+  DenseMap<Flow::DispatchRegionOp, std::optional<Flow::WorkloadBuilder>>
       workloadBuilders;
   for (const auto &it : llvm::enumerate(roots)) {
     // Compute workload.
-    Optional<Flow::WorkloadBuilder> workloadBuilder = std::nullopt;
+    std::optional<Flow::WorkloadBuilder> workloadBuilder = std::nullopt;
     if (generateWorkloadRegion) {
       auto maybeBuilder = iree_compiler::IREE::Flow::getWorkloadBuilder(
           rewriter, /*rootOp=*/it.value());
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/FormDispatchWorkgroups.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/FormDispatchWorkgroups.cpp
index 53f37bf..a955a90 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/FormDispatchWorkgroups.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/FormDispatchWorkgroups.cpp
@@ -75,7 +75,7 @@
     mlir::TensorDimTrackingRewriter &rewriter, Operation *op,
     bool generateWorkloadRegion) {
   // Compute workload.
-  Optional<Flow::WorkloadBuilder> workloadBuilder = std::nullopt;
+  std::optional<Flow::WorkloadBuilder> workloadBuilder = std::nullopt;
   if (generateWorkloadRegion) {
     auto maybeBuilder =
         iree_compiler::IREE::Flow::getWorkloadBuilder(rewriter, op);
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/FusionOfTensorOps.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/FusionOfTensorOps.cpp
index 234fb59..ac9d545 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/FusionOfTensorOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/FusionOfTensorOps.cpp
@@ -32,8 +32,8 @@
 namespace Flow {
 
 /// Check if any of the use dominates all other uses of the operation.
-static Optional<OpOperand *> getFusableUse(Operation *op,
-                                           DominanceInfo &dominanceInfo) {
+static std::optional<OpOperand *> getFusableUse(Operation *op,
+                                                DominanceInfo &dominanceInfo) {
   auto uses = op->getUses();
   for (OpOperand &source : uses) {
     Operation *sourceOp = source.getOwner();
@@ -167,7 +167,8 @@
       return;
     }
 
-    Optional<OpOperand *> fusableUse = getFusableUse(genericOp, dominanceInfo);
+    std::optional<OpOperand *> fusableUse =
+        getFusableUse(genericOp, dominanceInfo);
     if (!fusableUse) return;
     if (!linalg::areElementwiseOpsFusable(fusableUse.value())) return;
 
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/InferNumericNarrowing.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/InferNumericNarrowing.cpp
index 78be1e1..04138a0 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/InferNumericNarrowing.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/InferNumericNarrowing.cpp
@@ -119,7 +119,7 @@
     // Insert the annotation.
     OpBuilder builder(context);
     builder.setInsertionPointAfterValue(probePoint);
-    Optional<std::pair<int64_t, int64_t>> range;
+    std::optional<std::pair<int64_t, int64_t>> range;
     // i0 values cannot parse any values so omit.
     if (type.getWidth() != 0) {
       range = std::make_pair(minValue, maxValue);
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/InterchangeTransposeGenericOps.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/InterchangeTransposeGenericOps.cpp
index 90046bf..1fecd19 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/InterchangeTransposeGenericOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/InterchangeTransposeGenericOps.cpp
@@ -37,7 +37,7 @@
       return rewriter.notifyMatchFailure(genericOp, "not elementwise");
     }
 
-    Optional<AffineMap> mapForInterchange;
+    std::optional<AffineMap> mapForInterchange;
 
     for (auto operand : genericOp.getDpsInputOperands()) {
       auto producer = operand->get().getDefiningOp<linalg::LinalgOp>();
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/OptimizeNumerics.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/OptimizeNumerics.cpp
index f8c4fe1..93813ba 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/OptimizeNumerics.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/OptimizeNumerics.cpp
@@ -70,7 +70,7 @@
 }
 
 struct NarrowParams {
-  static Optional<NarrowParams> forValue(Value value) {
+  static std::optional<NarrowParams> forValue(Value value) {
     if (auto narrowOp =
             llvm::dyn_cast_or_null<IREE::Util::NumericOptionalNarrowOp>(
                 value.getDefiningOp())) {
@@ -96,7 +96,7 @@
   Value producer;
   Type fromType;
   Type toElementType;
-  Optional<std::pair<int64_t, int64_t>> range;
+  std::optional<std::pair<int64_t, int64_t>> range;
 };
 
 // Eliminates a cast produced by an empty by just initializing to that
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.cpp
index c56348c..5ee77af 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.cpp
@@ -212,7 +212,7 @@
 }
 
 Flow::DispatchRegionOp Flow::makeDispatchRegionWithWorkload(
-    OpBuilder &builder, Location loc, Optional<ValueRange> workload) {
+    OpBuilder &builder, Location loc, std::optional<ValueRange> workload) {
   OpBuilder::InsertionGuard guard(builder);
 
   // Create RegionOp.
@@ -318,8 +318,8 @@
 
 FailureOr<Flow::DispatchRegionOp> Flow::wrapOpInDispatchRegion(
     RewriterBase &rewriter, Operation *op,
-    Optional<Flow::WorkloadBuilder> workloadBuilder) {
-  Optional<ValueRange> workload = std::nullopt;
+    std::optional<Flow::WorkloadBuilder> workloadBuilder) {
+  std::optional<ValueRange> workload = std::nullopt;
   if (workloadBuilder.has_value()) workload = workloadBuilder->workload;
   // Make an empty dispatch region right before the op.
   rewriter.setInsertionPointAfter(op);
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.h b/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.h
index 1758724..cc31325 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.h
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.h
@@ -39,7 +39,7 @@
 /// Create an DispatchRegionOp with workload
 Flow::DispatchRegionOp makeDispatchRegionWithWorkload(
     OpBuilder &builder, Location loc,
-    Optional<ValueRange> workload = std::nullopt);
+    std::optional<ValueRange> workload = std::nullopt);
 
 /// Clone a `target` op that is preceding the given dispatch region op into the
 /// dispatch region.
@@ -81,7 +81,7 @@
 /// Wrap the given op in a new dispatch region op.
 FailureOr<Flow::DispatchRegionOp> wrapOpInDispatchRegion(
     RewriterBase &rewriter, Operation *op,
-    Optional<Flow::WorkloadBuilder> workloadBuilder = std::nullopt);
+    std::optional<Flow::WorkloadBuilder> workloadBuilder = std::nullopt);
 
 /// Decide whether the given op should be cloned and fused into a dispatch
 /// region using heuristics.
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/SetEncoding.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/SetEncoding.cpp
index c365963..f4f12e8 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/SetEncoding.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/SetEncoding.cpp
@@ -63,9 +63,9 @@
 
 /// Pads `value` to `padding` if needed. If no padding is specified,
 /// return `value` itself.
-static FailureOr<Value> padIfNeeded(OpBuilder &builder, Location loc,
-                                    Value value,
-                                    Optional<int64_t> padding = std::nullopt) {
+static FailureOr<Value> padIfNeeded(
+    OpBuilder &builder, Location loc, Value value,
+    std::optional<int64_t> padding = std::nullopt) {
   if (!padding) return value;
 
   OpFoldResult paddingOfr = builder.getIndexAttr(padding.value());
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertCommandBufferOps.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertCommandBufferOps.cpp
index b68e096..52f2037 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertCommandBufferOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertCommandBufferOps.cpp
@@ -16,9 +16,9 @@
 namespace {
 
 // TODO(benvanik): import op handling of optional values.
-// It'd be nice if the Optional<Index>:$binding_capacity could be emitted as 0
-// when not present; today it'll be omitted entirely (as it's not in the operand
-// set) but we need it for the fixed call signature.
+// It'd be nice if the std::optional<Index>:$binding_capacity could be emitted
+// as 0 when not present; today it'll be omitted entirely (as it's not in the
+// operand set) but we need it for the fixed call signature.
 class CommandBufferCreateOpConversion
     : public OpConversionPattern<IREE::HAL::CommandBufferCreateOp> {
  public:
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StandardToHAL/ConvertShapeOps.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StandardToHAL/ConvertShapeOps.cpp
index c8462f6..ca0a437 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StandardToHAL/ConvertShapeOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StandardToHAL/ConvertShapeOps.cpp
@@ -25,7 +25,7 @@
     if (!adaptor.getSource().getType().isa<IREE::HAL::BufferViewType>()) {
       return failure();
     }
-    Optional<int64_t> index = dimOp.getConstantIndex();
+    std::optional<int64_t> index = dimOp.getConstantIndex();
     assert(index.has_value() && "expect constant index in `std.dim` operation");
     rewriter.replaceOpWithNewOp<IREE::HAL::BufferViewDimOp>(
         dimOp, dimOp.getResult().getType(), adaptor.getSource(),
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/Patterns.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/Patterns.cpp
index 6b8c26c..08573d2 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/Patterns.cpp
@@ -746,8 +746,9 @@
 // NOTE: this relies on the enums being the same today. Ew.
 static IREE::HAL::CollectiveAttr convertCollectiveAttr(
     IREE::Stream::CollectiveAttr sourceAttr) {
-  auto convertReductionOp = [](Optional<IREE::Stream::CollectiveReductionOp> op)
-      -> Optional<IREE::HAL::CollectiveReductionOp> {
+  auto convertReductionOp =
+      [](std::optional<IREE::Stream::CollectiveReductionOp> op)
+      -> std::optional<IREE::HAL::CollectiveReductionOp> {
     if (!op.has_value()) return std::nullopt;
     return static_cast<IREE::HAL::CollectiveReductionOp>(op.value());
   };
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/TypeConverter.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/TypeConverter.cpp
index 393d7d4..47d01a1 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/TypeConverter.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/TypeConverter.cpp
@@ -30,7 +30,7 @@
   // Tensors become buffers by default.
   // Shapes and types are carried independently or folded away entirely - all
   // we need at the HAL level is a blob of bytes.
-  addConversion([=](TensorType type) -> Optional<Type> {
+  addConversion([=](TensorType type) -> std::optional<Type> {
     // HAL only should be concerned with numeric values.
     if (HALTypeConverter::shouldConvertToBufferView(type)) {
       return IREE::HAL::BufferViewType::get(type.getContext());
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALBase.td b/compiler/src/iree/compiler/Dialect/HAL/IR/HALBase.td
index 50d70fa..d8b7de1 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALBase.td
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALBase.td
@@ -522,7 +522,7 @@
   }];
   let parameters = (ins
     AttrParameter<"CollectiveKind", "">:$kind,
-    OptionalParameter<"mlir::Optional<CollectiveReductionOp>">:$reduction,
+    OptionalParameter<"std::optional<CollectiveReductionOp>">:$reduction,
     AttrParameter<"CollectiveElementType", "">:$element_type
   );
   let assemblyFormat = [{
@@ -544,7 +544,7 @@
   let parameters = (ins
     AttrParameter<"int64_t", "">:$ordinal,
     AttrParameter<"DescriptorType", "">:$type,
-    OptionalParameter<"mlir::Optional<DescriptorFlags>">:$flags
+    OptionalParameter<"std::optional<DescriptorFlags>">:$flags
   );
   let assemblyFormat = [{
     `<` $ordinal `,` $type (`,` $flags^)? `>`
@@ -799,7 +799,7 @@
 
     // Returns the contents of the object file or None if loading failed.
     // TODO(benvanik): better return type to support mapping/etc? eh
-    Optional<std::string> loadData();
+    std::optional<std::string> loadData();
   }];
 }
 
@@ -845,7 +845,7 @@
 
   let extraClassDeclaration = [{
     // Returns the objects specified for the given generic target.
-    Optional<ArrayAttr> getApplicableObjects(
+    std::optional<ArrayAttr> getApplicableObjects(
         IREE::HAL::ExecutableTargetAttr specificTargetAttr);
   }];
 }
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOpFolders.cpp b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOpFolders.cpp
index 1ef201e..3c1dca0 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOpFolders.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOpFolders.cpp
@@ -773,7 +773,7 @@
 
 // Produces a deduplicated and null-elided operand list.
 // Returns std::nullopt if nothing changed.
-static Optional<std::vector<Value>> deduplicateFenceOperands(
+static std::optional<std::vector<Value>> deduplicateFenceOperands(
     ValueRange operands) {
   SetVector<Value> newOperands;
   for (auto operand : operands) {
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp
index 75a3e4a..eb8dd55 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp
@@ -39,7 +39,8 @@
                                        DescriptorTypeAttr &dtAttr) {
   StringRef enumKeyword;
   if (failed(parser.parseKeyword(&enumKeyword))) return failure();
-  Optional<DescriptorType> maybeEnum = symbolizeDescriptorType(enumKeyword);
+  std::optional<DescriptorType> maybeEnum =
+      symbolizeDescriptorType(enumKeyword);
   if (!maybeEnum) return failure();
   dtAttr = DescriptorTypeAttr::get(parser.getContext(), *maybeEnum);
   return success();
@@ -186,7 +187,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getSource());
 }
 
-::llvm::Optional<unsigned> TensorImportOp::getTiedResultOperandIndex(
+::std::optional<unsigned> TensorImportOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // source
 }
@@ -263,7 +264,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getSource());
 }
 
-::llvm::Optional<unsigned> TensorExportOp::getTiedResultOperandIndex(
+::std::optional<unsigned> TensorExportOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // source
 }
@@ -299,7 +300,7 @@
       getSources()[resultIndex]);
 }
 
-::llvm::Optional<unsigned> TensorBarrierOp::getTiedResultOperandIndex(
+::std::optional<unsigned> TensorBarrierOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {resultIndex};  // sources[i]
 }
@@ -1065,7 +1066,7 @@
     OpBuilder &builder, OperationState &result, Type resultType, APInt set,
     APInt binding, IREE::HAL::DescriptorType descriptor_type, Value byte_offset,
     ValueRange dynamic_dims, IntegerAttr alignment,
-    Optional<DescriptorFlags> flags) {
+    std::optional<DescriptorFlags> flags) {
   IREE::HAL::DescriptorFlagsAttr descriptorAttr;
   if (flags.has_value()) {
     descriptorAttr = IREE::HAL::DescriptorFlagsAttr::get(builder.getContext(),
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.td b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.td
index c2880a6..3753e06 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.td
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.td
@@ -2373,7 +2373,7 @@
       "Value":$byte_offset,
       "ValueRange":$dynamic_dims,
       "IntegerAttr":$alignment,
-      CArg<"mlir::Optional<DescriptorFlags>", "llvm::None">:$flags
+      CArg<"std::optional<DescriptorFlags>", "llvm::None">:$flags
     )>,
   ];
 
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.cpp b/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.cpp
index 0da7907..2f8acd7 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.cpp
@@ -95,7 +95,7 @@
 }
 }  // namespace
 
-llvm::Optional<int32_t> getElementTypeValue(Type type) {
+std::optional<int32_t> getElementTypeValue(Type type) {
   if (auto intType = type.dyn_cast_or_null<IntegerType>()) {
     NumericalType numericalType;
     if (intType.isInteger(1)) {
@@ -134,7 +134,7 @@
   return std::nullopt;
 }
 
-llvm::Optional<int32_t> getEncodingTypeValue(Attribute attr) {
+std::optional<int32_t> getEncodingTypeValue(Attribute attr) {
   // TODO(#6762): encoding attribute handling/mapping to enums.
   assert(!attr && "encoding types other than default not yet supported");
   // Default to IREE_HAL_ENCODING_TYPE_DENSE_ROW_MAJOR for now.
@@ -528,7 +528,7 @@
   return findFileInPaths(pathAttr.getValue(), clExecutableObjectSearchPath);
 }
 
-Optional<std::string> ExecutableObjectAttr::loadData() {
+std::optional<std::string> ExecutableObjectAttr::loadData() {
   if (auto dataAttr = getData()) {
     // This is shady but so is using this feature.
     // TODO(benvanik): figure out a way to limit the attribute to signless int8.
@@ -617,7 +617,7 @@
   os << "}>";
 }
 
-Optional<ArrayAttr> ExecutableObjectsAttr::getApplicableObjects(
+std::optional<ArrayAttr> ExecutableObjectsAttr::getApplicableObjects(
     IREE::HAL::ExecutableTargetAttr specificTargetAttr) {
   SmallVector<Attribute> allObjectAttrs;
   for (auto [targetAttr, objectsAttr] :
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.h b/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.h
index e584f36..d3b0b12 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.h
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.h
@@ -45,11 +45,11 @@
 
 // Returns a stable identifier for the MLIR element type or nullopt if the
 // type is unsupported in the ABI.
-llvm::Optional<int32_t> getElementTypeValue(Type type);
+std::optional<int32_t> getElementTypeValue(Type type);
 
 // Returns a stable identifier for the MLIR encoding type or 0 (opaque) if the
 // type is unsupported in the ABI.
-llvm::Optional<int32_t> getEncodingTypeValue(Attribute attr);
+std::optional<int32_t> getEncodingTypeValue(Attribute attr);
 
 template <typename T>
 inline bool allEnumBitsSet(T value, T required) {
@@ -164,7 +164,7 @@
 
 template <>
 struct FieldParser<
-    mlir::Optional<mlir::iree_compiler::IREE::HAL::CollectiveReductionOp>> {
+    std::optional<mlir::iree_compiler::IREE::HAL::CollectiveReductionOp>> {
   static FailureOr<mlir::iree_compiler::IREE::HAL::CollectiveReductionOp> parse(
       AsmParser &parser) {
     std::string value;
@@ -177,7 +177,7 @@
 };
 static inline AsmPrinter &operator<<(
     AsmPrinter &printer,
-    mlir::Optional<mlir::iree_compiler::IREE::HAL::CollectiveReductionOp>
+    std::optional<mlir::iree_compiler::IREE::HAL::CollectiveReductionOp>
         param) {
   printer << (param.has_value()
                   ? mlir::iree_compiler::IREE::HAL::stringifyEnum(param.value())
@@ -187,7 +187,7 @@
 
 template <>
 struct FieldParser<
-    mlir::Optional<mlir::iree_compiler::IREE::HAL::DescriptorFlags>> {
+    std::optional<mlir::iree_compiler::IREE::HAL::DescriptorFlags>> {
   static FailureOr<mlir::iree_compiler::IREE::HAL::DescriptorFlags> parse(
       AsmParser &parser) {
     std::string value;
@@ -200,7 +200,7 @@
 };
 static inline AsmPrinter &operator<<(
     AsmPrinter &printer,
-    mlir::Optional<mlir::iree_compiler::IREE::HAL::DescriptorFlags> param) {
+    std::optional<mlir::iree_compiler::IREE::HAL::DescriptorFlags> param) {
   printer << (param.has_value()
                   ? mlir::iree_compiler::IREE::HAL::stringifyEnum(param.value())
                   : StringRef{""});
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/CUDA/CUDATarget.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/CUDA/CUDATarget.cpp
index bec1494..0fcda13 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/CUDA/CUDATarget.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/CUDA/CUDATarget.cpp
@@ -228,7 +228,8 @@
     SmallVector<uint32_t> workgroupLocalMemories;
     for (auto exportOp : variantOp.getOps<IREE::HAL::ExecutableExportOp>()) {
       std::array<int32_t, 3> workgroupSize;
-      if (Optional<ArrayAttr> workgroupSizeAttr = exportOp.getWorkgroupSize()) {
+      if (std::optional<ArrayAttr> workgroupSizeAttr =
+              exportOp.getWorkgroupSize()) {
         for (auto it : llvm::enumerate(workgroupSizeAttr.value())) {
           workgroupSize[it.index()] = it.value().cast<IntegerAttr>().getInt();
         }
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/LinkerTool.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/LinkerTool.cpp
index 975f00b..230a542 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/LinkerTool.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/LinkerTool.cpp
@@ -62,7 +62,7 @@
   if (outputFile) outputFile->keep();
 }
 
-Optional<std::vector<int8_t>> Artifact::read() const {
+std::optional<std::vector<int8_t>> Artifact::read() const {
   auto fileData = llvm::MemoryBuffer::getFile(path);
   if (!fileData) {
     llvm::errs() << "failed to load library output file '" << path << "'";
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/LinkerTool.h b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/LinkerTool.h
index 52e1894..5ab2766 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/LinkerTool.h
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/LinkerTool.h
@@ -49,7 +49,7 @@
   void keep() const;
 
   // Reads the artifact file contents as bytes.
-  Optional<std::vector<int8_t>> read() const;
+  std::optional<std::vector<int8_t>> read() const;
 
   // Reads the artifact file and writes it into the given |stream|.
   bool readInto(raw_ostream &targetStream) const;
@@ -105,7 +105,7 @@
   // Links the given object files into a dynamically loadable library.
   // The resulting library (and other associated artifacts) will be returned on
   // success.
-  virtual Optional<Artifacts> linkDynamicLibrary(
+  virtual std::optional<Artifacts> linkDynamicLibrary(
       StringRef libraryName, ArrayRef<Artifact> objectFiles) = 0;
 
  protected:
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/AndroidLinkerTool.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/AndroidLinkerTool.cpp
index b182552..328a0dc 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/AndroidLinkerTool.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/AndroidLinkerTool.cpp
@@ -133,7 +133,7 @@
         .str();
   }
 
-  Optional<Artifacts> linkDynamicLibrary(
+  std::optional<Artifacts> linkDynamicLibrary(
       StringRef libraryName, ArrayRef<Artifact> objectFiles) override {
     Artifacts artifacts;
 
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/EmbeddedLinkerTool.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/EmbeddedLinkerTool.cpp
index 8dc2427..42a6dba 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/EmbeddedLinkerTool.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/EmbeddedLinkerTool.cpp
@@ -103,7 +103,7 @@
     return success();
   }
 
-  Optional<Artifacts> linkDynamicLibrary(
+  std::optional<Artifacts> linkDynamicLibrary(
       StringRef libraryName, ArrayRef<Artifact> objectFiles) override {
     Artifacts artifacts;
 
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/UnixLinkerTool.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/UnixLinkerTool.cpp
index 36d17da..eceedcb 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/UnixLinkerTool.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/UnixLinkerTool.cpp
@@ -60,7 +60,7 @@
     return "";
   }
 
-  Optional<Artifacts> linkDynamicLibrary(
+  std::optional<Artifacts> linkDynamicLibrary(
       StringRef libraryName, ArrayRef<Artifact> objectFiles) override {
     Artifacts artifacts;
 
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/WasmLinkerTool.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/WasmLinkerTool.cpp
index 288330d..9e07944 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/WasmLinkerTool.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/WasmLinkerTool.cpp
@@ -75,7 +75,7 @@
     return success();
   }
 
-  Optional<Artifacts> linkDynamicLibrary(
+  std::optional<Artifacts> linkDynamicLibrary(
       StringRef libraryName, ArrayRef<Artifact> objectFiles) override {
     Artifacts artifacts;
 
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/WindowsLinkerTool.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/WindowsLinkerTool.cpp
index 7fddf02..e6fc5c9 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/WindowsLinkerTool.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/WindowsLinkerTool.cpp
@@ -90,7 +90,7 @@
     return success();
   }
 
-  Optional<Artifacts> linkDynamicLibrary(
+  std::optional<Artifacts> linkDynamicLibrary(
       StringRef libraryName, ArrayRef<Artifact> objectFiles) override {
     Artifacts artifacts;
 
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/MetalSPIRVTarget.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/MetalSPIRVTarget.cpp
index 71ba118..9f8ceff 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/MetalSPIRVTarget.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/MetalSPIRVTarget.cpp
@@ -147,7 +147,7 @@
     // 2. Cross compile SPIR-V to MSL source code.
     llvm::SmallVector<MetalShader, 2> mslShaders;
     for (const auto &entryPoint : entryPointNames) {
-      llvm::Optional<MetalShader> mslShader = crossCompileSPIRVToMSL(
+      std::optional<MetalShader> mslShader = crossCompileSPIRVToMSL(
           // We can use ArrayRef here given spvBinary reserves 0 bytes on stack.
           llvm::ArrayRef(spvBinary.data(), spvBinary.size()), entryPoint);
       if (!mslShader) {
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/SPIRVToMSL.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/SPIRVToMSL.cpp
index 6d6c201..3852b00 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/SPIRVToMSL.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/SPIRVToMSL.cpp
@@ -98,7 +98,7 @@
 };
 }  // namespace
 
-llvm::Optional<MetalShader> crossCompileSPIRVToMSL(
+std::optional<MetalShader> crossCompileSPIRVToMSL(
     llvm::ArrayRef<uint32_t> spvBinary, StringRef entryPoint) {
   SPIRVToMSLCompiler spvCrossCompiler(spvBinary.data(), spvBinary.size());
 
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/SPIRVToMSL.h b/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/SPIRVToMSL.h
index 37b4ad6..0098c8f 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/SPIRVToMSL.h
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/SPIRVToMSL.h
@@ -29,7 +29,7 @@
 
 // Cross compiles SPIR-V into Metal Shading Language source code for the
 // compute shader with |entryPoint|. Returns std::nullopt on failure.
-llvm::Optional<MetalShader> crossCompileSPIRVToMSL(
+std::optional<MetalShader> crossCompileSPIRVToMSL(
     llvm::ArrayRef<uint32_t> spvBinary, StringRef entryPoint);
 
 }  // namespace iree_compiler
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/ROCM/ROCMTarget.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/ROCM/ROCMTarget.cpp
index e36f44b..553af80 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/ROCM/ROCMTarget.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/ROCM/ROCMTarget.cpp
@@ -151,7 +151,8 @@
       if (llvmFunc->isDeclaration()) continue;
       std::array<int32_t, 3> workgroupSize;
       auto exportOp = exportOps[func.getName()];
-      if (Optional<ArrayAttr> workgroupSizeAttr = exportOp.getWorkgroupSize()) {
+      if (std::optional<ArrayAttr> workgroupSizeAttr =
+              exportOp.getWorkgroupSize()) {
         for (auto it : llvm::enumerate(workgroupSizeAttr.value())) {
           workgroupSize[it.index()] = it.value().cast<IntegerAttr>().getInt();
           flatWgSize *= it.value().cast<IntegerAttr>().getInt();
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/WebGPU/SPIRVToWGSL.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/WebGPU/SPIRVToWGSL.cpp
index 79f7387..0eca686 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/WebGPU/SPIRVToWGSL.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/WebGPU/SPIRVToWGSL.cpp
@@ -15,7 +15,7 @@
 namespace IREE {
 namespace HAL {
 
-llvm::Optional<std::string> compileSPIRVToWGSL(
+std::optional<std::string> compileSPIRVToWGSL(
     llvm::ArrayRef<uint32_t> spvBinary) {
   // TODO(scotttodd): reroute to MLIR diagnostics?
   auto diagPrinter = tint::diag::Printer::create(stderr, true);
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/WebGPU/SPIRVToWGSL.h b/compiler/src/iree/compiler/Dialect/HAL/Target/WebGPU/SPIRVToWGSL.h
index f6d8ce0..98c0e7a 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/WebGPU/SPIRVToWGSL.h
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/WebGPU/SPIRVToWGSL.h
@@ -19,7 +19,7 @@
 
 // Compiles SPIR-V into WebGPU Shading Language (WGSL) source code.
 // Returns std::nullopt on failure.
-llvm::Optional<std::string> compileSPIRVToWGSL(
+std::optional<std::string> compileSPIRVToWGSL(
     llvm::ArrayRef<uint32_t> spvBinary);
 
 }  // namespace HAL
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeDispatchInstrumentation.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeDispatchInstrumentation.cpp
index 764f9b2..4f5d586 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeDispatchInstrumentation.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeDispatchInstrumentation.cpp
@@ -263,7 +263,7 @@
           // NOTE: we just choose the first instrumented export for attribution
           // as that's good enough for all current use cases. If we start
           // specializing really early we may want to fix that.
-          Optional<uint32_t> functionId;
+          std::optional<uint32_t> functionId;
           for (auto entryPointAttr : dispatchOp.getEntryPointRefs()) {
             auto it = instrumentedExports.find(entryPointAttr);
             if (it != instrumentedExports.end()) {
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeInterfaces.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeInterfaces.cpp
index b07edc3..e85612d 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeInterfaces.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeInterfaces.cpp
@@ -174,7 +174,7 @@
           builder.getContext(), binding.ordinal, binding.type,
           binding.flags != IREE::HAL::DescriptorFlags::None
               ? binding.flags
-              : Optional<IREE::HAL::DescriptorFlags>{}));
+              : std::optional<IREE::HAL::DescriptorFlags>{}));
     }
     setLayoutAttrs.push_back(IREE::HAL::DescriptorSetLayoutAttr::get(
         builder.getContext(), setLayout.ordinal, bindingAttrs));
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/PreprocessExecutables.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/PreprocessExecutables.cpp
index 4ad394a..a0e6258 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/PreprocessExecutables.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/PreprocessExecutables.cpp
@@ -219,8 +219,8 @@
  public:
   PreprocessExecutablesPass() = default;
   PreprocessExecutablesPass(const PreprocessExecutablesPass &pass) {}
-  PreprocessExecutablesPass(Optional<std::string> pipeline,
-                            Optional<std::string> command) {
+  PreprocessExecutablesPass(std::optional<std::string> pipeline,
+                            std::optional<std::string> command) {
     if (pipeline.has_value()) {
       this->pipeline = std::move(pipeline).value();
     } else if (command.has_value()) {
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Analysis/ResourceUsage.cpp b/compiler/src/iree/compiler/Dialect/Stream/Analysis/ResourceUsage.cpp
index 2e388ec..ed91d25 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Analysis/ResourceUsage.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Analysis/ResourceUsage.cpp
@@ -664,7 +664,7 @@
 
 ResourceUsageAnalysis::~ResourceUsageAnalysis() = default;
 
-llvm::Optional<ResourceUsageBitfield>
+std::optional<ResourceUsageBitfield>
 ResourceUsageAnalysis::tryLookupResourceUsage(Value value) {
   auto resourceUsage =
       solver.lookupElementFor<ValueResourceUsage>(Position::forValue(value));
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Analysis/ResourceUsage.h b/compiler/src/iree/compiler/Dialect/Stream/Analysis/ResourceUsage.h
index affe3fc..bf70dff 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Analysis/ResourceUsage.h
+++ b/compiler/src/iree/compiler/Dialect/Stream/Analysis/ResourceUsage.h
@@ -82,7 +82,7 @@
   }
 
   // Returns the analyzed resource usage of the |value| resource, if analyzed.
-  llvm::Optional<ResourceUsageBitfield> tryLookupResourceUsage(Value value);
+  std::optional<ResourceUsageBitfield> tryLookupResourceUsage(Value value);
 
  private:
   Explorer explorer;
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Conversion/UtilToStream/Patterns.cpp b/compiler/src/iree/compiler/Dialect/Stream/Conversion/UtilToStream/Patterns.cpp
index 7a0ff72..54d2f10 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Conversion/UtilToStream/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Conversion/UtilToStream/Patterns.cpp
@@ -93,7 +93,7 @@
     auto resourceOp = rewriter.replaceOpWithNewOp<IREE::Util::GlobalOp>(
         globalOp, globalOp.getName(), globalOp.getIsMutable(), resourceType,
         initialValue && !tensorInitializerRequired
-            ? llvm::Optional<TypedAttr>{initialValue}
+            ? std::optional<TypedAttr>{initialValue}
             : std::nullopt);
     resourceOp.setVisibility(globalOp.getVisibility());
 
@@ -108,7 +108,7 @@
     auto indexType = rewriter.getIndexType();
     auto resourceSizeOp = rewriter.create<IREE::Util::GlobalOp>(
         globalOp.getLoc(), (globalOp.getName() + "__size").str(),
-        globalOp.getIsMutable(), indexType, Optional<TypedAttr>{});
+        globalOp.getIsMutable(), indexType, std::optional<TypedAttr>{});
     resourceSizeOp.setVisibility(globalOp.getVisibility());
 
     // Materialize the initializer if we need to setup a tensor-like constant.
diff --git a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamBase.td b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamBase.td
index 94f86d2..87484a4 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamBase.td
+++ b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamBase.td
@@ -227,7 +227,7 @@
   }];
   let parameters = (ins
     AttrParameter<"CollectiveKind", "">:$kind,
-    OptionalParameter<"mlir::Optional<CollectiveReductionOp>">:$reduction,
+    OptionalParameter<"std::optional<CollectiveReductionOp>">:$reduction,
     AttrParameter<"CollectiveElementType", "">:$element_type
   );
   let assemblyFormat = [{
diff --git a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOpFolders.cpp b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOpFolders.cpp
index 1aef723..c7502e8 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOpFolders.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOpFolders.cpp
@@ -47,7 +47,7 @@
 //  stream.async.concurrent ... {
 //    stream.yield
 //  }
-static Optional<IREE::Stream::YieldOp> getYieldIfOnlyOp(Block &block) {
+static std::optional<IREE::Stream::YieldOp> getYieldIfOnlyOp(Block &block) {
   if (block.empty()) return std::nullopt;
   if (&block.front() != &block.back()) return std::nullopt;
   auto yieldOp = dyn_cast<IREE::Stream::YieldOp>(block.back());
diff --git a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp
index fb7208b..06a34eb 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp
@@ -745,7 +745,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getSource());
 }
 
-::llvm::Optional<unsigned> ResourceSubviewOp::getTiedResultOperandIndex(
+::std::optional<unsigned> ResourceSubviewOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // source
 }
@@ -797,7 +797,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getSource());
 }
 
-::llvm::Optional<unsigned> TensorImportOp::getTiedResultOperandIndex(
+::std::optional<unsigned> TensorImportOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // source
 }
@@ -824,7 +824,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getSource());
 }
 
-::llvm::Optional<unsigned> TensorExportOp::getTiedResultOperandIndex(
+::std::optional<unsigned> TensorExportOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // source
 }
@@ -961,7 +961,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getTarget());
 }
 
-::llvm::Optional<unsigned> TensorUpdateOp::getTiedResultOperandIndex(
+::std::optional<unsigned> TensorUpdateOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // target
 }
@@ -988,7 +988,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getTarget());
 }
 
-::llvm::Optional<unsigned> TensorFillOp::getTiedResultOperandIndex(
+::std::optional<unsigned> TensorFillOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // target
 }
@@ -1037,7 +1037,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getTarget());
 }
 
-::llvm::Optional<unsigned> TensorStoreOp::getTiedResultOperandIndex(
+::std::optional<unsigned> TensorStoreOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // target
 }
@@ -1143,7 +1143,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getTarget());
 }
 
-::llvm::Optional<unsigned> BuiltinFillI64Op::getTiedResultOperandIndex(
+::std::optional<unsigned> BuiltinFillI64Op::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // target
 }
@@ -1313,7 +1313,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getTarget());
 }
 
-::llvm::Optional<unsigned> AsyncFillOp::getTiedResultOperandIndex(
+::std::optional<unsigned> AsyncFillOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // target
 }
@@ -1347,7 +1347,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getTarget());
 }
 
-::llvm::Optional<unsigned> AsyncUpdateOp::getTiedResultOperandIndex(
+::std::optional<unsigned> AsyncUpdateOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // target
 }
@@ -1390,7 +1390,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getTarget());
 }
 
-::llvm::Optional<unsigned> AsyncCopyOp::getTiedResultOperandIndex(
+::std::optional<unsigned> AsyncCopyOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // target
 }
@@ -1431,7 +1431,7 @@
 
 static ParseResult parseCollectiveParam(
     OpAsmParser &parser, Attribute opAttr,
-    Optional<OpAsmParser::UnresolvedOperand> &optionalParamValue) {
+    std::optional<OpAsmParser::UnresolvedOperand> &optionalParamValue) {
   const char *keyword = getCollectiveParamKeyword(opAttr);
   if (!keyword) return success();  // optional
   OpAsmParser::UnresolvedOperand paramValue;
@@ -1485,7 +1485,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getTarget());
 }
 
-::llvm::Optional<unsigned> AsyncCollectiveOp::getTiedResultOperandIndex(
+::std::optional<unsigned> AsyncCollectiveOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // target
 }
@@ -1553,7 +1553,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getTarget());
 }
 
-::llvm::Optional<unsigned> AsyncStoreOp::getTiedResultOperandIndex(
+::std::optional<unsigned> AsyncStoreOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // target
 }
@@ -1755,13 +1755,13 @@
 }
 
 OperandRange AsyncExecuteOp::getSuccessorEntryOperands(
-    Optional<unsigned> index) {
+    std::optional<unsigned> index) {
   assert(index && index.value() == 0 && "invalid region index");
   return getResourceOperands();
 }
 
 void AsyncExecuteOp::getSuccessorRegions(
-    Optional<unsigned> index, ArrayRef<Attribute> operands,
+    std::optional<unsigned> index, ArrayRef<Attribute> operands,
     SmallVectorImpl<RegionSuccessor> &regions) {
   // Unconditional control flow into the region and back to the parent, so
   // return the correct RegionSuccessor purely based on the index being None or
@@ -1909,13 +1909,13 @@
 }
 
 OperandRange AsyncConcurrentOp::getSuccessorEntryOperands(
-    Optional<unsigned> index) {
+    std::optional<unsigned> index) {
   assert(index && index.value() == 0 && "invalid region index");
   return getResourceOperands();
 }
 
 void AsyncConcurrentOp::getSuccessorRegions(
-    Optional<unsigned> index, ArrayRef<Attribute> operands,
+    std::optional<unsigned> index, ArrayRef<Attribute> operands,
     SmallVectorImpl<RegionSuccessor> &regions) {
   // Unconditional control flow into the region and back to the parent, so
   // return the correct RegionSuccessor purely based on the index being None or
@@ -2357,13 +2357,14 @@
   return success();
 }
 
-OperandRange CmdExecuteOp::getSuccessorEntryOperands(Optional<unsigned> index) {
+OperandRange CmdExecuteOp::getSuccessorEntryOperands(
+    std::optional<unsigned> index) {
   assert(index && index.value() == 0 && "invalid region index");
   return getResourceOperands();
 }
 
 void CmdExecuteOp::getSuccessorRegions(
-    Optional<unsigned> index, ArrayRef<Attribute> operands,
+    std::optional<unsigned> index, ArrayRef<Attribute> operands,
     SmallVectorImpl<RegionSuccessor> &regions) {
   // Unconditional control flow into the region and back to the parent, so
   // return the correct RegionSuccessor purely based on the index being None or
@@ -2431,7 +2432,7 @@
 }
 
 void CmdSerialOp::getSuccessorRegions(
-    Optional<unsigned> index, ArrayRef<Attribute> operands,
+    std::optional<unsigned> index, ArrayRef<Attribute> operands,
     SmallVectorImpl<RegionSuccessor> &regions) {
   // Unconditional control flow into the region and back to the parent, so
   // return the correct RegionSuccessor purely based on the index being None or
@@ -2456,7 +2457,7 @@
 }
 
 void CmdConcurrentOp::getSuccessorRegions(
-    Optional<unsigned> index, ArrayRef<Attribute> operands,
+    std::optional<unsigned> index, ArrayRef<Attribute> operands,
     SmallVectorImpl<RegionSuccessor> &regions) {
   // Unconditional control flow into the region and back to the parent, so
   // return the correct RegionSuccessor purely based on the index being None or
@@ -2495,7 +2496,7 @@
   return IREE::Util::TiedOpInterface::findTiedBaseValue(getResource());
 }
 
-::llvm::Optional<unsigned> TimepointBarrierOp::getTiedResultOperandIndex(
+::std::optional<unsigned> TimepointBarrierOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};
 }
@@ -2543,7 +2544,7 @@
   return success();
 }
 
-::llvm::Optional<unsigned> TimepointAwaitOp::getTiedResultOperandIndex(
+::std::optional<unsigned> TimepointAwaitOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {resultIndex};
 }
@@ -2660,7 +2661,7 @@
 //===----------------------------------------------------------------------===//
 
 MutableOperandRange ReturnOp::getMutableSuccessorOperands(
-    Optional<unsigned> index) {
+    std::optional<unsigned> index) {
   return getOperandsMutable();
 }
 
@@ -2669,7 +2670,7 @@
 //===----------------------------------------------------------------------===//
 
 MutableOperandRange YieldOp::getMutableSuccessorOperands(
-    Optional<unsigned> index) {
+    std::optional<unsigned> index) {
   return getResourceOperandsMutable();
 }
 
diff --git a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.cpp b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.cpp
index 9d1a894..166c221 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.cpp
@@ -273,7 +273,7 @@
 // !stream.resource<lifetime>
 //===----------------------------------------------------------------------===//
 
-static llvm::Optional<Lifetime> parseLifetime(StringRef str) {
+static std::optional<Lifetime> parseLifetime(StringRef str) {
   if (str == "*") {
     return Lifetime::Unknown;
   } else if (str == "external") {
diff --git a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.h b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.h
index 289a210..1e2d7ea 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.h
+++ b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.h
@@ -30,7 +30,7 @@
 
 template <>
 struct FieldParser<
-    mlir::Optional<mlir::iree_compiler::IREE::Stream::CollectiveReductionOp>> {
+    std::optional<mlir::iree_compiler::IREE::Stream::CollectiveReductionOp>> {
   static FailureOr<mlir::iree_compiler::IREE::Stream::CollectiveReductionOp>
   parse(AsmParser &parser) {
     std::string value;
@@ -43,7 +43,7 @@
 };
 static inline AsmPrinter &operator<<(
     AsmPrinter &printer,
-    mlir::Optional<mlir::iree_compiler::IREE::Stream::CollectiveReductionOp>
+    std::optional<mlir::iree_compiler::IREE::Stream::CollectiveReductionOp>
         param) {
   printer << (param.has_value()
                   ? mlir::iree_compiler::IREE::Stream::stringifyEnum(
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ConvertToStream.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ConvertToStream.cpp
index 0b0acc8..71c50e5 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ConvertToStream.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ConvertToStream.cpp
@@ -224,7 +224,7 @@
         });
     typeConverter.addArgumentMaterialization(
         [](OpBuilder &builder, TensorType resultType, ValueRange inputs,
-           Location loc) -> Optional<Value> {
+           Location loc) -> std::optional<Value> {
           assert(inputs.size() >= 2);
           auto resourceValue = inputs[0];
           auto resourceSize = inputs[1];
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/FoldUniformOperands.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/FoldUniformOperands.cpp
index a18a52c..50d6806 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/FoldUniformOperands.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/FoldUniformOperands.cpp
@@ -173,7 +173,7 @@
   unsigned operandCount = anyDispatchOp.getUniformOperands().size();
 
   // Find uniform constant values for each operand across all usages.
-  SmallVector<Optional<APInt>> operandValues(operandCount);
+  SmallVector<std::optional<APInt>> operandValues(operandCount);
   SmallVector<SmallVector<Location>> operandLocs(operandCount);
   llvm::BitVector uniformOperandMap(operandCount, /*t=*/true);
   for (auto dispatchOp : dispatchOps) {
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp
index 7cc0ae1..fc2b210 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp
@@ -814,7 +814,7 @@
 // Performs allocation for all local transients in the execution region (those
 // !stream.resource<transient> values that don't escape). A new allocation op
 // will be inserted using |externalBuilder| and mappings added to |scope|.
-static llvm::Optional<TransientAllocation> allocateLocalTransients(
+static std::optional<TransientAllocation> allocateLocalTransients(
     IREE::Stream::AsyncExecuteOp executeOp, AllocationScope &scope,
     OpBuilder &externalBuilder) {
   // Track which values we've already reserved. This makes it easier to early-
@@ -930,7 +930,7 @@
 // Extracts stream.async.constant ops from |executeOp| into their own dedicated
 // stream.resource.constants upload op. The uploaded constants will be captured
 // by the region for use within as if they had still existed in there.
-static Optional<ConstantAllocation> extractConstants(
+static std::optional<ConstantAllocation> extractConstants(
     IREE::Stream::AsyncExecuteOp executeOp, OpBuilder &externalBuilder) {
   // Gather all constant ops from the region, if any.
   auto constantOps =
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/VerifyLowerings.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/VerifyLowerings.cpp
index b2816b5..dc28f92 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/VerifyLowerings.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/VerifyLowerings.cpp
@@ -38,7 +38,7 @@
     ILLEGAL,
   };
 
-  using OpVerifierFn = std::function<Optional<Legality>(Operation *op)>;
+  using OpVerifierFn = std::function<std::optional<Legality>(Operation *op)>;
   using TypeVerifierFn = std::function<Legality(Type type)>;
 
   void addIllegalDialect(StringRef dialectName) {
@@ -64,13 +64,13 @@
     opLegality.insert({OpT::getOperationName(), Legality::ILLEGAL});
   }
 
-  void addOpVerifier(std::function<Optional<Legality>(Operation *)> fn) {
+  void addOpVerifier(std::function<std::optional<Legality>(Operation *)> fn) {
     opVerifiers.push_back(fn);
   }
 
   template <typename OpT>
-  void addOpVerifier(std::function<Optional<Legality>(OpT)> fn) {
-    auto wrapperFn = [=](Operation *baseOp) -> Optional<Legality> {
+  void addOpVerifier(std::function<std::optional<Legality>(OpT)> fn) {
+    auto wrapperFn = [=](Operation *baseOp) -> std::optional<Legality> {
       if (auto op = dyn_cast<OpT>(baseOp)) {
         return fn(op);
       }
@@ -213,30 +213,33 @@
 }
 
 static void markStreamTensorOpsIllegal(Verifier &verifier) {
-  verifier.addOpVerifier([](Operation *op) -> Optional<Verifier::Legality> {
-    if (op->hasTrait<OpTrait::IREE::Stream::TensorPhaseOp>()) {
-      return Verifier::Legality::ILLEGAL;
-    }
-    return std::nullopt;
-  });
+  verifier.addOpVerifier(
+      [](Operation *op) -> std::optional<Verifier::Legality> {
+        if (op->hasTrait<OpTrait::IREE::Stream::TensorPhaseOp>()) {
+          return Verifier::Legality::ILLEGAL;
+        }
+        return std::nullopt;
+      });
 }
 
 static void markStreamAsyncOpsIllegal(Verifier &verifier) {
-  verifier.addOpVerifier([](Operation *op) -> Optional<Verifier::Legality> {
-    if (op->hasTrait<OpTrait::IREE::Stream::AsyncPhaseOp>()) {
-      return Verifier::Legality::ILLEGAL;
-    }
-    return std::nullopt;
-  });
+  verifier.addOpVerifier(
+      [](Operation *op) -> std::optional<Verifier::Legality> {
+        if (op->hasTrait<OpTrait::IREE::Stream::AsyncPhaseOp>()) {
+          return Verifier::Legality::ILLEGAL;
+        }
+        return std::nullopt;
+      });
 }
 
 static void markStreamCmdOpsIllegal(Verifier &verifier) {
-  verifier.addOpVerifier([](Operation *op) -> Optional<Verifier::Legality> {
-    if (op->hasTrait<OpTrait::IREE::Stream::CmdPhaseOp>()) {
-      return Verifier::Legality::ILLEGAL;
-    }
-    return std::nullopt;
-  });
+  verifier.addOpVerifier(
+      [](Operation *op) -> std::optional<Verifier::Legality> {
+        if (op->hasTrait<OpTrait::IREE::Stream::CmdPhaseOp>()) {
+          return Verifier::Legality::ILLEGAL;
+        }
+        return std::nullopt;
+      });
 }
 
 //===----------------------------------------------------------------------===//
@@ -356,7 +359,7 @@
 
     // All streamable ops should be inside of execution regions.
     verifier.addOpVerifier<IREE::Stream::StreamableOpInterface>(
-        [](auto op) -> Optional<Verifier::Legality> {
+        [](auto op) -> std::optional<Verifier::Legality> {
           // Skip cmd ops that may exist.
           if (op->template hasTrait<OpTrait::IREE::Stream::CmdPhaseOp>()) {
             return Verifier::Legality::LEGAL;
diff --git a/compiler/src/iree/compiler/Dialect/Util/Analysis/DFX/Solver.h b/compiler/src/iree/compiler/Dialect/Util/Analysis/DFX/Solver.h
index b8b157f..9e7a7a9 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Analysis/DFX/Solver.h
+++ b/compiler/src/iree/compiler/Dialect/Util/Analysis/DFX/Solver.h
@@ -269,7 +269,7 @@
   void rememberDependences();
 
   // Maximum number of fixed point iterations or None for default.
-  Optional<unsigned> maxFixpointIterations;
+  std::optional<unsigned> maxFixpointIterations;
 
   // A flag that indicates which stage of the process we are in.
   enum class Phase {
diff --git a/compiler/src/iree/compiler/Dialect/Util/Analysis/Explorer.cpp b/compiler/src/iree/compiler/Dialect/Util/Analysis/Explorer.cpp
index 7790680..f4bdc0b 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Analysis/Explorer.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Analysis/Explorer.cpp
@@ -27,9 +27,9 @@
 // Returns the remapped successor operand index if the branch operand is
 // passed to a successor (vs being used by the op itself, such as the cond_br
 // condition).
-static llvm::Optional<unsigned> mapSuccessorOperand(BranchOpInterface branchOp,
-                                                    unsigned successorIdx,
-                                                    unsigned operandIdx) {
+static std::optional<unsigned> mapSuccessorOperand(BranchOpInterface branchOp,
+                                                   unsigned successorIdx,
+                                                   unsigned operandIdx) {
   // I don't know if there's a better way to do this - the interface doesn't
   // help.
   auto operandRange = branchOp.getSuccessorOperands(successorIdx);
diff --git a/compiler/src/iree/compiler/Dialect/Util/Conversion/MemRefToUtil/Patterns.cpp b/compiler/src/iree/compiler/Dialect/Util/Conversion/MemRefToUtil/Patterns.cpp
index dfeb8c5..811d2f0 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Conversion/MemRefToUtil/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Conversion/MemRefToUtil/Patterns.cpp
@@ -293,7 +293,7 @@
   conversionTarget.addIllegalDialect<memref::MemRefDialect>();
 
   typeConverter.addConversion(
-      [convertedBufferType](MemRefType type) -> llvm::Optional<Type> {
+      [convertedBufferType](MemRefType type) -> std::optional<Type> {
         if (isRankZeroOrOneMemRef(type)) {
           if (convertedBufferType) {
             return convertedBufferType;
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/ClosureOpUtils.cpp b/compiler/src/iree/compiler/Dialect/Util/IR/ClosureOpUtils.cpp
index c378e35..5a10f37 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/ClosureOpUtils.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/ClosureOpUtils.cpp
@@ -228,7 +228,7 @@
   // Build data structure for unused operand elision.
   SmallVector<unsigned, 4> elidedOperands;
   llvm::SmallMapVector<Value, BlockArgument, 8> argToBlockMap;
-  SmallVector<llvm::Optional<BlockArgument>, 8> blockArgReplacements(
+  SmallVector<std::optional<BlockArgument>, 8> blockArgReplacements(
       entryBlock.getNumArguments());
   for (auto opArg : llvm::enumerate(closureOp.getClosureOperands())) {
     auto blockArg = entryBlock.getArgument(opArg.index());
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/ClosureOpUtils.h b/compiler/src/iree/compiler/Dialect/Util/IR/ClosureOpUtils.h
index d70c3dd..74a5aa9 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/ClosureOpUtils.h
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/ClosureOpUtils.h
@@ -47,7 +47,7 @@
   // Maximum size in bytes of constant values to inline into the closure.
   // When 0 no constants will be inlined; when None all constants will be
   // inlined.
-  Optional<int64_t> maxInlinedConstantBytes = {256};
+  std::optional<int64_t> maxInlinedConstantBytes = {256};
 };
 
 // Optimizes closure |closureOp| to remove duplicate operands and unused
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilExternalModels.cpp b/compiler/src/iree/compiler/Dialect/Util/IR/UtilExternalModels.cpp
index 5f540fa..afca742 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilExternalModels.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilExternalModels.cpp
@@ -50,7 +50,7 @@
         insertSliceOp.getDest());
   }
 
-  ::llvm::Optional<unsigned> getTiedResultOperandIndex(
+  ::std::optional<unsigned> getTiedResultOperandIndex(
       Operation *op, unsigned resultIndex) const {
     return {1};  // dest
   }
@@ -70,7 +70,7 @@
         linalgOp.getDpsInitOperands()[resultIndex]->get());
   }
 
-  ::llvm::Optional<unsigned> getTiedResultOperandIndex(
+  ::std::optional<unsigned> getTiedResultOperandIndex(
       Operation *op, unsigned resultIndex) const {
     auto linalgOp = cast<OpTy>(op);
     return {linalgOp.getDpsInitOperands()[resultIndex]->getOperandNumber()};
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilInterfaces.td b/compiler/src/iree/compiler/Dialect/Util/IR/UtilInterfaces.td
index 0d2d470..e230d6b 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilInterfaces.td
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilInterfaces.td
@@ -673,7 +673,7 @@
         Note that the index returned is into the full range of all operands of
         the current op.
       }],
-      /*retTy=*/"::llvm::Optional<unsigned>",
+      /*retTy=*/"::std::optional<unsigned>",
       /*methodName=*/"getTiedResultOperandIndex",
       /*args=*/(ins "unsigned":$resultIndex),
       /*methodBody=*/[{}],
@@ -691,7 +691,7 @@
       /*retTy=*/"void",
       /*methodName=*/"setTiedResultOperandIndex",
       /*args=*/(ins "unsigned":$resultIndex,
-                    "::llvm::Optional<unsigned>":$operandIndex),
+                    "::std::optional<unsigned>":$operandIndex),
       /*methodBody=*/[{}],
       /*defaultImplementation=*/[{
         return IREE::Util::detail::setTiedResultOperandIndex($_op, resultIndex, operandIndex);
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp
index 7c57214..acc463b 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp
@@ -677,7 +677,7 @@
 // Numeric ops
 //===----------------------------------------------------------------------===//
 
-Optional<std::pair<int64_t, int64_t>>
+std::optional<std::pair<int64_t, int64_t>>
 NumericOptionalNarrowOp::getIntegerRange() {
   if (!getMinValue() || !getMaxValue()) return {};
   bool signExtend = isSigned();
@@ -762,7 +762,7 @@
 
 void GlobalOp::build(OpBuilder &builder, OperationState &result, StringRef name,
                      bool isMutable, Type type,
-                     Optional<TypedAttr> initialValue,
+                     std::optional<TypedAttr> initialValue,
                      ArrayRef<NamedAttribute> attrs) {
   result.addAttribute(SymbolTable::getSymbolAttrName(),
                       builder.getStringAttr(name));
@@ -1034,7 +1034,7 @@
   getResultSizeMutable().assign(operand.length);
 }
 
-::llvm::Optional<unsigned> BufferSubspanOp::getTiedResultOperandIndex(
+::std::optional<unsigned> BufferSubspanOp::getTiedResultOperandIndex(
     unsigned resultIndex) {
   return {0};  // source
 }
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.td b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.td
index 9c79984..bb1cb8b 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.td
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.td
@@ -126,7 +126,7 @@
     OpBuilder<(ins
       "Value":$operand,
       "Type":$type,
-      "Optional<std::pair<int64_t, int64_t>>":$integerRange
+      "std::optional<std::pair<int64_t, int64_t>>":$integerRange
     ),
     [{
       IntegerAttr minValueAttr;
@@ -148,7 +148,7 @@
       return true;
     }
 
-    Optional<std::pair<int64_t, int64_t>> getIntegerRange();
+    std::optional<std::pair<int64_t, int64_t>> getIntegerRange();
   }];
 }
 
@@ -488,7 +488,7 @@
       "StringRef":$name,
       "bool":$isMutable,
       "Type":$type,
-      "Optional<TypedAttr>":$initialValue,
+      "std::optional<TypedAttr>":$initialValue,
       CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs
     )>,
     OpBuilder<(ins
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.cpp b/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.cpp
index 9f6d769..8bfecee 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.cpp
@@ -294,7 +294,7 @@
 // IREE::Util::TiedOpInterface
 //===----------------------------------------------------------------------===//
 
-llvm::Optional<unsigned> detail::getTiedResultOperandIndex(
+std::optional<unsigned> detail::getTiedResultOperandIndex(
     Operation *op, unsigned resultIndex) {
   auto storageAttr =
       op->getAttrOfType<ArrayAttr>(TiedOpInterface::getStorageAttrName());
@@ -313,7 +313,7 @@
 }
 
 void detail::setTiedResultOperandIndex(Operation *op, unsigned resultIndex,
-                                       llvm::Optional<unsigned> operandIndex) {
+                                       std::optional<unsigned> operandIndex) {
   auto tiedOp = cast<TiedOpInterface>(op);
   auto resultRange = tiedOp.getTiedResultsIndexAndLength();
   resultIndex -= resultRange.first;
@@ -546,7 +546,7 @@
 // IREE::Util::ShapeAware*
 //===----------------------------------------------------------------------===//
 
-Optional<ValueRange> findDynamicDims(Value shapedValue) {
+std::optional<ValueRange> findDynamicDims(Value shapedValue) {
   // Look up the use-def chain: always safe, as any value we reach dominates
   // {|block|, |insertionPoint|} implicitly.
   SmallVector<Value> worklist;
@@ -565,8 +565,8 @@
   return std::nullopt;
 }
 
-Optional<ValueRange> findDynamicDims(Value shapedValue, Block *block,
-                                     Block::iterator insertionPoint) {
+std::optional<ValueRange> findDynamicDims(Value shapedValue, Block *block,
+                                          Block::iterator insertionPoint) {
   // Look up the use-def chain: always safe, as any value we reach dominates
   // {|block|, |insertionPoint|} implicitly.
   auto upwardRange = findDynamicDims(shapedValue);
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.h b/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.h
index 220fa45..df7572b 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.h
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.h
@@ -128,10 +128,10 @@
 
 namespace detail {
 
-llvm::Optional<unsigned> getTiedResultOperandIndex(Operation *op,
-                                                   unsigned resultIndex);
+std::optional<unsigned> getTiedResultOperandIndex(Operation *op,
+                                                  unsigned resultIndex);
 void setTiedResultOperandIndex(Operation *op, unsigned resultIndex,
-                               llvm::Optional<unsigned> operandIndex);
+                               std::optional<unsigned> operandIndex);
 SmallVector<int64_t, 4> getTiedResultOperandIndices(Operation *op);
 bool isOperandTied(Operation *tiedOp, unsigned operandIndex);
 SmallVector<Value> getOperandTiedResults(Operation *op, unsigned operandIndex);
@@ -152,13 +152,13 @@
 
 // Walks the SSA use-def chain upwards to find the dynamic dimensions of the
 // value. Returns None if the shape cannot be found.
-Optional<ValueRange> findDynamicDims(Value shapedValue);
+std::optional<ValueRange> findDynamicDims(Value shapedValue);
 
 // Walks the SSA use-def chain to find the dynamic dimensions of the value.
 // Returns None if the shape cannot be found or if it is defined after
 // {|block|, |insertionPoint|}.
-Optional<ValueRange> findDynamicDims(Value shapedValue, Block *block,
-                                     Block::iterator insertionPoint);
+std::optional<ValueRange> findDynamicDims(Value shapedValue, Block *block,
+                                          Block::iterator insertionPoint);
 
 // Returns the dynamic dimensions for the value at |idx|.
 ValueRange findVariadicDynamicDims(unsigned idx, ValueRange values,
diff --git a/compiler/src/iree/compiler/Dialect/Util/Transforms/FixedPointIterator.cpp b/compiler/src/iree/compiler/Dialect/Util/Transforms/FixedPointIterator.cpp
index b75f3ba..1c5355a 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Transforms/FixedPointIterator.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Transforms/FixedPointIterator.cpp
@@ -38,7 +38,7 @@
   void getDependentDialects(DialectRegistry &registry) const override;
   void runOnOperation() override;
 
-  Optional<OpPassManager> pipeline;
+  std::optional<OpPassManager> pipeline;
 
   // Serialized form of the body pipeline.
   Option<std::string> pipelineStr{
diff --git a/compiler/src/iree/compiler/Dialect/Util/Transforms/IPO.cpp b/compiler/src/iree/compiler/Dialect/Util/Transforms/IPO.cpp
index 5647fa6..d65feb4 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Transforms/IPO.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Transforms/IPO.cpp
@@ -34,7 +34,7 @@
 namespace {
 
 struct LocAttr {
-  Optional<Location> loc;
+  std::optional<Location> loc;
   Type type;
   Attribute attr;
   operator bool() const { return attr != nullptr; }
diff --git a/compiler/src/iree/compiler/Dialect/VM/Analysis/RegisterAllocation.cpp b/compiler/src/iree/compiler/Dialect/VM/Analysis/RegisterAllocation.cpp
index 2c9dab9..f5ce5ca 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Analysis/RegisterAllocation.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Analysis/RegisterAllocation.cpp
@@ -97,7 +97,7 @@
     maxRefRegisterOrdinal = -1;
   }
 
-  Optional<int> findFirstUnsetIntOrdinalSpan(size_t byteWidth) {
+  std::optional<int> findFirstUnsetIntOrdinalSpan(size_t byteWidth) {
     unsigned int requiredAlignment = byteWidth / 4;
     unsigned int ordinalStart = intRegisters.find_first_unset();
     while (ordinalStart != -1) {
@@ -122,7 +122,7 @@
     return std::nullopt;
   }
 
-  Optional<Register> allocateRegister(Type type) {
+  std::optional<Register> allocateRegister(Type type) {
     if (type.isIntOrFloat()) {
       size_t byteWidth = IREE::Util::getRoundedElementByteWidth(type);
       auto ordinalStartOr = findFirstUnsetIntOrdinalSpan(byteWidth);
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.cpp
index 00c8ae2..b69aa55 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.cpp
@@ -118,7 +118,7 @@
   }
 }
 
-Optional<SmallVector<Value, 4>> rewriteAttrToOperands(
+std::optional<SmallVector<Value, 4>> rewriteAttrToOperands(
     Location loc, Attribute attrValue, Type inputType,
     ConversionPatternRewriter &rewriter) {
   if (auto intAttr = attrValue.dyn_cast<IntegerAttr>()) {
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.h b/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.h
index 2a37a22..3394389 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.h
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.h
@@ -32,7 +32,7 @@
 
 namespace detail {
 size_t getSegmentSpanSize(Type spanType);
-Optional<SmallVector<Value, 4>> rewriteAttrToOperands(
+std::optional<SmallVector<Value, 4>> rewriteAttrToOperands(
     Location loc, Attribute attrValue, Type inputType,
     ConversionPatternRewriter &rewriter);
 }  // namespace detail
@@ -56,7 +56,7 @@
 // Automatically handles type conversion and special logic for variadic operands
 // and special types (such as ranked shape).
 template <typename T, typename Adaptor = typename T::Adaptor>
-Optional<SmallVector<Value>> rewriteToCall(
+std::optional<SmallVector<Value>> rewriteToCall(
     T op, Adaptor adaptor, IREE::VM::ImportOp importOp,
     TypeConverter &typeConverter, ConversionPatternRewriter &rewriter) {
   auto *operation = op.getOperation();
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVMTest.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVMTest.cpp
index 1315e92..e027c97 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVMTest.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVMTest.cpp
@@ -47,7 +47,7 @@
         IREE::VM::TargetOptions::FromFlags::get());
 
     typeConverter.addConversion(
-        [](IREE::Util::BufferType type) -> Optional<Type> {
+        [](IREE::Util::BufferType type) -> std::optional<Type> {
           return IREE::VM::RefType::get(
               IREE::VM::BufferType::get(type.getContext()));
         });
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp
index 97d828f..e6c055a 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp
@@ -31,7 +31,7 @@
   addConversion([](IREE::VM::RefType type) { return type; });
 
   // Wrap ref types.
-  addConversion([](Type type) -> Optional<Type> {
+  addConversion([](Type type) -> std::optional<Type> {
     if (RefType::isCompatible(type)) {
       return RefType::get(type);
     }
@@ -39,7 +39,7 @@
   });
 
   // Pointer types remain as pointer types types are passed through unmodified.
-  addConversion([this](IREE::Util::PtrType type) -> Optional<Type> {
+  addConversion([this](IREE::Util::PtrType type) -> std::optional<Type> {
     // Recursively handle pointer target types (we want to convert ptr<index> to
     // ptr<i32>, for example).
     auto targetType = convertType(type.getTargetType());
@@ -50,7 +50,7 @@
   });
 
   // Convert integer types.
-  addConversion([](IntegerType integerType) -> Optional<Type> {
+  addConversion([](IntegerType integerType) -> std::optional<Type> {
     if (integerType.isInteger(32) || integerType.isInteger(64)) {
       // i32 and i64 are always supported by the runtime.
       return integerType;
@@ -62,7 +62,7 @@
   });
 
   // Convert floating-point types.
-  addConversion([this](FloatType floatType) -> Optional<Type> {
+  addConversion([this](FloatType floatType) -> std::optional<Type> {
     if (floatType.getIntOrFloatBitWidth() < 32) {
       if (targetOptions_.f32Extension) {
         // Promote f16 -> f32.
@@ -93,12 +93,12 @@
   });
 
   // Convert index types to the target bit width.
-  addConversion([this](IndexType indexType) -> Optional<Type> {
+  addConversion([this](IndexType indexType) -> std::optional<Type> {
     return IntegerType::get(indexType.getContext(), targetOptions_.indexBits);
   });
 
   // Vectors are used for arbitrary byte storage.
-  addConversion([](VectorType vectorType) -> Optional<Type> {
+  addConversion([](VectorType vectorType) -> std::optional<Type> {
     return IREE::VM::RefType::get(
         IREE::VM::BufferType::get(vectorType.getContext()));
   });
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertBufferOps.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertBufferOps.cpp
index b42f327..ab34675 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertBufferOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertBufferOps.cpp
@@ -322,7 +322,7 @@
                                     TypeConverter &typeConverter,
                                     RewritePatternSet &patterns) {
   typeConverter.addConversion(
-      [](IREE::Util::BufferType type) -> Optional<Type> {
+      [](IREE::Util::BufferType type) -> std::optional<Type> {
         return IREE::VM::RefType::get(
             IREE::VM::BufferType::get(type.getContext()));
       });
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertGlobalOps.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertGlobalOps.cpp
index c13015b..1e6f92a 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertGlobalOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertGlobalOps.cpp
@@ -66,7 +66,7 @@
           op, op.getSymName(), op.getIsMutable(), convertedType,
           llvm::to_vector<4>(op->getDialectAttrs()));
     } else if (convertedType.isInteger(32)) {
-      llvm::Optional<TypedAttr> convertedValue = std::nullopt;
+      std::optional<TypedAttr> convertedValue = std::nullopt;
       if (op.getInitialValue().has_value()) {
         convertedValue = rewriter.getI32IntegerAttr(static_cast<int32_t>(
             op.getInitialValue().value().cast<IntegerAttr>().getInt()));
@@ -75,7 +75,7 @@
           op, op.getSymName(), op.getIsMutable(), convertedType, convertedValue,
           llvm::to_vector<4>(op->getDialectAttrs()));
     } else if (convertedType.isInteger(64)) {
-      llvm::Optional<TypedAttr> convertedValue = std::nullopt;
+      std::optional<TypedAttr> convertedValue = std::nullopt;
       if (op.getInitialValue().has_value()) {
         convertedValue = rewriter.getI64IntegerAttr(
             op.getInitialValue().value().cast<IntegerAttr>().getInt());
@@ -84,7 +84,7 @@
           op, op.getSymName(), op.getIsMutable(), convertedType, convertedValue,
           llvm::to_vector<4>(op->getDialectAttrs()));
     } else if (convertedType.isF32()) {
-      llvm::Optional<TypedAttr> convertedValue = std::nullopt;
+      std::optional<TypedAttr> convertedValue = std::nullopt;
       if (op.getInitialValue().has_value()) {
         convertedValue = rewriter.getF32FloatAttr(static_cast<float>(
             op.getInitialValue().value().cast<FloatAttr>().getValueAsDouble()));
@@ -93,7 +93,7 @@
           op, op.getSymName(), op.getIsMutable(), convertedType, convertedValue,
           llvm::to_vector<4>(op->getDialectAttrs()));
     } else if (convertedType.isF64()) {
-      llvm::Optional<TypedAttr> convertedValue = std::nullopt;
+      std::optional<TypedAttr> convertedValue = std::nullopt;
       if (op.getInitialValue().has_value()) {
         convertedValue = rewriter.getF64FloatAttr(
             op.getInitialValue().value().cast<FloatAttr>().getValueAsDouble());
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertListOps.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertListOps.cpp
index 5feb336..2cf4601 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertListOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertListOps.cpp
@@ -143,7 +143,7 @@
                                   TypeConverter &typeConverter,
                                   RewritePatternSet &patterns) {
   typeConverter.addConversion(
-      [&typeConverter](IREE::Util::ListType type) -> Optional<Type> {
+      [&typeConverter](IREE::Util::ListType type) -> std::optional<Type> {
         Type elementType;
         if (type.getElementType().isa<IREE::Util::VariantType>()) {
           elementType = IREE::VM::OpaqueType::get(type.getContext());
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp
index 2d204f2..af14977 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp
@@ -117,7 +117,8 @@
 
   attachAttribute(newFuncOp, "emitc.static", UnitAttr::get(ctx));
 
-  Optional<std::string> callingConvention = makeCallingConventionString(funcOp);
+  std::optional<std::string> callingConvention =
+      makeCallingConventionString(funcOp);
 
   // Annotate new function with calling convention string which gets used in
   // the CModuleTarget.
@@ -235,8 +236,8 @@
   return lastSegmentSize.getSExtValue();
 }
 
-Optional<std::string> buildFunctionName(IREE::VM::ModuleOp &moduleOp,
-                                        IREE::VM::ImportOp &importOp) {
+std::optional<std::string> buildFunctionName(IREE::VM::ModuleOp &moduleOp,
+                                             IREE::VM::ImportOp &importOp) {
   auto callingConvention = makeImportCallingConventionString(importOp);
   if (!callingConvention.has_value()) {
     return std::nullopt;
@@ -245,7 +246,7 @@
          "_import_shim";
 }
 
-Optional<std::string> buildVariadicFunctionName(
+std::optional<std::string> buildVariadicFunctionName(
     IREE::VM::ModuleOp &moduleOp, IREE::VM::ImportOp &importOp,
     DenseIntElementsAttr segmentSizes) {
   auto callingConvention = makeImportCallingConventionString(importOp);
@@ -266,9 +267,8 @@
   return result;
 }
 
-Optional<emitc::ApplyOp> createVmTypeDefPtr(ConversionPatternRewriter &rewriter,
-                                            Operation *srcOp,
-                                            Type elementType) {
+std::optional<emitc::ApplyOp> createVmTypeDefPtr(
+    ConversionPatternRewriter &rewriter, Operation *srcOp, Type elementType) {
   auto ctx = srcOp->getContext();
   auto loc = srcOp->getLoc();
 
@@ -1321,8 +1321,8 @@
   using OpConversionPattern<IREE::VM::ExportOp>::OpConversionPattern;
 
   struct GeneratedStruct {
-    Optional<Value> value = std::nullopt;
-    Optional<std::string> name = std::nullopt;
+    std::optional<Value> value = std::nullopt;
+    std::optional<std::string> name = std::nullopt;
     SmallVector<Value> callArguments;
   };
 
@@ -2424,7 +2424,7 @@
 
     updatedOperands = {stackArg, import};
 
-    Optional<std::string> funcName;
+    std::optional<std::string> funcName;
     if (auto variadicOp = dyn_cast<IREE::VM::CallVariadicOp>(op)) {
       funcName = buildVariadicFunctionName(moduleOp, importOp,
                                            variadicOp.getSegmentSizes());
@@ -2513,7 +2513,7 @@
     // parameter to the call.
     for (OpResult result : op->getResults()) {
       if (result.getType().isa<IREE::VM::RefType>()) {
-        Optional<Value> ref = typeConverter->materializeRef(result);
+        std::optional<Value> ref = typeConverter->materializeRef(result);
 
         if (!ref.has_value()) {
           return op->emitError() << "local ref not found";
@@ -2546,7 +2546,7 @@
       return operand;
     }
 
-    Optional<Value> operandRef = typeConverter->materializeRef(operand);
+    std::optional<Value> operandRef = typeConverter->materializeRef(operand);
 
     if (!operandRef.has_value()) {
       return emitError(loc) << "local ref not found";
@@ -2609,13 +2609,13 @@
     bool moveRhs =
         vmAnalysis.value().get().isMove(cmpOp.getRhs(), cmpOp.getOperation());
 
-    Optional<Value> refLhs = typeConverter->materializeRef(cmpOp.getLhs());
+    std::optional<Value> refLhs = typeConverter->materializeRef(cmpOp.getLhs());
 
     if (!refLhs.has_value()) {
       return cmpOp.emitError() << "local ref not found";
     }
 
-    Optional<Value> refRhs = typeConverter->materializeRef(cmpOp.getRhs());
+    std::optional<Value> refRhs = typeConverter->materializeRef(cmpOp.getRhs());
 
     if (!refRhs.has_value()) {
       return cmpOp.emitError() << "local ref not found";
@@ -2669,7 +2669,8 @@
     bool move = vmAnalysis.value().get().isMove(cmpOp.getOperand(),
                                                 cmpOp.getOperation());
 
-    Optional<Value> ref = typeConverter->materializeRef(cmpOp.getOperand());
+    std::optional<Value> ref =
+        typeConverter->materializeRef(cmpOp.getOperand());
 
     if (!ref.has_value()) {
       return cmpOp.emitError() << "local ref not found";
@@ -2735,7 +2736,7 @@
     IREE::VM::EmitCTypeConverter *typeConverter =
         getTypeConverter<IREE::VM::EmitCTypeConverter>();
 
-    Optional<Value> ref =
+    std::optional<Value> ref =
         typeConverter->materializeRef(constRefZeroOp.getResult());
 
     if (!ref.has_value()) {
@@ -2802,7 +2803,7 @@
     IREE::VM::EmitCTypeConverter *typeConverter =
         this->template getTypeConverter<IREE::VM::EmitCTypeConverter>();
 
-    Optional<Value> ref =
+    std::optional<Value> ref =
         typeConverter->materializeRef(constRefRodataOp.getResult());
 
     if (!ref.has_value()) {
@@ -2881,8 +2882,10 @@
         assert(operand.getType().isa<IREE::VM::RefType>());
         assert(blockArg.getType().isa<IREE::VM::RefType>());
 
-        Optional<Value> operandRef = typeConverter->materializeRef(operand);
-        Optional<Value> blockArgRef = typeConverter->materializeRef(blockArg);
+        std::optional<Value> operandRef =
+            typeConverter->materializeRef(operand);
+        std::optional<Value> blockArgRef =
+            typeConverter->materializeRef(blockArg);
 
         if (!operandRef.has_value()) {
           return op.emitError() << "local ref not found";
@@ -3041,7 +3044,8 @@
                emitc::PointerType::get(
                    emitc::OpaqueType::get(ctx, "iree_vm_ref_t")));
 
-        Optional<Value> operandRef = typeConverter->materializeRef(operand);
+        std::optional<Value> operandRef =
+            typeConverter->materializeRef(operand);
 
         if (!operandRef.has_value()) {
           return op->emitError() << "local ref not found";
@@ -3341,7 +3345,7 @@
 
     Value localValue = isLoad ? op->getResult(0) : op->getOperand(0);
 
-    Optional<Value> localRef = typeConverter->materializeRef(localValue);
+    std::optional<Value> localRef = typeConverter->materializeRef(localValue);
 
     if (!localRef.has_value()) {
       return op->emitError() << "local ref not found";
@@ -3498,8 +3502,8 @@
         Type objectType =
             originalType.cast<IREE::VM::RefType>().getObjectType();
 
-        Optional<std::pair<StringRef, StringRef>> vmNames =
-            TypeSwitch<Type, Optional<std::pair<StringRef, StringRef>>>(
+        std::optional<std::pair<StringRef, StringRef>> vmNames =
+            TypeSwitch<Type, std::optional<std::pair<StringRef, StringRef>>>(
                 objectType)
                 .Case<IREE::VM::ListType>([&](auto t) {
                   return std::make_pair(StringRef("iree_vm_list_t"),
@@ -3588,7 +3592,7 @@
 
     for (OpResult result : op->getResults()) {
       if (result.getType().isa<IREE::VM::RefType>()) {
-        Optional<Value> ref = typeConverter->materializeRef(result);
+        std::optional<Value> ref = typeConverter->materializeRef(result);
 
         if (!ref.has_value()) {
           return op->emitError() << "local ref not found";
@@ -3637,8 +3641,8 @@
 
     Type objectType =
         op.getType().template cast<IREE::VM::RefType>().getObjectType();
-    Optional<Type> elementType = extractElementType(ctx, objectType);
-    Optional<CNames> cNames = extractCNames(op);
+    std::optional<Type> elementType = extractElementType(ctx, objectType);
+    std::optional<CNames> cNames = extractCNames(op);
 
     if (!elementType.has_value() || !cNames.has_value()) {
       return op.emitError() << "unknown container type";
@@ -3667,7 +3671,7 @@
         /*memberName=*/"allocator",
         /*operand=*/stateArg);
 
-    Optional<SmallVector<Value>> operands = getOperands(
+    std::optional<SmallVector<Value>> operands = getOperands(
         op, adaptor, rewriter, elementType.value(), containerPtr, allocator);
 
     if (!operands.has_value()) {
@@ -3712,7 +3716,7 @@
     return success();
   }
 
-  Optional<Type> extractElementType(MLIRContext *ctx, Type t) const {
+  std::optional<Type> extractElementType(MLIRContext *ctx, Type t) const {
     if (auto listType = t.dyn_cast<IREE::VM::ListType>()) {
       return listType.getElementType();
     } else if (auto bufferType = t.dyn_cast<IREE::VM::BufferType>()) {
@@ -3721,7 +3725,7 @@
     return std::nullopt;
   }
 
-  Optional<CNames> extractCNames(SrcOpTy op) const {
+  std::optional<CNames> extractCNames(SrcOpTy op) const {
     if (isa<IREE::VM::ListAllocOp>(op)) {
       return CNames{"iree_vm_list_t", "iree_vm_list_type_id",
                     "iree_vm_list_create"};
@@ -3735,14 +3739,13 @@
     return std::nullopt;
   }
 
-  Optional<SmallVector<Value>> getOperands(IREE::VM::ListAllocOp op,
-                                           Adaptor adaptor,
-                                           ConversionPatternRewriter &rewriter,
-                                           Type elementType, Value containerPtr,
-                                           Value allocator) const {
+  std::optional<SmallVector<Value>> getOperands(
+      IREE::VM::ListAllocOp op, Adaptor adaptor,
+      ConversionPatternRewriter &rewriter, Type elementType, Value containerPtr,
+      Value allocator) const {
     SmallVector<Value> result;
 
-    Optional<emitc::ApplyOp> elementTypePtrOp =
+    std::optional<emitc::ApplyOp> elementTypePtrOp =
         createVmTypeDefPtr(rewriter, op.getOperation(), elementType);
 
     if (!elementTypePtrOp.has_value()) {
@@ -3759,11 +3762,10 @@
     return result;
   }
 
-  Optional<SmallVector<Value>> getOperands(IREE::VM::BufferAllocOp op,
-                                           Adaptor adaptor,
-                                           ConversionPatternRewriter &rewriter,
-                                           Type elementType, Value containerPtr,
-                                           Value allocator) const {
+  std::optional<SmallVector<Value>> getOperands(
+      IREE::VM::BufferAllocOp op, Adaptor adaptor,
+      ConversionPatternRewriter &rewriter, Type elementType, Value containerPtr,
+      Value allocator) const {
     auto ctx = op.getContext();
     auto loc = op.getLoc();
 
@@ -3792,11 +3794,10 @@
     return result;
   }
 
-  Optional<SmallVector<Value>> getOperands(IREE::VM::BufferCloneOp op,
-                                           Adaptor adaptor,
-                                           ConversionPatternRewriter &rewriter,
-                                           Type elementType, Value containerPtr,
-                                           Value allocator) const {
+  std::optional<SmallVector<Value>> getOperands(
+      IREE::VM::BufferCloneOp op, Adaptor adaptor,
+      ConversionPatternRewriter &rewriter, Type elementType, Value containerPtr,
+      Value allocator) const {
     auto ctx = op.getContext();
     auto loc = op.getLoc();
 
@@ -3859,12 +3860,12 @@
     auto ctx = getOp.getContext();
     auto loc = getOp.getLoc();
 
-    Optional<StringRef> valueTypeEnum;
-    Optional<StringRef> valueExtractor;
+    std::optional<StringRef> valueTypeEnum;
+    std::optional<StringRef> valueExtractor;
 
     std::tie(valueTypeEnum, valueExtractor) =
-        TypeSwitch<Operation *,
-                   std::pair<Optional<StringRef>, Optional<StringRef>>>(
+        TypeSwitch<Operation *, std::pair<std::optional<StringRef>,
+                                          std::optional<StringRef>>>(
             getOp.getOperation())
             .Case<IREE::VM::ListGetI32Op>([&](auto op) {
               return std::make_pair(StringRef("IREE_VM_VALUE_TYPE_I32"),
@@ -4067,8 +4068,8 @@
     auto ctx = setOp.getContext();
     auto loc = setOp.getLoc();
 
-    Optional<StringRef> valueConstructor =
-        TypeSwitch<Operation *, Optional<StringRef>>(setOp.getOperation())
+    std::optional<StringRef> valueConstructor =
+        TypeSwitch<Operation *, std::optional<StringRef>>(setOp.getOperation())
             .Case<IREE::VM::ListSetI32Op>(
                 [&](auto op) { return StringRef("iree_vm_value_make_i32"); })
             .template Case<IREE::VM::ListSetI64Op>(
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp
index 9ef60f3..dc29462 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp
@@ -112,7 +112,7 @@
 }
 
 Value allocateVariable(OpBuilder builder, Location location, Type type,
-                       Optional<StringRef> initializer) {
+                       std::optional<StringRef> initializer) {
   auto ctx = builder.getContext();
   return builder
       .create<emitc::VariableOp>(
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.h b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.h
index c81d327..98fb58a 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.h
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.h
@@ -66,7 +66,7 @@
                      Value lhs, Value rhs, Type resultType);
 
 Value allocateVariable(OpBuilder builder, Location location, Type type,
-                       Optional<StringRef> initializer = std::nullopt);
+                       std::optional<StringRef> initializer = std::nullopt);
 
 Value addressOf(OpBuilder builder, Location location, Value operand);
 
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCTypeConverter.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCTypeConverter.cpp
index ba3d133..3d0e886 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCTypeConverter.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCTypeConverter.cpp
@@ -29,7 +29,7 @@
     assert(inputs.size() == 1);
     assert(inputs[0].getType().isa<IREE::VM::RefType>());
     Value ref = inputs[0];
-    Optional<Value> result = materializeRef(ref);
+    std::optional<Value> result = materializeRef(ref);
     return result.has_value() ? result.value() : Value{};
   });
 
@@ -128,7 +128,7 @@
 
 // TODO(simon-camp): Make this a target materialization and cleanup the call
 // sites in the conversion.
-Optional<Value> EmitCTypeConverter::materializeRef(Value ref) {
+std::optional<Value> EmitCTypeConverter::materializeRef(Value ref) {
   assert(ref.getType().isa<IREE::VM::RefType>());
 
   mlir::func::FuncOp funcOp;
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCTypeConverter.h b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCTypeConverter.h
index d9f6469..2500eb1 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCTypeConverter.h
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCTypeConverter.h
@@ -29,7 +29,7 @@
       IREE::VM::FuncOp &funcOp) {
     return lookupAnalysis(funcOp.getOperation());
   }
-  Optional<Value> materializeRef(Value ref);
+  std::optional<Value> materializeRef(Value ref);
 
   // This is the same as convertType, but returns `iree_vm_ref_t` rather than a
   // pointer to it for `vm.ref` types.
diff --git a/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td b/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td
index d7d8425..43019ab 100644
--- a/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td
+++ b/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td
@@ -349,7 +349,7 @@
   let builders = [
     OpBuilder<(ins
       "StringRef":$name, "bool":$isMutable, "Type":$type,
-      "Optional<TypedAttr>":$initialValue,
+      "std::optional<TypedAttr>":$initialValue,
       CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs
     ),
     [{
diff --git a/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/ArchiveWriter.cpp b/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/ArchiveWriter.cpp
index 35fa86a..8f2d630 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/ArchiveWriter.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/ArchiveWriter.cpp
@@ -357,7 +357,7 @@
 // appendZIPFile implementation used when |os| is a stream without random
 // access (like stdout). This requires us to serialize the file twice in order
 // to compute the total length and CRC32.
-static Optional<ZIPFileRef> appendZIPFileToStream(
+static std::optional<ZIPFileRef> appendZIPFileToStream(
     std::string fileName, uint64_t filePadding, uint64_t fileLength,
     std::function<LogicalResult(llvm::raw_ostream &os)> write,
     llvm::raw_ostream &os) {
@@ -416,7 +416,7 @@
 // appendZIPFile implementation used when |os| is a file with random access.
 // This allows us to write the header and backpatch the CRC computed while while
 // serializing the file contents.
-static Optional<ZIPFileRef> appendZIPFileToFD(
+static std::optional<ZIPFileRef> appendZIPFileToFD(
     std::string fileName, uint64_t filePadding, uint64_t fileLength,
     std::function<LogicalResult(llvm::raw_ostream &os)> write,
     llvm::raw_fd_ostream &os) {
@@ -450,7 +450,7 @@
 // Appends a file wrapped in a ZIP header and data descriptor.
 // |write| is used to stream the file contents to |os| while also capturing its
 // CRC as required for the central directory.
-static Optional<ZIPFileRef> appendZIPFile(
+static std::optional<ZIPFileRef> appendZIPFile(
     std::string fileName, uint64_t filePadding, uint64_t fileLength,
     std::function<LogicalResult(llvm::raw_ostream &os)> write,
     llvm::raw_ostream &os) {
diff --git a/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeEncoder.cpp b/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeEncoder.cpp
index 9dedbdb..8256031 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeEncoder.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeEncoder.cpp
@@ -258,7 +258,7 @@
     return success();
   }
 
-  Optional<std::vector<uint8_t>> finish() {
+  std::optional<std::vector<uint8_t>> finish() {
     if (failed(fixupOffsets())) {
       return std::nullopt;
     }
@@ -343,7 +343,7 @@
 }  // namespace
 
 // static
-Optional<EncodedBytecodeFunction> BytecodeEncoder::encodeFunction(
+std::optional<EncodedBytecodeFunction> BytecodeEncoder::encodeFunction(
     IREE::VM::FuncOp funcOp, llvm::DenseMap<Type, int> &typeTable,
     SymbolTable &symbolTable, DebugDatabaseBuilder &debugDatabase) {
   EncodedBytecodeFunction result;
diff --git a/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeEncoder.h b/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeEncoder.h
index d4730a9..5ac4157 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeEncoder.h
+++ b/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeEncoder.h
@@ -44,7 +44,7 @@
 
   // Encodes a vm.func to bytecode and returns the result.
   // Returns None on failure.
-  static Optional<EncodedBytecodeFunction> encodeFunction(
+  static std::optional<EncodedBytecodeFunction> encodeFunction(
       IREE::VM::FuncOp funcOp, llvm::DenseMap<Type, int> &typeTable,
       SymbolTable &symbolTable, DebugDatabaseBuilder &debugDatabase);
 
diff --git a/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeModuleTarget.cpp b/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeModuleTarget.cpp
index 2ab87eb..f31afe8 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeModuleTarget.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeModuleTarget.cpp
@@ -76,7 +76,7 @@
   // Total size of the serialized data in bytes.
   uint64_t totalSize = 0;
   // Optional reference to the rodata in the file.
-  Optional<ArchiveWriter::File> archiveFile;
+  std::optional<ArchiveWriter::File> archiveFile;
 };
 
 }  // namespace
diff --git a/compiler/src/iree/compiler/Dialect/VM/Transforms/OrdinalAllocation.cpp b/compiler/src/iree/compiler/Dialect/VM/Transforms/OrdinalAllocation.cpp
index 785b637..9e0da25 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Transforms/OrdinalAllocation.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Transforms/OrdinalAllocation.cpp
@@ -63,7 +63,7 @@
     SmallVector<SmallVector<IREE::Util::GlobalOpInterface, 4>, 8>
         primitiveGlobalOps(sizeof(int64_t) + 1);
     for (auto &op : getOperation().getBlock().getOperations()) {
-      Optional<int> ordinal = std::nullopt;
+      std::optional<int> ordinal = std::nullopt;
       if (auto funcOp = dyn_cast<FuncOp>(op)) {
         ordinal = nextFuncOrdinal++;
       } else if (isa<ExportOp>(op)) {
diff --git a/compiler/src/iree/compiler/Dialect/VM/Utils/CallingConvention.cpp b/compiler/src/iree/compiler/Dialect/VM/Utils/CallingConvention.cpp
index ca50f41..8d9bb4c 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Utils/CallingConvention.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Utils/CallingConvention.cpp
@@ -74,7 +74,7 @@
   return result;
 }
 
-Optional<std::string> makeImportCallingConventionString(
+std::optional<std::string> makeImportCallingConventionString(
     IREE::VM::ImportOp importOp) {
   auto functionType = importOp.getFunctionType();
   if (functionType.getNumInputs() == 0 && functionType.getNumResults() == 0) {
@@ -113,7 +113,8 @@
   return std::string(s.data(), s.size());
 }
 
-Optional<std::string> makeCallingConventionString(IREE::VM::FuncOp funcOp) {
+std::optional<std::string> makeCallingConventionString(
+    IREE::VM::FuncOp funcOp) {
   auto functionType = funcOp.getFunctionType();
   if (functionType.getNumInputs() == 0 && functionType.getNumResults() == 0) {
     return std::string("0v_v");  // Valid but empty.
diff --git a/compiler/src/iree/compiler/Dialect/VM/Utils/CallingConvention.h b/compiler/src/iree/compiler/Dialect/VM/Utils/CallingConvention.h
index 64d5b11..1d17eca 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Utils/CallingConvention.h
+++ b/compiler/src/iree/compiler/Dialect/VM/Utils/CallingConvention.h
@@ -20,12 +20,12 @@
 // This differs from makeCallingConventionString in that it supports variadic
 // arguments. Ideally we'd combine the two, but we only have this additional
 // metadata on IREE::VM::ImportOp.
-Optional<std::string> makeImportCallingConventionString(
+std::optional<std::string> makeImportCallingConventionString(
     IREE::VM::ImportOp importOp);
 
 // Generates a string encoding the function type for defining the
 // FunctionSignatureDef::calling_convention field for internal/export functions.
-Optional<std::string> makeCallingConventionString(IREE::VM::FuncOp funcOp);
+std::optional<std::string> makeCallingConventionString(IREE::VM::FuncOp funcOp);
 
 }  // namespace VM
 }  // namespace IREE
diff --git a/compiler/src/iree/compiler/Dialect/VMVX/Conversion/VMVXToVM/ConvertVMVXToVM.cpp b/compiler/src/iree/compiler/Dialect/VMVX/Conversion/VMVXToVM/ConvertVMVXToVM.cpp
index 19a8fae..0501ce3 100644
--- a/compiler/src/iree/compiler/Dialect/VMVX/Conversion/VMVXToVM/ConvertVMVXToVM.cpp
+++ b/compiler/src/iree/compiler/Dialect/VMVX/Conversion/VMVXToVM/ConvertVMVXToVM.cpp
@@ -75,7 +75,7 @@
 
  protected:
   virtual std::string getImportFqName(T op) const = 0;
-  virtual Optional<SmallVector<Value>> emitCall(
+  virtual std::optional<SmallVector<Value>> emitCall(
       T op, typename T::Adaptor adaptor, IREE::VM::ImportOp importOp,
       ConversionPatternRewriter &rewriter) const {
     return rewriteToCall(op, adaptor, importOp, typeConverter, rewriter);
diff --git a/compiler/src/iree/compiler/Dialect/Vulkan/IR/VulkanAttributes.cpp b/compiler/src/iree/compiler/Dialect/Vulkan/IR/VulkanAttributes.cpp
index 2450894..a69691c 100644
--- a/compiler/src/iree/compiler/Dialect/Vulkan/IR/VulkanAttributes.cpp
+++ b/compiler/src/iree/compiler/Dialect/Vulkan/IR/VulkanAttributes.cpp
@@ -223,7 +223,7 @@
 
     MLIRContext *context = parser.getContext();
     auto processExtension = [&](llvm::SMLoc loc, StringRef extension) {
-      if (Optional<Extension> symbol = symbolizeExtension(extension)) {
+      if (std::optional<Extension> symbol = symbolizeExtension(extension)) {
         extensions.push_back(ExtensionAttr::get(context, *symbol));
         return success();
       }
diff --git a/compiler/src/iree/compiler/Dialect/Vulkan/IR/VulkanAttributes.td b/compiler/src/iree/compiler/Dialect/Vulkan/IR/VulkanAttributes.td
index 793bc4f..5fd7cf7 100644
--- a/compiler/src/iree/compiler/Dialect/Vulkan/IR/VulkanAttributes.td
+++ b/compiler/src/iree/compiler/Dialect/Vulkan/IR/VulkanAttributes.td
@@ -77,8 +77,8 @@
     //
     // This corresponds to the `VkPhysicalDeviceSubgroupSizeControlProperties` structure:
     // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceSubgroupSizeControlPropertiesEXT.html
-    OptionalParameter<"::llvm::Optional<int>">:$minSubgroupSize,
-    OptionalParameter<"::llvm::Optional<int>">:$maxSubgroupSize,
+    OptionalParameter<"::std::optional<int>">:$minSubgroupSize,
+    OptionalParameter<"::std::optional<int>">:$maxSubgroupSize,
 
     // VK_KHR_16bit_storage features.
     //
diff --git a/compiler/src/iree/compiler/Dialect/Vulkan/Utils/TargetTriple.cpp b/compiler/src/iree/compiler/Dialect/Vulkan/Utils/TargetTriple.cpp
index c7e495f..a29d9d4 100644
--- a/compiler/src/iree/compiler/Dialect/Vulkan/Utils/TargetTriple.cpp
+++ b/compiler/src/iree/compiler/Dialect/Vulkan/Utils/TargetTriple.cpp
@@ -210,7 +210,7 @@
 
   int subgroupSize = 32;
   SubgroupFeature subgroupFeatures = SubgroupFeature::Basic;
-  Optional<int> minSubgroupSize, maxSubgroupSize;
+  std::optional<int> minSubgroupSize, maxSubgroupSize;
 
   bool shaderFloat16 = false, shaderFloat64 = false;
   bool shaderInt8 = false, shaderInt16 = false, shaderInt64 = false;
diff --git a/compiler/src/iree/compiler/InputConversion/Common/ImportMLProgram.cpp b/compiler/src/iree/compiler/InputConversion/Common/ImportMLProgram.cpp
index 4e72070..f458430 100644
--- a/compiler/src/iree/compiler/InputConversion/Common/ImportMLProgram.cpp
+++ b/compiler/src/iree/compiler/InputConversion/Common/ImportMLProgram.cpp
@@ -80,7 +80,7 @@
     auto srcOpAttr = srcOp.getValue();
     auto srcOpTypedAttr =
         srcOpAttr.has_value()
-            ? Optional<TypedAttr>(srcOpAttr.value().cast<TypedAttr>())
+            ? std::optional<TypedAttr>(srcOpAttr.value().cast<TypedAttr>())
             : std::nullopt;
     const bool isMutable = srcOp.getIsMutable();
     const SymbolTable::Visibility visibility = srcOp.getVisibility();
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/BroadcastingToLinalgPatterns.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/BroadcastingToLinalgPatterns.cpp
index 166748c..14d8a0f 100644
--- a/compiler/src/iree/compiler/InputConversion/MHLO/BroadcastingToLinalgPatterns.cpp
+++ b/compiler/src/iree/compiler/InputConversion/MHLO/BroadcastingToLinalgPatterns.cpp
@@ -144,10 +144,11 @@
   return broadcast(builder, loc, scalarValue, resultExtents, isExpansion);
 }
 
-Optional<Extent> computeBinaryResultExtent(OpBuilder &builder, Location loc,
-                                           Extent &lhsDim, Extent &rhsDim,
-                                           bool &isLhsExpansion,
-                                           bool &isRhsExpansion) {
+std::optional<Extent> computeBinaryResultExtent(OpBuilder &builder,
+                                                Location loc, Extent &lhsDim,
+                                                Extent &rhsDim,
+                                                bool &isLhsExpansion,
+                                                bool &isRhsExpansion) {
   if (lhsDim.isStatic() && rhsDim.isStatic()) {
     // Both are static. Just check.
     if (lhsDim.getStatic() != rhsDim.getStatic() &&
@@ -214,11 +215,12 @@
   return Extent(lhsExtentValue);
 }
 
-Optional<Extent> computeTernaryResultExtent(OpBuilder &builder, Location loc,
-                                            Extent &aValue, Extent &bValue,
-                                            Extent &cValue, bool &isAExpansion,
-                                            bool &isBExpansion,
-                                            bool &isCExpansion) {
+std::optional<Extent> computeTernaryResultExtent(OpBuilder &builder,
+                                                 Location loc, Extent &aValue,
+                                                 Extent &bValue, Extent &cValue,
+                                                 bool &isAExpansion,
+                                                 bool &isBExpansion,
+                                                 bool &isCExpansion) {
   // Collect non unit extents (which includes, implicitly, dynamic dims).
   SmallVector<Extent> nonUnitExtents;
   if (!aValue.isUnitExtent()) nonUnitExtents.push_back(aValue);
@@ -430,7 +432,7 @@
                                    BroadcastValues broadcastValues,
                                    OpBuilder &builder) override {
     chlo::BroadcastCompareOpAdaptor adaptor(operands, op->getAttrDictionary());
-    Optional<chlo::ComparisonType> chloCmpType = adaptor.getCompareType();
+    std::optional<chlo::ComparisonType> chloCmpType = adaptor.getCompareType();
     mhlo::ComparisonTypeAttr mhloCmpType;
     if (chloCmpType)
       mhloCmpType = mhlo::ComparisonTypeAttr::get(
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertComplexToReal.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/ConvertComplexToReal.cpp
index c87a06b..a16a584 100644
--- a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertComplexToReal.cpp
+++ b/compiler/src/iree/compiler/InputConversion/MHLO/ConvertComplexToReal.cpp
@@ -19,7 +19,7 @@
 
 namespace {
 
-inline llvm::Optional<chlo::ComparisonDirection> chloComparisonDirection(
+inline std::optional<chlo::ComparisonDirection> chloComparisonDirection(
     mhlo::ComparisonDirection value) {
   switch (value) {
     case mhlo::ComparisonDirection::EQ:
@@ -39,7 +39,7 @@
   }
 }
 
-inline llvm::Optional<chlo::ComparisonType> chloComparisonType(
+inline std::optional<chlo::ComparisonType> chloComparisonType(
     mhlo::ComparisonType value) {
   switch (value) {
     case mhlo::ComparisonType::NOTYPE:
@@ -345,7 +345,7 @@
     chlo::ComparisonDirection chloCmpDirection =
         *chloComparisonDirection(adaptor.getComparisonDirection());
 
-    Optional<mhlo::ComparisonType> mhloCmpType = adaptor.getCompareType();
+    std::optional<mhlo::ComparisonType> mhloCmpType = adaptor.getCompareType();
     chlo::ComparisonTypeAttr chloCmpType;
     if (mhloCmpType)
       chloCmpType = chlo::ComparisonTypeAttr::get(
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToLinalgExt.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToLinalgExt.cpp
index 47e78e3..07a5948 100644
--- a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToLinalgExt.cpp
+++ b/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToLinalgExt.cpp
@@ -41,7 +41,8 @@
                           intType.getIntOrFloatBitWidth());
 }
 
-static Optional<Type> convertRank0TensorToScalar(RankedTensorType tensorType) {
+static std::optional<Type> convertRank0TensorToScalar(
+    RankedTensorType tensorType) {
   if (tensorType.getRank() != 0) return std::nullopt;
   Type elementType = tensorType.getElementType();
   if (auto intType = elementType.dyn_cast<IntegerType>()) {
@@ -56,8 +57,8 @@
   return shapedType;
 }
 
-static Optional<Value> materializeCast(OpBuilder &builder, Type toType,
-                                       ValueRange inputs, Location loc) {
+static std::optional<Value> materializeCast(OpBuilder &builder, Type toType,
+                                            ValueRange inputs, Location loc) {
   assert(inputs.size() == 1 && "too many inputs to type conversion");
   Value fromValue = inputs[0];
   auto fromType = fromValue.getType().dyn_cast<RankedTensorType>();
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/MHLOToLinalgOnTensors.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/MHLOToLinalgOnTensors.cpp
index ea51f00..353ee69 100644
--- a/compiler/src/iree/compiler/InputConversion/MHLO/MHLOToLinalgOnTensors.cpp
+++ b/compiler/src/iree/compiler/InputConversion/MHLO/MHLOToLinalgOnTensors.cpp
@@ -323,8 +323,8 @@
   }
 };
 
-llvm::Optional<Value> scalarToTensor(OpBuilder &builder, Type /*type*/,
-                                     ValueRange inputs, Location loc) {
+std::optional<Value> scalarToTensor(OpBuilder &builder, Type /*type*/,
+                                    ValueRange inputs, Location loc) {
   assert(inputs.size() == 1);
   if (inputs.front().getType().isa<ShapedType>()) {
     return std::nullopt;
diff --git a/compiler/src/iree/compiler/Utils/ModuleUtils.cpp b/compiler/src/iree/compiler/Utils/ModuleUtils.cpp
index 9b78231..4963203 100644
--- a/compiler/src/iree/compiler/Utils/ModuleUtils.cpp
+++ b/compiler/src/iree/compiler/Utils/ModuleUtils.cpp
@@ -17,7 +17,7 @@
 namespace mlir {
 namespace iree_compiler {
 
-static llvm::Optional<FileLineColLoc> findFirstFileLoc(Location baseLoc) {
+static std::optional<FileLineColLoc> findFirstFileLoc(Location baseLoc) {
   if (auto loc = baseLoc.dyn_cast<FusedLoc>()) {
     for (auto &childLoc : loc.getLocations()) {
       auto childResult = findFirstFileLoc(childLoc);
diff --git a/integrations/tensorflow/iree-dialects/include/iree-dialects/Dialect/Input/InputOps.td b/integrations/tensorflow/iree-dialects/include/iree-dialects/Dialect/Input/InputOps.td
index d3847e1..8170ed6 100644
--- a/integrations/tensorflow/iree-dialects/include/iree-dialects/Dialect/Input/InputOps.td
+++ b/integrations/tensorflow/iree-dialects/include/iree-dialects/Dialect/Input/InputOps.td
@@ -97,7 +97,7 @@
       "StringRef":$name,
       "bool":$isMutable,
       "Type":$type,
-      "Optional<TypedAttr>":$initialValue,
+      "std::optional<TypedAttr>":$initialValue,
       CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs
     )>,
     OpBuilder<(ins
diff --git a/integrations/tensorflow/iree-dialects/lib/Dialect/Input/InputOps.cpp b/integrations/tensorflow/iree-dialects/lib/Dialect/Input/InputOps.cpp
index 4f7523b..cd5d44a 100644
--- a/integrations/tensorflow/iree-dialects/lib/Dialect/Input/InputOps.cpp
+++ b/integrations/tensorflow/iree-dialects/lib/Dialect/Input/InputOps.cpp
@@ -98,7 +98,7 @@
 
 void GlobalOp::build(OpBuilder &builder, OperationState &result, StringRef name,
                      bool isMutable, Type type,
-                     Optional<TypedAttr> initialValue,
+                     std::optional<TypedAttr> initialValue,
                      ArrayRef<NamedAttribute> attrs) {
   result.addAttribute(SymbolTable::getSymbolAttrName(),
                       builder.getStringAttr(name));
diff --git a/integrations/tensorflow/iree_tf_compiler/MHLO/EmitDefaultIREEABI.cpp b/integrations/tensorflow/iree_tf_compiler/MHLO/EmitDefaultIREEABI.cpp
index 811340f..97edaef 100644
--- a/integrations/tensorflow/iree_tf_compiler/MHLO/EmitDefaultIREEABI.cpp
+++ b/integrations/tensorflow/iree_tf_compiler/MHLO/EmitDefaultIREEABI.cpp
@@ -95,7 +95,7 @@
     return flattened;
   }
 
-  llvm::Optional<json::Value> mapTypeToJsonTypeRecord(Type type) {
+  std::optional<json::Value> mapTypeToJsonTypeRecord(Type type) {
     if (auto shapedType = type.dyn_cast<ShapedType>()) {
       auto typeValue = mapTypeToJsonTypeRecord(shapedType.getElementType());
       json::Array record({
diff --git a/integrations/tensorflow/iree_tf_compiler/iree-import-xla-main.cpp b/integrations/tensorflow/iree_tf_compiler/iree-import-xla-main.cpp
index a886824..c2aa44a 100644
--- a/integrations/tensorflow/iree_tf_compiler/iree-import-xla-main.cpp
+++ b/integrations/tensorflow/iree_tf_compiler/iree-import-xla-main.cpp
@@ -147,7 +147,7 @@
   cl::ParseCommandLineOptions(argc, argv);
 
   auto openInputStream =
-      [&]() -> llvm::Optional<
+      [&]() -> std::optional<
                 std::pair<std::istream *, std::unique_ptr<std::ifstream>>> {
     auto fileInputStream = std::make_unique<std::ifstream>();
     std::istream *inputStream;
diff --git a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/Input/InputOps.td b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/Input/InputOps.td
index d3847e1..8170ed6 100644
--- a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/Input/InputOps.td
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/Input/InputOps.td
@@ -97,7 +97,7 @@
       "StringRef":$name,
       "bool":$isMutable,
       "Type":$type,
-      "Optional<TypedAttr>":$initialValue,
+      "std::optional<TypedAttr>":$initialValue,
       CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs
     )>,
     OpBuilder<(ins
diff --git a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/LinalgExt/IR/LinalgExtOps.td b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/LinalgExt/IR/LinalgExtOps.td
index ce99616..82b304b 100644
--- a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/LinalgExt/IR/LinalgExtOps.td
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/LinalgExt/IR/LinalgExtOps.td
@@ -482,7 +482,7 @@
     Value values() {
       return getInputOperand(0)->get();
     }
-    Optional<Value> indices() {
+    std::optional<Value> indices() {
       if (getNumInputs() < 2) {
         return {};
       } else {
@@ -594,7 +594,7 @@
     OpBuilder<(ins "Value":$source, "Value":$output,
       "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/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/LinalgExt/Passes/Passes.h b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/LinalgExt/Passes/Passes.h
index df5e1f5..ae2490e 100644
--- a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/LinalgExt/Passes/Passes.h
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/LinalgExt/Passes/Passes.h
@@ -39,11 +39,11 @@
 
   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;
@@ -78,7 +78,7 @@
 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;
diff --git a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/LinalgExt/Transforms/Transforms.h b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/LinalgExt/Transforms/Transforms.h
index efba8ab..398a356 100644
--- a/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/LinalgExt/Transforms/Transforms.h
+++ b/llvm-external-projects/iree-dialects/include/iree-dialects/Dialect/LinalgExt/Transforms/Transforms.h
@@ -345,7 +345,7 @@
     // the op and deleting the previous op. This
     // needs more investigation.
     rewriter.startRootUpdate(op);
-    Optional<linalg::LinalgOp> promotedOp =
+    std::optional<linalg::LinalgOp> promotedOp =
         promoteSubViews(rewriter, op, options);
     if (!promotedOp) {
       rewriter.cancelRootUpdate(op);
@@ -480,7 +480,8 @@
 FailureOr<linalg::TileLoopNest> tileConsumerAndFuseProducers(
     OpBuilder &b, linalg::LinalgOp consumerOp, ArrayRef<int64_t> tileSizes,
     ArrayRef<int64_t> tileInterchange,
-    const Optional<linalg::LinalgLoopDistributionOptions> &tileDistribution);
+    const std::optional<linalg::LinalgLoopDistributionOptions>
+        &tileDistribution);
 
 } // namespace LinalgExt
 } // namespace IREE
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/Input/InputOps.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/Input/InputOps.cpp
index 4f7523b..cd5d44a 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/Input/InputOps.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/Input/InputOps.cpp
@@ -98,7 +98,7 @@
 
 void GlobalOp::build(OpBuilder &builder, OperationState &result, StringRef name,
                      bool isMutable, Type type,
-                     Optional<TypedAttr> initialValue,
+                     std::optional<TypedAttr> initialValue,
                      ArrayRef<NamedAttribute> attrs) {
   result.addAttribute(SymbolTable::getSymbolAttrName(),
                       builder.getStringAttr(name));
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/IR/LinalgExtOps.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/IR/LinalgExtOps.cpp
index 1417860..d00a15e 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/IR/LinalgExtOps.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/IR/LinalgExtOps.cpp
@@ -1508,7 +1508,7 @@
       continue;
     auto it = dimAndTileMapping.find(dim);
     if (it != dimAndTileMapping.end()) {
-      Optional<int64_t> constantTile = getConstantIntValue(it->second);
+      std::optional<int64_t> constantTile = getConstantIntValue(it->second);
       if (!constantTile)
         continue;
       if (inputShape[dim] % (*constantTile) != 0)
@@ -1645,7 +1645,7 @@
           llvm::zip(packedType.getShape().take_back(mixedTiles.size()),
                     mixedTiles),
           [](std::tuple<int64_t, OpFoldResult> it) {
-            Optional<int64_t> constTileSize =
+            std::optional<int64_t> constTileSize =
                 getConstantIntValue(std::get<1>(it));
             int64_t shape = std::get<0>(it);
             if (!constTileSize) {
@@ -1677,7 +1677,7 @@
 void PackOp::build(OpBuilder &builder, OperationState &state, Value source,
                    Value output, 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/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/MaterializeEncoding.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/MaterializeEncoding.cpp
index 37f2a24..747244b 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/MaterializeEncoding.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/MaterializeEncoding.cpp
@@ -27,7 +27,7 @@
 //===---------------------------------------------------------------------===//
 
 /// Extract encoding from the `tensorType` if specified.
-static Optional<TensorEncoding> getEncoding(RankedTensorType tensorType) {
+static std::optional<TensorEncoding> getEncoding(RankedTensorType tensorType) {
   auto encodingAttr = tensorType.getEncoding().dyn_cast_or_null<EncodingAttr>();
   if (!encodingAttr)
     return std::nullopt;
@@ -40,7 +40,7 @@
 static RankedTensorType
 getMaterializedType(RankedTensorType tensorType,
                     MaterializeEncodingFn materializeEncodingFn) {
-  Optional<TensorEncoding> encoding = getEncoding(tensorType);
+  std::optional<TensorEncoding> encoding = getEncoding(tensorType);
   if (!encoding)
     return tensorType;
   FailureOr<MaterializeEncodingInfo> materializeEncodingInfo =
@@ -72,7 +72,7 @@
 // iree/compiler/src/iree/compiler/Codegen/Common/MaterializeEncodingPass.cpp
 static FailureOr<MaterializeEncodingInfo>
 chooseEncodingInfo(RankedTensorType tensorType) {
-  Optional<TensorEncoding> encoding = getEncoding(tensorType);
+  std::optional<TensorEncoding> encoding = getEncoding(tensorType);
   if (!encoding)
     return failure();
   switch (*encoding) {
@@ -101,7 +101,7 @@
 /// Utility method to get the optional padding value to use with pack operation
 /// if source is defined using a `tensor.pad` operation. Note `source` is
 /// passed by reference. It is updated to use the source of the pad operation.
-static Optional<Value> getPaddingValue(Value &source) {
+static std::optional<Value> getPaddingValue(Value &source) {
   auto padOp = source.getDefiningOp<tensor::PadOp>();
   if (!padOp || padOp.getNofold() || !padOp.hasZeroLowPad())
     return std::nullopt;
@@ -137,7 +137,7 @@
     return rewriter.notifyMatchFailure(
         encodingOp, "failed to generate runtime tile size query");
   }
-  Optional<TensorEncoding> encoding = getEncoding(resultType);
+  std::optional<TensorEncoding> encoding = getEncoding(resultType);
   if (!encoding)
     return failure();
   SmallVector<OpFoldResult> resultDims = tensor::PackOp::getResultShape(
@@ -146,7 +146,7 @@
       materializeEncodingInfo->outerDimsPerm);
   auto emptyOp = rewriter.create<tensor::EmptyOp>(loc, resultDims,
                                                   resultType.getElementType());
-  Optional<Value> paddingValue = getPaddingValue(source);
+  std::optional<Value> paddingValue = getPaddingValue(source);
   auto packOp = rewriter.create<tensor::PackOp>(
       loc, source, emptyOp, materializeEncodingInfo->innerDimsPos,
       *innerTileSizesOfr, paddingValue, materializeEncodingInfo->outerDimsPerm);
@@ -208,11 +208,11 @@
     return failure();
   auto inputs = matmulOp.getDpsInputOperands();
   auto outputs = matmulOp.getDpsInitOperands();
-  Optional<TensorEncoding> lhsEncoding =
+  std::optional<TensorEncoding> lhsEncoding =
       getEncoding(inputs[0]->get().getType().cast<RankedTensorType>());
-  Optional<TensorEncoding> rhsEncoding =
+  std::optional<TensorEncoding> rhsEncoding =
       getEncoding(inputs[1]->get().getType().cast<RankedTensorType>());
-  Optional<TensorEncoding> resultEncoding =
+  std::optional<TensorEncoding> resultEncoding =
       getEncoding(outputs[0]->get().getType().cast<RankedTensorType>());
   if (!lhsEncoding ||
       (lhsEncoding.value() != TensorEncoding::MATMUL_F32F32F32_LHS &&
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/Passes.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/Passes.cpp
index c6b01d9..ba7408a 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/Passes.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/Passes.cpp
@@ -24,13 +24,14 @@
     "__internal_linalg_transform__";
 
 LinalgTransformationFilter::LinalgTransformationFilter(
-    ArrayRef<StringAttr> matchDisjunction, Optional<StringAttr> replacement)
+    ArrayRef<StringAttr> matchDisjunction,
+    std::optional<StringAttr> replacement)
     : matchDisjunction(matchDisjunction.begin(), matchDisjunction.end()),
       replacement(replacement), matchByDefault(false) {}
 
 LinalgTransformationFilter::LinalgTransformationFilter(
     const FilterFunction &f, ArrayRef<StringAttr> matchDisjunction,
-    Optional<StringAttr> replacement)
+    std::optional<StringAttr> replacement)
     : matchDisjunction(matchDisjunction.begin(), matchDisjunction.end()),
       replacement(replacement), matchByDefault(false) {
   if (f)
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/SplitReduction.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/SplitReduction.cpp
index d36abd3..c99d4e8 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/SplitReduction.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/SplitReduction.cpp
@@ -117,8 +117,8 @@
       loc, valuesExpandedType, valuesOrig, reassociationIndices);
 
   // Expand input indices shape for parallel processing if they exist
-  Optional<Value> indicesExpanded;
-  if (Optional<Value> inputIndices = topkOp.indices()) {
+  std::optional<Value> indicesExpanded;
+  if (std::optional<Value> inputIndices = topkOp.indices()) {
     // Type inputElementType = inputIndices->getType().cast<ShapedType>();
     Type indicesExpandedType =
         RankedTensorType::get(expandedShape, indicesElementType);
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/Tiling.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/Tiling.cpp
index 882ffe2..ae77fb3 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/Tiling.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Passes/Tiling.cpp
@@ -56,7 +56,7 @@
 /// converted to an `IntegerAttr` of that value. So here just return true if
 /// this is an attribute with a zero value.
 static bool isUntiledLoop(OpFoldResult valueOrAttr) {
-  Optional<int64_t> intVal = getConstantIntValue(valueOrAttr);
+  std::optional<int64_t> intVal = getConstantIntValue(valueOrAttr);
   return intVal && *intVal == 0;
 }
 
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Transforms/Transforms.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Transforms/Transforms.cpp
index 17a670a..ddbca39 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Transforms/Transforms.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/Transforms/Transforms.cpp
@@ -43,7 +43,8 @@
 FailureOr<linalg::TileLoopNest> tileConsumerAndFuseProducers(
     OpBuilder &b, linalg::LinalgOp consumerOp, ArrayRef<int64_t> tileSizes,
     ArrayRef<int64_t> tileInterchange,
-    const Optional<linalg::LinalgLoopDistributionOptions> &tileDistribution) {
+    const std::optional<linalg::LinalgLoopDistributionOptions>
+        &tileDistribution) {
   assert(tileSizes.size() == tileInterchange.size() &&
          "expect the number of tile sizes and interchange dims to match");
   assert(isPermutationVector(tileInterchange) &&
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgTransform/IR/LinalgTransformOps.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgTransform/IR/LinalgTransformOps.cpp
index a64f64e..619aa68 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgTransform/IR/LinalgTransformOps.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgTransform/IR/LinalgTransformOps.cpp
@@ -70,7 +70,7 @@
 //===---------------------------------------------------------------------===//
 
 void linalg::transform::ScopeOp::getSuccessorRegions(
-    Optional<unsigned> index, ArrayRef<Attribute> operands,
+    std::optional<unsigned> index, ArrayRef<Attribute> operands,
     SmallVectorImpl<RegionSuccessor> &regions) {
   if (index)
     regions.emplace_back(getResults());
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgTransform/Passes/ExpertExpansion.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgTransform/Passes/ExpertExpansion.cpp
index 72a3350..66b6b0c 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgTransform/Passes/ExpertExpansion.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgTransform/Passes/ExpertExpansion.cpp
@@ -85,7 +85,7 @@
 
     ModuleOp strategyModule = nullptr;
     for (auto nestedModule : module.getOps<ModuleOp>()) {
-      Optional<StringRef> name = nestedModule.getSymName();
+      std::optional<StringRef> name = nestedModule.getSymName();
       if (!name)
         continue;
 
diff --git a/llvm-external-projects/iree-dialects/lib/Transforms/ListenerCSE.cpp b/llvm-external-projects/iree-dialects/lib/Transforms/ListenerCSE.cpp
index e8e6943..3363cc0 100644
--- a/llvm-external-projects/iree-dialects/lib/Transforms/ListenerCSE.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Transforms/ListenerCSE.cpp
@@ -436,7 +436,7 @@
                                     RewriterBase::Listener *listener) {
   assert(op->hasTrait<OpTrait::IsIsolatedFromAbove>() &&
          "can only do CSE on isolated-from-above ops");
-  Optional<DominanceInfo> defaultDomInfo;
+  std::optional<DominanceInfo> defaultDomInfo;
   if (domInfo == nullptr) {
     defaultDomInfo.emplace(op);
     domInfo = &*defaultDomInfo;