Integrate llvm-project and bump dependencies 20221213 (#11552)

Integrate llvm-project and bump dependencies
    
* llvm-project: fd21361a7942
* mlir-hlo: 8919c4f83416b2bab914cc8a800137b7615f1cbd
* tensorflow: aaca45a9df96b1401ae49928c8bcc2578379f77d

Fix several issues including:
* using std::nullopt
* fixes for FunctionOpInterface changes

Cherry-pick LLVM commits (top to bottom):
* 93bbcff
* f275148
* 0e0f8ca
* 0274ab4
* 8a051f6
* fdc8434

Fix mhlo to use std::nullopt
* 252d314

Disable tests/e2e/tosa_ops/mul_shift.mlir. (Issue #11571)

Co-authored-by: Lei Zhang <antiagainst@gmail.com>
diff --git a/compiler/src/iree/compiler/Codegen/Common/EraseHALDescriptorTypeFromMemRef.cpp b/compiler/src/iree/compiler/Codegen/Common/EraseHALDescriptorTypeFromMemRef.cpp
index ccb4747..986f44b 100644
--- a/compiler/src/iree/compiler/Codegen/Common/EraseHALDescriptorTypeFromMemRef.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/EraseHALDescriptorTypeFromMemRef.cpp
@@ -38,9 +38,9 @@
     addConversion([](BaseMemRefType memRefType) -> Optional<Type> {
       // Expect #hal.descriptor_type memory spaces.
       Attribute spaceAttr = memRefType.getMemorySpace();
-      if (!spaceAttr) return llvm::None;
+      if (!spaceAttr) return std::nullopt;
       auto dtAttr = spaceAttr.dyn_cast<IREE::HAL::DescriptorTypeAttr>();
-      if (!dtAttr) return llvm::None;
+      if (!dtAttr) return std::nullopt;
 
       // Erase the #hal.descriptor_type memory space.
       if (auto rankedType = memRefType.dyn_cast<MemRefType>()) {
diff --git a/compiler/src/iree/compiler/Codegen/Common/FlattenMemRefSubspanPass.cpp b/compiler/src/iree/compiler/Codegen/Common/FlattenMemRefSubspanPass.cpp
index b5941ed..bda3b7d 100644
--- a/compiler/src/iree/compiler/Codegen/Common/FlattenMemRefSubspanPass.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/FlattenMemRefSubspanPass.cpp
@@ -597,7 +597,7 @@
   };
 };
 
-/// Returns the number of bytes of the given `type`. Returns llvm::None if
+/// Returns the number of bytes of the given `type`. Returns std::nullopt if
 /// cannot deduce.
 ///
 /// Note that this should be kept consistent with how the byte offset was
@@ -606,10 +606,10 @@
   if (type.isIntOrFloat()) return IREE::Util::getRoundedElementByteWidth(type);
   if (auto vectorType = type.dyn_cast<VectorType>()) {
     auto elementBytes = getNumBytes(vectorType.getElementType());
-    if (!elementBytes) return llvm::None;
+    if (!elementBytes) return std::nullopt;
     return elementBytes.value() * vectorType.getNumElements();
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 /// Folds the byte offset on subspan ops into the consumer load/store ops.
@@ -775,7 +775,7 @@
       if (isRankOneMemRef(type)) return type;
 
       // Fall back to the default conversion flow.
-      return llvm::None;
+      return std::nullopt;
     });
     flattenPatterns
         .add<FlattenAlloc<memref::AllocaOp>, FlattenAlloc<memref::AllocOp>,
diff --git a/compiler/src/iree/compiler/Codegen/Common/GPUDistributeSharedMemoryCopy.cpp b/compiler/src/iree/compiler/Codegen/Common/GPUDistributeSharedMemoryCopy.cpp
index e0ccbd7..b727bdb 100644
--- a/compiler/src/iree/compiler/Codegen/Common/GPUDistributeSharedMemoryCopy.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/GPUDistributeSharedMemoryCopy.cpp
@@ -256,7 +256,7 @@
                     {StringAttr::get(patterns.getContext(),
                                      getCopyToWorkgroupMemoryMarker()),
                      StringAttr::get(patterns.getContext(), kCopyDistributed)},
-                    llvm::None));
+                    std::nullopt));
 }
 
 /// Return a flattened Id Value by combining the 3D gpu thread IDs.
diff --git a/compiler/src/iree/compiler/Codegen/Common/GPUVectorization.cpp b/compiler/src/iree/compiler/Codegen/Common/GPUVectorization.cpp
index e300e7b..fb0e443 100644
--- a/compiler/src/iree/compiler/Codegen/Common/GPUVectorization.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/GPUVectorization.cpp
@@ -39,7 +39,7 @@
   IREE::LinalgExt::LinalgTransformationFilter f(
       {StringAttr::get(ctx, getWorkgroupKTiledMarker()),
        StringAttr::get(ctx, getVectorizeMarker())},
-      llvm::None);
+      std::nullopt);
   f.setMatchByDefault();
   // When vectorizing if some ops didn't get tiled we may end up with large
   // vectors being created that will later explode code size. If we have any
diff --git a/compiler/src/iree/compiler/Codegen/Common/IREEComprehensiveBufferizePass.cpp b/compiler/src/iree/compiler/Codegen/Common/IREEComprehensiveBufferizePass.cpp
index 844d544..3f651a3 100644
--- a/compiler/src/iree/compiler/Codegen/Common/IREEComprehensiveBufferizePass.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/IREEComprehensiveBufferizePass.cpp
@@ -58,9 +58,10 @@
     : public IREEComprehensiveBufferizeBase<IREEComprehensiveBufferizePass> {
  public:
   explicit IREEComprehensiveBufferizePass(
-      Optional<BufferizationOptions::AllocationFn> allocationFn = None,
-      Optional<BufferizationOptions::DeallocationFn> deallocationFn = None,
-      Optional<BufferizationOptions::MemCpyFn> memCpyFn = None)
+      Optional<BufferizationOptions::AllocationFn> allocationFn = std::nullopt,
+      Optional<BufferizationOptions::DeallocationFn> deallocationFn =
+          std::nullopt,
+      Optional<BufferizationOptions::MemCpyFn> memCpyFn = std::nullopt)
       : allocationFn(allocationFn),
         deallocationFn(deallocationFn),
         memCpyFn(memCpyFn) {}
diff --git a/compiler/src/iree/compiler/Codegen/Common/MaterializeEncodingPass.cpp b/compiler/src/iree/compiler/Codegen/Common/MaterializeEncodingPass.cpp
index 934fd24..deb372c 100644
--- a/compiler/src/iree/compiler/Codegen/Common/MaterializeEncodingPass.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/MaterializeEncodingPass.cpp
@@ -95,7 +95,7 @@
 static Optional<TensorEncoding> getEncoding(RankedTensorType tensorType) {
   auto encodingAttr = tensorType.getEncoding()
                           .dyn_cast_or_null<IREE::LinalgExt::EncodingAttr>();
-  if (!encodingAttr) return llvm::None;
+  if (!encodingAttr) return std::nullopt;
   return encodingAttr.getEncoding().getValue();
 }
 
@@ -124,7 +124,7 @@
     case TensorEncoding::MATMUL_I8I8I32_RESULT:
       return MatmulType::I8I8I32;
     default:
-      return llvm::None;
+      return std::nullopt;
   }
 }
 
@@ -144,7 +144,7 @@
     case TensorEncoding::MATMUL_I8I8I32_RESULT:
       return MatmulOperandRole::RESULT;
     default:
-      return llvm::None;
+      return std::nullopt;
   }
 }
 
diff --git a/compiler/src/iree/compiler/Codegen/Common/RemoveTrivialLoops.cpp b/compiler/src/iree/compiler/Codegen/Common/RemoveTrivialLoops.cpp
index 92c9503..c53e3d8 100644
--- a/compiler/src/iree/compiler/Codegen/Common/RemoveTrivialLoops.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/RemoveTrivialLoops.cpp
@@ -59,7 +59,7 @@
     return std::make_pair(bound, bound);
   }
 
-  if (workgroupCount.empty()) return llvm::None;
+  if (workgroupCount.empty()) return std::nullopt;
 
   if (auto idOp =
           processorValue.getDefiningOp<IREE::HAL::InterfaceWorkgroupIDOp>()) {
@@ -67,7 +67,7 @@
 
     // Can't infer the range when workroupCount is unknown.
     unsigned index = idOp.getDimension().getZExtValue();
-    if (!workgroupCount[index]) return llvm::None;
+    if (!workgroupCount[index]) return std::nullopt;
 
     AffineExpr zero = builder.getAffineConstantExpr(0);
     AffineExpr ubExpr = builder.getAffineConstantExpr(workgroupCount[index]);
@@ -79,12 +79,12 @@
 
     // Can't infer the range when workroupCount is unknown.
     unsigned index = dimOp.getDimension().getZExtValue();
-    if (!workgroupCount[index]) return llvm::None;
+    if (!workgroupCount[index]) return std::nullopt;
 
     AffineExpr bound = builder.getAffineConstantExpr(workgroupCount[index]);
     return std::make_pair(bound, bound);
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 /// Return true if the given tiled loop is distributed to workgroups.
diff --git a/compiler/src/iree/compiler/Codegen/Common/TileAndDistributeToWorkgroupsPass.cpp b/compiler/src/iree/compiler/Codegen/Common/TileAndDistributeToWorkgroupsPass.cpp
index 8d54b6e..a49e5a0 100644
--- a/compiler/src/iree/compiler/Codegen/Common/TileAndDistributeToWorkgroupsPass.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/TileAndDistributeToWorkgroupsPass.cpp
@@ -83,7 +83,7 @@
   }
 
   partitionableLoops =
-      partitionableLoopInterface.getPartitionableLoops(llvm::None);
+      partitionableLoopInterface.getPartitionableLoops(std::nullopt);
   IREE::Codegen::LoweringConfigAttr rootOpConfig = getLoweringConfig(*rootOp);
   if (!rootOpConfig) {
     return rootOp.value()->emitOpError(
diff --git a/compiler/src/iree/compiler/Codegen/Common/TransformExtensions/CommonExtensions.cpp b/compiler/src/iree/compiler/Codegen/Common/TransformExtensions/CommonExtensions.cpp
index 2680e1c..c4ce5e2 100644
--- a/compiler/src/iree/compiler/Codegen/Common/TransformExtensions/CommonExtensions.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/TransformExtensions/CommonExtensions.cpp
@@ -251,7 +251,7 @@
     return mlir::emitDefiniteFailure(target, "listener tracking failed");
 
   results.assign({target});
-  return DiagnosedSilenceableFailure(success());
+  return DiagnosedSilenceableFailure::success();
 }
 
 //===---------------------------------------------------------------------===//
@@ -479,7 +479,7 @@
   }
 
   results.assign({target});
-  return DiagnosedSilenceableFailure(success());
+  return DiagnosedSilenceableFailure::success();
 }
 
 //===---------------------------------------------------------------------===//
@@ -724,7 +724,7 @@
 
   transformResults.set(getForeachThreadOp().cast<OpResult>(), tileOps);
   transformResults.set(getTiledOp().cast<OpResult>(), tiledOps);
-  return DiagnosedSilenceableFailure(success());
+  return DiagnosedSilenceableFailure::success();
 }
 
 //===---------------------------------------------------------------------===//
diff --git a/compiler/src/iree/compiler/Codegen/Common/TransformExtensions/CommonExtensionsOps.td b/compiler/src/iree/compiler/Codegen/Common/TransformExtensions/CommonExtensionsOps.td
index e42f75b..b5edbc9 100644
--- a/compiler/src/iree/compiler/Codegen/Common/TransformExtensions/CommonExtensionsOps.td
+++ b/compiler/src/iree/compiler/Codegen/Common/TransformExtensions/CommonExtensionsOps.td
@@ -350,7 +350,7 @@
 
   let builders = [
     OpBuilder<(ins "Value":$target, "StringRef":$attrName,
-               CArg<"Optional<int64_t>", "llvm::None">:$level)>
+               CArg<"Optional<int64_t>", "std::nullopt">:$level)>
   ];
   let extraClassDeclaration = [{
     ::mlir::DiagnosedSilenceableFailure apply(
diff --git a/compiler/src/iree/compiler/Codegen/Common/TypePropagationPass.cpp b/compiler/src/iree/compiler/Codegen/Common/TypePropagationPass.cpp
index 92ff157..0a4446c 100644
--- a/compiler/src/iree/compiler/Codegen/Common/TypePropagationPass.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/TypePropagationPass.cpp
@@ -38,7 +38,7 @@
 namespace iree_compiler {
 
 /// Returns the legal element type to use instead of the passed in element type.
-/// If the type is already legal, returns llvm::None.
+/// If the type is already legal, returns std::nullopt.
 static Optional<Type> getLegalizedElementType(Type elementType) {
   if (auto intType = elementType.dyn_cast<IntegerType>()) {
     unsigned bitWidth = intType.getWidth();
@@ -67,17 +67,18 @@
   return nullptr;
 }
 
-/// Legalizes the given type. If the type is already legal, returns llvm::None.
+/// Legalizes the given type. If the type is already legal, returns
+/// std::nullopt.
 static Optional<Type> getLegalizedType(Type t) {
   if (auto shapedType = t.dyn_cast<RankedTensorType>()) {
     Type elementType = shapedType.getElementType();
     Optional<Type> legalizedElementType = getLegalizedElementType(elementType);
-    if (!legalizedElementType) return llvm::None;
+    if (!legalizedElementType) return std::nullopt;
     return RankedTensorType::get(shapedType.getShape(),
                                  legalizedElementType.value(),
                                  shapedType.getEncoding());
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 namespace {
diff --git a/compiler/src/iree/compiler/Codegen/Common/VectorReductionToGPU.cpp b/compiler/src/iree/compiler/Codegen/Common/VectorReductionToGPU.cpp
index b60b354..96f240f 100644
--- a/compiler/src/iree/compiler/Codegen/Common/VectorReductionToGPU.cpp
+++ b/compiler/src/iree/compiler/Codegen/Common/VectorReductionToGPU.cpp
@@ -273,7 +273,7 @@
     SmallVector<Value> indices = {warpId};
     builder.create<scf::IfOp>(loc, lane0, [&](OpBuilder &b, Location l) {
       b.create<memref::StoreOp>(l, laneVal, alloc, indices);
-      b.create<scf::YieldOp>(l, llvm::None);
+      b.create<scf::YieldOp>(l, std::nullopt);
     });
     builder.create<gpu::BarrierOp>(loc);
     // Further reduce the outputs from each warps with a single warp reduce.
diff --git a/compiler/src/iree/compiler/Codegen/LLVMCPU/ConvertToLLVM.cpp b/compiler/src/iree/compiler/Codegen/LLVMCPU/ConvertToLLVM.cpp
index ee92720..af64f2a 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMCPU/ConvertToLLVM.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMCPU/ConvertToLLVM.cpp
@@ -830,7 +830,7 @@
     SmallVector<NamedAttribute, 4> funcAttrs;
     for (auto attr : stdFuncOp->getAttrs()) {
       if (attr.getName() == SymbolTable::getSymbolAttrName() ||
-          attr.getName() == mlir::function_interface_impl::getTypeAttrName()) {
+          attr.getName() == stdFuncOp.getFunctionTypeAttrName()) {
         continue;
       }
       funcAttrs.push_back(attr);
diff --git a/compiler/src/iree/compiler/Codegen/LLVMCPU/KernelDispatch.cpp b/compiler/src/iree/compiler/Codegen/LLVMCPU/KernelDispatch.cpp
index 321020d..28e25a2 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMCPU/KernelDispatch.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMCPU/KernelDispatch.cpp
@@ -202,9 +202,9 @@
   auto targetAttr = IREE::HAL::ExecutableTargetAttr::lookup(entryPointFn);
   auto nativeVectorSizeAttr =
       getConfigIntegerAttr(targetAttr, "native_vector_size");
-  if (!nativeVectorSizeAttr) return llvm::None;
+  if (!nativeVectorSizeAttr) return std::nullopt;
   int64_t nativeVectorSizeVal = nativeVectorSizeAttr->getInt();
-  if (!nativeVectorSizeVal) return llvm::None;
+  if (!nativeVectorSizeVal) return std::nullopt;
   return nativeVectorSizeVal;
 }
 
diff --git a/compiler/src/iree/compiler/Codegen/LLVMGPU/ConvertToLLVM.cpp b/compiler/src/iree/compiler/Codegen/LLVMGPU/ConvertToLLVM.cpp
index 1e08478..15ab9fc 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMGPU/ConvertToLLVM.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMGPU/ConvertToLLVM.cpp
@@ -252,7 +252,7 @@
     SmallVector<NamedAttribute, 4> funcAttrs;
     for (auto attr : funcOp->getAttrs()) {
       if (attr.getName() == SymbolTable::getSymbolAttrName() ||
-          attr.getName() == mlir::function_interface_impl::getTypeAttrName()) {
+          attr.getName() == funcOp.getFunctionTypeAttrName()) {
         continue;
       }
       funcAttrs.push_back(attr);
diff --git a/compiler/src/iree/compiler/Codegen/LLVMGPU/KernelConfig.cpp b/compiler/src/iree/compiler/Codegen/LLVMGPU/KernelConfig.cpp
index c5f8627..8381779 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMGPU/KernelConfig.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMGPU/KernelConfig.cpp
@@ -214,7 +214,7 @@
             std::move(workgroupTileSizes));  // Workgroup level.
         return setOpConfigAndEntryPointFnTranslation(
             entryPoint, op, tileSizes, pipeline, workgroupSize,
-            /*subgroupSize=*/llvm::None, softwarePipelineDepth);
+            /*subgroupSize=*/std::nullopt, softwarePipelineDepth);
       };
   // Infer the MxN size of the matmul based on operands and indexing maps.
   auto lhsShape =
@@ -394,7 +394,7 @@
       IREE::Codegen::DispatchLoweringPassPipeline::LLVMGPUDistribute;
   TileSizesListType tileSizes;
   auto interfaceOp = cast<PartitionableLoopsInterface>(*op);
-  auto partitionedLoops = interfaceOp.getPartitionableLoops(llvm::None);
+  auto partitionedLoops = interfaceOp.getPartitionableLoops(std::nullopt);
   if (partitionedLoops.empty()) {
     tileSizes.push_back({});
     return setOpConfigAndEntryPointFnTranslation(entryPoint, op, tileSizes,
@@ -492,12 +492,12 @@
       auto expr = dim.value().dyn_cast<AffineDimExpr>();
       if (expr && expr.getPosition() == d) {
         auto type = op->getOperand(map.index()).getType().cast<ShapedType>();
-        if (type.isDynamicDim(dim.index())) return llvm::None;
+        if (type.isDynamicDim(dim.index())) return std::nullopt;
         return type.getDimSize(dim.index());
       }
     }
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 /// Set configuration for reduction transform dialect based strategy.
diff --git a/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUDistribute.cpp b/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUDistribute.cpp
index 8d18623..c466cfd 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUDistribute.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUDistribute.cpp
@@ -51,7 +51,7 @@
 
     DiagnosedSilenceableFailure const result =
         mlir::transform::gpu::mapNestedForeachToThreadsImpl(
-            rewriter, funcOp, workgroupSize, false, llvm::None,
+            rewriter, funcOp, workgroupSize, false, std::nullopt,
             threadMappingAttributes);
 
     if (!result.succeeded()) return signalPassFailure();
diff --git a/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTensorCoreVectorization.cpp b/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTensorCoreVectorization.cpp
index 022e5a9..d827a45 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTensorCoreVectorization.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTensorCoreVectorization.cpp
@@ -41,7 +41,7 @@
 
 static Optional<SmallVector<int64_t>> unrollOrder(Operation *op) {
   auto contract = dyn_cast<vector::ContractionOp>(op);
-  if (!contract) return llvm::None;
+  if (!contract) return std::nullopt;
   SmallVector<int64_t> order;
   // Pick an unrolling order that will allow tensorcore operation to reuse LHS
   // register. This is needed to get good performance on sm_80 target.
@@ -97,9 +97,9 @@
     VectorType sliceType;
     for (Operation *users : op->getUsers()) {
       auto extract = dyn_cast<vector::ExtractStridedSliceOp>(users);
-      if (!extract) return llvm::None;
+      if (!extract) return std::nullopt;
       auto vecType = extract.getResult().getType().cast<VectorType>();
-      if (sliceType && sliceType != vecType) return llvm::None;
+      if (sliceType && sliceType != vecType) return std::nullopt;
       sliceType = vecType;
     }
     return llvm::to_vector<>(sliceType.getShape());
@@ -112,7 +112,7 @@
       return nativeSize;
     }
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 static void populateVectorUnrollPatterns(RewritePatternSet &patterns) {
diff --git a/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTileTensor.cpp b/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTileTensor.cpp
index ae0ef3e..42c58ce 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTileTensor.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMGPU/LLVMGPUTileTensor.cpp
@@ -160,7 +160,7 @@
 
     FailureOr<linalg::TileLoopNest> loopNest =
         IREE::LinalgExt::tileConsumerAndFuseProducers(
-            builder, consumerOp, tileSizes, identityLoopOrder, llvm::None);
+            builder, consumerOp, tileSizes, identityLoopOrder, std::nullopt);
     if (failed(loopNest)) {
       consumerOp.emitOpError("failed tiling and fusing producers");
       return failure();
diff --git a/compiler/src/iree/compiler/Codegen/LLVMGPU/TransformExtensions/LLVMGPUExtensions.cpp b/compiler/src/iree/compiler/Codegen/LLVMGPU/TransformExtensions/LLVMGPUExtensions.cpp
index f7ce10f..83ad1e5 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMGPU/TransformExtensions/LLVMGPUExtensions.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMGPU/TransformExtensions/LLVMGPUExtensions.cpp
@@ -63,7 +63,7 @@
     state.getTopLevel()->emitOpError(
         "requires HAL::ExecutableOp or HAL::ExecutableVariantOp toplevel to "
         "attach the workgroup size information to a nested ExecutableExportOp");
-    return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
+    return emitDefaultDefiniteFailure(target);
   }
 
   IREE::HAL::ExecutableExportOp exportOp;
@@ -72,7 +72,7 @@
   });
   if (!exportOp) {
     state.getTopLevel()->emitOpError("no IREE::HAL::ExecutableExportOp found");
-    return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
+    return emitDefaultDefiniteFailure(target);
   }
 
   SmallVector<int64_t> workgroupSize =
@@ -321,7 +321,7 @@
               "transform is not applied";
   }
   results.assign({vectorDistributionResult->warpOp});
-  return DiagnosedSilenceableFailure(success());
+  return DiagnosedSilenceableFailure::success();
 }
 
 //===---------------------------------------------------------------------===//
@@ -565,7 +565,7 @@
     target->emitOpError(
         "applies only to isolated-from-above targets because it needs to apply "
         "patterns greedily");
-    return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
+    return emitDefaultDefiniteFailure(target);
   }
 
   // TODO: Hook up into the ApplyPatternOp in CommonExtensions.cpp to
@@ -580,7 +580,7 @@
   populatePropagateVectorDistribution(target, patterns, /*benefit=*/1);
   if (failed(applyPatternsAndFoldGreedily(target, std::move(patterns)))) {
     target->emitOpError("warp distribution patterns failed to apply");
-    return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
+    return emitDefaultDefiniteFailure(target);
   }
 
   RewritePatternSet endPatterns(ctx);
@@ -591,10 +591,10 @@
   if (failed(applyPatternsAndFoldGreedily(target, std::move(endPatterns)))) {
     target->emitOpError(
         "warp execute on lane 0 to scf patterns failed to apply");
-    return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
+    return emitDefaultDefiniteFailure(target);
   }
 
-  return DiagnosedSilenceableFailure(success());
+  return DiagnosedSilenceableFailure::success();
 }
 
 void transform_dialect::VectorWarpDistributionOp::getEffects(
diff --git a/compiler/src/iree/compiler/Codegen/Passes.h b/compiler/src/iree/compiler/Codegen/Passes.h
index 26cbbd6..563f57b 100644
--- a/compiler/src/iree/compiler/Codegen/Passes.h
+++ b/compiler/src/iree/compiler/Codegen/Passes.h
@@ -44,9 +44,10 @@
 using bufferization::BufferizationOptions;
 void addIREEComprehensiveBufferizePasses(
     OpPassManager &passManager,
-    Optional<BufferizationOptions::AllocationFn> allocationFn = None,
-    Optional<BufferizationOptions::DeallocationFn> deallocationFn = None,
-    Optional<BufferizationOptions::MemCpyFn> memCpyFn = None);
+    Optional<BufferizationOptions::AllocationFn> allocationFn = std::nullopt,
+    Optional<BufferizationOptions::DeallocationFn> deallocationFn =
+        std::nullopt,
+    Optional<BufferizationOptions::MemCpyFn> memCpyFn = std::nullopt);
 
 /// Pass to perform canonicalizations/cleanups related to HAL interface/buffer
 /// allocations and view operations.
@@ -94,9 +95,10 @@
 /// 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 = None,
-    Optional<BufferizationOptions::DeallocationFn> deallocationFn = None,
-    Optional<BufferizationOptions::MemCpyFn> memCpyFn = None);
+    Optional<BufferizationOptions::AllocationFn> allocationFn = std::nullopt,
+    Optional<BufferizationOptions::DeallocationFn> deallocationFn =
+        std::nullopt,
+    Optional<BufferizationOptions::MemCpyFn> memCpyFn = std::nullopt);
 
 /// Creates a pass to remove single iteration distributed loops.
 std::unique_ptr<OperationPass<func::FuncOp>>
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/KernelConfig.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/KernelConfig.cpp
index 371f8fd..2284d42 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/KernelConfig.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/KernelConfig.cpp
@@ -665,7 +665,7 @@
     return setOpConfigAndEntryPointFnTranslation(
         op->getParentOfType<func::FuncOp>(), op, tileSizes,
         CodeGenPipeline::SPIRVMatmulPromoteVectorize, workgroupSize,
-        /*subgroupSize=*/llvm::None, pipelineDepth, storeStage);
+        /*subgroupSize=*/std::nullopt, pipelineDepth, storeStage);
   }
 
   return setOpConfigAndEntryPointFnTranslation(
@@ -785,7 +785,7 @@
                                  mWarpCount, nWarpCount, mTileCount,
                                  nTileCount, kTileCount};
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 namespace detail {
@@ -1172,7 +1172,7 @@
 
   // Distribute workload to the given `numThreads` by allowing a potental loss.
   auto distributeToThreads = [&](int64_t numThreads,
-                                 Optional<int64_t> lossFactor = llvm::None) {
+                                 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/SPIRVMapMemRefStorageClass.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVMapMemRefStorageClass.cpp
index 9bb4c3e..774d229 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVMapMemRefStorageClass.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVMapMemRefStorageClass.cpp
@@ -30,7 +30,7 @@
     case IREE::HAL::DescriptorType::StorageBuffer:
       return spirv::StorageClass::StorageBuffer;
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 Optional<spirv::StorageClass> mapHALDescriptorTypeForOpenCL(Attribute attr) {
@@ -42,7 +42,7 @@
     case IREE::HAL::DescriptorType::StorageBuffer:
       return spirv::StorageClass::CrossWorkgroup;
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 struct SPIRVMapMemRefStorageClassPass final
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTile.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTile.cpp
index 2140a36..1dbfd41 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTile.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTile.cpp
@@ -109,7 +109,7 @@
 
   FailureOr<linalg::TileLoopNest> loopNest =
       IREE::LinalgExt::tileConsumerAndFuseProducers(
-          builder, consumerOp, tileSizes, identityLoopOrder, llvm::None);
+          builder, consumerOp, tileSizes, identityLoopOrder, std::nullopt);
   if (failed(loopNest)) {
     return consumerOp.emitOpError("failed tiling and fusing producers");
   }
@@ -145,7 +145,7 @@
                            .setTileSizeComputationFunction(getTileSizeFn);
   auto marker = StringAttr::get(context, getTileReductionMarker());
   auto filter =
-      IREE::LinalgExt::LinalgTransformationFilter({marker}, llvm::None);
+      IREE::LinalgExt::LinalgTransformationFilter({marker}, std::nullopt);
 
   TilingPatterns<linalg::BatchMatmulOp, linalg::Conv2DNchwFchwOp,
                  linalg::Conv2DNhwcHwcfOp, linalg::DepthwiseConv2DNhwcHwcOp,
@@ -232,7 +232,7 @@
 
     FailureOr<linalg::TileLoopNest> loopNest =
         IREE::LinalgExt::tileConsumerAndFuseProducers(
-            builder, consumerOp, tileSizes, identityLoopOrder, llvm::None);
+            builder, consumerOp, tileSizes, identityLoopOrder, std::nullopt);
     if (failed(loopNest)) {
       return consumerOp.emitOpError("failed tiling and fusing producers");
     }
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndDistribute.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndDistribute.cpp
index 3aa4264..095a1ea 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndDistribute.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndDistribute.cpp
@@ -90,7 +90,7 @@
     const linalg::TileSizeComputationFunction &computeFn) {
   auto filter = IREE::LinalgExt::LinalgTransformationFilter(
       StringAttr::get(patterns.getContext(), getTileReductionMarker()),
-      llvm::None);
+      std::nullopt);
 
   auto tilingOptions = linalg::LinalgTilingOptions()
                            .setLoopType(linalg::LinalgTilingLoopType::Loops)
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndPromote.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndPromote.cpp
index 26d9a65..def8c8d 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndPromote.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndPromote.cpp
@@ -264,7 +264,7 @@
   if (!skipThreadLevel) {  // Tile and distribute to invocations.
     RewritePatternSet tilingPatterns(context);
     IREE::LinalgExt::LinalgTransformationFilter filter({workgroupMarker},
-                                                       llvm::None);
+                                                       std::nullopt);
     populateTilingToInvocationPatterns(tilingPatterns, filter,
                                        *threadTileComputeFn);
     if (failed(
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndVectorizeToCooperativeOps.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndVectorizeToCooperativeOps.cpp
index d271bc2..ce05d2d 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndVectorizeToCooperativeOps.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVTileAndVectorizeToCooperativeOps.cpp
@@ -186,15 +186,15 @@
     VectorType sliceType;
     for (Operation *users : op->getUsers()) {
       auto extract = dyn_cast<vector::ExtractStridedSliceOp>(users);
-      if (!extract) return llvm::None;
+      if (!extract) return std::nullopt;
       auto vecType = extract.getResult().getType().cast<VectorType>();
-      if (sliceType && sliceType != vecType) return llvm::None;
+      if (sliceType && sliceType != vecType) return std::nullopt;
       sliceType = vecType;
     }
     return llvm::to_vector<>(sliceType.getShape());
   }
 
-  return llvm::None;
+  return std::nullopt;
 }
 
 /// Adds patterns to unroll vector ops to SPIR-V native vector size.
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorize.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorize.cpp
index 4d04ad6..d8221d3 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorize.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorize.cpp
@@ -115,7 +115,7 @@
     nativeSize.back() = getComputeVectorSize(vectorType.getShape().back());
     return nativeSize;
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 /// Add patterns to vectorize any supported Linalg ops.
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorizeLoadStore.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorizeLoadStore.cpp
index bfb93dd..59f73ce 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorizeLoadStore.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/SPIRVVectorizeLoadStore.cpp
@@ -697,7 +697,7 @@
   // Creates a new function with the update signature.
   rewriter.updateRootInPlace(funcOp, [&] {
     funcOp.setType(rewriter.getFunctionType(
-        signatureConverter.getConvertedTypes(), llvm::None));
+        signatureConverter.getConvertedTypes(), std::nullopt));
   });
   return success();
 }
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/Utils.cpp b/compiler/src/iree/compiler/Codegen/SPIRV/Utils.cpp
index bb65600..56a6266 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/Utils.cpp
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/Utils.cpp
@@ -51,11 +51,11 @@
   llvm::StringMap<IREE::HAL::ExecutableExportOp> exportOps =
       getAllEntryPoints(moduleOp);
   auto exportOp = exportOps.lookup(funcOp.getName());
-  if (!exportOp) return llvm::None;
+  if (!exportOp) return std::nullopt;
   if (auto size = exportOp.getSubgroupSize()) return size->getSExtValue();
 
   spirv::TargetEnvAttr target = getSPIRVTargetEnvAttr(funcOp);
-  if (!target) return llvm::None;
+  if (!target) return std::nullopt;
   return target.getResourceLimits().getSubgroupSize();
 }
 
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/Utils.h b/compiler/src/iree/compiler/Codegen/SPIRV/Utils.h
index 3ade347..faf60e6 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/Utils.h
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/Utils.h
@@ -26,7 +26,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 llvm::None on failures.
+/// environment. Returns std::nullopt on failures.
 llvm::Optional<int> getSPIRVSubgroupSize(func::FuncOp funcOp);
 
 /// Returns the attribute name carrying information about distribution.
diff --git a/compiler/src/iree/compiler/Codegen/SPIRV/test/emulate_i64.mlir b/compiler/src/iree/compiler/Codegen/SPIRV/test/emulate_i64.mlir
index 10c8e73..a8032ec 100644
--- a/compiler/src/iree/compiler/Codegen/SPIRV/test/emulate_i64.mlir
+++ b/compiler/src/iree/compiler/Codegen/SPIRV/test/emulate_i64.mlir
@@ -94,8 +94,7 @@
 //
 // CHECK-LABEL: func.func @emulate_1d_vector
 //       CHECK:   [[LOAD:%.+]]     = memref.load {{%.+}}[{{%.+}}] : memref<?xvector<4xi32>, #spirv.storage_class<StorageBuffer>>
-//       CHECK:   {{%.+}}          = arith.muli {{%.+}}, {{%.+}} : vector<4xi32>
-//       CHECK:   {{%.+}}          = arith.addi {{%.+}}, {{%.+}} : vector<4xi32>
+//       CHECK:   {{%.+}}, {{%.+}} = arith.mului_extended {{%.+}}, {{%.+}} : vector<4xi32>
 //       CHECK:   {{%.+}}, {{%.+}} = arith.addui_extended {{%.+}}, {{%.+}} : vector<4xi32>, vector<4xi1>
 //       CHECK:   memref.store {{%.+}}, {{%.+}}[{{%.+}}] : memref<?xvector<4xi32>, #spirv.storage_class<StorageBuffer>>
 //       CHECK:   return
diff --git a/compiler/src/iree/compiler/Codegen/Utils/GPUUtils.cpp b/compiler/src/iree/compiler/Codegen/Utils/GPUUtils.cpp
index 9bdd803..c388e2f 100644
--- a/compiler/src/iree/compiler/Codegen/Utils/GPUUtils.cpp
+++ b/compiler/src/iree/compiler/Codegen/Utils/GPUUtils.cpp
@@ -118,14 +118,14 @@
   OpBuilder::InsertionGuard guard(builder);
 
   func::FuncOp funcOp = subview->getParentOfType<func::FuncOp>();
-  if (!funcOp) return llvm::None;
+  if (!funcOp) return std::nullopt;
 
   // The subview size bounds are expected to be constant; they specify the shape
   // of the allocation.
   SmallVector<int64_t, 2> shape;
   for (Value bound : sizeBounds) {
     APInt value;
-    if (!matchPattern(bound, m_ConstantInt(&value))) return llvm::None;
+    if (!matchPattern(bound, m_ConstantInt(&value))) return std::nullopt;
     shape.push_back(value.getSExtValue());
   }
 
diff --git a/compiler/src/iree/compiler/Codegen/Utils/Utils.cpp b/compiler/src/iree/compiler/Codegen/Utils/Utils.cpp
index 5c3c2b3..2d9d2ca 100644
--- a/compiler/src/iree/compiler/Codegen/Utils/Utils.cpp
+++ b/compiler/src/iree/compiler/Codegen/Utils/Utils.cpp
@@ -74,38 +74,38 @@
 
 Optional<StringAttr> getConfigStringAttr(
     IREE::HAL::ExecutableTargetAttr targetAttr, StringRef stringAttr) {
-  if (!targetAttr) return llvm::None;
+  if (!targetAttr) return std::nullopt;
   auto config = targetAttr.getConfiguration();
-  if (!config) return llvm::None;
+  if (!config) return std::nullopt;
   auto attr = config.getAs<StringAttr>(stringAttr);
-  if (!attr) return llvm::None;
+  if (!attr) return std::nullopt;
   return attr;
 }
 
 Optional<IntegerAttr> getConfigIntegerAttr(
     IREE::HAL::ExecutableTargetAttr targetAttr, StringRef integerAttr) {
-  if (!targetAttr) return llvm::None;
+  if (!targetAttr) return std::nullopt;
   auto config = targetAttr.getConfiguration();
-  if (!config) return llvm::None;
+  if (!config) return std::nullopt;
   auto attr = config.getAs<IntegerAttr>(integerAttr);
-  if (!attr) return llvm::None;
+  if (!attr) return std::nullopt;
   return attr;
 }
 
 Optional<BoolAttr> getConfigBoolAttr(IREE::HAL::ExecutableTargetAttr targetAttr,
                                      StringRef integerAttr) {
-  if (!targetAttr) return llvm::None;
+  if (!targetAttr) return std::nullopt;
   auto config = targetAttr.getConfiguration();
-  if (!config) return llvm::None;
+  if (!config) return std::nullopt;
   auto attr = config.getAs<BoolAttr>(integerAttr);
-  if (!attr) return llvm::None;
+  if (!attr) return std::nullopt;
   return attr;
 }
 
 Optional<llvm::Triple> getTargetTriple(
     IREE::HAL::ExecutableTargetAttr targetAttr) {
   auto triple = getConfigStringAttr(targetAttr, "target_triple");
-  if (!triple) return llvm::None;
+  if (!triple) return std::nullopt;
   return llvm::Triple(triple.value().str());
 }
 
@@ -113,7 +113,7 @@
 /// operation, if set.
 Optional<StringRef> getCpuFeatures(IREE::HAL::ExecutableTargetAttr targetAttr) {
   auto cpuFeatures = getConfigStringAttr(targetAttr, "cpu_features");
-  if (!cpuFeatures) return llvm::None;
+  if (!cpuFeatures) return std::nullopt;
   return cpuFeatures->getValue();
 }
 
@@ -254,11 +254,11 @@
   if (auto tOp = dyn_cast<T>(op)) {
     return tOp.getDimIndex();
   }
-  return llvm::None;
+  return std::nullopt;
 }
 template <typename T1, typename T2, typename... T3>
 static Optional<unsigned> getDimension(Operation *op) {
-  if (!op) return llvm::None;
+  if (!op) return std::nullopt;
   if (auto dimension = getDimension<T1>(op)) {
     return dimension;
   }
@@ -267,18 +267,18 @@
 
 /// Checks that all `vals` are defined by some processor id/count/size ops using
 /// the same `dimension`. If any element of `vals` is not defined by one of
-/// these ops, or the dimensions dont match, returns llvm::None; oterhwise,
+/// these ops, or the dimensions dont match, returns std::nullopt; oterhwise,
 /// 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 = llvm::None) {
+    ArrayRef<Value> vals, Optional<unsigned> refDimension = std::nullopt) {
   for (auto v : vals) {
     auto currDimension = getDimension<T...>(v.getDefiningOp());
-    if (!currDimension) return llvm::None;
+    if (!currDimension) return std::nullopt;
     if (refDimension) {
       if (refDimension.value() != currDimension.value()) {
-        return llvm::None;
+        return std::nullopt;
       }
     } else {
       refDimension = currDimension.value();
@@ -495,7 +495,7 @@
   if (auto op = value.getDefiningOp<OpTy>()) {
     return op.getDimension().getZExtValue();
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 /// Checks if the `forOp` is a tiled + distributed op. Looks for the op of this
@@ -535,7 +535,7 @@
       countDim = ifx.getDimIndex();
     }
 
-    if (!idDim || !countDim) return llvm::None;
+    if (!idDim || !countDim) return std::nullopt;
 
     Builder b(forOp.getContext());
     loopInfo.untiledLowerBound = b.getIndexAttr(0);
@@ -550,13 +550,13 @@
   StepExprVisitor stepVisitor(stepApplyOp, loopInfo);
 
   if (failed(lbVisitor.visit(lbApplyOp.getAffineMap().getResults()[0]))) {
-    return llvm::None;
+    return std::nullopt;
   }
   if (failed(stepVisitor.visit(stepApplyOp.getAffineMap().getResults()[0]))) {
-    return llvm::None;
+    return std::nullopt;
   }
   if (!loopInfo.untiledLowerBound || !loopInfo.untiledStep) {
-    return llvm::None;
+    return std::nullopt;
   }
   return loopInfo;
 }
diff --git a/compiler/src/iree/compiler/Codegen/VMVX/LowerLinalgMicrokernels.cpp b/compiler/src/iree/compiler/Codegen/VMVX/LowerLinalgMicrokernels.cpp
index 492e3d0..4056539 100644
--- a/compiler/src/iree/compiler/Codegen/VMVX/LowerLinalgMicrokernels.cpp
+++ b/compiler/src/iree/compiler/Codegen/VMVX/LowerLinalgMicrokernels.cpp
@@ -578,7 +578,7 @@
                                       op.getMatchingIndexingMap(result)),
             selection);
       } else {
-        return None;
+        return std::nullopt;
       }
     };
 
@@ -592,87 +592,87 @@
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "add");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](arith::AddIOp op) -> Optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "add");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](arith::AndIOp op) -> Optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "and");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](arith::DivFOp op) -> Optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "div");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](arith::DivSIOp op) -> Optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "divs");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](arith::DivUIOp op) -> Optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "divu");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](arith::MulFOp op) -> Optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "mul");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](arith::MulIOp op) -> Optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "mul");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](arith::OrIOp op) -> Optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "or");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](arith::ShLIOp op) -> Optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "shl");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](arith::ShRSIOp op) -> Optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "shrs");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](arith::XOrIOp op) -> Optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "xor");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](arith::SubFOp op) -> Optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "sub");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](arith::SubIOp op) -> Optional<BinaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericBinary(op, "sub");
               }
-              return None;
+              return std::nullopt;
             })
-            .Default([](Operation *) { return None; });
+            .Default([](Operation *) { return std::nullopt; });
 
     // Determine op type to lower to.
     if (!emitter) {
@@ -744,51 +744,51 @@
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "abs");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](math::CeilOp op) -> Optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "ceil");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](math::CountLeadingZerosOp op) -> Optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "ctlz");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](math::ExpOp op) -> Optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "exp");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](math::FloorOp op) -> Optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "floor");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](math::LogOp op) -> Optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "log");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](arith::NegFOp op) -> Optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "neg");
               }
-              return None;
+              return std::nullopt;
             })
             .Case([&](math::RsqrtOp op) -> Optional<UnaryEmitter> {
               if (resultType.getIntOrFloatBitWidth() == 32) {
                 return configureGenericUnary(op, "rsqrt");
               }
-              return None;
+              return std::nullopt;
             })
-            .Default([](Operation *) { return None; });
+            .Default([](Operation *) { return std::nullopt; });
 
     // Determine op type to lower to.
     if (!emitter) {
diff --git a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.cpp b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.cpp
index b2492f0..80772f0 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.cpp
@@ -135,13 +135,13 @@
             blockArg.getOwner()->getParentOp())) {
       return blockArg;
     }
-    return llvm::None;
+    return std::nullopt;
   }
   Operation *definingOp = v.getDefiningOp();
   if (auto loadOp = dyn_cast<IREE::Flow::DispatchTensorLoadOp>(definingOp)) {
     return getBindingArgument(loadOp.getSource());
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 /// Returns `true` if the slice (described by the `offset`, `sizes` and
diff --git a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.td b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.td
index 5f968e0..5e1acab 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.td
+++ b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.td
@@ -613,7 +613,7 @@
   let builders = [
     OpBuilder<(ins),
     [{
-      build($_builder, $_state, llvm::None);
+      build($_builder, $_state, std::nullopt);
     }]>,
   ];
 }
diff --git a/compiler/src/iree/compiler/Dialect/Flow/TransformExtensions/FlowExtensions.cpp b/compiler/src/iree/compiler/Dialect/Flow/TransformExtensions/FlowExtensions.cpp
index 5f3c126..96e8ab8 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/TransformExtensions/FlowExtensions.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/TransformExtensions/FlowExtensions.cpp
@@ -465,10 +465,9 @@
   SimplePatternRewriter rewriter(target->getContext());
   FailureOr<Flow::DispatchWorkgroupsOp> result =
       rewriteForeachThreadToFlowDispatchWorkgroups(target, rewriter);
-  if (failed(result))
-    return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
+  if (failed(result)) return emitDefaultDefiniteFailure(target);
   results.push_back(*result);
-  return DiagnosedSilenceableFailure(success());
+  return DiagnosedSilenceableFailure::success();
 }
 
 void transform_dialect::ForeachThreadToFlowDispatchWorkgroupsOp::getEffects(
@@ -484,10 +483,9 @@
   IRRewriter rewriter(target->getContext());
   FailureOr<Flow::DispatchWorkgroupsOp> result =
       rewriteFlowDispatchRegionToFlowDispatchWorkgroups(target, rewriter);
-  if (failed(result))
-    return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
+  if (failed(result)) return emitDefaultDefiniteFailure(target);
   results.push_back(*result);
-  return DiagnosedSilenceableFailure(success());
+  return DiagnosedSilenceableFailure::success();
 }
 
 void transform_dialect::RegionToWorkgroupsOp::getEffects(
@@ -512,13 +510,12 @@
   }
 
   if (dispatchRegion.size() != 1)
-    return DiagnosedSilenceableFailure(this->emitOpError(
-        "requires exactly one target/dispatch region handle"));
+    return emitDefiniteFailure(
+        "requires exactly one target/dispatch region handle");
 
   auto regionOp = dyn_cast<Flow::DispatchRegionOp>(dispatchRegion.front());
   if (!regionOp)
-    return DiagnosedSilenceableFailure(
-        this->emitOpError("expected 'dispatch.region' operand"));
+    return emitDefiniteFailure("expected 'dispatch.region' operand");
 
   // We are cloning ops one-by-one, so the order must be inversed (as opposed
   // to cloning all ops in one go).
@@ -533,13 +530,12 @@
   for (Operation *target : orderedTargets) {
     FailureOr<Operation *> clonedTarget =
         clonePrecedingOpIntoDispatchRegion(rewriter, target, regionOp);
-    if (failed(clonedTarget))
-      return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
+    if (failed(clonedTarget)) return emitDefaultDefiniteFailure(target);
     clonedTargets.push_back(*clonedTarget);
   }
 
   transformResults.set(getCloned().cast<OpResult>(), clonedTargets);
-  return DiagnosedSilenceableFailure(success());
+  return DiagnosedSilenceableFailure::success();
 }
 
 void transform_dialect::ClonePrecedingOpIntoDispatchRegionOp::getEffects(
@@ -565,13 +561,12 @@
   }
 
   if (dispatchRegion.size() != 1)
-    return DiagnosedSilenceableFailure(this->emitOpError(
-        "requires exactly one target/dispatch region handle"));
+    return emitDefiniteFailure(
+        "requires exactly one target/dispatch region handle");
 
   auto regionOp = dyn_cast<Flow::DispatchRegionOp>(dispatchRegion.front());
   if (!regionOp)
-    return DiagnosedSilenceableFailure(
-        this->emitOpError("expected 'dispatch.region' operand"));
+    return emitDefiniteFailure("expected 'dispatch.region' operand");
 
   // We are cloning ops one-by-one, so the order must be inversed (as opposed
   // to cloning all ops in one go).
@@ -585,14 +580,13 @@
   for (Operation *target : orderedTargets) {
     auto newRegionOp =
         movePrecedingOpIntoDispatchRegion(rewriter, target, regionOp);
-    if (failed(newRegionOp))
-      return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
+    if (failed(newRegionOp)) return emitDefaultDefiniteFailure(target);
     regionOp = *newRegionOp;
   }
 
   transformResults.set(getTransformed().cast<OpResult>(),
                        regionOp.getOperation());
-  return DiagnosedSilenceableFailure(success());
+  return DiagnosedSilenceableFailure::success();
 }
 
 void transform_dialect::MovePrecedingOpIntoDispatchRegionOp::getEffects(
@@ -757,13 +751,11 @@
       state.getPayloadOps(getDispatchRegion());
 
   if (dispatchRegion.size() != 1)
-    return DiagnosedSilenceableFailure(
-        this->emitOpError("requires exactly one dispatch region handle"));
+    return emitDefiniteFailure("requires exactly one dispatch region handle");
 
   auto regionOp = dyn_cast<Flow::DispatchRegionOp>(dispatchRegion.front());
   if (!regionOp)
-    return DiagnosedSilenceableFailure(
-        this->emitOpError("expected 'dispatch.region' operand"));
+    return emitDefiniteFailure("expected 'dispatch.region' operand");
 
   SmallVector<Operation *> orderedTargets(targetOps.begin(), targetOps.end());
   bool sortResult = computeTopologicalSorting(orderedTargets);
@@ -780,7 +772,7 @@
   }
 
   transformResults.set(getCloned().cast<OpResult>(), newTargets);
-  return DiagnosedSilenceableFailure(success());
+  return DiagnosedSilenceableFailure::success();
 }
 
 void transform_dialect::CloneSucceedingOpIntoDispatchRegionOp::getEffects(
@@ -800,13 +792,12 @@
       state.getPayloadOps(getDispatchRegion());
 
   if (dispatchRegion.size() != 1)
-    return DiagnosedSilenceableFailure(this->emitOpError(
-        "requires exactly one target/dispatch region handle"));
+    return emitDefiniteFailure(
+        "requires exactly one target/dispatch region handle");
 
   auto regionOp = dyn_cast<Flow::DispatchRegionOp>(dispatchRegion.front());
   if (!regionOp)
-    return DiagnosedSilenceableFailure(
-        this->emitOpError("expected 'dispatch.region' operand"));
+    return emitDefiniteFailure("expected 'dispatch.region' operand");
 
   SmallVector<Operation *> orderedTargets(targetOps.begin(), targetOps.end());
   bool sortResult = computeTopologicalSorting(orderedTargets);
@@ -823,7 +814,7 @@
 
   transformResults.set(getTransformed().cast<OpResult>(),
                        regionOp.getOperation());
-  return DiagnosedSilenceableFailure(success());
+  return DiagnosedSilenceableFailure::success();
 }
 
 void transform_dialect::MoveSucceedingOpIntoDispatchRegionOp::getEffects(
@@ -839,21 +830,20 @@
     Operation *target, SmallVectorImpl<Operation *> &results,
     transform::TransformState &state) {
   IRRewriter rewriter(target->getContext());
-  Optional<Flow::WorkloadBuilder> workloadBuilder = llvm::None;
+  Optional<Flow::WorkloadBuilder> workloadBuilder = std::nullopt;
   if (getGenerateWorkload()) {
     auto maybeBuilder = Flow::getWorkloadBuilder(rewriter, target);
     if (failed(maybeBuilder)) {
-      return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
+      return emitDefaultDefiniteFailure(target);
     }
     workloadBuilder = *maybeBuilder;
   }
   auto regionOp =
       Flow::wrapOpInDispatchRegion(rewriter, target, workloadBuilder);
-  if (failed(regionOp))
-    return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
+  if (failed(regionOp)) return emitDefaultDefiniteFailure(target);
 
   results.push_back(*regionOp);
-  return DiagnosedSilenceableFailure(success());
+  return DiagnosedSilenceableFailure::success();
 }
 
 void transform_dialect::WrapInDispatchRegionOp::getEffects(
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertLinalgMatmulToMmt4D.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertLinalgMatmulToMmt4D.cpp
index 0b1dd74..af6c043 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertLinalgMatmulToMmt4D.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertLinalgMatmulToMmt4D.cpp
@@ -387,7 +387,7 @@
         "generic tiling parameters, as no known kernel was "
         "matched for this matmul and target");
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 /// Canonicalizes [tensor.empty() -> linalg.fill -> linalg.generic] ->
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertRegionToWorkgroups.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertRegionToWorkgroups.cpp
index cbd86ae..20d6039 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertRegionToWorkgroups.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertRegionToWorkgroups.cpp
@@ -61,11 +61,11 @@
     auto tiedOpInterface = value.getDefiningOp<IREE::Util::TiedOpInterface>();
     if (!tiedOpInterface)
       // Reached an op that does not implement the interface.
-      return llvm::None;
+      return std::nullopt;
     value = tiedOpInterface.getTiedResultOperand(value);
     if (!value)
       // Nothing is tied here.
-      return llvm::None;
+      return std::nullopt;
   }
 
   return value;
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/DumpDispatchGraph.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/DumpDispatchGraph.cpp
index df33e3c..410f3fa 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/DumpDispatchGraph.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/DumpDispatchGraph.cpp
@@ -118,7 +118,7 @@
 /// cluster, an invisible "anchor" node is created.
 struct Node {
  public:
-  Node(int id = 0, Optional<int> clusterId = llvm::None)
+  Node(int id = 0, Optional<int> clusterId = std::nullopt)
       : id(id), clusterId(clusterId) {}
 
   int id;
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/FormDispatchRegions.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/FormDispatchRegions.cpp
index 3bbe7e8..be65059 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/FormDispatchRegions.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/FormDispatchRegions.cpp
@@ -393,7 +393,7 @@
 static Optional<OpOperand *> getFusableUse(Operation *op,
                                            DominanceInfo const &dominanceInfo,
                                            bool fuseMultiUse) {
-  if (!fuseMultiUse && !op->hasOneUse()) return llvm::None;
+  if (!fuseMultiUse && !op->hasOneUse()) return std::nullopt;
 
   for (auto &use : op->getUses()) {
     Operation *user = use.getOwner();
@@ -403,7 +403,7 @@
       return &use;
     }
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 /// Returns true if the operands are fusable under the aggressive fusion
@@ -731,7 +731,7 @@
       workloadBuilders;
   for (const auto &it : llvm::enumerate(roots)) {
     // Compute workload.
-    Optional<Flow::WorkloadBuilder> workloadBuilder = llvm::None;
+    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 e078d66..1185bdd 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/FormDispatchWorkgroups.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/FormDispatchWorkgroups.cpp
@@ -155,7 +155,7 @@
     mlir::TensorDimTrackingRewriter &rewriter, Operation *op,
     bool generateWorkloadRegion) {
   // Compute workload.
-  Optional<Flow::WorkloadBuilder> workloadBuilder = llvm::None;
+  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 d306e85..4a77bd6 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/FusionOfTensorOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/FusionOfTensorOps.cpp
@@ -52,11 +52,11 @@
       for (OpOperand &operand : sourceOp->getOpOperands()) {
         if (operand.get().getDefiningOp() == op) numUsesOfOp++;
       }
-      if (numUsesOfOp != 1) return llvm::None;
+      if (numUsesOfOp != 1) return std::nullopt;
       return &source;
     }
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 /// Check if the producer generic op is fusable with the consumer generic op.
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.cpp
index 843ffad..5d67ae1 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.cpp
@@ -302,7 +302,7 @@
 FailureOr<Flow::DispatchRegionOp> Flow::wrapOpInDispatchRegion(
     RewriterBase &rewriter, Operation *op,
     Optional<Flow::WorkloadBuilder> workloadBuilder) {
-  Optional<ValueRange> workload = llvm::None;
+  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 6fffbf5..a7cd075 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.h
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.h
@@ -40,7 +40,7 @@
 /// Create an DispatchRegionOp with workload
 Flow::DispatchRegionOp makeDispatchRegionWithWorkload(
     OpBuilder &builder, Location loc,
-    Optional<ValueRange> workload = llvm::None);
+    Optional<ValueRange> workload = std::nullopt);
 
 /// Clone a `target` op that is preceding the given dispatch region op into the
 /// dispatch region.
@@ -82,7 +82,7 @@
 /// Wrap the given op in a new dispatch region op.
 FailureOr<Flow::DispatchRegionOp> wrapOpInDispatchRegion(
     RewriterBase &rewriter, Operation *op,
-    Optional<Flow::WorkloadBuilder> workloadBuilder = llvm::None);
+    Optional<Flow::WorkloadBuilder> workloadBuilder = std::nullopt);
 
 }  // namespace Flow
 }  // namespace IREE
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/SetEncoding.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/SetEncoding.cpp
index 27cb387..89f356e 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/SetEncoding.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/SetEncoding.cpp
@@ -65,7 +65,7 @@
 /// return `value` itself.
 static FailureOr<Value> padIfNeeded(OpBuilder &builder, Location loc,
                                     Value value,
-                                    Optional<int64_t> padding = llvm::None) {
+                                    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/StreamToHAL/Patterns.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/Patterns.cpp
index 8bcd7c9..573c089 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/Patterns.cpp
@@ -748,7 +748,7 @@
     IREE::Stream::CollectiveAttr sourceAttr) {
   auto convertReductionOp = [](Optional<IREE::Stream::CollectiveReductionOp> op)
       -> Optional<IREE::HAL::CollectiveReductionOp> {
-    if (!op.has_value()) return llvm::None;
+    if (!op.has_value()) return std::nullopt;
     return static_cast<IREE::HAL::CollectiveReductionOp>(op.value());
   };
   return IREE::HAL::CollectiveAttr::get(
@@ -1268,7 +1268,7 @@
     auto initialValue = op.getInitialValue();
     if (!initialValue.has_value()) return failure();
     if (!initialValue->isa<IREE::Stream::TimepointAttr>()) return failure();
-    rewriter.updateRootInPlace(op, [&]() { op.removeInitial_valueAttr(); });
+    rewriter.updateRootInPlace(op, [&]() { op.removeInitialValueAttr(); });
     return success();
   }
 };
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/TypeConverter.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/TypeConverter.cpp
index 3fa9c5c..393d7d4 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/TypeConverter.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/TypeConverter.cpp
@@ -35,7 +35,7 @@
     if (HALTypeConverter::shouldConvertToBufferView(type)) {
       return IREE::HAL::BufferViewType::get(type.getContext());
     }
-    return llvm::None;
+    return std::nullopt;
   });
 
   addTargetMaterialization([](OpBuilder &builder, IREE::HAL::BufferType type,
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOpFolders.cpp b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOpFolders.cpp
index c152b96..e4941eb 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOpFolders.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOpFolders.cpp
@@ -15,6 +15,7 @@
 #include "mlir/IR/Attributes.h"
 #include "mlir/IR/BlockAndValueMapping.h"
 #include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/Matchers.h"
 #include "mlir/IR/OpDefinition.h"
 #include "mlir/IR/OpImplementation.h"
@@ -569,7 +570,8 @@
     auto fusedLoc = rewriter.getFusedLoc(blockLocs);
     auto newBlockOp = rewriter.create<ExecutableConstantBlockOp>(
         fusedLoc, rewriter.getFunctionType(inputTypes, resultTypes),
-        rewriter.getArrayAttr(resultKeys));
+        rewriter.getArrayAttr(resultKeys), /*arg_attrs=*/ArrayAttr(),
+        /*res_attrs=*/ArrayAttr());
 
     // Create the entry block that captures the optional device argument and
     // the exit block that returns the final flattened set of keys.
@@ -770,7 +772,7 @@
 };
 
 // Produces a deduplicated and null-elided operand list.
-// Returns None if nothing changed.
+// Returns std::nullopt if nothing changed.
 static Optional<std::vector<Value>> deduplicateFenceOperands(
     ValueRange operands) {
   SetVector<Value> newOperands;
@@ -783,7 +785,7 @@
     newOperands.insert(operand);
   }
 
-  if (newOperands.size() == operands.size()) return None;
+  if (newOperands.size() == operands.size()) return std::nullopt;
   return newOperands.takeVector();
 }
 
@@ -831,7 +833,7 @@
   LogicalResult matchAndRewrite(FenceAwaitOp op,
                                 PatternRewriter &rewriter) const override {
     auto newOperands = deduplicateFenceOperands(op.getFences());
-    if (newOperands == None) return failure();
+    if (newOperands == std::nullopt) return failure();
     rewriter.replaceOpWithNewOp<FenceAwaitOp>(op, op.getStatus().getType(),
                                               op.getTimeoutMillis(),
                                               newOperands.value());
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp
index efa16f9..b17a6b9 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp
@@ -910,8 +910,9 @@
   }
   SmallVector<Type> argTypes;
   for (auto &arg : entryArgs) argTypes.push_back(arg.type);
-  result.addAttribute("function_type", TypeAttr::get(builder.getFunctionType(
-                                           argTypes, resultTypes)));
+  auto fnType = builder.getFunctionType(argTypes, resultTypes);
+  result.addAttribute(getFunctionTypeAttrName(result.name),
+                      TypeAttr::get(fnType));
 
   // Parse the keys used for each yielded constant value.
   // There must be one key per result. Note that we support omitted parens when
@@ -946,8 +947,9 @@
 
   // Add the attributes to the function arguments.
   assert(resultAttrs.size() == resultTypes.size());
-  mlir::function_interface_impl::addArgAndResultAttrs(builder, result,
-                                                      entryArgs, resultAttrs);
+  mlir::function_interface_impl::addArgAndResultAttrs(
+      builder, result, entryArgs, resultAttrs, getArgAttrsAttrName(result.name),
+      getResAttrsAttrName(result.name));
 
   // Parse the optional function body. The printer will not print the body if
   // its empty, so disallow parsing of empty body in the parser.
@@ -977,7 +979,7 @@
                         [&](Attribute attr) { p << attr; });
   if (resultTypes.size() != 1) p << ')';
   mlir::function_interface_impl::printFunctionAttributes(
-      p, op, argTypes.size(), resultTypes.size(), {"keys"});
+      p, op, {getFunctionTypeAttrName(), getKeysAttrName()});
   p << " ";
   p.printRegion(getBody(), /*printEntryBlockArgs=*/false,
                 /*printBlockTerminators=*/true);
@@ -1097,7 +1099,7 @@
   }
 
   // TODO(benvanik): more searching.
-  return llvm::None;
+  return std::nullopt;
 }
 
 llvm::Align InterfaceBindingSubspanOp::calculateAlignment() {
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.td b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.td
index d69674b..d12ea15 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.td
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.td
@@ -1341,7 +1341,7 @@
   let builders = [
     OpBuilder<(ins),
     [{
-      build($_builder, $_state, llvm::None);
+      build($_builder, $_state, std::nullopt);
     }]>,
   ];
 
@@ -1830,7 +1830,9 @@
 
   let arguments = (ins
     TypeAttrOf<FunctionType>:$function_type,
-    ArrayAttr:$keys
+    ArrayAttr:$keys,
+    OptionalAttr<DictArrayAttr>:$arg_attrs,
+    OptionalAttr<DictArrayAttr>:$res_attrs
   );
 
   let regions = (region AnyRegion:$body);
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.cpp b/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.cpp
index bec97cf..3c20b2d 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.cpp
@@ -123,14 +123,14 @@
         return makeElementTypeValue(NumericalType::kFloatBrain,
                                     floatType.getWidth());
       default:
-        return llvm::None;
+        return std::nullopt;
     }
   } else if (auto complexType = type.dyn_cast_or_null<ComplexType>()) {
     return makeElementTypeValue(
         NumericalType::kFloatComplex,
         complexType.getElementType().getIntOrFloatBitWidth() * 2);
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 llvm::Optional<int32_t> getEncodingTypeValue(Attribute attr) {
@@ -486,13 +486,13 @@
           << "ERROR: referenced object file not found on any path; use "
              "--iree-hal-executable-object-search-path= to add search paths: "
           << *this << "\n";
-      return None;
+      return std::nullopt;
     }
     auto file = llvm::MemoryBuffer::getFile(*filePath);
-    if (!file) return None;
+    if (!file) return std::nullopt;
     return std::string((*file)->getBuffer());
   }
-  return None;
+  return std::nullopt;
 }
 
 //===----------------------------------------------------------------------===//
@@ -569,7 +569,7 @@
       allObjectAttrs.append(objectsArrayAttr.begin(), objectsArrayAttr.end());
     }
   }
-  if (allObjectAttrs.empty()) return None;
+  if (allObjectAttrs.empty()) return std::nullopt;
   return ArrayAttr::get(specificTargetAttr.getContext(), allObjectAttrs);
 }
 
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 b73c8c7..3d9febf 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/CUDA/CUDATarget.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/CUDA/CUDATarget.cpp
@@ -155,7 +155,7 @@
   llvm::StandardInstrumentations si(module.getContext(), false);
   si.registerCallbacks(pic, &fam);
 
-  llvm::PassBuilder pb(&targetMachine, pto, llvm::None, &pic);
+  llvm::PassBuilder pb(&targetMachine, pto, std::nullopt, &pic);
   pb.registerModuleAnalyses(mam);
   pb.registerCGSCCAnalyses(cgam);
   pb.registerFunctionAnalyses(fam);
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/LinkerTool.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/LinkerTool.cpp
index 943760e..d84d26d 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/LinkerTool.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/LinkerTool.cpp
@@ -65,7 +65,7 @@
   auto fileData = llvm::MemoryBuffer::getFile(path);
   if (!fileData) {
     llvm::errs() << "failed to load library output file '" << path << "'";
-    return llvm::None;
+    return std::nullopt;
   }
   auto sourceBuffer = fileData.get()->getBuffer();
   std::vector<int8_t> resultBuffer(sourceBuffer.size());
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/AndroidLinkerTool.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/AndroidLinkerTool.cpp
index 2799ad9..f1b7756 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/AndroidLinkerTool.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/AndroidLinkerTool.cpp
@@ -216,7 +216,7 @@
     flagsToPrefixForLinker.clear();
 
     auto commandLine = llvm::join(flags, " ");
-    if (failed(runLinkCommand(commandLine))) return llvm::None;
+    if (failed(runLinkCommand(commandLine))) return std::nullopt;
     return artifacts;
   }
 };
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/EmbeddedLinkerTool.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/EmbeddedLinkerTool.cpp
index ce86f66..d196961 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/EmbeddedLinkerTool.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/EmbeddedLinkerTool.cpp
@@ -101,7 +101,7 @@
     artifacts.libraryFile.close();
 
     std::string embeddedToolPath = getEmbeddedToolPath();
-    if (embeddedToolPath.empty()) return llvm::None;
+    if (embeddedToolPath.empty()) return std::nullopt;
 
     SmallVector<std::string, 8> flags = {
         embeddedToolPath,
@@ -188,7 +188,7 @@
           }
         }
       }
-      return llvm::None;
+      return std::nullopt;
     }
     return artifacts;
   }
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/UnixLinkerTool.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/UnixLinkerTool.cpp
index e9c0de5..49ae141 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/UnixLinkerTool.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/UnixLinkerTool.cpp
@@ -127,7 +127,7 @@
     }
 
     auto commandLine = llvm::join(flags, " ");
-    if (failed(runLinkCommand(commandLine))) return llvm::None;
+    if (failed(runLinkCommand(commandLine))) return std::nullopt;
     return artifacts;
   }
 
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/WasmLinkerTool.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/WasmLinkerTool.cpp
index c99f810..410096d 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/WasmLinkerTool.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/WasmLinkerTool.cpp
@@ -129,7 +129,7 @@
     }
 
     auto commandLine = llvm::join(flags, " ");
-    if (failed(runLinkCommand(commandLine))) return llvm::None;
+    if (failed(runLinkCommand(commandLine))) return std::nullopt;
     return artifacts;
   }
 };
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/WindowsLinkerTool.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/WindowsLinkerTool.cpp
index d8c52d9..e29fe94 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/WindowsLinkerTool.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/LLVM/internal/WindowsLinkerTool.cpp
@@ -192,7 +192,7 @@
       llvm::errs() << "required environment for lld-link/link not specified; "
                       "ensure you are building from a shell where "
                       "vcvarsall/VsDevCmd.bat/etc has been used";
-      return llvm::None;
+      return std::nullopt;
     }
     const char *arch;
     if (targetTriple.isARM() && targetTriple.isArch32Bit()) {
@@ -206,7 +206,7 @@
     } else {
       llvm::errs() << "unsupported Windows target triple (no arch libs): "
                    << targetTriple.str();
-      return llvm::None;
+      return std::nullopt;
     }
     flags.push_back(
         llvm::formatv("/libpath:\"{0}\\lib\\{1}\"", "%VCToolsInstallDir%", arch)
@@ -262,7 +262,7 @@
     }
 
     auto commandLine = llvm::join(flags, " ");
-    if (failed(runLinkCommand(commandLine))) return llvm::None;
+    if (failed(runLinkCommand(commandLine))) return std::nullopt;
 
     // PDB file gets generated wtih the same path + .pdb.
     artifacts.debugFile =
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 e5d3aa7..6d6c201 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/SPIRVToMSL.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/SPIRVToMSL.cpp
@@ -136,7 +136,7 @@
   auto workgroupSize =
       spvCrossCompiler.getWorkgroupSizeForEntryPoint(entryPoint);
   if (!workgroupSize.x || !workgroupSize.y || !workgroupSize.z) {
-    return llvm::None;
+    return std::nullopt;
   }
   return MetalShader{std::move(mslSource), workgroupSize};
 }
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 75ad986..37b4ad6 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/SPIRVToMSL.h
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/MetalSPIRV/SPIRVToMSL.h
@@ -28,7 +28,7 @@
 };
 
 // Cross compiles SPIR-V into Metal Shading Language source code for the
-// compute shader with |entryPoint|. Returns llvm::None on failure.
+// compute shader with |entryPoint|. Returns std::nullopt on failure.
 llvm::Optional<MetalShader> crossCompileSPIRVToMSL(
     llvm::ArrayRef<uint32_t> spvBinary, StringRef entryPoint);
 
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Target/ROCM/ROCMTargetUtils.cpp b/compiler/src/iree/compiler/Dialect/HAL/Target/ROCM/ROCMTargetUtils.cpp
index 9f8bae8..d309fae 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/ROCM/ROCMTargetUtils.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/ROCM/ROCMTargetUtils.cpp
@@ -188,7 +188,7 @@
   // Executing LLD
   std::string errorMessage;
   int lldResult = llvm::sys::ExecuteAndWait(
-      lldProgram, llvm::ArrayRef<llvm::StringRef>(lldArgs), llvm::None, {}, 5,
+      lldProgram, llvm::ArrayRef<llvm::StringRef>(lldArgs), std::nullopt, {}, 5,
       0, &errorMessage);
   if (lldResult) {
     llvm::WithColor::error(llvm::errs(), name)
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 a8930a7..79f7387 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/WebGPU/SPIRVToWGSL.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/WebGPU/SPIRVToWGSL.cpp
@@ -30,26 +30,26 @@
       std::make_unique<tint::Program>(tint::reader::spirv::Parse(binaryVector));
   if (!program) {
     llvm::errs() << "Tint failed to parse SPIR-V program\n";
-    return llvm::None;
+    return std::nullopt;
   }
 
   if (program->Diagnostics().contains_errors()) {
     llvm::errs() << "Tint reported " << program->Diagnostics().error_count()
                  << " error(s) for a SPIR-V program, see diagnostics:\n";
     diagFormatter.format(program->Diagnostics(), diagPrinter.get());
-    return llvm::None;
+    return std::nullopt;
   }
 
   if (!program->IsValid()) {
     llvm::errs() << "Tint parsed an invalid SPIR-V program\n";
-    return llvm::None;
+    return std::nullopt;
   }
 
   tint::writer::wgsl::Options genOptions;
   auto result = tint::writer::wgsl::Generate(program.get(), genOptions);
   if (!result.success) {
     llvm::errs() << "Tint failed to generate WGSL: " << result.error << "\n";
-    return llvm::None;
+    return std::nullopt;
   }
 
   return result.wgsl;
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 c712631..f6d8ce0 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Target/WebGPU/SPIRVToWGSL.h
+++ b/compiler/src/iree/compiler/Dialect/HAL/Target/WebGPU/SPIRVToWGSL.h
@@ -18,7 +18,7 @@
 namespace HAL {
 
 // Compiles SPIR-V into WebGPU Shading Language (WGSL) source code.
-// Returns llvm::None on failure.
+// Returns std::nullopt on failure.
 llvm::Optional<std::string> compileSPIRVToWGSL(
     llvm::ArrayRef<uint32_t> spvBinary);
 
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Analysis/ResourceUsage.cpp b/compiler/src/iree/compiler/Dialect/Stream/Analysis/ResourceUsage.cpp
index 81aa487..2e388ec 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Analysis/ResourceUsage.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Analysis/ResourceUsage.cpp
@@ -668,7 +668,7 @@
 ResourceUsageAnalysis::tryLookupResourceUsage(Value value) {
   auto resourceUsage =
       solver.lookupElementFor<ValueResourceUsage>(Position::forValue(value));
-  if (!resourceUsage) return llvm::None;
+  if (!resourceUsage) return std::nullopt;
   return resourceUsage->getAssumedUsage();
 }
 
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 674d7134..7a0ff72 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Conversion/UtilToStream/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Conversion/UtilToStream/Patterns.cpp
@@ -94,7 +94,7 @@
         globalOp, globalOp.getName(), globalOp.getIsMutable(), resourceType,
         initialValue && !tensorInitializerRequired
             ? llvm::Optional<TypedAttr>{initialValue}
-            : llvm::None);
+            : std::nullopt);
     resourceOp.setVisibility(globalOp.getVisibility());
 
     // NOTE: we ignore noinline here, possibly to our peril. In earlier dialects
diff --git a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOpFolders.cpp b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOpFolders.cpp
index 1a2f70f..3528272 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOpFolders.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOpFolders.cpp
@@ -48,11 +48,11 @@
 //    stream.yield
 //  }
 static Optional<IREE::Stream::YieldOp> getYieldIfOnlyOp(Block &block) {
-  if (block.empty()) return llvm::None;
-  if (&block.front() != &block.back()) return llvm::None;
+  if (block.empty()) return std::nullopt;
+  if (&block.front() != &block.back()) return std::nullopt;
   auto yieldOp = dyn_cast<IREE::Stream::YieldOp>(block.back());
   if (yieldOp) return yieldOp;
-  return llvm::None;
+  return std::nullopt;
 }
 
 // Finds the insertion point before |targetOp| and after |earliestOp| that would
diff --git a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.cpp b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.cpp
index d2cb187..9d1a894 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.cpp
@@ -287,7 +287,7 @@
   } else if (str == "constant") {
     return Lifetime::Constant;
   } else {
-    return llvm::None;
+    return std::nullopt;
   }
 }
 
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp
index 5c7f3a4..db22870 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp
@@ -855,7 +855,7 @@
   }
   if (transientValues.empty()) {
     // No transients required.
-    return llvm::None;
+    return std::nullopt;
   }
 
   // Insert the stream.resource.pack op to compute the slices and total size of
@@ -929,7 +929,7 @@
   // Gather all constant ops from the region, if any.
   auto constantOps =
       llvm::to_vector<4>(executeOp.getOps<IREE::Stream::AsyncConstantOp>());
-  if (constantOps.empty()) return llvm::None;
+  if (constantOps.empty()) return std::nullopt;
 
   // Allocate a new constant upload op and insert a subview for each constant.
   SmallVector<Location> locs;
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/VerifyLowerings.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/VerifyLowerings.cpp
index 7b77452..0902d82 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/VerifyLowerings.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/VerifyLowerings.cpp
@@ -74,7 +74,7 @@
       if (auto op = dyn_cast<OpT>(baseOp)) {
         return fn(op);
       }
-      return llvm::None;
+      return std::nullopt;
     };
     opVerifiers.push_back(wrapperFn);
   }
@@ -217,7 +217,7 @@
     if (op->hasTrait<OpTrait::IREE::Stream::TensorPhaseOp>()) {
       return Verifier::Legality::ILLEGAL;
     }
-    return llvm::None;
+    return std::nullopt;
   });
 }
 
@@ -226,7 +226,7 @@
     if (op->hasTrait<OpTrait::IREE::Stream::AsyncPhaseOp>()) {
       return Verifier::Legality::ILLEGAL;
     }
-    return llvm::None;
+    return std::nullopt;
   });
 }
 
@@ -235,7 +235,7 @@
     if (op->hasTrait<OpTrait::IREE::Stream::CmdPhaseOp>()) {
       return Verifier::Legality::ILLEGAL;
     }
-    return llvm::None;
+    return std::nullopt;
   });
 }
 
@@ -366,7 +366,7 @@
                 << ": streamable op expected to be in an execution region";
             return Verifier::Legality::ILLEGAL;
           }
-          return llvm::None;
+          return std::nullopt;
         });
 
     if (failed(verifier.run(getOperation()))) {
diff --git a/compiler/src/iree/compiler/Dialect/Util/Analysis/Explorer.cpp b/compiler/src/iree/compiler/Dialect/Util/Analysis/Explorer.cpp
index 28bb23e..7790680 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Analysis/Explorer.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Analysis/Explorer.cpp
@@ -33,14 +33,14 @@
   // I don't know if there's a better way to do this - the interface doesn't
   // help.
   auto operandRange = branchOp.getSuccessorOperands(successorIdx);
-  if (operandRange.empty()) return llvm::None;
+  if (operandRange.empty()) return std::nullopt;
   unsigned beginIdx =
       operandRange.getForwardedOperands().getBeginOperandIndex();
   if (operandIdx >= beginIdx && operandIdx < beginIdx + operandRange.size()) {
     // Covered.
     return {operandIdx - beginIdx};
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 Explorer::Explorer(Operation *rootOp, TraversalAction defaultAction)
@@ -459,7 +459,7 @@
   return walkReturnOps(parentOp, [&](Operation *returnOp) {
     if (auto terminatorOp =
             dyn_cast<RegionBranchTerminatorOpInterface>(returnOp)) {
-      return fn(terminatorOp.getSuccessorOperands(llvm::None));
+      return fn(terminatorOp.getSuccessorOperands(std::nullopt));
     } else {
       return fn(returnOp->getOperands());
     }
@@ -477,7 +477,7 @@
     auto *parentOp = targetBlock->getParentOp();
     if (auto regionOp = dyn_cast<RegionBranchOpInterface>(parentOp)) {
       SmallVector<RegionSuccessor, 2> entrySuccessors;
-      regionOp.getSuccessorRegions(/*index=*/llvm::None, entrySuccessors);
+      regionOp.getSuccessorRegions(/*index=*/std::nullopt, entrySuccessors);
       for (auto &entrySuccessor : entrySuccessors) {
         if (fn(regionOp->getBlock(),
                regionOp.getSuccessorEntryOperands(
@@ -797,7 +797,7 @@
   auto traverseRegionOp = [&](RegionBranchOpInterface regionOp,
                               unsigned operandIdx) {
     SmallVector<RegionSuccessor, 2> entrySuccessors;
-    regionOp.getSuccessorRegions(/*index=*/llvm::None, entrySuccessors);
+    regionOp.getSuccessorRegions(/*index=*/std::nullopt, entrySuccessors);
     for (auto &entrySuccessor : entrySuccessors) {
       auto successorInputs = entrySuccessor.getSuccessorInputs();
       if (operandIdx >= successorInputs.size()) {
@@ -821,7 +821,7 @@
   // Move within/out-of a region.
   auto traverseRegionBranchOp = [&](RegionBranchTerminatorOpInterface branchOp,
                                     unsigned operandIdx) {
-    auto successorOperands = branchOp.getSuccessorOperands(llvm::None);
+    auto successorOperands = branchOp.getSuccessorOperands(std::nullopt);
     unsigned beginIdx = successorOperands.getBeginOperandIndex();
     if (operandIdx < beginIdx ||
         operandIdx >= beginIdx + successorOperands.size()) {
@@ -831,7 +831,7 @@
                  << operandIdx << "\n");
       return TraversalResult::COMPLETE;
     }
-    auto result = branchOp.getSuccessorOperands(llvm::None)[operandIdx];
+    auto result = branchOp.getSuccessorOperands(std::nullopt)[operandIdx];
     LLVM_DEBUG({
       llvm::dbgs() << "   + queuing region result ";
       result.printAsOperand(llvm::dbgs(), asmState);
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 a3ddc56..5abe08d 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Conversion/MemRefToUtil/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Conversion/MemRefToUtil/Patterns.cpp
@@ -279,7 +279,7 @@
             return IREE::Util::BufferType::get(type.getContext());
           }
         }
-        return llvm::None;
+        return std::nullopt;
       });
 
   patterns
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilInterfaces.td b/compiler/src/iree/compiler/Dialect/Util/IR/UtilInterfaces.td
index 5dccf05..0d2d470 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilInterfaces.td
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilInterfaces.td
@@ -232,7 +232,7 @@
         if (value) {
           $_op.setIsMutableAttr(UnitAttr::get($_op.getContext()));
         } else {
-          $_op.removeIs_mutableAttr();
+          $_op.removeIsMutableAttr();
         }
       }]
     >,
@@ -263,7 +263,7 @@
           // Not fantastic but the typed attr may not accept Attribute.
           $_op->setAttr("initial_value", (value));
         } else {
-          $_op.removeInitial_valueAttr();
+          $_op.removeInitialValueAttr();
         }
       }]
     >,
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp
index 21ac8c8..a1769e3 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp
@@ -786,7 +786,7 @@
 void GlobalOp::build(OpBuilder &builder, OperationState &result, StringRef name,
                      bool isMutable, Type type,
                      ArrayRef<NamedAttribute> attrs) {
-  build(builder, result, name, isMutable, type, llvm::None, attrs);
+  build(builder, result, name, isMutable, type, std::nullopt, attrs);
 }
 
 void GlobalAddressOp::getAsmResultNames(
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.td b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.td
index 0fceb70..0c41ae2 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.td
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.td
@@ -393,7 +393,9 @@
   }];
 
   let arguments = (ins
-    TypeAttrOf<FunctionType>:$function_type
+    TypeAttrOf<FunctionType>:$function_type,
+    OptionalAttr<DictArrayAttr>:$arg_attrs,
+    OptionalAttr<DictArrayAttr>:$res_attrs    
   );
 
   let regions = (region AnyRegion:$body);
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.cpp b/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.cpp
index d574deb..f3db7f9 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.cpp
@@ -298,16 +298,16 @@
     Operation *op, unsigned resultIndex) {
   auto storageAttr =
       op->getAttrOfType<ArrayAttr>(TiedOpInterface::getStorageAttrName());
-  if (!storageAttr) return llvm::None;
+  if (!storageAttr) return std::nullopt;
   auto valueAttrs = storageAttr.getValue();
-  if (valueAttrs.empty()) return llvm::None;
+  if (valueAttrs.empty()) return std::nullopt;
   auto tiedOp = cast<TiedOpInterface>(op);
   auto indexAndLength = tiedOp.getTiedResultsIndexAndLength();
-  if (resultIndex < indexAndLength.first) return None;
+  if (resultIndex < indexAndLength.first) return std::nullopt;
   resultIndex -= indexAndLength.first;
-  if (resultIndex >= indexAndLength.second) return None;
+  if (resultIndex >= indexAndLength.second) return std::nullopt;
   int64_t value = valueAttrs[resultIndex].cast<IntegerAttr>().getInt();
-  if (value == TiedOpInterface::kUntiedIndex) return llvm::None;
+  if (value == TiedOpInterface::kUntiedIndex) return std::nullopt;
   unsigned tiedOperandsOffset = tiedOp.getTiedOperandsIndexAndLength().first;
   return tiedOperandsOffset + static_cast<unsigned>(value);
 }
@@ -562,7 +562,7 @@
       if (tiedValue) worklist.push_back(tiedValue);
     }
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 Optional<ValueRange> findDynamicDims(Value shapedValue, Block *block,
@@ -588,7 +588,7 @@
     }
   }
 
-  return None;
+  return std::nullopt;
 }
 
 ValueRange findVariadicDynamicDims(unsigned idx, ValueRange values,
diff --git a/compiler/src/iree/compiler/Dialect/Util/Transforms/CombineInitializers.cpp b/compiler/src/iree/compiler/Dialect/Util/Transforms/CombineInitializers.cpp
index be7366a..de41d51 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Transforms/CombineInitializers.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Transforms/CombineInitializers.cpp
@@ -63,7 +63,7 @@
               inlinerInterface, &initializerOp.getBody(),
               builder.getInsertionBlock(), builder.getInsertionPoint(),
               /*inlinedOperands=*/ValueRange{},
-              /*resultsToReplace=*/ValueRange{}, /*inlineLoc=*/llvm::None,
+              /*resultsToReplace=*/ValueRange{}, /*inlineLoc=*/std::nullopt,
               /*shouldCloneInlinedRegion=*/false))) {
         initializerOp.emitOpError()
             << "failed to inline into combined initializer";
diff --git a/compiler/src/iree/compiler/Dialect/VM/Analysis/RegisterAllocation.cpp b/compiler/src/iree/compiler/Dialect/VM/Analysis/RegisterAllocation.cpp
index 40e9f0d..2c9dab9 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Analysis/RegisterAllocation.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Analysis/RegisterAllocation.cpp
@@ -107,7 +107,7 @@
       }
       unsigned int ordinalEnd = ordinalStart + (byteWidth / 4) - 1;
       if (ordinalEnd >= Register::kInt32RegisterCount) {
-        return llvm::None;
+        return std::nullopt;
       }
       bool rangeAvailable = true;
       for (unsigned int ordinal = ordinalStart + 1; ordinal <= ordinalEnd;
@@ -119,7 +119,7 @@
       }
       ordinalStart = intRegisters.find_next_unset(ordinalEnd);
     }
-    return llvm::None;
+    return std::nullopt;
   }
 
   Optional<Register> allocateRegister(Type type) {
@@ -127,7 +127,7 @@
       size_t byteWidth = IREE::Util::getRoundedElementByteWidth(type);
       auto ordinalStartOr = findFirstUnsetIntOrdinalSpan(byteWidth);
       if (!ordinalStartOr.has_value()) {
-        return llvm::None;
+        return std::nullopt;
       }
       int ordinalStart = ordinalStartOr.value();
       unsigned int ordinalEnd = ordinalStart + (byteWidth / 4) - 1;
@@ -138,7 +138,7 @@
     } else {
       int ordinal = refRegisters.find_first_unset();
       if (ordinal >= Register::kRefRegisterCount || ordinal == -1) {
-        return llvm::None;
+        return std::nullopt;
       }
       refRegisters.set(ordinal);
       maxRefRegisterOrdinal = std::max(ordinal, maxRefRegisterOrdinal);
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.cpp
index 2c9aad7..5c74537 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.cpp
@@ -147,7 +147,7 @@
     for (auto elementAttr : arrayAttr) {
       auto flattenedValues =
           rewriteAttrToOperands(loc, elementAttr, inputType, rewriter);
-      if (!flattenedValues) return llvm::None;
+      if (!flattenedValues) return std::nullopt;
       allValues.append(flattenedValues->begin(), flattenedValues->end());
     }
     return allValues;
@@ -181,7 +181,7 @@
             }
             allValues.append(flattenedValues->begin(), flattenedValues->end());
           });
-      if (failed(walkStatus)) return llvm::None;
+      if (failed(walkStatus)) return std::nullopt;
     } else {
       // Custom dialect type maps into zero or more input types (ala arrays).
       LogicalResult walkStatus = conversionInterface->walkAttributeStorage(
@@ -195,14 +195,14 @@
             }
             allValues.append(flattenedValues->begin(), flattenedValues->end());
           });
-      if (failed(walkStatus)) return llvm::None;
+      if (failed(walkStatus)) return std::nullopt;
     }
-    if (anyFailed) return llvm::None;
+    if (anyFailed) return std::nullopt;
     return allValues;
   }
 
   emitError(loc) << "unsupported attribute encoding: " << attrValue;
-  return llvm::None;
+  return std::nullopt;
 }
 
 }  // namespace detail
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.h b/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.h
index 949afbf..3b212d7 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.h
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.h
@@ -78,7 +78,7 @@
     if (auto attrValue = op->getAttr(inputName)) {
       auto flattenedAttrs = detail::rewriteAttrToOperands(
           op.getLoc(), attrValue, inputType, rewriter);
-      if (!flattenedAttrs) return None;
+      if (!flattenedAttrs) return std::nullopt;
       state.addOperands(*flattenedAttrs);
       if (importOp.isFuncArgumentVariadic(input.index())) {
         segmentSizes.push_back(flattenedAttrs->size() /
@@ -98,7 +98,7 @@
         // This only supports a single level of unpacking.
         if (inputTupleType.size() != newOperands.size()) {
           assert(false && "arity mismatch between tuple and variadic");
-          return None;
+          return std::nullopt;
         }
         for (auto it : llvm::zip(newOperands, inputTupleType.getTypes())) {
           state.addOperands(
@@ -140,7 +140,7 @@
     auto result = std::get<0>(resultToType);
     auto targetType = std::get<1>(resultToType);
     targetType = typeConverter.convertType(targetType);
-    if (!targetType) return None;
+    if (!targetType) return std::nullopt;
     results.push_back(castFromImportType(result, targetType, rewriter));
   }
   return results;
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.cpp
index 8ef8839..c159e65 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.cpp
@@ -153,7 +153,7 @@
     // vm.export ops.
     newFuncOp.setPrivate();
 
-    rewriter.replaceOp(srcOp, llvm::None);
+    rewriter.replaceOp(srcOp, std::nullopt);
     return success();
   }
 };
@@ -227,7 +227,7 @@
     // Retain function attributes in the allowlist.
     copyImportAttrs(srcOp, importOp);
 
-    rewriter.replaceOp(srcOp, llvm::None);
+    rewriter.replaceOp(srcOp, std::nullopt);
     return success();
   }
 };
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp
index 3703ebc..97d828f 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp
@@ -35,7 +35,7 @@
     if (RefType::isCompatible(type)) {
       return RefType::get(type);
     }
-    return llvm::None;
+    return std::nullopt;
   });
 
   // Pointer types remain as pointer types types are passed through unmodified.
@@ -44,7 +44,7 @@
     // ptr<i32>, for example).
     auto targetType = convertType(type.getTargetType());
     if (!targetType) {
-      return llvm::None;
+      return std::nullopt;
     }
     return IREE::Util::PtrType::get(targetType);
   });
@@ -58,7 +58,7 @@
       // Promote i1/i8/i16 -> i32.
       return IntegerType::get(integerType.getContext(), 32);
     }
-    return llvm::None;
+    return std::nullopt;
   });
 
   // Convert floating-point types.
@@ -69,14 +69,14 @@
         return FloatType::getF32(floatType.getContext());
       } else {
         // f32 is not supported; can't compile.
-        return llvm::None;
+        return std::nullopt;
       }
     } else if (floatType.isF32()) {
       if (targetOptions_.f32Extension) {
         return floatType;
       } else {
         // f32 is not supported; can't compile.
-        return llvm::None;
+        return std::nullopt;
       }
     } else if (floatType.isF64()) {
       if (targetOptions_.f64Extension) {
@@ -89,7 +89,7 @@
         return FloatType::getF32(floatType.getContext());
       }
     }
-    return llvm::None;
+    return std::nullopt;
   });
 
   // Convert index types to the target bit width.
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 ee942d9..c13015b 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 = llvm::None;
+      llvm::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 = llvm::None;
+      llvm::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 = llvm::None;
+      llvm::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 = llvm::None;
+      llvm::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 4ae220e..5feb336 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertListOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertListOps.cpp
@@ -150,7 +150,7 @@
         } else {
           elementType = typeConverter.convertType(type.getElementType());
         }
-        if (!elementType) return llvm::None;
+        if (!elementType) return std::nullopt;
         return IREE::VM::RefType::get(IREE::VM::ListType::get(elementType));
       });
 
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 c1ea014..b3dfffb 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp
@@ -6,6 +6,8 @@
 
 #include "iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.h"
 
+#include <optional>
+
 #include "iree/compiler/Dialect/Util/Conversion/ConversionPatterns.h"
 #include "iree/compiler/Dialect/Util/IR/UtilDialect.h"
 #include "iree/compiler/Dialect/Util/IR/UtilOps.h"
@@ -277,7 +279,7 @@
                                         IREE::VM::ImportOp &importOp) {
   auto callingConvention = makeImportCallingConventionString(importOp);
   if (!callingConvention.has_value()) {
-    return None;
+    return std::nullopt;
   }
   return moduleOp.getName().str() + "_call_" + callingConvention.value() +
          "_import_shim";
@@ -288,7 +290,7 @@
     DenseIntElementsAttr segmentSizes) {
   auto callingConvention = makeImportCallingConventionString(importOp);
   if (!callingConvention.has_value()) {
-    return None;
+    return std::nullopt;
   }
   std::string result(moduleOp.getName());
   result += "_call_";
@@ -335,7 +337,7 @@
       /*value=*/emitc::OpaqueAttr::get(ctx, ""));
 
   if (failed(clearStruct(rewriter, elementTypeOp.getResult()))) {
-    return None;
+    return std::nullopt;
   }
 
   auto ptr = valueTypeMap.find((elementType));
@@ -351,7 +353,7 @@
                                        /*value=*/ptr->second.second);
   } else {
     if (!elementType.isa<IREE::VM::RefType>()) {
-      return None;
+      return std::nullopt;
     }
     Type objType = elementType.cast<IREE::VM::RefType>().getObjectType();
 
@@ -1350,8 +1352,8 @@
 
  private:
   struct GeneratedStruct {
-    Optional<Value> value = None;
-    Optional<std::string> name = None;
+    Optional<Value> value = std::nullopt;
+    Optional<std::string> name = std::nullopt;
     SmallVector<Value> callArguments;
   };
 
@@ -3769,7 +3771,9 @@
               return std::make_pair(StringRef("IREE_VM_VALUE_TYPE_I64"),
                                     StringRef("iree_vm_value_get_i64"));
             })
-            .Default([](Operation *) { return std::make_pair(None, None); });
+            .Default([](Operation *) {
+              return std::make_pair(std::nullopt, std::nullopt);
+            });
 
     if (!valueTypeEnum.has_value() || !valueExtractor.has_value()) {
       return getOp.emitOpError() << "element type not handled";
@@ -3997,7 +4001,7 @@
                 [&](auto op) { return StringRef("iree_vm_value_make_i32"); })
             .template Case<IREE::VM::ListSetI64Op>(
                 [&](auto op) { return StringRef("iree_vm_value_make_i64"); })
-            .Default([](Operation *) { return None; });
+            .Default([](Operation *) { return std::nullopt; });
 
     if (!valueConstructor.has_value()) {
       return setOp.emitOpError() << " not handled";
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 1f074d4..ba3d133 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCTypeConverter.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCTypeConverter.cpp
@@ -142,7 +142,7 @@
   auto vmAnalysis = lookupAnalysis(funcOp);
   if (failed(vmAnalysis)) {
     funcOp.emitError() << "parent func op not found in cache.";
-    return None;
+    return std::nullopt;
   }
 
   int32_t ordinal = vmAnalysis.value().get().getRefRegisterOrdinal(ref);
diff --git a/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.cpp b/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.cpp
index ca46f84..98e660d 100644
--- a/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.cpp
@@ -99,12 +99,15 @@
          function_interface_impl::VariadicFlag,
          std::string &) { return builder.getFunctionType(argTypes, results); };
   return function_interface_impl::parseFunctionOp(
-      parser, result, /*allowVariadic=*/false, buildFuncType);
+      parser, result, /*allowVariadic=*/false,
+      getFunctionTypeAttrName(result.name), buildFuncType,
+      getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
 }
 
 void FuncOp::print(OpAsmPrinter &p) {
-  Operation *op = getOperation();
-  function_interface_impl::printFunctionOp(p, op, /*isVariadic=*/false);
+  function_interface_impl::printFunctionOp(
+      p, *this, /*isVariadic=*/false, getFunctionTypeAttrName(),
+      getArgAttrsAttrName(), getResAttrsAttrName());
 }
 
 void FuncOp::build(OpBuilder &builder, OperationState &result, StringRef name,
@@ -121,8 +124,10 @@
 
   assert(type.getNumInputs() == argAttrs.size() &&
          "expected as many argument attribute lists as arguments");
-  function_interface_impl::addArgAndResultAttrs(builder, result, argAttrs,
-                                                /*resultAttrs=*/llvm::None);
+  function_interface_impl::addArgAndResultAttrs(
+      builder, result, argAttrs,
+      /*resultAttrs=*/std::nullopt, getArgAttrsAttrName(result.name),
+      getResAttrsAttrName(result.name));
 }
 
 Block *FuncOp::addEntryBlock() {
@@ -135,10 +140,9 @@
 }
 
 LogicalResult FuncOp::verifyType() {
-  auto type =
-      getOperation()->getAttrOfType<TypeAttr>(getTypeAttrName()).getValue();
+  auto type = getFunctionTypeAttr().getValue();
   if (!type.isa<FunctionType>())
-    return emitOpError("requires '" + getTypeAttrName() +
+    return emitOpError("requires '" + getFunctionTypeAttrName().getValue() +
                        "' attribute of function type");
   return success();
 }
@@ -272,15 +276,17 @@
     return parser.emitError(parser.getCurrentLocation())
            << "invalid result type list";
   }
-  function_interface_impl::addArgAndResultAttrs(builder, result, argAttrs,
-                                                /*resultAttrs=*/llvm::None);
+  function_interface_impl::addArgAndResultAttrs(
+      builder, result, argAttrs,
+      /*resultAttrs=*/std::nullopt, getArgAttrsAttrName(result.name),
+      getResAttrsAttrName(result.name));
   if (failed(parser.parseOptionalAttrDictWithKeyword(result.attributes))) {
     return failure();
   }
 
   auto functionType =
       FunctionType::get(result.getContext(), argTypes, resultTypes);
-  result.addAttribute(mlir::function_interface_impl::getTypeAttrName(),
+  result.addAttribute(getFunctionTypeAttrName(result.name),
                       TypeAttr::get(functionType));
 
   result.addRegion();
@@ -316,11 +322,13 @@
     p << " -> (" << getFunctionType().getResults() << ")";
   }
   mlir::function_interface_impl::printFunctionAttributes(
-      p, op, getArgumentTypes().size(), getResultTypes().size(),
-      /*elided=*/
+      p, op,
       {
+          getFunctionTypeAttrName(),
+          getArgAttrsAttrName(),
+          getResAttrsAttrName(),
           "is_variadic",
-          "is_optional",
+          getIsOptionalAttrName(),
       });
 }
 
@@ -334,18 +342,19 @@
   if (!argAttrs.empty()) {
     assert(type.getNumInputs() == argAttrs.size() &&
            "expected as many argument attribute lists as arguments");
-    function_interface_impl::addArgAndResultAttrs(builder, result, argAttrs,
-                                                  /*resultAttrs=*/llvm::None);
+    function_interface_impl::addArgAndResultAttrs(
+        builder, result, argAttrs,
+        /*resultAttrs=*/std::nullopt, getArgAttrsAttrName(result.name),
+        getResAttrsAttrName(result.name));
   }
 
   result.addRegion();
 }
 
 LogicalResult ImportOp::verifyType() {
-  auto type =
-      getOperation()->getAttrOfType<TypeAttr>(getTypeAttrName()).getValue();
+  auto type = getFunctionTypeAttr().getValue();
   if (!type.isa<FunctionType>())
-    return emitOpError("requires '" + getTypeAttrName() +
+    return emitOpError("requires '" + getFunctionTypeAttrName().getValue() +
                        "' attribute of function type");
   return success();
 }
diff --git a/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td b/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td
index 2cf0658..e5bf9b5 100644
--- a/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td
+++ b/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td
@@ -113,7 +113,9 @@
   let arguments = (ins
     TypeAttrOf<FunctionType>:$function_type,
     OptionalAttr<VM_Ordinal>:$ordinal,
-    OptionalAttr<UnitAttr>:$noinline
+    OptionalAttr<UnitAttr>:$noinline,
+    OptionalAttr<DictArrayAttr>:$arg_attrs,
+    OptionalAttr<DictArrayAttr>:$res_attrs    
   );
 
   let regions = (region AnyRegion:$body);
@@ -204,10 +206,14 @@
     they were resolved can be queried with `vm.import.resolved`.
   }];
 
-  let arguments = (ins
-    OptionalAttr<VM_Ordinal>:$ordinal,
-    OptionalAttr<UnitAttr>:$is_optional,
-    OptionalAttr<I32Attr>:$minimum_version
+  let arguments = (ins SymbolNameAttr:$sym_name,
+                       TypeAttrOf<FunctionType>:$function_type,
+                       OptionalAttr<DictArrayAttr>:$arg_attrs,
+                       OptionalAttr<DictArrayAttr>:$res_attrs,
+                       OptionalAttr<StrAttr>:$sym_visibility,
+                       OptionalAttr<VM_Ordinal>:$ordinal,
+                       OptionalAttr<UnitAttr>:$is_optional,
+                       OptionalAttr<I32Attr>:$minimum_version
   );
 
   // Required because FunctionOpInterface and CallableOpInterface disagree with
@@ -222,13 +228,6 @@
   ];
 
   let extraClassDeclaration = [{
-    /// Returns the type of this function.
-    FunctionType getFunctionType() {
-      return getOperation()->getAttrOfType<TypeAttr>(getTypeAttrName())
-          .getValue()
-          .cast<FunctionType>();
-    }
-
     /// Returns true if the import must be invoked via vm.call.variadic.
     bool isVariadic() {
       for (int i = 0; i < getArgumentTypes().size(); ++i) {
@@ -280,7 +279,9 @@
   }];
 
   let arguments = (ins
-    TypeAttrOf<FunctionType>:$function_type
+    TypeAttrOf<FunctionType>:$function_type,
+    OptionalAttr<DictArrayAttr>:$arg_attrs,
+    OptionalAttr<DictArrayAttr>:$res_attrs    
   );
 
   let regions = (region AnyRegion:$body);
@@ -367,7 +368,7 @@
       CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs
     ),
     [{
-      build($_builder, $_state, name, isMutable, type, llvm::None, attrs);
+      build($_builder, $_state, name, isMutable, type, std::nullopt, attrs);
     }]>,
   ];
 }
@@ -3821,7 +3822,7 @@
   let builders = [
     OpBuilder<(ins),
     [{
-      build($_builder, $_state, llvm::None);
+      build($_builder, $_state, std::nullopt);
     }]>,
   ];
 }
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 79c1368..35fa86a 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/ArchiveWriter.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/ArchiveWriter.cpp
@@ -376,7 +376,7 @@
   uint32_t crc32 = 0;
   null_crc32_ostream crcStream(crc32);
   if (failed(write(crcStream))) {
-    return None;
+    return std::nullopt;
   }
 
   // Write the ZIP header and padding up to the start of the file.
@@ -386,7 +386,7 @@
   // Stream out the file contents to the output stream.
   uint64_t start = os.tell();
   if (failed(write(os))) {
-    return None;
+    return std::nullopt;
   }
   fileRef.totalLength = os.tell() - start;
   assert(fileRef.totalLength == fileLength && "declared length mismatch");
@@ -431,7 +431,7 @@
   {
     crc32_ostream crcStream(os, fileRef.crc32);
     if (failed(write(crcStream))) {
-      return None;
+      return std::nullopt;
     }
     crcStream.flush();
   }
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 3438ce5..85e1d4e 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeEncoder.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Target/Bytecode/BytecodeEncoder.cpp
@@ -259,7 +259,7 @@
 
   Optional<std::vector<uint8_t>> finish() {
     if (failed(fixupOffsets())) {
-      return llvm::None;
+      return std::nullopt;
     }
     return std::move(bytecode_);
   }
@@ -352,7 +352,7 @@
   RegisterAllocation registerAllocation;
   if (failed(registerAllocation.recalculate(funcOp))) {
     funcOp.emitError() << "register allocation failed";
-    return llvm::None;
+    return std::nullopt;
   }
 
   FunctionSourceMap sourceMap;
@@ -362,14 +362,14 @@
   for (auto &block : funcOp.getBlocks()) {
     if (failed(encoder.beginBlock(&block))) {
       funcOp.emitError() << "failed to begin block";
-      return llvm::None;
+      return std::nullopt;
     }
 
     for (auto &op : block.getOperations()) {
       auto serializableOp = dyn_cast<IREE::VM::VMSerializableOp>(op);
       if (!serializableOp) {
         op.emitOpError() << "is not serializable";
-        return llvm::None;
+        return std::nullopt;
       }
       sourceMap.locations.push_back(
           {static_cast<int32_t>(encoder.getOffset()), op.getLoc()});
@@ -377,13 +377,13 @@
           failed(serializableOp.encode(symbolTable, encoder)) ||
           failed(encoder.endOp(&op))) {
         op.emitOpError() << "failed to encode";
-        return llvm::None;
+        return std::nullopt;
       }
     }
 
     if (failed(encoder.endBlock(&block))) {
       funcOp.emitError() << "failed to end block";
-      return llvm::None;
+      return std::nullopt;
     }
   }
 
@@ -391,12 +391,12 @@
 
   if (failed(encoder.ensureAlignment(8))) {
     funcOp.emitError() << "failed to pad function";
-    return llvm::None;
+    return std::nullopt;
   }
   auto bytecodeData = encoder.finish();
   if (!bytecodeData.has_value()) {
     funcOp.emitError() << "failed to fixup and finish encoding";
-    return llvm::None;
+    return std::nullopt;
   }
   result.bytecodeData = bytecodeData.value();
   result.i32RegisterCount = registerAllocation.getMaxI32RegisterOrdinal() + 1;
diff --git a/compiler/src/iree/compiler/Dialect/VM/Transforms/GlobalInitialization.cpp b/compiler/src/iree/compiler/Dialect/VM/Transforms/GlobalInitialization.cpp
index 51245d2..4629891 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Transforms/GlobalInitialization.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Transforms/GlobalInitialization.cpp
@@ -327,7 +327,7 @@
         inlinerInterface, &initializerOp.getBody(), builder.getInsertionBlock(),
         builder.getInsertionPoint(),
         /*inlinedOperands=*/ValueRange{},
-        /*resultsToReplace=*/ValueRange{}, /*inlineLoc=*/llvm::None,
+        /*resultsToReplace=*/ValueRange{}, /*inlineLoc=*/std::nullopt,
         /*shouldCloneInlinedRegion=*/false);
     builder.setInsertionPointToEnd(builder.getInsertionBlock());
     return result;
diff --git a/compiler/src/iree/compiler/Dialect/VM/Transforms/OrdinalAllocation.cpp b/compiler/src/iree/compiler/Dialect/VM/Transforms/OrdinalAllocation.cpp
index ead22d8..785b637 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 = llvm::None;
+      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 4ecbaa9..ca50f41 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Utils/CallingConvention.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Utils/CallingConvention.cpp
@@ -87,12 +87,12 @@
       if (importOp.isFuncArgumentVariadic(i)) {
         if (failed(encodeVariadicCallingConventionType(
                 importOp, functionType.getInput(i), s))) {
-          return None;
+          return std::nullopt;
         }
       } else {
         if (failed(encodeCallingConventionType(importOp,
                                                functionType.getInput(i), s))) {
-          return None;
+          return std::nullopt;
         }
       }
     }
@@ -104,7 +104,7 @@
     for (int i = 0; i < functionType.getNumResults(); ++i) {
       if (failed(encodeCallingConventionType(importOp,
                                              functionType.getResult(i), s))) {
-        return None;
+        return std::nullopt;
       }
     }
   } else {
@@ -124,7 +124,7 @@
     for (int i = 0; i < functionType.getNumInputs(); ++i) {
       if (failed(encodeCallingConventionType(funcOp, functionType.getInput(i),
                                              s))) {
-        return None;
+        return std::nullopt;
       }
     }
   } else {
@@ -135,7 +135,7 @@
     for (int i = 0; i < functionType.getNumResults(); ++i) {
       if (failed(encodeCallingConventionType(funcOp, functionType.getResult(i),
                                              s))) {
-        return None;
+        return std::nullopt;
       }
     }
   } else {
diff --git a/compiler/src/iree/compiler/InputConversion/Common/IREEImportPublic.cpp b/compiler/src/iree/compiler/InputConversion/Common/IREEImportPublic.cpp
index 9565dc9..197161e 100644
--- a/compiler/src/iree/compiler/InputConversion/Common/IREEImportPublic.cpp
+++ b/compiler/src/iree/compiler/InputConversion/Common/IREEImportPublic.cpp
@@ -193,7 +193,7 @@
       return failure();
     }
 
-    rewriter.replaceOp(srcOp, llvm::None);
+    rewriter.replaceOp(srcOp, std::nullopt);
     return success();
   }
 };
diff --git a/compiler/src/iree/compiler/InputConversion/Common/ImportMLProgram.cpp b/compiler/src/iree/compiler/InputConversion/Common/ImportMLProgram.cpp
index 9eb9860..56c550b 100644
--- a/compiler/src/iree/compiler/InputConversion/Common/ImportMLProgram.cpp
+++ b/compiler/src/iree/compiler/InputConversion/Common/ImportMLProgram.cpp
@@ -76,7 +76,7 @@
     auto srcOpTypedAttr =
         srcOpAttr.has_value()
             ? Optional<TypedAttr>(srcOpAttr.value().cast<TypedAttr>())
-            : llvm::None;
+            : std::nullopt;
     auto globalOp = rewriter.replaceOpWithNewOp<IREE::Util::GlobalOp>(
         srcOp, srcOp.getName(), srcOp.getIsMutable(), newType, srcOpTypedAttr);
     globalOp.setVisibility(srcOp.getVisibility());
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/BroadcastingToLinalgPatterns.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/BroadcastingToLinalgPatterns.cpp
index 31fa850..5b002cf 100644
--- a/compiler/src/iree/compiler/InputConversion/MHLO/BroadcastingToLinalgPatterns.cpp
+++ b/compiler/src/iree/compiler/InputConversion/MHLO/BroadcastingToLinalgPatterns.cpp
@@ -156,7 +156,7 @@
       emitError(loc) << "cannot broadcast extents of differing size unless "
                         "if one of them is 1 (got "
                      << lhsDim.getStatic() << ", " << rhsDim.getStatic() << ")";
-      return llvm::None;
+      return std::nullopt;
     }
 
     // Static expansions.
@@ -266,7 +266,7 @@
                           "if one of them is 1 (got "
                        << cmpLhs.getStatic() << ", " << cmpRhs.getStatic()
                        << ")";
-        return llvm::None;
+        return std::nullopt;
       }
       continue;
     }
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToLinalgExt.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToLinalgExt.cpp
index 0908fbd..dad9054 100644
--- a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToLinalgExt.cpp
+++ b/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToLinalgExt.cpp
@@ -41,7 +41,7 @@
 }
 
 static Optional<Type> convertRank0TensorToScalar(RankedTensorType tensorType) {
-  if (tensorType.getRank() != 0) return llvm::None;
+  if (tensorType.getRank() != 0) return std::nullopt;
   Type elementType = tensorType.getElementType();
   if (auto intType = elementType.dyn_cast<IntegerType>()) {
     elementType = convertIntegerToSignless(intType);
@@ -60,7 +60,7 @@
   assert(inputs.size() == 1 && "too many inputs to type conversion");
   Value fromValue = inputs[0];
   auto fromType = fromValue.getType().dyn_cast<RankedTensorType>();
-  if (!fromType) return llvm::None;
+  if (!fromType) return std::nullopt;
 
   if (auto intFromType = fromType.getElementType().dyn_cast<IntegerType>()) {
     Type castType = getElementTypeOrSelf(toType);
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/FlattenTuplesInCFG.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/FlattenTuplesInCFG.cpp
index 27e988c..1c562de 100644
--- a/compiler/src/iree/compiler/InputConversion/MHLO/FlattenTuplesInCFG.cpp
+++ b/compiler/src/iree/compiler/InputConversion/MHLO/FlattenTuplesInCFG.cpp
@@ -239,7 +239,7 @@
   BlockAndValueMapping mapping;
 
   for (auto attr : oldFunction->getAttrs()) {
-    if (attr.getName() != oldFunction.getTypeAttrName()) {
+    if (attr.getName() != oldFunction.getFunctionTypeAttrName()) {
       newFunction->setAttr(attr.getName(), attr.getValue());
     }
   }
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/MHLOToLinalgOnTensors.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/MHLOToLinalgOnTensors.cpp
index f8aadfa..03aa781 100644
--- a/compiler/src/iree/compiler/InputConversion/MHLO/MHLOToLinalgOnTensors.cpp
+++ b/compiler/src/iree/compiler/InputConversion/MHLO/MHLOToLinalgOnTensors.cpp
@@ -327,7 +327,7 @@
                                      ValueRange inputs, Location loc) {
   assert(inputs.size() == 1);
   if (inputs.front().getType().isa<ShapedType>()) {
-    return llvm::None;
+    return std::nullopt;
   }
   return builder
       .create<tensor::FromElementsOp>(
diff --git a/compiler/src/iree/compiler/Utils/ModuleUtils.cpp b/compiler/src/iree/compiler/Utils/ModuleUtils.cpp
index d867dfc..119cf53 100644
--- a/compiler/src/iree/compiler/Utils/ModuleUtils.cpp
+++ b/compiler/src/iree/compiler/Utils/ModuleUtils.cpp
@@ -26,7 +26,7 @@
   } else if (auto loc = baseLoc.dyn_cast<FileLineColLoc>()) {
     return loc;
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 std::string guessModuleName(mlir::ModuleOp moduleOp, StringRef defaultName) {
diff --git a/integrations/tensorflow/WORKSPACE b/integrations/tensorflow/WORKSPACE
index 5c2f58b..c83e891 100644
--- a/integrations/tensorflow/WORKSPACE
+++ b/integrations/tensorflow/WORKSPACE
@@ -7,7 +7,7 @@
 
 load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
 
-TENSORFLOW_COMMIT = "0bc2c74645fc31cc5e759eabcbf032e7612bd483"
+TENSORFLOW_COMMIT = "aaca45a9df96b1401ae49928c8bcc2578379f77d"
 
 git_repository(
     name = "org_tensorflow",
diff --git a/integrations/tensorflow/iree-dialects/lib/Dialect/Input/InputOps.cpp b/integrations/tensorflow/iree-dialects/lib/Dialect/Input/InputOps.cpp
index e6b43fc..4f7523b 100644
--- a/integrations/tensorflow/iree-dialects/lib/Dialect/Input/InputOps.cpp
+++ b/integrations/tensorflow/iree-dialects/lib/Dialect/Input/InputOps.cpp
@@ -115,7 +115,7 @@
 void GlobalOp::build(OpBuilder &builder, OperationState &result, StringRef name,
                      bool isMutable, Type type,
                      ArrayRef<NamedAttribute> attrs) {
-  build(builder, result, name, isMutable, type, llvm::None, attrs);
+  build(builder, result, name, isMutable, type, std::nullopt, attrs);
 }
 
 // Returns true if the given |accessType| is compatible with the |globalType|.
diff --git a/integrations/tensorflow/iree_tf_compiler/MHLO/EmitDefaultIREEABI.cpp b/integrations/tensorflow/iree_tf_compiler/MHLO/EmitDefaultIREEABI.cpp
index dcb377c..c864942 100644
--- a/integrations/tensorflow/iree_tf_compiler/MHLO/EmitDefaultIREEABI.cpp
+++ b/integrations/tensorflow/iree_tf_compiler/MHLO/EmitDefaultIREEABI.cpp
@@ -126,7 +126,7 @@
       return json::Value(std::move(name));
     }
 
-    return llvm::None;
+    return std::nullopt;
   }
 };
 
diff --git a/integrations/tensorflow/iree_tf_compiler/TF/StripMetadata.cpp b/integrations/tensorflow/iree_tf_compiler/TF/StripMetadata.cpp
index e9c16e7..2d14fbe 100644
--- a/integrations/tensorflow/iree_tf_compiler/TF/StripMetadata.cpp
+++ b/integrations/tensorflow/iree_tf_compiler/TF/StripMetadata.cpp
@@ -5,6 +5,7 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
 #include "iree_tf_compiler/TF/Passes.h"
+#include "mlir/IR/FunctionInterfaces.h"
 #include "mlir/Pass/Pass.h"
 #include "mlir/Support/LLVM.h"
 #include "tensorflow/compiler/mlir/tensorflow/ir/tf_device.h"
@@ -76,7 +77,7 @@
 
     for (int i = 0; i < funcOp.getNumArguments(); ++i) {
       auto stripAttrs = llvm::to_vector<4>(llvm::make_filter_range(
-          funcOp.getArgAttrs(i),
+          mlir::function_interface_impl::getArgAttrs(funcOp, i),
           [](NamedAttribute namedAttr) { return isTFAttr(namedAttr); }));
       for (auto namedAttr : stripAttrs) {
         funcOp.removeArgAttr(i, namedAttr.getName());
@@ -85,7 +86,7 @@
 
     for (int i = 0; i < funcOp.getNumResults(); ++i) {
       auto stripAttrs = llvm::to_vector<4>(llvm::make_filter_range(
-          funcOp.getResultAttrs(i),
+          mlir::function_interface_impl::getResultAttrs(funcOp, i),
           [](NamedAttribute namedAttr) { return isTFAttr(namedAttr); }));
       for (auto namedAttr : stripAttrs) {
         funcOp.removeResultAttr(i, namedAttr.getName());
diff --git a/integrations/tensorflow/iree_tf_compiler/TFL/StripMetadata.cpp b/integrations/tensorflow/iree_tf_compiler/TFL/StripMetadata.cpp
index 6dadf7e..241165d 100644
--- a/integrations/tensorflow/iree_tf_compiler/TFL/StripMetadata.cpp
+++ b/integrations/tensorflow/iree_tf_compiler/TFL/StripMetadata.cpp
@@ -6,6 +6,7 @@
 
 #include "iree_tf_compiler/TFL/PassDetail.h"
 #include "iree_tf_compiler/TFL/Passes.h"
+#include "mlir/IR/FunctionInterfaces.h"
 #include "mlir/Pass/Pass.h"
 #include "mlir/Support/LLVM.h"
 
@@ -31,7 +32,6 @@
 class StripModuleMetadataPass
     : public StripModuleMetadataBase<StripModuleMetadataPass> {
  public:
-
   void runOnOperation() override {
     auto moduleOp = getOperation();
     auto stripAttrs = llvm::to_vector<4>(llvm::make_filter_range(
@@ -46,7 +46,6 @@
 class StripFunctionMetadataPass
     : public StripFunctionMetadataBase<StripFunctionMetadataPass> {
  public:
-
   void runOnOperation() override {
     auto funcOp = getOperation();
     auto stripAttrs = llvm::to_vector<4>(llvm::make_filter_range(
@@ -58,7 +57,7 @@
 
     for (int i = 0; i < funcOp.getNumArguments(); ++i) {
       auto stripAttrs = llvm::to_vector<4>(llvm::make_filter_range(
-          funcOp.getArgAttrs(i),
+          mlir::function_interface_impl::getArgAttrs(funcOp, i),
           [](NamedAttribute namedAttr) { return isTFLAttr(namedAttr); }));
       for (auto namedAttr : stripAttrs) {
         funcOp.removeArgAttr(i, namedAttr.getName());
@@ -67,7 +66,7 @@
 
     for (int i = 0; i < funcOp.getNumResults(); ++i) {
       auto stripAttrs = llvm::to_vector<4>(llvm::make_filter_range(
-          funcOp.getResultAttrs(i),
+          mlir::function_interface_impl::getResultAttrs(funcOp, i),
           [](NamedAttribute namedAttr) { return isTFLAttr(namedAttr); }));
       for (auto namedAttr : stripAttrs) {
         funcOp.removeResultAttr(i, namedAttr.getName());
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 d8b1a4b..a7da555 100644
--- a/integrations/tensorflow/iree_tf_compiler/iree-import-xla-main.cpp
+++ b/integrations/tensorflow/iree_tf_compiler/iree-import-xla-main.cpp
@@ -154,7 +154,7 @@
       fileInputStream->open(inputPath, std::ios::in | std::ios::binary);
       if (!fileInputStream->is_open()) {
         llvm::errs() << "Unable to open input file " << inputPath << "\n";
-        return llvm::None;
+        return std::nullopt;
       }
       inputStream = fileInputStream.get();
     }
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 04249dd..1a43a05 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
@@ -597,7 +597,7 @@
     OpBuilder<(ins "Value":$source, "Value":$output,
       "ArrayRef<int64_t>":$innerDimsPos,
       "ArrayRef<OpFoldResult>":$innerTiles,
-      CArg<"Optional<Value>", "llvm::None">:$paddingValue,
+      CArg<"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 1d16af5..dfbdad6 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
@@ -38,11 +38,11 @@
 
   explicit LinalgTransformationFilter(
       ArrayRef<StringAttr> matchDisjunction = {},
-      Optional<StringAttr> replacement = None);
+      Optional<StringAttr> replacement = std::nullopt);
 
   explicit LinalgTransformationFilter(
       const FilterFunction &f, ArrayRef<StringAttr> matchDisjunction = {},
-      Optional<StringAttr> replacement = None);
+      Optional<StringAttr> replacement = std::nullopt);
 
   LinalgTransformationFilter(LinalgTransformationFilter &&) = default;
   LinalgTransformationFilter(const LinalgTransformationFilter &) = default;
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 e6b43fc..4f7523b 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/Input/InputOps.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/Input/InputOps.cpp
@@ -115,7 +115,7 @@
 void GlobalOp::build(OpBuilder &builder, OperationState &result, StringRef name,
                      bool isMutable, Type type,
                      ArrayRef<NamedAttribute> attrs) {
-  build(builder, result, name, isMutable, type, llvm::None, attrs);
+  build(builder, result, name, isMutable, type, std::nullopt, attrs);
 }
 
 // Returns true if the given |accessType| is compatible with the |globalType|.
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 fc22757..7c85a19 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
@@ -29,7 +29,7 @@
 static Optional<TensorEncoding> getEncoding(RankedTensorType tensorType) {
   auto encodingAttr = tensorType.getEncoding().dyn_cast_or_null<EncodingAttr>();
   if (!encodingAttr)
-    return llvm::None;
+    return std::nullopt;
   return encodingAttr.getEncoding().getValue();
 }
 
@@ -117,11 +117,11 @@
 static Optional<Value> getPaddingValue(Value &source) {
   auto padOp = source.getDefiningOp<tensor::PadOp>();
   if (!padOp || padOp.getNofold() || !padOp.hasZeroLowPad())
-    return llvm::None;
+    return std::nullopt;
 
   Value constantPaddingValue = padOp.getConstantPaddingValue();
   if (!constantPaddingValue)
-    return llvm::None;
+    return std::nullopt;
 
   source = padOp.getSource();
   return constantPaddingValue;
diff --git a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/TransformOps/LinalgExtTransformOps.cpp b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/TransformOps/LinalgExtTransformOps.cpp
index 20465dc..9df5c83 100644
--- a/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/TransformOps/LinalgExtTransformOps.cpp
+++ b/llvm-external-projects/iree-dialects/lib/Dialect/LinalgExt/TransformOps/LinalgExtTransformOps.cpp
@@ -131,9 +131,9 @@
   FailureOr<Operation *> result =
       pattern.returningMatchAndRewrite(target, rewriter);
   if (failed(result))
-    return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
+    return emitDefaultDefiniteFailure(target);
   results.assign({*result});
-  return DiagnosedSilenceableFailure(success());
+  return DiagnosedSilenceableFailure::success();
 }
 
 DiagnosedSilenceableFailure
@@ -145,9 +145,9 @@
   FailureOr<Operation *> result =
       pattern.returningMatchAndRewrite(target, rewriter);
   if (failed(result))
-    return DiagnosedSilenceableFailure(reportUnknownTransformError(target));
+    return emitDefaultDefiniteFailure(target);
   results.assign({*result});
-  return DiagnosedSilenceableFailure(success());
+  return DiagnosedSilenceableFailure::success();
 }
 
 #define GET_OP_CLASSES
diff --git a/tests/e2e/tosa_ops/BUILD b/tests/e2e/tosa_ops/BUILD
index 2ee394f..c970989 100644
--- a/tests/e2e/tosa_ops/BUILD
+++ b/tests/e2e/tosa_ops/BUILD
@@ -46,6 +46,7 @@
         "maximum.mlir",
         "minimum.mlir",
         "mul.mlir",
+        "mul_shift.mlir",
         "negate.mlir",
         "pad.mlir",
         "reciprocal.mlir",
@@ -99,6 +100,7 @@
         "maximum.mlir",
         "minimum.mlir",
         "mul.mlir",
+        "mul_shift.mlir",
         "negate.mlir",
         "pad.mlir",
         "reciprocal.mlir",
@@ -156,6 +158,7 @@
         "maximum.mlir",
         "minimum.mlir",
         "mul.mlir",
+        "mul_shift.mlir",
         "negate.mlir",
         "pad.mlir",
         "reciprocal.mlir",
@@ -228,6 +231,7 @@
         "while.mlir",
     ],
     include = ["*.mlir"],
+    exclude = ["mul_shift.mlir"],  # TODO(#11571)
 )
 
 iree_check_single_backend_test_suite(
diff --git a/tests/e2e/tosa_ops/CMakeLists.txt b/tests/e2e/tosa_ops/CMakeLists.txt
index 1f6c115..2b55579 100644
--- a/tests/e2e/tosa_ops/CMakeLists.txt
+++ b/tests/e2e/tosa_ops/CMakeLists.txt
@@ -40,6 +40,7 @@
     "maximum.mlir"
     "minimum.mlir"
     "mul.mlir"
+    "mul_shift.mlir"
     "negate.mlir"
     "pad.mlir"
     "reciprocal.mlir"
@@ -91,6 +92,7 @@
     "maximum.mlir"
     "minimum.mlir"
     "mul.mlir"
+    "mul_shift.mlir"
     "negate.mlir"
     "pad.mlir"
     "reciprocal.mlir"
@@ -141,6 +143,7 @@
     "maximum.mlir"
     "minimum.mlir"
     "mul.mlir"
+    "mul_shift.mlir"
     "negate.mlir"
     "pad.mlir"
     "reciprocal.mlir"
@@ -246,6 +249,7 @@
     "maximum.mlir"
     "minimum.mlir"
     "mul.mlir"
+    # "mul_shift.mlir"  # TODO($11571)
     "negate.mlir"
     "pad.mlir"
     "reciprocal.mlir"
diff --git a/tests/e2e/tosa_ops/mul.mlir b/tests/e2e/tosa_ops/mul.mlir
index 2576d1f..375586e 100644
--- a/tests/e2e/tosa_ops/mul.mlir
+++ b/tests/e2e/tosa_ops/mul.mlir
@@ -13,16 +13,3 @@
   check.expect_eq_const(%result, dense<[5, 0, -9, 32]> : tensor<4xi32>) : tensor<4xi32>
   return
 }
-
-// TODO: The following generates tosa.ApplyScale ops that leaks to backends.
-// Sizes like tensor<4xi32> will trigger vectorization on the SPIR-V backend.
-// But we cannot vectorize tosa.ApplyScale ops.
-
-func.func @tensor_int_shifted() {
-  %0 = util.unfoldable_constant dense<[1, 0, 3, 4, 4]> : tensor<5xi32>
-  %1 = util.unfoldable_constant dense<[5, 6, -3, 8, 8]> : tensor<5xi32>
-  %result = "tosa.mul"(%0, %1) {shift = 1 : i32} : (tensor<5xi32>, tensor<5xi32>) -> tensor<5xi32>
-  check.expect_eq_const(%result, dense<[3, 0, -4, 16, 16]> : tensor<5xi32>) : tensor<5xi32>
-  return
-}
-
diff --git a/tests/e2e/tosa_ops/mul_shift.mlir b/tests/e2e/tosa_ops/mul_shift.mlir
new file mode 100644
index 0000000..c3c795a
--- /dev/null
+++ b/tests/e2e/tosa_ops/mul_shift.mlir
@@ -0,0 +1,11 @@
+// TODO: The following generates tosa.ApplyScale ops that leaks to backends.
+// Sizes like tensor<4xi32> will trigger vectorization on the SPIR-V backend.
+// But we cannot vectorize tosa.ApplyScale ops.
+
+func.func @tensor_int_shifted() {
+  %0 = util.unfoldable_constant dense<[1, 0, 3, 4, 4]> : tensor<5xi32>
+  %1 = util.unfoldable_constant dense<[5, 6, -3, 8, 8]> : tensor<5xi32>
+  %result = "tosa.mul"(%0, %1) {shift = 1 : i32} : (tensor<5xi32>, tensor<5xi32>) -> tensor<5xi32>
+  check.expect_eq_const(%result, dense<[3, 0, -4, 16, 16]> : tensor<5xi32>) : tensor<5xi32>
+  return
+}
diff --git a/third_party/llvm-project b/third_party/llvm-project
index fdc8434..6425acd 160000
--- a/third_party/llvm-project
+++ b/third_party/llvm-project
@@ -1 +1 @@
-Subproject commit fdc84349e0fcc5fed8869665346e1730094812b7
+Subproject commit 6425acd8fb8915ade15583eeaaa22a286b8d10eb
diff --git a/third_party/mlir-hlo b/third_party/mlir-hlo
index 39afac0..252d314 160000
--- a/third_party/mlir-hlo
+++ b/third_party/mlir-hlo
@@ -1 +1 @@
-Subproject commit 39afac0958a76b667168fab139fbcc3ef79d4712
+Subproject commit 252d3140a0cf243910ae5c99b6abe0d86f9f744d