[Codegen] Upgrade iree dialects to free create functions. NFC. (#21898)

The builder create methods are deprecated:
https://mlir.llvm.org/deprecation/. See
https://discourse.llvm.org/t/psa-opty-create-now-with-100-more-tab-complete/87339.
The main benefit of free functions is better tab completion with
LSP/IDE.

I'm splitting the upgrade in chunks going by project directories.
diff --git a/compiler/src/iree/compiler/Dialect/Encoding/IR/EncodingAttrs.cpp b/compiler/src/iree/compiler/Dialect/Encoding/IR/EncodingAttrs.cpp
index 792e739..818cb1b 100644
--- a/compiler/src/iree/compiler/Dialect/Encoding/IR/EncodingAttrs.cpp
+++ b/compiler/src/iree/compiler/Dialect/Encoding/IR/EncodingAttrs.cpp
@@ -85,7 +85,7 @@
       res = requestedSize;
       continue;
     }
-    res = builder.create<arith::MaxUIOp>(loc, res, requestedSize);
+    res = arith::MaxUIOp::create(builder, loc, res, requestedSize);
   }
   return res;
 }
@@ -457,7 +457,7 @@
 
   const int64_t elementSize = getRoundedElementByteWidth(type.getElementType());
   int64_t staticProduct = elementSize;
-  Value dynamicProduct = builder.create<arith::ConstantIndexOp>(loc, 1);
+  Value dynamicProduct = arith::ConstantIndexOp::create(builder, loc, 1);
 
   size_t dynamicDimIdx = 0;
   for (auto [dimSize, padValue] : llvm::zip_equal(type.getShape(), padding)) {
@@ -470,9 +470,9 @@
     ++dynamicDimIdx;
 
     if (padValue != 0) {
-      dynamicDimSize = builder.create<arith::AddIOp>(
-          loc, dynamicDimSize,
-          builder.create<arith::ConstantIndexOp>(loc, padValue),
+      dynamicDimSize = arith::AddIOp::create(
+          builder, loc, dynamicDimSize,
+          arith::ConstantIndexOp::create(builder, loc, padValue),
           arith::IntegerOverflowFlags::nsw);
     }
     dynamicProduct = builder.createOrFold<arith::MulIOp>(
@@ -480,7 +480,7 @@
   }
 
   return builder.createOrFold<arith::MulIOp>(
-      loc, builder.create<arith::ConstantIndexOp>(loc, staticProduct),
+      loc, arith::ConstantIndexOp::create(builder, loc, staticProduct),
       dynamicProduct, arith::IntegerOverflowFlags::nsw);
 }
 
@@ -506,7 +506,7 @@
                                                 ValueRange dynamicDims) const {
   const int64_t elementSize = getRoundedElementByteWidth(type.getElementType());
   int64_t staticProduct = elementSize;
-  Value dynamicProduct = builder.create<arith::ConstantIndexOp>(loc, 1);
+  Value dynamicProduct = arith::ConstantIndexOp::create(builder, loc, 1);
 
   size_t dynamicDimIdx = 0;
   for (int64_t dimSize : type.getShape()) {
@@ -521,7 +521,7 @@
         loc, dynamicProduct, dynamicDimSize, arith::IntegerOverflowFlags::nsw);
   }
   return builder.createOrFold<arith::MulIOp>(
-      loc, builder.create<arith::ConstantIndexOp>(loc, staticProduct),
+      loc, arith::ConstantIndexOp::create(builder, loc, staticProduct),
       dynamicProduct, arith::IntegerOverflowFlags::nsw);
 }
 
diff --git a/compiler/src/iree/compiler/Dialect/Encoding/Utils/ElementPackingUtils.cpp b/compiler/src/iree/compiler/Dialect/Encoding/Utils/ElementPackingUtils.cpp
index 9288933..4abf1c2 100644
--- a/compiler/src/iree/compiler/Dialect/Encoding/Utils/ElementPackingUtils.cpp
+++ b/compiler/src/iree/compiler/Dialect/Encoding/Utils/ElementPackingUtils.cpp
@@ -114,7 +114,7 @@
   }
   // Scale by dynamic dims, if present.
   auto value =
-      builder.create<arith::ConstantIndexOp>(loc, staticCount).getResult();
+      arith::ConstantIndexOp::create(builder, loc, staticCount).getResult();
   for (auto dim : dynamicDims) {
     value = builder.createOrFold<arith::MulIOp>(loc, value, dim);
   }
@@ -124,7 +124,7 @@
     unsigned byteElements = 8 / elementBits;
     // TODO(antiagainst): We may want to emit runtime check to make sure this is
     // divisible.
-    auto divisor = builder.create<arith::ConstantIndexOp>(loc, byteElements);
+    auto divisor = arith::ConstantIndexOp::create(builder, loc, byteElements);
     if (!isPackedStorage && dynamicDims.empty() &&
         (staticCount * elementBits) % 8 != 0) {
       return nullptr;
@@ -148,15 +148,15 @@
   // Sub-byte packing requires putting multiple elements in the same byte.
   if (needToPackSubByteElementBitWidthImpl(elementBits, isPackedStorage)) {
     Value byteElements =
-        builder.create<arith::ConstantIndexOp>(loc, 8 / elementBits);
+        arith::ConstantIndexOp::create(builder, loc, 8 / elementBits);
     // TODO(antiagainst): We may want to emit runtime check to make sure this is
     // divisible.
     return builder.createOrFold<arith::DivUIOp>(loc, linearizedIndex,
                                                 byteElements);
   }
 
-  Value elementBytes = builder.create<arith::ConstantIndexOp>(
-      loc, IREE::Util::getRoundedElementByteWidth(alignedElementType));
+  Value elementBytes = arith::ConstantIndexOp::create(
+      builder, loc, IREE::Util::getRoundedElementByteWidth(alignedElementType));
   return builder.createOrFold<arith::MulIOp>(loc, linearizedIndex,
                                              elementBytes);
 }
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Conversion/ShardToFlow/Patterns.cpp b/compiler/src/iree/compiler/Dialect/Flow/Conversion/ShardToFlow/Patterns.cpp
index eb700d7..6c75271 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Conversion/ShardToFlow/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Conversion/ShardToFlow/Patterns.cpp
@@ -64,9 +64,9 @@
   SmallVector<int64_t> transposedShape =
       permute(type.getShape(), transposeVector);
   Value target =
-      builder.create<tensor::EmptyOp>(transposedShape, type.getElementType());
+      tensor::EmptyOp::create(builder, transposedShape, type.getElementType());
   return cast<TypedValue<RankedTensorType>>(
-      builder.create<linalg::TransposeOp>(v, target, transposeVector)
+      linalg::TransposeOp::create(builder, v, target, transposeVector)
           ->getResult(0));
 }
 
@@ -162,7 +162,7 @@
   std::optional<SmallVector<ReassociationIndices>> reassociation =
       getReassociationIndicesForCollapse(shape, newShape);
   return cast<TypedValue<RankedTensorType>>(
-      builder.create<tensor::CollapseShapeOp>(tensor, reassociation.value())
+      tensor::CollapseShapeOp::create(builder, tensor, reassociation.value())
           .getResult());
 }
 
@@ -230,10 +230,10 @@
     Value channel = buildCachedChannelLoading(op, builder);
     RankedTensorType resultType =
         cast<RankedTensorType>(op.getOperand().getType());
-    Value target = builder.create<tensor::EmptyOp>(resultType.getShape(),
-                                                   resultType.getElementType());
-    auto flowAllReduce = builder.create<IREE::Flow::CollectiveAllReduceOp>(
-        convertReductionKind(op.getReductionAttr()),
+    Value target = tensor::EmptyOp::create(builder, resultType.getShape(),
+                                           resultType.getElementType());
+    auto flowAllReduce = IREE::Flow::CollectiveAllReduceOp::create(
+        builder, convertReductionKind(op.getReductionAttr()),
         getCollectiveElementTypeAttr(resultType), target, op.getOperand(),
         channel);
     rewriter.replaceAllUsesWith(op.getResult(), flowAllReduce.getResult());
@@ -268,11 +268,11 @@
 
     RankedTensorType flowAllGatherResultType = transpose(
         cast<RankedTensorType>(op.getResult().getType()), 0, gatherAxis);
-    Value target = builder.create<tensor::EmptyOp>(
-        flowAllGatherResultType.getShape(),
-        op.getResult().getType().getElementType());
-    auto flowAllGather = builder.create<IREE::Flow::CollectiveAllGatherOp>(
-        getCollectiveElementTypeAttr(flowAllGatherResultType), target,
+    Value target =
+        tensor::EmptyOp::create(builder, flowAllGatherResultType.getShape(),
+                                op.getResult().getType().getElementType());
+    auto flowAllGather = IREE::Flow::CollectiveAllGatherOp::create(
+        builder, getCollectiveElementTypeAttr(flowAllGatherResultType), target,
         flowAllGatherOperand, channel);
 
     Value res = buildTranspose(flowAllGather, 0, gatherAxis, builder);
@@ -318,12 +318,12 @@
     TypedValue<RankedTensorType> splitAxisAsMostOuter =
         buildTranspose(op.getOperand(), 0, splitAxis, builder);
 
-    Value target = builder.create<tensor::EmptyOp>(
-        splitAxisAsMostOuter.getType().getShape(),
+    Value target = tensor::EmptyOp::create(
+        builder, splitAxisAsMostOuter.getType().getShape(),
         splitAxisAsMostOuter.getType().getElementType());
-    auto flowAllToAll = builder.create<IREE::Flow::CollectiveAllToAllOp>(
-        getCollectiveElementTypeAttr(splitAxisAsMostOuter.getType()), target,
-        splitAxisAsMostOuter, channel);
+    auto flowAllToAll = IREE::Flow::CollectiveAllToAllOp::create(
+        builder, getCollectiveElementTypeAttr(splitAxisAsMostOuter.getType()),
+        target, splitAxisAsMostOuter, channel);
 
     TypedValue<RankedTensorType> splitAxisBackInItsPlace =
         buildTranspose(flowAllToAll, 0, splitAxis, builder);
@@ -347,8 +347,8 @@
     ImplicitLocOpBuilder builder(op->getLoc(), rewriter);
     builder.setInsertionPointAfter(op.getOperation());
     Value channel = buildCachedChannelLoading(op, builder);
-    Value newIndex = builder.create<IREE::Flow::ChannelRankOp>(
-        builder.getIndexType(), channel);
+    Value newIndex = IREE::Flow::ChannelRankOp::create(
+        builder, builder.getIndexType(), channel);
     rewriter.replaceAllUsesWith(op.getResult(), newIndex);
     return success();
   }
@@ -380,14 +380,13 @@
     RankedTensorType flowReduceScatterResultType = transpose(
         cast<RankedTensorType>(op.getResult().getType()), 0, scatterAxis);
 
-    Value target = builder.create<tensor::EmptyOp>(
-        flowReduceScatterResultType.getShape(),
-        op.getResult().getType().getElementType());
-    auto flowReduceScatter =
-        builder.create<IREE::Flow::CollectiveReduceScatterOp>(
-            convertReductionKind(op.getReductionAttr()),
-            getCollectiveElementTypeAttr(flowReduceScatterResultType), target,
-            flowReduceScatterOperand, channel);
+    Value target =
+        tensor::EmptyOp::create(builder, flowReduceScatterResultType.getShape(),
+                                op.getResult().getType().getElementType());
+    auto flowReduceScatter = IREE::Flow::CollectiveReduceScatterOp::create(
+        builder, convertReductionKind(op.getReductionAttr()),
+        getCollectiveElementTypeAttr(flowReduceScatterResultType), target,
+        flowReduceScatterOperand, channel);
 
     Value res = buildTranspose(flowReduceScatter, 0, scatterAxis, builder);
 
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Conversion/TensorToFlow/Patterns.cpp b/compiler/src/iree/compiler/Dialect/Flow/Conversion/TensorToFlow/Patterns.cpp
index f95ec9e..99b0ee5 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Conversion/TensorToFlow/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Conversion/TensorToFlow/Patterns.cpp
@@ -164,11 +164,11 @@
                                 ? inputType.getDimSize(position)
                                 : resultType.getDimSize(position);
           dimSizes[position] =
-              rewriter.create<arith::ConstantIndexOp>(loc, dimSize);
+              arith::ConstantIndexOp::create(rewriter, loc, dimSize);
         } else {
           // Dynamic dim.
           dimSizes[position] =
-              rewriter.create<tensor::DimOp>(loc, input, position);
+              tensor::DimOp::create(rewriter, loc, input, position);
         }
       }
 
@@ -249,14 +249,14 @@
       inputShapes.emplace_back(std::move(inputShape));
     }
 
-    Value replacement = rewriter.create<tensor::EmptyOp>(
-        loc, outputShape, concatOp.getType().getElementType());
+    Value replacement = tensor::EmptyOp::create(
+        rewriter, loc, outputShape, concatOp.getType().getElementType());
 
     SmallVector<int64_t> resultStaticDims;
     SmallVector<Value> resultDynamicDims;
     dispatchIndexOpFoldResults(outputShape, resultDynamicDims,
                                resultStaticDims);
-    Value zero = rewriter.create<arith::ConstantIndexOp>(loc, 0);
+    Value zero = arith::ConstantIndexOp::create(rewriter, loc, 0);
     // Generate the `flow.tensor.update` operations for the concat.
     for (auto [index, input] : llvm::enumerate(concatOp.getInputs())) {
       SmallVector<int64_t> inputStaticShape;
@@ -266,9 +266,9 @@
       SmallVector<Value> offsets(inputStaticShape.size(), zero);
       offsets[0] =
           getValueOrCreateConstantIndexOp(rewriter, loc, concatOffsets[index]);
-      replacement = rewriter.create<IREE::Flow::TensorUpdateOp>(
-          loc, replacement.getType(), replacement, resultDynamicDims, offsets,
-          input, inputDynamicShape);
+      replacement = IREE::Flow::TensorUpdateOp::create(
+          rewriter, loc, replacement.getType(), replacement, resultDynamicDims,
+          offsets, input, inputDynamicShape);
     }
     rewriter.replaceOp(concatOp, replacement);
     return success();
@@ -299,19 +299,20 @@
     }
 
     const int64_t rank = tensorType.getRank();
-    Value result = rewriter.create<tensor::EmptyOp>(
-        op.getLoc(), tensorType.getShape(), tensorType.getElementType());
+    Value result =
+        tensor::EmptyOp::create(rewriter, op.getLoc(), tensorType.getShape(),
+                                tensorType.getElementType());
     SmallVector<Value> ivs(rank);
     for (int i = 0, s = op.getNumOperands(); i < s; ++i) {
       int64_t index = i;
       for (int j = rank - 1; j >= 0; --j) {
         int64_t iv = index % tensorType.getDimSize(j);
         index = index / tensorType.getDimSize(j);
-        ivs[j] = rewriter.create<arith::ConstantIndexOp>(op.getLoc(), iv);
+        ivs[j] = arith::ConstantIndexOp::create(rewriter, op.getLoc(), iv);
       }
 
-      result = rewriter.create<Flow::TensorStoreOp>(
-          op.getLoc(), op.getOperand(i), result, ivs);
+      result = Flow::TensorStoreOp::create(rewriter, op.getLoc(),
+                                           op.getOperand(i), result, ivs);
     }
 
     rewriter.replaceOp(op, result);
@@ -327,7 +328,7 @@
   SmallVector<Value> sizes;
   for (const auto [idx, size] : enumerate(type.getShape())) {
     if (type.isDynamicDim(idx)) {
-      Value dim = builder.create<tensor::DimOp>(loc, tensor, idx);
+      Value dim = tensor::DimOp::create(builder, loc, tensor, idx);
       sizes.push_back(dim);
     }
   }
@@ -360,14 +361,14 @@
     // (ignore static dimensions)
     SmallVector<Value> destSizes;
     for (int i = 0; i < shapeOperandType.getShape()[0]; i++) {
-      Value idx = rewriter.create<arith::ConstantIndexOp>(loc, i);
-      Value element = rewriter.create<tensor::ExtractOp>(loc, op.getShape(),
-                                                         ValueRange({idx}));
+      Value idx = arith::ConstantIndexOp::create(rewriter, loc, i);
+      Value element = tensor::ExtractOp::create(rewriter, loc, op.getShape(),
+                                                ValueRange({idx}));
       if (ShapedType::isDynamic(resultType.getShape()[i])) {
         auto elementTy = element.getType();
         if (isa<IntegerType>(elementTy)) {
-          element = rewriter.create<arith::IndexCastOp>(
-              loc, rewriter.getIndexType(), element);
+          element = arith::IndexCastOp::create(
+              rewriter, loc, rewriter.getIndexType(), element);
         }
         destSizes.push_back(element);
       }
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Conversion/TensorToFlow/Utils.cpp b/compiler/src/iree/compiler/Dialect/Flow/Conversion/TensorToFlow/Utils.cpp
index 2cd6bc4..4ba9c16 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Conversion/TensorToFlow/Utils.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Conversion/TensorToFlow/Utils.cpp
@@ -153,8 +153,9 @@
     auto unreducedShape = getShapeFromSizes(sizes);
     sourceType =
         RankedTensorType::get(unreducedShape, sourceType.getElementType());
-    source = rewriter.create<IREE::Flow::TensorReshapeOp>(
-        loc, sourceType, source, sourceDynamicDims, sourceDynamicDims);
+    source = IREE::Flow::TensorReshapeOp::create(rewriter, loc, sourceType,
+                                                 source, sourceDynamicDims,
+                                                 sourceDynamicDims);
   }
 
   auto offsetVals = getValueOrCreateConstantIndexOp(rewriter, loc,
@@ -203,12 +204,12 @@
   auto sourceDynamicDims =
       tensor::createDynamicDimValues(rewriter, loc, sliceOp.getSource());
   auto resultDynamicDims = getDynamicValues(sizes);
-  Value replacement = rewriter.create<TensorSliceOp>(
-      loc, resultType, sliceOp.getSource(), sourceDynamicDims, offsetVals,
-      sizeVals, resultDynamicDims);
+  Value replacement = TensorSliceOp::create(
+      rewriter, loc, resultType, sliceOp.getSource(), sourceDynamicDims,
+      offsetVals, sizeVals, resultDynamicDims);
   if (resultType.getRank() > sliceOp.getType().getRank()) {
-    replacement = rewriter.create<IREE::Flow::TensorReshapeOp>(
-        loc, sliceOp.getType(), replacement, resultDynamicDims,
+    replacement = IREE::Flow::TensorReshapeOp::create(
+        rewriter, loc, sliceOp.getType(), replacement, resultDynamicDims,
         resultDynamicDims);
   }
   rewriter.replaceOp(sliceOp, replacement);
diff --git a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowDialect.cpp b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowDialect.cpp
index 577ad48..dd78f83 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowDialect.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowDialect.cpp
@@ -75,10 +75,11 @@
 Operation *FlowDialect::materializeConstant(OpBuilder &builder, Attribute value,
                                             Type type, Location loc) {
   if (arith::ConstantOp::isBuildableWith(value, type)) {
-    return builder.create<arith::ConstantOp>(loc, type, cast<TypedAttr>(value));
+    return arith::ConstantOp::create(builder, loc, type,
+                                     cast<TypedAttr>(value));
   } else if (IREE::Flow::TensorConstantOp::isBuildableWith(value, type)) {
-    return builder.create<IREE::Flow::TensorConstantOp>(loc, type,
-                                                        cast<TypedAttr>(value));
+    return IREE::Flow::TensorConstantOp::create(builder, loc, type,
+                                                cast<TypedAttr>(value));
   }
   return nullptr;
 }
diff --git a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOpFolders.cpp b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOpFolders.cpp
index acb417e..ec8c8cb 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOpFolders.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOpFolders.cpp
@@ -216,8 +216,8 @@
         continue;
       if (isTensorResultZeroElements(result)) {
         auto dynamicDims = op.getResultDynamicDims(result.getResultNumber());
-        auto emptyOp = rewriter.create<IREE::Flow::TensorEmptyOp>(
-            result.getLoc(), result.getType(), dynamicDims);
+        auto emptyOp = IREE::Flow::TensorEmptyOp::create(
+            rewriter, result.getLoc(), result.getType(), dynamicDims);
         rewriter.replaceAllUsesWith(result, emptyOp);
         didReplaceAny = true;
       }
@@ -243,8 +243,8 @@
 
     // Create a new flow.dispatch.workgroup op with new workloads.
     Location loc = op.getLoc();
-    auto newWorkgroupsOp = rewriter.create<DispatchWorkgroupsOp>(
-        loc, newWorkload, op.getResultTypes(), op.getResultDims(),
+    auto newWorkgroupsOp = DispatchWorkgroupsOp::create(
+        rewriter, loc, newWorkload, op.getResultTypes(), op.getResultDims(),
         op.getArguments(), op.getArgumentDims(),
         op.getTiedOperandsAsIntegerList(),
         getPrunedAttributeList(op, /*elidedAttrs=*/{}));
@@ -452,8 +452,8 @@
   using OpRewritePattern::OpRewritePattern;
   LogicalResult matchAndRewrite(TensorDynamicConstantOp op,
                                 PatternRewriter &rewriter) const override {
-    auto constantOp = rewriter.create<IREE::Flow::TensorConstantOp>(
-        op.getLoc(), op.getValue());
+    auto constantOp = IREE::Flow::TensorConstantOp::create(
+        rewriter, op.getLoc(), op.getValue());
     auto dynamicType = op.getType();
     auto staticType = cast<ShapedType>(op.getValue().getType());
     SmallVector<Value> dynamicDims;
@@ -837,8 +837,7 @@
     }
     Value originValue = sourceOp.getSource();
     ValueRange originDims = sourceOp.getSourceDims();
-    auto newOp =
-        rewriter.create<TransferOpT>(transferOp.getLoc(), originValue,
+    auto newOp = TransferOpT::create(rewriter, transferOp.getLoc(), originValue,
                                      originDims, transferOp.getTargetAttr());
     IRMapping mapper;
     mapper.map(originValue, newOp.getResult());
@@ -1080,8 +1079,8 @@
                                  : cast<Value>(updateOp.getTarget()));
     Value update = (updateCastOp ? cast<Value>(updateCastOp.getSource())
                                  : cast<Value>(updateOp.getUpdate()));
-    auto newOp = rewriter.create<TensorUpdateOp>(
-        updateOp.getLoc(), target.getType(), target,
+    auto newOp = TensorUpdateOp::create(
+        rewriter, updateOp.getLoc(), target.getType(), target,
         refreshDimsOnTypeChange(updateOp, updateOp.getTarget().getType(),
                                 target.getType(), updateOp.getTargetDims(),
                                 rewriter),
diff --git a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.cpp b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.cpp
index f2f7373..6f12217 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOps.cpp
@@ -595,8 +595,9 @@
     return false;
 
   // Create new region and move over the body.
-  auto newRegionOp = rewriter.create<Flow::DispatchRegionOp>(
-      regionOp.getLoc(), resultTypes, dynamicDims, regionOp.getWorkload());
+  auto newRegionOp =
+      Flow::DispatchRegionOp::create(rewriter, regionOp.getLoc(), resultTypes,
+                                     dynamicDims, regionOp.getWorkload());
   newRegionOp.getBody().takeBody(regionOp.getBody());
 
   // Update terminator.
@@ -1049,9 +1050,10 @@
   IREE::Util::excludeTiedOperandAndResultIndices(
       excludedOperandIndices, excludedResultIndices, newTiedOperandIndices);
 
-  auto newOp = rewriter.create<DispatchWorkgroupsOp>(
-      getLoc(), getWorkload(), newResultTypes, newResultDims, newArguments,
-      newArgumentDims, newTiedOperandIndices, getOperation()->getAttrs());
+  auto newOp = DispatchWorkgroupsOp::create(
+      rewriter, getLoc(), getWorkload(), newResultTypes, newResultDims,
+      newArguments, newArgumentDims, newTiedOperandIndices,
+      getOperation()->getAttrs());
   newOp->setDialectAttrs(getOperation()->getDialectAttrs());
   auto &newBody = newOp.getClosureBodyRegion();
   newBody.takeBody(getClosureBodyRegion());
diff --git a/compiler/src/iree/compiler/Dialect/Flow/TransformExtensions/FlowExtensions.cpp b/compiler/src/iree/compiler/Dialect/Flow/TransformExtensions/FlowExtensions.cpp
index 7736be5..14daed2 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/TransformExtensions/FlowExtensions.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/TransformExtensions/FlowExtensions.cpp
@@ -69,9 +69,9 @@
   }
   // Resize to `3` to match IREE's assumptions.
   for (unsigned i = results.size(); i < 3; ++i) {
-    results.push_back(rewriter.create<arith::ConstantIndexOp>(loc, 1));
+    results.push_back(arith::ConstantIndexOp::create(rewriter, loc, 1));
   }
-  rewriter.create<IREE::Flow::ReturnOp>(loc, results);
+  IREE::Flow::ReturnOp::create(rewriter, loc, results);
 
   return success();
 }
@@ -101,7 +101,7 @@
            "expected that dest is an output bbArg");
     Value dest = forallOp.getTiedOpOperand(destBbArg)->get();
     // clang-format off
-    rewriter.create<IREE::TensorExt::DispatchTensorStoreOp>(
+    IREE::TensorExt::DispatchTensorStoreOp::create(rewriter,
         loc,
         parallelInsertOp.getSource(),
         tensorToFlowBvm.lookup(dest),
@@ -144,7 +144,7 @@
     auto dynamicDims = IREE::Util::findDynamicDimsInList(index, tensorOperands,
                                                          tensorDynamicDims);
     // clang-format off
-    Value load = rewriter.create<IREE::TensorExt::DispatchTensorLoadOp>(
+    Value load = IREE::TensorExt::DispatchTensorLoadOp::create(rewriter,
         loc,
         sourceFlow,
         dynamicDims,
@@ -273,7 +273,7 @@
         getIndicesOfDynamicDims(llvm::cast<ShapedType>(dest.getType()));
     for (int64_t dim : dynamicDims)
       resultTensorsDynamicDims.insert(
-          rewriter.create<tensor::DimOp>(loc, dest, dim));
+          tensor::DimOp::create(rewriter, loc, dest, dim));
   }
   assert(resultTensorOperands.size() == forallOp.getNumResults() &&
          "Expected as many resultTensorOperands as results of forallOp");
@@ -296,7 +296,7 @@
       continue;
     tensorOperands.push_back(v);
     for (int64_t dim : getIndicesOfDynamicDims(tensorType))
-      tensorDynamicDims.push_back(rewriter.create<tensor::DimOp>(loc, v, dim));
+      tensorDynamicDims.push_back(tensor::DimOp::create(rewriter, loc, v, dim));
   }
   // Also add shared outputs. (These are usually already added as result
   // tensor operands.)
@@ -306,7 +306,7 @@
       continue;
     tensorOperands.push_back(v);
     for (int64_t dim : getIndicesOfDynamicDims(tensorType))
-      tensorDynamicDims.push_back(rewriter.create<tensor::DimOp>(loc, v, dim));
+      tensorDynamicDims.push_back(tensor::DimOp::create(rewriter, loc, v, dim));
   }
 
   // Step 3. Create ordered vectors of operands to pass to the builder and
@@ -330,7 +330,7 @@
   SmallVector<Value> allTensorDynamicDims = tensorDynamicDims;
   llvm::append_range(allTensorDynamicDims, resultTensorsDynamicDims);
   // clang-format off
-  auto dispatchOp = rewriter.create<IREE::Flow::DispatchWorkgroupsOp>(
+  auto dispatchOp = IREE::Flow::DispatchWorkgroupsOp::create(rewriter,
       loc,
       /*workload=*/ValueRange{},
       /*resultTypes=*/forallOp.getResultTypes(),
@@ -374,7 +374,7 @@
   {
     OpBuilder::InsertionGuard g(rewriter);
     rewriter.setInsertionPointToEnd(block);
-    rewriter.create<IREE::Flow::ReturnOp>(loc);
+    IREE::Flow::ReturnOp::create(rewriter, loc);
   }
   // Add trailing index bbArgs and perform a basic sanity check.
   block->addArguments(
@@ -411,8 +411,8 @@
     // does not work out of the box with IREE::TensorExt::DispatchTensorType.
     auto dynamicDims = IREE::Util::findDynamicDimsInList(
         en.index(), allTensorOperands, allTensorDimsBBArgs);
-    auto loadOp = rewriter.create<IREE::TensorExt::DispatchTensorLoadOp>(
-        loc, llvm::cast<RankedTensorType>(en.value().getType()),
+    auto loadOp = IREE::TensorExt::DispatchTensorLoadOp::create(
+        rewriter, loc, llvm::cast<RankedTensorType>(en.value().getType()),
         tensorToFlowBvm.lookup(en.value()), dynamicDims);
     // Replace the tensor -> iree_tensor_ext.dispatch.tensor entry by a
     // tensor -> iree_tensor_ext.dispatch.tensor.load entry.
@@ -425,9 +425,9 @@
   for (int64_t rank :
        llvm::seq<int64_t>(0, forallOp.getInductionVars().size())) {
     workgroupIds.push_back(
-        rewriter.create<IREE::Flow::DispatchWorkgroupIDOp>(loc, rank));
+        IREE::Flow::DispatchWorkgroupIDOp::create(rewriter, loc, rank));
     workgroupCounts.push_back(
-        rewriter.create<IREE::Flow::DispatchWorkgroupCountOp>(loc, rank));
+        IREE::Flow::DispatchWorkgroupCountOp::create(rewriter, loc, rank));
   }
   bvm.map(forallOp.getInductionVars(), workgroupIds);
   bvm.map(forallOp.getUpperBound(rewriter), workgroupCounts);
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/CaptureDynamicDims.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/CaptureDynamicDims.cpp
index c531167..5932170 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/CaptureDynamicDims.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/CaptureDynamicDims.cpp
@@ -105,8 +105,9 @@
     }
 
     // Insert a shape tie op into the region to associate the dims.
-    auto tieOp = entryBuilder.create<IREE::Flow::DispatchTieShapeOp>(
-        internalValue.getLoc(), tensorType, internalValue, capturedDims);
+    auto tieOp = IREE::Flow::DispatchTieShapeOp::create(
+        entryBuilder, internalValue.getLoc(), tensorType, internalValue,
+        capturedDims);
     internalValue.replaceAllUsesExcept(tieOp.getResult(), tieOp);
   };
 
@@ -195,9 +196,9 @@
   llvm::append_range(
       newInits, llvm::map_range(newIterables, std::mem_fn(&Iterable::init)));
   OpBuilder builder(forOp);
-  auto newForOp = builder.create<scf::ForOp>(
-      forOp->getLoc(), forOp.getLowerBound(), forOp.getUpperBound(),
-      forOp.getStep(), newInits);
+  auto newForOp =
+      scf::ForOp::create(builder, forOp->getLoc(), forOp.getLowerBound(),
+                         forOp.getUpperBound(), forOp.getStep(), newInits);
   newForOp.getRegion().takeBody(forOp.getRegion());
 
   // Adjust the loop body taken from the old 'scf.for' to account for the new
@@ -225,8 +226,8 @@
     if (dims.empty())
       continue;
 
-    Value tied = builder.create<Flow::TensorTieShapeOp>(
-        forOp.getLoc(), tensor.bbArg,
+    Value tied = Flow::TensorTieShapeOp::create(
+        builder, forOp.getLoc(), tensor.bbArg,
         llvm::map_to_vector(dims, std::mem_fn(&Iterable::bbArg)));
     tensor.bbArg.replaceAllUsesExcept(tied,
                                       /*exceptedUser=*/tied.getDefiningOp());
@@ -245,8 +246,8 @@
       continue;
 
     Value &replacement = results[tensor.result.getResultNumber()];
-    replacement = builder.create<Flow::TensorTieShapeOp>(
-        forOp.getLoc(), replacement,
+    replacement = Flow::TensorTieShapeOp::create(
+        builder, forOp.getLoc(), replacement,
         llvm::to_vector_of<Value>(
             llvm::map_range(dims, std::mem_fn(&Iterable::result))));
   }
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertRegionToWorkgroups.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertRegionToWorkgroups.cpp
index b92e043..ba73520 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertRegionToWorkgroups.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertRegionToWorkgroups.cpp
@@ -155,8 +155,8 @@
   }
 
   // Create the shell dispatch.workgroup ops.
-  auto workgroupsOp = rewriter.create<IREE::Flow::DispatchWorkgroupsOp>(
-      loc, regionOp.getWorkload(), regionOp.getResultTypes(),
+  auto workgroupsOp = IREE::Flow::DispatchWorkgroupsOp::create(
+      rewriter, loc, regionOp.getWorkload(), regionOp.getResultTypes(),
       regionOp.getResultDims(), arguments, argumentDims, tiedArguments);
   workgroupsOp->setDialectAttrs(regionOp->getDialectAttrs());
 
@@ -196,8 +196,8 @@
            "dynamic dims not found among arguments");
     SmallVector<Value> bbArgDims =
         llvm::map_to_vector(dims, [&](Value v) { return bvm.lookup(v); });
-    Value loadedTensor = rewriter.create<IREE::TensorExt::DispatchTensorLoadOp>(
-        loc, tensorType, inputBbArg, bbArgDims);
+    Value loadedTensor = IREE::TensorExt::DispatchTensorLoadOp::create(
+        rewriter, loc, tensorType, inputBbArg, bbArgDims);
     bvm.map(it.value(), loadedTensor);
     argValues.push_back(loadedTensor);
   }
@@ -240,12 +240,12 @@
 #endif // NDEBUG
       SmallVector<Value> bbArgDims =
           llvm::map_to_vector(dims, [&](Value v) { return bvm.lookup(v); });
-      rewriter.create<IREE::TensorExt::DispatchTensorStoreOp>(
-          loc, it.value(), outputBbArg, bbArgDims);
+      IREE::TensorExt::DispatchTensorStoreOp::create(rewriter, loc, it.value(),
+                                                     outputBbArg, bbArgDims);
     }
 
     // Delete the old terminator and create a new one.
-    rewriter.create<IREE::Flow::ReturnOp>(loc);
+    IREE::Flow::ReturnOp::create(rewriter, loc);
     rewriter.eraseOp(terminator);
   }
 
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertShardToFlow.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertShardToFlow.cpp
index 04f27dd..5c3ac5f 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertShardToFlow.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/ConvertShardToFlow.cpp
@@ -127,9 +127,10 @@
                                bool useNamedDefaultChannels,
                                OpBuilder &builder) {
   if (useNamedDefaultChannels)
-    return builder.create<IREE::Flow::ChannelDefaultOp>(loc, grid.getSymName());
+    return IREE::Flow::ChannelDefaultOp::create(builder, loc,
+                                                grid.getSymName());
   else
-    return builder.create<IREE::Flow::ChannelDefaultOp>(loc);
+    return IREE::Flow::ChannelDefaultOp::create(builder, loc);
 }
 
 static Value buildCachedChannelLoading(Location loc, shard::GridOp grid,
@@ -141,8 +142,8 @@
   }
   // TODO: lookup the shard name instead of generating it again - today this
   // will fail if there are any conflicting names during channel creation.
-  return builder.create<IREE::Util::GlobalLoadOp>(
-      loc, builder.getType<IREE::Flow::ChannelType>(),
+  return IREE::Util::GlobalLoadOp::create(
+      builder, loc, builder.getType<IREE::Flow::ChannelType>(),
       getGridChannelName(grid, gridAxes));
 }
 
@@ -166,9 +167,9 @@
   Value shardChannel = getDefaultChannel(builder.getLoc(), grid,
                                          useNamedDefaultChannels, builder);
   SmallVector<Value> gridProcessMultiIndex =
-      builder.create<shard::ProcessMultiIndexOp>(grid).getResults();
+      shard::ProcessMultiIndexOp::create(builder, grid).getResults();
   SmallVector<Value> gridShape =
-      builder.create<shard::GridShapeOp>(grid).getResults();
+      shard::GridShapeOp::create(builder, grid).getResults();
   SmallVector<Value> reorderedGridIndex =
       permute(ArrayRef<Value>(gridProcessMultiIndex), gridAxes);
   SmallVector<Value> reorderedGridShape =
@@ -181,8 +182,8 @@
                            toOpFoldResults(reorderedGridShape), builder);
   OpFoldResult color = linearIndexFromShape(
       toOpFoldResults(groupIndex), toOpFoldResults(groupsShape), builder);
-  return builder.create<IREE::Flow::ChannelSplitOp>(
-      shardChannel,
+  return IREE::Flow::ChannelSplitOp::create(
+      builder, shardChannel,
       getValueOrCreateConstantIndexOp(builder, builder.getLoc(), color),
       getValueOrCreateConstantIndexOp(builder, builder.getLoc(),
                                       reorderedProcessLinearIndex));
@@ -192,16 +193,15 @@
                                     ArrayRef<shard::GridAxis> gridAxes,
                                     bool useNamedDefaultChannels,
                                     ImplicitLocOpBuilder &builder) {
-  IREE::Util::InitializerOp initOp =
-      builder.create<IREE::Util::InitializerOp>();
+  auto initOp = IREE::Util::InitializerOp::create(builder);
   Block *block = builder.createBlock(&initOp.getBody());
   ImplicitLocOpBuilder::InsertionGuard insertionGuard(builder);
   builder.setInsertionPointToStart(block);
   Value channel =
       buildChannelCreation(grid, gridAxes, useNamedDefaultChannels, builder);
-  builder.create<IREE::Util::GlobalStoreOp>(channel,
-                                            getGridChannelName(grid, gridAxes));
-  builder.create<IREE::Util::ReturnOp>();
+  IREE::Util::GlobalStoreOp::create(builder, channel,
+                                    getGridChannelName(grid, gridAxes));
+  IREE::Util::ReturnOp::create(builder);
 }
 
 // Construct a Flow channel inside `module` using
@@ -219,8 +219,8 @@
   builder.setInsertionPointToStart(&module.getBodyRegion().getBlocks().front());
 
   auto channelName = getGridChannelName(grid, gridAxes);
-  builder.create<IREE::Util::GlobalOp>(
-      builder.getStringAttr("private"), channelName,
+  IREE::Util::GlobalOp::create(
+      builder, builder.getStringAttr("private"), channelName,
       builder.getType<IREE::Flow::ChannelType>(), false, TypedAttr(),
       builder.getAttr<IREE::Util::InlineNeverAttr>());
   buildChannelInitializer(grid, gridAxes, useNamedDefaultChannels, builder);
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/ExportBenchmarkFuncs.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/ExportBenchmarkFuncs.cpp
index c2c96e6..3d207b3 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/ExportBenchmarkFuncs.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/ExportBenchmarkFuncs.cpp
@@ -43,9 +43,9 @@
   }
 
   // Global with initializer; tensors will get turned into buffers eventually.
-  auto globalOp = moduleBuilder.create<IREE::Util::GlobalOp>(
-      loc, name,
-      /*isMutable=*/false, type, initialValue);
+  auto globalOp =
+      IREE::Util::GlobalOp::create(moduleBuilder, loc, name,
+                                   /*isMutable=*/false, type, initialValue);
   globalOp.setPrivate();
   globalOp.setGlobalInliningPolicy(
       moduleBuilder.getAttr<IREE::Util::InlineNeverAttr>());
@@ -60,9 +60,8 @@
                          TensorType tensorType, SymbolTable &symbolTable,
                          OpBuilder &moduleBuilder) {
   // Create !hal.buffer global for the storage buffer or buffer view.
-  auto globalOp = moduleBuilder.create<IREE::Util::GlobalOp>(
-      loc, name,
-      /*isMutable=*/false, globalType);
+  auto globalOp = IREE::Util::GlobalOp::create(moduleBuilder, loc, name,
+                                               /*isMutable=*/false, globalType);
   globalOp.setPrivate();
   globalOp.setGlobalInliningPolicy(
       moduleBuilder.getAttr<IREE::Util::InlineNeverAttr>());
@@ -71,25 +70,26 @@
   // Create an initializer that allocates the buffer storage.
   // We do this by splatting and exporting to a buffer so that it looks like it
   // was created by the user.
-  auto initializerOp = moduleBuilder.create<IREE::Util::InitializerOp>(loc);
+  auto initializerOp = IREE::Util::InitializerOp::create(moduleBuilder, loc);
   auto initializerBuilder =
       OpBuilder::atBlockBegin(initializerOp.addEntryBlock());
   auto zeroAttr = moduleBuilder.getZeroAttr(tensorType.getElementType());
-  auto zeroOp = initializerBuilder.create<arith::ConstantOp>(loc, zeroAttr);
+  auto zeroOp = arith::ConstantOp::create(initializerBuilder, loc, zeroAttr);
   // flow.tensor.splat 0
-  auto splatOp = initializerBuilder.create<IREE::Flow::TensorSplatOp>(
-      loc, tensorType, zeroOp, /*result_dims=*/ValueRange{});
+  auto splatOp =
+      IREE::Flow::TensorSplatOp::create(initializerBuilder, loc, tensorType,
+                                        zeroOp, /*result_dims=*/ValueRange{});
   // hal.tensor.export
-  auto bufferExportOp = initializerBuilder.create<IREE::HAL::TensorExportOp>(
-      loc, globalOp.getType(), splatOp.getResult(),
+  auto bufferExportOp = IREE::HAL::TensorExportOp::create(
+      initializerBuilder, loc, globalOp.getType(), splatOp.getResult(),
       TypeAttr::get(splatOp.getType()), /*name=*/nullptr,
       /*affinity=*/nullptr);
   // util.optimization_barrier (try to prevent optimizations across the export)
-  auto barrierOp = initializerBuilder.create<IREE::Util::OptimizationBarrierOp>(
-      loc, bufferExportOp.getTarget());
+  auto barrierOp = IREE::Util::OptimizationBarrierOp::create(
+      initializerBuilder, loc, bufferExportOp.getTarget());
   // util.global.store
   globalOp.createStoreOp(loc, barrierOp.getResult(0), initializerBuilder);
-  initializerBuilder.create<IREE::Util::ReturnOp>(loc);
+  IREE::Util::ReturnOp::create(initializerBuilder, loc);
 
   return globalOp;
 }
@@ -230,8 +230,8 @@
 
   // Create a `() -> ()` entry point op the benchmark tool can run.
   Location loc = entryFuncOp.getLoc();
-  auto funcOp = moduleBuilder.create<IREE::Util::FuncOp>(
-      loc, funcName, moduleBuilder.getFunctionType({}, {}));
+  auto funcOp = IREE::Util::FuncOp::create(
+      moduleBuilder, loc, funcName, moduleBuilder.getFunctionType({}, {}));
   funcOp.setPublic();
   funcOp->setAttr("iree.abi.stub", moduleBuilder.getUnitAttr());
   NamedAttribute reflectionAttr("iree.benchmark",
@@ -248,14 +248,15 @@
                        .createLoadOp(loc, blockBuilder)
                        .getLoadedGlobalValue());
   }
-  auto callOp = blockBuilder.create<IREE::Util::CallOp>(loc, entryFuncOp, args);
+  auto callOp =
+      IREE::Util::CallOp::create(blockBuilder, loc, entryFuncOp, args);
 
   // Sink all results with a barrier to ensure that DCE does not remove the
   // call.
   for (auto result : callOp.getResults()) {
-    blockBuilder.create<IREE::Util::OptimizationBarrierOp>(loc, result);
+    IREE::Util::OptimizationBarrierOp::create(blockBuilder, loc, result);
   }
-  blockBuilder.create<IREE::Util::ReturnOp>(loc);
+  IREE::Util::ReturnOp::create(blockBuilder, loc);
 
   // Ensure the original function is not exported and not inlined.
   entryFuncOp->setAttr("noinline", moduleBuilder.getUnitAttr());
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/InitializeEmptyTensors.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/InitializeEmptyTensors.cpp
index 0e15e92..736af33 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/InitializeEmptyTensors.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/InitializeEmptyTensors.cpp
@@ -58,7 +58,7 @@
           emptyTensorOp, "unable to get zero value for element type");
     }
     Value value =
-        rewriter.create<arith::ConstantOp>(loc, elementType, zero.value());
+        arith::ConstantOp::create(rewriter, loc, elementType, zero.value());
     rewriter.replaceOpWithNewOp<TensorSplatOp>(emptyTensorOp, resultType, value,
                                                emptyTensorOp.getDynamicSizes());
     return success();
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/InjectDispatchTracing.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/InjectDispatchTracing.cpp
index 3ef6b52..fc9f2d6 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/InjectDispatchTracing.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/InjectDispatchTracing.cpp
@@ -57,8 +57,8 @@
     }
     OpBuilder::InsertionGuard g(builder);
     builder.setInsertionPointAfterValue(v.value);
-    Value rowMajorTensor = builder.create<IREE::Flow::TensorEncodeOp>(
-        v.value.getLoc(), rankedTensorType.dropEncoding(), v.value,
+    Value rowMajorTensor = IREE::Flow::TensorEncodeOp::create(
+        builder, v.value.getLoc(), rankedTensorType.dropEncoding(), v.value,
         /*operand_dims=*/v.dynamicDims, /*result_dims=*/v.dynamicDims);
     rowMajorTensors.push_back(rowMajorTensor);
     decodedIndices.push_back(idx);
@@ -96,8 +96,8 @@
       std::string inputsLabelStr = appendDecodedValuesToLabel(
           entryPointName + " inputs", decodedInputIndices);
       StringAttr inputsLabel = builder.getStringAttr(inputsLabelStr);
-      builder.create<IREE::Flow::TensorTraceOp>(
-          dispatchOp.getLoc(), inputsLabel, decodedInputValues);
+      IREE::Flow::TensorTraceOp::create(builder, dispatchOp.getLoc(),
+                                        inputsLabel, decodedInputValues);
 
       // Output tensors:
       SmallVector<TensorValue> resultTensorValues = filterTensorValues(
@@ -119,8 +119,8 @@
         }
       }
       builder.setInsertionPointAfter(lastResult);
-      builder.create<IREE::Flow::TensorTraceOp>(
-          dispatchOp.getLoc(), outputsLabel, decodedResultValues);
+      IREE::Flow::TensorTraceOp::create(builder, dispatchOp.getLoc(),
+                                        outputsLabel, decodedResultValues);
     }
   }
 };
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/InjectTensorTracing.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/InjectTensorTracing.cpp
index 7688c2a..d1a174b 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/InjectTensorTracing.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/InjectTensorTracing.cpp
@@ -53,16 +53,16 @@
   OpBuilder builder(op);
   auto inputTensors = getTensorOperands(op);
   if (!inputTensors.empty()) {
-    builder.create<IREE::Flow::TensorTraceOp>(
-        op->getLoc(), builder.getStringAttr(traceKey + " inputs"),
+    IREE::Flow::TensorTraceOp::create(
+        builder, op->getLoc(), builder.getStringAttr(traceKey + " inputs"),
         inputTensors);
   }
 
   builder.setInsertionPointAfter(op);
   auto outputTensors = filterTensorValues(op->getResults());
   if (!outputTensors.empty()) {
-    builder.create<IREE::Flow::TensorTraceOp>(
-        op->getLoc(), builder.getStringAttr(traceKey + " outputs"),
+    IREE::Flow::TensorTraceOp::create(
+        builder, op->getLoc(), builder.getStringAttr(traceKey + " outputs"),
         outputTensors);
   }
 }
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/InsertDispatchDebugTargets.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/InsertDispatchDebugTargets.cpp
index 49212b5..3318176 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/InsertDispatchDebugTargets.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/InsertDispatchDebugTargets.cpp
@@ -60,15 +60,15 @@
                             std::string name) {
   OpBuilder builder(dispatchOp);
   // Input tensors:
-  builder.create<IREE::Flow::TensorTraceOp>(
-      dispatchOp.getLoc(), builder.getStringAttr(name + " inputs"),
+  IREE::Flow::TensorTraceOp::create(
+      builder, dispatchOp.getLoc(), builder.getStringAttr(name + " inputs"),
       filterNonTensorValues(dispatchOp.getArguments()));
 
   // Output tensors:
   OpBuilder::InsertionGuard guard(builder);
   builder.setInsertionPointAfter(dispatchOp);
-  builder.create<IREE::Flow::TensorTraceOp>(
-      dispatchOp.getLoc(), builder.getStringAttr(name + " outputs"),
+  IREE::Flow::TensorTraceOp::create(
+      builder, dispatchOp.getLoc(), builder.getStringAttr(name + " outputs"),
       filterNonTensorValues(dispatchOp.getResults()));
 }
 
@@ -102,8 +102,9 @@
   for (auto retVal : op->getResults()) {
     if (llvm::isa<TensorType>(retVal.getType())) {
       auto type = IREE::HAL::BufferViewType::get(context);
-      auto exportOp = builder.create<IREE::HAL::TensorExportOp>(
-          loc, type, retVal, TypeAttr::get(retVal.getType()), /*name=*/nullptr,
+      auto exportOp = IREE::HAL::TensorExportOp::create(
+          builder, loc, type, retVal, TypeAttr::get(retVal.getType()),
+          /*name=*/nullptr,
           /*affinity=*/nullptr);
       exports.push_back(exportOp.getResult());
       newTypes.push_back(type);
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/OutlineConstants.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/OutlineConstants.cpp
index 0e1562b..26cfddd 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/OutlineConstants.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/OutlineConstants.cpp
@@ -132,9 +132,9 @@
 
       // New immutable global takes the constant attribute in its specified
       // encoding.
-      auto globalOp = moduleBuilder.create<IREE::Util::GlobalOp>(
-          def.op->getLoc(), getConstantName(def), /*isMutable=*/false, def.type,
-          def.value);
+      auto globalOp = IREE::Util::GlobalOp::create(
+          moduleBuilder, def.op->getLoc(), getConstantName(def),
+          /*isMutable=*/false, def.type, def.value);
       globalOp.setPrivate();
       IREE::Util::HoistableAttrInterface::gatherHoistableAttrs(def.op,
                                                                globalOp);
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/OutlineDispatchExterns.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/OutlineDispatchExterns.cpp
index b15c34a..7344bc7 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/OutlineDispatchExterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/OutlineDispatchExterns.cpp
@@ -40,8 +40,8 @@
   // Create the dispatch op to the executable function.
   // Note that we copy the tied operand indices from the workgroups op - it
   // lines up 1:1 with the dispatch once we've outlined things.
-  auto dispatchOp = builder.create<IREE::Flow::DispatchOp>(
-      dispatchExternOp.getLoc(), dispatchExternOp.getResultTypes(),
+  auto dispatchOp = IREE::Flow::DispatchOp::create(
+      builder, dispatchExternOp.getLoc(), dispatchExternOp.getResultTypes(),
       dispatchExternOp.getWorkload(), builder.getArrayAttr(exportRefs),
       dispatchExternOp.getArguments(), dispatchExternOp.getArgumentDims(),
       dispatchExternOp.getResultDims(), dispatchExternOp.getTiedOperandsAttr());
@@ -67,8 +67,8 @@
       dispatchExternOp->getParentOfType<mlir::FunctionOpInterface>();
   auto parentModuleOp = parentFuncOp->getParentOfType<mlir::ModuleOp>();
   OpBuilder parentModuleBuilder(&parentModuleOp.getBody()->back());
-  auto executableOp = parentModuleBuilder.create<IREE::HAL::ExecutableOp>(
-      dispatchExternOp.getLoc(), name);
+  auto executableOp = IREE::HAL::ExecutableOp::create(
+      parentModuleBuilder, dispatchExternOp.getLoc(), name);
   executableOp.getOperation()->moveBefore(parentFuncOp);
   executableOp.setPrivate();
   moduleSymbolTable.insert(executableOp);
@@ -88,26 +88,26 @@
     // Create the variant for the given target. Note that we may have multiple
     // variants that use the same base targetAttr but have unique condition
     // regions so we rely on the symbol table for uniquing names.
-    auto variantOp = executableBuilder.create<IREE::HAL::ExecutableVariantOp>(
-        dispatchExternOp.getLoc(), targetAttr.getSymbolNameFragment(),
-        targetAttr);
+    auto variantOp = IREE::HAL::ExecutableVariantOp::create(
+        executableBuilder, dispatchExternOp.getLoc(),
+        targetAttr.getSymbolNameFragment(), targetAttr);
     variantOp.setObjectsAttr(targetObjectsAttr);
     executableSymbolTable.insert(variantOp);
 
     // Move over optional target condition region to a condition op.
     OpBuilder variantBuilder(variantOp.getBody());
     if (!targetConditionRegion.empty()) {
-      auto conditionOp =
-          variantBuilder.create<IREE::HAL::ExecutableConditionOp>(
-              dispatchExternOp.getLoc());
+      auto conditionOp = IREE::HAL::ExecutableConditionOp::create(
+          variantBuilder, dispatchExternOp.getLoc());
       IRMapping mapper;
       targetConditionRegion.cloneInto(&conditionOp.getBody(), mapper);
     }
 
     // Add an export pointing at the entry point function.
-    auto exportOp = variantBuilder.create<IREE::HAL::ExecutableExportOp>(
-        dispatchExternOp.getLoc(), dispatchExternOp.getExportNameAttr(),
-        targetOrdinalAttr, dispatchExternOp.getLayoutAttr(),
+    auto exportOp = IREE::HAL::ExecutableExportOp::create(
+        variantBuilder, dispatchExternOp.getLoc(),
+        dispatchExternOp.getExportNameAttr(), targetOrdinalAttr,
+        dispatchExternOp.getLayoutAttr(),
         dispatchExternOp.getWorkgroupSizeAttr(),
         dispatchExternOp.getSubgroupSizeAttr(),
         dispatchExternOp.getWorkgroupLocalMemoryAttr());
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/OutlineDispatchRegions.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/OutlineDispatchRegions.cpp
index 9e7f982..bd52c6f 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/OutlineDispatchRegions.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/OutlineDispatchRegions.cpp
@@ -39,15 +39,15 @@
   // Create the executable that will contain the outlined region.
   // NOTE: this will get uniquified if we have multiple in the same block.
   OpBuilder parentModuleBuilder(&parentModuleOp.getBody()->back());
-  auto executableOp =
-      parentModuleBuilder.create<IREE::Flow::ExecutableOp>(loc, executableName);
+  auto executableOp = IREE::Flow::ExecutableOp::create(parentModuleBuilder, loc,
+                                                       executableName);
 
   // Create the inner ModuleOp that contains the original functions. We need
   // to provide this shim as some ops (like std.call) look for the
   // containing module to provide symbol resolution.
   OpBuilder executableBuilder(executableOp);
   executableBuilder.setInsertionPointToStart(&executableOp.getBlock());
-  auto innerModule = executableBuilder.create<mlir::ModuleOp>(loc);
+  auto innerModule = mlir::ModuleOp::create(executableBuilder, loc);
   for (auto funcOp : funcOps) {
     innerModule.push_back(funcOp);
   }
@@ -72,8 +72,8 @@
   // Create the dispatch op to the executable function.
   // Note that we copy the tied operand indices from the workgroups op - it
   // lines up 1:1 with the dispatch once we've outlined things.
-  auto dispatchOp = builder.create<IREE::Flow::DispatchOp>(
-      dispatchWorkgroupsOp.getLoc(), exportOp,
+  auto dispatchOp = IREE::Flow::DispatchOp::create(
+      builder, dispatchWorkgroupsOp.getLoc(), exportOp,
       dispatchWorkgroupsOp.getWorkload(), dispatchWorkgroupsOp.getResultTypes(),
       dispatchWorkgroupsOp.getResultDims(), dispatchWorkgroupsOp.getArguments(),
       dispatchWorkgroupsOp.getArgumentDims(),
@@ -106,8 +106,8 @@
   for (auto &block : funcOp.getBlocks()) {
     if (auto returnOp = dyn_cast<IREE::Flow::ReturnOp>(block.back())) {
       OpBuilder builder(returnOp);
-      builder.create<mlir::func::ReturnOp>(
-          returnOp.getLoc(), llvm::to_vector(returnOp.getOperands()));
+      mlir::func::ReturnOp::create(builder, returnOp.getLoc(),
+                                   llvm::to_vector(returnOp.getOperands()));
       returnOp.erase();
     }
   }
@@ -138,8 +138,8 @@
 
   // Add an export pointing at the entry point function.
   OpBuilder builder(executableOp.getBody());
-  auto exportOp = builder.create<IREE::Flow::ExecutableExportOp>(
-      dispatchWorkgroupsOp.getLoc(), workgroupFuncOp.getName(),
+  auto exportOp = IREE::Flow::ExecutableExportOp::create(
+      builder, dispatchWorkgroupsOp.getLoc(), workgroupFuncOp.getName(),
       SymbolRefAttr::get(workgroupFuncOp));
   exportOp->setDialectAttrs(dispatchWorkgroupsOp->getDialectAttrs());
 
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.cpp
index 0a0cb1e..f9b5a4a 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/RegionOpUtils.cpp
@@ -55,7 +55,7 @@
 static SmallVector<Range> getLoopRangesImpl(TilingInterface tilableOp,
                                             Location loc, OpBuilder &builder) {
   SmallVector<Range> loopRanges = tilableOp.getIterationDomain(builder);
-  Value one = builder.create<arith::ConstantIndexOp>(loc, 1);
+  Value one = arith::ConstantIndexOp::create(builder, loc, 1);
   for (auto iteratorType : llvm::enumerate(tilableOp.getLoopIteratorTypes())) {
     if (iteratorType.value() == utils::IteratorType::reduction) {
       loopRanges[iteratorType.index()].size = one;
@@ -78,8 +78,8 @@
 static SmallVector<Range>
 getLoopRangesImpl(ReifyRankedShapedTypeOpInterface shapedOp, Location loc,
                   OpBuilder &builder) {
-  Value zero = builder.create<arith::ConstantIndexOp>(loc, 0);
-  Value one = builder.create<arith::ConstantIndexOp>(loc, 1);
+  Value zero = arith::ConstantIndexOp::create(builder, loc, 0);
+  Value one = arith::ConstantIndexOp::create(builder, loc, 1);
   ReifiedRankedShapedTypeDims resultDims;
   LogicalResult status = shapedOp.reifyResultShapes(builder, resultDims);
   (void)status;
@@ -143,8 +143,8 @@
     Value offset = getValueOrCreateConstantIndexOp(builder, loc, r.offset);
     Value size = getValueOrCreateConstantIndexOp(builder, loc, r.size);
     Value stride = getValueOrCreateConstantIndexOp(builder, loc, r.stride);
-    return builder.create<affine::AffineApplyOp>(
-        rootOp->getLoc(), workload, ValueRange{offset, size, stride});
+    return affine::AffineApplyOp::create(builder, rootOp->getLoc(), workload,
+                                         ValueRange{offset, size, stride});
   });
 }
 
@@ -212,10 +212,9 @@
   OpBuilder::InsertionGuard g(rewriter);
   rewriter.setInsertionPointToStart(body);
   Location loc = regionOp.getLoc();
-  auto countOp =
-      rewriter.create<IREE::TensorExt::DispatchWorkgroupCountFromDagRootOp>(
-          loc, args);
-  rewriter.create<IREE::Flow::ReturnOp>(loc, countOp->getResults());
+  auto countOp = IREE::TensorExt::DispatchWorkgroupCountFromDagRootOp::create(
+      rewriter, loc, args);
+  IREE::Flow::ReturnOp::create(rewriter, loc, countOp->getResults());
 }
 
 /// Return `true` if the given type is a ShapedType and has at least one
@@ -245,7 +244,7 @@
   auto emitTensorDimOps = [&]() {
     for (int64_t i = 0; i < shapedType.getRank(); ++i) {
       if (shapedType.isDynamicDim(i)) {
-        Value dim = b.create<tensor::DimOp>(value.getLoc(), value, i);
+        Value dim = tensor::DimOp::create(b, value.getLoc(), value, i);
         dynamicDims.push_back(dim);
       }
     }
@@ -371,8 +370,8 @@
   rewriter.setInsertionPoint(regionOp);
 
   // Create new DispatchRegionOp and move over the body.
-  auto newRegionOp = rewriter.create<IREE::Flow::DispatchRegionOp>(
-      regionOp->getLoc(), resultTypes, regionDynamicDims,
+  auto newRegionOp = IREE::Flow::DispatchRegionOp::create(
+      rewriter, regionOp->getLoc(), resultTypes, regionDynamicDims,
       regionOp.getWorkload());
   rewriter.inlineRegionBefore(regionOp.getBody(), newRegionOp.getBody(),
                               newRegionOp.getBody().begin());
@@ -394,11 +393,12 @@
   OpBuilder::InsertionGuard guard(builder);
 
   // Create RegionOp.
-  auto regionOp = builder.create<IREE::Flow::DispatchRegionOp>(
-      loc, /*resultTypes=*/TypeRange(), /*dynamicDims=*/ValueRange(), workload);
+  auto regionOp = IREE::Flow::DispatchRegionOp::create(
+      builder, loc, /*resultTypes=*/TypeRange(), /*dynamicDims=*/ValueRange(),
+      workload);
   Block &body = regionOp.getBody().emplaceBlock();
   builder.setInsertionPointToStart(&body);
-  builder.create<IREE::Flow::ReturnOp>(loc, ValueRange());
+  IREE::Flow::ReturnOp::create(builder, loc, ValueRange());
   return regionOp;
 }
 
@@ -749,9 +749,9 @@
       llvm::map_to_vector(newDispatchReturnOperands,
                           [](Value operand) { return operand.getType(); });
   rewriter.setInsertionPoint(dispatchRegionOp);
-  auto newDispatchRegionOp = rewriter.create<IREE::Flow::DispatchRegionOp>(
-      dispatchRegionOp->getLoc(), newResultTypes, newDispatchResultDynamicDims,
-      dispatchRegionOp.getWorkload());
+  auto newDispatchRegionOp = IREE::Flow::DispatchRegionOp::create(
+      rewriter, dispatchRegionOp->getLoc(), newResultTypes,
+      newDispatchResultDynamicDims, dispatchRegionOp.getWorkload());
   rewriter.inlineRegionBefore(dispatchRegionOp.getBody(),
                               newDispatchRegionOp.getBody(),
                               newDispatchRegionOp.getBody().begin());
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToHAL/Patterns.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToHAL/Patterns.cpp
index 705292b..1f8b4fc 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToHAL/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToHAL/Patterns.cpp
@@ -30,9 +30,9 @@
     Value device;
     auto resolveDevice = [&]() {
       if (!device) {
-        device = rewriter.create<IREE::HAL::DevicesGetOp>(
-            resolveOp.getLoc(), deviceType,
-            rewriter.create<arith::ConstantIndexOp>(resolveOp.getLoc(), 0));
+        device = IREE::HAL::DevicesGetOp::create(
+            rewriter, resolveOp.getLoc(), deviceType,
+            arith::ConstantIndexOp::create(rewriter, resolveOp.getLoc(), 0));
       }
       return device;
     };
@@ -42,11 +42,11 @@
       if (isa<IREE::HAL::DeviceType>(resultType)) {
         results.push_back(resolveDevice());
       } else if (isa<IREE::HAL::AllocatorType>(resultType)) {
-        results.push_back(rewriter.create<IREE::HAL::DeviceAllocatorOp>(
-            resolveOp.getLoc(), resolveDevice()));
+        results.push_back(IREE::HAL::DeviceAllocatorOp::create(
+            rewriter, resolveOp.getLoc(), resolveDevice()));
       } else if (isa<IntegerType>(resultType)) {
-        results.push_back(rewriter.create<arith::ConstantIntOp>(
-            resolveOp.getLoc(), -1ll, 64));
+        results.push_back(arith::ConstantIntOp::create(
+            rewriter, resolveOp.getLoc(), -1ll, 64));
       }
     }
 
@@ -76,8 +76,8 @@
     Value device;
     auto resolveDevice = [&]() {
       if (!device) {
-        device = rewriter.create<IREE::Util::GlobalLoadOp>(
-            resolveOp.getLoc(), deviceType, flatDeviceAttr.getValue(),
+        device = IREE::Util::GlobalLoadOp::create(
+            rewriter, resolveOp.getLoc(), deviceType, flatDeviceAttr.getValue(),
             /*is_immutable=*/true);
       }
       return device;
@@ -88,11 +88,11 @@
       if (isa<IREE::HAL::DeviceType>(resultType)) {
         results.push_back(resolveDevice());
       } else if (isa<IREE::HAL::AllocatorType>(resultType)) {
-        results.push_back(rewriter.create<IREE::HAL::DeviceAllocatorOp>(
-            resolveOp.getLoc(), resolveDevice()));
+        results.push_back(IREE::HAL::DeviceAllocatorOp::create(
+            rewriter, resolveOp.getLoc(), resolveDevice()));
       } else if (isa<IntegerType>(resultType)) {
-        results.push_back(rewriter.create<arith::ConstantIntOp>(
-            resolveOp.getLoc(), affinityAttr.getQueueMask(), 64));
+        results.push_back(arith::ConstantIntOp::create(
+            rewriter, resolveOp.getLoc(), affinityAttr.getQueueMask(), 64));
       }
     }
 
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertAllocatorOps.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertAllocatorOps.cpp
index 5b052bb..62d05f0 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertAllocatorOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertAllocatorOps.cpp
@@ -111,8 +111,8 @@
   LogicalResult
   matchAndRewrite(IREE::HAL::AllocatorImportOp op, OpAdaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
-    auto callOp = rewriter.create<IREE::VM::CallOp>(
-        op.getLoc(), importOp.getName(),
+    auto callOp = IREE::VM::CallOp::create(
+        rewriter, op.getLoc(), importOp.getName(),
         ArrayRef<Type>{
             getTypeConverter()->convertType(op.getResult().getType()),
         },
@@ -133,8 +133,8 @@
         });
     copyImportAttrs(importOp, callOp);
     auto result = callOp.getResults().front();
-    auto didImport = rewriter.create<IREE::VM::CmpNZRefOp>(
-        op.getLoc(), rewriter.getI32Type(), result);
+    auto didImport = IREE::VM::CmpNZRefOp::create(
+        rewriter, op.getLoc(), rewriter.getI32Type(), result);
     rewriter.replaceOp(op, {didImport, result});
     return success();
   }
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertBufferOps.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertBufferOps.cpp
index 17e8946..0405d32 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertBufferOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertBufferOps.cpp
@@ -44,45 +44,49 @@
     // 32-bit values are loaded directly, 64-bit are combined from 32 | 32.
     Value value;
     if (validByteWidth <= 4) {
-      auto byteWidth = rewriter.create<arith::ConstantIntOp>(
-          op.getLoc(), validByteWidth, 32);
-      auto callOp = rewriter.create<IREE::VM::CallOp>(
-          op.getLoc(), SymbolRefAttr::get(importOp), importType.getResults(),
+      auto byteWidth = arith::ConstantIntOp::create(rewriter, op.getLoc(),
+                                                    validByteWidth, 32);
+      auto callOp = IREE::VM::CallOp::create(
+          rewriter, op.getLoc(), SymbolRefAttr::get(importOp),
+          importType.getResults(),
           ArrayRef<Value>{adaptor.getSourceBuffer(), sourceOffset, byteWidth});
       copyImportAttrs(importOp, callOp);
       value = callOp.getResult(0);
     } else {
       auto halfByteWidth =
-          rewriter.create<arith::ConstantIntOp>(op.getLoc(), 4, 32);
+          arith::ConstantIntOp::create(rewriter, op.getLoc(), 4, 32);
 
       // value = (i64(hi) << 32) | i64(lo)
       auto hiOffset = rewriter.createOrFold<arith::AddIOp>(
           op.getLoc(), sourceOffset,
-          rewriter.create<IREE::VM::ConstI64Op>(op.getLoc(), 4));
-      auto hiCallOp = rewriter.create<IREE::VM::CallOp>(
-          op.getLoc(), SymbolRefAttr::get(importOp), importType.getResults(),
+          IREE::VM::ConstI64Op::create(rewriter, op.getLoc(), 4));
+      auto hiCallOp = IREE::VM::CallOp::create(
+          rewriter, op.getLoc(), SymbolRefAttr::get(importOp),
+          importType.getResults(),
           ArrayRef<Value>{adaptor.getSourceBuffer(), hiOffset, halfByteWidth});
-      auto hi = rewriter.create<arith::ShLIOp>(
-          op.getLoc(),
-          rewriter.create<arith::ExtUIOp>(
-              op.getLoc(), rewriter.getIntegerType(targetBitwidth),
-              hiCallOp.getResult(0)),
-          rewriter.create<arith::ConstantIntOp>(op.getLoc(), 32, 32));
+      auto hi = arith::ShLIOp::create(
+          rewriter, op.getLoc(),
+          arith::ExtUIOp::create(rewriter, op.getLoc(),
+                                 rewriter.getIntegerType(targetBitwidth),
+                                 hiCallOp.getResult(0)),
+          arith::ConstantIntOp::create(rewriter, op.getLoc(), 32, 32));
 
-      auto loCallOp = rewriter.create<IREE::VM::CallOp>(
-          op.getLoc(), SymbolRefAttr::get(importOp), importType.getResults(),
+      auto loCallOp = IREE::VM::CallOp::create(
+          rewriter, op.getLoc(), SymbolRefAttr::get(importOp),
+          importType.getResults(),
           ArrayRef<Value>{adaptor.getSourceBuffer(), sourceOffset,
                           halfByteWidth});
-      auto lo = rewriter.create<arith::ExtUIOp>(
-          op.getLoc(), rewriter.getIntegerType(targetBitwidth),
-          loCallOp.getResult(0));
+      auto lo = arith::ExtUIOp::create(rewriter, op.getLoc(),
+                                       rewriter.getIntegerType(targetBitwidth),
+                                       loCallOp.getResult(0));
 
-      value = rewriter.create<arith::OrIOp>(op.getLoc(), lo, hi);
+      value = arith::OrIOp::create(rewriter, op.getLoc(), lo, hi);
     }
 
     // i32 -> f32, etc
     if (llvm::isa<FloatType>(targetType)) {
-      value = rewriter.create<arith::BitcastOp>(op.getLoc(), targetType, value);
+      value =
+          arith::BitcastOp::create(rewriter, op.getLoc(), targetType, value);
     }
 
     rewriter.replaceOp(op, {value});
@@ -131,8 +135,8 @@
 
     // 32-bit values are stored directly, 64-bit are split into 32 | 32.
     if (validByteWidth <= 4) {
-      auto byteWidth = rewriter.create<arith::ConstantIntOp>(
-          op.getLoc(), validByteWidth, 32);
+      auto byteWidth = arith::ConstantIntOp::create(rewriter, op.getLoc(),
+                                                    validByteWidth, 32);
       auto callOp = rewriter.replaceOpWithNewOp<IREE::VM::CallOp>(
           op, SymbolRefAttr::get(importOp), importType.getResults(),
           ArrayRef<Value>{value, adaptor.getTargetBuffer(), targetOffset,
@@ -140,13 +144,14 @@
       copyImportAttrs(importOp, callOp);
     } else {
       auto halfByteWidth =
-          rewriter.create<arith::ConstantIntOp>(op.getLoc(), 4, 32);
+          arith::ConstantIntOp::create(rewriter, op.getLoc(), 4, 32);
 
       auto lo = rewriter.createOrFold<arith::TruncIOp>(
           op.getLoc(), rewriter.getI32Type(), value);
       auto loOffset = targetOffset;
-      auto loCallOp = rewriter.create<IREE::VM::CallOp>(
-          op.getLoc(), SymbolRefAttr::get(importOp), importType.getResults(),
+      auto loCallOp = IREE::VM::CallOp::create(
+          rewriter, op.getLoc(), SymbolRefAttr::get(importOp),
+          importType.getResults(),
           ArrayRef<Value>{lo, adaptor.getTargetBuffer(), loOffset,
                           halfByteWidth});
       copyImportAttrs(importOp, loCallOp);
@@ -155,10 +160,10 @@
           op.getLoc(), rewriter.getI32Type(),
           rewriter.createOrFold<arith::ShRUIOp>(
               op.getLoc(), value,
-              rewriter.create<arith::ConstantIntOp>(op.getLoc(), 32, 64)));
+              arith::ConstantIntOp::create(rewriter, op.getLoc(), 32, 64)));
       auto hiOffset = rewriter.createOrFold<arith::AddIOp>(
           op.getLoc(), targetOffset,
-          rewriter.create<IREE::VM::ConstI64Op>(op.getLoc(), 4));
+          IREE::VM::ConstI64Op::create(rewriter, op.getLoc(), 4));
       auto hiCallOp = rewriter.replaceOpWithNewOp<IREE::VM::CallOp>(
           op, SymbolRefAttr::get(importOp), importType.getResults(),
           ArrayRef<Value>{hi, adaptor.getTargetBuffer(), hiOffset,
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertCommandBufferOps.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertCommandBufferOps.cpp
index 7a28793..42f92ae 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertCommandBufferOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertCommandBufferOps.cpp
@@ -24,20 +24,20 @@
 splitBufferSlot(Location loc, Value bufferOrSlot, OpBuilder &builder) {
   if (!bufferOrSlot) {
     return std::make_tuple(
-        builder.create<IREE::VM::ConstI32ZeroOp>(loc),
-        builder.create<IREE::VM::ConstRefZeroOp>(
-            loc,
+        IREE::VM::ConstI32ZeroOp::create(builder, loc),
+        IREE::VM::ConstRefZeroOp::create(
+            builder, loc,
             IREE::VM::RefType::get(builder.getType<IREE::HAL::BufferType>())));
   } else if (isa<IREE::VM::RefType>(bufferOrSlot.getType())) {
     // Direct buffer binding; pass 0 for table slot.
-    return std::make_tuple(builder.create<IREE::VM::ConstI32ZeroOp>(loc),
+    return std::make_tuple(IREE::VM::ConstI32ZeroOp::create(builder, loc),
                            bufferOrSlot);
   } else {
     // Indirect binding table reference; pass null for the buffer.
     return std::make_tuple(
         castToImportType(bufferOrSlot, builder.getI32Type(), builder),
-        builder.create<IREE::VM::ConstRefZeroOp>(
-            loc,
+        IREE::VM::ConstRefZeroOp::create(
+            builder, loc,
             IREE::VM::RefType::get(builder.getType<IREE::HAL::BufferType>())));
   }
 }
@@ -83,7 +83,7 @@
                                               rewriter.getI32Type(), rewriter));
     } else {
       callOperands.push_back(
-          rewriter.create<IREE::VM::ConstI32ZeroOp>(op.getLoc()));
+          IREE::VM::ConstI32ZeroOp::create(rewriter, op.getLoc()));
     }
 
     auto callOp = rewriter.replaceOpWithNewOp<IREE::VM::CallOp>(
@@ -265,7 +265,7 @@
     Value zeroI64;
     auto getZeroI64 = [&]() {
       if (!zeroI64) {
-        zeroI64 = rewriter.create<IREE::VM::ConstI64ZeroOp>(op.getLoc());
+        zeroI64 = IREE::VM::ConstI64ZeroOp::create(rewriter, op.getLoc());
       }
       return zeroI64;
     };
@@ -286,13 +286,13 @@
     SmallVector<Value> callOperands;
     callOperands.push_back(adaptor.getCommandBuffer());
     callOperands.push_back(adaptor.getChannel());
-    callOperands.push_back(rewriter.create<IREE::VM::ConstI32Op>(
-        op.getLoc(), adaptor.getOp().getEncodedValue()));
+    callOperands.push_back(IREE::VM::ConstI32Op::create(
+        rewriter, op.getLoc(), adaptor.getOp().getEncodedValue()));
     if (auto paramValue = adaptor.getParam()) {
       callOperands.push_back(paramValue);
     } else {
       callOperands.push_back(
-          rewriter.create<IREE::VM::ConstI32ZeroOp>(op.getLoc()));
+          IREE::VM::ConstI32ZeroOp::create(rewriter, op.getLoc()));
     }
 
     auto [sendBufferSlot, sendBuffer] =
@@ -346,7 +346,7 @@
 
     auto i32Type = rewriter.getI32Type();
     auto i64Type = rewriter.getI64Type();
-    Value zeroI32 = rewriter.create<IREE::VM::ConstI32ZeroOp>(op.getLoc());
+    Value zeroI32 = IREE::VM::ConstI32ZeroOp::create(rewriter, op.getLoc());
 
     SmallVector<Value, 8> callOperands = {
         adaptor.getCommandBuffer(),
@@ -417,7 +417,7 @@
 
     auto i32Type = rewriter.getI32Type();
     auto i64Type = rewriter.getI64Type();
-    Value zeroI32 = rewriter.create<IREE::VM::ConstI32ZeroOp>(op.getLoc());
+    Value zeroI32 = IREE::VM::ConstI32ZeroOp::create(rewriter, op.getLoc());
 
     auto [workgroupsBufferSlot, workgroupsBuffer] =
         splitBufferSlot(op.getLoc(), adaptor.getWorkgroupsBuffer(), rewriter);
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertDeviceOps.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertDeviceOps.cpp
index d61044b..7d4c454 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertDeviceOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertDeviceOps.cpp
@@ -35,8 +35,8 @@
     // ourselves instead of allowing the i64 do the same. We could let it handle
     // things but then we are generating more IR that may prevent other
     // canonicalizations (a select of i1 to i1 is easier to handle).
-    auto queryOp = rewriter.create<IREE::HAL::DeviceQueryOp>(
-        op.getLoc(), rewriter.getI1Type(), rewriter.getI64Type(),
+    auto queryOp = IREE::HAL::DeviceQueryOp::create(
+        rewriter, op.getLoc(), rewriter.getI1Type(), rewriter.getI64Type(),
         adaptor.getDevice(), op.getCategoryAttr(), op.getKeyAttr(),
         TypedAttr{});
     auto ok = llvm::cast<Value>(queryOp.getOk());
@@ -46,21 +46,22 @@
     if (targetType.isIndex()) {
       // i64 -> index cast.
       value =
-          rewriter.create<arith::IndexCastOp>(op.getLoc(), targetType, value);
+          arith::IndexCastOp::create(rewriter, op.getLoc(), targetType, value);
     } else if (targetType.isInteger(1)) {
       // i64 -> i1 cast.
-      value = rewriter.create<IREE::VM::CmpNZI64Op>(
-          op.getLoc(), rewriter.getI32Type(), value);
+      value = IREE::VM::CmpNZI64Op::create(rewriter, op.getLoc(),
+                                           rewriter.getI32Type(), value);
     } else {
       // i64 -> {integer} cast.
       if (targetType.getIntOrFloatBitWidth() <
           value.getType().getIntOrFloatBitWidth()) {
         // i64 -> narrowing cast.
         value =
-            rewriter.create<arith::TruncIOp>(op.getLoc(), targetType, value);
+            arith::TruncIOp::create(rewriter, op.getLoc(), targetType, value);
       } else {
         // i64 -> widening cast.
-        value = rewriter.create<arith::ExtUIOp>(op.getLoc(), targetType, value);
+        value =
+            arith::ExtUIOp::create(rewriter, op.getLoc(), targetType, value);
       }
     }
 
@@ -68,11 +69,11 @@
       // Select the default value based on the converted type as that's the type
       // of the attribute we have is in. 'ok' result is set to true as we've
       // already handled the error case.
-      value = rewriter.create<arith::SelectOp>(
-          op.getLoc(), ok, value,
-          rewriter.create<arith::ConstantOp>(op.getLoc(),
-                                             op.getDefaultValueAttr()));
-      ok = rewriter.create<IREE::VM::ConstI32Op>(op.getLoc(), 1);
+      value = arith::SelectOp::create(
+          rewriter, op.getLoc(), ok, value,
+          arith::ConstantOp::create(rewriter, op.getLoc(),
+                                    op.getDefaultValueAttr()));
+      ok = IREE::VM::ConstI32Op::create(rewriter, op.getLoc(), 1);
     }
 
     rewriter.replaceOp(op, {ok, value});
@@ -132,8 +133,8 @@
                   ConversionPatternRewriter &rewriter) const override {
     auto importType = importOp.getFunctionType();
     auto i64Type = rewriter.getI64Type();
-    auto patternLength = rewriter.create<IREE::VM::ConstI32Op>(
-        op.getLoc(),
+    auto patternLength = IREE::VM::ConstI32Op::create(
+        rewriter, op.getLoc(),
         llvm::divideCeil(op.getPattern().getType().getIntOrFloatBitWidth(), 8));
     std::array<Value, 10> callOperands = {
         adaptor.getDevice(),
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertExecutableOps.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertExecutableOps.cpp
index bb0fe4f..bc8f3ce 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertExecutableOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/ConvertExecutableOps.cpp
@@ -35,7 +35,7 @@
   size_t constantCount = constantValues.size();
   if (constantValues.empty()) {
     // No constants; pass a null buffer.
-    return builder.create<IREE::VM::ConstRefZeroOp>(loc, bufferRefType);
+    return IREE::VM::ConstRefZeroOp::create(builder, loc, bufferRefType);
   }
 
   // Create the constant storage buffer.
@@ -45,11 +45,11 @@
     constantLocs.push_back(constantValue.getLoc());
   }
   auto constantBufferLoc = builder.getFusedLoc(constantLocs);
-  auto constantBuffer = builder.create<IREE::VM::BufferAllocOp>(
-      constantBufferLoc, bufferRefType,
-      builder.create<IREE::VM::ConstI64Op>(constantBufferLoc,
-                                           constantCount * sizeof(uint32_t)),
-      builder.create<IREE::VM::ConstI32Op>(constantBufferLoc, 16));
+  auto constantBuffer = IREE::VM::BufferAllocOp::create(
+      builder, constantBufferLoc, bufferRefType,
+      IREE::VM::ConstI64Op::create(builder, constantBufferLoc,
+                                   constantCount * sizeof(uint32_t)),
+      IREE::VM::ConstI32Op::create(builder, constantBufferLoc, 16));
 
   // Store each constant into it.
   // TODO(#8477): better ops for this pattern; this creates a lot of
@@ -59,10 +59,10 @@
     if (mlir::matchPattern(constantValue.value(), m_Zero()))
       continue;
     auto constantLoc = constantValue.value().getLoc();
-    builder.create<IREE::VM::BufferStoreI32Op>(
-        constantLoc, constantBuffer,
-        builder.create<IREE::VM::ConstI64Op>(constantLoc,
-                                             constantValue.index()),
+    IREE::VM::BufferStoreI32Op::create(
+        builder, constantLoc, constantBuffer,
+        IREE::VM::ConstI64Op::create(builder, constantLoc,
+                                     constantValue.index()),
         constantValue.value());
   }
 
@@ -106,15 +106,15 @@
                             ->getParentOfType<IREE::HAL::ExecutableOp>();
     std::string rodataName = sanitizeSymbolName(
         (executableOp.getName() + "_" + executableBinaryOp.getName()).str());
-    auto rodataOp = rewriter.create<IREE::VM::RodataInlineOp>(
-        executableBinaryOp.getLoc(),
+    auto rodataOp = IREE::VM::RodataInlineOp::create(
+        rewriter, executableBinaryOp.getLoc(),
         IREE::VM::RefType::get(rewriter.getType<IREE::VM::BufferType>()),
         rewriter.getStringAttr(rodataName), executableBinaryOp.getData(),
         rewriter.getI64IntegerAttr(16), executableBinaryOp.getMimeTypeAttr());
 
     // Get format string as a rodata blob.
-    auto executableFormatStr = rewriter.create<IREE::VM::RodataInlineOp>(
-        createOp.getLoc(), executableBinaryOp.getFormatAttr());
+    auto executableFormatStr = IREE::VM::RodataInlineOp::create(
+        rewriter, createOp.getLoc(), executableBinaryOp.getFormatAttr());
 
     // Pack constants, if any.
     auto constantBuffer = createPackedConstantBuffer(
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/Patterns.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/Patterns.cpp
index a4119a5..9f134e0 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/HALToVM/Patterns.cpp
@@ -12,9 +12,9 @@
 
 Value getFlagsI64(Location loc, IntegerAttr flagsAttr, OpBuilder &builder) {
   return flagsAttr
-             ? builder.create<IREE::VM::ConstI64Op>(loc, flagsAttr.getInt())
+             ? IREE::VM::ConstI64Op::create(builder, loc, flagsAttr.getInt())
                    .getResult()
-             : builder.create<IREE::VM::ConstI64ZeroOp>(loc).getResult();
+             : IREE::VM::ConstI64ZeroOp::create(builder, loc).getResult();
 }
 
 extern void populateHALAllocatorToVMPatterns(MLIRContext *context,
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 d70d59f..32a7145 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/Patterns.cpp
@@ -99,11 +99,10 @@
     auto resourceType =
         cast<IREE::Stream::ResourceType>(allocOp.getResult().getType());
 
-    auto resolveOp =
-        rewriter.create<IREE::HAL::AllocatorResolveMemoryPropertiesOp>(
-            allocOp.getLoc(), rewriter.getI32Type(), rewriter.getI32Type(),
-            allocOp.getAffinity().value_or(nullptr),
-            static_cast<IREE::HAL::Lifetime>(resourceType.getLifetime()));
+    auto resolveOp = IREE::HAL::AllocatorResolveMemoryPropertiesOp::create(
+        rewriter, allocOp.getLoc(), rewriter.getI32Type(),
+        rewriter.getI32Type(), allocOp.getAffinity().value_or(nullptr),
+        static_cast<IREE::HAL::Lifetime>(resourceType.getLifetime()));
 
     // Lookup the appropriate allocator/queue for allocation based on the buffer
     // propreties.
@@ -134,11 +133,10 @@
 
     // Lookup the appropriate device/queue for allocation based on the buffer
     // propreties.
-    auto resolveOp =
-        rewriter.create<IREE::HAL::AllocatorResolveMemoryPropertiesOp>(
-            loc, rewriter.getI32Type(), rewriter.getI32Type(),
-            allocaOp.getAffinity().value_or(nullptr),
-            static_cast<IREE::HAL::Lifetime>(resourceType.getLifetime()));
+    auto resolveOp = IREE::HAL::AllocatorResolveMemoryPropertiesOp::create(
+        rewriter, loc, rewriter.getI32Type(), rewriter.getI32Type(),
+        allocaOp.getAffinity().value_or(nullptr),
+        static_cast<IREE::HAL::Lifetime>(resourceType.getLifetime()));
 
     auto [device, queueAffinity] =
         lookupDeviceAndQueueAffinityFor(allocaOp, resolveOp.getMemoryTypes(),
@@ -157,11 +155,11 @@
         loc, device, allocaOp.getResultTimepoint(), rewriter);
 
     // Queue allocation.
-    auto pool = rewriter.create<arith::ConstantIntOp>(loc, 0, 64);
-    auto allocateOp = rewriter.create<IREE::HAL::DeviceQueueAllocaOp>(
-        loc, bufferType, device, queueAffinity, waitFence, signalFence, pool,
-        resolveOp.getMemoryTypes(), resolveOp.getBufferUsage(),
-        adaptor.getStorageSize(), flags);
+    auto pool = arith::ConstantIntOp::create(rewriter, loc, 0, 64);
+    auto allocateOp = IREE::HAL::DeviceQueueAllocaOp::create(
+        rewriter, loc, bufferType, device, queueAffinity, waitFence,
+        signalFence, pool, resolveOp.getMemoryTypes(),
+        resolveOp.getBufferUsage(), adaptor.getStorageSize(), flags);
 
     rewriter.replaceOp(allocaOp, {allocateOp.getResult(), signalFence});
     return success();
@@ -183,11 +181,10 @@
     auto resourceType =
         cast<IREE::Stream::ResourceType>(deallocaOp.getOperand().getType());
 
-    auto resolveOp =
-        rewriter.create<IREE::HAL::AllocatorResolveMemoryPropertiesOp>(
-            loc, rewriter.getI32Type(), rewriter.getI32Type(),
-            deallocaOp.getAffinity().value_or(nullptr),
-            static_cast<IREE::HAL::Lifetime>(resourceType.getLifetime()));
+    auto resolveOp = IREE::HAL::AllocatorResolveMemoryPropertiesOp::create(
+        rewriter, loc, rewriter.getI32Type(), rewriter.getI32Type(),
+        deallocaOp.getAffinity().value_or(nullptr),
+        static_cast<IREE::HAL::Lifetime>(resourceType.getLifetime()));
 
     auto [device, queueAffinity] =
         lookupDeviceAndQueueAffinityFor(deallocaOp, resolveOp.getMemoryTypes(),
@@ -208,8 +205,8 @@
     }
 
     // Queue deallocation.
-    rewriter.create<IREE::HAL::DeviceQueueDeallocaOp>(
-        loc, device, queueAffinity, waitFence, signalFence,
+    IREE::HAL::DeviceQueueDeallocaOp::create(
+        rewriter, loc, device, queueAffinity, waitFence, signalFence,
         adaptor.getOperand(), flags);
 
     rewriter.replaceOp(deallocaOp, {signalFence});
@@ -309,10 +306,10 @@
       break;
     }
 
-    Value bufferUsageOp = rewriter.create<IREE::HAL::BufferUsageOp>(
-        tryMapOp.getLoc(), bufferUsage);
-    Value memoryTypeOp = rewriter.create<IREE::HAL::MemoryTypeOp>(
-        tryMapOp.getLoc(), memoryTypes);
+    Value bufferUsageOp = IREE::HAL::BufferUsageOp::create(
+        rewriter, tryMapOp.getLoc(), bufferUsage);
+    Value memoryTypeOp = IREE::HAL::MemoryTypeOp::create(
+        rewriter, tryMapOp.getLoc(), memoryTypes);
     // Lookup the appropriate allocator/queue for allocation based on the buffer
     // propreties.
     auto [allocator, queueAffinity] = lookupAllocatorAndQueueAffinityFor(
@@ -382,7 +379,7 @@
         queueAffinity, IREE::HAL::MemoryAccessBitfield::Read,
         constantOp.getSource(), constantOp.getSourceOffset(),
         constantOp.getSourceLength(),
-        rewriter.create<arith::ConstantIntOp>(constantOp.getLoc(), 0, 32));
+        arith::ConstantIntOp::create(rewriter, constantOp.getLoc(), 0, 32));
     return success();
   }
 };
@@ -404,9 +401,9 @@
         loc, device, readOp.getResultTimepoint(), rewriter);
 
     // Queue read.
-    rewriter.create<IREE::HAL::DeviceQueueReadOp>(
-        loc, device, queueAffinity, waitFence, signalFence, adaptor.getSource(),
-        adaptor.getSourceOffset(), adaptor.getTarget(),
+    IREE::HAL::DeviceQueueReadOp::create(
+        rewriter, loc, device, queueAffinity, waitFence, signalFence,
+        adaptor.getSource(), adaptor.getSourceOffset(), adaptor.getTarget(),
         adaptor.getTargetOffset(), adaptor.getLength(),
         rewriter.getAttr<IREE::HAL::ReadFlagBitfieldAttr>(
             IREE::HAL::ReadFlagBitfield::None));
@@ -433,9 +430,9 @@
         loc, device, writeOp.getResultTimepoint(), rewriter);
 
     // Queue write.
-    rewriter.create<IREE::HAL::DeviceQueueWriteOp>(
-        loc, device, queueAffinity, waitFence, signalFence, adaptor.getSource(),
-        adaptor.getSourceOffset(), adaptor.getTarget(),
+    IREE::HAL::DeviceQueueWriteOp::create(
+        rewriter, loc, device, queueAffinity, waitFence, signalFence,
+        adaptor.getSource(), adaptor.getSourceOffset(), adaptor.getTarget(),
         adaptor.getTargetOffset(), adaptor.getLength(),
         rewriter.getAttr<IREE::HAL::WriteFlagBitfieldAttr>(
             IREE::HAL::WriteFlagBitfield::None));
@@ -468,9 +465,9 @@
   auto requiredUsage = IREE::HAL::BufferUsageBitfieldAttr::get(
       builder.getContext(), bufferUsage);
 
-  builder.create<IREE::HAL::BufferAssertOp>(loc, buffer, message, allocator,
-                                            minimumLength, requiredTypes,
-                                            requiredUsage);
+  IREE::HAL::BufferAssertOp::create(builder, loc, buffer, message, allocator,
+                                    minimumLength, requiredTypes,
+                                    requiredUsage);
   return success();
 }
 
@@ -573,10 +570,10 @@
 
     // NOTE: we should have verified supported encodings/types at entry into the
     // HAL pipeline.
-    auto encodingType = rewriter.create<IREE::HAL::EncodingTypeOp>(
-        loc, tensorType.getEncoding());
-    auto elementType = rewriter.create<IREE::HAL::ElementTypeOp>(
-        loc, tensorType.getElementType());
+    auto encodingType = IREE::HAL::EncodingTypeOp::create(
+        rewriter, loc, tensorType.getEncoding());
+    auto elementType = IREE::HAL::ElementTypeOp::create(
+        rewriter, loc, tensorType.getElementType());
 
     // Flatten static + dynamic shape dimensions.
     SmallVector<Value> dims;
@@ -585,14 +582,14 @@
       if (tensorType.isDynamicDim(idx)) {
         dims.push_back(dynamicDims[dynamicIdx++]);
       } else {
-        dims.push_back(rewriter.create<arith::ConstantIndexOp>(
-            loc, tensorType.getDimSize(idx)));
+        dims.push_back(arith::ConstantIndexOp::create(
+            rewriter, loc, tensorType.getDimSize(idx)));
       }
     }
 
     rewriter.replaceOpWithNewOp<IREE::HAL::BufferViewCreateOp>(
         exportOp, adaptor.getSource(),
-        rewriter.create<arith::ConstantIndexOp>(loc, 0),
+        arith::ConstantIndexOp::create(rewriter, loc, 0),
         adaptor.getSourceSize(), elementType, encodingType, dims);
     return success();
   }
@@ -611,10 +608,11 @@
              adaptor.getResourceEncodings().getAsRange<TypeAttr>())) {
       int64_t dynamicDimCount =
           cast<ShapedType>(resourceEncoding.getValue()).getNumDynamicDims();
-      bufferViews.push_back(rewriter.create<IREE::Stream::TensorExportOp>(
-          traceOp.getLoc(), rewriter.getType<IREE::HAL::BufferViewType>(),
-          resource, resourceEncoding,
-          resourceEncodingDims.take_front(dynamicDimCount), resourceSize,
+      bufferViews.push_back(IREE::Stream::TensorExportOp::create(
+          rewriter, traceOp.getLoc(),
+          rewriter.getType<IREE::HAL::BufferViewType>(), resource,
+          resourceEncoding, resourceEncodingDims.take_front(dynamicDimCount),
+          resourceSize,
           /*affinity=*/IREE::Stream::AffinityAttr{}));
       resourceEncodingDims = resourceEncodingDims.drop_front(dynamicDimCount);
     }
@@ -784,8 +782,8 @@
     // Get the device handle we're executing against in this execution region.
     // Note that this is a dynamic value: we have to treat the device as unknown
     // here.
-    Value device = rewriter.create<IREE::HAL::CommandBufferDeviceOp>(
-        loc, rewriter.getType<IREE::HAL::DeviceType>(),
+    Value device = IREE::HAL::CommandBufferDeviceOp::create(
+        rewriter, loc, rewriter.getType<IREE::HAL::DeviceType>(),
         commandBufferMapping.getHandle());
 
     // Prepare for variant switch table by gathering the conditions selecting
@@ -826,8 +824,9 @@
           rewriter);
 
       // Allow each variant to define how it is dispatched.
-      auto switchOp = rewriter.create<scf::IndexSwitchOp>(
-          loc, TypeRange{}, selectedIndex, caseIndices, caseIndices.size());
+      auto switchOp =
+          scf::IndexSwitchOp::create(rewriter, loc, TypeRange{}, selectedIndex,
+                                     caseIndices, caseIndices.size());
       for (size_t i = 0; i < caseExportOps.size(); ++i) {
         auto [entryPointAttr, exportOp] = caseExportOps[i];
         auto &caseBlock = switchOp.getCaseRegions()[i].emplaceBlock();
@@ -835,14 +834,14 @@
         emitDispatchOp(loc, affinityAttr, device, commandBufferMapping,
                        exportOp, entryPointAttr, dispatchOp, adaptor,
                        caseBuilder);
-        caseBuilder.create<scf::YieldOp>(loc);
+        scf::YieldOp::create(caseBuilder, loc);
       }
 
       // Fallback for no available variant. Today we just no-op as executable
       // loading should have already failed.
       auto &defaultBlock = switchOp.getDefaultRegion().emplaceBlock();
       auto defaultBuilder = OpBuilder::atBlockBegin(&defaultBlock);
-      defaultBuilder.create<scf::YieldOp>(loc);
+      scf::YieldOp::create(defaultBuilder, loc);
 
       rewriter.replaceOp(dispatchOp, switchOp);
     }
@@ -890,8 +889,8 @@
                Value device, ValueRange workload, OpBuilder &builder) const {
     if (!baseExportOp.getConditionBody()) {
       // No fallback - fast path to just the base export.
-      Value ordinal = builder.create<IREE::HAL::ExecutableExportOrdinalOp>(
-          loc, builder.getIndexType(), getExportRef(baseExportOp));
+      Value ordinal = IREE::HAL::ExecutableExportOrdinalOp::create(
+          builder, loc, builder.getIndexType(), getExportRef(baseExportOp));
       auto workgroupCount =
           baseExportOp.calculateWorkgroupCount(loc, device, workload, builder);
       return {ordinal, workgroupCount};
@@ -916,23 +915,24 @@
     // ordinal (condition matches) and the else region will contain the rest of
     // the decision tree.
     Type indexType = builder.getIndexType();
-    auto ifOp = builder.create<scf::IfOp>(
-        loc, TypeRange{indexType, indexType, indexType, indexType},
+    auto ifOp = scf::IfOp::create(
+        builder, loc, TypeRange{indexType, indexType, indexType, indexType},
         tryCondition,
         /*addThenBlock=*/true, /*addElseBlock=*/true);
     {
       auto thenBuilder = ifOp.getThenBodyBuilder();
-      Value tryOrdinal =
-          thenBuilder.create<IREE::HAL::ExecutableExportOrdinalOp>(
-              loc, thenBuilder.getIndexType(), getExportRef(tryExportOp));
+      Value tryOrdinal = IREE::HAL::ExecutableExportOrdinalOp::create(
+          thenBuilder, loc, thenBuilder.getIndexType(),
+          getExportRef(tryExportOp));
       auto tryWorkgroupCount = tryExportOp.calculateWorkgroupCount(
           loc, device, workload, thenBuilder);
-      thenBuilder.create<scf::YieldOp>(loc, ValueRange{
-                                                tryOrdinal,
-                                                tryWorkgroupCount[0],
-                                                tryWorkgroupCount[1],
-                                                tryWorkgroupCount[2],
-                                            });
+      scf::YieldOp::create(thenBuilder, loc,
+                           ValueRange{
+                               tryOrdinal,
+                               tryWorkgroupCount[0],
+                               tryWorkgroupCount[1],
+                               tryWorkgroupCount[2],
+                           });
     }
     {
       auto elseBuilder = ifOp.getElseBodyBuilder();
@@ -944,25 +944,26 @@
         auto [chainOrdinal, chainWorkgroupCount] =
             buildExportSelection(loc, fallbackExportOp, chainExportOp, device,
                                  workload, elseBuilder);
-        elseBuilder.create<scf::YieldOp>(loc, ValueRange{
-                                                  chainOrdinal,
-                                                  chainWorkgroupCount[0],
-                                                  chainWorkgroupCount[1],
-                                                  chainWorkgroupCount[2],
-                                              });
+        scf::YieldOp::create(elseBuilder, loc,
+                             ValueRange{
+                                 chainOrdinal,
+                                 chainWorkgroupCount[0],
+                                 chainWorkgroupCount[1],
+                                 chainWorkgroupCount[2],
+                             });
       } else {
         // Tail of recursion; fallback has no fallback.
-        Value fallbackOrdinal =
-            elseBuilder.create<IREE::HAL::ExecutableExportOrdinalOp>(
-                loc, indexType, getExportRef(fallbackExportOp));
+        Value fallbackOrdinal = IREE::HAL::ExecutableExportOrdinalOp::create(
+            elseBuilder, loc, indexType, getExportRef(fallbackExportOp));
         auto fallbackWorkgroupCount = fallbackExportOp.calculateWorkgroupCount(
             loc, device, workload, elseBuilder);
-        elseBuilder.create<scf::YieldOp>(loc, ValueRange{
-                                                  fallbackOrdinal,
-                                                  fallbackWorkgroupCount[0],
-                                                  fallbackWorkgroupCount[1],
-                                                  fallbackWorkgroupCount[2],
-                                              });
+        scf::YieldOp::create(elseBuilder, loc,
+                             ValueRange{
+                                 fallbackOrdinal,
+                                 fallbackWorkgroupCount[0],
+                                 fallbackWorkgroupCount[1],
+                                 fallbackWorkgroupCount[2],
+                             });
       }
     }
     return {ifOp.getResult(0),
@@ -979,8 +980,8 @@
       IREE::HAL::ExecutableExportOp exportOp, SymbolRefAttr entryPointAttr,
       IREE::Stream::CmdDispatchOp dispatchOp, OpAdaptor adaptor,
       OpBuilder &builder) const {
-    Value executable = builder.create<IREE::HAL::ExecutableLookupOp>(
-        loc, builder.getType<IREE::HAL::ExecutableType>(), device,
+    Value executable = IREE::HAL::ExecutableLookupOp::create(
+        builder, loc, builder.getType<IREE::HAL::ExecutableType>(), device,
         entryPointAttr.getRootReference().getValue());
 
     // Select the export and calculate its workgroup count.
@@ -1016,8 +1017,8 @@
 
     auto flags = IREE::HAL::DispatchFlags::None;
 
-    return builder.create<IREE::HAL::CommandBufferDispatchOp>(
-        loc, commandBufferMapping.getHandle(), executable, ordinal,
+    return IREE::HAL::CommandBufferDispatchOp::create(
+        builder, loc, commandBufferMapping.getHandle(), executable, ordinal,
         workgroupCount, adaptor.getUniformOperands(), bindings, flags);
   }
 };
@@ -1084,15 +1085,17 @@
     Value zeroIndex;
     auto getZeroIndex = [&]() {
       if (!zeroIndex) {
-        zeroIndex = rewriter.create<arith::ConstantIndexOp>(callOp.getLoc(), 0);
+        zeroIndex =
+            arith::ConstantIndexOp::create(rewriter, callOp.getLoc(), 0);
       }
       return zeroIndex;
     };
     Value nullBuffer;
     auto getNullBuffer = [&]() {
       if (!nullBuffer) {
-        nullBuffer = rewriter.create<IREE::Util::NullOp>(
-            callOp.getLoc(), rewriter.getType<IREE::HAL::BufferType>());
+        nullBuffer = IREE::Util::NullOp::create(
+            rewriter, callOp.getLoc(),
+            rewriter.getType<IREE::HAL::BufferType>());
       }
       return nullBuffer;
     };
@@ -1205,8 +1208,8 @@
     if (op->hasTrait<OpTrait::IsTerminator>())
       continue;
     builder.setInsertionPointAfter(op);
-    builder.create<IREE::HAL::CommandBufferExecutionBarrierOp>(
-        loc, commandBuffer, sourceStage, targetStage, flags);
+    IREE::HAL::CommandBufferExecutionBarrierOp::create(
+        builder, loc, commandBuffer, sourceStage, targetStage, flags);
   }
 }
 
@@ -1287,8 +1290,8 @@
       if (auto fillOp = dyn_cast<IREE::Stream::CmdFillOp>(*singleTransferOp)) {
         auto fillTargetBuffer = rewriter.getRemappedValue(
             executeOp.getClosureCapturedValue(fillOp.getTarget()));
-        rewriter.create<IREE::HAL::DeviceQueueFillOp>(
-            loc, device, queueAffinity, waitFence, signalFence,
+        IREE::HAL::DeviceQueueFillOp::create(
+            rewriter, loc, device, queueAffinity, waitFence, signalFence,
             fillTargetBuffer, fillOp.getTargetOffset(),
             fillOp.getTargetLength(), fillOp.getValue(),
             IREE::HAL::FillFlagBitfield::None);
@@ -1298,8 +1301,8 @@
             executeOp.getClosureCapturedValue(copyOp.getSource()));
         auto copyTargetBuffer = rewriter.getRemappedValue(
             executeOp.getClosureCapturedValue(copyOp.getTarget()));
-        rewriter.create<IREE::HAL::DeviceQueueCopyOp>(
-            loc, device, queueAffinity, waitFence, signalFence,
+        IREE::HAL::DeviceQueueCopyOp::create(
+            rewriter, loc, device, queueAffinity, waitFence, signalFence,
             copySourceBuffer, copyOp.getSourceOffset(), copyTargetBuffer,
             copyOp.getTargetOffset(), copyOp.getLength(),
             IREE::HAL::CopyFlagBitfield::None);
@@ -1360,11 +1363,12 @@
       // Create a new command buffer for recording.
       Value bindingTableCapacity =
           bindingTable.empty() ? Value{}
-                               : rewriter.create<arith::ConstantIndexOp>(
-                                     loc, bindingTable.size());
-      Value commandBuffer = rewriter.create<IREE::HAL::CommandBufferCreateOp>(
-          loc, rewriter.getType<IREE::HAL::CommandBufferType>(), device, modes,
-          commandCategories, queueAffinity, bindingTableCapacity);
+                               : arith::ConstantIndexOp::create(
+                                     rewriter, loc, bindingTable.size());
+      Value commandBuffer = IREE::HAL::CommandBufferCreateOp::create(
+          rewriter, loc, rewriter.getType<IREE::HAL::CommandBufferType>(),
+          device, modes, commandCategories, queueAffinity,
+          bindingTableCapacity);
       mapping->mapCommandBuffer(executeOp, commandBuffer,
                                 std::move(bindingTable));
 
@@ -1375,8 +1379,8 @@
                                   OpBuilder::atBlockBegin(&bodyBlock));
 
       // Begin/end recording and inline the execution region between them.
-      auto endOp = rewriter.create<IREE::HAL::CommandBufferFinalizeOp>(
-          loc, commandBuffer);
+      auto endOp = IREE::HAL::CommandBufferFinalizeOp::create(rewriter, loc,
+                                                              commandBuffer);
       rewriter.inlineBlockBefore(&executeOp.getBody().front(), endOp,
                                  adaptor.getResourceOperands());
 
@@ -1390,13 +1394,13 @@
     Value commandBuffer;
     if (!bitEnumContainsAll(modes,
                             IREE::HAL::CommandBufferModeBitfield::OneShot)) {
-      auto memoizeOp = rewriter.create<IREE::HAL::DeviceMemoizeOp>(
-          loc, rewriter.getType<IREE::HAL::CommandBufferType>(), device,
-          queueAffinity);
+      auto memoizeOp = IREE::HAL::DeviceMemoizeOp::create(
+          rewriter, loc, rewriter.getType<IREE::HAL::CommandBufferType>(),
+          device, queueAffinity);
       auto ip = rewriter.saveInsertionPoint();
       rewriter.setInsertionPointToStart(&memoizeOp.getBody().emplaceBlock());
-      rewriter.create<IREE::HAL::ReturnOp>(
-          loc, recordCommandBuffer(device, queueAffinity, rewriter));
+      IREE::HAL::ReturnOp::create(
+          rewriter, loc, recordCommandBuffer(device, queueAffinity, rewriter));
       rewriter.restoreInsertionPoint(ip);
       commandBuffer = memoizeOp.getResult(0);
     } else {
@@ -1412,13 +1416,13 @@
     // Queue execution.
     IREE::HAL::ExecuteFlagBitfield flags = IREE::HAL::ExecuteFlagBitfield::None;
     if (bindingTableValues.empty()) {
-      rewriter.create<IREE::HAL::DeviceQueueExecuteOp>(
-          loc, device, queueAffinity, waitFence, signalFence, commandBuffer,
-          flags);
+      IREE::HAL::DeviceQueueExecuteOp::create(
+          rewriter, loc, device, queueAffinity, waitFence, signalFence,
+          commandBuffer, flags);
     } else {
-      rewriter.create<IREE::HAL::DeviceQueueExecuteIndirectOp>(
-          loc, device, queueAffinity, waitFence, signalFence, commandBuffer,
-          bindingTableValues, flags);
+      IREE::HAL::DeviceQueueExecuteIndirectOp::create(
+          rewriter, loc, device, queueAffinity, waitFence, signalFence,
+          commandBuffer, bindingTableValues, flags);
     }
 
     rewriter.replaceOp(executeOp, signalFence);
@@ -1559,8 +1563,8 @@
     // NOTE: this assumes that if this op still exists the input resource is
     // already available. If it isn't then timepoint propagation should have
     // replaced the signal op with the producing timepoint.
-    Value nullFence = rewriter.create<IREE::Util::NullOp>(
-        barrierOp.getLoc(), rewriter.getType<IREE::HAL::FenceType>());
+    Value nullFence = IREE::Util::NullOp::create(
+        rewriter, barrierOp.getLoc(), rewriter.getType<IREE::HAL::FenceType>());
     rewriter.replaceOp(barrierOp, {adaptor.getResource(), nullFence});
     return success();
   }
@@ -1575,12 +1579,12 @@
     auto loc = awaitOp.getLoc();
 
     // Perform the blocking wait.
-    Value timeoutMillis = rewriter.create<arith::ConstantIntOp>(loc, -1, 32);
-    auto fenceOp = rewriter.create<IREE::HAL::FenceAwaitOp>(
-        loc, rewriter.getI32Type(), timeoutMillis,
+    Value timeoutMillis = arith::ConstantIntOp::create(rewriter, loc, -1, 32);
+    auto fenceOp = IREE::HAL::FenceAwaitOp::create(
+        rewriter, loc, rewriter.getI32Type(), timeoutMillis,
         IREE::HAL::WaitFlagBitfield::None, adaptor.getAwaitTimepoint());
-    rewriter.create<IREE::Util::StatusCheckOkOp>(loc, fenceOp.getStatus(),
-                                                 "failed to wait on timepoint");
+    IREE::Util::StatusCheckOkOp::create(rewriter, loc, fenceOp.getStatus(),
+                                        "failed to wait on timepoint");
 
     // Pass along operands.
     rewriter.replaceOp(awaitOp, adaptor.getResourceOperands());
@@ -1600,14 +1604,15 @@
     auto getDefault = [&]() {
       if (!neg1I32) {
         neg1I32 =
-            rewriter.create<arith::ConstantIntOp>(createOp.getLoc(), -1, 32);
+            arith::ConstantIntOp::create(rewriter, createOp.getLoc(), -1, 32);
       }
       return neg1I32;
     };
     Value id = adaptor.getId();
     if (!id) {
-      id = rewriter.create<IREE::Util::NullOp>(
-          createOp.getLoc(), rewriter.getType<IREE::Util::BufferType>());
+      id = IREE::Util::NullOp::create(
+          rewriter, createOp.getLoc(),
+          rewriter.getType<IREE::Util::BufferType>());
     }
     Value group =
         adaptor.getGroupAttr()
@@ -1622,16 +1627,16 @@
                       createOp.getLoc(),
                       rewriter.getType<IREE::Util::BufferType>())
                   .getResult();
-    Value rank =
-        adaptor.getRank()
-            ? rewriter.create<arith::IndexCastOp>(
-                  createOp.getLoc(), rewriter.getI32Type(), adaptor.getRank())
-            : getDefault();
-    Value count =
-        adaptor.getRank()
-            ? rewriter.create<arith::IndexCastOp>(
-                  createOp.getLoc(), rewriter.getI32Type(), adaptor.getCount())
-            : getDefault();
+    Value rank = adaptor.getRank()
+                     ? arith::IndexCastOp::create(rewriter, createOp.getLoc(),
+                                                  rewriter.getI32Type(),
+                                                  adaptor.getRank())
+                     : getDefault();
+    Value count = adaptor.getRank()
+                      ? arith::IndexCastOp::create(rewriter, createOp.getLoc(),
+                                                   rewriter.getI32Type(),
+                                                   adaptor.getCount())
+                      : getDefault();
     rewriter.replaceOpWithNewOp<IREE::HAL::ChannelCreateOp>(
         createOp, rewriter.getType<IREE::HAL::ChannelType>(), device,
         queueAffinity, IREE::HAL::ChannelFlagBitfield::None, id, group, rank,
@@ -1646,10 +1651,10 @@
   LogicalResult
   matchAndRewrite(IREE::Stream::ChannelSplitOp splitOp, OpAdaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
-    Value color = rewriter.create<arith::IndexCastOp>(
-        splitOp.getLoc(), rewriter.getI32Type(), adaptor.getColor());
-    Value key = rewriter.create<arith::IndexCastOp>(
-        splitOp.getLoc(), rewriter.getI32Type(), adaptor.getKey());
+    Value color = arith::IndexCastOp::create(
+        rewriter, splitOp.getLoc(), rewriter.getI32Type(), adaptor.getColor());
+    Value key = arith::IndexCastOp::create(
+        rewriter, splitOp.getLoc(), rewriter.getI32Type(), adaptor.getKey());
     rewriter.replaceOpWithNewOp<IREE::HAL::ChannelSplitOp>(
         splitOp, rewriter.getType<IREE::HAL::ChannelType>(),
         adaptor.getChannel(), color, key, IREE::HAL::ChannelFlagBitfield::None);
@@ -1663,11 +1668,11 @@
   LogicalResult
   matchAndRewrite(IREE::Stream::ChannelRankOp rankOp, OpAdaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
-    auto newOp = rewriter.create<IREE::HAL::ChannelRankAndCountOp>(
-        rankOp.getLoc(), rewriter.getI32Type(), rewriter.getI32Type(),
+    auto newOp = IREE::HAL::ChannelRankAndCountOp::create(
+        rewriter, rankOp.getLoc(), rewriter.getI32Type(), rewriter.getI32Type(),
         adaptor.getChannel());
-    Value indexRank = rewriter.create<arith::IndexCastOp>(
-        rankOp.getLoc(), rewriter.getIndexType(), newOp.getRank());
+    Value indexRank = arith::IndexCastOp::create(
+        rewriter, rankOp.getLoc(), rewriter.getIndexType(), newOp.getRank());
     rewriter.replaceOp(rankOp, indexRank);
     return success();
   }
@@ -1679,11 +1684,11 @@
   LogicalResult
   matchAndRewrite(IREE::Stream::ChannelCountOp countOp, OpAdaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
-    auto newOp = rewriter.create<IREE::HAL::ChannelRankAndCountOp>(
-        countOp.getLoc(), rewriter.getI32Type(), rewriter.getI32Type(),
-        adaptor.getChannel());
-    Value indexCount = rewriter.create<arith::IndexCastOp>(
-        countOp.getLoc(), rewriter.getIndexType(), newOp.getCount());
+    auto newOp = IREE::HAL::ChannelRankAndCountOp::create(
+        rewriter, countOp.getLoc(), rewriter.getI32Type(),
+        rewriter.getI32Type(), adaptor.getChannel());
+    Value indexCount = arith::IndexCastOp::create(
+        rewriter, countOp.getLoc(), rewriter.getIndexType(), newOp.getCount());
     rewriter.replaceOp(countOp, indexCount);
     return success();
   }
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/Utils.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/Utils.cpp
index 878ec23..76e4887 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/Utils.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/StreamToHAL/Utils.cpp
@@ -13,8 +13,8 @@
 
 Value lookupDeviceFor(Operation *op, OpBuilder &builder) {
   auto affinityAttr = IREE::Stream::AffinityAttr::lookupOrDefault(op);
-  auto resolveOp = builder.create<IREE::Stream::ContextResolveOp>(
-      op->getLoc(),
+  auto resolveOp = IREE::Stream::ContextResolveOp::create(
+      builder, op->getLoc(),
       TypeRange{
           builder.getType<IREE::HAL::DeviceType>(),
       },
@@ -24,8 +24,8 @@
 
 static std::tuple<Value, Value> lookupDeviceAndQueueAffinityFor(
     Location loc, IREE::Stream::AffinityAttr affinityAttr, OpBuilder &builder) {
-  auto resolveOp = builder.create<IREE::Stream::ContextResolveOp>(
-      loc,
+  auto resolveOp = IREE::Stream::ContextResolveOp::create(
+      builder, loc,
       TypeRange{
           builder.getType<IREE::HAL::DeviceType>(),
           builder.getI64Type(),
@@ -74,15 +74,16 @@
   }
   // Emit a select op to let the runtime decide which device/queue affinity to
   // use, if required.
-  auto selectOp = builder.create<IREE::HAL::AllocatorSelectOp>(
-      op->getLoc(), devices, queueAffinities, memoryTypes, bufferUsage);
+  auto selectOp = IREE::HAL::AllocatorSelectOp::create(
+      builder, op->getLoc(), devices, queueAffinities, memoryTypes,
+      bufferUsage);
   return {selectOp.getResult(0), selectOp.getResult(1)};
 }
 
 Value lookupAllocatorFor(Operation *op, OpBuilder &builder) {
   auto affinityAttr = IREE::Stream::AffinityAttr::lookupOrDefault(op);
-  auto resolveOp = builder.create<IREE::Stream::ContextResolveOp>(
-      op->getLoc(),
+  auto resolveOp = IREE::Stream::ContextResolveOp::create(
+      builder, op->getLoc(),
       TypeRange{
           builder.getType<IREE::HAL::AllocatorType>(),
       },
@@ -96,7 +97,7 @@
   auto [device, queueAffinity] =
       lookupDeviceAndQueueAffinityFor(op, memoryTypes, bufferUsage, builder);
   Value allocator =
-      builder.create<IREE::HAL::DeviceAllocatorOp>(op->getLoc(), device);
+      IREE::HAL::DeviceAllocatorOp::create(builder, op->getLoc(), device);
   return {allocator, queueAffinity};
 }
 
@@ -104,8 +105,8 @@
                            PatternRewriter &rewriter) {
   if (timepointFence)
     return timepointFence;
-  return rewriter.create<IREE::Util::NullOp>(
-      loc, rewriter.getType<IREE::HAL::FenceType>());
+  return IREE::Util::NullOp::create(rewriter, loc,
+                                    rewriter.getType<IREE::HAL::FenceType>());
 }
 
 // Finds a !hal.fence bound to |timepoint| via a chain op and returns it if
@@ -148,8 +149,8 @@
   // Check to see if anyone is consuming the timepoint - if not then we don't
   // need create a fence.
   if (timepoint.use_empty()) {
-    return rewriter.create<IREE::Util::NullOp>(
-        loc, rewriter.getType<IREE::HAL::FenceType>());
+    return IREE::Util::NullOp::create(rewriter, loc,
+                                      rewriter.getType<IREE::HAL::FenceType>());
   }
 
   // Check to see if the timepoint is associated with a fence. In common cases
@@ -159,8 +160,8 @@
     return fence;
 
   // Create a new fence.
-  return rewriter.create<IREE::HAL::FenceCreateOp>(
-      loc, rewriter.getType<IREE::HAL::FenceType>(), device,
+  return IREE::HAL::FenceCreateOp::create(
+      rewriter, loc, rewriter.getType<IREE::HAL::FenceType>(), device,
       IREE::HAL::FenceFlagBitfield::None);
 }
 
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Conversion/TypeConverter.cpp b/compiler/src/iree/compiler/Dialect/HAL/Conversion/TypeConverter.cpp
index ca0932c..f297841 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Conversion/TypeConverter.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Conversion/TypeConverter.cpp
@@ -41,10 +41,10 @@
                               ValueRange inputs, Location loc) -> Value {
     assert(inputs.size() == 1);
     if (llvm::isa<TensorType>(inputs[0].getType())) {
-      return builder.create<IREE::HAL::TensorExportOp>(loc, type, inputs[0]);
+      return IREE::HAL::TensorExportOp::create(builder, loc, type, inputs[0]);
     } else if (llvm::isa<IREE::HAL::BufferViewType>(inputs[0].getType())) {
-      return builder.create<IREE::HAL::BufferViewBufferOp>(loc, type,
-                                                           inputs[0]);
+      return IREE::HAL::BufferViewBufferOp::create(builder, loc, type,
+                                                   inputs[0]);
     } else {
       emitError(loc) << "unsupported HAL target materialization: "
                      << inputs[0].getType();
@@ -58,7 +58,7 @@
     auto inputValue = inputs[0];
     auto inputType = inputValue.getType();
     if (llvm::isa<TensorType>(inputType)) {
-      return builder.create<IREE::HAL::TensorExportOp>(loc, type, inputValue);
+      return IREE::HAL::TensorExportOp::create(builder, loc, type, inputValue);
     } else if (llvm::isa<IREE::HAL::BufferType>(inputType)) {
       // Look for the buffer view this buffer came from, if any.
       // If we don't have the origin buffer view then we can't know the shape
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALAttrs.cpp b/compiler/src/iree/compiler/Dialect/HAL/IR/HALAttrs.cpp
index fa5e11b..79db18a 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALAttrs.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALAttrs.cpp
@@ -632,16 +632,17 @@
   // Enumerate all devices and match the first one found (if any).
   Type indexType = builder.getIndexType();
   Type deviceType = builder.getType<IREE::HAL::DeviceType>();
-  Value c0 = builder.create<arith::ConstantIndexOp>(loc, 0);
-  Value c1 = builder.create<arith::ConstantIndexOp>(loc, 1);
-  Value nullDevice = builder.create<IREE::Util::NullOp>(loc, deviceType);
+  Value c0 = arith::ConstantIndexOp::create(builder, loc, 0);
+  Value c1 = arith::ConstantIndexOp::create(builder, loc, 1);
+  Value nullDevice = IREE::Util::NullOp::create(builder, loc, deviceType);
   Value deviceOrdinal = deviceOrdinalAttr
-                            ? builder.create<arith::ConstantIndexOp>(
-                                  loc, deviceOrdinalAttr.getInt())
+                            ? arith::ConstantIndexOp::create(
+                                  builder, loc, deviceOrdinalAttr.getInt())
                             : c0;
-  Value deviceCount = builder.create<IREE::HAL::DevicesCountOp>(loc, indexType);
-  auto whileOp = builder.create<scf::WhileOp>(
-      loc,
+  Value deviceCount =
+      IREE::HAL::DevicesCountOp::create(builder, loc, indexType);
+  auto whileOp = scf::WhileOp::create(
+      builder, loc,
       TypeRange{
           /*i=*/indexType,
           /*match_ordinal=*/indexType,
@@ -653,43 +654,44 @@
           /*device=*/nullDevice,
       },
       [&](OpBuilder &beforeBuilder, Location loc, ValueRange operands) {
-        Value isNull = beforeBuilder.create<IREE::Util::CmpEQOp>(
-            loc, operands[/*device=*/2], nullDevice);
-        Value inBounds = beforeBuilder.create<arith::CmpIOp>(
-            loc, arith::CmpIPredicate::slt, operands[/*i=*/0], deviceCount);
+        Value isNull = IREE::Util::CmpEQOp::create(
+            beforeBuilder, loc, operands[/*device=*/2], nullDevice);
+        Value inBounds =
+            arith::CmpIOp::create(beforeBuilder, loc, arith::CmpIPredicate::slt,
+                                  operands[/*i=*/0], deviceCount);
         Value continueWhile =
-            beforeBuilder.create<arith::AndIOp>(loc, isNull, inBounds);
-        beforeBuilder.create<scf::ConditionOp>(loc, continueWhile, operands);
+            arith::AndIOp::create(beforeBuilder, loc, isNull, inBounds);
+        scf::ConditionOp::create(beforeBuilder, loc, continueWhile, operands);
       },
       [&](OpBuilder &afterBuilder, Location loc, ValueRange operands) {
         // Check whether the device is a match.
-        Value device = afterBuilder.create<IREE::HAL::DevicesGetOp>(
-            loc, deviceType, operands[/*i=*/0]);
+        Value device = IREE::HAL::DevicesGetOp::create(
+            afterBuilder, loc, deviceType, operands[/*i=*/0]);
         Value isDeviceMatch = buildDeviceMatch(loc, device, afterBuilder);
 
         // Check whether whether this matching device ordinal is the requested
         // ordinal out of all matching devices.
-        Value isOrdinalMatch = afterBuilder.create<arith::CmpIOp>(
-            loc, arith::CmpIPredicate::eq, operands[/*match_ordinal=*/1],
-            deviceOrdinal);
-        Value nextMatchOrdinal = afterBuilder.create<arith::AddIOp>(
-            loc, operands[/*match_ordinal=*/1],
-            afterBuilder.create<arith::SelectOp>(loc, isDeviceMatch, c1, c0));
+        Value isOrdinalMatch =
+            arith::CmpIOp::create(afterBuilder, loc, arith::CmpIPredicate::eq,
+                                  operands[/*match_ordinal=*/1], deviceOrdinal);
+        Value nextMatchOrdinal = arith::AddIOp::create(
+            afterBuilder, loc, operands[/*match_ordinal=*/1],
+            arith::SelectOp::create(afterBuilder, loc, isDeviceMatch, c1, c0));
 
         // Break if the device and ordinal match, otherwise continue with null.
-        Value isMatch = afterBuilder.create<arith::AndIOp>(loc, isDeviceMatch,
-                                                           isOrdinalMatch);
-        Value tryDevice = afterBuilder.create<arith::SelectOp>(
-            loc, isMatch, device, nullDevice);
+        Value isMatch = arith::AndIOp::create(afterBuilder, loc, isDeviceMatch,
+                                              isOrdinalMatch);
+        Value tryDevice = arith::SelectOp::create(afterBuilder, loc, isMatch,
+                                                  device, nullDevice);
 
         Value nextI =
-            afterBuilder.create<arith::AddIOp>(loc, operands[/*i=*/0], c1);
-        afterBuilder.create<scf::YieldOp>(
-            loc, ValueRange{
-                     /*i=*/nextI,
-                     /*match_ordinal=*/nextMatchOrdinal,
-                     /*device=*/tryDevice,
-                 });
+            arith::AddIOp::create(afterBuilder, loc, operands[/*i=*/0], c1);
+        scf::YieldOp::create(afterBuilder, loc,
+                             ValueRange{
+                                 /*i=*/nextI,
+                                 /*match_ordinal=*/nextMatchOrdinal,
+                                 /*device=*/tryDevice,
+                             });
       });
   return whileOp.getResult(/*device=*/2);
 }
@@ -708,15 +710,15 @@
   if (executableTargetAttrs.empty()) {
     return idMatch; // just device ID
   } else {
-    auto ifOp = builder.create<scf::IfOp>(loc, builder.getI1Type(), idMatch,
-                                          true, true);
+    auto ifOp = scf::IfOp::create(builder, loc, builder.getI1Type(), idMatch,
+                                  true, true);
     auto thenBuilder = ifOp.getThenBodyBuilder();
     Value anyFormatMatch = buildExecutableFormatMatch(
         loc, device, executableTargetAttrs, thenBuilder);
-    thenBuilder.create<scf::YieldOp>(loc, anyFormatMatch);
+    scf::YieldOp::create(thenBuilder, loc, anyFormatMatch);
     auto elseBuilder = ifOp.getElseBodyBuilder();
-    Value falseValue = elseBuilder.create<arith::ConstantIntOp>(loc, 0, 1);
-    elseBuilder.create<scf::YieldOp>(loc, falseValue);
+    Value falseValue = arith::ConstantIntOp::create(elseBuilder, loc, 0, 1);
+    scf::YieldOp::create(elseBuilder, loc, falseValue);
     return ifOp.getResult(0);
   }
 }
@@ -727,7 +729,7 @@
     ArrayRef<IREE::HAL::ExecutableTargetAttr> executableTargetAttrs,
     OpBuilder &builder) {
   if (executableTargetAttrs.empty()) {
-    return builder.create<arith::ConstantIntOp>(loc, 1, 1);
+    return arith::ConstantIntOp::create(builder, loc, 1, 1);
   }
   Value anyFormatMatch;
   for (auto executableTargetAttr : executableTargetAttrs) {
@@ -738,7 +740,7 @@
       anyFormatMatch = formatMatch;
     } else {
       anyFormatMatch =
-          builder.create<arith::OrIOp>(loc, anyFormatMatch, formatMatch);
+          arith::OrIOp::create(builder, loc, anyFormatMatch, formatMatch);
     }
   }
   return anyFormatMatch;
@@ -756,9 +758,9 @@
 Value IREE::HAL::DeviceOrdinalAttr::buildDeviceEnumeration(
     Location loc, IREE::HAL::BuildDeviceTargetMatchFn buildDeviceTargetMatch,
     OpBuilder &builder) const {
-  return builder.create<IREE::HAL::DevicesGetOp>(
-      loc, getType(),
-      builder.create<arith::ConstantIndexOp>(loc, getOrdinal()));
+  return IREE::HAL::DevicesGetOp::create(
+      builder, loc, getType(),
+      arith::ConstantIndexOp::create(builder, loc, getOrdinal()));
 }
 
 //===----------------------------------------------------------------------===//
@@ -776,8 +778,8 @@
   // TODO(benvanik): hal.device.cast if needed - may need to look up the global
   // to do it as we don't encode what the device is here in a way that is
   // guaranteed to be consistent.
-  return builder.create<IREE::Util::GlobalLoadOp>(loc, getType(),
-                                                  getName().getValue());
+  return IREE::Util::GlobalLoadOp::create(builder, loc, getType(),
+                                          getName().getValue());
 }
 
 //===----------------------------------------------------------------------===//
@@ -823,7 +825,7 @@
     Location loc, IREE::HAL::BuildDeviceTargetMatchFn buildDeviceTargetMatch,
     OpBuilder &builder) const {
   Type deviceType = builder.getType<IREE::HAL::DeviceType>();
-  Value nullDevice = builder.create<IREE::Util::NullOp>(loc, deviceType);
+  Value nullDevice = IREE::Util::NullOp::create(builder, loc, deviceType);
   std::function<Value(ArrayRef<IREE::HAL::DeviceInitializationAttrInterface>,
                       OpBuilder &)>
       buildTry;
@@ -836,14 +838,14 @@
     if (deviceAttrs.size() == 1)
       return tryDevice; // termination case
     Value isNull =
-        tryBuilder.create<IREE::Util::CmpEQOp>(loc, tryDevice, nullDevice);
+        IREE::Util::CmpEQOp::create(tryBuilder, loc, tryDevice, nullDevice);
     auto ifOp =
-        tryBuilder.create<scf::IfOp>(loc, deviceType, isNull, true, true);
+        scf::IfOp::create(tryBuilder, loc, deviceType, isNull, true, true);
     auto thenBuilder = ifOp.getThenBodyBuilder();
     Value tryChainDevice = buildTry(deviceAttrs.drop_front(1), thenBuilder);
-    thenBuilder.create<scf::YieldOp>(loc, tryChainDevice);
+    scf::YieldOp::create(thenBuilder, loc, tryChainDevice);
     auto elseBuilder = ifOp.getElseBodyBuilder();
-    elseBuilder.create<scf::YieldOp>(loc, tryDevice);
+    scf::YieldOp::create(elseBuilder, loc, tryDevice);
     return ifOp.getResult(0);
   };
   SmallVector<IREE::HAL::DeviceInitializationAttrInterface> deviceAttrs(
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALDialect.cpp b/compiler/src/iree/compiler/Dialect/HAL/IR/HALDialect.cpp
index 1c9db80b..1422c61 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALDialect.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALDialect.cpp
@@ -208,8 +208,8 @@
   if (llvm::isa<IndexType>(type)) {
     // Some folders materialize raw index types, which just become std
     // constants.
-    return builder.create<mlir::arith::ConstantIndexOp>(
-        loc, llvm::cast<IntegerAttr>(value).getValue().getSExtValue());
+    return mlir::arith::ConstantIndexOp::create(
+        builder, loc, llvm::cast<IntegerAttr>(value).getValue().getSExtValue());
   }
   return nullptr;
 }
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOpFolders.cpp b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOpFolders.cpp
index 2536c7f..8c201d9 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOpFolders.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOpFolders.cpp
@@ -98,8 +98,8 @@
     if (orderedSources.size() == op.getSources().size()) {
       return failure();
     }
-    auto newOp = rewriter.create<TensorBarrierOp>(op.getLoc(), orderedSources,
-                                                  op.getSignalFence());
+    auto newOp = TensorBarrierOp::create(rewriter, op.getLoc(), orderedSources,
+                                         op.getSignalFence());
     SmallVector<Value> newResults;
     newResults.reserve(newOp.getNumResults());
     for (unsigned newIndex : resultMapping) {
@@ -844,8 +844,8 @@
     // about making that work.
     rewriter.setInsertionPoint(blockOps.front());
     auto fusedLoc = rewriter.getFusedLoc(blockLocs);
-    auto newBlockOp = rewriter.create<ExecutableConstantBlockOp>(
-        fusedLoc, rewriter.getFunctionType(inputTypes, resultTypes),
+    auto newBlockOp = ExecutableConstantBlockOp::create(
+        rewriter, fusedLoc, rewriter.getFunctionType(inputTypes, resultTypes),
         rewriter.getArrayAttr(resultKeys), /*arg_attrs=*/ArrayAttr(),
         /*res_attrs=*/ArrayAttr());
 
@@ -1129,8 +1129,8 @@
     }
 
     // Safe to elide.
-    Value nullFence = rewriter.create<IREE::Util::NullOp>(
-        rewriter.getFusedLoc({createOp.getLoc(), signalOp.getLoc()}),
+    Value nullFence = IREE::Util::NullOp::create(
+        rewriter, rewriter.getFusedLoc({createOp.getLoc(), signalOp.getLoc()}),
         fence.getType());
     rewriter.replaceAllUsesWith(fence, nullFence);
     rewriter.eraseOp(signalOp);
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp
index 16e891f..6cabdce 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALOps.cpp
@@ -1767,7 +1767,7 @@
   // Always evaluate to true if no region is present.
   auto *body = getConditionBody();
   if (!body) {
-    return builder.create<arith::ConstantIntOp>(loc, 1, 1);
+    return arith::ConstantIntOp::create(builder, loc, 1, 1);
   }
 
   // TODO(benvanik): replace with region inlining util.
@@ -1933,7 +1933,8 @@
   assert(!getConditionOp() && "condition op already exists");
 
   builder.setInsertionPointToStart(&getRegion().front());
-  auto conditionOp = builder.create<IREE::HAL::ExecutableConditionOp>(getLoc());
+  auto conditionOp =
+      IREE::HAL::ExecutableConditionOp::create(builder, getLoc());
   Block *entryPoint = conditionOp.addEntryBlock();
   Value device = entryPoint->getArgument(0);
 
@@ -1950,8 +1951,8 @@
   // Factor in variant condition region, if any.
   auto conditionOp = getConditionOp();
   if (conditionOp) {
-    auto regionOp = builder.create<scf::ExecuteRegionOp>(conditionOp.getLoc(),
-                                                         builder.getI1Type());
+    auto regionOp = scf::ExecuteRegionOp::create(builder, conditionOp.getLoc(),
+                                                 builder.getI1Type());
 
     IRMapping mapper;
     mapper.map(conditionOp.getRegion().getArgument(0), device);
@@ -1964,8 +1965,8 @@
       returnOp.erase();
     }
 
-    selected = builder.create<arith::AndIOp>(getLoc(), selected,
-                                             regionOp.getResult(0));
+    selected = arith::AndIOp::create(builder, getLoc(), selected,
+                                     regionOp.getResult(0));
   }
 
   return selected;
diff --git a/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.cpp b/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.cpp
index ea46009..9d53617 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/IR/HALTypes.cpp
@@ -84,9 +84,9 @@
 
 // static
 Value DeviceType::resolveAny(Location loc, OpBuilder &builder) {
-  Value deviceIndex = builder.create<arith::ConstantIndexOp>(loc, 0);
-  return builder.create<IREE::HAL::DevicesGetOp>(
-      loc, builder.getType<IREE::HAL::DeviceType>(), deviceIndex);
+  Value deviceIndex = arith::ConstantIndexOp::create(builder, loc, 0);
+  return IREE::HAL::DevicesGetOp::create(
+      builder, loc, builder.getType<IREE::HAL::DeviceType>(), deviceIndex);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/CaptureExecutableSources.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/CaptureExecutableSources.cpp
index 4874a39..bd204fd 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/CaptureExecutableSources.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/CaptureExecutableSources.cpp
@@ -86,8 +86,8 @@
             &clonedExecutableOp.getBody().emplaceBlock());
         auto clonedVariantOp = cast<IREE::HAL::ExecutableVariantOp>(
             clonedBuilder.clone(*variantOp));
-        clonedBuilder.create<IREE::HAL::ExecutableEndOp>(
-            clonedBuilder.getUnknownLoc());
+        IREE::HAL::ExecutableEndOp::create(clonedBuilder,
+                                           clonedBuilder.getUnknownLoc());
 
         // Capture the source contents and update the locations in the IR to
         // reference it.
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/DumpExecutableBenchmarks.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/DumpExecutableBenchmarks.cpp
index 095b3fc..3775897 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/DumpExecutableBenchmarks.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/DumpExecutableBenchmarks.cpp
@@ -154,8 +154,8 @@
                           OpBuilder &builder) {
   if (auto deviceAffinityAttr =
           dyn_cast_if_present<IREE::HAL::DeviceAffinityAttr>(affinityAttr)) {
-    auto resolveOp = builder.create<IREE::HAL::DeviceResolveOp>(
-        loc,
+    auto resolveOp = IREE::HAL::DeviceResolveOp::create(
+        builder, loc,
         TypeRange{
             builder.getType<IREE::HAL::DeviceType>(),
             builder.getI64Type(),
@@ -164,7 +164,7 @@
     return std::make_pair(resolveOp.getResult(0), resolveOp.getResult(1));
   }
   auto device = IREE::HAL::DeviceType::resolveAny(loc, builder);
-  auto queueAffinity = builder.create<arith::ConstantIntOp>(loc, -1, 64);
+  auto queueAffinity = arith::ConstantIntOp::create(builder, loc, -1, 64);
   return std::make_pair(device, queueAffinity);
 }
 
@@ -174,8 +174,8 @@
     Location loc, StringRef baseName, const DispatchParams &dispatchParams,
     IREE::Stream::AffinityAttr affinityAttr, OpBuilder &moduleBuilder) {
   // Create a global to hold the HAL buffer.
-  auto globalOp = moduleBuilder.create<IREE::Util::GlobalOp>(
-      loc, (baseName + "_buffer").str(),
+  auto globalOp = IREE::Util::GlobalOp::create(
+      moduleBuilder, loc, (baseName + "_buffer").str(),
       /*isMutable=*/true,
       IREE::HAL::BufferType::get(moduleBuilder.getContext()));
   globalOp.setPrivate();
@@ -189,7 +189,7 @@
   }
 
   // Build an initializer to allocate the buffer.
-  auto initOp = moduleBuilder.create<IREE::Util::InitializerOp>(loc);
+  auto initOp = IREE::Util::InitializerOp::create(moduleBuilder, loc);
   auto initBuilder = OpBuilder::atBlockBegin(initOp.addEntryBlock());
   IndexSet indexSet(loc, initBuilder);
 
@@ -197,21 +197,22 @@
   auto [device, queueAffinity] =
       getDeviceAndQueueAffinity(loc, affinityAttr, initBuilder);
   auto allocator =
-      initBuilder.create<IREE::HAL::DeviceAllocatorOp>(loc, device).getResult();
+      IREE::HAL::DeviceAllocatorOp::create(initBuilder, loc, device)
+          .getResult();
 
   auto memoryTypes = IREE::HAL::MemoryTypeBitfield::DeviceLocal;
   auto bufferUsage = IREE::HAL::BufferUsageBitfield::Transfer |
                      IREE::HAL::BufferUsageBitfield::DispatchStorage;
   Value memoryTypeOp =
-      initBuilder.create<IREE::HAL::MemoryTypeOp>(loc, memoryTypes);
+      IREE::HAL::MemoryTypeOp::create(initBuilder, loc, memoryTypes);
   Value bufferUsageOp =
-      initBuilder.create<IREE::HAL::BufferUsageOp>(loc, bufferUsage);
-  auto allocateOp = initBuilder.create<IREE::HAL::AllocatorAllocateOp>(
-      loc, globalOp.getType(), allocator, queueAffinity, memoryTypeOp,
-      bufferUsageOp, indexSet.get(totalLength));
+      IREE::HAL::BufferUsageOp::create(initBuilder, loc, bufferUsage);
+  auto allocateOp = IREE::HAL::AllocatorAllocateOp::create(
+      initBuilder, loc, globalOp.getType(), allocator, queueAffinity,
+      memoryTypeOp, bufferUsageOp, indexSet.get(totalLength));
 
   globalOp.createStoreOp(loc, allocateOp.getResult(), initBuilder);
-  initBuilder.create<IREE::Util::ReturnOp>(loc);
+  IREE::Util::ReturnOp::create(initBuilder, loc);
 
   return globalOp;
 }
@@ -247,7 +248,7 @@
   auto funcType =
       moduleBuilder.getFunctionType({moduleBuilder.getI32Type()}, {});
   auto funcOp =
-      moduleBuilder.create<IREE::Util::FuncOp>(loc, baseName, funcType);
+      IREE::Util::FuncOp::create(moduleBuilder, loc, baseName, funcType);
   funcOp.setVisibility(SymbolTable::Visibility::Public);
 
   // Mark the function as being a dispatch benchmark.
@@ -264,8 +265,8 @@
   auto *entryBlock = funcOp.addEntryBlock();
   OpBuilder funcBuilder = OpBuilder::atBlockBegin(entryBlock);
   IndexSet indexSet(loc, funcBuilder);
-  auto batchSizeArg = funcBuilder.create<arith::IndexCastOp>(
-      loc, funcBuilder.getIndexType(), entryBlock->getArgument(0));
+  auto batchSizeArg = arith::IndexCastOp::create(
+      funcBuilder, loc, funcBuilder.getIndexType(), entryBlock->getArgument(0));
 
   // Resolve device for this particular benchmark.
   auto [device, queueAffinity] =
@@ -291,8 +292,8 @@
   if (int64_t pushConstantCount = layoutAttr.getConstants()) {
     constantValues.reserve(pushConstantCount);
     for (int64_t i = 0; i < pushConstantCount; ++i) {
-      constantValues.push_back(funcBuilder.create<arith::ConstantOp>(
-          loc, dispatchParams.uniformOperands[i]));
+      constantValues.push_back(arith::ConstantOp::create(
+          funcBuilder, loc, dispatchParams.uniformOperands[i]));
     }
   }
 
@@ -322,27 +323,27 @@
   // Compute the workgroup parameters.
   auto workload = llvm::map_to_vector(
       dispatchParams.workload, [&](unsigned dim) { return indexSet.get(dim); });
-  auto workgroupCountOp =
-      funcBuilder.create<IREE::HAL::ExecutableCalculateWorkgroupsOp>(
-          loc, funcBuilder.getIndexType(), funcBuilder.getIndexType(),
-          funcBuilder.getIndexType(), device, exportRefAttr, workload);
+  auto workgroupCountOp = IREE::HAL::ExecutableCalculateWorkgroupsOp::create(
+      funcBuilder, loc, funcBuilder.getIndexType(), funcBuilder.getIndexType(),
+      funcBuilder.getIndexType(), device, exportRefAttr, workload);
 
   // Get the executable/entry point ordinal used to dispatch.
-  Value executable = funcBuilder.create<IREE::HAL::ExecutableLookupOp>(
-      loc, funcBuilder.getType<IREE::HAL::ExecutableType>(), device,
-      exportRefAttr.getRootReference().getValue());
-  Value ordinal = funcBuilder.create<IREE::HAL::ExecutableExportOrdinalOp>(
-      loc, funcBuilder.getIndexType(), exportRefAttr);
+  Value executable = IREE::HAL::ExecutableLookupOp::create(
+      funcBuilder, loc, funcBuilder.getType<IREE::HAL::ExecutableType>(),
+      device, exportRefAttr.getRootReference().getValue());
+  Value ordinal = IREE::HAL::ExecutableExportOrdinalOp::create(
+      funcBuilder, loc, funcBuilder.getIndexType(), exportRefAttr);
 
   // Loop around dispatches based on batch size.
   // Note that we insert a barrier between each dispatch - we could make this
   // optional so that concurrent utilization is measured.
-  funcBuilder.create<scf::ForOp>(
-      loc, indexSet.get(0), batchSizeArg, indexSet.get(1), ValueRange{},
+  scf::ForOp::create(
+      funcBuilder, loc, indexSet.get(0), batchSizeArg, indexSet.get(1),
+      ValueRange{},
       [&](OpBuilder &forBuilder, Location loc, Value iv, ValueRange iters) {
         // Dispatch.
-        forBuilder.create<IREE::HAL::CommandBufferDispatchOp>(
-            loc, commandBuffer, executable, ordinal,
+        IREE::HAL::CommandBufferDispatchOp::create(
+            forBuilder, loc, commandBuffer, executable, ordinal,
             workgroupCountOp.getResults(), constantValues, bindingValues,
             IREE::HAL::DispatchFlags::None);
 
@@ -352,36 +353,37 @@
         auto targetStage = IREE::HAL::ExecutionStageBitfield::CommandIssue |
                            IREE::HAL::ExecutionStageBitfield::Dispatch;
         auto barrierFlags = IREE::HAL::ExecutionBarrierFlagBitfield::None;
-        forBuilder.create<IREE::HAL::CommandBufferExecutionBarrierOp>(
-            loc, commandBuffer, sourceStage, targetStage, barrierFlags);
+        IREE::HAL::CommandBufferExecutionBarrierOp::create(
+            forBuilder, loc, commandBuffer, sourceStage, targetStage,
+            barrierFlags);
 
-        forBuilder.create<scf::YieldOp>(loc);
+        scf::YieldOp::create(forBuilder, loc);
       });
 
-  funcBuilder.create<IREE::HAL::CommandBufferFinalizeOp>(loc, commandBuffer);
+  IREE::HAL::CommandBufferFinalizeOp::create(funcBuilder, loc, commandBuffer);
 
   // We begin executing immediately and then wait on a fence.
   // TODO(benvanik): add fences to ABI so the benchmark tool can pipeline.
-  Value waitFence = funcBuilder.create<IREE::Util::NullOp>(
-      loc, funcBuilder.getType<IREE::HAL::FenceType>());
-  Value signalFence = funcBuilder.create<IREE::HAL::FenceCreateOp>(
-      loc, funcBuilder.getType<IREE::HAL::FenceType>(), device,
+  Value waitFence = IREE::Util::NullOp::create(
+      funcBuilder, loc, funcBuilder.getType<IREE::HAL::FenceType>());
+  Value signalFence = IREE::HAL::FenceCreateOp::create(
+      funcBuilder, loc, funcBuilder.getType<IREE::HAL::FenceType>(), device,
       IREE::HAL::FenceFlagBitfield::None);
 
   // Queue execution.
-  funcBuilder.create<IREE::HAL::DeviceQueueExecuteOp>(
-      loc, device, queueAffinity, waitFence, signalFence, commandBuffer,
-      IREE::HAL::ExecuteFlagBitfield::None);
+  IREE::HAL::DeviceQueueExecuteOp::create(
+      funcBuilder, loc, device, queueAffinity, waitFence, signalFence,
+      commandBuffer, IREE::HAL::ExecuteFlagBitfield::None);
 
   // Block until it completes.
-  Value timeoutMillis = funcBuilder.create<arith::ConstantIntOp>(loc, -1, 32);
-  auto fenceOp = funcBuilder.create<IREE::HAL::FenceAwaitOp>(
-      loc, funcBuilder.getI32Type(), timeoutMillis,
+  Value timeoutMillis = arith::ConstantIntOp::create(funcBuilder, loc, -1, 32);
+  auto fenceOp = IREE::HAL::FenceAwaitOp::create(
+      funcBuilder, loc, funcBuilder.getI32Type(), timeoutMillis,
       IREE::HAL::WaitFlagBitfield::None, signalFence);
-  funcBuilder.create<IREE::Util::StatusCheckOkOp>(
-      loc, fenceOp.getStatus(), "failed to wait on timepoint");
+  IREE::Util::StatusCheckOkOp::create(funcBuilder, loc, fenceOp.getStatus(),
+                                      "failed to wait on timepoint");
 
-  funcBuilder.create<IREE::Util::ReturnOp>(loc);
+  IREE::Util::ReturnOp::create(funcBuilder, loc);
 }
 
 // Builds a module exporting one function for each dispatch configuration
@@ -407,8 +409,8 @@
   }
 
   // Clone the executable variant into the new module.
-  auto executableOp = moduleBuilder.create<IREE::HAL::ExecutableOp>(
-      sourceExecutableOp.getLoc(), sourceExecutableOp.getName());
+  auto executableOp = IREE::HAL::ExecutableOp::create(
+      moduleBuilder, sourceExecutableOp.getLoc(), sourceExecutableOp.getName());
   executableOp.setVisibility(sourceExecutableOp.getVisibility());
   auto variantOp = cast<IREE::HAL::ExecutableVariantOp>(
       OpBuilder::atBlockBegin(&executableOp.getBlock())
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/InitializeDevices.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/InitializeDevices.cpp
index 6c0808d..e9d4be7 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/InitializeDevices.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/InitializeDevices.cpp
@@ -38,7 +38,7 @@
   // Build a new util.initializer.
   OpBuilder moduleBuilder(globalOp);
   moduleBuilder.setInsertionPointAfter(globalOp);
-  auto initializerOp = moduleBuilder.create<IREE::Util::InitializerOp>(loc);
+  auto initializerOp = IREE::Util::InitializerOp::create(moduleBuilder, loc);
   auto *block = moduleBuilder.createBlock(&initializerOp.getBody());
   auto initializerBuilder = OpBuilder::atBlockBegin(block);
 
@@ -60,15 +60,16 @@
   // the compiler today and may never want to. If selecting from multiple
   // devices queries can be used to detect what the selected device was and
   // those will be memoized.
-  Value nullDevice = initializerBuilder.create<IREE::Util::NullOp>(
-      loc, enumeratedDevice.getType());
-  Value isNull = initializerBuilder.create<IREE::Util::CmpEQOp>(
-      loc, enumeratedDevice, nullDevice);
-  initializerBuilder.create<scf::IfOp>(
-      loc, isNull, [&](OpBuilder &thenBuilder, Location thenLoc) {
-        Value status = thenBuilder.create<arith::ConstantIntOp>(
-            thenLoc, static_cast<int64_t>(IREE::Util::StatusCode::Incompatible),
-            32);
+  Value nullDevice = IREE::Util::NullOp::create(initializerBuilder, loc,
+                                                enumeratedDevice.getType());
+  Value isNull = IREE::Util::CmpEQOp::create(initializerBuilder, loc,
+                                             enumeratedDevice, nullDevice);
+  scf::IfOp::create(
+      initializerBuilder, loc, isNull,
+      [&](OpBuilder &thenBuilder, Location thenLoc) {
+        Value status = arith::ConstantIntOp::create(
+            thenBuilder, thenLoc,
+            static_cast<int64_t>(IREE::Util::StatusCode::Incompatible), 32);
         std::string str;
         {
           llvm::raw_string_ostream os(str);
@@ -76,13 +77,13 @@
              << "` not found or unavailable: ";
           initialValue.printStatusDescription(os);
         }
-        thenBuilder.create<IREE::Util::StatusCheckOkOp>(thenLoc, status, str);
-        thenBuilder.create<scf::YieldOp>(thenLoc);
+        IREE::Util::StatusCheckOkOp::create(thenBuilder, thenLoc, status, str);
+        scf::YieldOp::create(thenBuilder, thenLoc);
       });
 
   // Store the device back to the global to complete initialization.
   globalOp.createStoreOp(loc, enumeratedDevice, initializerBuilder);
-  initializerBuilder.create<IREE::Util::ReturnOp>(loc);
+  IREE::Util::ReturnOp::create(initializerBuilder, loc);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/InlineMemoizeRegions.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/InlineMemoizeRegions.cpp
index ab74f97..bf62add 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/InlineMemoizeRegions.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/InlineMemoizeRegions.cpp
@@ -74,7 +74,7 @@
           memoizeOp.getResultTypes(), fusedResultLocs));
       rewriter.inlineRegionBefore(memoizeOp.getBody(), continueBlock);
       rewriter.setInsertionPointToEnd(initialBlock);
-      rewriter.create<mlir::cf::BranchOp>(memoizeOp.getLoc(), entryBlock);
+      mlir::cf::BranchOp::create(rewriter, memoizeOp.getLoc(), entryBlock);
       for (auto returnOp : returnOps) {
         rewriter.setInsertionPoint(returnOp);
         rewriter.replaceOpWithNewOp<mlir::cf::BranchOp>(returnOp, continueBlock,
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeDispatchInstrumentation.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeDispatchInstrumentation.cpp
index 2c4a595..4385474 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeDispatchInstrumentation.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeDispatchInstrumentation.cpp
@@ -64,8 +64,8 @@
       VectorType::get({sizeof(header)}, builder.getI8Type()),
       ArrayRef<char>(reinterpret_cast<const char *>(&header), sizeof(header)));
 
-  return builder.create<IREE::Util::BufferConstantOp>(
-      loc, /*name=*/nullptr, dataAttr, builder.getIndexAttr(16),
+  return IREE::Util::BufferConstantOp::create(
+      builder, loc, /*name=*/nullptr, dataAttr, builder.getIndexAttr(16),
       /*mimeType=*/nullptr);
 }
 
@@ -79,22 +79,23 @@
   auto zeroAttr = IntegerAttr::get(i8Type, 0);
   auto dataAttr = DenseElementsAttr::get(
       VectorType::get({(int64_t)padding}, i8Type), zeroAttr);
-  return builder.create<IREE::Util::BufferConstantOp>(
-      loc, /*name=*/nullptr, dataAttr, builder.getIndexAttr(16),
+  return IREE::Util::BufferConstantOp::create(
+      builder, loc, /*name=*/nullptr, dataAttr, builder.getIndexAttr(16),
       /*mimeType=*/nullptr);
 }
 
 static void appendListItems(Location loc, Value list, ArrayRef<Value> items,
                             OpBuilder &builder) {
-  Value oldLength = builder.create<IREE::Util::ListSizeOp>(loc, list);
-  Value newLength = builder.create<arith::AddIOp>(
-      loc, oldLength,
-      builder.create<arith::ConstantIndexOp>(loc, items.size()));
-  builder.create<IREE::Util::ListResizeOp>(loc, list, newLength);
+  Value oldLength = IREE::Util::ListSizeOp::create(builder, loc, list);
+  Value newLength = arith::AddIOp::create(
+      builder, loc, oldLength,
+      arith::ConstantIndexOp::create(builder, loc, items.size()));
+  IREE::Util::ListResizeOp::create(builder, loc, list, newLength);
   for (size_t i = 0; i < items.size(); ++i) {
-    Value idx = builder.create<arith::AddIOp>(
-        loc, oldLength, builder.create<arith::ConstantIndexOp>(loc, i));
-    builder.create<IREE::Util::ListSetOp>(loc, list, idx, items[i]);
+    Value idx =
+        arith::AddIOp::create(builder, loc, oldLength,
+                              arith::ConstantIndexOp::create(builder, loc, i));
+    IREE::Util::ListSetOp::create(builder, loc, list, idx, items[i]);
   }
 }
 
@@ -135,22 +136,23 @@
     auto bufferType = MemRefType::get({totalBufferSize}, i8Type);
 
     // Create global device-side instrumentation resource.
-    auto globalOp = moduleBuilder.create<IREE::Util::GlobalOp>(
-        loc, "__dispatch_instrumentation",
+    auto globalOp = IREE::Util::GlobalOp::create(
+        moduleBuilder, loc, "__dispatch_instrumentation",
         /*isMutable=*/false,
         moduleBuilder.getType<IREE::Stream::ResourceType>(
             IREE::Stream::Lifetime::External));
     {
-      auto initializerOp = moduleBuilder.create<IREE::Util::InitializerOp>(loc);
+      auto initializerOp =
+          IREE::Util::InitializerOp::create(moduleBuilder, loc);
       auto initializerBuilder =
           OpBuilder::atBlockBegin(initializerOp.addEntryBlock());
       Value bufferSize =
-          initializerBuilder.create<arith::ConstantOp>(loc, bufferSizeAttr);
-      Value buffer = initializerBuilder.create<IREE::Stream::ResourceAllocOp>(
-          loc, globalOp.getType(), bufferSize,
+          arith::ConstantOp::create(initializerBuilder, loc, bufferSizeAttr);
+      Value buffer = IREE::Stream::ResourceAllocOp::create(
+          initializerBuilder, loc, globalOp.getType(), bufferSize,
           /*uninitialized=*/true, /*affinity=*/nullptr);
       globalOp.createStoreOp(loc, buffer, initializerBuilder);
-      initializerBuilder.create<IREE::Util::ReturnOp>(loc);
+      IREE::Util::ReturnOp::create(initializerBuilder, loc);
     }
 
     FlatbufferBuilder metadataBuilder;
@@ -199,11 +201,12 @@
         // capturing workgroup ID yet with this instrumentation op and instead
         // leave that until late in the codegen pipeline.
         auto funcBuilder = OpBuilder::atBlockBegin(&funcOp.front());
-        Value zero = funcBuilder.create<arith::ConstantIndexOp>(loc, 0);
-        auto subspanOp = funcBuilder.create<IREE::Stream::BindingSubspanOp>(
-            loc, bufferType, bindingArg, /*byteOffset=*/zero, ValueRange{});
-        funcBuilder.create<IREE::HAL::InstrumentWorkgroupOp>(
-            loc, indexType, subspanOp.getResult(), dispatchIdArg);
+        Value zero = arith::ConstantIndexOp::create(funcBuilder, loc, 0);
+        auto subspanOp = IREE::Stream::BindingSubspanOp::create(
+            funcBuilder, loc, bufferType, bindingArg, /*byteOffset=*/zero,
+            ValueRange{});
+        IREE::HAL::InstrumentWorkgroupOp::create(
+            funcBuilder, loc, indexType, subspanOp.getResult(), dispatchIdArg);
 
         // Build function metadata.
         auto nameRef = metadataBuilder.createString(exportOp.getName());
@@ -232,9 +235,9 @@
         // Load the ringbuffer and capture it for use within the execute region.
         auto loadedValue =
             globalOp.createLoadOp(loc, parentBuilder).getLoadedGlobalValue();
-        Value zero = parentBuilder.create<arith::ConstantIndexOp>(loc, 0);
+        Value zero = arith::ConstantIndexOp::create(parentBuilder, loc, 0);
         Value bufferSize =
-            parentBuilder.create<arith::ConstantOp>(loc, bufferSizeAttr);
+            arith::ConstantOp::create(parentBuilder, loc, bufferSizeAttr);
         executeOp.getResourceOperandsMutable().append(loadedValue);
         executeOp.getResourceOperandSizesMutable().append(bufferSize);
         auto bufferArg =
@@ -309,8 +312,8 @@
     // Create query function for getting the instrumentation data.
     auto listType = moduleBuilder.getType<IREE::Util::ListType>(
         moduleBuilder.getType<IREE::Util::VariantType>());
-    auto queryOp = moduleBuilder.create<IREE::Util::FuncOp>(
-        loc, "__query_instruments",
+    auto queryOp = IREE::Util::FuncOp::create(
+        moduleBuilder, loc, "__query_instruments",
         moduleBuilder.getFunctionType({listType}, {}));
     {
       queryOp.setPublic();
@@ -325,9 +328,10 @@
                             metadataAttr.size(), queryBuilder));
 
       // Grab the read-only dispatch metadata.
-      iovecs.push_back(queryBuilder.create<IREE::Util::BufferConstantOp>(
-          loc, queryBuilder.getStringAttr("dispatch_instrument.fb"),
-          metadataAttr, queryBuilder.getIndexAttr(16),
+      iovecs.push_back(IREE::Util::BufferConstantOp::create(
+          queryBuilder, loc,
+          queryBuilder.getStringAttr("dispatch_instrument.fb"), metadataAttr,
+          queryBuilder.getIndexAttr(16),
           queryBuilder.getStringAttr("application/x-flatbuffers")));
 
       if (Value metadataPadding =
@@ -343,10 +347,10 @@
       Value buffer =
           globalOp.createLoadOp(loc, queryBuilder).getLoadedGlobalValue();
       Value bufferSize =
-          queryBuilder.create<arith::ConstantOp>(loc, bufferSizeAttr);
+          arith::ConstantOp::create(queryBuilder, loc, bufferSizeAttr);
       auto bufferViewType = moduleBuilder.getType<IREE::HAL::BufferViewType>();
-      auto exportOp = queryBuilder.create<IREE::Stream::TensorExportOp>(
-          loc, bufferViewType, buffer,
+      auto exportOp = IREE::Stream::TensorExportOp::create(
+          queryBuilder, loc, bufferViewType, buffer,
           RankedTensorType::get({totalBufferSize}, queryBuilder.getI8Type()),
           ValueRange{}, bufferSize,
           /*affinity=*/nullptr);
@@ -358,7 +362,7 @@
       }
 
       appendListItems(loc, listArg, iovecs, queryBuilder);
-      queryBuilder.create<IREE::Util::ReturnOp>(loc);
+      IREE::Util::ReturnOp::create(queryBuilder, loc);
     }
   }
 };
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeInterfaces.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeInterfaces.cpp
index 180e25e..39a6887 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeInterfaces.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeInterfaces.cpp
@@ -178,8 +178,8 @@
 
   // Create the op that will contain the translated executable.
   OpBuilder moduleBuilder(sourceOp);
-  auto executableOp = moduleBuilder.create<IREE::HAL::ExecutableOp>(
-      sourceOp.getLoc(), sourceOp.getName());
+  auto executableOp = IREE::HAL::ExecutableOp::create(
+      moduleBuilder, sourceOp.getLoc(), sourceOp.getName());
   executableOp.setVisibility(sourceOp.getVisibility());
 
   // With this hand-authored path all variants have the same layout and entry
@@ -193,8 +193,9 @@
   OpBuilder targetBuilder(&executableOp.getBlock().back());
   for (auto targetAttr : targetAttrs) {
     // Create new variant and clone the exports.
-    auto targetVariantOp = targetBuilder.create<IREE::HAL::ExecutableVariantOp>(
-        sourceOp->getLoc(), targetAttr.getSymbolNameFragment(), targetAttr);
+    auto targetVariantOp = IREE::HAL::ExecutableVariantOp::create(
+        targetBuilder, sourceOp->getLoc(), targetAttr.getSymbolNameFragment(),
+        targetAttr);
     targetSymbolTable.insert(targetVariantOp);
     OpBuilder variantBuilder(&targetVariantOp.getBlock().back());
     for (auto sourceExportOp : sourceExportOps) {
@@ -282,8 +283,8 @@
       arg.getArgNumber(), "stream.alignment");
   auto valuesAttr = sourceFuncOp.getArgAttrOfType<ArrayAttr>(arg.getArgNumber(),
                                                              "stream.values");
-  auto loadOp = builder.create<IREE::HAL::InterfaceConstantLoadOp>(
-      arg.getLoc(), arg.getType(), pipelineLayoutAttr,
+  auto loadOp = IREE::HAL::InterfaceConstantLoadOp::create(
+      builder, arg.getLoc(), arg.getType(), pipelineLayoutAttr,
       builder.getIndexAttr(pushConstantIdx), alignmentAttr, valuesAttr);
   arg.replaceAllUsesWith(loadOp);
 }
@@ -302,8 +303,8 @@
     OpBuilder builder(oldOp);
     auto alignmentAttr = sourceFuncOp.getArgAttrOfType<IntegerAttr>(
         arg.getArgNumber(), "stream.alignment");
-    auto newOp = builder.create<IREE::HAL::InterfaceBindingSubspanOp>(
-        oldOp.getLoc(), oldOp.getType(), pipelineLayoutAttr,
+    auto newOp = IREE::HAL::InterfaceBindingSubspanOp::create(
+        builder, oldOp.getLoc(), oldOp.getType(), pipelineLayoutAttr,
         APInt(64, bindingOrdinal), oldOp.getByteOffset(),
         oldOp.getDynamicDims(), alignmentAttr, bindingAttr.getFlags());
     oldOp.replaceAllUsesWith(newOp.getResult());
@@ -419,8 +420,8 @@
                            : makePipelineLayoutAttr(pipelineLayout,
                                                     variantOp.getTargetAttr(),
                                                     targetBuilder);
-      auto newExportOp = targetBuilder.create<IREE::HAL::ExecutableExportOp>(
-          exportOp.getLoc(),
+      auto newExportOp = IREE::HAL::ExecutableExportOp::create(
+          targetBuilder, exportOp.getLoc(),
           targetBuilder.getStringAttr(exportOp.getFunctionRef()),
           targetBuilder.getIndexAttr(ordinal), variantLayoutAttr, workgroupSize,
           /*subgroup_size=*/IntegerAttr{},
@@ -632,8 +633,8 @@
       // Create the op that will contain the translated executable.
       OpBuilder builder = OpBuilder::atBlockEnd(moduleOp.getBody());
       builder.setInsertionPointAfter(sourceOp);
-      auto executableOp = builder.create<IREE::HAL::ExecutableOp>(
-          sourceOp.getLoc(), sourceOp.getName());
+      auto executableOp = IREE::HAL::ExecutableOp::create(
+          builder, sourceOp.getLoc(), sourceOp.getName());
       executableOp.setVisibility(sourceOp.getVisibility());
 
       // Materialize all of the hal.executable.variant ops for all backends we
@@ -641,15 +642,14 @@
       SymbolTable targetSymbolTable(executableOp);
       OpBuilder targetBuilder(&executableOp.getBlock().back());
       for (auto targetAttr : targetAttrs) {
-        auto targetContainerOp =
-            targetBuilder.create<IREE::HAL::ExecutableVariantOp>(
-                sourceOp->getLoc(), targetAttr.getSymbolNameFragment(),
-                targetAttr);
+        auto targetContainerOp = IREE::HAL::ExecutableVariantOp::create(
+            targetBuilder, sourceOp->getLoc(),
+            targetAttr.getSymbolNameFragment(), targetAttr);
         setApplicableObjects(sourceOp, targetContainerOp);
         targetSymbolTable.insert(targetContainerOp);
         if (sourceOp.getInnerModule()) {
           OpBuilder containerBuilder(&targetContainerOp.getBlock().back());
-          containerBuilder.create<mlir::ModuleOp>(sourceOp->getLoc());
+          mlir::ModuleOp::create(containerBuilder, sourceOp->getLoc());
         }
       }
 
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeResourceCaches.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeResourceCaches.cpp
index 1894852..4f9c7ee 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeResourceCaches.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeResourceCaches.cpp
@@ -92,7 +92,8 @@
                     << deviceOp.getGlobalName().getValue()
                     << "` executable global `" << symbolName << "`\n");
   auto executableType = moduleBuilder.getType<IREE::HAL::ExecutableType>();
-  auto globalOp = moduleBuilder.create<IREE::Util::GlobalOp>(
+  auto globalOp = IREE::Util::GlobalOp::create(
+      moduleBuilder,
       moduleBuilder.getFusedLoc(llvm::to_vector(executable.locs)), symbolName,
       /*isMutable=*/false, executableType);
   globalOp.setPrivate();
@@ -123,8 +124,8 @@
   LLVM_DEBUG(DBGS() << "- inlining constant block `" << funcName << "`\n");
 
   // Create the function with the region contents of the constant block.
-  auto funcOp = moduleBuilder.create<IREE::Util::FuncOp>(
-      blockOp.getLoc(), funcName, blockOp.getFunctionType());
+  auto funcOp = IREE::Util::FuncOp::create(moduleBuilder, blockOp.getLoc(),
+                                           funcName, blockOp.getFunctionType());
   funcOp.setPrivate();
   IRMapping mapping;
   blockOp.getRegion().cloneInto(&funcOp.getRegion(), mapping);
@@ -142,8 +143,8 @@
   if (funcOp.getNumArguments() > 0) {
     callOperands.push_back(callerDevice);
   }
-  auto callOp = callerBuilder.create<IREE::Util::CallOp>(blockOp.getLoc(),
-                                                         funcOp, callOperands);
+  auto callOp = IREE::Util::CallOp::create(callerBuilder, blockOp.getLoc(),
+                                           funcOp, callOperands);
   return llvm::to_vector_of<Value>(callOp.getResults());
 }
 
@@ -175,8 +176,9 @@
       initializerBuilder);
 
   // Allow each variant to define how it is loaded and what pipeline it has.
-  auto switchOp = initializerBuilder.create<scf::IndexSwitchOp>(
-      loc, executableType, selectedIndex, caseIndices, caseIndices.size());
+  auto switchOp = scf::IndexSwitchOp::create(initializerBuilder, loc,
+                                             executableType, selectedIndex,
+                                             caseIndices, caseIndices.size());
   for (auto [i, variantOp] : llvm::enumerate(caseVariantOps)) {
     auto &caseBlock = switchOp.getCaseRegions()[i].emplaceBlock();
     auto caseBuilder = OpBuilder::atBlockBegin(&caseBlock);
@@ -202,14 +204,15 @@
                 {SymbolRefAttr::get(variantOp.getSymNameAttr())}),
             constantValues);
 
-    caseBuilder.create<scf::YieldOp>(loc, executableValue);
+    scf::YieldOp::create(caseBuilder, loc, executableValue);
   }
 
   // Fallback for no available variant.
   auto &defaultBlock = switchOp.getDefaultRegion().emplaceBlock();
   auto defaultBuilder = OpBuilder::atBlockBegin(&defaultBlock);
-  Value status = defaultBuilder.create<arith::ConstantIntOp>(
-      loc, static_cast<int>(IREE::Util::StatusCode::Unavailable), 32);
+  Value status = arith::ConstantIntOp::create(
+      defaultBuilder, loc,
+      static_cast<int>(IREE::Util::StatusCode::Unavailable), 32);
   {
     std::string errorStr;
     llvm::raw_string_ostream errorStream(errorStr);
@@ -222,11 +225,11 @@
       errorStream << variantOp.getTargetAttr().getFormat().getValue();
     });
     errorStream << "]";
-    defaultBuilder.create<IREE::Util::StatusCheckOkOp>(loc, status, errorStr);
+    IREE::Util::StatusCheckOkOp::create(defaultBuilder, loc, status, errorStr);
   }
   auto nullValue =
       defaultBuilder.createOrFold<IREE::Util::NullOp>(loc, executableType);
-  defaultBuilder.create<scf::YieldOp>(loc, nullValue);
+  scf::YieldOp::create(defaultBuilder, loc, nullValue);
 
   return switchOp.getResult(0);
 }
@@ -270,7 +273,7 @@
 static void buildDeviceResourceInitializer(DeviceResources &deviceResources,
                                            OpBuilder &moduleBuilder) {
   auto loc = deviceResources.deviceOp.getLoc();
-  auto initializerOp = moduleBuilder.create<IREE::Util::InitializerOp>(loc);
+  auto initializerOp = IREE::Util::InitializerOp::create(moduleBuilder, loc);
   OpBuilder initializerBuilder =
       OpBuilder::atBlockEnd(initializerOp.addEntryBlock());
   Value initializerDevice =
@@ -281,7 +284,7 @@
   // any queue will have execution scheduled but if we know that it won't (such
   // as when sharding) we can reduce runtime load overhead.
   Value initializerAffinity =
-      initializerBuilder.create<arith::ConstantIntOp>(loc, -1, 64);
+      arith::ConstantIntOp::create(initializerBuilder, loc, -1, 64);
 
   // If there are any fallbacks then we need to handle referencing their
   // resources and otherwise will initialize our own.
@@ -298,12 +301,13 @@
           Value fallbackDevice =
               fallbackResources->deviceOp.createLoadOp(loc, caseBuilder)
                   .getLoadedGlobalValue();
-          return caseBuilder.create<IREE::Util::CmpEQOp>(loc, initializerDevice,
-                                                         fallbackDevice);
+          return IREE::Util::CmpEQOp::create(caseBuilder, loc,
+                                             initializerDevice, fallbackDevice);
         },
         initializerBuilder);
-    auto switchOp = initializerBuilder.create<scf::IndexSwitchOp>(
-        loc, TypeRange{}, selectedIndex, caseIndices, caseIndices.size());
+    auto switchOp = scf::IndexSwitchOp::create(initializerBuilder, loc,
+                                               TypeRange{}, selectedIndex,
+                                               caseIndices, caseIndices.size());
     for (auto [fallbackResources, caseRegion] :
          llvm::zip_equal(deviceResources.fallbackDeviceResources,
                          switchOp.getCaseRegions())) {
@@ -311,16 +315,16 @@
       auto caseBuilder = OpBuilder::atBlockBegin(&caseBlock);
       reuseFallbackDeviceResources(deviceResources, *fallbackResources,
                                    initializerDevice, caseBuilder);
-      caseBuilder.create<scf::YieldOp>(loc);
+      scf::YieldOp::create(caseBuilder, loc);
     }
     auto &defaultBlock = switchOp.getDefaultRegion().emplaceBlock();
     auto defaultBuilder = OpBuilder::atBlockBegin(&defaultBlock);
     initializeDeviceResources(deviceResources, moduleBuilder, initializerDevice,
                               initializerAffinity, defaultBuilder);
-    defaultBuilder.create<scf::YieldOp>(loc);
+    scf::YieldOp::create(defaultBuilder, loc);
   }
 
-  initializerBuilder.create<IREE::Util::ReturnOp>(loc);
+  IREE::Util::ReturnOp::create(initializerBuilder, loc);
 }
 
 // Returns zero or more devices globals that may act as fallbacks for the
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeTargetDevices.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeTargetDevices.cpp
index 5d70f1b..f479882 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeTargetDevices.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MaterializeTargetDevices.cpp
@@ -64,8 +64,8 @@
 createDeviceGlobal(Location loc, StringAttr name, Attribute targetAttr,
                    OpBuilder &moduleBuilder) {
   auto deviceType = moduleBuilder.getType<IREE::HAL::DeviceType>();
-  auto globalOp = moduleBuilder.create<IREE::Util::GlobalOp>(
-      loc, name, /*isMutable=*/false, deviceType);
+  auto globalOp = IREE::Util::GlobalOp::create(moduleBuilder, loc, name,
+                                               /*isMutable=*/false, deviceType);
   globalOp.setPrivate();
 
   TypedAttr attrValue;
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MemoizeDeviceQueries.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MemoizeDeviceQueries.cpp
index f3a1468..0a5871b 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MemoizeDeviceQueries.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MemoizeDeviceQueries.cpp
@@ -139,14 +139,14 @@
             getDeviceNamePrefix(deviceOp) + "_query_" + std::to_string(i) +
             "_" + sanitizeSymbolName(anyQueryOp.getCategory()) + "_" +
             sanitizeSymbolName(anyQueryOp.getKey());
-        auto okGlobalOp = moduleBuilder.create<IREE::Util::GlobalOp>(
-            queryLoc, variableName + "_ok",
+        auto okGlobalOp = IREE::Util::GlobalOp::create(
+            moduleBuilder, queryLoc, variableName + "_ok",
             /*isMutable=*/false, moduleBuilder.getI1Type());
         symbolTable.insert(okGlobalOp);
         okGlobalOp.setPrivate();
-        auto valueGlobalOp = moduleBuilder.create<IREE::Util::GlobalOp>(
-            queryLoc, variableName,
-            /*isMutable=*/false, queryType);
+        auto valueGlobalOp =
+            IREE::Util::GlobalOp::create(moduleBuilder, queryLoc, variableName,
+                                         /*isMutable=*/false, queryType);
         symbolTable.insert(valueGlobalOp);
         valueGlobalOp.setPrivate();
 
@@ -178,21 +178,21 @@
       auto fusedLoc = moduleBuilder.getFusedLoc(
           llvm::map_to_vector(queries, [&](auto &query) { return query.loc; }));
       auto initializerOp =
-          moduleBuilder.create<IREE::Util::InitializerOp>(fusedLoc);
+          IREE::Util::InitializerOp::create(moduleBuilder, fusedLoc);
       auto funcBuilder = OpBuilder::atBlockBegin(initializerOp.addEntryBlock());
       Value device =
           deviceOp.createLoadOp(fusedLoc, funcBuilder).getLoadedGlobalValue();
       for (auto [i, queryKey] : llvm::enumerate(deviceQueries.queryKeys)) {
         auto &query = queries[i];
-        auto queryOp = funcBuilder.create<IREE::HAL::DeviceQueryOp>(
-            fusedLoc, funcBuilder.getI1Type(),
+        auto queryOp = IREE::HAL::DeviceQueryOp::create(
+            funcBuilder, fusedLoc, funcBuilder.getI1Type(),
             query.valueGlobalOp.getGlobalType(), device, query.categoryAttr,
             query.keyAttr, query.defaultValueAttr);
         query.okGlobalOp.createStoreOp(fusedLoc, queryOp.getOk(), funcBuilder);
         query.valueGlobalOp.createStoreOp(fusedLoc, queryOp.getValue(),
                                           funcBuilder);
       }
-      funcBuilder.create<IREE::Util::ReturnOp>(fusedLoc);
+      IREE::Util::ReturnOp::create(funcBuilder, fusedLoc);
     }
   }
 };
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MemoizeDeviceSelection.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MemoizeDeviceSelection.cpp
index b269c28..5c586a1 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/MemoizeDeviceSelection.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/MemoizeDeviceSelection.cpp
@@ -70,21 +70,20 @@
   std::string globalNamePrefix = "__allocator_select";
 
   // Insert globals for query results.
-  auto selectedDeviceGlobalOp = moduleBuilder.create<IREE::Util::GlobalOp>(
-      fusedLoc, globalNamePrefix + "_device", /*isMutable=*/false,
-      moduleBuilder.getType<IREE::HAL::DeviceType>());
+  auto selectedDeviceGlobalOp = IREE::Util::GlobalOp::create(
+      moduleBuilder, fusedLoc, globalNamePrefix + "_device",
+      /*isMutable=*/false, moduleBuilder.getType<IREE::HAL::DeviceType>());
   symbolTable.insert(selectedDeviceGlobalOp);
   selectedDeviceGlobalOp.setPrivate();
-  auto selectedQueueAffinityGlobalOp =
-      moduleBuilder.create<IREE::Util::GlobalOp>(
-          fusedLoc, globalNamePrefix + "_affinity", /*isMutable=*/false,
-          moduleBuilder.getIntegerType(64));
+  auto selectedQueueAffinityGlobalOp = IREE::Util::GlobalOp::create(
+      moduleBuilder, fusedLoc, globalNamePrefix + "_affinity",
+      /*isMutable=*/false, moduleBuilder.getIntegerType(64));
   symbolTable.insert(selectedQueueAffinityGlobalOp);
   selectedQueueAffinityGlobalOp.setPrivate();
 
   // Build initializer for the globals.
   auto initializerOp =
-      moduleBuilder.create<IREE::Util::InitializerOp>(fusedLoc);
+      IREE::Util::InitializerOp::create(moduleBuilder, fusedLoc);
   {
     auto initializerBuilder =
         OpBuilder::atBlockBegin(initializerOp.addEntryBlock());
@@ -101,28 +100,27 @@
           deviceGlobalOp.createLoadOp(fusedLoc, initializerBuilder)
               .getLoadedGlobalValue();
       deviceValues.push_back(deviceValue);
-      queueAffinityValues.push_back(
-          initializerBuilder.create<arith::ConstantOp>(fusedLoc,
-                                                       queueAffinity));
+      queueAffinityValues.push_back(arith::ConstantOp::create(
+          initializerBuilder, fusedLoc, queueAffinity));
     }
 
-    Value memoryTypeValue = initializerBuilder.create<IREE::HAL::MemoryTypeOp>(
-        fusedLoc, cast<MemoryTypeBitfieldAttr>(selectOpOperands.memoryType));
+    Value memoryTypeValue = IREE::HAL::MemoryTypeOp::create(
+        initializerBuilder, fusedLoc,
+        cast<MemoryTypeBitfieldAttr>(selectOpOperands.memoryType));
 
-    Value bufferUsageValue =
-        initializerBuilder.create<IREE::HAL::BufferUsageOp>(
-            fusedLoc,
-            cast<BufferUsageBitfieldAttr>(selectOpOperands.bufferUsage));
+    Value bufferUsageValue = IREE::HAL::BufferUsageOp::create(
+        initializerBuilder, fusedLoc,
+        cast<BufferUsageBitfieldAttr>(selectOpOperands.bufferUsage));
 
-    auto newSelectOp = initializerBuilder.create<IREE::HAL::AllocatorSelectOp>(
-        fusedLoc, deviceValues, queueAffinityValues, memoryTypeValue,
-        bufferUsageValue);
+    auto newSelectOp = IREE::HAL::AllocatorSelectOp::create(
+        initializerBuilder, fusedLoc, deviceValues, queueAffinityValues,
+        memoryTypeValue, bufferUsageValue);
 
     selectedDeviceGlobalOp.createStoreOp(
         fusedLoc, newSelectOp.getSelectedDevice(), initializerBuilder);
     selectedQueueAffinityGlobalOp.createStoreOp(
         fusedLoc, newSelectOp.getSelectedQueueAffinity(), initializerBuilder);
-    initializerBuilder.create<IREE::Util::ReturnOp>(fusedLoc);
+    IREE::Util::ReturnOp::create(initializerBuilder, fusedLoc);
   }
 
   // Replace all select ops with global loads.
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/OutlineMemoizeRegions.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/OutlineMemoizeRegions.cpp
index bd1ea39..e457ad1 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/OutlineMemoizeRegions.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/OutlineMemoizeRegions.cpp
@@ -152,8 +152,8 @@
                                 [](Value value) { return value.getType(); }));
   auto funcType =
       moduleBuilder.getFunctionType(argTypes, memoizeOp.getResultTypes());
-  auto funcOp = moduleBuilder.create<IREE::Util::FuncOp>(memoizeOp.getLoc(),
-                                                         name, funcType);
+  auto funcOp = IREE::Util::FuncOp::create(moduleBuilder, memoizeOp.getLoc(),
+                                           name, funcType);
   moduleSymbolTable.insert(funcOp);
   funcOp.setVisibility(SymbolTable::Visibility::Private);
   funcOp.setInliningPolicyAttr(
@@ -210,8 +210,8 @@
   for (auto returnOp :
        llvm::make_early_inc_range(funcOp.getOps<IREE::HAL::ReturnOp>())) {
     OpBuilder returnBuilder(returnOp);
-    returnBuilder.create<IREE::Util::ReturnOp>(returnOp.getLoc(),
-                                               returnOp.getOperands());
+    IREE::Util::ReturnOp::create(returnBuilder, returnOp.getLoc(),
+                                 returnOp.getOperands());
     returnOp.erase();
   }
 
@@ -236,8 +236,8 @@
 
   // Call the function.
   OpBuilder callerBuilder(memoizeOp);
-  auto callOp = callerBuilder.create<IREE::Util::CallOp>(
-      memoizeOp.getLoc(), applyFuncOp, callOperands);
+  auto callOp = IREE::Util::CallOp::create(callerBuilder, memoizeOp.getLoc(),
+                                           applyFuncOp, callOperands);
 
   // Replace memoize op with the results of the function call.
   memoizeOp.replaceAllUsesWith(callOp.getResults());
@@ -261,8 +261,9 @@
         (namePrefix + "_result_" + std::to_string(result.getResultNumber()) +
          "_" + deviceName)
             .str();
-    auto globalOp = moduleBuilder.create<IREE::Util::GlobalOp>(
-        resultLoc, globalName, /*isMutable=*/false, result.getType());
+    auto globalOp =
+        IREE::Util::GlobalOp::create(moduleBuilder, resultLoc, globalName,
+                                     /*isMutable=*/false, result.getType());
     moduleSymbolTable.insert(globalOp);
     globalOp.setVisibility(SymbolTable::Visibility::Private);
     resultGlobalOps.push_back(globalOp);
@@ -271,7 +272,7 @@
   // Create an initializer to call the apply function and store the results into
   // globals.
   auto initializerOp =
-      moduleBuilder.create<IREE::Util::InitializerOp>(memoizeOp.getLoc());
+      IREE::Util::InitializerOp::create(moduleBuilder, memoizeOp.getLoc());
   auto initializerBuilder =
       OpBuilder::atBlockBegin(initializerOp.addEntryBlock());
 
@@ -283,8 +284,9 @@
   Value deviceValue = deviceLoadOp.getLoadedGlobalValue();
   deviceLoadOp.setGlobalImmutable(true);
   mapping.map(memoizeOp.getDevice(), deviceValue);
-  Value queueAffinityValue = initializerBuilder.create<arith::ConstantIntOp>(
-      memoizeOp.getLoc(), memoizeAnalysis.queueAffinity.value_or(-1), 64);
+  Value queueAffinityValue = arith::ConstantIntOp::create(
+      initializerBuilder, memoizeOp.getLoc(),
+      memoizeAnalysis.queueAffinity.value_or(-1), 64);
   mapping.map(memoizeOp.getQueueAffinity(), queueAffinityValue);
 
   // We'll pass the device, affinity, and all dynamic operands to the apply
@@ -307,8 +309,8 @@
          "dynamic values not allowed in memoized initialization functions");
 
   // Call the apply function to produce the memoized results.
-  auto callOp = initializerBuilder.create<IREE::Util::CallOp>(
-      memoizeOp.getLoc(), applyFuncOp, callOperands);
+  auto callOp = IREE::Util::CallOp::create(
+      initializerBuilder, memoizeOp.getLoc(), applyFuncOp, callOperands);
 
   // Store the results to the globals.
   for (auto [result, resultGlobalOp] :
@@ -317,7 +319,7 @@
                                  initializerBuilder);
   }
 
-  initializerBuilder.create<IREE::Util::ReturnOp>(memoizeOp.getLoc());
+  IREE::Util::ReturnOp::create(initializerBuilder, memoizeOp.getLoc());
 
   return resultGlobalOps;
 }
@@ -355,13 +357,13 @@
   Value deviceGlobal =
       deviceGlobalOp.createLoadOp(loc, builder).getLoadedGlobalValue();
   Value isDevice =
-      builder.create<IREE::Util::CmpEQOp>(loc, device, deviceGlobal);
-  auto ifOp = builder.create<scf::IfOp>(
-      loc, resultTypes, isDevice, /*addThenBlock=*/true, /*addElseBlock=*/true);
+      IREE::Util::CmpEQOp::create(builder, loc, device, deviceGlobal);
+  auto ifOp = scf::IfOp::create(builder, loc, resultTypes, isDevice,
+                                /*addThenBlock=*/true, /*addElseBlock=*/true);
 
   auto thenBuilder = ifOp.getThenBodyBuilder();
   scf::ValueVector thenResults = perDevice(deviceGlobalOp, thenBuilder);
-  thenBuilder.create<scf::YieldOp>(loc, thenResults);
+  scf::YieldOp::create(thenBuilder, loc, thenResults);
 
   auto elseBuilder = ifOp.getElseBodyBuilder();
   scf::ValueVector elseResults;
@@ -373,7 +375,7 @@
         remainingDeviceGlobalOps.drop_front(1), perDevice, fallback,
         elseBuilder);
   }
-  elseBuilder.create<scf::YieldOp>(loc, elseResults);
+  scf::YieldOp::create(elseBuilder, loc, elseResults);
 
   return llvm::to_vector_of<Value>(ifOp.getResults());
 }
@@ -412,10 +414,11 @@
         for (auto resultType : resultTypes) {
           Value fallbackValue;
           if (resultType.isIntOrIndexOrFloat()) {
-            fallbackValue = builder.create<arith::ConstantOp>(
-                loc, resultType, builder.getZeroAttr(resultType));
+            fallbackValue = arith::ConstantOp::create(
+                builder, loc, resultType, builder.getZeroAttr(resultType));
           } else {
-            fallbackValue = builder.create<IREE::Util::NullOp>(loc, resultType);
+            fallbackValue =
+                IREE::Util::NullOp::create(builder, loc, resultType);
           }
           fallbackValues.push_back(fallbackValue);
         }
@@ -444,8 +447,8 @@
                                 [](Value value) { return value.getType(); }));
   auto funcType =
       moduleBuilder.getFunctionType(argTypes, memoizeOp.getResultTypes());
-  auto funcOp = moduleBuilder.create<IREE::Util::FuncOp>(memoizeOp.getLoc(),
-                                                         name, funcType);
+  auto funcOp = IREE::Util::FuncOp::create(moduleBuilder, memoizeOp.getLoc(),
+                                           name, funcType);
   moduleSymbolTable.insert(funcOp);
   funcOp.setVisibility(SymbolTable::Visibility::Private);
   auto funcBuilder = OpBuilder::atBlockBegin(funcOp.addEntryBlock());
@@ -483,7 +486,8 @@
       memoizeOp.getLoc(), funcType.getResults(),
       mapping.lookup(memoizeOp.getDevice()), deviceResultMap, funcBuilder);
 
-  funcBuilder.create<IREE::Util::ReturnOp>(memoizeOp.getLoc(), selectedResults);
+  IREE::Util::ReturnOp::create(funcBuilder, memoizeOp.getLoc(),
+                               selectedResults);
 
   return funcOp;
 }
@@ -500,8 +504,8 @@
 
   // Call the function.
   OpBuilder callerBuilder(memoizeOp);
-  auto callOp = callerBuilder.create<IREE::Util::CallOp>(
-      memoizeOp.getLoc(), lookupFuncOp, callOperands);
+  auto callOp = IREE::Util::CallOp::create(callerBuilder, memoizeOp.getLoc(),
+                                           lookupFuncOp, callOperands);
 
   // Replace memoize op with the results of the function call.
   memoizeOp.replaceAllUsesWith(callOp.getResults());
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/RepeatDispatches.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/RepeatDispatches.cpp
index d7ee923..e03a03e 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/RepeatDispatches.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/RepeatDispatches.cpp
@@ -41,8 +41,8 @@
         // will have an over optimistic result. Inserting barriers avoids that,
         // but it assumes that the command buffer has a linear dispatch
         // structure.
-        builder.create<IREE::HAL::CommandBufferExecutionBarrierOp>(
-            op.getLoc(), op.getCommandBuffer(),
+        IREE::HAL::CommandBufferExecutionBarrierOp::create(
+            builder, op.getLoc(), op.getCommandBuffer(),
             IREE::HAL::ExecutionStageBitfield::CommandRetire |
                 IREE::HAL::ExecutionStageBitfield::Dispatch,
             IREE::HAL::ExecutionStageBitfield::CommandIssue |
diff --git a/compiler/src/iree/compiler/Dialect/HAL/Transforms/ResolveTopologyQueries.cpp b/compiler/src/iree/compiler/Dialect/HAL/Transforms/ResolveTopologyQueries.cpp
index 708b3b3..3af535e 100644
--- a/compiler/src/iree/compiler/Dialect/HAL/Transforms/ResolveTopologyQueries.cpp
+++ b/compiler/src/iree/compiler/Dialect/HAL/Transforms/ResolveTopologyQueries.cpp
@@ -160,9 +160,9 @@
     // If we don't have an optimal attribute, we just set the default
     // memory types and buffer usage.
     auto memoryTypeOp =
-        builder.create<IREE::HAL::MemoryTypeOp>(loc, memoryTypes);
+        IREE::HAL::MemoryTypeOp::create(builder, loc, memoryTypes);
     auto bufferUsageOp =
-        builder.create<IREE::HAL::BufferUsageOp>(loc, bufferUsage);
+        IREE::HAL::BufferUsageOp::create(builder, loc, bufferUsage);
     op.replaceAllUsesWith(ValueRange{memoryTypeOp, bufferUsageOp});
     op.erase();
     LLVM_DEBUG(llvm::dbgs()
@@ -192,9 +192,10 @@
                              "with shared usage bits\n");
 
   // Create the resolved memory type and buffer usage ops.
-  auto memoryTypeOp = builder.create<IREE::HAL::MemoryTypeOp>(loc, memoryTypes);
+  auto memoryTypeOp =
+      IREE::HAL::MemoryTypeOp::create(builder, loc, memoryTypes);
   auto bufferUsageOp =
-      builder.create<IREE::HAL::BufferUsageOp>(loc, bufferUsage);
+      IREE::HAL::BufferUsageOp::create(builder, loc, bufferUsage);
   op.replaceAllUsesWith(ValueRange{memoryTypeOp, bufferUsageOp});
   op.erase();
 
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/IR/AggregatedOpInterfaceImpl.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/IR/AggregatedOpInterfaceImpl.cpp
index 4bc6219..dc28a51 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/IR/AggregatedOpInterfaceImpl.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/IR/AggregatedOpInterfaceImpl.cpp
@@ -43,15 +43,15 @@
   SmallVector<utils::IteratorType> iteratorTypes(inputMap.getNumDims(),
                                                  utils::IteratorType::parallel);
 
-  auto genericOp = builder.create<linalg::GenericOp>(
-      loc, value.getType(), scale, value,
+  auto genericOp = linalg::GenericOp::create(
+      builder, loc, value.getType(), scale, value,
       SmallVector<AffineMap>{scaleMap, inputMap}, iteratorTypes,
       [&](OpBuilder &b, Location loc, ValueRange args) {
         // Convert scale to the same datatype as input.
         Value scale = convertScalarToDtype(b, loc, args[0], args[1].getType(),
                                            /*isUnsignedCast=*/false);
-        Value result = b.create<T>(loc, scale, args[1]);
-        b.create<linalg::YieldOp>(loc, result);
+        Value result = T::create(b, loc, scale, args[1]);
+        linalg::YieldOp::create(b, loc, result);
       });
   return genericOp.getResult(0);
 }
@@ -64,16 +64,16 @@
 
   SmallVector<utils::IteratorType> iteratorTypes(rank,
                                                  utils::IteratorType::parallel);
-  auto genericOp = b.create<linalg::GenericOp>(
-      loc, output.getType(), ValueRange{input}, output, maps, iteratorTypes,
+  auto genericOp = linalg::GenericOp::create(
+      b, loc, output.getType(), ValueRange{input}, output, maps, iteratorTypes,
       [&](OpBuilder &b, Location loc, ValueRange args) {
         Value in = convertScalarToDtype(b, loc, args[0], args[1].getType(),
                                         /*isUnsignedCast=*/false);
         // Convert scale to the same datatype as input.
-        Value one =
-            b.create<arith::ConstantOp>(loc, b.getFloatAttr(in.getType(), 1.0));
-        Value result = b.create<arith::DivFOp>(loc, one, in);
-        b.create<linalg::YieldOp>(loc, result);
+        Value one = arith::ConstantOp::create(
+            b, loc, b.getFloatAttr(in.getType(), 1.0));
+        Value result = arith::DivFOp::create(b, loc, one, in);
+        linalg::YieldOp::create(b, loc, result);
       });
   return genericOp.getResult(0);
 }
@@ -88,8 +88,8 @@
 
   SmallVector<utils::IteratorType> iteratorTypes(inputMap.getNumDims(),
                                                  utils::IteratorType::parallel);
-  auto genericOp = builder.create<linalg::GenericOp>(
-      loc, output.getType(), value, output,
+  auto genericOp = linalg::GenericOp::create(
+      builder, loc, output.getType(), value, output,
       SmallVector<AffineMap>{inputMap, outputMap}, iteratorTypes,
       [&](OpBuilder &b, Location loc, ValueRange args) {
         auto srcTy = cast<FloatType>(args[0].getType());
@@ -105,15 +105,15 @@
           // Clamp input to dstTy(usually `fp8`) MAX value to prevent NaNs.
           // We do not clamp for `-MAX` because this function meant to only be
           // used by attention's exp2 who's value is always > 0.
-          Value mx = builder.create<arith::ConstantOp>(
-              loc, builder.getFloatAttr(srcTy, mxDbl));
-          input = b.create<arith::MinimumFOp>(loc, mx, input);
+          Value mx = arith::ConstantOp::create(
+              builder, loc, builder.getFloatAttr(srcTy, mxDbl));
+          input = arith::MinimumFOp::create(b, loc, mx, input);
         }
 
         // Convert scale to the same datatype as input.
         Value trunc = convertScalarToDtype(b, loc, input, dstTy,
                                            /*isUnsignedCast=*/false);
-        b.create<linalg::YieldOp>(loc, trunc);
+        linalg::YieldOp::create(b, loc, trunc);
       });
   return genericOp.getResult(0);
 }
@@ -134,15 +134,15 @@
     iteratorTypes[pos] = utils::IteratorType::parallel;
   }
 
-  auto genericOp = builder.create<linalg::GenericOp>(
-      loc, output.getType(), input, output,
+  auto genericOp = linalg::GenericOp::create(
+      builder, loc, output.getType(), input, output,
       SmallVector<AffineMap>{inputMap, outputMap}, iteratorTypes,
       [&](OpBuilder &b, Location loc, ValueRange args) {
         // Convert input to the same datatype as acc.
         Value in = convertScalarToDtype(b, loc, args[0], args[1].getType(),
                                         /*isUnsignedCast=*/false);
-        Value result = b.create<T>(loc, in, args[1]);
-        b.create<linalg::YieldOp>(loc, result);
+        Value result = T::create(b, loc, in, args[1]);
+        linalg::YieldOp::create(b, loc, result);
       });
 
   return genericOp.getResult(0);
@@ -166,8 +166,8 @@
     iteratorTypes[pos] = utils::IteratorType::parallel;
   }
 
-  auto genericOp = builder.create<linalg::GenericOp>(
-      loc, acc.getType(), SmallVector<Value>{lhs, rhs}, acc,
+  auto genericOp = linalg::GenericOp::create(
+      builder, loc, acc.getType(), SmallVector<Value>{lhs, rhs}, acc,
       SmallVector<AffineMap>{lhsMap, rhsMap, accMap}, iteratorTypes,
       [&](OpBuilder &b, Location loc, ValueRange args) {
         // Cast inputs to match output datatype.
@@ -175,9 +175,9 @@
                                          /*isUnsignedCast=*/false);
         Value rhs = convertScalarToDtype(b, loc, args[1], args[2].getType(),
                                          /*isUnsignedCast=*/false);
-        Value mul = b.create<arith::MulFOp>(loc, lhs, rhs);
-        Value add = b.create<arith::AddFOp>(loc, mul, args[2]);
-        b.create<linalg::YieldOp>(loc, add);
+        Value mul = arith::MulFOp::create(b, loc, lhs, rhs);
+        Value add = arith::AddFOp::create(b, loc, mul, args[2]);
+        linalg::YieldOp::create(b, loc, add);
       });
 
   return genericOp.getResult(0);
@@ -191,15 +191,16 @@
   SmallVector<AffineMap> indexingMaps{identityMap};
   SmallVector<utils::IteratorType> iteratorTypes(rank,
                                                  utils::IteratorType::parallel);
-  auto genericOp = builder.create<linalg::GenericOp>(
-      loc, value.getType(), ValueRange{}, value, indexingMaps, iteratorTypes);
+  auto genericOp =
+      linalg::GenericOp::create(builder, loc, value.getType(), ValueRange{},
+                                value, indexingMaps, iteratorTypes);
   auto &dstRegion = genericOp.getRegion();
   builder.cloneRegionBefore(region, dstRegion, dstRegion.end());
   {
     OpBuilder::InsertionGuard withinRegion(builder);
     builder.setInsertionPoint(dstRegion.back().getTerminator());
-    builder.create<linalg::YieldOp>(
-        loc, dstRegion.back().getTerminator()->getOperands());
+    linalg::YieldOp::create(builder, loc,
+                            dstRegion.back().getTerminator()->getOperands());
     dstRegion.back().getTerminator()->erase();
   }
   return genericOp.getResult(0);
@@ -216,13 +217,15 @@
   SmallVector<utils::IteratorType> iteratorTypes(qkMap.getNumDims(),
                                                  utils::IteratorType::parallel);
 
-  Value zero = builder.create<arith::ConstantOp>(
-      loc, builder.getFloatAttr(getElementTypeOrSelf(qk.getType()), 0.0));
-  Value negInf = builder.create<arith::ConstantOp>(
-      loc, builder.getFloatAttr(getElementTypeOrSelf(qk.getType()),
-                                -std::numeric_limits<double>::infinity()));
-  auto genericOp = builder.create<linalg::GenericOp>(
-      loc, qk.getType(), SmallVector<Value>{mask}, qk,
+  Value zero = arith::ConstantOp::create(
+      builder, loc,
+      builder.getFloatAttr(getElementTypeOrSelf(qk.getType()), 0.0));
+  Value negInf = arith::ConstantOp::create(
+      builder, loc,
+      builder.getFloatAttr(getElementTypeOrSelf(qk.getType()),
+                           -std::numeric_limits<double>::infinity()));
+  auto genericOp = linalg::GenericOp::create(
+      builder, loc, qk.getType(), SmallVector<Value>{mask}, qk,
       SmallVector<AffineMap>{maskMap, qkMap}, iteratorTypes,
       [&](OpBuilder &b, Location loc, ValueRange args) {
         Value qkVal = args[1];
@@ -233,23 +236,23 @@
         if (maskValType.isInteger()) {
           if (maskValType.getIntOrFloatBitWidth() != 1) {
             maskVal =
-                b.create<arith::TruncIOp>(loc, builder.getI1Type(), maskVal);
+                arith::TruncIOp::create(b, loc, builder.getI1Type(), maskVal);
           }
-          maskVal = b.create<arith::SelectOp>(loc, maskVal, zero, negInf);
+          maskVal = arith::SelectOp::create(b, loc, maskVal, zero, negInf);
         } else {
           maskVal = convertScalarToDtype(b, loc, maskVal, qkVal.getType(),
                                          /*isUnsignedCast=*/false);
           // Scaling to compensate for base-2 softmax
-          Value log2e = b.create<arith::ConstantOp>(
-              loc, b.getFloatAttr(qkVal.getType(), M_LOG2E));
-          maskVal = b.create<arith::MulFOp>(loc, maskVal, log2e);
+          Value log2e = arith::ConstantOp::create(
+              b, loc, b.getFloatAttr(qkVal.getType(), M_LOG2E));
+          maskVal = arith::MulFOp::create(b, loc, maskVal, log2e);
         }
         // Finally, set the returned value to the qk element plus the mask
         // element (or 0/-infinity if bool mask). We opt for a AddFOp (instead
         // of a SelectFOp to stay consistent with the additive definition of
         // attention masking)
-        Value add = b.create<arith::AddFOp>(loc, qkVal, maskVal);
-        b.create<linalg::YieldOp>(loc, add);
+        Value add = arith::AddFOp::create(b, loc, qkVal, maskVal);
+        linalg::YieldOp::create(b, loc, add);
       });
 
   return genericOp.getResult(0);
@@ -266,16 +269,16 @@
 
   SmallVector<utils::IteratorType> iteratorTypes(inputMap.getNumDims(),
                                                  utils::IteratorType::parallel);
-  auto genericOp = builder.create<linalg::GenericOp>(
-      loc, output.getType(), input, output,
+  auto genericOp = linalg::GenericOp::create(
+      builder, loc, output.getType(), input, output,
       SmallVector<AffineMap>{inputMap, outputMap}, iteratorTypes,
       [&](OpBuilder &b, Location loc, ValueRange args) {
         // Convert input to the same datatype as output.
         Value in = convertScalarToDtype(b, loc, args[0], args[1].getType(),
                                         /*isUnsignedCast=*/false);
-        Value diff = b.create<arith::SubFOp>(loc, args[1], in);
-        Value weight = b.create<math::Exp2Op>(loc, diff);
-        b.create<linalg::YieldOp>(loc, weight);
+        Value diff = arith::SubFOp::create(b, loc, args[1], in);
+        Value weight = math::Exp2Op::create(b, loc, diff);
+        linalg::YieldOp::create(b, loc, weight);
       });
   return genericOp.getResult(0);
 }
@@ -317,9 +320,9 @@
   // multiply the scale by log2(e). We use exp2 instead of exp as most platforms
   // have better support for exp2 (we verified that we gain some speedup on
   // some GPUs).
-  Value log2e = b.create<arith::ConstantOp>(
-      loc, b.getFloatAttr(scale.getType(), M_LOG2E));
-  scale = b.create<arith::MulFOp>(loc, scale, log2e);
+  Value log2e = arith::ConstantOp::create(
+      b, loc, b.getFloatAttr(scale.getType(), M_LOG2E));
+  scale = arith::MulFOp::create(b, loc, scale, log2e);
 
   auto qETy = getElementTypeOrSelf(query.getType());
 
@@ -350,9 +353,9 @@
 
   // S = Q @ K
   // SMap = QMap @ KMap
-  Value emptyS = b.create<tensor::EmptyOp>(loc, sSizes, sElementType);
-  Value sZero = b.create<arith::ConstantOp>(loc, b.getZeroAttr(sElementType));
-  Value s = b.create<linalg::FillOp>(loc, sZero, emptyS).getResult(0);
+  Value emptyS = tensor::EmptyOp::create(b, loc, sSizes, sElementType);
+  Value sZero = arith::ConstantOp::create(b, loc, b.getZeroAttr(sElementType));
+  Value s = linalg::FillOp::create(b, loc, sZero, emptyS).getResult(0);
 
   s = computeMatmul(b, loc, qMap, kMap, sMap, query, key, s);
   if (qkAttrs) {
@@ -379,8 +382,8 @@
     double mx =
         APFloat::getLargest(fpTy.getFloatSemantics(), /*Negative=*/false)
             .convertToDouble();
-    Value offset = b.create<arith::ConstantOp>(
-        loc, b.getFloatAttr(sElementType, clAttentionSoftmaxMax / mx));
+    Value offset = arith::ConstantOp::create(
+        b, loc, b.getFloatAttr(sElementType, clAttentionSoftmaxMax / mx));
     s = elementwiseValueInPlace<arith::AddFOp>(b, loc, sMap, scaleMap, s,
                                                offset);
   }
@@ -450,7 +453,7 @@
   SmallVector<OpFoldResult> rowRedSize =
       applyPermutationMap<OpFoldResult>(maxMap, sizes);
 
-  Value rowRedEmpty = b.create<tensor::EmptyOp>(loc, rowRedSize, f32Type);
+  Value rowRedEmpty = tensor::EmptyOp::create(b, loc, rowRedSize, f32Type);
 
   Value accInit = arith::getIdentityValue(arith::AtomicRMWKind::addf,
                                           getElementTypeOrSelf(output), b, loc,
@@ -462,12 +465,12 @@
       arith::getIdentityValue(arith::AtomicRMWKind::addf, f32Type, b, loc);
 
   Value accFill =
-      b.create<linalg::FillOp>(loc, ValueRange{accInit}, output).getResult(0);
+      linalg::FillOp::create(b, loc, ValueRange{accInit}, output).getResult(0);
   Value maxFill =
-      b.create<linalg::FillOp>(loc, ValueRange{maxInit}, rowRedEmpty)
+      linalg::FillOp::create(b, loc, ValueRange{maxInit}, rowRedEmpty)
           .getResult(0);
   Value sumFill =
-      b.create<linalg::FillOp>(loc, ValueRange{sumInit}, rowRedEmpty)
+      linalg::FillOp::create(b, loc, ValueRange{sumInit}, rowRedEmpty)
           .getResult(0);
 
   // max = rowMax(S)
@@ -493,7 +496,7 @@
   auto pETy = getElementTypeOrSelf(p.getType());
   auto vETy = getElementTypeOrSelf(value.getType());
   if (pETy != vETy && isa<FloatType>(vETy)) {
-    Value convertP = b.create<tensor::EmptyOp>(loc, sSizes, vETy);
+    Value convertP = tensor::EmptyOp::create(b, loc, sSizes, vETy);
     p = truncateFloat(b, loc, pMap, pMap, p, convertP, lowPrecision);
   }
 
@@ -589,7 +592,7 @@
   auto pETy = getElementTypeOrSelf(p.getType());
   auto vETy = getElementTypeOrSelf(value.getType());
   if (pETy != vETy && isa<FloatType>(vETy)) {
-    Value convertP = b.create<tensor::EmptyOp>(loc, sSizes, vETy);
+    Value convertP = tensor::EmptyOp::create(b, loc, sSizes, vETy);
     p = truncateFloat(b, loc, pMap, pMap, p, convertP, lowPrecision);
   }
 
@@ -812,9 +815,9 @@
     kIndex = addOfrs(b, nestedLoc, kIndex, ivOffset);
   }
   ValueRange delinKOffset =
-      b.create<affine::AffineDelinearizeIndexOp>(
-           nestedLoc, getValueOrCreateConstantIndexOp(b, loc, kIndex), kBasis,
-           /*hasOuterBound=*/true)
+      affine::AffineDelinearizeIndexOp::create(
+          b, nestedLoc, getValueOrCreateConstantIndexOp(b, loc, kIndex), kBasis,
+          /*hasOuterBound=*/true)
           .getResults();
   // Split the delinearized offsets into the window offsets (for M offsets)
   // and the K offsets for the input tensor based on the layout.
@@ -852,10 +855,10 @@
   // `mBasis` contains the basis for the iteration space of result of the
   // convolution op (i.e., basis for result H and W dims).
   ValueRange delinMOffset =
-      b.create<affine::AffineDelinearizeIndexOp>(
-           nestedLoc, getValueOrCreateConstantIndexOp(b, loc, linearMOffset),
-           mBasis,
-           /*hasOuterBound=*/true)
+      affine::AffineDelinearizeIndexOp::create(
+          b, nestedLoc, getValueOrCreateConstantIndexOp(b, loc, linearMOffset),
+          mBasis,
+          /*hasOuterBound=*/true)
           .getResults();
 
   // Compute the final offsets into the input tensor.
@@ -927,8 +930,8 @@
   dispatchIndexOpFoldResults(inputTileSizes, tileSizeDynamic, tileSizeStatic);
   auto extractType = cast<RankedTensorType>(outputType.clone(tileSizeStatic));
   auto extract =
-      b.create<tensor::ExtractSliceOp>(nestedLoc, extractType, inputSlice,
-                                       sliceOffsets, sliceSizes, sliceStrides);
+      tensor::ExtractSliceOp::create(b, nestedLoc, extractType, inputSlice,
+                                     sliceOffsets, sliceSizes, sliceStrides);
 
   // Insert the slice into the destination tensor.
   sliceOffsets = SmallVector<OpFoldResult>(outputRank, zero);
@@ -957,10 +960,10 @@
     ArrayRef<int64_t> extractShape = extractType.getShape();
     SmallVector<int64_t> emptyShape =
         applyPermutation(extractShape, transposePerm);
-    auto empty = b.create<tensor::EmptyOp>(nestedLoc, emptyShape,
-                                           outputType.getElementType());
-    auto transposeOp =
-        b.create<linalg::TransposeOp>(nestedLoc, extract, empty, transposePerm);
+    auto empty = tensor::EmptyOp::create(b, nestedLoc, emptyShape,
+                                         outputType.getElementType());
+    auto transposeOp = linalg::TransposeOp::create(b, nestedLoc, extract, empty,
+                                                   transposePerm);
     inputForInsert = transposeOp->getResult(0);
   } else {
     // Insert a `linalg.copy` so there is something to vectorize in the
@@ -968,16 +971,16 @@
     // do not get vectorized, and the sequence becomes a scalar memref.copy.
     // This memref.copy could be vectorized after bufferization, but it is
     // probably better to vectorize during generic vectorization.
-    Value copyDest = b.create<tensor::ExtractSliceOp>(
-        nestedLoc, extractType, loopNest.loops.back().getRegionIterArg(0),
+    Value copyDest = tensor::ExtractSliceOp::create(
+        b, nestedLoc, extractType, loopNest.loops.back().getRegionIterArg(0),
         sliceOffsets, sliceSizes, sliceStrides);
     auto copiedSlice =
-        b.create<linalg::CopyOp>(nestedLoc, extract.getResult(), copyDest);
+        linalg::CopyOp::create(b, nestedLoc, extract.getResult(), copyDest);
     inputForInsert = copiedSlice.getResult(0);
   }
 
-  auto insert = b.create<tensor::InsertSliceOp>(
-      nestedLoc, inputForInsert, loopNest.loops.back().getRegionIterArg(0),
+  auto insert = tensor::InsertSliceOp::create(
+      b, nestedLoc, inputForInsert, loopNest.loops.back().getRegionIterArg(0),
       sliceOffsets, sliceSizes, sliceStrides);
   auto yieldOp =
       cast<scf::YieldOp>(loopNest.loops.back().getBody()->getTerminator());
@@ -1006,7 +1009,7 @@
              isa<RankedTensorType>(argument.getType()) &&
              "expected operand and arguments to be `RankedTensorType`");
       Value cast =
-          builder.create<tensor::CastOp>(loc, argument.getType(), operand);
+          tensor::CastOp::create(builder, loc, argument.getType(), operand);
       argReplacements.push_back(cast);
     } else {
       argReplacements.push_back(operand);
@@ -1029,7 +1032,7 @@
              isa<RankedTensorType>(result.getType()) &&
              "expected yielded value and result to be `RankedTensorType`");
       Value cast =
-          builder.create<tensor::CastOp>(loc, result.getType(), yieldedVal);
+          tensor::CastOp::create(builder, loc, result.getType(), yieldedVal);
       customOpReplacements.push_back(cast);
     } else {
       customOpReplacements.push_back(yieldedVal);
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/IR/LinalgExtOps.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/IR/LinalgExtOps.cpp
index 10e98f6..09a7338 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/IR/LinalgExtOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/IR/LinalgExtOps.cpp
@@ -316,7 +316,7 @@
     changeNeeded = true;
     // Get the new operand value given its size and element type by
     // casting it.
-    Value newOperand = rewriter.create<tensor::CastOp>(loc, resultType, src);
+    Value newOperand = tensor::CastOp::create(rewriter, loc, resultType, src);
     unsigned index = opOperand->getOperandNumber();
     newOperands[index] = newOperand;
   }
@@ -375,10 +375,10 @@
          llvm::zip_equal(op->getResults(), newOp->getResults())) {
       Type newType = newResult.getType();
       Type oldType = oldResult.getType();
-      replacements.push_back((newType != oldType)
-                                 ? rewriter.create<tensor::CastOp>(
-                                       loc, oldType, cast<Value>(newResult))
-                                 : cast<Value>(newResult));
+      replacements.push_back(
+          (newType != oldType) ? tensor::CastOp::create(rewriter, loc, oldType,
+                                                        cast<Value>(newResult))
+                               : cast<Value>(newResult));
     }
     rewriter.replaceOp(op, replacements);
     return success();
@@ -515,13 +515,13 @@
     }
 
     // Get all `indexDepth` indices as scalars.
-    SmallVector<Value> indices(indicesShape.size(),
-                               rewriter.create<arith::ConstantIndexOp>(loc, 0));
+    SmallVector<Value> indices(
+        indicesShape.size(), arith::ConstantIndexOp::create(rewriter, loc, 0));
     SmallVector<OpFoldResult> offsets(gatherOp.getIndexDepth());
     for (int64_t i = 0; i < gatherOp.getIndexDepth(); ++i) {
-      indices.back() = rewriter.create<arith::ConstantIndexOp>(loc, i);
-      Value elem = rewriter.create<tensor::ExtractOp>(
-          loc, gatherOp.getIndices(), indices);
+      indices.back() = arith::ConstantIndexOp::create(rewriter, loc, i);
+      Value elem = tensor::ExtractOp::create(rewriter, loc,
+                                             gatherOp.getIndices(), indices);
       offsets[i] =
           rewriter
               .create<arith::IndexCastOp>(loc, rewriter.getIndexType(), elem)
@@ -544,8 +544,9 @@
     }
     auto resultType =
         cast<RankedTensorType>(gatherOp.getSourceType()).clone(resultShape);
-    auto sliceOp = rewriter.create<tensor::ExtractSliceOp>(
-        loc, resultType, gatherOp.getSource(), offsets, sizes, strides);
+    auto sliceOp = tensor::ExtractSliceOp::create(rewriter, loc, resultType,
+                                                  gatherOp.getSource(), offsets,
+                                                  sizes, strides);
 
     // `sliceOp` may differ from the expected result type by leading unit
     // dimensions. Reshape so that the types match.
@@ -596,7 +597,7 @@
     resultType.push_back(output.getType());
   }
   auto mapScatterOp =
-      builder.create<MapScatterOp>(loc, resultType, input, output);
+      MapScatterOp::create(builder, loc, resultType, input, output);
 
   // Add the transformation block with an identity transformation.
   Region &region = mapScatterOp.getTransformationRegion();
@@ -607,10 +608,10 @@
   Block *block =
       builder.createBlock(&region, region.end(), indexTypes, blockArgLocs);
   SmallVector<Value> yieldedValues(block->getArguments());
-  Value mask = builder.create<arith::ConstantIntOp>(loc, /*value=*/1,
-                                                    /*width=*/1);
+  Value mask = arith::ConstantIntOp::create(builder, loc, /*value=*/1,
+                                            /*width=*/1);
   yieldedValues.push_back(mask);
-  builder.create<IREE::LinalgExt::YieldOp>(loc, yieldedValues);
+  IREE::LinalgExt::YieldOp::create(builder, loc, yieldedValues);
   return mapScatterOp;
 }
 
@@ -874,8 +875,8 @@
 
     // Create new op using only operands associated to used results or block
     // args.
-    auto newSortOp = rewriter.create<IREE::LinalgExt::SortOp>(
-        loc, usedResultTypes,
+    auto newSortOp = IREE::LinalgExt::SortOp::create(
+        rewriter, loc, usedResultTypes,
         /*inputs=*/ValueRange{}, usedOperands, sortOp.getDimension());
     newSortOp.getRegion().takeBody(sortOp.getRegion());
     newSortOp.getRegion().front().eraseArguments(eraseArg);
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/IR/TilingInterfaceImpl.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/IR/TilingInterfaceImpl.cpp
index b65a914..d74ebc2 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/IR/TilingInterfaceImpl.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/IR/TilingInterfaceImpl.cpp
@@ -224,7 +224,7 @@
                                                       Location loc,
                                                       ValueRange ivs) {
   auto indexDepth = getIndexDepth();
-  Value update = b.create<memref::LoadOp>(loc, getUpdates(), ivs);
+  Value update = memref::LoadOp::create(b, loc, getUpdates(), ivs);
   SmallVector<Value> starts;
   SmallVector<Value> loadIndices;
   append_range(loadIndices, ivs.take_front(getBatchRank()));
@@ -246,19 +246,19 @@
   }
   for (auto i : llvm::seq<unsigned>(0, indexDepth)) {
     if (getIndicesType().getRank() > getBatchRank()) {
-      loadIndices.back() = b.create<arith::ConstantIndexOp>(loc, i);
+      loadIndices.back() = arith::ConstantIndexOp::create(b, loc, i);
     }
-    Value idx = b.create<memref::LoadOp>(loc, getIndices(), loadIndices);
-    Value ret = b.create<arith::IndexCastOp>(loc, b.getIndexType(), idx);
+    Value idx = memref::LoadOp::create(b, loc, getIndices(), loadIndices);
+    Value ret = arith::IndexCastOp::create(b, loc, b.getIndexType(), idx);
 
     auto dim = dimMap[i];
 
     if (starts[dim])
-      ret = b.create<arith::AddIOp>(loc, ret, starts[dim]);
+      ret = arith::AddIOp::create(b, loc, ret, starts[dim]);
     starts[dim] = ret;
   }
 
-  Value init = b.create<memref::LoadOp>(loc, getOriginal(), starts);
+  Value init = memref::LoadOp::create(b, loc, getOriginal(), starts);
 
   IRMapping bvm;
   Block &block = getRegion().front();
@@ -269,8 +269,8 @@
   }
   // The last op is linalg_ext.yield op. Store the operand to
   // destination.
-  b.create<memref::StoreOp>(
-      loc, bvm.lookupOrDefault(block.getTerminator()->getOperand(0)),
+  memref::StoreOp::create(
+      b, loc, bvm.lookupOrDefault(block.getTerminator()->getOperand(0)),
       getOriginal(), starts);
   return success();
 }
@@ -398,21 +398,21 @@
   ArrayRef<int64_t> dimMap = getDimensionMap();
   for (int64_t i = 0; i < indexDepth; ++i) {
     if (hasIndexDim) {
-      loadIndices.back() = b.create<arith::ConstantIndexOp>(loc, i);
+      loadIndices.back() = arith::ConstantIndexOp::create(b, loc, i);
     }
-    Value idx = b.create<memref::LoadOp>(loc, getIndices(), loadIndices);
-    Value ret = b.create<arith::IndexCastOp>(loc, b.getIndexType(), idx);
+    Value idx = memref::LoadOp::create(b, loc, getIndices(), loadIndices);
+    Value ret = arith::IndexCastOp::create(b, loc, b.getIndexType(), idx);
     auto dim = dimMap[i];
     if (starts[dim])
-      ret = b.create<arith::AddIOp>(loc, ret, starts[dim]);
+      ret = arith::AddIOp::create(b, loc, ret, starts[dim]);
     starts[dim] = ret;
   }
 
-  Value init = b.create<memref::LoadOp>(loc, getSource(), starts);
+  Value init = memref::LoadOp::create(b, loc, getSource(), starts);
 
   // The last op is linalg_ext.yield op. Store the operand to
   // destination.
-  b.create<memref::StoreOp>(loc, init, getOutput(), ivs);
+  memref::StoreOp::create(b, loc, init, getOutput(), ivs);
   return success();
 }
 
@@ -540,12 +540,12 @@
     ArrayRef<Value> storeIndices = yieldedValues.drop_back();
     auto thenBuilder = [&](OpBuilder &ifBuilder, Location ifLoc) {
       SmallVector<OpFoldResult> ivsOfr(ivs);
-      Value input = ifBuilder.create<memref::LoadOp>(ifLoc, getInput(), ivs);
-      ifBuilder.create<memref::StoreOp>(ifLoc, input, getOutput(),
-                                        storeIndices);
-      ifBuilder.create<scf::YieldOp>(ifLoc);
+      Value input = memref::LoadOp::create(ifBuilder, ifLoc, getInput(), ivs);
+      memref::StoreOp::create(ifBuilder, ifLoc, input, getOutput(),
+                              storeIndices);
+      scf::YieldOp::create(ifBuilder, ifLoc);
     };
-    nestedBuilder.create<scf::IfOp>(nestedLoc, ifCond, thenBuilder);
+    scf::IfOp::create(nestedBuilder, nestedLoc, ifCond, thenBuilder);
   };
   inlineMapScatterBody(b, loc, ivs, bodyBuilder);
   return success();
@@ -621,26 +621,28 @@
   SmallVector<Value> indices, sortBlkArgs;
   indices.append(ivs.begin(), ivs.end());
   // Bubble sort innermost loop.
-  Value zero = b.create<arith::ConstantIndexOp>(loc, 0);
-  Value one = b.create<arith::ConstantIndexOp>(loc, 1);
+  Value zero = arith::ConstantIndexOp::create(b, loc, 0);
+  Value one = arith::ConstantIndexOp::create(b, loc, 1);
   Value ub;
   if (getOperandType(0).isDynamicDim(sortDim)) {
-    ub = b.create<memref::DimOp>(loc, getOperand(0), sortDim);
+    ub = memref::DimOp::create(b, loc, getOperand(0), sortDim);
   } else {
-    ub = b.create<arith::ConstantIndexOp>(
-        loc, getOperandType(0).getDimSize(sortDim));
+    ub = arith::ConstantIndexOp::create(b, loc,
+                                        getOperandType(0).getDimSize(sortDim));
   }
-  ub = b.create<arith::SubIOp>(loc, ub, one);
-  auto scfFor = b.create<scf::ForOp>(
-      loc, zero, ub, one, ValueRange{},
+  ub = arith::SubIOp::create(b, loc, ub, one);
+  auto scfFor = scf::ForOp::create(
+      b, loc, zero, ub, one, ValueRange{},
       [&](OpBuilder &b, Location loc, Value iv, ValueRange iters) {
         SmallVector<Value> indices(ivs);
-        Value ivPlusOne = b.create<arith::AddIOp>(loc, iv, one);
+        Value ivPlusOne = arith::AddIOp::create(b, loc, iv, one);
         for (auto output : getDpsInits()) {
           indices[sortDim] = iv;
-          sortBlkArgs.push_back(b.create<memref::LoadOp>(loc, output, indices));
+          sortBlkArgs.push_back(
+              memref::LoadOp::create(b, loc, output, indices));
           indices[sortDim] = ivPlusOne;
-          sortBlkArgs.push_back(b.create<memref::LoadOp>(loc, output, indices));
+          sortBlkArgs.push_back(
+              memref::LoadOp::create(b, loc, output, indices));
         }
       });
 
@@ -662,28 +664,28 @@
 
   OpBuilder::InsertionGuard g(b);
   b.setInsertionPointToEnd(&region.front());
-  b.create<scf::IfOp>(
-      loc, cond,
+  scf::IfOp::create(
+      b, loc, cond,
       [&](OpBuilder &b, Location loc) {
         // Do not swap the pairs if true.
-        b.create<scf::YieldOp>(loc);
+        scf::YieldOp::create(b, loc);
       },
       [&](OpBuilder &b, Location loc) {
         // Swap the pairs if false.
         SmallVector<Value> indices(ivs);
         Value ivPlusOne =
-            b.create<arith::AddIOp>(loc, scfFor.getInductionVar(), one);
+            arith::AddIOp::create(b, loc, scfFor.getInductionVar(), one);
         for (int i = 0, e = getNumDpsInits(); i < e; ++i) {
           Value v1 = sortBlkArgs[i * 2];
           Value v2 = sortBlkArgs[i * 2 + 1];
           indices[sortDim] = scfFor.getInductionVar();
-          b.create<memref::StoreOp>(loc, v2, getDpsInits()[i], indices);
+          memref::StoreOp::create(b, loc, v2, getDpsInits()[i], indices);
           indices[sortDim] = ivPlusOne;
-          b.create<memref::StoreOp>(loc, v1, getDpsInits()[i], indices);
+          memref::StoreOp::create(b, loc, v1, getDpsInits()[i], indices);
         }
-        b.create<scf::YieldOp>(loc);
+        scf::YieldOp::create(b, loc);
       });
-  b.create<scf::YieldOp>(loc);
+  scf::YieldOp::create(b, loc);
   return success();
 }
 
@@ -703,8 +705,8 @@
 SmallVector<Range> FftOp::getIterationDomain(OpBuilder &builder) {
   SmallVector<Range> res;
   Location loc = getLoc();
-  Value zero = builder.create<arith::ConstantIndexOp>(loc, 0);
-  Value one = builder.create<arith::ConstantIndexOp>(loc, 1);
+  Value zero = arith::ConstantIndexOp::create(builder, loc, 0);
+  Value one = arith::ConstantIndexOp::create(builder, loc, 1);
   for (auto [idx, val] : llvm::enumerate(getOperandShape().drop_back())) {
     OpFoldResult size;
     if (ShapedType::isDynamic(val)) {
@@ -716,7 +718,7 @@
   }
 
   OpFoldResult size = getDim(builder, loc, getReal(), getOperandRank() - 1);
-  Value stride = builder.create<arith::ShLIOp>(loc, one, getStage());
+  Value stride = arith::ShLIOp::create(builder, loc, one, getStage());
   res.emplace_back(Range{/*offset=*/zero, size, /*stride=*/stride});
   return res;
 }
@@ -729,18 +731,18 @@
 
   auto f32Type = b.getF32Type();
   auto indexToF32 = [](OpBuilder &builder, Location loc, Value v) -> Value {
-    v = builder.create<arith::IndexCastOp>(loc, builder.getI32Type(), v);
-    return builder.create<arith::SIToFPOp>(loc, builder.getF32Type(), v);
+    v = arith::IndexCastOp::create(builder, loc, builder.getI32Type(), v);
+    return arith::SIToFPOp::create(builder, loc, builder.getF32Type(), v);
   };
 
   // We will need exp(-2 * PI * j / m * I), compute "-2 * PI / m" for imag part
   // first.
-  Value coeff = b.create<arith::ConstantFloatOp>(
-      loc, f32Type, llvm::APFloat(static_cast<float>(-2 * acos(-1))));
-  coeff = b.create<arith::DivFOp>(loc, coeff, indexToF32(b, loc, wholeSize));
+  Value coeff = arith::ConstantFloatOp::create(
+      b, loc, f32Type, llvm::APFloat(static_cast<float>(-2 * acos(-1))));
+  coeff = arith::DivFOp::create(b, loc, coeff, indexToF32(b, loc, wholeSize));
 
-  b.create<linalg::GenericOp>(
-      loc, TypeRange{}, ValueRange{}, operands, maps, getLoopIteratorTypes(),
+  linalg::GenericOp::create(
+      b, loc, TypeRange{}, ValueRange{}, operands, maps, getLoopIteratorTypes(),
       [&](OpBuilder &b, Location loc, ValueRange args) {
         Value lhsReal = args[0];
         Value lhsImag = args[1];
@@ -748,29 +750,29 @@
         Value rhsImag = args[3];
 
         // Compute "-2 * PI / m * j"
-        Value w = b.create<arith::MulFOp>(
-            loc, coeff,
-            indexToF32(b, loc, b.create<linalg::IndexOp>(loc, rank - 1)));
-        Value wReal = b.create<math::CosOp>(loc, w);
-        Value wImag = b.create<math::SinOp>(loc, w);
+        Value w = arith::MulFOp::create(
+            b, loc, coeff,
+            indexToF32(b, loc, linalg::IndexOp::create(b, loc, rank - 1)));
+        Value wReal = math::CosOp::create(b, loc, w);
+        Value wImag = math::SinOp::create(b, loc, w);
 
         // t = w * a[k + j + mh];
         // ->  (x + yi)(u + vi) = (xu - yv) + (xv + yu)i
-        Value xu = b.create<arith::MulFOp>(loc, wReal, rhsReal);
-        Value yv = b.create<arith::MulFOp>(loc, wImag, rhsImag);
-        Value xv = b.create<arith::MulFOp>(loc, wReal, rhsImag);
-        Value yu = b.create<arith::MulFOp>(loc, wImag, rhsReal);
-        Value tReal = b.create<arith::SubFOp>(loc, xu, yv);
-        Value tImag = b.create<arith::AddFOp>(loc, xv, yu);
+        Value xu = arith::MulFOp::create(b, loc, wReal, rhsReal);
+        Value yv = arith::MulFOp::create(b, loc, wImag, rhsImag);
+        Value xv = arith::MulFOp::create(b, loc, wReal, rhsImag);
+        Value yu = arith::MulFOp::create(b, loc, wImag, rhsReal);
+        Value tReal = arith::SubFOp::create(b, loc, xu, yv);
+        Value tImag = arith::AddFOp::create(b, loc, xv, yu);
 
         // cplx u = a[k + j];
         // a[k + j] = u + t;
         // a[k + j + mh] = u - t;
-        Value r1 = b.create<arith::AddFOp>(loc, lhsReal, tReal);
-        Value r2 = b.create<arith::AddFOp>(loc, lhsImag, tImag);
-        Value r3 = b.create<arith::SubFOp>(loc, lhsReal, tReal);
-        Value r4 = b.create<arith::SubFOp>(loc, lhsImag, tImag);
-        b.create<linalg::YieldOp>(loc, ValueRange{r1, r2, r3, r4});
+        Value r1 = arith::AddFOp::create(b, loc, lhsReal, tReal);
+        Value r2 = arith::AddFOp::create(b, loc, lhsImag, tImag);
+        Value r3 = arith::SubFOp::create(b, loc, lhsReal, tReal);
+        Value r4 = arith::SubFOp::create(b, loc, lhsImag, tImag);
+        linalg::YieldOp::create(b, loc, ValueRange{r1, r2, r3, r4});
       });
 }
 
@@ -784,8 +786,8 @@
       2, AffineMap::get(rank, 0, b.getAffineDimExpr(rank - 1), b.getContext()));
   maps.append(operands.size(), b.getMultiDimIdentityMap(rank));
 
-  b.create<linalg::GenericOp>(
-      loc, TypeRange{}, ValueRange{getRealCoeff(), getImagCoeff()}, operands,
+  linalg::GenericOp::create(
+      b, loc, TypeRange{}, ValueRange{getRealCoeff(), getImagCoeff()}, operands,
       maps, getLoopIteratorTypes(),
       [&](OpBuilder &b, Location loc, ValueRange args) {
         Value wReal = args[0];
@@ -797,21 +799,21 @@
 
         // t = w * a[k + j + mh];
         // ->  (x + yi)(u + vi) = (xu - yv) + (xv + yu)i
-        Value xu = b.create<arith::MulFOp>(loc, wReal, rhsReal);
-        Value yv = b.create<arith::MulFOp>(loc, wImag, rhsImag);
-        Value xv = b.create<arith::MulFOp>(loc, wReal, rhsImag);
-        Value yu = b.create<arith::MulFOp>(loc, wImag, rhsReal);
-        Value tReal = b.create<arith::SubFOp>(loc, xu, yv);
-        Value tImag = b.create<arith::AddFOp>(loc, xv, yu);
+        Value xu = arith::MulFOp::create(b, loc, wReal, rhsReal);
+        Value yv = arith::MulFOp::create(b, loc, wImag, rhsImag);
+        Value xv = arith::MulFOp::create(b, loc, wReal, rhsImag);
+        Value yu = arith::MulFOp::create(b, loc, wImag, rhsReal);
+        Value tReal = arith::SubFOp::create(b, loc, xu, yv);
+        Value tImag = arith::AddFOp::create(b, loc, xv, yu);
 
         // cplx u = a[k + j];
         // a[k + j] = u + t;
         // a[k + j + mh] = u - t;
-        Value r1 = b.create<arith::AddFOp>(loc, lhsReal, tReal);
-        Value r2 = b.create<arith::AddFOp>(loc, lhsImag, tImag);
-        Value r3 = b.create<arith::SubFOp>(loc, lhsReal, tReal);
-        Value r4 = b.create<arith::SubFOp>(loc, lhsImag, tImag);
-        b.create<linalg::YieldOp>(loc, ValueRange{r1, r2, r3, r4});
+        Value r1 = arith::AddFOp::create(b, loc, lhsReal, tReal);
+        Value r2 = arith::AddFOp::create(b, loc, lhsImag, tImag);
+        Value r3 = arith::SubFOp::create(b, loc, lhsReal, tReal);
+        Value r4 = arith::SubFOp::create(b, loc, lhsImag, tImag);
+        linalg::YieldOp::create(b, loc, ValueRange{r1, r2, r3, r4});
       });
 }
 
@@ -834,9 +836,9 @@
   Value real = getReal();
   Value imag = getImag();
   Value stage = getStage();
-  Value one = b.create<arith::ConstantIndexOp>(loc, 1);
-  Value wholeSize = b.create<arith::ShLIOp>(loc, one, stage);
-  Value halfSize = b.create<arith::ShRSIOp>(loc, wholeSize, one);
+  Value one = arith::ConstantIndexOp::create(b, loc, 1);
+  Value wholeSize = arith::ShLIOp::create(b, loc, one, stage);
+  Value halfSize = arith::ShRSIOp::create(b, loc, wholeSize, one);
 
   auto rank = getOperandRank();
   SmallVector<Value> operands;
@@ -845,17 +847,17 @@
   SmallVector<OpFoldResult> sizes(rank, b.getIndexAttr(1));
   sizes.back() = halfSize;
   operands.push_back(
-      b.create<memref::SubViewOp>(loc, real, lhsIvs, sizes, ones));
+      memref::SubViewOp::create(b, loc, real, lhsIvs, sizes, ones));
   operands.push_back(
-      b.create<memref::SubViewOp>(loc, imag, lhsIvs, sizes, ones));
+      memref::SubViewOp::create(b, loc, imag, lhsIvs, sizes, ones));
 
   SmallVector<OpFoldResult> rhsIvs(ivs);
   rhsIvs.back() =
-      b.create<arith::AddIOp>(loc, ivs.back(), halfSize).getResult();
+      arith::AddIOp::create(b, loc, ivs.back(), halfSize).getResult();
   operands.push_back(
-      b.create<memref::SubViewOp>(loc, real, rhsIvs, sizes, ones));
+      memref::SubViewOp::create(b, loc, real, rhsIvs, sizes, ones));
   operands.push_back(
-      b.create<memref::SubViewOp>(loc, imag, rhsIvs, sizes, ones));
+      memref::SubViewOp::create(b, loc, imag, rhsIvs, sizes, ones));
 
   if (hasCoeff()) {
     generateScalarImplWithCoeffBuf(b, loc, operands);
@@ -942,11 +944,11 @@
                                                    ValueRange ivs) {
   SmallVector<Value> indices, scanBlkArgs;
   indices.append(ivs.begin(), ivs.end());
-  Value zero = b.create<arith::ConstantIndexOp>(loc, 0);
-  Value one = b.create<arith::ConstantIndexOp>(loc, 1);
+  Value zero = arith::ConstantIndexOp::create(b, loc, 0);
+  Value one = arith::ConstantIndexOp::create(b, loc, 1);
   auto scanDim = getDimension();
-  auto cond = b.create<arith::CmpIOp>(loc, arith::CmpIPredicate::eq,
-                                      indices[scanDim], zero);
+  auto cond = arith::CmpIOp::create(b, loc, arith::CmpIPredicate::eq,
+                                    indices[scanDim], zero);
   bool isInclusive = getInclusive();
   SmallVector<Value> accIndices;
   for (int i = 0; i < indices.size(); i++) {
@@ -955,32 +957,32 @@
     }
   }
 
-  auto scfIf = b.create<scf::IfOp>(
-      loc, cond,
+  auto scfIf = scf::IfOp::create(
+      b, loc, cond,
       [&](OpBuilder &b, Location loc) {
         if (isInclusive) {
-          auto value = b.create<memref::LoadOp>(loc, getInput(), indices);
-          b.create<memref::StoreOp>(loc, value, getOutput(), indices);
+          auto value = memref::LoadOp::create(b, loc, getInput(), indices);
+          memref::StoreOp::create(b, loc, value, getOutput(), indices);
         } else {
           auto value =
-              b.create<memref::LoadOp>(loc, getAccumulator(), accIndices);
-          b.create<memref::StoreOp>(loc, value, getOutput(), indices);
+              memref::LoadOp::create(b, loc, getAccumulator(), accIndices);
+          memref::StoreOp::create(b, loc, value, getOutput(), indices);
         }
-        b.create<scf::YieldOp>(loc);
+        scf::YieldOp::create(b, loc);
       },
       [&](OpBuilder &b, Location loc) {
         SmallVector<Value> indices(ivs);
         Value iv = indices[scanDim];
-        Value ivMinusOne = b.create<arith::SubIOp>(loc, iv, one);
+        Value ivMinusOne = arith::SubIOp::create(b, loc, iv, one);
         indices[scanDim] = ivMinusOne;
         scanBlkArgs.push_back(
-            b.create<memref::LoadOp>(loc, getOutput(), indices));
+            memref::LoadOp::create(b, loc, getOutput(), indices));
         Value i0;
         if (!isInclusive)
-          i0 = b.create<memref::LoadOp>(loc, getInput(), indices);
+          i0 = memref::LoadOp::create(b, loc, getInput(), indices);
         indices[scanDim] = iv;
         if (isInclusive)
-          i0 = b.create<memref::LoadOp>(loc, getInput(), indices);
+          i0 = memref::LoadOp::create(b, loc, getInput(), indices);
         scanBlkArgs.push_back(i0);
       });
 
@@ -997,13 +999,13 @@
     for (auto &blockOp : srcBlock.without_terminator()) {
       b.clone(blockOp, bvm);
     }
-    b.create<memref::StoreOp>(
-        loc, bvm.lookupOrDefault(srcBlock.getTerminator()->getOperand(0)),
+    memref::StoreOp::create(
+        b, loc, bvm.lookupOrDefault(srcBlock.getTerminator()->getOperand(0)),
         getOutput(), indices);
-    b.create<memref::StoreOp>(
-        loc, bvm.lookupOrDefault(srcBlock.getTerminator()->getOperand(0)),
+    memref::StoreOp::create(
+        b, loc, bvm.lookupOrDefault(srcBlock.getTerminator()->getOperand(0)),
         getAccumulator(), accIndices);
-    b.create<scf::YieldOp>(loc);
+    scf::YieldOp::create(b, loc);
   }
   return success();
 }
@@ -1116,23 +1118,23 @@
 LogicalResult TopkOp::generateScalarImplementation(OpBuilder &b, Location loc,
                                                    ValueRange ivs) {
   uint64_t kDim = getDimension();
-  Value zero = b.create<arith::ConstantIndexOp>(loc, 0);
-  Value one = b.create<arith::ConstantIndexOp>(loc, 1);
-  Value initialValue = b.create<memref::LoadOp>(loc, getValues(), ivs);
+  Value zero = arith::ConstantIndexOp::create(b, loc, 0);
+  Value one = arith::ConstantIndexOp::create(b, loc, 1);
+  Value initialValue = memref::LoadOp::create(b, loc, getValues(), ivs);
 
   // If the indices tensor is not provided, the value index is derived from the
   // loop induction variables.
   Value initialIndex;
   if (getIndices()) {
-    initialIndex = b.create<memref::LoadOp>(loc, *getIndices(), ivs);
+    initialIndex = memref::LoadOp::create(b, loc, *getIndices(), ivs);
   } else {
     Value rawInitialIndex = ivs[kDim];
     initialIndex =
-        b.create<arith::IndexCastOp>(loc, b.getI32Type(), rawInitialIndex);
+        arith::IndexCastOp::create(b, loc, b.getI32Type(), rawInitialIndex);
   }
 
   // Compute K (ub) from the selected dim of the output
-  Value ub = b.create<memref::DimOp>(loc, outputValues(), getDimension());
+  Value ub = memref::DimOp::create(b, loc, outputValues(), getDimension());
 
   // Inner K loop functions:
   //   Load current K value and index
@@ -1143,13 +1145,13 @@
   //   Store new k value and index
   //   Yield loop carry values after K selection
   Value kValue, kIndex;
-  auto scfFor = b.create<scf::ForOp>(
-      loc, zero, ub, one, ValueRange{initialValue, initialIndex},
+  auto scfFor = scf::ForOp::create(
+      b, loc, zero, ub, one, ValueRange{initialValue, initialIndex},
       [&](OpBuilder &b, Location loc, Value iv, ValueRange loopCarryValues) {
         SmallVector<Value> indices(ivs);
         indices[kDim] = iv;
-        kValue = b.create<memref::LoadOp>(loc, outputValues(), indices);
-        kIndex = b.create<memref::LoadOp>(loc, outputIndices(), indices);
+        kValue = memref::LoadOp::create(b, loc, outputValues(), indices);
+        kIndex = memref::LoadOp::create(b, loc, outputIndices(), indices);
       });
 
   SmallVector<Value> indices(ivs);
@@ -1183,28 +1185,29 @@
     //   f(x,y) --> forwardCmpRes
     //   f(y,x) --> reverseCmpRes
     //   if forwardCmpRes == reverseCmpRes then select which came first
-    Value cmpValuesEqual = b.create<arith::CmpIOp>(
-        loc, arith::CmpIPredicate::eq, forwardCmpRes, reverseCmpRes);
-    Value cmpFirstIndex = b.create<arith::CmpIOp>(
-        loc, arith::CmpIPredicate::slt, loopCarryValues[1], kIndex);
+    Value cmpValuesEqual = arith::CmpIOp::create(
+        b, loc, arith::CmpIPredicate::eq, forwardCmpRes, reverseCmpRes);
+    Value cmpFirstIndex = arith::CmpIOp::create(
+        b, loc, arith::CmpIPredicate::slt, loopCarryValues[1], kIndex);
     Value combinedCmpEqRes =
-        b.create<arith::AndIOp>(loc, cmpValuesEqual, cmpFirstIndex);
+        arith::AndIOp::create(b, loc, cmpValuesEqual, cmpFirstIndex);
     // True if N > K or N came before K
     Value indexCmpRes =
-        b.create<arith::OrIOp>(loc, forwardCmpRes, combinedCmpEqRes);
+        arith::OrIOp::create(b, loc, forwardCmpRes, combinedCmpEqRes);
     // Select results for K based on comparisons
-    Value resultKValue = b.create<arith::SelectOp>(loc, forwardCmpRes,
-                                                   loopCarryValues[0], kValue);
-    Value resultKIndex =
-        b.create<arith::SelectOp>(loc, indexCmpRes, loopCarryValues[1], kIndex);
-    b.create<memref::StoreOp>(loc, resultKValue, outputValues(), indices);
-    b.create<memref::StoreOp>(loc, resultKIndex, outputIndices(), indices);
+    Value resultKValue = arith::SelectOp::create(b, loc, forwardCmpRes,
+                                                 loopCarryValues[0], kValue);
+    Value resultKIndex = arith::SelectOp::create(b, loc, indexCmpRes,
+                                                 loopCarryValues[1], kIndex);
+    memref::StoreOp::create(b, loc, resultKValue, outputValues(), indices);
+    memref::StoreOp::create(b, loc, resultKIndex, outputIndices(), indices);
     // Select loop carry, opposite of K results
-    Value resultCarryValue = b.create<arith::SelectOp>(
-        loc, forwardCmpRes, kValue, loopCarryValues[0]);
-    Value resultCarryIndex =
-        b.create<arith::SelectOp>(loc, indexCmpRes, kIndex, loopCarryValues[1]);
-    b.create<scf::YieldOp>(loc, ValueRange{resultCarryValue, resultCarryIndex});
+    Value resultCarryValue = arith::SelectOp::create(
+        b, loc, forwardCmpRes, kValue, loopCarryValues[0]);
+    Value resultCarryIndex = arith::SelectOp::create(
+        b, loc, indexCmpRes, kIndex, loopCarryValues[1]);
+    scf::YieldOp::create(b, loc,
+                         ValueRange{resultCarryValue, resultCarryIndex});
   }
   return success();
 }
@@ -1406,11 +1409,11 @@
   }
 
   Value bestValueSoFar =
-      b.create<memref::LoadOp>(loc, outputValue(), parallelIndices);
+      memref::LoadOp::create(b, loc, outputValue(), parallelIndices);
   Value bestIndexSoFar =
-      b.create<memref::LoadOp>(loc, outputIndex(), parallelIndices);
+      memref::LoadOp::create(b, loc, outputIndex(), parallelIndices);
 
-  Value candidateValue = b.create<memref::LoadOp>(loc, getInputValue(), ivs);
+  Value candidateValue = memref::LoadOp::create(b, loc, getInputValue(), ivs);
 
   auto &srcBlock = getRegion().front();
   IRMapping regionMap;
@@ -1421,22 +1424,24 @@
   }
 
   Value cmpResult = regionMap.lookup(srcBlock.getTerminator()->getOperand(0));
-  Value selectedValue =
-      b.create<arith::SelectOp>(loc, cmpResult, candidateValue, bestValueSoFar);
+  Value selectedValue = arith::SelectOp::create(b, loc, cmpResult,
+                                                candidateValue, bestValueSoFar);
   Value indexOffset = ivs[reductionDim];
   if (getIndexBase()) {
-    indexOffset = b.create<arith::AddIOp>(loc, getIndexBase(), indexOffset);
+    indexOffset = arith::AddIOp::create(b, loc, getIndexBase(), indexOffset);
   }
   Value castedIndex = indexOffset;
   if (castedIndex.getType() != bestIndexSoFar.getType()) {
-    castedIndex = b.create<arith::IndexCastOp>(loc, bestIndexSoFar.getType(),
-                                               castedIndex);
+    castedIndex = arith::IndexCastOp::create(b, loc, bestIndexSoFar.getType(),
+                                             castedIndex);
   }
 
   Value selectedIndex =
-      b.create<arith::SelectOp>(loc, cmpResult, castedIndex, bestIndexSoFar);
-  b.create<memref::StoreOp>(loc, selectedValue, outputValue(), parallelIndices);
-  b.create<memref::StoreOp>(loc, selectedIndex, outputIndex(), parallelIndices);
+      arith::SelectOp::create(b, loc, cmpResult, castedIndex, bestIndexSoFar);
+  memref::StoreOp::create(b, loc, selectedValue, outputValue(),
+                          parallelIndices);
+  memref::StoreOp::create(b, loc, selectedIndex, outputIndex(),
+                          parallelIndices);
   return success();
 }
 
@@ -1454,8 +1459,8 @@
   int64_t rank = (std::is_same<OpTy, PackOp>::value) ? op.getInputRank()
                                                      : op.getOutputRank();
   SmallVector<Range> loopBounds(rank);
-  Value zero = builder.create<arith::ConstantIndexOp>(loc, 0);
-  Value one = builder.create<arith::ConstantIndexOp>(loc, 1);
+  Value zero = arith::ConstantIndexOp::create(builder, loc, 0);
+  Value one = arith::ConstantIndexOp::create(builder, loc, 1);
   ReifiedRankedShapedTypeDims resultShape;
   (void)op.reifyResultShapes(builder, resultShape);
   for (auto dim : llvm::seq<int64_t>(0, rank)) {
@@ -1526,8 +1531,8 @@
   }
 
   auto createLoad = [&]() -> Value {
-    return builder.create<memref::LoadOp>(
-        loc, packOp.getInput(),
+    return memref::LoadOp::create(
+        builder, loc, packOp.getInput(),
         getValueOrCreateConstantIndexOp(builder, loc, sourceIndices));
   };
   Value scalar;
@@ -1545,18 +1550,18 @@
                  .create<scf::IfOp>(
                      loc, isInBounds, /*thenBuilder=*/
                      [&](OpBuilder &b, Location l) {
-                       b.create<scf::YieldOp>(l, createLoad());
+                       scf::YieldOp::create(b, l, createLoad());
                      },
                      /*elseBuilder=*/
                      [&](OpBuilder &b, Location l) {
-                       b.create<scf::YieldOp>(l, paddingValue);
+                       scf::YieldOp::create(b, l, paddingValue);
                      })
                  .getResult(0);
   } else {
     scalar = createLoad();
   }
 
-  builder.create<memref::StoreOp>(loc, scalar, packOp.getOutput(), ivs);
+  memref::StoreOp::create(builder, loc, scalar, packOp.getOutput(), ivs);
 }
 
 LogicalResult PackOp::generateScalarImplementation(OpBuilder &builder,
@@ -1577,8 +1582,8 @@
   }
 
   // Generate the loops that iterate over the data tile.
-  Value zero = builder.create<arith::ConstantIndexOp>(loc, 0);
-  Value one = builder.create<arith::ConstantIndexOp>(loc, 1);
+  Value zero = arith::ConstantIndexOp::create(builder, loc, 0);
+  Value one = arith::ConstantIndexOp::create(builder, loc, 1);
 
   // All loops except the innermost are simple loops that just iterate
   // over the tile dimensions.
@@ -1586,13 +1591,13 @@
        llvm::seq<unsigned>(getInputRank(), getOutputRank() - 1)) {
     Value ub = getValueOrCreateConstantIndexOp(builder, loc,
                                                outputShape[0][dataTileDim]);
-    scf::ForOp loop = builder.create<scf::ForOp>(loc, zero, ub, one);
+    scf::ForOp loop = scf::ForOp::create(builder, loc, zero, ub, one);
     builder.setInsertionPointToStart(loop.getBody());
     ivVec.push_back(loop.getInductionVar());
   }
   // The body of the innermost loops does the actual data movement.
-  builder.create<scf::ForOp>(
-      loc, zero,
+  scf::ForOp::create(
+      builder, loc, zero,
       getValueOrCreateConstantIndexOp(builder, loc, outputShape[0].back()), one,
       ValueRange{},
       [&](OpBuilder &bodyBuilder, Location bodyLoc, Value iv,
@@ -1600,7 +1605,7 @@
         ivVec.push_back(iv);
         generatePackOpScalarImplementationBody(*this, bodyBuilder, bodyLoc,
                                                ivVec);
-        bodyBuilder.create<scf::YieldOp>(bodyLoc);
+        scf::YieldOp::create(bodyBuilder, bodyLoc);
       });
   return success();
 }
@@ -1663,8 +1668,8 @@
   }
 
   llvm::append_range(inputIvs, interchangedInputIvsPointLoops);
-  Value scalar = builder.create<memref::LoadOp>(loc, getInput(), inputIvs);
-  builder.create<memref::StoreOp>(loc, scalar, getOutput(), ivs);
+  Value scalar = memref::LoadOp::create(builder, loc, getInput(), inputIvs);
+  memref::StoreOp::create(builder, loc, scalar, getOutput(), ivs);
   return success();
 }
 
@@ -2582,9 +2587,9 @@
   Type maxElTy = getElementTypeOrSelf(getMax().getType());
   Type sumElTy = getElementTypeOrSelf(getSum().getType());
 
-  Value partialAcc = b.create<tensor::EmptyOp>(loc, accSize, accElTy);
-  Value partialMax = b.create<tensor::EmptyOp>(loc, maxSize, maxElTy);
-  Value partialSum = b.create<tensor::EmptyOp>(loc, sumSize, sumElTy);
+  Value partialAcc = tensor::EmptyOp::create(b, loc, accSize, accElTy);
+  Value partialMax = tensor::EmptyOp::create(b, loc, maxSize, maxElTy);
+  Value partialSum = tensor::EmptyOp::create(b, loc, sumSize, sumElTy);
 
   Value accInit = arith::getIdentityValue(arith::AtomicRMWKind::addf, accElTy,
                                           b, loc, /*useOnlyFiniteValue=*/true);
@@ -2594,12 +2599,15 @@
   Value sumInit =
       arith::getIdentityValue(arith::AtomicRMWKind::addf, sumElTy, b, loc);
 
-  Value accFill = b.create<linalg::FillOp>(loc, ValueRange{accInit}, partialAcc)
-                      .getResult(0);
-  Value maxFill = b.create<linalg::FillOp>(loc, ValueRange{maxInit}, partialMax)
-                      .getResult(0);
-  Value sumFill = b.create<linalg::FillOp>(loc, ValueRange{sumInit}, partialSum)
-                      .getResult(0);
+  Value accFill =
+      linalg::FillOp::create(b, loc, ValueRange{accInit}, partialAcc)
+          .getResult(0);
+  Value maxFill =
+      linalg::FillOp::create(b, loc, ValueRange{maxInit}, partialMax)
+          .getResult(0);
+  Value sumFill =
+      linalg::FillOp::create(b, loc, ValueRange{sumInit}, partialSum)
+          .getResult(0);
 
   return SmallVector<Value>{accFill, maxFill, sumFill};
 }
@@ -2702,11 +2710,11 @@
     }
   }
 
-  return b.create<linalg::ReduceOp>(
-      loc, partialResult, init, partialReductionDims,
+  return linalg::ReduceOp::create(
+      b, loc, partialResult, init, partialReductionDims,
       [&](OpBuilder &b, Location loc, ValueRange inputs) {
-        Value reduced = b.create<CombinerOp>(loc, inputs[0], inputs[1]);
-        b.create<linalg::YieldOp>(loc, reduced);
+        Value reduced = CombinerOp::create(b, loc, inputs[0], inputs[1]);
+        linalg::YieldOp::create(b, loc, reduced);
       });
 };
 
@@ -2722,15 +2730,15 @@
   SmallVector<utils::IteratorType> iteratorTypes(inputMap.getNumDims(),
                                                  utils::IteratorType::parallel);
 
-  auto genericOp = builder.create<linalg::GenericOp>(
-      loc, value.getType(), scale, value,
+  auto genericOp = linalg::GenericOp::create(
+      builder, loc, value.getType(), scale, value,
       SmallVector<AffineMap>{scaleMap, inputMap}, iteratorTypes,
       [&](OpBuilder &b, Location loc, ValueRange args) {
         // Convert scale to the same datatype as input.
         Value scale = convertScalarToDtype(b, loc, args[0], args[1].getType(),
                                            /*isUnsignedCast=*/false);
-        Value result = b.create<T>(loc, scale, args[1]);
-        b.create<linalg::YieldOp>(loc, result);
+        Value result = T::create(b, loc, scale, args[1]);
+        linalg::YieldOp::create(b, loc, result);
       });
   return genericOp.getResult(0);
 }
@@ -2746,16 +2754,16 @@
 
   SmallVector<utils::IteratorType> iteratorTypes(inputMap.getNumDims(),
                                                  utils::IteratorType::parallel);
-  auto genericOp = builder.create<linalg::GenericOp>(
-      loc, output.getType(), input, output,
+  auto genericOp = linalg::GenericOp::create(
+      builder, loc, output.getType(), input, output,
       SmallVector<AffineMap>{inputMap, outputMap}, iteratorTypes,
       [&](OpBuilder &b, Location loc, ValueRange args) {
         // Convert input to the same datatype as output.
         Value in = convertScalarToDtype(b, loc, args[0], args[1].getType(),
                                         /*isUnsignedCast=*/false);
-        Value diff = b.create<arith::SubFOp>(loc, args[1], in);
-        Value weight = b.create<math::Exp2Op>(loc, diff);
-        b.create<linalg::YieldOp>(loc, weight);
+        Value diff = arith::SubFOp::create(b, loc, args[1], in);
+        Value weight = math::Exp2Op::create(b, loc, diff);
+        linalg::YieldOp::create(b, loc, weight);
       });
   return genericOp.getResult(0);
 }
@@ -3032,8 +3040,8 @@
   auto shapedType = dyn_cast<ShapedType>(valueToTile.getType());
   auto *sliceOp = TypeSwitch<ShapedType, Operation *>(shapedType)
                       .Case([&](RankedTensorType) {
-                        return builder.create<tensor::ExtractSliceOp>(
-                            loc, valueToTile, sliceParams.offsets,
+                        return tensor::ExtractSliceOp::create(
+                            builder, loc, valueToTile, sliceParams.offsets,
                             sliceParams.sizes, sliceParams.strides);
                       })
                       .Default([](ShapedType) -> Operation * {
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ConvertConv2DToWinograd.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ConvertConv2DToWinograd.cpp
index 4ce7ef5..980b8fc 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ConvertConv2DToWinograd.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ConvertConv2DToWinograd.cpp
@@ -71,8 +71,8 @@
   auto tensorType = cast<ShapedType>(tensor.getType());
   auto elementTy = tensorType.getElementType();
   auto resultType = RankedTensorType::get(outputShape, elementTy);
-  return rewriter.create<tensor::CollapseShapeOp>(loc, resultType, tensor,
-                                                  reassociations);
+  return tensor::CollapseShapeOp::create(rewriter, loc, resultType, tensor,
+                                         reassociations);
 }
 
 static Value
@@ -82,8 +82,8 @@
   auto tensorType = cast<ShapedType>(tensor.getType());
   auto elementTy = tensorType.getElementType();
   auto resultType = RankedTensorType::get(outputShape, elementTy);
-  return rewriter.create<tensor::ExpandShapeOp>(loc, resultType, tensor,
-                                                reassociations);
+  return tensor::ExpandShapeOp::create(rewriter, loc, resultType, tensor,
+                                       reassociations);
 }
 
 namespace {
@@ -204,7 +204,7 @@
     filterResultShape[2] = isNchwFchw ? kernelShape[1] : kernelShape[2];
     filterResultShape[3] = isNchwFchw ? kernelShape[0] : kernelShape[3];
     Value kernelInit =
-        rewriter.create<tensor::EmptyOp>(loc, filterResultShape, inElemType);
+        tensor::EmptyOp::create(rewriter, loc, filterResultShape, inElemType);
     const std::array<int64_t, 2> kernelDims =
         isNchwFchw ? fchwKernelDims : hwcfKernelDims;
     Value winogradFilter =
@@ -256,7 +256,7 @@
       }
     }
     Value inputTfInit =
-        rewriter.create<tensor::EmptyOp>(loc, resultShape, inElemType);
+        tensor::EmptyOp::create(rewriter, loc, resultShape, inElemType);
     const std::array<int64_t, 2> imageDims =
         isNchwFchw ? nchwImageDims : nhwcImageDims;
     Value winogradInput =
@@ -283,13 +283,13 @@
     bmmShape[2] = outputShape[3];
     auto bmmOutputType = RankedTensorType::get(bmmShape, outElemType);
     Value bmmInit =
-        rewriter.create<tensor::EmptyOp>(loc, bmmShape, outElemType);
-    Value zero = rewriter.create<arith::ConstantOp>(
-        loc, rewriter.getZeroAttr(outElemType));
-    auto fillOp = rewriter.create<linalg::FillOp>(loc, ValueRange{zero},
-                                                  ValueRange{bmmInit});
-    auto bmmOp = rewriter.create<linalg::BatchMatmulOp>(
-        loc, bmmOutputType,
+        tensor::EmptyOp::create(rewriter, loc, bmmShape, outElemType);
+    Value zero = arith::ConstantOp::create(rewriter, loc,
+                                           rewriter.getZeroAttr(outElemType));
+    auto fillOp = linalg::FillOp::create(rewriter, loc, ValueRange{zero},
+                                         ValueRange{bmmInit});
+    auto bmmOp = linalg::BatchMatmulOp::create(
+        rewriter, loc, bmmOutputType,
         ValueRange({collapsedWinogradInput, collapsedWinogradFilter}),
         ValueRange({fillOp.result()}));
     Value bmmResult = bmmOp.getResult(0);
@@ -315,7 +315,7 @@
       permute<IREE::LinalgExt::Permutation::NHWC_TO_NCHW>(paddedResultShape);
     }
     Value outputTfInit =
-        rewriter.create<tensor::EmptyOp>(loc, paddedResultShape, outElemType);
+        tensor::EmptyOp::create(rewriter, loc, paddedResultShape, outElemType);
     Value paddedOutput =
         rewriter
             .create<IREE::LinalgExt::WinogradOutputTransformOp>(
@@ -330,8 +330,8 @@
                                       rewriter.getIndexAttr(1));
     SmallVector<OpFoldResult> sizes =
         getAsIndexOpFoldResult(rewriter.getContext(), outputType.getShape());
-    auto winogradOutput = rewriter.create<tensor::ExtractSliceOp>(
-        loc, outputType, paddedOutput, offsets, sizes, strides);
+    auto winogradOutput = tensor::ExtractSliceOp::create(
+        rewriter, loc, outputType, paddedOutput, offsets, sizes, strides);
 
     rewriter.replaceOp(convOp, winogradOutput);
     return success();
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ConvertConvToIm2ColOp.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ConvertConvToIm2ColOp.cpp
index ac8fc99..2b18e01 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ConvertConvToIm2ColOp.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ConvertConvToIm2ColOp.cpp
@@ -28,15 +28,15 @@
 static Value createAdd(Location loc, Value x, Value y, OpBuilder &builder) {
   bool isInt = llvm::isa<IntegerType>(x.getType());
   if (isInt)
-    return builder.create<arith::AddIOp>(loc, x, y);
-  return builder.create<arith::AddFOp>(loc, x, y);
+    return arith::AddIOp::create(builder, loc, x, y);
+  return arith::AddFOp::create(builder, loc, x, y);
 }
 
 static Value createMul(Location loc, Value x, Value y, OpBuilder &builder) {
   bool isInt = llvm::isa<IntegerType>(x.getType());
   if (isInt)
-    return builder.create<arith::MulIOp>(loc, x, y);
-  return builder.create<arith::MulFOp>(loc, x, y);
+    return arith::MulIOp::create(builder, loc, x, y);
+  return arith::MulFOp::create(builder, loc, x, y);
 }
 
 // TODO : Upstream utility that does this pruning is broken for LinalgOp. Drop
@@ -263,8 +263,8 @@
     }
     colTensorShape.append(mShape);
     colTensorShape.append(kShape);
-    Value colTensor = rewriter.create<tensor::EmptyOp>(
-        loc, colTensorShape, inputType.getElementType());
+    Value colTensor = tensor::EmptyOp::create(rewriter, loc, colTensorShape,
+                                              inputType.getElementType());
     Value img2ColTensor =
         rewriter
             .create<IREE::LinalgExt::Im2colOp>(
@@ -273,11 +273,11 @@
                 kBasis, batchPos, mPos, kPos, inputKPerm)
             .getResult(0);
 
-    Value reshapedFilter = rewriter.create<tensor::CollapseShapeOp>(
-        loc, filter, filterReassocIndices);
+    Value reshapedFilter = tensor::CollapseShapeOp::create(
+        rewriter, loc, filter, filterReassocIndices);
 
-    auto genericGEMMOp = rewriter.create<linalg::GenericOp>(
-        loc, outputType,
+    auto genericGEMMOp = linalg::GenericOp::create(
+        rewriter, loc, outputType,
         /*inputs=*/
         isOutputChannelFirst ? ValueRange{reshapedFilter, img2ColTensor}
                              : ValueRange{img2ColTensor, reshapedFilter},
@@ -292,7 +292,7 @@
                                            /*isUnsignedCast=*/false);
           Value mul = createMul(nestedLoc, lhs, rhs, nestedBuilder);
           Value add = createAdd(nestedLoc, mul, args[2], nestedBuilder);
-          nestedBuilder.create<linalg::YieldOp>(nestedLoc, add);
+          linalg::YieldOp::create(nestedBuilder, nestedLoc, add);
         });
     genericGEMMOp->setDiscardableAttrs(getPrunedAttributeList(linalgOp));
     Value result = genericGEMMOp.getResults().front();
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ConvertToLoops.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ConvertToLoops.cpp
index bd12ed9..24059dc 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ConvertToLoops.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ConvertToLoops.cpp
@@ -39,8 +39,8 @@
     return tilableOp.generateScalarImplementation(builder, loc, ivs);
   }
   LogicalResult status = success();
-  builder.create<scf::ForOp>(
-      loc,
+  scf::ForOp::create(
+      builder, loc,
       getValueOrCreateConstantIndexOp(builder, loc,
                                       loopRanges[loopDepth].offset),
       getValueOrCreateConstantIndexOp(builder, loc, loopRanges[loopDepth].size),
@@ -49,7 +49,7 @@
       ValueRange{}, [&](OpBuilder &b, Location loc, Value iv, ValueRange args) {
         ivs.push_back(iv);
         status = lowerToLoopsImpl(b, tilableOp, loopRanges, loopDepth + 1, ivs);
-        b.create<scf::YieldOp>(loc);
+        scf::YieldOp::create(b, loc);
       });
   return status;
 }
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/DecomposeMapScatter.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/DecomposeMapScatter.cpp
index ee7b358..1943e20 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/DecomposeMapScatter.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/DecomposeMapScatter.cpp
@@ -40,13 +40,13 @@
   Location loc = mapScatterOp.getLoc();
   OpBuilder::InsertionGuard g(rewriter);
   rewriter.setInsertionPoint(mapScatterOp);
-  Value flatOutputBuffer = rewriter.create<memref::CollapseShapeOp>(
-      loc, mapScatterOp.getOutput(), reassociations);
+  Value flatOutputBuffer = memref::CollapseShapeOp::create(
+      rewriter, loc, mapScatterOp.getOutput(), reassociations);
 
-  auto idxInit = rewriter.create<tensor::EmptyOp>(loc, inputType.getShape(),
-                                                  rewriter.getIndexType());
-  auto maskInit = rewriter.create<tensor::EmptyOp>(loc, inputType.getShape(),
-                                                   rewriter.getIntegerType(1));
+  auto idxInit = tensor::EmptyOp::create(rewriter, loc, inputType.getShape(),
+                                         rewriter.getIndexType());
+  auto maskInit = tensor::EmptyOp::create(rewriter, loc, inputType.getShape(),
+                                          rewriter.getIntegerType(1));
   SmallVector<OpFoldResult> outputSizes =
       memref::getMixedSizes(rewriter, loc, mapScatterOp.getOutput());
 
@@ -55,14 +55,15 @@
                                  ArrayRef<Value> yieldedValues) {
       SmallVector<Value> outputIndices(yieldedValues);
       Value mask = outputIndices.pop_back_val();
-      Value linearIdx = inlineBuilder.create<affine::AffineLinearizeIndexOp>(
-          inlineLoc, outputIndices, outputSizes, /*disjoint=*/true);
-      inlineBuilder.create<linalg::YieldOp>(inlineLoc,
-                                            ValueRange{linearIdx, mask});
+      Value linearIdx = affine::AffineLinearizeIndexOp::create(
+          inlineBuilder, inlineLoc, outputIndices, outputSizes,
+          /*disjoint=*/true);
+      linalg::YieldOp::create(inlineBuilder, inlineLoc,
+                              ValueRange{linearIdx, mask});
     };
     SmallVector<Value> indices = llvm::map_to_vector(
         llvm::seq<int64_t>(inputType.getRank()), [&](int64_t dim) -> Value {
-          return b.create<linalg::IndexOp>(nestedLoc, b.getIndexType(), dim);
+          return linalg::IndexOp::create(b, nestedLoc, b.getIndexType(), dim);
         });
     mapScatterOp.inlineMapScatterBody(b, nestedLoc, indices, inlineBodyBuilder);
   };
@@ -71,8 +72,9 @@
   SmallVector<utils::IteratorType> iterTypes(inputType.getRank(),
                                              utils::IteratorType::parallel);
   SmallVector<Value> outs = {idxInit.getResult(), maskInit.getResult()};
-  auto genericOp = rewriter.create<linalg::GenericOp>(
-      loc, TypeRange(outs), ValueRange(), outs, maps, iterTypes, bodyBuilder);
+  auto genericOp =
+      linalg::GenericOp::create(rewriter, loc, TypeRange(outs), ValueRange(),
+                                outs, maps, iterTypes, bodyBuilder);
 
   // Lower linearize and delinearize ops before vectorizing, because the
   // vectorizer can't hendle them.
@@ -125,18 +127,18 @@
   auto flatIndexType =
       VectorType::get({flatVectorSize}, rewriter.getIndexType());
   indexVector =
-      rewriter.create<vector::ShapeCastOp>(loc, flatIndexType, indexVector);
+      vector::ShapeCastOp::create(rewriter, loc, flatIndexType, indexVector);
   auto flatMaskType =
       VectorType::get({flatVectorSize}, rewriter.getIntegerType(1));
   maskVector =
-      rewriter.create<vector::ShapeCastOp>(loc, flatMaskType, maskVector);
+      vector::ShapeCastOp::create(rewriter, loc, flatMaskType, maskVector);
   auto flatInputType =
       VectorType::get({flatVectorSize}, inputType.getElementType());
-  Value inputVector = rewriter.create<vector::ShapeCastOp>(
-      loc, flatInputType, mapScatterOp.getInput());
+  Value inputVector = vector::ShapeCastOp::create(rewriter, loc, flatInputType,
+                                                  mapScatterOp.getInput());
 
   SmallVector<Value> offsets = {
-      rewriter.create<arith::ConstantIndexOp>(loc, 0)};
+      arith::ConstantIndexOp::create(rewriter, loc, 0)};
   rewriter.replaceOpWithNewOp<vector::ScatterOp>(mapScatterOp, flatOutputBuffer,
                                                  offsets, indexVector,
                                                  maskVector, inputVector);
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/DecomposeWinogradPass.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/DecomposeWinogradPass.cpp
index 50ae0ad..bd9930f 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/DecomposeWinogradPass.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/DecomposeWinogradPass.cpp
@@ -127,8 +127,8 @@
     llvm::SmallSetVector<int64_t, 2> kernelDimsSet(kernelDims.begin(),
                                                    kernelDims.end());
     Type elementType = transformOp.getOutputType().getElementType();
-    Value zeroF32 = rewriter.create<arith::ConstantOp>(
-        loc, rewriter.getZeroAttr(elementType));
+    Value zeroF32 = arith::ConstantOp::create(
+        rewriter, loc, rewriter.getZeroAttr(elementType));
     /// The two values below are the transpose(G) [GT]
     /// and G [G] constant matrices that convert the filter
     /// tile from the original domain to the Winograd domain.
@@ -145,18 +145,18 @@
     Value inputSlice = transformOp.getInput();
     Value outputSlice = transformOp.getOutput();
     auto tensorType = transformOp.getOutputType().clone(initShape);
-    Value init = rewriter.create<tensor::EmptyOp>(loc, initShape, elementType);
-    linalg::FillOp fillOp = rewriter.create<linalg::FillOp>(
-        loc, ValueRange{zeroF32}, ValueRange{init});
-    linalg::MatmulOp matmulOp = rewriter.create<linalg::MatmulOp>(
-        loc, tensorType, ValueRange{inputSlice, GT}, fillOp.result());
+    Value init = tensor::EmptyOp::create(rewriter, loc, initShape, elementType);
+    linalg::FillOp fillOp = linalg::FillOp::create(
+        rewriter, loc, ValueRange{zeroF32}, ValueRange{init});
+    linalg::MatmulOp matmulOp = linalg::MatmulOp::create(
+        rewriter, loc, tensorType, ValueRange{inputSlice, GT}, fillOp.result());
 
     // Create matmul(G, matmul(input, GT))
-    fillOp = rewriter.create<linalg::FillOp>(loc, ValueRange{zeroF32},
-                                             ValueRange{outputSlice});
-    matmulOp = rewriter.create<linalg::MatmulOp>(
-        loc, outputSlice.getType(), ValueRange{G, matmulOp.getResult(0)},
-        fillOp.result());
+    fillOp = linalg::FillOp::create(rewriter, loc, ValueRange{zeroF32},
+                                    ValueRange{outputSlice});
+    matmulOp = linalg::MatmulOp::create(rewriter, loc, outputSlice.getType(),
+                                        ValueRange{G, matmulOp.getResult(0)},
+                                        fillOp.result());
     rewriter.replaceOp(transformOp, matmulOp.getResult(0));
     return success();
   }
@@ -217,8 +217,8 @@
     // Pad the input slice.
     Value dynamicSlice = transformOp.getInput();
     Type elementType = transformOp.getOutputType().getElementType();
-    Value zero = rewriter.create<arith::ConstantOp>(
-        loc, rewriter.getZeroAttr(elementType));
+    Value zero = arith::ConstantOp::create(rewriter, loc,
+                                           rewriter.getZeroAttr(elementType));
     SmallVector<int64_t> inputTileSquare(
         transformOp.getImageDimensions().size(), inputTileSize);
     auto inputSliceType = RankedTensorType::get(inputTileSquare, elementType);
@@ -229,8 +229,8 @@
     Value result, AMatrix, BMatrix;
     linalg::MatmulOp matmulOp;
     for (int i = 0; i < 2; i++) {
-      auto fillOp = rewriter.create<linalg::FillOp>(
-          loc, ValueRange{zero}, ValueRange{transformOp.getOutput()});
+      auto fillOp = linalg::FillOp::create(rewriter, loc, ValueRange{zero},
+                                           ValueRange{transformOp.getOutput()});
       if (i == 0) {
         AMatrix = inputSlice;
         BMatrix = B;
@@ -238,9 +238,9 @@
         AMatrix = BT;
         BMatrix = result;
       }
-      matmulOp = rewriter.create<linalg::MatmulOp>(
-          loc, transformOp.getOutputType(), ValueRange{AMatrix, BMatrix},
-          fillOp.result());
+      matmulOp = linalg::MatmulOp::create(
+          rewriter, loc, transformOp.getOutputType(),
+          ValueRange{AMatrix, BMatrix}, fillOp.result());
       result = matmulOp.getResult(0);
     }
     rewriter.replaceOp(transformOp, result);
@@ -300,11 +300,11 @@
     Value A = IREE::LinalgExt::createValueFrom2DConstant(
         IREE::LinalgExt::Winograd::A_6x6_3x3, inputTileSize, outputTileSize,
         loc, rewriter);
-    Value zeroF32 = rewriter.create<arith::ConstantOp>(
-        loc, rewriter.getZeroAttr(elementType));
+    Value zeroF32 = arith::ConstantOp::create(
+        rewriter, loc, rewriter.getZeroAttr(elementType));
     SmallVector<int64_t> scratchShape = {inputTileSize, outputTileSize};
     Value scratch =
-        rewriter.create<tensor::EmptyOp>(loc, scratchShape, elementType);
+        tensor::EmptyOp::create(rewriter, loc, scratchShape, elementType);
     // Create computation
     Value result, AMatrix, BMatrix;
     linalg::MatmulOp matmulOp;
@@ -312,8 +312,8 @@
     Value tmp;
     for (int i = 0; i < 2; i++) {
       tmp = i == 0 ? scratch : outputSlice;
-      fillOp = rewriter.create<linalg::FillOp>(loc, ValueRange{zeroF32},
-                                               ValueRange{tmp});
+      fillOp = linalg::FillOp::create(rewriter, loc, ValueRange{zeroF32},
+                                      ValueRange{tmp});
       if (i == 0) {
         AMatrix = inputSlice;
         BMatrix = A;
@@ -321,8 +321,9 @@
         AMatrix = AT;
         BMatrix = result;
       }
-      matmulOp = rewriter.create<linalg::MatmulOp>(
-          loc, tmp.getType(), ValueRange{AMatrix, BMatrix}, fillOp.result());
+      matmulOp = linalg::MatmulOp::create(rewriter, loc, tmp.getType(),
+                                          ValueRange{AMatrix, BMatrix},
+                                          fillOp.result());
       result = matmulOp.getResult(0);
     }
     rewriter.replaceOp(transformOp, result);
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/PadContractionToBlockSize.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/PadContractionToBlockSize.cpp
index fe93055..9f2135d 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/PadContractionToBlockSize.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/PadContractionToBlockSize.cpp
@@ -26,8 +26,8 @@
       tensor::getMixedSizes(builder, loc, original);
   SmallVector<OpFoldResult> offsets(sizes.size(), builder.getI64IntegerAttr(0));
   SmallVector<OpFoldResult> strides(sizes.size(), builder.getI64IntegerAttr(1));
-  return builder.create<tensor::ExtractSliceOp>(loc, expanded, offsets, sizes,
-                                                strides);
+  return tensor::ExtractSliceOp::create(builder, loc, expanded, offsets, sizes,
+                                        strides);
 }
 
 static bool padTensor(Location loc, OpOperand *operand,
@@ -61,9 +61,9 @@
       needsPad = true;
     } else {
       // Dynamic dim.
-      Value inputDimValue = builder.create<tensor::DimOp>(loc, original, i);
+      Value inputDimValue = tensor::DimOp::create(builder, loc, original, i);
       Value alignedDim =
-          builder.create<IREE::Util::AlignOp>(loc, inputDimValue, alignment);
+          IREE::Util::AlignOp::create(builder, loc, inputDimValue, alignment);
       newPaddingSizes[i] = alignedDim;
       needsPad = true;
     }
@@ -73,14 +73,14 @@
   }
 
   auto resultType = RankedTensorType::get(newStaticDims, type.getElementType());
-  Value zeroConstant = builder.create<arith::ConstantOp>(
-      loc, builder.getZeroAttr(type.getElementType()));
+  Value zeroConstant = arith::ConstantOp::create(
+      builder, loc, builder.getZeroAttr(type.getElementType()));
   SmallVector<OpFoldResult> zeroStaticLow(shape.size(),
                                           builder.getI64IntegerAttr(0));
   SmallVector<Value> nullLow;
-  Value padded = builder.create<tensor::PadOp>(loc, resultType, operand->get(),
-                                               zeroStaticLow, newPaddingSizes,
-                                               zeroConstant);
+  Value padded =
+      tensor::PadOp::create(builder, loc, resultType, operand->get(),
+                            zeroStaticLow, newPaddingSizes, zeroConstant);
   operand->set(padded);
   return true;
 }
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ReshapeFusion.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ReshapeFusion.cpp
index 4d8990e..19c544d 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ReshapeFusion.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/ReshapeFusion.cpp
@@ -96,8 +96,8 @@
             /*isExpandingReshape=*/true))) {
       return {};
     }
-    return rewriter.create<tensor::ExpandShapeOp>(loc, newType, operand->get(),
-                                                  reassoc);
+    return tensor::ExpandShapeOp::create(rewriter, loc, newType, operand->get(),
+                                         reassoc);
   };
 
   /// Get the shape map for the operand.
@@ -452,8 +452,9 @@
   if (isIdentityReassoc(originalReassoc)) {
     return std::optional{newOp->getResult(0)};
   }
-  return rewriter.create<tensor::CollapseShapeOp>(
-      loc, op.getResult(0).getType(), newOp->getResult(0), originalReassoc);
+  return tensor::CollapseShapeOp::create(rewriter, loc,
+                                         op.getResult(0).getType(),
+                                         newOp->getResult(0), originalReassoc);
 }
 
 //===----------------------------------------------------------------------===//
@@ -478,8 +479,8 @@
       reassoc.emplace_back(1, i);
     }
     reassoc.push_back(ReassociationIndices{batchRank - 1, batchRank});
-    auto collapseOp = rewriter.create<tensor::CollapseShapeOp>(
-        scatterOp.getLoc(), scatterOp.getIndices(), reassoc);
+    auto collapseOp = tensor::CollapseShapeOp::create(
+        rewriter, scatterOp.getLoc(), scatterOp.getIndices(), reassoc);
 
     rewriter.modifyOpInPlace(scatterOp, [&]() {
       scatterOp.setOperand(ScatterOp::kIndicesOpNum, collapseOp.getResult());
@@ -559,8 +560,8 @@
     SmallVector<OpFoldResult> sizes =
         tensor::getMixedSizes(rewriter, loc, destVal);
     SmallVector<OpFoldResult> strides(rank, rewriter.getIndexAttr(1));
-    return rewriter.create<tensor::InsertSliceOp>(loc, val, destVal, offsets,
-                                                  sizes, strides);
+    return tensor::InsertSliceOp::create(rewriter, loc, val, destVal, offsets,
+                                         sizes, strides);
   } else if (options.rankReductionStrategy ==
              linalg::ControlDropUnitDims::RankReductionStrategy::
                  ReassociativeReshape) {
@@ -568,8 +569,8 @@
         getReassociationIndicesForReshape(cast<ShapedType>(val.getType()),
                                           cast<ShapedType>(destVal.getType()));
     assert(reassoc.has_value());
-    return rewriter.create<tensor::ExpandShapeOp>(loc, destVal.getType(), val,
-                                                  reassoc.value());
+    return tensor::ExpandShapeOp::create(rewriter, loc, destVal.getType(), val,
+                                         reassoc.value());
   } else {
     llvm_unreachable("unhandled rank reduction strategy");
   }
@@ -599,7 +600,7 @@
 
     auto newInputType = cast<ShapedType>(newInput->getType());
     auto unitFoldingBuilder = [&](ArrayRef<BlockArgument> nonUnitIndices) {
-      Value zero = rewriter.create<arith::ConstantIndexOp>(loc, 0);
+      Value zero = arith::ConstantIndexOp::create(rewriter, loc, 0);
       int nonUnitArgIdx = 0;
       return llvm::map_to_vector(
           llvm::seq<int64_t>(inputType.getRank()), [&](int64_t dim) -> Value {
@@ -681,8 +682,8 @@
       return failure();
     }
 
-    auto newGather = rewriter.create<GatherOp>(
-        gatherOp.getLoc(), TypeRange{reducedOutput.getType()},
+    auto newGather = GatherOp::create(
+        rewriter, gatherOp.getLoc(), TypeRange{reducedOutput.getType()},
         ValueRange{reducedSource, reducedIndices}, ValueRange{reducedOutput},
         gatherOp.getDimensionMap());
     rewriter.replaceOp(gatherOp,
@@ -748,8 +749,8 @@
       return failure();
     }
 
-    auto newScatter = rewriter.create<ScatterOp>(
-        scatterOp.getLoc(), TypeRange{original.getType()},
+    auto newScatter = ScatterOp::create(
+        rewriter, scatterOp.getLoc(), TypeRange{original.getType()},
         ValueRange{updates, indices}, ValueRange{original},
         scatterOp.getDimensionMap());
     rewriter.inlineRegionBefore(scatterOp.getRegion(), newScatter.getRegion(),
@@ -987,9 +988,9 @@
     maskOperand = inputOperands[4];
   }
 
-  auto collapsedOp = rewriter.create<AttentionOp>(
-      origOp.getLoc(), resultTypes, inputOperands[0], inputOperands[1],
-      inputOperands[2], inputOperands[3], outputOperands[0],
+  auto collapsedOp = AttentionOp::create(
+      rewriter, origOp.getLoc(), resultTypes, inputOperands[0],
+      inputOperands[1], inputOperands[2], inputOperands[3], outputOperands[0],
       rewriter.getAffineMapArrayAttr(indexingMaps), maskOperand);
   rewriter.inlineRegionBefore(origOp.getRegion(), collapsedOp.getRegion(),
                               collapsedOp.getRegion().begin());
@@ -1031,11 +1032,13 @@
       if (isa<MemRefType>(collapsedOpResult.getType())) {
         MemRefType expandShapeResultType = MemRefType::get(
             originalResultType.getShape(), originalResultType.getElementType());
-        result = rewriter.create<memref::ExpandShapeOp>(
-            loc, expandShapeResultType, collapsedOpResult, reassociation);
+        result =
+            memref::ExpandShapeOp::create(rewriter, loc, expandShapeResultType,
+                                          collapsedOpResult, reassociation);
       } else {
-        result = rewriter.create<tensor::ExpandShapeOp>(
-            loc, originalResultType, collapsedOpResult, reassociation);
+        result =
+            tensor::ExpandShapeOp::create(rewriter, loc, originalResultType,
+                                          collapsedOpResult, reassociation);
       }
       results.push_back(result);
     } else {
@@ -1081,8 +1084,8 @@
       auto resultTypes = llvm::map_to_vector(
           newOperands.take_back(attentionOp.getNumDpsInits()),
           [](Value v) { return v.getType(); });
-      auto newOp = b.create<AttentionOp>(
-          op.getLoc(), resultTypes,
+      auto newOp = AttentionOp::create(
+          b, op.getLoc(), resultTypes,
           newOperands.take_front(attentionOp.getNumDpsInputs()),
           newOperands.take_back(attentionOp.getNumDpsInits()),
           b.getAffineMapArrayAttr(newIndexingMaps));
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/RewriteFft.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/RewriteFft.cpp
index 2a3fdcb..e367b97 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/RewriteFft.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/RewriteFft.cpp
@@ -38,7 +38,7 @@
     SmallVector<OpFoldResult> mixedSizes =
         tensor::getMixedSizes(b, b.getLoc(), real);
     Value emptyTensor =
-        b.create<tensor::EmptyOp>(mixedSizes, realType.getElementType());
+        tensor::EmptyOp::create(b, mixedSizes, realType.getElementType());
 
     SmallVector<AffineMap> maps;
     maps.push_back(
@@ -59,25 +59,25 @@
         values.push_back(b.getI64IntegerAttr(r));
       }
       auto type = RankedTensorType::get({fftLength}, b.getI64Type());
-      return b.create<arith::ConstantOp>(
-          type, DenseIntElementsAttr::get(type, values));
+      return arith::ConstantOp::create(b, type,
+                                       DenseIntElementsAttr::get(type, values));
     };
     Value indices = getBitReversalBuffer(b, fftLength);
-    auto genericOp = b.create<linalg::GenericOp>(
-        TypeRange{realType}, indices, emptyTensor, maps, iterTypes,
+    auto genericOp = linalg::GenericOp::create(
+        b, TypeRange{realType}, indices, emptyTensor, maps, iterTypes,
         [&](OpBuilder &b, Location loc, ValueRange args) {
           SmallVector<Value> ivs;
           for (auto i : llvm::seq<uint64_t>(0, rank - 1)) {
-            ivs.push_back(b.create<linalg::IndexOp>(loc, i));
+            ivs.push_back(linalg::IndexOp::create(b, loc, i));
           }
           ivs.push_back(
-              b.create<arith::IndexCastOp>(loc, b.getIndexType(), args[0]));
-          b.create<linalg::YieldOp>(
-              loc, b.create<tensor::ExtractOp>(loc, real, ivs).getResult());
+              arith::IndexCastOp::create(b, loc, b.getIndexType(), args[0]));
+          linalg::YieldOp::create(
+              b, loc, tensor::ExtractOp::create(b, loc, real, ivs).getResult());
         });
     return {genericOp.getResult(0),
-            b.create<arith::ConstantOp>(
-                realType,
+            arith::ConstantOp::create(
+                b, realType,
                 DenseFPElementsAttr::get(
                     realType, llvm::cast<Attribute>(b.getF32FloatAttr(0.0))))};
   };
@@ -96,20 +96,20 @@
       imag.push_back(b.getF32FloatAttr(v.imag()));
     }
     auto type = RankedTensorType::get({mh}, b.getF32Type());
-    return {
-        b.create<arith::ConstantOp>(type, DenseFPElementsAttr::get(type, real)),
-        b.create<arith::ConstantOp>(type,
-                                    DenseFPElementsAttr::get(type, imag))};
+    return {arith::ConstantOp::create(b, type,
+                                      DenseFPElementsAttr::get(type, real)),
+            arith::ConstantOp::create(b, type,
+                                      DenseFPElementsAttr::get(type, imag))};
   };
 
   int64_t lognPlus1 = std::log(fftLength) / std::log<int64_t>(2) + 1;
   for (auto s : llvm::seq<uint64_t>(1, lognPlus1)) {
     SmallVector<Value> inputs;
-    inputs.push_back(b.create<arith::ConstantIndexOp>(s));
+    inputs.push_back(arith::ConstantIndexOp::create(b, s));
     inputs.append(getCoeffConstants(b, s));
-    results = b.create<IREE::LinalgExt::FftOp>(
-                   TypeRange{results[0].getType(), results[1].getType()},
-                   inputs, results)
+    results = IREE::LinalgExt::FftOp::create(
+                  b, TypeRange{results[0].getType(), results[1].getType()},
+                  inputs, results)
                   .getResults();
   }
 
@@ -122,10 +122,10 @@
   SmallVector<OpFoldResult> sizes =
       tensor::getMixedSizes(b, b.getLoc(), operand);
   sizes.back() = b.getIndexAttr(shape.back());
-  Value real =
-      b.create<tensor::ExtractSliceOp>(ty, results[0], offsets, sizes, strides);
-  Value imag =
-      b.create<tensor::ExtractSliceOp>(ty, results[1], offsets, sizes, strides);
+  Value real = tensor::ExtractSliceOp::create(b, ty, results[0], offsets, sizes,
+                                              strides);
+  Value imag = tensor::ExtractSliceOp::create(b, ty, results[1], offsets, sizes,
+                                              strides);
 
   return std::make_pair(real, imag);
 }
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/SplitReduction.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/SplitReduction.cpp
index 1319ad3..ec4d912 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/SplitReduction.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/SplitReduction.cpp
@@ -115,8 +115,8 @@
       RankedTensorType::get(expandedShape, valueElementType);
 
   // Expand input values shape for parallel processing
-  Value valuesExpanded = rewriter.create<tensor::ExpandShapeOp>(
-      loc, valuesExpandedType, valuesOrig, reassociationIndices);
+  Value valuesExpanded = tensor::ExpandShapeOp::create(
+      rewriter, loc, valuesExpandedType, valuesOrig, reassociationIndices);
 
   // Expand input indices shape for parallel processing if they exist
   std::optional<Value> indicesExpanded;
@@ -124,8 +124,9 @@
     // Type inputElementType = cast<ShapedType>(inputIndices->getType());
     Type indicesExpandedType =
         RankedTensorType::get(expandedShape, indicesElementType);
-    indicesExpanded = rewriter.create<tensor::ExpandShapeOp>(
-        loc, indicesExpandedType, inputIndices.value(), reassociationIndices);
+    indicesExpanded = tensor::ExpandShapeOp::create(
+        rewriter, loc, indicesExpandedType, inputIndices.value(),
+        reassociationIndices);
   }
 
   // Define the expanded output types
@@ -141,13 +142,15 @@
   for (auto i : llvm::seq<int64_t>(0, valuesExpandedType.getRank())) {
     if (valuesExpandedType.isDynamicDim(i)) {
       dynSizes.push_back(
-          rewriter.create<tensor::DimOp>(loc, valuesExpanded, i));
+          tensor::DimOp::create(rewriter, loc, valuesExpanded, i));
     }
   }
-  Value emptyTensorOutputValues = rewriter.create<tensor::EmptyOp>(
-      loc, outputValuesExpandedType.getShape(), valueElementType, dynSizes);
-  Value emptyTensorOutputIndices = rewriter.create<tensor::EmptyOp>(
-      loc, outputIndicesExpandedType.getShape(), indicesElementType, dynSizes);
+  Value emptyTensorOutputValues = tensor::EmptyOp::create(
+      rewriter, loc, outputValuesExpandedType.getShape(), valueElementType,
+      dynSizes);
+  Value emptyTensorOutputIndices = tensor::EmptyOp::create(
+      rewriter, loc, outputIndicesExpandedType.getShape(), indicesElementType,
+      dynSizes);
 
   // Initialize indices to positive infinity and values to negative infinity
   // for a top (maxk) comparison.
@@ -161,15 +164,15 @@
                         /*Negative=*/true);
     negInfAttr = rewriter.getFloatAttr(valueElementType, negApFloat);
   }
-  Value negInf = rewriter.create<arith::ConstantOp>(loc, negInfAttr);
+  Value negInf = arith::ConstantOp::create(rewriter, loc, negInfAttr);
   TypedAttr posInfAttr =
       rewriter.getIntegerAttr(indicesElementType, APInt::getSignedMaxValue(32));
-  Value posInf = rewriter.create<arith::ConstantOp>(loc, posInfAttr);
+  Value posInf = arith::ConstantOp::create(rewriter, loc, posInfAttr);
   Value negInfTensor =
-      rewriter.create<linalg::FillOp>(loc, negInf, emptyTensorOutputValues)
+      linalg::FillOp::create(rewriter, loc, negInf, emptyTensorOutputValues)
           .result();
   Value posInfTensor =
-      rewriter.create<linalg::FillOp>(loc, posInf, emptyTensorOutputIndices)
+      linalg::FillOp::create(rewriter, loc, posInf, emptyTensorOutputIndices)
           .result();
 
   SmallVector<Type> parallelTopkResultTypes = {outputValuesExpandedType,
@@ -181,8 +184,8 @@
   SmallVector<Value> parallelTopkOuts = {negInfTensor, posInfTensor};
 
   // Parallel topk
-  auto parallelTopkOp = rewriter.create<iree_compiler::IREE::LinalgExt::TopkOp>(
-      loc,
+  auto parallelTopkOp = iree_compiler::IREE::LinalgExt::TopkOp::create(
+      rewriter, loc,
       /*resultTypes=*/
       parallelTopkResultTypes,
       /*ins=*/parallelTopkIns,
@@ -208,8 +211,8 @@
   SmallVector<AffineMap> indexingMaps = {mapIdentity};
   SmallVector<utils::IteratorType> iterators(parallelIndicesRank,
                                              utils::IteratorType::parallel);
-  Value mSplitVal = rewriter.create<arith::ConstantIntOp>(
-      loc, parallelIndicesType.getElementType(), kDimParallelSize);
+  Value mSplitVal = arith::ConstantIntOp::create(
+      rewriter, loc, parallelIndicesType.getElementType(), kDimParallelSize);
   return rewriter
       .create<linalg::GenericOp>(
           loc,
@@ -217,14 +220,15 @@
           /*inputs=*/ValueRange{},
           /*outputs=*/ValueRange{parallelIndices}, indexingMaps, iterators,
           [&](OpBuilder &b, Location loc, ValueRange args) {
-            Value splitIndex = b.create<linalg::IndexOp>(loc, splitDimParallel);
-            Value splitIndexInt = b.create<arith::IndexCastOp>(
-                loc, parallelIndicesType.getElementType(), splitIndex);
+            Value splitIndex =
+                linalg::IndexOp::create(b, loc, splitDimParallel);
+            Value splitIndexInt = arith::IndexCastOp::create(
+                b, loc, parallelIndicesType.getElementType(), splitIndex);
             Value mOffset =
-                b.create<arith::MulIOp>(loc, mSplitVal, splitIndexInt);
+                arith::MulIOp::create(b, loc, mSplitVal, splitIndexInt);
             Value updatedParallelIndex =
-                b.create<arith::AddIOp>(loc, mOffset, args[0]);
-            b.create<linalg::YieldOp>(loc, updatedParallelIndex);
+                arith::AddIOp::create(b, loc, mOffset, args[0]);
+            linalg::YieldOp::create(b, loc, updatedParallelIndex);
           })
       .getResult(0);
 }
@@ -251,19 +255,19 @@
       RankedTensorType::get(collapsedShape, indicesElementType);
 
   // Collapse collapse parallel output for the input of final reduction
-  Value valuesCollapsed = rewriter.create<tensor::CollapseShapeOp>(
-      loc, valuesCollapsedType, parallelTopkOp.getResults()[0],
+  Value valuesCollapsed = tensor::CollapseShapeOp::create(
+      rewriter, loc, valuesCollapsedType, parallelTopkOp.getResults()[0],
       reassociationIndices);
-  Value indicesCollapsed = rewriter.create<tensor::CollapseShapeOp>(
-      loc, indicesCollapsedType, updatedParallelIndices, reassociationIndices);
+  Value indicesCollapsed = tensor::CollapseShapeOp::create(
+      rewriter, loc, indicesCollapsedType, updatedParallelIndices,
+      reassociationIndices);
 
   // Combined final topk
-  auto reductionTopkOp =
-      rewriter.create<iree_compiler::IREE::LinalgExt::TopkOp>(
-          loc,
-          /*resultTypes=*/topkOp->getResultTypes(),
-          /*ins=*/ValueRange{valuesCollapsed, indicesCollapsed},
-          /*outs=*/topkOp.getOutputs(), kDimOrig);
+  auto reductionTopkOp = iree_compiler::IREE::LinalgExt::TopkOp::create(
+      rewriter, loc,
+      /*resultTypes=*/topkOp->getResultTypes(),
+      /*ins=*/ValueRange{valuesCollapsed, indicesCollapsed},
+      /*outs=*/topkOp.getOutputs(), kDimOrig);
   rewriter.cloneRegionBefore(topkOp.getRegion(), reductionTopkOp.getRegion(),
                              reductionTopkOp.getRegion().end());
   return reductionTopkOp;
@@ -448,8 +452,8 @@
   auto reassociation =
       getReassociationIndicesForReshape(originalType, expandedType);
   assert(reassociation && "failed to infer reassociation indices from types");
-  return builder.create<tensor::ExpandShapeOp>(loc, expandedType, value,
-                                               *reassociation);
+  return tensor::ExpandShapeOp::create(builder, loc, expandedType, value,
+                                       *reassociation);
 }
 
 // Returns an expanded input AffineMap by splitting the given reduction
@@ -515,10 +519,10 @@
       tensor::getMixedSizes(builder, loc, origInit);
   shape.insert(shape.begin() + insertSplitIndex,
                builder.getIndexAttr(insertDimSize));
-  Value identityVal = builder.create<arith::ConstantOp>(
-      loc, elemType, cast<TypedAttr>(identityAttr));
-  Value empty = builder.create<tensor::EmptyOp>(loc, shape, elemType);
-  return builder.create<linalg::FillOp>(loc, identityVal, empty).getResult(0);
+  Value identityVal = arith::ConstantOp::create(builder, loc, elemType,
+                                                cast<TypedAttr>(identityAttr));
+  Value empty = tensor::EmptyOp::create(builder, loc, shape, elemType);
+  return linalg::FillOp::create(builder, loc, identityVal, empty).getResult(0);
 }
 
 FailureOr<linalg::SplitReductionResult>
@@ -647,29 +651,29 @@
   // linalg.index). The result yields the local maximum values and their
   // corresponding local indices within each tile. These local indices will be
   // adjusted to global indices in step 2.
-  auto partialArgmax = rewriter.create<linalg::GenericOp>(
-      loc, TypeRange{identityValue.getType(), identityIndex.getType()},
-      newInputs, ValueRange{identityValue, identityIndex}, newMaps,
-      newIteratorTypes,
+  auto partialArgmax = linalg::GenericOp::create(
+      rewriter, loc,
+      TypeRange{identityValue.getType(), identityIndex.getType()}, newInputs,
+      ValueRange{identityValue, identityIndex}, newMaps, newIteratorTypes,
       [reductionDim](OpBuilder &b, Location loc, ValueRange args) {
         Value in = args[0];
         Value outVal = args[1];
         Value outIdx = args[2];
-        Value reductionIdx = b.create<linalg::IndexOp>(loc, reductionDim + 1);
+        Value reductionIdx = linalg::IndexOp::create(b, loc, reductionDim + 1);
         if (outIdx.getType() != reductionIdx.getType())
-          reductionIdx =
-              b.create<arith::IndexCastOp>(loc, outIdx.getType(), reductionIdx);
-        Value maxVal = b.create<arith::MaximumFOp>(loc, in, outVal);
-        Value cmp =
-            b.create<arith::CmpFOp>(loc, arith::CmpFPredicate::OGT, in, outVal);
+          reductionIdx = arith::IndexCastOp::create(b, loc, outIdx.getType(),
+                                                    reductionIdx);
+        Value maxVal = arith::MaximumFOp::create(b, loc, in, outVal);
+        Value cmp = arith::CmpFOp::create(b, loc, arith::CmpFPredicate::OGT, in,
+                                          outVal);
         Value selIdx =
-            b.create<arith::SelectOp>(loc, cmp, reductionIdx, outIdx);
-        b.create<linalg::YieldOp>(loc, ValueRange{maxVal, selIdx});
+            arith::SelectOp::create(b, loc, cmp, reductionIdx, outIdx);
+        linalg::YieldOp::create(b, loc, ValueRange{maxVal, selIdx});
       });
 
   // Step 2: Final reduction that computes global indices and selects the one
   // corresponding to the maximum value.
-  Value tileSize = rewriter.create<arith::ConstantIndexOp>(loc, ratio);
+  Value tileSize = arith::ConstantIndexOp::create(rewriter, loc, ratio);
   unsigned intermRank =
       cast<RankedTensorType>(identityValue.getType()).getRank();
   AffineMap valueMap = rewriter.getMultiDimIdentityMap(intermRank);
@@ -689,8 +693,8 @@
       AffineMap::get(intermRank, 0, resultExprs, rewriter.getContext());
   SmallVector<AffineMap> finalReductionMaps = {valueMap, indexMap, outputMap,
                                                outputMap};
-  auto finalReduction = rewriter.create<linalg::GenericOp>(
-      loc, genericOp.getResultTypes(),
+  auto finalReduction = linalg::GenericOp::create(
+      rewriter, loc, genericOp.getResultTypes(),
       ValueRange{partialArgmax.getResult(0), partialArgmax.getResult(1)},
       genericOp.getDpsInits(), finalReductionMaps, reductionIteratorTypes,
       [combinerOps, tileSize, insertSplitDimension](OpBuilder &b, Location loc,
@@ -699,20 +703,21 @@
         Value local = inputs[1];
         Value outVal = inputs[2];
         Value outIdx = inputs[3];
-        Value outer = b.create<linalg::IndexOp>(loc, insertSplitDimension);
-        Value offset = b.create<arith::MulIOp>(loc, outer, tileSize);
+        Value outer = linalg::IndexOp::create(b, loc, insertSplitDimension);
+        Value offset = arith::MulIOp::create(b, loc, outer, tileSize);
         if (offset.getType() != local.getType())
-          offset = b.create<arith::IndexCastOp>(loc, local.getType(), offset);
+          offset = arith::IndexCastOp::create(b, loc, local.getType(), offset);
         // gidx = outer * ratio + local.
-        Value gidx = b.create<arith::AddIOp>(loc, offset, local);
+        Value gidx = arith::AddIOp::create(b, loc, offset, local);
         Operation *clonedMax = b.clone(*combinerOps.maxOp);
         clonedMax->setOperands({val, outVal});
         Operation *clonedCmp = b.clone(*combinerOps.cmpOp);
         clonedCmp->setOperands({val, outVal});
         Operation *clonedSel = b.clone(*combinerOps.selectOp);
         clonedSel->setOperands({clonedCmp->getResult(0), gidx, outIdx});
-        b.create<linalg::YieldOp>(
-            loc, ValueRange{clonedMax->getResult(0), clonedSel->getResult(0)});
+        linalg::YieldOp::create(
+            b, loc,
+            ValueRange{clonedMax->getResult(0), clonedSel->getResult(0)});
       });
 
   rewriter.replaceOp(genericOp, finalReduction.getResults());
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/TileAttention.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/TileAttention.cpp
index f092fe8..7a94bfb 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/TileAttention.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/TileAttention.cpp
@@ -72,9 +72,9 @@
       applyPermutationMap<OpFoldResult>(maxMap, sizes);
 
   Type f32Type = rewriter.getF32Type();
-  Value acc = rewriter.create<tensor::EmptyOp>(loc, accSize, f32Type);
+  Value acc = tensor::EmptyOp::create(rewriter, loc, accSize, f32Type);
   Value rowRedEmpty =
-      rewriter.create<tensor::EmptyOp>(loc, rowRedSize, f32Type);
+      tensor::EmptyOp::create(rewriter, loc, rowRedSize, f32Type);
 
   Value accInit =
       arith::getIdentityValue(arith::AtomicRMWKind::addf, f32Type, rewriter,
@@ -85,13 +85,14 @@
   Value sumInit = arith::getIdentityValue(arith::AtomicRMWKind::addf, f32Type,
                                           rewriter, loc);
 
-  Value accFill = rewriter.create<linalg::FillOp>(loc, ValueRange{accInit}, acc)
-                      .getResult(0);
+  Value accFill =
+      linalg::FillOp::create(rewriter, loc, ValueRange{accInit}, acc)
+          .getResult(0);
   Value maxFill =
-      rewriter.create<linalg::FillOp>(loc, ValueRange{maxInit}, rowRedEmpty)
+      linalg::FillOp::create(rewriter, loc, ValueRange{maxInit}, rowRedEmpty)
           .getResult(0);
   Value sumFill =
-      rewriter.create<linalg::FillOp>(loc, ValueRange{sumInit}, rowRedEmpty)
+      linalg::FillOp::create(rewriter, loc, ValueRange{sumInit}, rowRedEmpty)
           .getResult(0);
 
   // Create online attention op.
@@ -101,8 +102,9 @@
 
   Value mask = attnOp.getMask() ? attnOp.getMask() : Value();
 
-  OnlineAttentionOp onlineAttn = rewriter.create<OnlineAttentionOp>(
-      loc, TypeRange{accFill.getType(), maxFill.getType(), sumFill.getType()},
+  OnlineAttentionOp onlineAttn = OnlineAttentionOp::create(
+      rewriter, loc,
+      TypeRange{accFill.getType(), maxFill.getType(), sumFill.getType()},
       attnOp.getQuery(), attnOp.getKey(), attnOp.getValue(), attnOp.getScale(),
       mask, accFill, maxFill, sumFill,
       rewriter.getAffineMapArrayAttr(indexingMaps),
@@ -126,20 +128,20 @@
   SmallVector<utils::IteratorType> iteratorTypes(compressedMaps[0].getNumDims(),
                                                  utils::IteratorType::parallel);
 
-  auto genericOp = rewriter.create<linalg::GenericOp>(
-      loc, attnOp.getOutput().getType(), ValueRange{sum, x}, attnOp.getOutput(),
-      compressedMaps, iteratorTypes,
+  auto genericOp = linalg::GenericOp::create(
+      rewriter, loc, attnOp.getOutput().getType(), ValueRange{sum, x},
+      attnOp.getOutput(), compressedMaps, iteratorTypes,
       [&](OpBuilder &b, Location loc, ValueRange args) {
-        Value one = b.create<arith::ConstantOp>(
-            loc, b.getFloatAttr(args[0].getType(), 1.0));
-        Value reciprocal = b.create<arith::DivFOp>(loc, one, args[0]);
+        Value one = arith::ConstantOp::create(
+            b, loc, b.getFloatAttr(args[0].getType(), 1.0));
+        Value reciprocal = arith::DivFOp::create(b, loc, one, args[0]);
         // Both sum and x are in fp32, as created earlier, so we only need
         // to cast after the mul.
-        Value result = b.create<arith::MulFOp>(loc, reciprocal, args[1]);
+        Value result = arith::MulFOp::create(b, loc, reciprocal, args[1]);
         // Cast result to the required type by attention output.
         result = convertScalarToDtype(b, loc, result, args[2].getType(),
                                       /*isUnsignedCast=*/false);
-        b.create<linalg::YieldOp>(loc, result);
+        linalg::YieldOp::create(b, loc, result);
       });
   ops.push_back(genericOp);
 
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/TransposeFusion.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/TransposeFusion.cpp
index 31544a2..697b904 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/TransposeFusion.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/TransposeFusion.cpp
@@ -171,10 +171,10 @@
         tensor::getMixedSizes(rewriter, loc, value);
     applyPermutationToVector(transVShape, perm);
     Value initTransV =
-        rewriter.create<tensor::EmptyOp>(loc, transVShape, valueElType)
+        tensor::EmptyOp::create(rewriter, loc, transVShape, valueElType)
             .getResult();
     Value transposeV =
-        rewriter.create<linalg::TransposeOp>(loc, value, initTransV, perm)
+        linalg::TransposeOp::create(rewriter, loc, value, initTransV, perm)
             ->getResult(0);
 
     // Generate transpose V map.
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/VectorizeIREELinalgExtOps.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/VectorizeIREELinalgExtOps.cpp
index 06275f0..78241ff 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/VectorizeIREELinalgExtOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/Transforms/VectorizeIREELinalgExtOps.cpp
@@ -34,12 +34,13 @@
     }
     Location loc = mapScatterOp.getLoc();
     rewriter.setInsertionPoint(mapScatterOp);
-    Value zero = rewriter.create<arith::ConstantIndexOp>(loc, 0);
+    Value zero = arith::ConstantIndexOp::create(rewriter, loc, 0);
     SmallVector<Value> zeros(inputType.getRank(), zero);
     auto inputVectorType =
         VectorType::get(inputType.getShape(), inputType.getElementType());
-    Value inputVector = rewriter.create<vector::TransferReadOp>(
-        loc, inputVectorType, mapScatterOp.getInput(), /*indices=*/zeros,
+    Value inputVector = vector::TransferReadOp::create(
+        rewriter, loc, inputVectorType, mapScatterOp.getInput(),
+        /*indices=*/zeros,
         /*padding=*/std::nullopt);
     auto vectorizedMapScatterOp =
         clone(rewriter, mapScatterOp, mapScatterOp.getResultTypes(),
diff --git a/compiler/src/iree/compiler/Dialect/LinalgExt/Utils/Utils.cpp b/compiler/src/iree/compiler/Dialect/LinalgExt/Utils/Utils.cpp
index 5d6aeaa..0f5684c 100644
--- a/compiler/src/iree/compiler/Dialect/LinalgExt/Utils/Utils.cpp
+++ b/compiler/src/iree/compiler/Dialect/LinalgExt/Utils/Utils.cpp
@@ -60,7 +60,7 @@
 Value getDimValue(OpBuilder &builder, Location loc, Value v, int64_t dim) {
   ShapedType type = cast<ShapedType>(v.getType());
   if (!type.isDynamicDim(dim)) {
-    return builder.create<arith::ConstantIndexOp>(loc, type.getDimSize(dim));
+    return arith::ConstantIndexOp::create(builder, loc, type.getDimSize(dim));
   }
   return TypeSwitch<Type, Value>(v.getType())
       .Case<RankedTensorType>([&](RankedTensorType t) -> Value {
@@ -101,11 +101,11 @@
                     ArrayRef<OpFoldResult> strides) {
   return TypeSwitch<Type, Operation *>(src.getType())
       .Case<RankedTensorType>([&](RankedTensorType t) -> Operation * {
-        return b.create<tensor::ExtractSliceOp>(loc, src, offsets, sizes,
-                                                strides);
+        return tensor::ExtractSliceOp::create(b, loc, src, offsets, sizes,
+                                              strides);
       })
       .Case<MemRefType>([&](MemRefType type) -> Operation * {
-        return b.create<memref::SubViewOp>(loc, src, offsets, sizes, strides);
+        return memref::SubViewOp::create(b, loc, src, offsets, sizes, strides);
       })
       .Default([&](Type t) -> Operation * {
         assert(false && "invalid type");
@@ -117,11 +117,11 @@
   return TypeSwitch<Type, Value>(src.getType())
       .Case<RankedTensorType>([&](RankedTensorType t) -> Value {
         assert(isa<RankedTensorType>(type) && "expected compatible type");
-        return b.create<tensor::CastOp>(loc, type, src)->getResult(0);
+        return tensor::CastOp::create(b, loc, type, src)->getResult(0);
       })
       .Case<MemRefType>([&](MemRefType type) -> Value {
         assert(isa<MemRefType>(type) && "expected compatible type");
-        return b.create<memref::CastOp>(loc, type, src)->getResult(0);
+        return memref::CastOp::create(b, loc, type, src)->getResult(0);
       })
       .Default([&](Type t) {
         assert(false && "invalid type");
@@ -159,9 +159,10 @@
                                 Location loc, RewriterBase &rewriter) {
   ArrayRef<float> vector(val, rows * cols);
   SmallVector<int64_t> shape{rows, cols};
-  return rewriter.create<arith::ConstantOp>(
-      loc, DenseFPElementsAttr::get(
-               RankedTensorType::get(shape, rewriter.getF32Type()), vector));
+  return arith::ConstantOp::create(
+      rewriter, loc,
+      DenseFPElementsAttr::get(
+          RankedTensorType::get(shape, rewriter.getF32Type()), vector));
 }
 
 SmallVector<int64_t> asShapeWithAnyValueAsDynamic(ArrayRef<OpFoldResult> ofrs) {
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Conversion/FlowToStream/Patterns.cpp b/compiler/src/iree/compiler/Dialect/Stream/Conversion/FlowToStream/Patterns.cpp
index 43c74f9..3965c4d 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Conversion/FlowToStream/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Conversion/FlowToStream/Patterns.cpp
@@ -39,9 +39,9 @@
                                ConversionPatternRewriter &rewriter) {
   // TODO(benvanik): see if we can stash this on the side to avoid expensive
   // materialization of a bunch of redundant IR.
-  return rewriter.create<IREE::Stream::TensorSizeOfOp>(
-      loc, rewriter.getIndexType(), TypeAttr::get(tensorValue.getType()),
-      dynamicDims, affinityAttr);
+  return IREE::Stream::TensorSizeOfOp::create(
+      rewriter, loc, rewriter.getIndexType(),
+      TypeAttr::get(tensorValue.getType()), dynamicDims, affinityAttr);
 }
 
 struct ConvertTensorConstantOp
@@ -55,8 +55,8 @@
     // Capture the tensor constant strongly typed with constant lifetime.
     auto constantType = rewriter.getType<IREE::Stream::ResourceType>(
         IREE::Stream::Lifetime::Constant);
-    auto newOp = rewriter.create<IREE::Stream::TensorConstantOp>(
-        constantOp.getLoc(), constantType,
+    auto newOp = IREE::Stream::TensorConstantOp::create(
+        rewriter, constantOp.getLoc(), constantType,
         convertAttributeToStream(constantOp.getValue()),
         TypeAttr::get(constantOp.getType()), ValueRange{},
         executionAffinityAttr);
@@ -65,9 +65,9 @@
     auto unknownType = rewriter.getType<IREE::Stream::ResourceType>();
     auto constantSize = rewriter.createOrFold<IREE::Stream::ResourceSizeOp>(
         constantOp.getLoc(), rewriter.getIndexType(), newOp.getResult());
-    auto transferOp = rewriter.create<IREE::Stream::AsyncTransferOp>(
-        constantOp.getLoc(), unknownType, newOp.getResult(), constantSize,
-        constantSize,
+    auto transferOp = IREE::Stream::AsyncTransferOp::create(
+        rewriter, constantOp.getLoc(), unknownType, newOp.getResult(),
+        constantSize, constantSize,
         /*source_affinity=*/executionAffinityAttr,
         /*result_affinity=*/executionAffinityAttr);
     rewriter.replaceOpWithMultiple(constantOp,
@@ -94,8 +94,8 @@
     SmallVector<Value> dynamicDims;
     for (unsigned i = 0; i < resultType.getRank(); ++i) {
       if (resultType.isDynamicDim(i)) {
-        Value staticDim = rewriter.create<arith::ConstantIndexOp>(
-            constantOp.getLoc(), attrType.getDimSize(i));
+        Value staticDim = arith::ConstantIndexOp::create(
+            rewriter, constantOp.getLoc(), attrType.getDimSize(i));
         Value dynamicDim = rewriter
                                .create<IREE::Util::OptimizationBarrierOp>(
                                    constantOp.getLoc(), staticDim)
@@ -107,8 +107,8 @@
     // Capture the tensor constant strongly typed with constant lifetime.
     auto constantType = rewriter.getType<IREE::Stream::ResourceType>(
         IREE::Stream::Lifetime::Constant);
-    auto newOp = rewriter.create<IREE::Stream::TensorConstantOp>(
-        constantOp.getLoc(), constantType,
+    auto newOp = IREE::Stream::TensorConstantOp::create(
+        rewriter, constantOp.getLoc(), constantType,
         convertAttributeToStream(constantOp.getValue()),
         TypeAttr::get(resultType), dynamicDims, executionAffinityAttr);
 
@@ -116,9 +116,9 @@
     auto unknownType = rewriter.getType<IREE::Stream::ResourceType>();
     auto constantSize = rewriter.createOrFold<IREE::Stream::ResourceSizeOp>(
         constantOp.getLoc(), rewriter.getIndexType(), newOp.getResult());
-    auto transferOp = rewriter.create<IREE::Stream::AsyncTransferOp>(
-        constantOp.getLoc(), unknownType, newOp.getResult(), constantSize,
-        constantSize,
+    auto transferOp = IREE::Stream::AsyncTransferOp::create(
+        rewriter, constantOp.getLoc(), unknownType, newOp.getResult(),
+        constantSize, constantSize,
         /*source_affinity=*/executionAffinityAttr,
         /*result_affinity=*/executionAffinityAttr);
     rewriter.replaceOpWithMultiple(constantOp, {{transferOp, constantSize}});
@@ -150,10 +150,11 @@
         buildResultSizeOf(op.getLoc(), op.getResult(), op.getResultDims(),
                           resultAffinityAttr, rewriter);
     auto unknownType = rewriter.getType<IREE::Stream::ResourceType>();
-    Value cloneOp = rewriter.create<IREE::Stream::TensorCloneOp>(
-        op.getLoc(), unknownType, source.resource, op.getSource().getType(),
-        op.getSourceDims(), source.resourceSize, op.getResult().getType(),
-        flattenValues(adaptor.getResultDims()), resultSize, resultAffinityAttr);
+    Value cloneOp = IREE::Stream::TensorCloneOp::create(
+        rewriter, op.getLoc(), unknownType, source.resource,
+        op.getSource().getType(), op.getSourceDims(), source.resourceSize,
+        op.getResult().getType(), flattenValues(adaptor.getResultDims()),
+        resultSize, resultAffinityAttr);
     rewriter.replaceOpWithMultiple(op, {{cloneOp, resultSize}});
     return success();
   }
@@ -170,8 +171,8 @@
         buildResultSizeOf(op.getLoc(), op.getResult(), op.getResultDims(),
                           executionAffinityAttr, rewriter);
     auto unknownType = rewriter.getType<IREE::Stream::ResourceType>();
-    auto allocaOp = rewriter.create<IREE::Stream::AsyncAllocaOp>(
-        op.getLoc(), unknownType, resultSize, executionAffinityAttr);
+    auto allocaOp = IREE::Stream::AsyncAllocaOp::create(
+        rewriter, op.getLoc(), unknownType, resultSize, executionAffinityAttr);
     rewriter.replaceOpWithMultiple(op, {{allocaOp.getResult(), resultSize}});
     return success();
   }
@@ -188,8 +189,8 @@
         buildResultSizeOf(op.getLoc(), op.getResult(), op.getResultDims(),
                           executionAffinityAttr, rewriter);
     auto unknownType = rewriter.getType<IREE::Stream::ResourceType>();
-    auto emptyOp = rewriter.create<IREE::Stream::TensorEmptyOp>(
-        op.getLoc(), unknownType, op.getResult().getType(),
+    auto emptyOp = IREE::Stream::TensorEmptyOp::create(
+        rewriter, op.getLoc(), unknownType, op.getResult().getType(),
         flattenValues(adaptor.getResultDims()), resultSize,
         executionAffinityAttr);
     rewriter.replaceOpWithMultiple(op, {{emptyOp.getResult(), resultSize}});
@@ -208,8 +209,8 @@
         buildResultSizeOf(op.getLoc(), op.getResult(), op.getResultDims(),
                           executionAffinityAttr, rewriter);
     auto unknownType = rewriter.getType<IREE::Stream::ResourceType>();
-    auto splatOp = rewriter.create<IREE::Stream::TensorSplatOp>(
-        op.getLoc(), unknownType, adaptor.getValue().front(),
+    auto splatOp = IREE::Stream::TensorSplatOp::create(
+        rewriter, op.getLoc(), unknownType, adaptor.getValue().front(),
         op.getResult().getType(), flattenValues(adaptor.getResultDims()),
         resultSize, executionAffinityAttr);
     rewriter.replaceOpWithMultiple(op, {{splatOp, resultSize}});
@@ -228,11 +229,11 @@
                                           adaptor.getOperand(),
                                           executionAffinityAttr, rewriter);
     auto unknownType = rewriter.getType<IREE::Stream::ResourceType>();
-    auto cloneOp = rewriter.create<IREE::Stream::TensorCloneOp>(
-        op.getLoc(), unknownType, operand.resource, op.getOperand().getType(),
-        op.getOperandDims(), operand.resourceSize, op.getResult().getType(),
-        flattenValues(adaptor.getOperandDims()), operand.resourceSize,
-        executionAffinityAttr);
+    auto cloneOp = IREE::Stream::TensorCloneOp::create(
+        rewriter, op.getLoc(), unknownType, operand.resource,
+        op.getOperand().getType(), op.getOperandDims(), operand.resourceSize,
+        op.getResult().getType(), flattenValues(adaptor.getOperandDims()),
+        operand.resourceSize, executionAffinityAttr);
     rewriter.replaceOpWithMultiple(op, {{cloneOp, operand.resourceSize}});
     return success();
   }
@@ -252,11 +253,11 @@
     auto resultSize =
         buildResultSizeOf(op.getLoc(), op.getResult(), op.getOperandDims(),
                           executionAffinityAttr, rewriter);
-    auto encodeOp = rewriter.create<IREE::Stream::TensorEncodeOp>(
-        op.getLoc(), unknownType, operand.resource, op.getOperand().getType(),
-        op.getOperandDims(), operand.resourceSize, op.getResult().getType(),
-        flattenValues(adaptor.getResultDims()), resultSize,
-        executionAffinityAttr);
+    auto encodeOp = IREE::Stream::TensorEncodeOp::create(
+        rewriter, op.getLoc(), unknownType, operand.resource,
+        op.getOperand().getType(), op.getOperandDims(), operand.resourceSize,
+        op.getResult().getType(), flattenValues(adaptor.getResultDims()),
+        resultSize, executionAffinityAttr);
     rewriter.replaceOpWithMultiple(op, {{encodeOp, resultSize}});
     return success();
   }
@@ -271,8 +272,8 @@
       ConversionPatternRewriter &rewriter) const override {
     auto operand = resolveTensorOperands(op.getLoc(), op.getOperand(),
                                          adaptor.getOperand(), rewriter);
-    auto barrierOp = rewriter.create<IREE::Stream::AsyncBarrierOp>(
-        op.getLoc(), operand.resource.getType(), operand.resource,
+    auto barrierOp = IREE::Stream::AsyncBarrierOp::create(
+        rewriter, op.getLoc(), operand.resource.getType(), operand.resource,
         operand.resourceSize,
         /*affinity=*/executionAffinityAttr);
     rewriter.replaceOpWithMultiple(op, {{barrierOp, operand.resourceSize}});
@@ -293,9 +294,9 @@
     auto operand = resolveTensorOperands(op.getLoc(), op.getOperand(),
                                          adaptor.getOperand(), rewriter);
     auto unknownType = rewriter.getType<IREE::Stream::ResourceType>();
-    auto transferOp = rewriter.create<IREE::Stream::AsyncTransferOp>(
-        op.getLoc(), unknownType, operand.resource, operand.resourceSize,
-        operand.resourceSize,
+    auto transferOp = IREE::Stream::AsyncTransferOp::create(
+        rewriter, op.getLoc(), unknownType, operand.resource,
+        operand.resourceSize, operand.resourceSize,
         /*source_affinity=*/operand.affinity,
         /*result_affinity=*/executionAffinityAttr);
     rewriter.replaceOpWithMultiple(op, {{transferOp, operand.resourceSize}});
@@ -317,9 +318,9 @@
         buildResultSizeOf(op.getLoc(), op.getResult(), op.getResultDims(),
                           executionAffinityAttr, rewriter);
     auto unknownType = rewriter.getType<IREE::Stream::ResourceType>();
-    auto sliceOp = rewriter.create<IREE::Stream::TensorSliceOp>(
-        op.getLoc(), unknownType, source.resource, op.getSource().getType(),
-        op.getSourceDims(), source.resourceSize,
+    auto sliceOp = IREE::Stream::TensorSliceOp::create(
+        rewriter, op.getLoc(), unknownType, source.resource,
+        op.getSource().getType(), op.getSourceDims(), source.resourceSize,
         flattenValues(adaptor.getStartIndices()),
         flattenValues(adaptor.getLengths()), op.getResult().getType(),
         flattenValues(adaptor.getResultDims()), resultSize,
@@ -342,8 +343,8 @@
     auto update =
         transferTensorOperands(op.getLoc(), op.getUpdate(), adaptor.getUpdate(),
                                executionAffinityAttr, rewriter);
-    auto updateOp = rewriter.create<IREE::Stream::TensorUpdateOp>(
-        op.getLoc(), target.resource.getType(), target.resource,
+    auto updateOp = IREE::Stream::TensorUpdateOp::create(
+        rewriter, op.getLoc(), target.resource.getType(), target.resource,
         op.getTarget().getType(), flattenValues(adaptor.getTargetDims()),
         target.resourceSize, flattenValues(adaptor.getStartIndices()),
         update.resource, op.getUpdate().getType(), op.getUpdateDims(),
@@ -397,9 +398,9 @@
     // Scalar tensors get transferred without slicing.
     auto sourceEncoding = op.getSource().getType();
     if (isScalarTensor(sourceEncoding)) {
-      auto transferOp = rewriter.create<IREE::Stream::AsyncTransferOp>(
-          op.getLoc(), stagingType, source.resource, source.resourceSize,
-          source.resourceSize,
+      auto transferOp = IREE::Stream::AsyncTransferOp::create(
+          rewriter, op.getLoc(), stagingType, source.resource,
+          source.resourceSize, source.resourceSize,
           /*source_affinity=*/source.affinity,
           /*result_affinity=*/source.affinity);
       rewriter.replaceOpWithNewOp<IREE::Stream::TensorLoadOp>(
@@ -425,15 +426,16 @@
     auto resultEncoding =
         RankedTensorType::get(resultDims, sourceEncoding.getElementType(),
                               sourceEncoding.getEncoding());
-    Value resultSize = rewriter.create<IREE::Stream::TensorSizeOfOp>(
-        op.getLoc(), resultEncoding, ValueRange{}, source.affinity);
-    auto sliceOp = rewriter.create<IREE::Stream::TensorSliceOp>(
-        op.getLoc(), source.resource.getType(), source.resource, sourceEncoding,
-        convertedSourceDims, source.resourceSize, sliceIndices, sliceLengths,
-        resultEncoding, ValueRange{}, resultSize, source.affinity);
-    auto transferOp = rewriter.create<IREE::Stream::AsyncTransferOp>(
-        op.getLoc(), stagingType, sliceOp.getResult(), sliceOp.getResultSize(),
-        sliceOp.getResultSize(),
+    Value resultSize = IREE::Stream::TensorSizeOfOp::create(
+        rewriter, op.getLoc(), resultEncoding, ValueRange{}, source.affinity);
+    auto sliceOp = IREE::Stream::TensorSliceOp::create(
+        rewriter, op.getLoc(), source.resource.getType(), source.resource,
+        sourceEncoding, convertedSourceDims, source.resourceSize, sliceIndices,
+        sliceLengths, resultEncoding, ValueRange{}, resultSize,
+        source.affinity);
+    auto transferOp = IREE::Stream::AsyncTransferOp::create(
+        rewriter, op.getLoc(), stagingType, sliceOp.getResult(),
+        sliceOp.getResultSize(), sliceOp.getResultSize(),
         /*source_affinity=*/source.affinity,
         /*result_affinity=*/source.affinity);
     rewriter.replaceOpWithNewOp<IREE::Stream::TensorLoadOp>(
@@ -458,8 +460,8 @@
     auto stagingType = rewriter.getType<IREE::Stream::ResourceType>(
         IREE::Stream::Lifetime::Staging);
     if (target.resource.getType() == stagingType) {
-      auto storeOp = rewriter.create<IREE::Stream::TensorStoreOp>(
-          op.getLoc(), target.resource.getType(), target.resource,
+      auto storeOp = IREE::Stream::TensorStoreOp::create(
+          rewriter, op.getLoc(), target.resource.getType(), target.resource,
           op.getTarget().getType(), flattenValues(adaptor.getTargetDims()),
           target.resourceSize, flattenValues(adaptor.getIndices()),
           adaptor.getValue().front());
@@ -474,8 +476,8 @@
     indexSet.populate(convertedIndices);
     SmallVector<Value> lengths(convertedIndices.size(), indexSet.get(1));
     auto targetEncoding = op.getTarget().getType();
-    auto fillOp = rewriter.create<IREE::Stream::TensorFillOp>(
-        op.getLoc(), target.resource, targetEncoding,
+    auto fillOp = IREE::Stream::TensorFillOp::create(
+        rewriter, op.getLoc(), target.resource, targetEncoding,
         flattenValues(adaptor.getTargetDims()), target.resourceSize,
         convertedIndices, lengths, adaptor.getValue().front(), target.affinity);
     rewriter.replaceOpWithMultiple(op, {{fillOp, target.resourceSize}});
@@ -500,9 +502,9 @@
           IREE::Stream::Lifetime::Staging);
       auto traceSource = source.resource;
       if (source.resource.getType() != stagingType) {
-        traceSource = rewriter.create<IREE::Stream::AsyncTransferOp>(
-            op.getLoc(), stagingType, source.resource, source.resourceSize,
-            source.resourceSize,
+        traceSource = IREE::Stream::AsyncTransferOp::create(
+            rewriter, op.getLoc(), stagingType, source.resource,
+            source.resourceSize, source.resourceSize,
             /*source_affinity=*/source.affinity,
             /*result_affinity=*/source.affinity);
       }
@@ -583,9 +585,9 @@
         /*reduction=*/std::nullopt,
         static_cast<IREE::Stream::CollectiveElementType>(op.getElementType()));
 
-    auto zeroOffset = rewriter.create<arith::ConstantIndexOp>(op.getLoc(), 0);
-    auto elementCount = rewriter.create<arith::ConstantIndexOp>(
-        op.getLoc(), op.getType().getNumElements());
+    auto zeroOffset = arith::ConstantIndexOp::create(rewriter, op.getLoc(), 0);
+    auto elementCount = arith::ConstantIndexOp::create(
+        rewriter, op.getLoc(), op.getType().getNumElements());
     auto newTargetCast =
         transferTensorOperands(op.getLoc(), op.getTarget(), adaptor.getTarget(),
                                executionAffinityAttr, rewriter);
@@ -593,8 +595,8 @@
         transferTensorOperands(op.getLoc(), op.getSource(), adaptor.getSource(),
                                executionAffinityAttr, rewriter);
 
-    auto collectiveOp = rewriter.create<IREE::Stream::AsyncCollectiveOp>(
-        op.getLoc(), collectiveAttr,
+    auto collectiveOp = IREE::Stream::AsyncCollectiveOp::create(
+        rewriter, op.getLoc(), collectiveAttr,
         /*target=*/newTargetCast.resource,
         /*target_size=*/newTargetCast.resourceSize,
         /*target_offset=*/zeroOffset,
@@ -626,9 +628,9 @@
         static_cast<IREE::Stream::CollectiveReductionOp>(op.getReductionOp()),
         static_cast<IREE::Stream::CollectiveElementType>(op.getElementType()));
 
-    auto zeroOffset = rewriter.create<arith::ConstantIndexOp>(op.getLoc(), 0);
-    auto elementCount = rewriter.create<arith::ConstantIndexOp>(
-        op.getLoc(), op.getType().getNumElements());
+    auto zeroOffset = arith::ConstantIndexOp::create(rewriter, op.getLoc(), 0);
+    auto elementCount = arith::ConstantIndexOp::create(
+        rewriter, op.getLoc(), op.getType().getNumElements());
     auto newTargetCast =
         transferTensorOperands(op.getLoc(), op.getTarget(), adaptor.getTarget(),
                                executionAffinityAttr, rewriter);
@@ -636,8 +638,8 @@
         transferTensorOperands(op.getLoc(), op.getSource(), adaptor.getSource(),
                                executionAffinityAttr, rewriter);
 
-    auto collectiveOp = rewriter.create<IREE::Stream::AsyncCollectiveOp>(
-        op.getLoc(), collectiveAttr,
+    auto collectiveOp = IREE::Stream::AsyncCollectiveOp::create(
+        rewriter, op.getLoc(), collectiveAttr,
         /*target=*/newTargetCast.resource,
         /*target_size=*/newTargetCast.resourceSize,
         /*target_offset=*/zeroOffset,
@@ -669,9 +671,9 @@
         /*reduction=*/std::nullopt,
         static_cast<IREE::Stream::CollectiveElementType>(op.getElementType()));
 
-    auto zeroOffset = rewriter.create<arith::ConstantIndexOp>(op.getLoc(), 0);
-    auto elementCount = rewriter.create<arith::ConstantIndexOp>(
-        op.getLoc(), op.getType().getNumElements());
+    auto zeroOffset = arith::ConstantIndexOp::create(rewriter, op.getLoc(), 0);
+    auto elementCount = arith::ConstantIndexOp::create(
+        rewriter, op.getLoc(), op.getType().getNumElements());
     auto newTargetCast =
         transferTensorOperands(op.getLoc(), op.getTarget(), adaptor.getTarget(),
                                executionAffinityAttr, rewriter);
@@ -679,8 +681,8 @@
         transferTensorOperands(op.getLoc(), op.getSource(), adaptor.getSource(),
                                executionAffinityAttr, rewriter);
 
-    auto collectiveOp = rewriter.create<IREE::Stream::AsyncCollectiveOp>(
-        op.getLoc(), collectiveAttr,
+    auto collectiveOp = IREE::Stream::AsyncCollectiveOp::create(
+        rewriter, op.getLoc(), collectiveAttr,
         /*target=*/newTargetCast.resource,
         /*target_size=*/newTargetCast.resourceSize,
         /*target_offset=*/zeroOffset,
@@ -712,9 +714,9 @@
         static_cast<IREE::Stream::CollectiveReductionOp>(op.getReductionOp()),
         static_cast<IREE::Stream::CollectiveElementType>(op.getElementType()));
 
-    auto zeroOffset = rewriter.create<arith::ConstantIndexOp>(op.getLoc(), 0);
-    auto elementCount = rewriter.create<arith::ConstantIndexOp>(
-        op.getLoc(), op.getType().getNumElements());
+    auto zeroOffset = arith::ConstantIndexOp::create(rewriter, op.getLoc(), 0);
+    auto elementCount = arith::ConstantIndexOp::create(
+        rewriter, op.getLoc(), op.getType().getNumElements());
     auto newTargetCast =
         transferTensorOperands(op.getLoc(), op.getTarget(), adaptor.getTarget(),
                                executionAffinityAttr, rewriter);
@@ -722,8 +724,8 @@
         transferTensorOperands(op.getLoc(), op.getSource(), adaptor.getSource(),
                                executionAffinityAttr, rewriter);
 
-    auto collectiveOp = rewriter.create<IREE::Stream::AsyncCollectiveOp>(
-        op.getLoc(), collectiveAttr,
+    auto collectiveOp = IREE::Stream::AsyncCollectiveOp::create(
+        rewriter, op.getLoc(), collectiveAttr,
         /*target=*/newTargetCast.resource,
         /*target_size=*/newTargetCast.resourceSize,
         /*target_offset=*/zeroOffset,
@@ -755,9 +757,9 @@
         /*reduction=*/std::nullopt,
         static_cast<IREE::Stream::CollectiveElementType>(op.getElementType()));
 
-    auto zeroOffset = rewriter.create<arith::ConstantIndexOp>(op.getLoc(), 0);
-    auto elementCount = rewriter.create<arith::ConstantIndexOp>(
-        op.getLoc(), op.getType().getNumElements());
+    auto zeroOffset = arith::ConstantIndexOp::create(rewriter, op.getLoc(), 0);
+    auto elementCount = arith::ConstantIndexOp::create(
+        rewriter, op.getLoc(), op.getType().getNumElements());
     auto newTargetCast =
         transferTensorOperands(op.getLoc(), op.getTarget(), adaptor.getTarget(),
                                executionAffinityAttr, rewriter);
@@ -767,20 +769,20 @@
 
     // Pack send, recv into param. The values are checked to be within the
     // 16-bit range during lowering to Flow dialect.
-    auto send = rewriter.create<arith::IndexCastOp>(
-        op.getLoc(), rewriter.getI32Type(), adaptor.getSend());
-    auto lo = rewriter.create<arith::AndIOp>(
-        op.getLoc(), send,
-        rewriter.create<arith::ConstantIntOp>(op.getLoc(), 0xFFFF, 32));
-    auto recv = rewriter.create<arith::IndexCastOp>(
-        op.getLoc(), rewriter.getI32Type(), adaptor.getRecv());
-    auto hi = rewriter.create<arith::ShLIOp>(
-        op.getLoc(), recv,
-        rewriter.create<arith::ConstantIntOp>(op.getLoc(), 16, 32));
-    auto param = rewriter.create<arith::OrIOp>(op.getLoc(), hi, lo);
+    auto send = arith::IndexCastOp::create(
+        rewriter, op.getLoc(), rewriter.getI32Type(), adaptor.getSend());
+    auto lo = arith::AndIOp::create(
+        rewriter, op.getLoc(), send,
+        arith::ConstantIntOp::create(rewriter, op.getLoc(), 0xFFFF, 32));
+    auto recv = arith::IndexCastOp::create(
+        rewriter, op.getLoc(), rewriter.getI32Type(), adaptor.getRecv());
+    auto hi = arith::ShLIOp::create(
+        rewriter, op.getLoc(), recv,
+        arith::ConstantIntOp::create(rewriter, op.getLoc(), 16, 32));
+    auto param = arith::OrIOp::create(rewriter, op.getLoc(), hi, lo);
 
-    auto collectiveOp = rewriter.create<IREE::Stream::AsyncCollectiveOp>(
-        op.getLoc(), collectiveAttr,
+    auto collectiveOp = IREE::Stream::AsyncCollectiveOp::create(
+        rewriter, op.getLoc(), collectiveAttr,
         /*target=*/newTargetCast.resource,
         /*target_size=*/newTargetCast.resourceSize,
         /*target_offset=*/zeroOffset,
@@ -861,13 +863,13 @@
       }
     }
 
-    auto newOp = rewriter.create<IREE::Stream::TensorDispatchOp>(
-        op.getLoc(), resultTypes, flattenValues(adaptor.getWorkload()),
-        adaptor.getEntryPointsAttr(), operands, operandSizes,
-        rewriter.getTypeArrayAttr(operandEncodings), op.getArgumentDims(),
-        resultSizes, rewriter.getTypeArrayAttr(resultEncodings),
-        op.getResultDims(), adaptor.getTiedOperandsAttr(),
-        executionAffinityAttr);
+    auto newOp = IREE::Stream::TensorDispatchOp::create(
+        rewriter, op.getLoc(), resultTypes,
+        flattenValues(adaptor.getWorkload()), adaptor.getEntryPointsAttr(),
+        operands, operandSizes, rewriter.getTypeArrayAttr(operandEncodings),
+        op.getArgumentDims(), resultSizes,
+        rewriter.getTypeArrayAttr(resultEncodings), op.getResultDims(),
+        adaptor.getTiedOperandsAttr(), executionAffinityAttr);
     newOp->setDialectAttrs(
         llvm::make_filter_range(op->getDialectAttrs(), [](NamedAttribute attr) {
           return attr.getName() != "stream.affinity";
@@ -925,7 +927,7 @@
       IREE::Stream::AffinityAttr executionAffinityAttr,
       ConversionPatternRewriter &rewriter) const override {
     // Zero is going to be used for each operand to start.
-    auto zeroOffset = rewriter.create<arith::ConstantIndexOp>(op.getLoc(), 0);
+    auto zeroOffset = arith::ConstantIndexOp::create(rewriter, op.getLoc(), 0);
 
     // Query and resolve all operands and their sizes.
     SmallVector<Value> callOperands;
@@ -981,9 +983,9 @@
       }
     }
 
-    auto newOp = rewriter.create<IREE::Stream::AsyncCallOp>(
-        op.getLoc(), resultTypes, adaptor.getCalleeAttr(), callOperands,
-        callOperandSizes, callOperandOffsets, callOperandEnds,
+    auto newOp = IREE::Stream::AsyncCallOp::create(
+        rewriter, op.getLoc(), resultTypes, adaptor.getCalleeAttr(),
+        callOperands, callOperandSizes, callOperandOffsets, callOperandEnds,
         callOperandLengths, resultSizes, adaptor.getTiedOperandsAttr(),
         op.getArgAttrsAttr(), op.getResAttrsAttr(), executionAffinityAttr);
     newOp->setDialectAttrs(op->getDialectAttrs());
@@ -1041,8 +1043,8 @@
     }
   }
 
-  auto subspanOp = builder.create<IREE::Stream::BindingSubspanOp>(
-      arg.getLoc(), tensorType, arg, zero, dynamicDims);
+  auto subspanOp = IREE::Stream::BindingSubspanOp::create(
+      builder, arg.getLoc(), tensorType, arg, zero, dynamicDims);
   arg.replaceAllUsesExcept(subspanOp.getResult(), subspanOp);
 
   // If we needed to insert at a special point restore back to the original
@@ -1093,16 +1095,16 @@
   matchAndRewrite(IREE::Flow::ExecutableOp flowOp, OpAdaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
     // flow.executable -> stream.executable
-    auto streamOp = rewriter.create<IREE::Stream::ExecutableOp>(
-        flowOp.getLoc(), flowOp.getSymName());
+    auto streamOp = IREE::Stream::ExecutableOp::create(
+        rewriter, flowOp.getLoc(), flowOp.getSymName());
     streamOp.setVisibility(flowOp.getVisibility());
     streamOp->setDialectAttrs(flowOp->getDialectAttrs());
     rewriter.setInsertionPointToStart(&streamOp.getBody().front());
 
     // flow.executable.export -> stream.executable.export
     for (auto exportOp : flowOp.getOps<IREE::Flow::ExecutableExportOp>()) {
-      auto newOp = rewriter.create<IREE::Stream::ExecutableExportOp>(
-          exportOp.getLoc(), exportOp.getSymName(),
+      auto newOp = IREE::Stream::ExecutableExportOp::create(
+          rewriter, exportOp.getLoc(), exportOp.getSymName(),
           exportOp.getFunctionRefAttr());
       newOp->setDialectAttrs(exportOp->getDialectAttrs());
       if (!exportOp.getWorkgroupCount().empty()) {
@@ -1132,7 +1134,8 @@
                "flow dispatches have no results");
 
         rewriter.setInsertionPointToStart(&funcOp.front());
-        auto zero = rewriter.create<arith::ConstantIndexOp>(funcOp.getLoc(), 0);
+        auto zero =
+            arith::ConstantIndexOp::create(rewriter, funcOp.getLoc(), 0);
         for (auto arg : funcOp.front().getArguments()) {
           auto oldType = arg.getType();
           if (auto tensorType =
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Conversion/HALToStream/Patterns.cpp b/compiler/src/iree/compiler/Dialect/Stream/Conversion/HALToStream/Patterns.cpp
index 1d849a8..7b9311b 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Conversion/HALToStream/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Conversion/HALToStream/Patterns.cpp
@@ -62,20 +62,21 @@
     // Import (buffer view to stream resource).
     auto resultType = rewriter.getType<IREE::Stream::ResourceType>(
         IREE::Stream::Lifetime::External);
-    Value resultSize = rewriter.create<IREE::Stream::TensorSizeOfOp>(
-        op.getLoc(), rewriter.getIndexType(),
+    Value resultSize = IREE::Stream::TensorSizeOfOp::create(
+        rewriter, op.getLoc(), rewriter.getIndexType(),
         TypeAttr::get(op.getTarget().getType()),
         flattenValues(adaptor.getTargetDims()), executionAffinityAttr);
-    Value resource = rewriter.create<IREE::Stream::TensorImportOp>(
-        op.getLoc(), resultType, adaptor.getSource().front(), targetType,
-        flattenValues(adaptor.getTargetDims()), resultSize, op.getConsume(),
-        executionAffinityAttr);
+    Value resource = IREE::Stream::TensorImportOp::create(
+        rewriter, op.getLoc(), resultType, adaptor.getSource().front(),
+        targetType, flattenValues(adaptor.getTargetDims()), resultSize,
+        op.getConsume(), executionAffinityAttr);
 
     // Await the fence, if needed. When not specified the resource is assumed to
     // be immediately available.
     if (auto waitFence = op.getWaitFence()) {
-      Value waitTimepoint = rewriter.create<IREE::Stream::TimepointImportOp>(
-          op.getLoc(), rewriter.getType<IREE::Stream::TimepointType>(),
+      Value waitTimepoint = IREE::Stream::TimepointImportOp::create(
+          rewriter, op.getLoc(),
+          rewriter.getType<IREE::Stream::TimepointType>(),
           ValueRange{waitFence}, executionAffinityAttr);
       resource = rewriter
                      .create<IREE::Stream::TimepointAwaitOp>(
@@ -85,8 +86,8 @@
     }
 
     auto unknownType = rewriter.getType<IREE::Stream::ResourceType>();
-    Value newImport = rewriter.create<IREE::Stream::AsyncTransferOp>(
-        op.getLoc(), unknownType, resource, resultSize, resultSize,
+    Value newImport = IREE::Stream::AsyncTransferOp::create(
+        rewriter, op.getLoc(), unknownType, resource, resultSize, resultSize,
         /*source_affinity=*/executionAffinityAttr,
         /*target_affinity=*/executionAffinityAttr);
     rewriter.replaceOpWithMultiple(op, {{newImport, resultSize}});
@@ -108,10 +109,10 @@
       return success();
     }
 
-    auto expectedElementType = builder.create<IREE::HAL::ElementTypeOp>(
-        loc, tensorType.getElementType());
-    auto expectedEncodingType = builder.create<IREE::HAL::EncodingTypeOp>(
-        loc, tensorType.getEncoding());
+    auto expectedElementType = IREE::HAL::ElementTypeOp::create(
+        builder, loc, tensorType.getElementType());
+    auto expectedEncodingType = IREE::HAL::EncodingTypeOp::create(
+        builder, loc, tensorType.getEncoding());
 
     SmallVector<Value> shapeDims;
     if (tensorType.getRank() > 0) {
@@ -121,15 +122,16 @@
         if (tensorType.isDynamicDim(idx)) {
           expectedDim = dynamicDims[dynamicIdx++];
         } else {
-          expectedDim = builder.create<arith::ConstantIndexOp>(
-              loc, tensorType.getDimSize(idx));
+          expectedDim = arith::ConstantIndexOp::create(
+              builder, loc, tensorType.getDimSize(idx));
         }
         shapeDims.push_back(expectedDim);
       }
     }
 
-    builder.create<IREE::HAL::BufferViewAssertOp>(
-        loc, bufferView, message ? message : builder.getStringAttr("tensor"),
+    IREE::HAL::BufferViewAssertOp::create(
+        builder, loc, bufferView,
+        message ? message : builder.getStringAttr("tensor"),
         expectedElementType, expectedEncodingType, shapeDims);
     return success();
   }
@@ -163,9 +165,10 @@
     auto externalType = rewriter.getType<IREE::Stream::ResourceType>(
         IREE::Stream::Lifetime::External);
     if (source.resource.getType() != externalType) {
-      exportSource = rewriter.create<IREE::Stream::AsyncTransferOp>(
-          op.getLoc(), externalType, source.resource, source.resourceSize,
-          source.resourceSize, /*source_affinity=*/source.affinity,
+      exportSource = IREE::Stream::AsyncTransferOp::create(
+          rewriter, op.getLoc(), externalType, source.resource,
+          source.resourceSize, source.resourceSize,
+          /*source_affinity=*/source.affinity,
           /*target_affinity=*/executionAffinityAttr);
     }
 
@@ -205,8 +208,8 @@
     // what is required for the output.
     SmallVector<Value> convertedSourceDims =
         flattenValues(adaptor.getSourceDims());
-    Value storageSize = rewriter.create<IREE::Stream::TensorSizeOfOp>(
-        op.getLoc(), rewriter.getIndexType(),
+    Value storageSize = IREE::Stream::TensorSizeOfOp::create(
+        rewriter, op.getLoc(), rewriter.getIndexType(),
         TypeAttr::get(op.getSource().getType()), convertedSourceDims,
         executionAffinityAttr);
 
@@ -215,8 +218,8 @@
     // target type so we know we can update it.
     auto externalType = rewriter.getType<IREE::Stream::ResourceType>(
         IREE::Stream::Lifetime::External);
-    auto importOp = rewriter.create<IREE::Stream::TensorImportOp>(
-        op.getLoc(), externalType, adaptor.getStorage().front(),
+    auto importOp = IREE::Stream::TensorImportOp::create(
+        rewriter, op.getLoc(), externalType, adaptor.getStorage().front(),
         TypeAttr::get(sourceType), convertedSourceDims, storageSize,
         /*consume=*/UnitAttr{}, executionAffinityAttr);
 
@@ -224,8 +227,9 @@
     // be immediately available.
     Value storage = importOp.getResult();
     if (auto waitFence = op.getWaitFence()) {
-      Value waitTimepoint = rewriter.create<IREE::Stream::TimepointImportOp>(
-          op.getLoc(), rewriter.getType<IREE::Stream::TimepointType>(),
+      Value waitTimepoint = IREE::Stream::TimepointImportOp::create(
+          rewriter, op.getLoc(),
+          rewriter.getType<IREE::Stream::TimepointType>(),
           ValueRange{waitFence}, executionAffinityAttr);
       storage = rewriter
                     .create<IREE::Stream::TimepointAwaitOp>(
@@ -235,26 +239,27 @@
     }
 
     // Copy the source value into the imported target storage.
-    auto zeroOffset = rewriter.create<arith::ConstantIndexOp>(op.getLoc(), 0);
-    auto updateOp = rewriter.create<IREE::Stream::AsyncUpdateOp>(
-        op.getLoc(), externalType, storage, storageSize, zeroOffset,
+    auto zeroOffset = arith::ConstantIndexOp::create(rewriter, op.getLoc(), 0);
+    auto updateOp = IREE::Stream::AsyncUpdateOp::create(
+        rewriter, op.getLoc(), externalType, storage, storageSize, zeroOffset,
         source.resourceSize, source.resource, source.resourceSize,
         executionAffinityAttr);
 
     // Slice out the value from the updated tensor.
     // This preserves the use-def chain but is almost always elided by aliasing
     // the input value later on.
-    auto sliceOp = rewriter.create<IREE::Stream::AsyncSliceOp>(
-        op.getLoc(), externalType, updateOp.getResult(),
+    auto sliceOp = IREE::Stream::AsyncSliceOp::create(
+        rewriter, op.getLoc(), externalType, updateOp.getResult(),
         updateOp.getTargetSize(), zeroOffset, source.resourceSize,
         source.resourceSize, executionAffinityAttr);
 
     // Transfer to match original lifetime (if needed).
     Value result = sliceOp.getResult();
     if (source.resource.getType() != result.getType()) {
-      result = rewriter.create<IREE::Stream::AsyncTransferOp>(
-          op.getLoc(), source.resource.getType(), result, source.resourceSize,
-          source.resourceSize, executionAffinityAttr, executionAffinityAttr);
+      result = IREE::Stream::AsyncTransferOp::create(
+          rewriter, op.getLoc(), source.resource.getType(), result,
+          source.resourceSize, source.resourceSize, executionAffinityAttr,
+          executionAffinityAttr);
     }
     rewriter.replaceOpWithMultiple(op, {{result, source.resourceSize}});
 
@@ -286,8 +291,8 @@
          llvm::zip_equal(op.getSources(), adaptor.getSources())) {
       auto source = resolveTensorOperands(op.getLoc(), sourceTensor,
                                           sourceResource, rewriter);
-      auto barrierOp = rewriter.create<IREE::Stream::TimepointBarrierOp>(
-          sourceResource.front().getLoc(), source.resource.getType(),
+      auto barrierOp = IREE::Stream::TimepointBarrierOp::create(
+          rewriter, sourceResource.front().getLoc(), source.resource.getType(),
           timepointType, source.resource, source.resourceSize, source.affinity);
       signaledResources.push_back(barrierOp.getResult());
       signaledResourceSizes.push_back(source.resourceSize);
@@ -303,9 +308,9 @@
     }
     Value joinedTimepoint = IREE::Stream::TimepointJoinOp::join(
         op.getLoc(), signaledTimepoints, rewriter);
-    rewriter.create<IREE::Stream::TimepointChainExternalOp>(
-        op.getLoc(), joinedTimepoint, ValueRange{adaptor.getSignalFence()},
-        anyAffinityAttr);
+    IREE::Stream::TimepointChainExternalOp::create(
+        rewriter, op.getLoc(), joinedTimepoint,
+        ValueRange{adaptor.getSignalFence()}, anyAffinityAttr);
     replaceOpWithMultiple(op, signaledResources, signaledResourceSizes,
                           rewriter);
     return success();
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Conversion/PatternUtils.cpp b/compiler/src/iree/compiler/Dialect/Stream/Conversion/PatternUtils.cpp
index 051b6a1..72f5b4f 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Conversion/PatternUtils.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Conversion/PatternUtils.cpp
@@ -67,8 +67,8 @@
   bool isBarrier = resource.getDefiningOp() &&
                    isa<IREE::Stream::AsyncBarrierOp>(resource.getDefiningOp());
   if (affinityAttr != requiredAffinityAttr && !isBarrier) {
-    resource = builder.create<IREE::Stream::AsyncTransferOp>(
-        loc, resource.getType(), resource, resourceSize, resourceSize,
+    resource = IREE::Stream::AsyncTransferOp::create(
+        builder, loc, resource.getType(), resource, resourceSize, resourceSize,
         affinityAttr, requiredAffinityAttr);
   }
   return {requiredAffinityAttr, resource, resourceSize};
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Conversion/StandardToStream/Patterns.cpp b/compiler/src/iree/compiler/Dialect/Stream/Conversion/StandardToStream/Patterns.cpp
index ce51aad..795975e 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Conversion/StandardToStream/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Conversion/StandardToStream/Patterns.cpp
@@ -52,8 +52,8 @@
 
     auto constantType = rewriter.getType<IREE::Stream::ResourceType>(
         IREE::Stream::Lifetime::Constant);
-    auto newOp = rewriter.create<IREE::Stream::TensorConstantOp>(
-        constantOp.getLoc(), constantType,
+    auto newOp = IREE::Stream::TensorConstantOp::create(
+        rewriter, constantOp.getLoc(), constantType,
         convertAttributeToStream(constantOp.getValue()),
         TypeAttr::get(constantOp.getType()),
         /*result_encoding_dims=*/ValueRange{}, executionAffinityAttr);
@@ -61,9 +61,9 @@
     auto unknownType = rewriter.getType<IREE::Stream::ResourceType>();
     auto constantSize = rewriter.createOrFold<IREE::Stream::ResourceSizeOp>(
         constantOp.getLoc(), rewriter.getIndexType(), newOp.getResult());
-    auto transferOp = rewriter.create<IREE::Stream::AsyncTransferOp>(
-        constantOp.getLoc(), unknownType, newOp.getResult(), constantSize,
-        constantSize,
+    auto transferOp = IREE::Stream::AsyncTransferOp::create(
+        rewriter, constantOp.getLoc(), unknownType, newOp.getResult(),
+        constantSize, constantSize,
         /*source_affinity=*/executionAffinityAttr,
         /*result_affinity=*/executionAffinityAttr);
     rewriter.replaceOpWithMultiple(constantOp,
@@ -136,12 +136,12 @@
                                              adaptor.getTrueValue(), rewriter);
     auto falseOperand = resolveTensorOperands(
         op.getLoc(), op.getFalseValue(), adaptor.getFalseValue(), rewriter);
-    auto resourceSelectOp = rewriter.create<mlir::arith::SelectOp>(
-        op.getLoc(), adaptor.getCondition().front(), trueOperand.resource,
-        falseOperand.resource);
-    auto sizeSelectOp = rewriter.create<mlir::arith::SelectOp>(
-        op.getLoc(), adaptor.getCondition().front(), trueOperand.resourceSize,
-        falseOperand.resourceSize);
+    auto resourceSelectOp = mlir::arith::SelectOp::create(
+        rewriter, op.getLoc(), adaptor.getCondition().front(),
+        trueOperand.resource, falseOperand.resource);
+    auto sizeSelectOp = mlir::arith::SelectOp::create(
+        rewriter, op.getLoc(), adaptor.getCondition().front(),
+        trueOperand.resourceSize, falseOperand.resourceSize);
     rewriter.replaceOpWithMultiple(op, {ValueRange{resourceSelectOp.getResult(),
                                                    sizeSelectOp.getResult()}});
     return success();
@@ -177,8 +177,8 @@
     // Create a new call that takes the expanded input operands and returns the
     // expanded output results. We can't directly replace the original call as
     // the result counts differ.
-    auto ifOp = rewriter.create<mlir::scf::IfOp>(op.getLoc(), expandedTypes,
-                                                 op.getCondition());
+    auto ifOp = mlir::scf::IfOp::create(rewriter, op.getLoc(), expandedTypes,
+                                        op.getCondition());
 
     ifOp.getThenRegion().getBlocks().clear();
     rewriter.inlineRegionBefore(op.getThenRegion(), ifOp.getThenRegion(),
@@ -251,8 +251,8 @@
     // Create a new loop that takes the expanded input operands and returns the
     // expanded output results. We can't directly replace the original loop as
     // the result counts differ.
-    auto forOp = rewriter.create<mlir::scf::ForOp>(
-        op.getLoc(), adaptor.getLowerBound().front(),
+    auto forOp = mlir::scf::ForOp::create(
+        rewriter, op.getLoc(), adaptor.getLowerBound().front(),
         adaptor.getUpperBound().front(), adaptor.getStep().front(),
         expandedOperands);
 
@@ -327,8 +327,8 @@
     // Create a new call that takes the expanded input operands and returns the
     // expanded output results. We can't directly replace the original call as
     // the result counts differ.
-    auto whileOp = rewriter.create<mlir::scf::WhileOp>(
-        op.getLoc(), expandedTypes, expandedOperands);
+    auto whileOp = mlir::scf::WhileOp::create(rewriter, op.getLoc(),
+                                              expandedTypes, expandedOperands);
 
     // Inline the `before` block and update the block arguments.
     whileOp.getBefore().getBlocks().clear();
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 b7c24d4..17b6815 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Conversion/UtilToStream/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Conversion/UtilToStream/Patterns.cpp
@@ -236,8 +236,8 @@
     // is constant and will fold throughout the program. Global optimizations
     // such as same-value deduplication will also take effect.
     auto indexType = rewriter.getIndexType();
-    auto resourceSizeOp = rewriter.create<IREE::Util::GlobalOp>(
-        globalOp.getLoc(), (globalOp.getName() + "__size").str(),
+    auto resourceSizeOp = IREE::Util::GlobalOp::create(
+        rewriter, globalOp.getLoc(), (globalOp.getName() + "__size").str(),
         globalOp.getIsMutable(), indexType, std::optional<TypedAttr>{});
     resourceSizeOp.setVisibility(globalOp.getVisibility());
 
@@ -249,32 +249,32 @@
     // Materialize the initializer if we need to setup a tensor-like constant.
     if (tensorInitializerRequired) {
       auto initializerOp =
-          rewriter.create<IREE::Util::InitializerOp>(globalOp.getLoc());
+          IREE::Util::InitializerOp::create(rewriter, globalOp.getLoc());
       auto *entryBlock = rewriter.createBlock(&initializerOp.getBody());
       rewriter.setInsertionPointToStart(entryBlock);
       Value initialValue, initialValueSize;
       if (isa<IREE::Util::UninitializedAttr>(initialValueAttr)) {
-        initialValueSize = rewriter.create<IREE::Stream::TensorSizeOfOp>(
-            globalOp.getLoc(), TypeAttr::get(globalOp.getType()),
+        initialValueSize = IREE::Stream::TensorSizeOfOp::create(
+            rewriter, globalOp.getLoc(), TypeAttr::get(globalOp.getType()),
             /*result_encoding_dims=*/ValueRange{}, affinityAttr);
-        initialValue = rewriter.create<IREE::Stream::TensorEmptyOp>(
-            globalOp.getLoc(), resourceOp.getType(),
+        initialValue = IREE::Stream::TensorEmptyOp::create(
+            rewriter, globalOp.getLoc(), resourceOp.getType(),
             TypeAttr::get(globalOp.getType()),
             /*result_encoding_dims=*/ValueRange{}, initialValueSize,
             affinityAttr);
       } else {
-        initialValue = rewriter.create<IREE::Stream::TensorConstantOp>(
-            globalOp.getLoc(), resourceOp.getType(),
+        initialValue = IREE::Stream::TensorConstantOp::create(
+            rewriter, globalOp.getLoc(), resourceOp.getType(),
             convertAttributeToStream(initialValueAttr),
             TypeAttr::get(globalOp.getType()),
             /*result_encoding_dims=*/ValueRange{}, affinityAttr);
-        initialValueSize = rewriter.create<IREE::Stream::ResourceSizeOp>(
-            globalOp.getLoc(), indexType, initialValue);
+        initialValueSize = IREE::Stream::ResourceSizeOp::create(
+            rewriter, globalOp.getLoc(), indexType, initialValue);
       }
       resourceOp.createStoreOp(globalOp.getLoc(), initialValue, rewriter);
       resourceSizeOp.createStoreOp(globalOp.getLoc(), initialValueSize,
                                    rewriter);
-      rewriter.create<IREE::Util::ReturnOp>(globalOp.getLoc());
+      IREE::Util::ReturnOp::create(rewriter, globalOp.getLoc());
     }
 
     expansionState->globalMap[globalOp.getSymName()] = ExpandedGlobalResource{
@@ -317,8 +317,9 @@
                                 loadOp.getLoc(), rewriter.getIndexType(),
                                 expandedGlobal.resourceSizeOp.getSymName())
                             .getResult();
-    auto transferOp = rewriter.create<IREE::Stream::AsyncTransferOp>(
-        loadOp.getLoc(), unknownType, resource, resourceSize, resourceSize,
+    auto transferOp = IREE::Stream::AsyncTransferOp::create(
+        rewriter, loadOp.getLoc(), unknownType, resource, resourceSize,
+        resourceSize,
         /*source_affinity=*/expandedGlobal.affinityAttr,
         /*result_affinity=*/expandedGlobal.affinityAttr);
     rewriter.replaceOpWithMultiple(loadOp,
@@ -350,16 +351,16 @@
         resolveTensorOperands(storeOp.getLoc(), storeOp.getValue(),
                               adaptor.getValue(), affinityAnalysis, rewriter);
     assert(expandedGlobal.resourceOp && "Missing resource op");
-    auto transferOp = rewriter.create<IREE::Stream::AsyncTransferOp>(
-        storeOp.getLoc(), expandedGlobal.resourceOp.getType(), value.resource,
-        value.resourceSize, value.resourceSize,
+    auto transferOp = IREE::Stream::AsyncTransferOp::create(
+        rewriter, storeOp.getLoc(), expandedGlobal.resourceOp.getType(),
+        value.resource, value.resourceSize, value.resourceSize,
         /*source_affinity=*/value.affinity,
         /*result_affinity=*/expandedGlobal.affinityAttr);
     rewriter.replaceOpWithNewOp<IREE::Util::GlobalStoreOp>(
         storeOp, transferOp.getResult(),
         expandedGlobal.resourceOp.getSymName());
-    rewriter.create<IREE::Util::GlobalStoreOp>(
-        storeOp.getLoc(), value.resourceSize,
+    IREE::Util::GlobalStoreOp::create(
+        rewriter, storeOp.getLoc(), value.resourceSize,
         expandedGlobal.resourceSizeOp.getSymName());
 
     return success();
@@ -388,8 +389,8 @@
         operandSizes.push_back(nullptr);
       }
     }
-    auto barrierOp = rewriter.create<IREE::Util::OptimizationBarrierOp>(
-        op.getLoc(), newOperands);
+    auto barrierOp = IREE::Util::OptimizationBarrierOp::create(
+        rewriter, op.getLoc(), newOperands);
     replaceOpWithMultiple(op, barrierOp->getResults(), operandSizes, rewriter);
     return success();
   }
diff --git a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamDialect.cpp b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamDialect.cpp
index 121905a..4a7f60d 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamDialect.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamDialect.cpp
@@ -117,12 +117,13 @@
                                               Attribute value, Type type,
                                               Location loc) {
   if (mlir::func::ConstantOp::isBuildableWith(value, type)) {
-    return builder.create<mlir::func::ConstantOp>(
-        loc, type, llvm::cast<FlatSymbolRefAttr>(value));
+    return mlir::func::ConstantOp::create(builder, loc, type,
+                                          llvm::cast<FlatSymbolRefAttr>(value));
   } else if (arith::ConstantOp::isBuildableWith(value, type)) {
-    return builder.create<arith::ConstantOp>(loc, type, cast<TypedAttr>(value));
+    return arith::ConstantOp::create(builder, loc, type,
+                                     cast<TypedAttr>(value));
   } else if (llvm::isa<IREE::Stream::TimepointAttr>(value)) {
-    return builder.create<IREE::Stream::TimepointImmediateOp>(loc);
+    return IREE::Stream::TimepointImmediateOp::create(builder, loc);
   }
   return nullptr;
 }
diff --git a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOpFolders.cpp b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOpFolders.cpp
index b90144d..28dbf2a 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOpFolders.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOpFolders.cpp
@@ -162,7 +162,7 @@
 
     // Replace the pattern on the op with the new one.
     auto narrowValue =
-        rewriter.create<arith::ConstantOp>(fillOp.getLoc(), newPatternAttr);
+        arith::ConstantOp::create(rewriter, fillOp.getLoc(), newPatternAttr);
     rewriter.modifyOpInPlace(
         fillOp, [&]() { fillOp.getValueMutable().assign(narrowValue); });
     return success();
@@ -523,8 +523,8 @@
     }
     Value newTimepoint = allocaOp.getAwaitTimepoint();
     if (!newTimepoint) {
-      newTimepoint = rewriter.create<IREE::Stream::TimepointImmediateOp>(
-          allocaOp.getLoc());
+      newTimepoint = IREE::Stream::TimepointImmediateOp::create(
+          rewriter, allocaOp.getLoc());
     }
     rewriter.replaceAllUsesWith(allocaOp.getResultTimepoint(), newTimepoint);
     rewriter.eraseOp(allocaOp);
@@ -557,16 +557,15 @@
     // replace that first.
     Value newAllocaTimepoint = allocaOp.getAwaitTimepoint();
     if (!newAllocaTimepoint) {
-      newAllocaTimepoint = rewriter.create<IREE::Stream::TimepointImmediateOp>(
-          allocaOp.getLoc());
+      newAllocaTimepoint = IREE::Stream::TimepointImmediateOp::create(
+          rewriter, allocaOp.getLoc());
     }
     rewriter.replaceAllUsesWith(allocaOp.getResultTimepoint(),
                                 newAllocaTimepoint);
     Value newDeallocaTimepoint = deallocaOp.getAwaitTimepoint();
     if (!newDeallocaTimepoint) {
-      newDeallocaTimepoint =
-          rewriter.create<IREE::Stream::TimepointImmediateOp>(
-              deallocaOp.getLoc());
+      newDeallocaTimepoint = IREE::Stream::TimepointImmediateOp::create(
+          rewriter, deallocaOp.getLoc());
     }
     rewriter.replaceAllUsesWith(deallocaOp.getResultTimepoint(),
                                 newDeallocaTimepoint);
@@ -629,8 +628,8 @@
       allocaTimepoints.push_back(allocaOp.getResultTimepoint());
     }
     rewriter.setInsertionPointAfter(allocaOps.back());
-    auto joinOp = rewriter.create<IREE::Stream::TimepointJoinOp>(
-        rewriter.getFusedLoc(allocaLocs),
+    auto joinOp = IREE::Stream::TimepointJoinOp::create(
+        rewriter, rewriter.getFusedLoc(allocaLocs),
         rewriter.getType<IREE::Stream::TimepointType>(), allocaTimepoints);
 
     // Make all alloca ops wait on the earliest timepoint so they can proceed
@@ -883,7 +882,7 @@
     rewriter.setInsertionPointAfter(op);
     for (auto sliceOffset : op.getPackedOffsets()) {
       auto addOp =
-          rewriter.create<arith::AddIOp>(op.getLoc(), baseOffset, sliceOffset);
+          arith::AddIOp::create(rewriter, op.getLoc(), baseOffset, sliceOffset);
       rewriter.replaceAllUsesExcept(sliceOffset, addOp.getResult(), addOp);
     }
 
@@ -939,8 +938,8 @@
       dynamicSliceSizes[i] = slice.dynamicSize;
     }
     SmallVector<Type> packedOffsetTypes(slices.size(), rewriter.getIndexType());
-    auto newOp = rewriter.create<ResourcePackOp>(
-        op.getLoc(), op.getTotalLength().getType(), packedOffsetTypes,
+    auto newOp = ResourcePackOp::create(
+        rewriter, op.getLoc(), op.getTotalLength().getType(), packedOffsetTypes,
         op.getOffset(), rewriter.getIndexArrayAttr(lifetimeIntervals),
         dynamicSliceSizes, op.getAffinityAttr());
 
@@ -990,9 +989,9 @@
     auto fusedLoc = rewriter.getFusedLoc({parentOp.getLoc(), op.getLoc()});
     auto newOffset = rewriter.createOrFold<arith::AddIOp>(
         fusedLoc, parentOp.getSourceOffset(), op.getSourceOffset());
-    auto newOp = rewriter.create<ResourceSubviewOp>(
-        fusedLoc, parentOp.getSource(), parentOp.getSourceSize(), newOffset,
-        op.getResultSize());
+    auto newOp = ResourceSubviewOp::create(
+        rewriter, fusedLoc, parentOp.getSource(), parentOp.getSourceSize(),
+        newOffset, op.getResultSize());
     rewriter.replaceOp(op, newOp.getResult());
     return success();
   }
@@ -1025,8 +1024,8 @@
         trueSubview.getResultSize() != falseSubview.getResultSize()) {
       return failure();
     }
-    auto offsetSelectOp = rewriter.create<mlir::arith::SelectOp>(
-        op.getLoc(), op.getCondition(), trueSubview.getSourceOffset(),
+    auto offsetSelectOp = mlir::arith::SelectOp::create(
+        rewriter, op.getLoc(), op.getCondition(), trueSubview.getSourceOffset(),
         falseSubview.getSourceOffset());
     rewriter.replaceOpWithNewOp<IREE::Stream::ResourceSubviewOp>(
         op, op.getResult().getType(), trueSubview.getSource(),
@@ -1343,8 +1342,8 @@
       return failure();
 
     // Definitely empty if here.
-    Value resultSize = rewriter.create<IREE::Stream::TensorSizeOfOp>(
-        constantOp.getLoc(), rewriter.getIndexType(),
+    Value resultSize = IREE::Stream::TensorSizeOfOp::create(
+        rewriter, constantOp.getLoc(), rewriter.getIndexType(),
         TypeAttr::get(constantOp.getResultEncoding()),
         constantOp.getResultEncodingDims(), constantOp.getAffinityAttr());
     rewriter.replaceOpWithNewOp<IREE::Stream::TensorEmptyOp>(
@@ -1369,22 +1368,24 @@
     Value splatValue;
     if (isa<ComplexType>(getElementTypeOrSelf(splatAttr.getType()))) {
       auto splatElementAttr = splatAttr.getSplatValue<ArrayAttr>();
-      splatValue = rewriter.create<complex::ConstantOp>(
-          constantOp.getLoc(), getElementTypeOrSelf(splatAttr.getType()),
-          cast<ArrayAttr>(splatElementAttr));
+      splatValue =
+          complex::ConstantOp::create(rewriter, constantOp.getLoc(),
+                                      getElementTypeOrSelf(splatAttr.getType()),
+                                      cast<ArrayAttr>(splatElementAttr));
     } else {
       auto splatElementAttr = splatAttr.getSplatValue<TypedAttr>();
-      splatValue = rewriter.create<arith::ConstantOp>(
-          constantOp.getLoc(), splatElementAttr.getType(), splatElementAttr);
+      splatValue = arith::ConstantOp::create(rewriter, constantOp.getLoc(),
+                                             splatElementAttr.getType(),
+                                             splatElementAttr);
     }
 
     auto resultType = IREE::Stream::ResourceType::get(constantOp.getContext());
-    Value resultSize = rewriter.create<IREE::Stream::TensorSizeOfOp>(
-        constantOp.getLoc(), rewriter.getIndexType(),
+    Value resultSize = IREE::Stream::TensorSizeOfOp::create(
+        rewriter, constantOp.getLoc(), rewriter.getIndexType(),
         TypeAttr::get(constantOp.getResultEncoding()),
         constantOp.getResultEncodingDims(), constantOp.getAffinityAttr());
-    auto splatOp = rewriter.create<TensorSplatOp>(
-        constantOp.getLoc(), resultType, splatValue,
+    auto splatOp = TensorSplatOp::create(
+        rewriter, constantOp.getLoc(), resultType, splatValue,
         constantOp.getResultEncoding(), constantOp.getResultEncodingDims(),
         resultSize, constantOp.getAffinityAttr());
     rewriter.replaceOpWithNewOp<AsyncTransferOp>(
@@ -1678,8 +1679,9 @@
     }
     auto splatElementAttr =
         llvm::dyn_cast<SplatElementsAttr>(value).getSplatValue<TypedAttr>();
-    auto splatValue = rewriter.create<arith::ConstantOp>(
-        constantOp.getLoc(), splatElementAttr.getType(), splatElementAttr);
+    auto splatValue =
+        arith::ConstantOp::create(rewriter, constantOp.getLoc(),
+                                  splatElementAttr.getType(), splatElementAttr);
     rewriter.replaceOpWithNewOp<IREE::Stream::AsyncSplatOp>(
         constantOp, constantOp.getResult().getType(), splatValue,
         constantOp.getResultSize(), constantOp.getAffinityAttr());
@@ -2416,10 +2418,11 @@
       // Clone the subview into the region and wire it up to take the same
       // range as the original.
       auto arg = entryBlock.getArgument(capture.operandIdx);
-      auto newOp = rewriter.create<ResourceSubviewOp>(
-          capture.subviewOp.getLoc(), arg, capture.subviewOp.getSourceSize(),
-          capture.subviewOp.getSourceOffset(),
-          capture.subviewOp.getResultSize());
+      auto newOp =
+          ResourceSubviewOp::create(rewriter, capture.subviewOp.getLoc(), arg,
+                                    capture.subviewOp.getSourceSize(),
+                                    capture.subviewOp.getSourceOffset(),
+                                    capture.subviewOp.getResultSize());
       rewriter.replaceAllUsesExcept(arg, newOp.getResult(), newOp);
     }
 
@@ -2456,8 +2459,8 @@
              "expect 1:1 types on captures to results");
       newResults.push_back(capture);
     }
-    auto immediateTimepoint = rewriter.create<TimepointImmediateOp>(
-        op.getLoc(), op.getResultTimepoint().getType());
+    auto immediateTimepoint = TimepointImmediateOp::create(
+        rewriter, op.getLoc(), op.getResultTimepoint().getType());
     newResults.push_back(immediateTimepoint);
     rewriter.replaceOp(op, newResults);
     return success();
@@ -2923,10 +2926,11 @@
       // Clone the subview into the region and wire it up to take the same
       // range as the original.
       auto arg = entryBlock.getArgument(capture.operandIdx);
-      auto newOp = rewriter.create<ResourceSubviewOp>(
-          capture.subviewOp.getLoc(), arg, capture.subviewOp.getSourceSize(),
-          capture.subviewOp.getSourceOffset(),
-          capture.subviewOp.getResultSize());
+      auto newOp =
+          ResourceSubviewOp::create(rewriter, capture.subviewOp.getLoc(), arg,
+                                    capture.subviewOp.getSourceSize(),
+                                    capture.subviewOp.getSourceOffset(),
+                                    capture.subviewOp.getResultSize());
       rewriter.replaceAllUsesExcept(arg, newOp.getResult(), newOp);
     }
 
@@ -3253,8 +3257,8 @@
       // Could not analyze or found to be a timeline op.
       return failure();
     }
-    auto immediateTimepoint =
-        rewriter.create<IREE::Stream::TimepointImmediateOp>(barrierOp.getLoc());
+    auto immediateTimepoint = IREE::Stream::TimepointImmediateOp::create(
+        rewriter, barrierOp.getLoc());
     rewriter.replaceOp(barrierOp,
                        {barrierOp.getResource(), immediateTimepoint});
     return success();
@@ -3439,8 +3443,8 @@
       // Create a new subview op matching the original on our result and swap
       // users to it.
       auto result = op.getResults()[operandIdx];
-      auto newOp = rewriter.create<IREE::Stream::ResourceSubviewOp>(
-          subviewOp.getLoc(), result, subviewOp.getSourceSize(),
+      auto newOp = IREE::Stream::ResourceSubviewOp::create(
+          rewriter, subviewOp.getLoc(), result, subviewOp.getSourceSize(),
           subviewOp.getSourceOffset(), subviewOp.getResultSize());
       rewriter.replaceAllUsesExcept(result, newOp.getResult(), newOp);
 
@@ -3531,8 +3535,9 @@
       llvm::append_range(newOperands, coveredOp.getResourceOperands());
       llvm::append_range(newOperandSizes, coveredOp.getResourceOperandSizes());
     }
-    auto newOp = rewriter.create<TimepointAwaitOp>(
-        op.getLoc(), newOperands, newOperandSizes, op.getAwaitTimepoint());
+    auto newOp =
+        TimepointAwaitOp::create(rewriter, op.getLoc(), newOperands,
+                                 newOperandSizes, op.getAwaitTimepoint());
 
     // Replace covered ops with the new results.
     unsigned resultIdx = 0;
@@ -3578,8 +3583,9 @@
     }
 
     // Create replacement op with deduped operands/results.
-    auto newOp = rewriter.create<IREE::Stream::TimepointAwaitOp>(
-        op.getLoc(), newOperands, newOperandSizes, op.getAwaitTimepoint());
+    auto newOp = IREE::Stream::TimepointAwaitOp::create(
+        rewriter, op.getLoc(), newOperands, newOperandSizes,
+        op.getAwaitTimepoint());
     newOp.setSync(op.getSync());
 
     // Replace all duplicate results with the base results.
diff --git a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp
index 5f3630a..19fbfe1 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp
@@ -1408,9 +1408,9 @@
   if (locs.empty())
     return {};
   if (locs.size() == 1) {
-    auto allocOp = builder.create<IREE::Stream::ResourceAllocOp>(
-        locs.front(), resourceType, storageSizes.front(), uninitialized,
-        affinityAttr);
+    auto allocOp = IREE::Stream::ResourceAllocOp::create(
+        builder, locs.front(), resourceType, storageSizes.front(),
+        uninitialized, affinityAttr);
     return {allocOp, {allocOp.getResult()}};
   }
   auto fusedLoc = builder.getFusedLoc(locs);
@@ -1430,13 +1430,13 @@
   // pack op.
   auto indexType = builder.getIndexType();
   SmallVector<Type> packedOffsetTypes(sliceCount, indexType);
-  auto packOp = builder.create<IREE::Stream::ResourcePackOp>(
-      fusedLoc, indexType, packedOffsetTypes, /*offset=*/nullptr,
+  auto packOp = IREE::Stream::ResourcePackOp::create(
+      builder, fusedLoc, indexType, packedOffsetTypes, /*offset=*/nullptr,
       builder.getIndexArrayAttr(lifetimeIntervals), storageSizes, affinityAttr);
 
   // Create the new alloca based on the total required size.
-  auto allocOp = builder.create<IREE::Stream::ResourceAllocOp>(
-      fusedLoc, resourceType, packOp.getTotalLength(), uninitialized,
+  auto allocOp = IREE::Stream::ResourceAllocOp::create(
+      builder, fusedLoc, resourceType, packOp.getTotalLength(), uninitialized,
       affinityAttr);
   auto slab = allocOp.getResult();
   auto slabSize = packOp.getTotalLength();
@@ -1470,8 +1470,9 @@
   if (locs.empty())
     return {};
   if (locs.size() == 1) {
-    auto allocaOp = builder.create<IREE::Stream::ResourceAllocaOp>(
-        locs.front(), resourceType, timepointType, storageSizes.front(),
+    auto allocaOp = IREE::Stream::ResourceAllocaOp::create(
+        builder, locs.front(), resourceType, timepointType,
+        storageSizes.front(),
         /*indeterminate_lifetime=*/UnitAttr{}, awaitTimepoint, affinityAttr);
     return {allocaOp, {allocaOp.getResult()}};
   }
@@ -1495,13 +1496,13 @@
   // pack op.
   auto indexType = builder.getIndexType();
   SmallVector<Type> packedOffsetTypes(sliceCount, indexType);
-  auto packOp = builder.create<IREE::Stream::ResourcePackOp>(
-      fusedLoc, indexType, packedOffsetTypes, /*offset=*/nullptr,
+  auto packOp = IREE::Stream::ResourcePackOp::create(
+      builder, fusedLoc, indexType, packedOffsetTypes, /*offset=*/nullptr,
       builder.getIndexArrayAttr(lifetimeIntervals), storageSizes, affinityAttr);
 
   // Create the new alloca based on the total required size.
-  auto allocaOp = builder.create<IREE::Stream::ResourceAllocaOp>(
-      fusedLoc, resourceType, timepointType, packOp.getTotalLength(),
+  auto allocaOp = IREE::Stream::ResourceAllocaOp::create(
+      builder, fusedLoc, resourceType, timepointType, packOp.getTotalLength(),
       /*indeterminate_lifetime=*/UnitAttr{}, awaitTimepoint, affinityAttr);
   auto slab = allocaOp.getResult();
   auto slabSize = packOp.getTotalLength();
@@ -3176,8 +3177,8 @@
   assert(getTiedOperandsIndexAndLength().first == 0 &&
          "operands must be the first ODS group");
 
-  auto newOp = rewriter.create<AsyncExecuteOp>(
-      getLoc(), newResultTypes, newResultSizes, getAwaitTimepoint(),
+  auto newOp = AsyncExecuteOp::create(
+      rewriter, getLoc(), newResultTypes, newResultSizes, getAwaitTimepoint(),
       newOperandsValues, newOperandSizes, newTiedOperandIndices,
       getOperation()->getAttrs());
   auto &newBody = newOp.getClosureBodyRegion();
@@ -3297,8 +3298,8 @@
   assert(getTiedOperandsIndexAndLength().first == 0 &&
          "operands must be the first ODS group");
 
-  auto newOp = rewriter.create<AsyncConcurrentOp>(
-      getLoc(), newResultTypes, newResultSizes, newOperandsValues,
+  auto newOp = AsyncConcurrentOp::create(
+      rewriter, getLoc(), newResultTypes, newResultSizes, newOperandsValues,
       newOperandSizes, newTiedOperandIndices, getOperation()->getAttrs());
   auto &newBody = newOp.getClosureBodyRegion();
   newBody.takeBody(getClosureBodyRegion());
@@ -4092,9 +4093,9 @@
       newOperandsValues, newOperandSizes, excludedOperandIndices,
       newResultTypes, newResultSizes, excludedResultIndices);
 
-  auto newOp = rewriter.create<CmdExecuteOp>(getLoc(), getAwaitTimepoint(),
-                                             newOperandsValues, newOperandSizes,
-                                             getOperation()->getAttrs());
+  auto newOp = CmdExecuteOp::create(rewriter, getLoc(), getAwaitTimepoint(),
+                                    newOperandsValues, newOperandSizes,
+                                    getOperation()->getAttrs());
   newOp.setOnce(getOnce());
   auto &newBody = newOp.getClosureBodyRegion();
   newBody.takeBody(getClosureBodyRegion());
@@ -4173,8 +4174,8 @@
   assert(!timepoints.empty() && "must have at least one timepoint");
   if (timepoints.size() == 1)
     return timepoints.front();
-  return builder.create<IREE::Stream::TimepointJoinOp>(
-      loc, builder.getType<IREE::Stream::TimepointType>(), timepoints);
+  return IREE::Stream::TimepointJoinOp::create(
+      builder, loc, builder.getType<IREE::Stream::TimepointType>(), timepoints);
 }
 
 // static
diff --git a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.cpp b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.cpp
index 6b47c01..aff6c05 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamTypes.cpp
@@ -526,8 +526,8 @@
                                      Value resourceSize, Value subrangeOffset,
                                      Value subrangeLength,
                                      OpBuilder &builder) const {
-  return builder.create<IREE::Stream::ResourceSubviewOp>(
-      loc, resource, resourceSize, subrangeOffset, subrangeLength);
+  return IREE::Stream::ResourceSubviewOp::create(
+      builder, loc, resource, resourceSize, subrangeOffset, subrangeLength);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/AnnotateDispatchAssumptions.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/AnnotateDispatchAssumptions.cpp
index 67ca41c..eb74773 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/AnnotateDispatchAssumptions.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/AnnotateDispatchAssumptions.cpp
@@ -173,8 +173,8 @@
 
   // Do the rewrite.
   OpBuilder builder = OpBuilder::atBlockBegin(&funcOp.front());
-  auto assumeOp = builder.create<IREE::Util::AssumeIntOp>(
-      funcOp.getLoc(), arguments, argumentAssumptions);
+  auto assumeOp = IREE::Util::AssumeIntOp::create(
+      builder, funcOp.getLoc(), arguments, argumentAssumptions);
   for (unsigned argIndex = 0; argIndex < arguments.size(); ++argIndex) {
     arguments[argIndex].replaceAllUsesExcept(assumeOp.getResult(argIndex),
                                              assumeOp);
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/AutomaticReferenceCounting.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/AutomaticReferenceCounting.cpp
index ddccd2b..7f9c79d 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/AutomaticReferenceCounting.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/AutomaticReferenceCounting.cpp
@@ -662,10 +662,10 @@
           lastTimepoint.printAsOperand(llvm::dbgs(), *asmState);
           llvm::dbgs() << " directly\n";
         });
-        auto deallocaOp = builder.create<IREE::Stream::ResourceDeallocaOp>(
-            timepointsLoc, builder.getType<IREE::Stream::TimepointType>(),
-            resource, resourceSize, preferOrigin, lastTimepoint,
-            resourceAffinity);
+        auto deallocaOp = IREE::Stream::ResourceDeallocaOp::create(
+            builder, timepointsLoc,
+            builder.getType<IREE::Stream::TimepointType>(), resource,
+            resourceSize, preferOrigin, lastTimepoint, resourceAffinity);
         lastTimepoint.replaceAllUsesExcept(deallocaOp.getResultTimepoint(),
                                            deallocaOp);
       } else if (timepoints.size() > 1) {
@@ -685,13 +685,15 @@
           lastTimepoint.printAsOperand(llvm::dbgs(), *asmState);
           llvm::dbgs() << " as a join\n";
         });
-        auto joinOp = builder.create<IREE::Stream::TimepointJoinOp>(
-            timepointsLoc, builder.getType<IREE::Stream::TimepointType>(),
+        auto joinOp = IREE::Stream::TimepointJoinOp::create(
+            builder, timepointsLoc,
+            builder.getType<IREE::Stream::TimepointType>(),
             llvm::map_to_vector(timepoints,
                                 [](Value timepoint) { return timepoint; }));
-        auto deallocaOp = builder.create<IREE::Stream::ResourceDeallocaOp>(
-            timepointsLoc, builder.getType<IREE::Stream::TimepointType>(),
-            resource, resourceSize, preferOrigin, joinOp.getResultTimepoint(),
+        auto deallocaOp = IREE::Stream::ResourceDeallocaOp::create(
+            builder, timepointsLoc,
+            builder.getType<IREE::Stream::TimepointType>(), resource,
+            resourceSize, preferOrigin, joinOp.getResultTimepoint(),
             resourceAffinity);
         lastTimepoint.replaceAllUsesExcept(deallocaOp.getResultTimepoint(),
                                            joinOp);
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ConvertToStream.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ConvertToStream.cpp
index 183a512..cd59df5 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ConvertToStream.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ConvertToStream.cpp
@@ -139,8 +139,8 @@
     auto externalType = builder.getType<IREE::Stream::ResourceType>(
         IREE::Stream::Lifetime::External);
     if (source.resource.getType() != externalType) {
-      source.resource = builder.create<IREE::Stream::AsyncTransferOp>(
-          loc, externalType, source.resource, source.resourceSize,
+      source.resource = IREE::Stream::AsyncTransferOp::create(
+          builder, loc, externalType, source.resource, source.resourceSize,
           source.resourceSize,
           /*source_affinity=*/source.affinity,
           /*result_affinity=*/executionAffinityAttr);
@@ -148,8 +148,8 @@
 
     // Associate the stream resource and external encoding and shape
     // information.
-    auto newOp = builder.create<IREE::Stream::TensorExportOp>(
-        loc, targetType, source.resource, TypeAttr::get(targetType),
+    auto newOp = IREE::Stream::TensorExportOp::create(
+        builder, loc, targetType, source.resource, TypeAttr::get(targetType),
         dynamicDims, source.resourceSize, executionAffinityAttr);
     return newOp.getResult();
   }
@@ -169,18 +169,19 @@
     // Compute the size of the tensor once in the stream resource.
     // This may differ from the external encoding of the tensor as imports are
     // a transfer operation that may need to reformat the tensor.
-    Value resultSize = builder.create<IREE::Stream::TensorSizeOfOp>(
-        loc, builder.getIndexType(), TypeAttr::get(sourceTensor.getType()),
-        dynamicDims, executionAffinityAttr);
+    Value resultSize = IREE::Stream::TensorSizeOfOp::create(
+        builder, loc, builder.getIndexType(),
+        TypeAttr::get(sourceTensor.getType()), dynamicDims,
+        executionAffinityAttr);
 
     // Associate the external SSA value, encoding, and shape information with
     // the stream resource. When lowering we'll then have all the metadata
     // required even after erasing it all on the resource.
     auto externalType = builder.getType<IREE::Stream::ResourceType>(
         IREE::Stream::Lifetime::External);
-    auto importOp = builder.create<IREE::Stream::TensorImportOp>(
-        loc, externalType, sourceTensor, sourceTensor.getType(), dynamicDims,
-        resultSize,
+    auto importOp = IREE::Stream::TensorImportOp::create(
+        builder, loc, externalType, sourceTensor, sourceTensor.getType(),
+        dynamicDims, resultSize,
         /*consume=*/true, executionAffinityAttr);
     consumingOps.insert(importOp);
 
@@ -195,8 +196,8 @@
                    .getResult();
     }
 
-    auto castOp = builder.create<mlir::UnrealizedConversionCastOp>(
-        loc, sourceTensor.getType(), ValueRange{result, resultSize});
+    auto castOp = mlir::UnrealizedConversionCastOp::create(
+        builder, loc, sourceTensor.getType(), ValueRange{result, resultSize});
     consumingOps.insert(castOp);
     return castOp.getResult(0);
   }
@@ -276,7 +277,7 @@
                            /*source_affinity=*/nullptr,
                            /*result_affinity=*/nullptr)
                        .getResult();
-      return builder.create<UnrealizedConversionCastOp>(loc, resultType, cast)
+      return UnrealizedConversionCastOp::create(builder, loc, resultType, cast)
           .getResult(0);
     });
 
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ElideTimepoints.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ElideTimepoints.cpp
index a691259..b8b6c37 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ElideTimepoints.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ElideTimepoints.cpp
@@ -703,8 +703,8 @@
     if (existingReplacement != pendingReplacements.end()) {
       return existingReplacement->second;
     }
-    return builder.create<IREE::Stream::TimepointImmediateOp>(
-        elidedTimepoint.getLoc());
+    return IREE::Stream::TimepointImmediateOp::create(builder,
+                                                      elidedTimepoint.getLoc());
   };
 
   // Elides |elidedTimepoint| by replacing all its uses by |op| with an
@@ -746,9 +746,8 @@
       return; // already immediate
     OpBuilder afterBuilder(op);
     afterBuilder.setInsertionPointAfterValue(elidedTimepoint);
-    Value immediateTimepoint =
-        afterBuilder.create<IREE::Stream::TimepointImmediateOp>(
-            elidedTimepoint.getLoc());
+    Value immediateTimepoint = IREE::Stream::TimepointImmediateOp::create(
+        afterBuilder, elidedTimepoint.getLoc());
     // Defer actually swapping until later.
     pendingReplacements.insert(
         std::make_pair(elidedTimepoint, immediateTimepoint));
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/EmplaceAllocations.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/EmplaceAllocations.cpp
index 5ae72eb..04af360 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/EmplaceAllocations.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/EmplaceAllocations.cpp
@@ -58,8 +58,8 @@
       newValue.getLoc(), newValue, builder);
   IREE::Stream::AffinityAttr sourceAffinity = usageAffinityAttr;
   IREE::Stream::AffinityAttr resultAffinity = usageAffinityAttr;
-  Value transferValue = builder.create<IREE::Stream::AsyncTransferOp>(
-      newValue.getLoc(), oldValue.getType(), newValue, newValueSize,
+  Value transferValue = IREE::Stream::AsyncTransferOp::create(
+      builder, newValue.getLoc(), oldValue.getType(), newValue, newValueSize,
       newValueSize, sourceAffinity, resultAffinity);
   oldValue.replaceAllUsesWith(transferValue);
 }
@@ -153,8 +153,8 @@
 
     // TODO(multi-device): possibly perform analysis to pick an affinity based
     // on usage. Today we assume the resource affinity matches the execution op.
-    auto allocaOp = builder.create<IREE::Stream::AsyncAllocaOp>(
-        dispatchOp.getLoc(), result.getType(), resultSize,
+    auto allocaOp = IREE::Stream::AsyncAllocaOp::create(
+        builder, dispatchOp.getLoc(), result.getType(), resultSize,
         dispatchOp.getAffinityAttr());
 
     auto operandIndex = dispatchOp.getResourceOperands().size();
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/EncodeTensors.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/EncodeTensors.cpp
index e1863a3..229ab57 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/EncodeTensors.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/EncodeTensors.cpp
@@ -77,8 +77,8 @@
                            PatternRewriter &rewriter) {
   // Static dimension early-out:
   if (!tensorType.isDynamicDim(i)) {
-    return rewriter.create<arith::ConstantIndexOp>(loc,
-                                                   tensorType.getDimSize(i));
+    return arith::ConstantIndexOp::create(rewriter, loc,
+                                          tensorType.getDimSize(i));
   }
 
   // Map from absolute dimension index to the compact dynamic index.
@@ -148,7 +148,7 @@
         complexType.getElementType().getIntOrFloatBitWidth();
     assert(elementBitWidth <= 32 && "unsupported complex<f64>");
     Type bwType = builder.getIntegerType(elementBitWidth * 2);
-    return builder.create<complex::BitcastOp>(loc, bwType, pattern);
+    return complex::BitcastOp::create(builder, loc, bwType, pattern);
   }
 
   // Get floats into integer form first; may need additional processing below.
@@ -551,13 +551,13 @@
     // Dense:
     auto sourceOffset = calculateElementByteOffset(
         op.getLoc(), sourceType, sourceDims, op.getIndices(), rewriter);
-    Value load = rewriter.create<IREE::Stream::AsyncLoadOp>(
-        op.getLoc(), loadType, op.getSource(), op.getSourceSize(),
+    Value load = IREE::Stream::AsyncLoadOp::create(
+        rewriter, op.getLoc(), loadType, op.getSource(), op.getSourceSize(),
         sourceOffset);
 
     if (loadType != op.getType()) {
       load =
-          rewriter.create<complex::BitcastOp>(op.getLoc(), op.getType(), load);
+          complex::BitcastOp::create(rewriter, op.getLoc(), op.getType(), load);
     }
 
     rewriter.replaceOp(op, load);
@@ -608,7 +608,7 @@
     // we changed the tensor dispatch op to accept indices and lengths for
     // offsetting we would need to account for that here but today we require
     // that to happen on slices/updates instead.
-    Value zeroOffset = rewriter.create<arith::ConstantIndexOp>(op.getLoc(), 0);
+    Value zeroOffset = arith::ConstantIndexOp::create(rewriter, op.getLoc(), 0);
     SmallVector<Value> operandOffsets;
     SmallVector<Value> operandEnds;
     SmallVector<Value> operandLengths;
@@ -726,7 +726,7 @@
     auto loadedValue = op.getResult();
     rewriter.setInsertionPointAfterValue(loadedValue);
     auto truncOp =
-        rewriter.create<arith::TruncIOp>(op.getLoc(), targetType, loadedValue);
+        arith::TruncIOp::create(rewriter, op.getLoc(), targetType, loadedValue);
     rewriter.modifyOpInPlace(op, [&]() {
       loadedValue.replaceAllUsesExcept(truncOp, truncOp);
       loadedValue.setType(alignedType);
@@ -757,8 +757,8 @@
            "stores must extend");
 
     // Extend the sub-byte -> byte type; e.g. i1 -> i8.
-    auto extOp = rewriter.create<arith::ExtUIOp>(op.getLoc(), alignedType,
-                                                 op.getValue());
+    auto extOp = arith::ExtUIOp::create(rewriter, op.getLoc(), alignedType,
+                                        op.getValue());
     rewriter.modifyOpInPlace(
         op, [&]() { op.getValueMutable().assign(extOp.getResult()); });
     return success();
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/FoldUniformOperands.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/FoldUniformOperands.cpp
index 1fc4f40..f0a47e5 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/FoldUniformOperands.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/FoldUniformOperands.cpp
@@ -229,8 +229,8 @@
     unsigned argIdx = operandToArgMap[operandIdx];
     auto arg = entryBlock.getArgument(argIdx);
     deadArgMap.set(argIdx);
-    auto constantOp = builder.create<arith::ConstantOp>(
-        builder.getFusedLoc(operandLocs[operandIdx]),
+    auto constantOp = arith::ConstantOp::create(
+        builder, builder.getFusedLoc(operandLocs[operandIdx]),
         builder.getIntegerAttr(arg.getType(),
                                operandValues[operandIdx].value()));
     arg.replaceAllUsesWith(constantOp);
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/FuseDispatchBindings.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/FuseDispatchBindings.cpp
index 18a64c9..5790c8b 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/FuseDispatchBindings.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/FuseDispatchBindings.cpp
@@ -298,8 +298,8 @@
 
   // Replace the old dispatch op with a new one.
   OpBuilder builder(dispatchOp);
-  auto newOp = builder.create<IREE::Stream::CmdDispatchOp>(
-      dispatchOp.getLoc(), dispatchOp.getWorkload(),
+  auto newOp = IREE::Stream::CmdDispatchOp::create(
+      builder, dispatchOp.getLoc(), dispatchOp.getWorkload(),
       dispatchOp.getEntryPointsAttr(), newOperands, newResources,
       newResourceSizes, newOffsets, newLengths,
       builder.getArrayAttr(newAccesses));
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/MaterializeBuiltins.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/MaterializeBuiltins.cpp
index 5ea7273..514ccd5 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/MaterializeBuiltins.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/MaterializeBuiltins.cpp
@@ -213,8 +213,8 @@
       splatOp.getResult().getType(),
   };
   OpBuilder builder(splatOp);
-  auto dispatchOp = builder.create<IREE::Stream::AsyncDispatchOp>(
-      loc, resultTypes, workload,
+  auto dispatchOp = IREE::Stream::AsyncDispatchOp::create(
+      builder, loc, resultTypes, workload,
       builder.getArrayAttr({SymbolRefAttr::get(
           builder.getStringAttr(builtinName),
           FlatSymbolRefAttr::get(builder.getContext(), builtinName))}),
@@ -308,8 +308,8 @@
       fillOp.getResult().getType(),
   };
   OpBuilder builder(fillOp);
-  auto dispatchOp = builder.create<IREE::Stream::AsyncDispatchOp>(
-      loc, resultTypes, workload,
+  auto dispatchOp = IREE::Stream::AsyncDispatchOp::create(
+      builder, loc, resultTypes, workload,
       builder.getArrayAttr({SymbolRefAttr::get(
           builder.getStringAttr(builtinName),
           FlatSymbolRefAttr::get(builder.getContext(), builtinName))}),
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/MaterializeCopyOnWrite.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/MaterializeCopyOnWrite.cpp
index 5b7d3a9..f5eaa62 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/MaterializeCopyOnWrite.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/MaterializeCopyOnWrite.cpp
@@ -89,8 +89,8 @@
   auto sizeAwareType =
       llvm::cast<IREE::Util::SizeAwareTypeInterface>(resourceType);
   auto size = sizeAwareType.queryValueSize(loc, operand.get(), builder);
-  return builder.create<IREE::Stream::AsyncCloneOp>(
-      loc, resourceType, operand.get(), size, size, affinity);
+  return IREE::Stream::AsyncCloneOp::create(
+      builder, loc, resourceType, operand.get(), size, size, affinity);
 }
 
 // Materializes a copy for each mutated operand on |tiedOp| as required.
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/MaterializeEncodings.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/MaterializeEncodings.cpp
index e933dbf..a496e76 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/MaterializeEncodings.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/MaterializeEncodings.cpp
@@ -107,31 +107,32 @@
   for (auto argument : block.getArguments().drop_front(1).take_front(
            encodeOp.getSourceEncodingDims().size())) {
     sourceDynamicDims.push_back(
-        builder.create<IREE::TensorExt::DispatchWorkloadOrdinalOp>(
-            loc, argument, builder.getIndexAttr(ordinalCount++)));
+        IREE::TensorExt::DispatchWorkloadOrdinalOp::create(
+            builder, loc, argument, builder.getIndexAttr(ordinalCount++)));
   }
   for (auto argument : block.getArguments().drop_back(1).take_back(
            encodeOp.getResultEncodingDims().size())) {
     destinationDynamicDims.push_back(
-        builder.create<IREE::TensorExt::DispatchWorkloadOrdinalOp>(
-            loc, argument, builder.getIndexAttr(ordinalCount++)));
+        IREE::TensorExt::DispatchWorkloadOrdinalOp::create(
+            builder, loc, argument, builder.getIndexAttr(ordinalCount++)));
   }
 
-  auto zero = builder.create<arith::ConstantIndexOp>(loc, 0);
+  auto zero = arith::ConstantIndexOp::create(builder, loc, 0);
   auto sourceDispatchType = IREE::TensorExt::DispatchTensorType::get(
       IREE::TensorExt::TensorAccess::ReadOnly, encodeOp.getSourceEncoding());
-  Value source = builder.create<IREE::Stream::BindingSubspanOp>(
-      loc, sourceDispatchType, block.getArgument(0), zero, sourceDynamicDims);
+  Value source = IREE::Stream::BindingSubspanOp::create(
+      builder, loc, sourceDispatchType, block.getArgument(0), zero,
+      sourceDynamicDims);
   auto destinationDispatchType = IREE::TensorExt::DispatchTensorType::get(
       IREE::TensorExt::TensorAccess::WriteOnly, encodeOp.getResultEncoding());
-  Value destination = builder.create<IREE::Stream::BindingSubspanOp>(
-      loc, destinationDispatchType, block.getArguments().back(), zero,
+  Value destination = IREE::Stream::BindingSubspanOp::create(
+      builder, loc, destinationDispatchType, block.getArguments().back(), zero,
       destinationDynamicDims);
 
   // Load the value from the source binding.
   RankedTensorType sourceType = sourceDispatchType.asRankedTensorType();
-  Value value = builder.create<IREE::TensorExt::DispatchTensorLoadOp>(
-      loc, sourceType, source, sourceDynamicDims);
+  Value value = IREE::TensorExt::DispatchTensorLoadOp::create(
+      builder, loc, sourceType, source, sourceDynamicDims);
 
   // We can only add/remove encodings using set_encoding/unset_encoding ops
   // today. Thus, we firstly need to bring the tensor encodings to pure tensor
@@ -140,19 +141,19 @@
       destinationDispatchType.asRankedTensorType();
   if (sourceType != destinationType) {
     if (sourceType.getEncoding()) {
-      value = builder.create<IREE::Encoding::UnsetEncodingOp>(
-          loc, sourceType.dropEncoding(), value, sourceDynamicDims);
+      value = IREE::Encoding::UnsetEncodingOp::create(
+          builder, loc, sourceType.dropEncoding(), value, sourceDynamicDims);
     }
     if (destinationType.getEncoding()) {
-      value = builder.create<IREE::Encoding::SetEncodingOp>(
-          loc, destinationType, value);
+      value = IREE::Encoding::SetEncodingOp::create(builder, loc,
+                                                    destinationType, value);
     }
   }
 
   // Store the value to the destination binding.
-  builder.create<IREE::TensorExt::DispatchTensorStoreOp>(
-      loc, value, destination, destinationDynamicDims);
-  builder.create<func::ReturnOp>(loc);
+  IREE::TensorExt::DispatchTensorStoreOp::create(
+      builder, loc, value, destination, destinationDynamicDims);
+  func::ReturnOp::create(builder, loc);
 
   return funcOp;
 }
@@ -183,16 +184,16 @@
 
   OpBuilder::InsertionGuard guard(rewriter);
   rewriter.setInsertionPointToStart(&executableOp.getBody().front());
-  auto exportOp = rewriter.create<IREE::Stream::ExecutableExportOp>(
-      loc, funcOp.getName(), SymbolRefAttr::get(funcOp));
+  auto exportOp = IREE::Stream::ExecutableExportOp::create(
+      rewriter, loc, funcOp.getName(), SymbolRefAttr::get(funcOp));
   Block *block = rewriter.createBlock(&exportOp.getWorkgroupCount(),
                                       exportOp.getWorkgroupCount().end(),
                                       workloadTypes, workloadLocs);
   rewriter.setInsertionPointToStart(block);
   auto defaultCountOp =
-      rewriter.create<IREE::TensorExt::DispatchWorkgroupCountFromSliceOp>(
-          loc, block->getArguments());
-  rewriter.create<IREE::Stream::ReturnOp>(loc, defaultCountOp.getResults());
+      IREE::TensorExt::DispatchWorkgroupCountFromSliceOp::create(
+          rewriter, loc, block->getArguments());
+  IREE::Stream::ReturnOp::create(rewriter, loc, defaultCountOp.getResults());
   return exportOp;
 }
 
@@ -210,7 +211,7 @@
   Location loc = encodeOp.getLoc();
   std::string executableName = "_encoding_" + std::to_string(executableId);
   auto executableOp =
-      rewriter.create<IREE::Stream::ExecutableOp>(loc, executableName);
+      IREE::Stream::ExecutableOp::create(rewriter, loc, executableName);
   executableOp.getOperation()->moveBefore(parentFuncOp);
   executableOp.setPrivate();
 
@@ -219,7 +220,7 @@
   std::string funcName = executableName + "_" + getDispatchFuncName(encodeOp);
   auto funcOp = createWorkgroupFunc(encodeOp, funcName);
   rewriter.setInsertionPointToStart(&executableOp.getBody().front());
-  auto innerModule = rewriter.create<mlir::ModuleOp>(loc);
+  auto innerModule = mlir::ModuleOp::create(rewriter, loc);
   innerModule.push_back(funcOp);
   IREE::Stream::ExecutableExportOp exportOp =
       createExportOp(rewriter, loc, encodeOp, executableOp, funcOp);
@@ -243,7 +244,7 @@
                               IREE::Stream::ExecutableExportOp exportOp) {
   OpBuilder::InsertionGuard guard(rewriter);
   rewriter.setInsertionPoint(encodeOp);
-  Value zero = rewriter.create<arith::ConstantIndexOp>(encodeOp.getLoc(), 0);
+  Value zero = arith::ConstantIndexOp::create(rewriter, encodeOp.getLoc(), 0);
   SmallVector<Value> operandOffsets = {zero};
   SmallVector<Value> operandEnds = {encodeOp.getSourceSize()};
   SmallVector<Value> operandLengths = {encodeOp.getSourceSize()};
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/PackConstants.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/PackConstants.cpp
index c38f4dc..b0cf229 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/PackConstants.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/PackConstants.cpp
@@ -304,8 +304,8 @@
 
   // Load all in a batch. One resource is returned per parameter but they may
   // alias depending on the runtime implementation.
-  auto loadOp = builder.create<IREE::Stream::ParameterLoadOp>(
-      builder.getFusedLoc(spanLocs), targetTypes,
+  auto loadOp = IREE::Stream::ParameterLoadOp::create(
+      builder, builder.getFusedLoc(spanLocs), targetTypes,
       builder.getType<IREE::Stream::TimepointType>(), scope,
       builder.getArrayAttr(sourceKeys), sourceOffsets, targetLengths,
       awaitTimepoint, affinityAttr);
@@ -315,10 +315,10 @@
   unsigned resultIndex = 0;
   for (auto *storageResource : storageResources) {
     for (auto &packedSpan : storageResource->spans) {
-      auto subviewOp = builder.create<IREE::Stream::ResourceSubviewOp>(
-          packedSpan.slice.result.getLoc(), loadOp.getResult(resultIndex),
-          loadOp.getResultSize(resultIndex), indexSet.get(packedSpan.offset),
-          packedSpan.slice.resultSize);
+      auto subviewOp = IREE::Stream::ResourceSubviewOp::create(
+          builder, packedSpan.slice.result.getLoc(),
+          loadOp.getResult(resultIndex), loadOp.getResultSize(resultIndex),
+          indexSet.get(packedSpan.offset), packedSpan.slice.resultSize);
       packedSpan.slice.result.replaceAllUsesWith(subviewOp.getResult());
       ++resultIndex;
     }
@@ -332,8 +332,8 @@
     Type targetType, Value targetSize, MutableArrayRef<PackedSpan> packedSpans,
     IntegerSet<int64_t> &i64Set, IndexSet &indexSet, OpBuilder &builder) {
   // Allocate the resulting storage resource of the final resource type.
-  auto allocOp = builder.create<IREE::Stream::ResourceAllocOp>(
-      loc, targetType, targetSize,
+  auto allocOp = IREE::Stream::ResourceAllocOp::create(
+      builder, loc, targetType, targetSize,
       /*uninitialized=*/builder.getUnitAttr(), affinityAttr);
 
   // Parameters may be from multiple scopes - bucket by scope and gather from
@@ -361,8 +361,8 @@
       targetOffsets.push_back(indexSet.get(packedSpan.offset));
       targetLengths.push_back(indexSet.get(packedSpan.length));
     }
-    auto gatherOp = builder.create<IREE::Stream::ParameterGatherOp>(
-        loc, builder.getType<IREE::Stream::TimepointType>(), scope,
+    auto gatherOp = IREE::Stream::ParameterGatherOp::create(
+        builder, loc, builder.getType<IREE::Stream::TimepointType>(), scope,
         builder.getArrayAttr(sourceKeys), sourceOffsets, allocOp.getResult(),
         allocOp.getResultSize(0), targetOffsets, targetLengths, awaitTimepoint,
         affinityAttr);
@@ -372,8 +372,8 @@
   // Slice out each span from the allocation.
   // Note that access must be guarded by the final ready timepoint.
   for (auto &packedSpan : packedSpans) {
-    auto subviewOp = builder.create<IREE::Stream::ResourceSubviewOp>(
-        packedSpan.slice.result.getLoc(), allocOp.getResult(),
+    auto subviewOp = IREE::Stream::ResourceSubviewOp::create(
+        builder, packedSpan.slice.result.getLoc(), allocOp.getResult(),
         allocOp.getResultSize(0), indexSet.get(packedSpan.offset),
         packedSpan.slice.resultSize);
     packedSpan.slice.result.replaceAllUsesWith(subviewOp.getResult());
@@ -392,19 +392,19 @@
     Value storageBuffer, Value storageBufferSize, IntegerSet<int64_t> &i64Set,
     IndexSet &indexSet, OpBuilder &builder) {
   // Allocate the resulting storage resource of the final resource type.
-  auto allocOp = builder.create<IREE::Stream::ResourceAllocOp>(
-      loc, resourceType, storageResourceSize,
+  auto allocOp = IREE::Stream::ResourceAllocOp::create(
+      builder, loc, resourceType, storageResourceSize,
       /*uninitialized=*/builder.getUnitAttr(), affinityAttr);
 
   // Create the file backed by the constant resource buffer.
-  auto fileOp = builder.create<IREE::Stream::FileConstantOp>(
-      loc, storageBuffer, storageBufferSize, indexSet.get(0),
+  auto fileOp = IREE::Stream::FileConstantOp::create(
+      builder, loc, storageBuffer, storageBufferSize, indexSet.get(0),
       storageResourceSize, affinityAttr);
 
   // Issue asynchronous file read into the buffer.
   auto zeroI64 = i64Set.get(0);
-  auto readOp = builder.create<IREE::Stream::FileReadOp>(
-      loc, fileOp.getResult(), zeroI64, allocOp.getResult(),
+  auto readOp = IREE::Stream::FileReadOp::create(
+      builder, loc, fileOp.getResult(), zeroI64, allocOp.getResult(),
       allocOp.getResultSize(0), indexSet.get(0), storageResourceSize,
       awaitTimepoint, affinityAttr);
 
@@ -423,31 +423,33 @@
     IndexSet &indexSet, OpBuilder &builder) {
   // Try mapping; this may fail if the device can't use the storage buffer as
   // the type of resource requested.
-  auto tryMapOp = builder.create<IREE::Stream::ResourceTryMapOp>(
-      loc, builder.getI1Type(), resourceType, storageBuffer, indexSet.get(0),
-      storageResourceSize, affinityAttr);
+  auto tryMapOp = IREE::Stream::ResourceTryMapOp::create(
+      builder, loc, builder.getI1Type(), resourceType, storageBuffer,
+      indexSet.get(0), storageResourceSize, affinityAttr);
 
   // If we are able to directly map the resources then we don't need to wait.
   // Otherwise we need to stage the storage buffer into memory via the file
   // streaming API.
-  auto ifOp = builder.create<scf::IfOp>(
-      loc, tryMapOp.getDidMap(),
+  auto ifOp = scf::IfOp::create(
+      builder, loc, tryMapOp.getDidMap(),
       [&](OpBuilder &thenBuilder, Location loc) {
         // Just return the resources + an immediate timepoint.
-        thenBuilder.create<scf::YieldOp>(loc, ValueRange{
-                                                  awaitTimepoint,
-                                                  tryMapOp.getResult(),
-                                              });
+        scf::YieldOp::create(thenBuilder, loc,
+                             ValueRange{
+                                 awaitTimepoint,
+                                 tryMapOp.getResult(),
+                             });
       },
       [&](OpBuilder &elseBuilder, Location loc) {
         auto readResult =
             buildFileRead(loc, awaitTimepoint, affinityAttr, resourceType,
                           storageResourceSize, storageBuffer, storageBufferSize,
                           i64Set, indexSet, elseBuilder);
-        elseBuilder.create<scf::YieldOp>(loc, ValueRange{
-                                                  readResult.timepoint,
-                                                  readResult.resource,
-                                              });
+        scf::YieldOp::create(elseBuilder, loc,
+                             ValueRange{
+                                 readResult.timepoint,
+                                 readResult.resource,
+                             });
       });
   auto ifTimepoint = ifOp.getResults().front();
   auto ifResource = ifOp.getResults().back();
@@ -479,8 +481,9 @@
   Value currentTimepoint = awaitTimepoint;
   for (auto &storageResource : storageResources) {
     // Serialized resources are stored as packed host data.
-    Value storageBuffer = builder.create<IREE::Util::BufferConstantOp>(
-        storageResource.loc, /*name=*/nullptr, storageResource.packedData,
+    Value storageBuffer = IREE::Util::BufferConstantOp::create(
+        builder, storageResource.loc, /*name=*/nullptr,
+        storageResource.packedData,
         builder.getIndexAttr(resourceConfig.getMinBufferOffsetAlignment()),
         /*mimeType=*/nullptr);
 
@@ -501,9 +504,10 @@
 
     for (auto &span : storageResource.spans) {
       auto loc = span.slice.result.getLoc();
-      auto subviewOp = builder.create<IREE::Stream::ResourceSubviewOp>(
-          loc, uploadedResource.resource, uploadedResource.resourceSize,
-          indexSet.get(span.offset), span.slice.resultSize);
+      auto subviewOp = IREE::Stream::ResourceSubviewOp::create(
+          builder, loc, uploadedResource.resource,
+          uploadedResource.resourceSize, indexSet.get(span.offset),
+          span.slice.resultSize);
       span.slice.result.replaceAllUsesWith(subviewOp.getResult());
     }
 
@@ -672,8 +676,8 @@
       indexSet.populate(constantsOp.getResultSizes());
 
       // Perform upload/processing for immutable and mutable constants.
-      Value awaitTimepoint = builder.create<IREE::Stream::TimepointImmediateOp>(
-          constantsOp.getLoc());
+      Value awaitTimepoint = IREE::Stream::TimepointImmediateOp::create(
+          builder, constantsOp.getLoc());
       auto uploadTimepoint =
           generateUploads(awaitTimepoint, constantsOp, resourceConfig, i64Set,
                           indexSet, builder);
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/PackDispatchOperands.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/PackDispatchOperands.cpp
index 2d1aace..1b7393a 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/PackDispatchOperands.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/PackDispatchOperands.cpp
@@ -75,8 +75,8 @@
   // Complex types are decomposed into real/imaginary components and processed
   // as if they were independent.
   if (auto complexType = dyn_cast<ComplexType>(operand.getType())) {
-    auto real = builder.create<complex::ReOp>(loc, operand);
-    auto imag = builder.create<complex::ImOp>(loc, operand);
+    auto real = complex::ReOp::create(builder, loc, operand);
+    auto imag = complex::ImOp::create(builder, loc, operand);
     convertAndDecomposeToI32s(loc, real, newOperands, resourceConfig, builder);
     convertAndDecomposeToI32s(loc, imag, newOperands, resourceConfig, builder);
     return;
@@ -145,7 +145,7 @@
         loc, builder.getI32Type(),
         builder.createOrFold<arith::ShRUIOp>(
             loc, builder.getI64Type(), operand,
-            builder.create<arith::ConstantIntOp>(loc, 32, 64)));
+            arith::ConstantIntOp::create(builder, loc, 32, 64)));
     newOperands.push_back(lo);
     newOperands.push_back(hi);
   } else {
@@ -194,7 +194,7 @@
     Value imag = recomposeFromI32sAndConvert(
         entryBlock, loc, complexType.getElementType(), oldArgAttr, newArgTypes,
         newArgAttrs, resourceConfig, builder);
-    return builder.create<complex::CreateOp>(loc, oldArgType, real, imag);
+    return complex::CreateOp::create(builder, loc, oldArgType, real, imag);
   }
 
   // Pass through/no change other types (!stream.binding, probably).
@@ -216,12 +216,13 @@
     auto hiArg = entryBlock->addArgument(builder.getI32Type(), loc);
     newArgTypes.push_back(hiArg.getType());
     // i64(lo) | (i64(hi) << 32)
-    value = builder.create<arith::OrIOp>(
-        loc, builder.create<arith::ExtUIOp>(loc, builder.getI64Type(), loArg),
-        builder.create<arith::ShLIOp>(
-            loc,
-            builder.create<arith::ExtUIOp>(loc, builder.getI64Type(), hiArg),
-            builder.create<arith::ConstantIntOp>(loc, 32, 64)));
+    value = arith::OrIOp::create(
+        builder, loc,
+        arith::ExtUIOp::create(builder, loc, builder.getI64Type(), loArg),
+        arith::ShLIOp::create(
+            builder, loc,
+            arith::ExtUIOp::create(builder, loc, builder.getI64Type(), hiArg),
+            arith::ConstantIntOp::create(builder, loc, 32, 64)));
   } else {
     // Forced bitcast.
     value = entryBlock->addArgument(builder.getI32Type(), loc);
@@ -230,20 +231,21 @@
 
   // i32 or i64 -> index
   if (oldArgType.isIndex()) {
-    value = builder.create<arith::IndexCastUIOp>(loc, builder.getIndexType(),
-                                                 value);
+    value = arith::IndexCastUIOp::create(builder, loc, builder.getIndexType(),
+                                         value);
   }
 
   // Truncate back to original bit width.
   // i32 -> i16, i64 -> i48, ...
   if (oldArgType.isIntOrFloat() && oldArgType.getIntOrFloatBitWidth() < 32) {
-    value = builder.create<arith::TruncIOp>(
-        loc, builder.getIntegerType(oldArgType.getIntOrFloatBitWidth()), value);
+    value = arith::TruncIOp::create(
+        builder, loc,
+        builder.getIntegerType(oldArgType.getIntOrFloatBitWidth()), value);
   }
 
   // i16 -> bf16, i32 -> f32, i64 -> f64 ...
   if (auto floatType = llvm::dyn_cast<FloatType>(oldArgType)) {
-    value = builder.create<arith::BitcastOp>(loc, oldArgType, value);
+    value = arith::BitcastOp::create(builder, loc, oldArgType, value);
   }
 
   // Preserve the arg attrs on either the final op or the function argument
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/PropagateTimepoints.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/PropagateTimepoints.cpp
index 5c35074..9209c99 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/PropagateTimepoints.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/PropagateTimepoints.cpp
@@ -77,8 +77,8 @@
     auto resourceOp = it.second.resourceOp;
     OpBuilder builder(resourceOp);
     auto timepointName = (resourceOp.getName() + "__timepoint").str();
-    auto timepointOp = builder.create<IREE::Util::GlobalOp>(
-        resourceOp.getLoc(), timepointName,
+    auto timepointOp = IREE::Util::GlobalOp::create(
+        builder, resourceOp.getLoc(), timepointName,
         /*isMutable=*/true, timepointType, immediateAttr);
     timepointOp.setVisibility(resourceOp.getVisibility());
     symbolTable.insert(timepointOp);
@@ -144,7 +144,7 @@
     // and all results will be available immediately (fallthrough to below).
     if (awaitOp.getSync()) {
       return std::make_pair(
-          builder.create<IREE::Stream::TimepointImmediateOp>(loc).getResult(),
+          IREE::Stream::TimepointImmediateOp::create(builder, loc).getResult(),
           value);
     } else {
       return std::make_pair(awaitOp.getAwaitTimepoint(),
@@ -155,7 +155,7 @@
     return std::make_pair(executeOp.getResultTimepoint(), value);
   } else {
     return std::make_pair(
-        builder.create<IREE::Stream::TimepointImmediateOp>(loc).getResult(),
+        IREE::Stream::TimepointImmediateOp::create(builder, loc).getResult(),
         value);
   }
 }
@@ -233,7 +233,7 @@
 
   // If we couldn't find anything we could use we'll insert the size query. The
   // hope is that more program analysis could take care of this for us.
-  return builder.create<IREE::Stream::ResourceSizeOp>(loc, resourceValue);
+  return IREE::Stream::ResourceSizeOp::create(builder, loc, resourceValue);
 }
 
 // Recursively expands resources into (timepoint, resource) pairs within the
@@ -273,8 +273,8 @@
       // though and those are available.
       auto resourceSize =
           makeBlockArgResourceSize(region.getLoc(), resource, builder);
-      auto awaitOp = builder.create<IREE::Stream::TimepointAwaitOp>(
-          region.getLoc(), resource, resourceSize, timepoint);
+      auto awaitOp = IREE::Stream::TimepointAwaitOp::create(
+          builder, region.getLoc(), resource, resourceSize, timepoint);
       SmallPtrSet<Operation *, 2> excludedUsers;
       excludedUsers.insert(awaitOp);
       if (auto *sizeOp = resourceSize.getDefiningOp()) {
@@ -333,15 +333,15 @@
   if (resultSize) {
     replacementExceptions.insert(resultSize.getDefiningOp());
   } else {
-    auto sizeOp = builder.create<IREE::Stream::ResourceSizeOp>(
-        op.getLoc(), op.getLoadedGlobalValue());
+    auto sizeOp = IREE::Stream::ResourceSizeOp::create(
+        builder, op.getLoc(), op.getLoadedGlobalValue());
     replacementExceptions.insert(sizeOp);
     resultSize = sizeOp.getResult();
   }
   assert(resultSize && "need to be able to get a size");
 
-  auto awaitOp = builder.create<IREE::Stream::TimepointAwaitOp>(
-      op.getLoc(), op.getLoadedGlobalValue(), resultSize, timepoint);
+  auto awaitOp = IREE::Stream::TimepointAwaitOp::create(
+      builder, op.getLoc(), op.getLoadedGlobalValue(), resultSize, timepoint);
   replacementExceptions.insert(awaitOp);
 
   op.getLoadedGlobalValue().replaceAllUsesExcept(awaitOp.getResults().front(),
@@ -460,10 +460,10 @@
     auto newTimepoint = newOp.getResult(newIdx++);
     resourceTimepointMap.map(newResult, newTimepoint);
     auto newResultSize =
-        builder.create<IREE::Stream::ResourceSizeOp>(op.getLoc(), newResult)
+        IREE::Stream::ResourceSizeOp::create(builder, op.getLoc(), newResult)
             .getResult();
-    auto awaitOp = builder.create<IREE::Stream::TimepointAwaitOp>(
-        op.getLoc(), newResult, newResultSize, newTimepoint);
+    auto awaitOp = IREE::Stream::TimepointAwaitOp::create(
+        builder, op.getLoc(), newResult, newResultSize, newTimepoint);
     oldResult.replaceAllUsesWith(awaitOp.getResults().front());
   }
 
@@ -488,7 +488,7 @@
   OpBuilder builder(op);
   auto operands = expandOperands(op.getLoc(), op.getOperands(),
                                  resourceTimepointMap, builder);
-  builder.create<IREE::Util::ReturnOp>(op.getLoc(), operands);
+  IREE::Util::ReturnOp::create(builder, op.getLoc(), operands);
   op.erase();
 }
 
@@ -510,7 +510,7 @@
   OpBuilder builder(op);
   auto operands = expandOperands(op.getLoc(), op.getDestOperands(),
                                  resourceTimepointMap, builder);
-  builder.create<mlir::cf::BranchOp>(op.getLoc(), op.getDest(), operands);
+  mlir::cf::BranchOp::create(builder, op.getLoc(), op.getDest(), operands);
   op.erase();
 }
 
@@ -519,8 +519,8 @@
   if (!usesResources(op))
     return;
   OpBuilder builder(op);
-  builder.create<mlir::cf::CondBranchOp>(
-      op.getLoc(), op.getCondition(), op.getTrueDest(),
+  mlir::cf::CondBranchOp::create(
+      builder, op.getLoc(), op.getCondition(), op.getTrueDest(),
       expandOperands(op.getLoc(), op.getTrueDestOperands(),
                      resourceTimepointMap, builder),
       op.getFalseDest(),
@@ -540,8 +540,8 @@
                               builder);
       }));
   auto asValueRange = [](ArrayRef<Value> ref) -> ValueRange { return ref; };
-  builder.create<mlir::cf::SwitchOp>(
-      op.getLoc(), op.getFlag(), op.getDefaultDestination(),
+  mlir::cf::SwitchOp::create(
+      builder, op.getLoc(), op.getFlag(), op.getDefaultDestination(),
       expandOperands(op.getLoc(), op.getDefaultOperands(), resourceTimepointMap,
                      builder),
       op.getCaseValuesAttr(), op.getCaseDestinations(),
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/RefineUsage.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/RefineUsage.cpp
index 5b051be..358b13b 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/RefineUsage.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/RefineUsage.cpp
@@ -132,8 +132,8 @@
       auto resultSize = rewriter.createOrFold<IREE::Stream::ResourceSizeOp>(
           op->getLoc(), result);
       auto affinityAttr = getOpAffinity(op);
-      auto transferOp = rewriter.create<IREE::Stream::AsyncTransferOp>(
-          op->getLoc(), newType, result, resultSize, resultSize,
+      auto transferOp = IREE::Stream::AsyncTransferOp::create(
+          rewriter, op->getLoc(), newType, result, resultSize, resultSize,
           /*source_affinity=*/affinityAttr,
           /*target_affinity=*/affinityAttr);
       result.replaceUsesWithIf(transferOp.getResult(), [&](OpOperand &operand) {
@@ -180,8 +180,8 @@
           }
         }
       }
-      auto transferOp = rewriter.create<IREE::Stream::AsyncTransferOp>(
-          result.getLoc(), newType, result, resultSize, resultSize,
+      auto transferOp = IREE::Stream::AsyncTransferOp::create(
+          rewriter, result.getLoc(), newType, result, resultSize, resultSize,
           /*source_affinity=*/affinityAttr,
           /*target_affinity=*/affinityAttr);
       result.replaceAllUsesExcept(transferOp.getResult(), transferOp);
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ReuseAllocations.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ReuseAllocations.cpp
index 3fc0b9d..4dcc467 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ReuseAllocations.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ReuseAllocations.cpp
@@ -95,8 +95,8 @@
   Value availableTimepoint = chosenDeallocaOp.getAwaitTimepoint();
   if (!availableTimepoint) {
     OpBuilder builder(chosenDeallocaOp);
-    availableTimepoint = builder.create<IREE::Stream::TimepointImmediateOp>(
-        chosenDeallocaOp.getLoc());
+    availableTimepoint = IREE::Stream::TimepointImmediateOp::create(
+        builder, chosenDeallocaOp.getLoc());
   }
   allocaOp.replaceAllUsesWith(
       ValueRange{chosenDeallocaOp.getOperand(), availableTimepoint});
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp
index 48b6237..0132a57 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleAllocation.cpp
@@ -517,8 +517,8 @@
                                        AllocationScope &scope,
                                        OpBuilder builder) {
   auto targetRange = scope.lookupResourceRange(asyncOp.getResult());
-  builder.create<IREE::Stream::CmdFillOp>(
-      asyncOp.getLoc(), targetRange.resource, targetRange.resourceSize,
+  IREE::Stream::CmdFillOp::create(
+      builder, asyncOp.getLoc(), targetRange.resource, targetRange.resourceSize,
       targetRange.offset, targetRange.length, asyncOp.getValue());
   asyncOp.erase();
   return success();
@@ -529,8 +529,8 @@
                                        OpBuilder builder) {
   auto sourceRange = scope.lookupResourceRange(asyncOp.getSource());
   auto targetRange = scope.lookupResourceRange(asyncOp.getResult());
-  builder.create<IREE::Stream::CmdCopyOp>(
-      asyncOp.getLoc(), sourceRange.resource, sourceRange.resourceSize,
+  IREE::Stream::CmdCopyOp::create(
+      builder, asyncOp.getLoc(), sourceRange.resource, sourceRange.resourceSize,
       sourceRange.offset, targetRange.resource, targetRange.resourceSize,
       targetRange.offset, targetRange.length);
   asyncOp.erase();
@@ -544,8 +544,8 @@
   auto sourceOffset = scope.add(asyncOp.getLoc(), sourceRange.offset,
                                 asyncOp.getSourceOffset());
   auto targetRange = scope.lookupResourceRange(asyncOp.getResult());
-  builder.create<IREE::Stream::CmdCopyOp>(
-      asyncOp.getLoc(), sourceRange.resource, sourceRange.resourceSize,
+  IREE::Stream::CmdCopyOp::create(
+      builder, asyncOp.getLoc(), sourceRange.resource, sourceRange.resourceSize,
       sourceOffset, targetRange.resource, targetRange.resourceSize,
       targetRange.offset, asyncOp.getResultSize());
   asyncOp.erase();
@@ -558,8 +558,8 @@
   auto targetRange = scope.lookupResourceRange(asyncOp.getResult());
   auto targetOffset = scope.add(asyncOp.getLoc(), targetRange.offset,
                                 asyncOp.getTargetOffset());
-  builder.create<IREE::Stream::CmdFillOp>(
-      asyncOp.getLoc(), targetRange.resource, targetRange.resourceSize,
+  IREE::Stream::CmdFillOp::create(
+      builder, asyncOp.getLoc(), targetRange.resource, targetRange.resourceSize,
       targetOffset, asyncOp.getTargetLength(), asyncOp.getValue());
   asyncOp.erase();
   return success();
@@ -573,8 +573,8 @@
   auto targetRange = scope.lookupResourceRange(asyncOp.getResult());
   auto targetOffset = scope.add(asyncOp.getLoc(), targetRange.offset,
                                 asyncOp.getTargetOffset());
-  builder.create<IREE::Stream::CmdCopyOp>(
-      asyncOp.getLoc(), sourceRange.resource, sourceRange.resourceSize,
+  IREE::Stream::CmdCopyOp::create(
+      builder, asyncOp.getLoc(), sourceRange.resource, sourceRange.resourceSize,
       sourceOffset, targetRange.resource, targetRange.resourceSize,
       targetOffset, asyncOp.getUpdateSize());
   asyncOp.erase();
@@ -590,8 +590,8 @@
   auto targetRange = scope.lookupResourceRange(asyncOp.getResult());
   auto targetOffset = scope.add(asyncOp.getLoc(), targetRange.offset,
                                 asyncOp.getTargetOffset());
-  builder.create<IREE::Stream::CmdCopyOp>(
-      asyncOp.getLoc(), sourceRange.resource, sourceRange.resourceSize,
+  IREE::Stream::CmdCopyOp::create(
+      builder, asyncOp.getLoc(), sourceRange.resource, sourceRange.resourceSize,
       sourceOffset, targetRange.resource, targetRange.resourceSize,
       targetOffset, asyncOp.getLength());
   asyncOp.erase();
@@ -632,8 +632,8 @@
   newResourceAccesses.push_back(IREE::Stream::ResourceAccessBitfieldAttr::get(
       builder.getContext(), IREE::Stream::ResourceAccessBitfield::Write));
 
-  builder.create<IREE::Stream::CmdCollectiveOp>(
-      asyncOp.getLoc(), asyncOp.getOp(), asyncOp.getChannel(),
+  IREE::Stream::CmdCollectiveOp::create(
+      builder, asyncOp.getLoc(), asyncOp.getOp(), asyncOp.getChannel(),
       asyncOp.getElementCount(), asyncOp.getParam(), newResources,
       newResourceSizes, newResourceOffsets, newResourceLengths,
       builder.getArrayAttr(newResourceAccesses));
@@ -650,10 +650,10 @@
   auto targetRange = scope.lookupResourceRange(barrierOp.getResult());
 
   // Perform the copy.
-  builder.create<IREE::Stream::CmdCopyOp>(
-      barrierOp.getLoc(), sourceRange.resource, sourceRange.resourceSize,
-      sourceRange.offset, targetRange.resource, targetRange.resourceSize,
-      targetRange.offset, sourceRange.length);
+  IREE::Stream::CmdCopyOp::create(
+      builder, barrierOp.getLoc(), sourceRange.resource,
+      sourceRange.resourceSize, sourceRange.offset, targetRange.resource,
+      targetRange.resourceSize, targetRange.offset, sourceRange.length);
 
   barrierOp.erase();
   return success();
@@ -684,23 +684,23 @@
 
   // Incoming transfers need invalidation.
   if (transferIn) {
-    builder.create<IREE::Stream::CmdInvalidateOp>(
-        asyncOp.getLoc(), sourceRange.resource, sourceRange.resourceSize,
-        sourceRange.offset, sourceRange.length,
+    IREE::Stream::CmdInvalidateOp::create(
+        builder, asyncOp.getLoc(), sourceRange.resource,
+        sourceRange.resourceSize, sourceRange.offset, sourceRange.length,
         asyncOp.getSourceAffinityAttr());
   }
 
   // Perform the copy.
-  builder.create<IREE::Stream::CmdCopyOp>(
-      asyncOp.getLoc(), sourceRange.resource, sourceRange.resourceSize,
+  IREE::Stream::CmdCopyOp::create(
+      builder, asyncOp.getLoc(), sourceRange.resource, sourceRange.resourceSize,
       sourceRange.offset, targetRange.resource, targetRange.resourceSize,
       targetRange.offset, sourceRange.length);
 
   // Outgoing transfers need flushes.
   if (transferOut) {
-    builder.create<IREE::Stream::CmdFlushOp>(
-        asyncOp.getLoc(), targetRange.resource, targetRange.resourceSize,
-        targetRange.offset, targetRange.length,
+    IREE::Stream::CmdFlushOp::create(
+        builder, asyncOp.getLoc(), targetRange.resource,
+        targetRange.resourceSize, targetRange.offset, targetRange.length,
         asyncOp.getResultAffinityAttr());
   }
 
@@ -768,10 +768,11 @@
     newResourceAccesses.push_back(resourceAccess);
   }
 
-  auto newOp = builder.create<IREE::Stream::CmdDispatchOp>(
-      asyncOp.getLoc(), asyncOp.getWorkload(), asyncOp.getEntryPointsAttr(),
-      newOperands, newResources, newResourceSizes, newResourceOffsets,
-      newResourceLengths, builder.getArrayAttr(newResourceAccesses));
+  auto newOp = IREE::Stream::CmdDispatchOp::create(
+      builder, asyncOp.getLoc(), asyncOp.getWorkload(),
+      asyncOp.getEntryPointsAttr(), newOperands, newResources, newResourceSizes,
+      newResourceOffsets, newResourceLengths,
+      builder.getArrayAttr(newResourceAccesses));
   newOp->setDialectAttrs(asyncOp->getDialectAttrs());
   asyncOp.erase();
   return success();
@@ -826,9 +827,9 @@
       FunctionType::get(asyncOp.getContext(), newInputs, newResults);
 
   OpBuilder builder(asyncOp);
-  auto cmdOp = builder.create<IREE::Stream::CmdFuncOp>(
-      asyncOp.getLoc(), asyncOp.getName(), newFunctionType, newArgAttrs,
-      newResultAttrs);
+  auto cmdOp = IREE::Stream::CmdFuncOp::create(
+      builder, asyncOp.getLoc(), asyncOp.getName(), newFunctionType,
+      newArgAttrs, newResultAttrs);
   cmdOp->setDialectAttrs(asyncOp->getDialectAttrs());
   asyncOp.erase();
 }
@@ -898,8 +899,8 @@
     newResourceAccesses.push_back(resourceAccess);
   }
 
-  auto newOp = builder.create<IREE::Stream::CmdCallOp>(
-      asyncOp.getLoc(), newResultTypes, asyncOp.getCalleeAttr(),
+  auto newOp = IREE::Stream::CmdCallOp::create(
+      builder, asyncOp.getLoc(), newResultTypes, asyncOp.getCalleeAttr(),
       newResourceOperands, newResourceSizes, newResourceOffsets,
       newResourceLengths,
       /*result_sizes=*/ValueRange{},
@@ -936,7 +937,7 @@
   block.eraseArguments([&](auto arg) { return true; });
 
   // Rewrite wave op to remove results.
-  auto newOp = builder.create<IREE::Stream::CmdConcurrentOp>(asyncOp.getLoc());
+  auto newOp = IREE::Stream::CmdConcurrentOp::create(builder, asyncOp.getLoc());
   newOp.getBody().takeBody(asyncOp.getBody());
   asyncOp.erase();
   return success();
@@ -1086,8 +1087,8 @@
   auto fusedLoc = externalBuilder.getFusedLoc(locs);
   auto indexType = externalBuilder.getIndexType();
   SmallVector<Type> packedOffsetTypes(dynamicSliceSizes.size(), indexType);
-  auto packOp = externalBuilder.create<IREE::Stream::ResourcePackOp>(
-      fusedLoc, indexType, packedOffsetTypes,
+  auto packOp = IREE::Stream::ResourcePackOp::create(
+      externalBuilder, fusedLoc, indexType, packedOffsetTypes,
       /*offset=*/nullptr, externalBuilder.getIndexArrayAttr(lifetimeIntervals),
       dynamicSliceSizes, executeOp.getAffinityAttr());
 
@@ -1095,8 +1096,9 @@
   auto transientType = externalBuilder.getType<IREE::Stream::ResourceType>(
       IREE::Stream::Lifetime::Transient);
   auto timepointType = externalBuilder.getType<IREE::Stream::TimepointType>();
-  auto allocaOp = externalBuilder.create<IREE::Stream::ResourceAllocaOp>(
-      fusedLoc, transientType, timepointType, packOp.getTotalLength(),
+  auto allocaOp = IREE::Stream::ResourceAllocaOp::create(
+      externalBuilder, fusedLoc, transientType, timepointType,
+      packOp.getTotalLength(),
       /*indeterminate_lifetime=*/UnitAttr{}, executeOp.getAwaitTimepoint(),
       executeOp.getAffinityAttr());
   TransientAllocation allocation;
@@ -1286,11 +1288,10 @@
   }
   auto timepointType = externalBuilder.getType<IREE::Stream::TimepointType>();
   ConstantAllocation allocation;
-  allocation.constantsOp =
-      externalBuilder.create<IREE::Stream::ResourceConstantsOp>(
-          externalBuilder.getFusedLoc(locs), resultTypes, timepointType,
-          externalBuilder.getArrayAttr(initialValues), resultSizes,
-          affinityAttr);
+  allocation.constantsOp = IREE::Stream::ResourceConstantsOp::create(
+      externalBuilder, externalBuilder.getFusedLoc(locs), resultTypes,
+      timepointType, externalBuilder.getArrayAttr(initialValues), resultSizes,
+      affinityAttr);
 
   // Remap original constants to reservations.
   auto &entryBlock = executeOp.getBody().front();
@@ -1779,10 +1780,10 @@
                                                          externalBuilder);
       scope.mapResourceRange(yieldValue, resourceRange, asmState.get());
       if (resourceRange.offset) {
-        auto resultSubviewOp =
-            externalBuilder.create<IREE::Stream::ResourceSubviewOp>(
-                yieldValue.getLoc(), tiedOperand, resourceRange.resourceSize,
-                resourceRange.offset, resourceRange.length);
+        auto resultSubviewOp = IREE::Stream::ResourceSubviewOp::create(
+            externalBuilder, yieldValue.getLoc(), tiedOperand,
+            resourceRange.resourceSize, resourceRange.offset,
+            resourceRange.length);
         resultReplacements.push_back(
             std::make_pair(resultValue, resultSubviewOp.getResult()));
       } else {
@@ -1922,8 +1923,9 @@
 
   // Recreate the execution op with all the new arguments. Note that we drop
   // the results (besides the timepoint) as they are all aliased.
-  auto newExecuteOp = executeBuilder.create<IREE::Stream::CmdExecuteOp>(
-      executeOp.getLoc(), newAwaitTimepoint, newOperands, newOperandSizes);
+  auto newExecuteOp = IREE::Stream::CmdExecuteOp::create(
+      executeBuilder, executeOp.getLoc(), newAwaitTimepoint, newOperands,
+      newOperandSizes);
   newExecuteOp.setOnce(isExecutedOnce(executeOp));
   if (executeOp.getAffinity().has_value()) {
     newExecuteOp.setAffinityAttr(executeOp.getAffinityAttr());
@@ -2008,8 +2010,8 @@
   for (auto &release : pendingReleases) {
     auto reservation = release.first;
     auto reservationSize = release.second;
-    auto deallocaOp = builder.create<IREE::Stream::ResourceDeallocaOp>(
-        reservation.getLoc(), reservation, reservationSize,
+    auto deallocaOp = IREE::Stream::ResourceDeallocaOp::create(
+        builder, reservation.getLoc(), reservation, reservationSize,
         /*prefer_origin=*/false, newExecuteOp.getResultTimepoint(),
         newExecuteOp.getAffinityAttr());
     joinTimepoints.push_back(deallocaOp.getResultTimepoint());
@@ -2023,8 +2025,9 @@
     joinTimepoints.push_back(newExecuteOp.getResultTimepoint());
     auto fusedLoc = builder.getFusedLoc(llvm::map_to_vector(
         joinTimepoints, [](auto timepoint) { return timepoint.getLoc(); }));
-    auto joinOp = builder.create<IREE::Stream::TimepointJoinOp>(
-        fusedLoc, newExecuteOp.getResultTimepoint().getType(), joinTimepoints);
+    auto joinOp = IREE::Stream::TimepointJoinOp::create(
+        builder, fusedLoc, newExecuteOp.getResultTimepoint().getType(),
+        joinTimepoints);
     executeTimepointUsers.insert(joinOp);
     newExecuteOp.getResultTimepoint().replaceUsesWithIf(
         joinOp.getResultTimepoint(), [&](OpOperand &operand) {
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleConcurrency.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleConcurrency.cpp
index ec9c563..27cf5b7 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleConcurrency.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleConcurrency.cpp
@@ -105,9 +105,9 @@
 
     // TODO(benvanik): tie operands, or leave to canonicalization.
     SmallVector<int64_t> tiedOperands;
-    concurrentOp = parentBuilder.create<IREE::Stream::AsyncConcurrentOp>(
-        fusedLoc, resultTypes, resultSizes, operands, operandSizes,
-        tiedOperands);
+    concurrentOp = IREE::Stream::AsyncConcurrentOp::create(
+        parentBuilder, fusedLoc, resultTypes, resultSizes, operands,
+        operandSizes, tiedOperands);
 
     // Add entry block and arguments.
     auto &entryBlock = concurrentOp.getBody().emplaceBlock();
@@ -162,8 +162,8 @@
       if (resultSize)
         resultSizes.push_back(resultSize);
     }
-    builder.create<IREE::Stream::YieldOp>(concurrentOp.getLoc(), results,
-                                          resultSizes);
+    IREE::Stream::YieldOp::create(builder, concurrentOp.getLoc(), results,
+                                  resultSizes);
   }
 
   size_t ordinal = -1;
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleExecution.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleExecution.cpp
index 3a26bb9..c235779 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleExecution.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/ScheduleExecution.cpp
@@ -105,9 +105,9 @@
 
     // TODO(benvanik): tie operands, or leave to canonicalization.
     SmallVector<int64_t> tiedOperands;
-    executeOp = parentBuilder.create<IREE::Stream::AsyncExecuteOp>(
-        fusedLoc, resultTypes, resultSizes, /*awaitTimepoint=*/Value{},
-        operands, operandSizes, tiedOperands);
+    executeOp = IREE::Stream::AsyncExecuteOp::create(
+        parentBuilder, fusedLoc, resultTypes, resultSizes,
+        /*awaitTimepoint=*/Value{}, operands, operandSizes, tiedOperands);
     if (partition->affinity) {
       executeOp.setAffinityAttr(partition->affinity);
     }
@@ -181,8 +181,8 @@
       if (resultSize)
         resultSizes.push_back(resultSize);
     }
-    builder.create<IREE::Stream::YieldOp>(executeOp.getLoc(), results,
-                                          resultSizes);
+    IREE::Stream::YieldOp::create(builder, executeOp.getLoc(), results,
+                                  resultSizes);
     return executeOp;
   }
 
@@ -279,8 +279,8 @@
         // prematurely tie their lifetimes together. By having unique awaits
         // we allow propagation to move the waits further to where the values
         // are used (including right into other execution regions).
-        auto awaitOp = builder.create<IREE::Stream::TimepointAwaitOp>(
-            executeOp.getLoc(), newResult, newResultSize,
+        auto awaitOp = IREE::Stream::TimepointAwaitOp::create(
+            builder, executeOp.getLoc(), newResult, newResultSize,
             executeOp.getResultTimepoint());
 
         // Explicitly copy the Value since it is marked as const.
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/SpecializeDispatches.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/SpecializeDispatches.cpp
index 36371f8..f46ab0e 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/SpecializeDispatches.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/SpecializeDispatches.cpp
@@ -181,8 +181,8 @@
   SmallVector<Value> tableTensors;
   for (auto &set : constantTable.sets) {
     auto tableAttr = buildConstantSetAttr(set, builder);
-    auto tableTensor = builder.create<arith::ConstantOp>(
-        builder.getFusedLoc(set.locs.takeVector()), tableAttr);
+    auto tableTensor = arith::ConstantOp::create(
+        builder, builder.getFusedLoc(set.locs.takeVector()), tableAttr);
     tableTensors.push_back(tableTensor);
   }
 
@@ -204,8 +204,8 @@
                                     })
                                 .getResult();
       if (extractedValue.getType() != arg.getType()) {
-        extractedValue = builder.create<arith::IndexCastOp>(
-            arg.getLoc(), arg.getType(), extractedValue);
+        extractedValue = arith::IndexCastOp::create(
+            builder, arg.getLoc(), arg.getType(), extractedValue);
       }
       arg.replaceAllUsesWith(extractedValue);
     }
diff --git a/compiler/src/iree/compiler/Dialect/TensorExt/IR/TensorExtDialect.cpp b/compiler/src/iree/compiler/Dialect/TensorExt/IR/TensorExtDialect.cpp
index c502c58..93da383 100644
--- a/compiler/src/iree/compiler/Dialect/TensorExt/IR/TensorExtDialect.cpp
+++ b/compiler/src/iree/compiler/Dialect/TensorExt/IR/TensorExtDialect.cpp
@@ -55,7 +55,8 @@
                                                      Attribute value, Type type,
                                                      Location loc) {
   if (arith::ConstantOp::isBuildableWith(value, type)) {
-    return builder.create<arith::ConstantOp>(loc, type, cast<TypedAttr>(value));
+    return arith::ConstantOp::create(builder, loc, type,
+                                     cast<TypedAttr>(value));
   }
   return nullptr;
 }
diff --git a/compiler/src/iree/compiler/Dialect/TensorExt/IR/TensorExtOpFolders.cpp b/compiler/src/iree/compiler/Dialect/TensorExt/IR/TensorExtOpFolders.cpp
index e543777..c812871 100644
--- a/compiler/src/iree/compiler/Dialect/TensorExt/IR/TensorExtOpFolders.cpp
+++ b/compiler/src/iree/compiler/Dialect/TensorExt/IR/TensorExtOpFolders.cpp
@@ -85,9 +85,9 @@
     auto newType =
         RankedTensorType::get(newResultSizes, resTensorType.getElementType(),
                               resTensorType.getEncoding());
-    Value newBitcast = rewriter.create<BitCastOp>(
-        bitcastOp.getLoc(), newType, tensorCastOp.getOperand(), newDynamicDims,
-        newDynamicDims);
+    Value newBitcast = BitCastOp::create(rewriter, bitcastOp.getLoc(), newType,
+                                         tensorCastOp.getOperand(),
+                                         newDynamicDims, newDynamicDims);
     // We create a new cast to continue propagating static information.
     rewriter.replaceOpWithNewOp<tensor::CastOp>(bitcastOp, resTensorType,
                                                 newBitcast);
@@ -260,12 +260,12 @@
 
     // We need to resolve the new inferred type with the specified type.
     Location loc = loadOp.getLoc();
-    Value replacement = rewriter.create<DispatchTensorLoadOp>(
-        loc, newResultType.value(), loadOp.getSource(), loadOp.getSourceDims(),
-        mixedOffsets, mixedSizes, mixedStrides);
+    Value replacement = DispatchTensorLoadOp::create(
+        rewriter, loc, newResultType.value(), loadOp.getSource(),
+        loadOp.getSourceDims(), mixedOffsets, mixedSizes, mixedStrides);
     if (newResultType.value() != resultType) {
       replacement =
-          rewriter.create<tensor::CastOp>(loc, resultType, replacement);
+          tensor::CastOp::create(rewriter, loc, resultType, replacement);
     }
     rewriter.replaceOp(loadOp, replacement);
     return success();
@@ -361,7 +361,8 @@
     Value value = storeOp.getValue();
     Location loc = storeOp.getLoc();
     if (newValueType.value() != valueType) {
-      value = rewriter.create<tensor::CastOp>(loc, newValueType.value(), value);
+      value =
+          tensor::CastOp::create(rewriter, loc, newValueType.value(), value);
     }
     rewriter.replaceOpWithNewOp<DispatchTensorStoreOp>(
         storeOp, value, storeOp.getTarget(), storeOp.getTargetDims(),
@@ -412,8 +413,8 @@
       }
       break;
     }
-    auto newOrdinalOp = rewriter.create<DispatchWorkloadOrdinalOp>(
-        ordinalOp.getLoc(), blockArg, ordinalOp.getOrdinalAttr());
+    auto newOrdinalOp = DispatchWorkloadOrdinalOp::create(
+        rewriter, ordinalOp.getLoc(), blockArg, ordinalOp.getOrdinalAttr());
     rewriter.replaceAllUsesExcept(blockArg, newOrdinalOp, newOrdinalOp);
     rewriter.replaceOp(ordinalOp, newOrdinalOp.getResult());
     return success();
diff --git a/compiler/src/iree/compiler/Dialect/Util/Conversion/ConversionPatterns.cpp b/compiler/src/iree/compiler/Dialect/Util/Conversion/ConversionPatterns.cpp
index 346660f..b0dc837 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Conversion/ConversionPatterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Conversion/ConversionPatterns.cpp
@@ -298,9 +298,9 @@
         llvm::map_to_vector(ifOp.getResultTypes(), [&](Type type) {
           return getTypeConverter()->convertType(type);
         });
-    auto newOp = rewriter.create<scf::IfOp>(ifOp.getLoc(), resultTypes,
-                                            adaptor.getCondition(),
-                                            ifOp.elseBlock() != nullptr);
+    auto newOp =
+        scf::IfOp::create(rewriter, ifOp.getLoc(), resultTypes,
+                          adaptor.getCondition(), ifOp.elseBlock() != nullptr);
     rewriter.inlineRegionBefore(ifOp.getThenRegion(), newOp.getThenRegion(),
                                 newOp.getThenRegion().end());
     rewriter.eraseBlock(&newOp.getThenRegion().front());
diff --git a/compiler/src/iree/compiler/Dialect/Util/Conversion/FuncToUtil/Patterns.cpp b/compiler/src/iree/compiler/Dialect/Util/Conversion/FuncToUtil/Patterns.cpp
index 3bf9b84..81d7546 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Conversion/FuncToUtil/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Conversion/FuncToUtil/Patterns.cpp
@@ -65,8 +65,9 @@
     auto newFuncType = mlir::FunctionType::get(
         srcOp.getContext(), signatureConversion.getConvertedTypes(),
         convertedResultTypes);
-    auto newFuncOp = rewriter.create<IREE::Util::FuncOp>(
-        srcOp.getLoc(), srcOp.getName(), newFuncType, tiedOperandsAttr);
+    auto newFuncOp =
+        IREE::Util::FuncOp::create(rewriter, srcOp.getLoc(), srcOp.getName(),
+                                   newFuncType, tiedOperandsAttr);
     newFuncOp.setSymVisibilityAttr(srcOp.getSymVisibilityAttr());
     rewriter.inlineRegionBefore(srcOp.getBody(), newFuncOp.getFunctionBody(),
                                 newFuncOp.end());
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 68028b0..8835337 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Conversion/MemRefToUtil/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Conversion/MemRefToUtil/Patterns.cpp
@@ -66,7 +66,7 @@
 
   // Rank 1 memrefs are just offset by their element width by the offset.
   auto elementCount = indices[0];
-  return builder.create<arith::MulIOp>(loc, elementTypeByteSize, elementCount);
+  return arith::MulIOp::create(builder, loc, elementTypeByteSize, elementCount);
 }
 
 static Value getByteLength(OpBuilder &builder, Location loc,
@@ -79,7 +79,7 @@
     emitError(loc, "memrefs should have been flattened");
     return {};
   }
-  Value size = builder.create<memref::DimOp>(loc, memrefValue, 0);
+  Value size = memref::DimOp::create(builder, loc, memrefValue, 0);
   Value elementTypeByteSize = getElementTypeByteSize(builder, loc, memrefValue);
   return getByteOffsetForIndices(builder, loc, memrefValue, {size},
                                  elementTypeByteSize);
@@ -135,19 +135,19 @@
     newOp.setPrivate();
 
     auto initializerOp =
-        rewriter.create<IREE::Util::InitializerOp>(globalOp.getLoc());
+        IREE::Util::InitializerOp::create(rewriter, globalOp.getLoc());
     auto initializerBuilder =
         OpBuilder::atBlockBegin(initializerOp.addEntryBlock());
     auto alignmentAttr = globalOp.getAlignmentAttr()
                              ? initializerBuilder.getIndexAttr(
                                    globalOp.getAlignmentAttr().getInt())
                              : IntegerAttr{};
-    auto constantOp = initializerBuilder.create<IREE::Util::BufferConstantOp>(
-        globalOp.getLoc(), /*name=*/nullptr, globalOp.getInitialValueAttr(),
-        alignmentAttr, /*mimeType=*/nullptr);
+    auto constantOp = IREE::Util::BufferConstantOp::create(
+        initializerBuilder, globalOp.getLoc(), /*name=*/nullptr,
+        globalOp.getInitialValueAttr(), alignmentAttr, /*mimeType=*/nullptr);
     newOp.createStoreOp(globalOp.getLoc(), constantOp.getResult(),
                         initializerBuilder);
-    initializerBuilder.create<IREE::Util::ReturnOp>(globalOp.getLoc());
+    IREE::Util::ReturnOp::create(initializerBuilder, globalOp.getLoc());
 
     return success();
   }
@@ -197,8 +197,8 @@
         llvm::cast<MemRefType>(dimOp.getSource().getType()).getElementType();
     Value elementSize = rewriter.createOrFold<IREE::Util::SizeOfOp>(
         dimOp.getLoc(), elementType);
-    Value bufferSize = rewriter.create<IREE::Util::BufferSizeOp>(
-        dimOp.getLoc(), rewriter.getIndexType(), adaptor.getSource());
+    Value bufferSize = IREE::Util::BufferSizeOp::create(
+        rewriter, dimOp.getLoc(), rewriter.getIndexType(), adaptor.getSource());
     rewriter.replaceOpWithNewOp<arith::FloorDivSIOp>(dimOp, bufferSize,
                                                      elementSize);
     return success();
@@ -225,8 +225,8 @@
     auto byteOffset =
         getByteOffsetForIndices(rewriter, loc, loadOp.getMemref(),
                                 loadOp.getIndices(), elementTypeByteSize);
-    Value loaded = rewriter.create<IREE::Util::BufferLoadOp>(
-        loc, oldType, adaptor.getMemref(), memRefSize, byteOffset,
+    Value loaded = IREE::Util::BufferLoadOp::create(
+        rewriter, loc, oldType, adaptor.getMemref(), memRefSize, byteOffset,
         elementTypeByteSize);
     if (newType != oldType) {
       // Since the BufferLoadOp semantics include its result type (i.e. a load
@@ -235,8 +235,9 @@
       // conversion cast for downstreams. In this case, further legalizations
       // will be required to resolve it. This comes up in A->B->C lowerings
       // where the BufferLoad is an intermediate stage.
-      loaded = rewriter.create<UnrealizedConversionCastOp>(loc, newType, loaded)
-                   .getResult(0);
+      loaded =
+          UnrealizedConversionCastOp::create(rewriter, loc, newType, loaded)
+              .getResult(0);
     }
     rewriter.replaceOp(loadOp, loaded);
     return success();
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilDialect.cpp b/compiler/src/iree/compiler/Dialect/Util/IR/UtilDialect.cpp
index e85f25d..d7f773f 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilDialect.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilDialect.cpp
@@ -88,8 +88,8 @@
     if (!returnOp)
       return;
     OpBuilder builder(op);
-    builder.create<mlir::cf::BranchOp>(op->getLoc(), newDest,
-                                       returnOp.getOperands());
+    mlir::cf::BranchOp::create(builder, op->getLoc(), newDest,
+                               returnOp.getOperands());
     op->erase();
   }
 
@@ -128,9 +128,10 @@
 Operation *UtilDialect::materializeConstant(OpBuilder &builder, Attribute value,
                                             Type type, Location loc) {
   if (isa<IREE::Util::NullAttr>(value)) {
-    return builder.create<IREE::Util::NullOp>(loc, type);
+    return IREE::Util::NullOp::create(builder, loc, type);
   } else if (arith::ConstantOp::isBuildableWith(value, type)) {
-    return builder.create<arith::ConstantOp>(loc, type, cast<TypedAttr>(value));
+    return arith::ConstantOp::create(builder, loc, type,
+                                     cast<TypedAttr>(value));
   }
   return nullptr;
 }
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOpFolders.cpp b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOpFolders.cpp
index c680b17..f42bc14 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOpFolders.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOpFolders.cpp
@@ -124,10 +124,10 @@
       Value constantValue;
       if (result.getType().isIndex()) {
         constantValue =
-            rewriter.create<arith::ConstantIndexOp>(op.getLoc(), *fixedValue);
+            arith::ConstantIndexOp::create(rewriter, op.getLoc(), *fixedValue);
       } else {
-        constantValue = rewriter.create<arith::ConstantIntOp>(
-            op.getLoc(), result.getType(), *fixedValue);
+        constantValue = arith::ConstantIntOp::create(
+            rewriter, op.getLoc(), result.getType(), *fixedValue);
       }
       rewriter.replaceAllUsesWith(result, constantValue);
       madeChange = true;
@@ -147,7 +147,7 @@
 
   if (!newOperands.empty()) {
     auto newOp =
-        rewriter.create<AssumeIntOp>(op.getLoc(), newOperands, newAssumptions);
+        AssumeIntOp::create(rewriter, op.getLoc(), newOperands, newAssumptions);
     rewriter.replaceAllUsesWith(retainedResults, newOp.getResults());
   }
 
@@ -253,7 +253,7 @@
     }
 
     auto newOp =
-        rewriter.create<AssumeIntOp>(op.getLoc(), newOperands, newRanges);
+        AssumeIntOp::create(rewriter, op.getLoc(), newOperands, newRanges);
     rewriter.replaceAllUsesWith(valuesToReplace, newOp.getResults());
     rewriter.eraseOp(op);
     return success();
@@ -493,8 +493,8 @@
       return failure();
     }
     if (constantValue != initialValue) {
-      operands.insert(rewriter.create<arith::ConstantOp>(
-          op.getLoc(), op.getResult().getType(),
+      operands.insert(arith::ConstantOp::create(
+          rewriter, op.getLoc(), op.getResult().getType(),
           rewriter.getIntegerAttr(op.getResult().getType(), constantValue)));
     }
     rewriter.replaceOpWithNewOp<OpT>(op, op.getResult().getType(),
@@ -523,15 +523,15 @@
 
 static Value makeRangeEnd(Location loc, Value offset, Value length, Value one,
                           OpBuilder &builder) {
-  return builder.create<arith::SubIOp>(
-      loc, builder.create<arith::AddIOp>(loc, offset, length), one);
+  return arith::SubIOp::create(
+      builder, loc, arith::AddIOp::create(builder, loc, offset, length), one);
 }
 static Value makeRangeEnd(Location loc, Value offset, Value length,
                           OpBuilder &builder) {
   return makeRangeEnd(
       loc, offset, length,
-      builder.create<arith::ConstantOp>(
-          loc, offset.getType(), builder.getIntegerAttr(offset.getType(), 1)),
+      arith::ConstantOp::create(builder, loc, offset.getType(),
+                                builder.getIntegerAttr(offset.getType(), 1)),
       builder);
 }
 
@@ -570,28 +570,30 @@
     Value min;
     Value max;
     if (!offsets.empty()) {
-      auto newOp = rewriter.create<RangeExtentsOp>(
-          op.getLoc(), op.getMin().getType(), op.getMax().getType(), offsets,
-          lengths);
+      auto newOp =
+          RangeExtentsOp::create(rewriter, op.getLoc(), op.getMin().getType(),
+                                 op.getMax().getType(), offsets, lengths);
       min = newOp.getMin();
       max = newOp.getMax();
     }
 
     // Min/max with constant ranges. This allows for normal folding to happen
     // downstream of the op.
-    auto constantMinOp = rewriter.create<arith::ConstantOp>(
-        op.getLoc(), op.getMin().getType(),
+    auto constantMinOp = arith::ConstantOp::create(
+        rewriter, op.getLoc(), op.getMin().getType(),
         rewriter.getIntegerAttr(op.getMin().getType(), constantMin));
-    auto constantMaxOp = rewriter.create<arith::ConstantOp>(
-        op.getLoc(), op.getMax().getType(),
+    auto constantMaxOp = arith::ConstantOp::create(
+        rewriter, op.getLoc(), op.getMax().getType(),
         rewriter.getIntegerAttr(op.getMax().getType(),
                                 constantMax - constantMin + 1));
-    min = min ? rewriter.create<arith::MinUIOp>(op.getLoc(), min, constantMinOp)
-                    .getResult()
-              : constantMinOp.getResult();
-    max = max ? rewriter.create<arith::MaxUIOp>(op.getLoc(), max, constantMaxOp)
-                    .getResult()
-              : constantMaxOp.getResult();
+    min =
+        min ? arith::MinUIOp::create(rewriter, op.getLoc(), min, constantMinOp)
+                  .getResult()
+            : constantMinOp.getResult();
+    max =
+        max ? arith::MaxUIOp::create(rewriter, op.getLoc(), max, constantMaxOp)
+                  .getResult()
+            : constantMaxOp.getResult();
 
     rewriter.replaceOp(op, {min, max});
     return success();
@@ -611,16 +613,16 @@
                               op.getLengths().front(), rewriter);
     } else if (op.getOffsets().size() == 2) {
       // Two ranges turn into min/max.
-      minValue = rewriter.create<arith::MinUIOp>(loc, op.getOffsets().front(),
-                                                 op.getOffsets().back());
-      auto one = rewriter.create<arith::ConstantOp>(
-          loc, op.getMin().getType(),
+      minValue = arith::MinUIOp::create(rewriter, loc, op.getOffsets().front(),
+                                        op.getOffsets().back());
+      auto one = arith::ConstantOp::create(
+          rewriter, loc, op.getMin().getType(),
           rewriter.getIntegerAttr(op.getMin().getType(), 1));
       auto endLhs = makeRangeEnd(loc, op.getOffsets().front(),
                                  op.getLengths().front(), one, rewriter);
       auto endRhs = makeRangeEnd(loc, op.getOffsets().back(),
                                  op.getLengths().back(), one, rewriter);
-      maxValue = rewriter.create<arith::MaxUIOp>(loc, endLhs, endRhs);
+      maxValue = arith::MaxUIOp::create(rewriter, loc, endLhs, endRhs);
     }
     if (!minValue || !maxValue)
       return failure();
@@ -827,8 +829,8 @@
   using OpRewritePattern::OpRewritePattern;
   LogicalResult matchAndRewrite(UnfoldableConstantOp op,
                                 PatternRewriter &rewriter) const override {
-    auto stdConst = rewriter.create<arith::ConstantOp>(
-        op.getLoc(), cast<TypedAttr>(op.getValue()));
+    auto stdConst = arith::ConstantOp::create(rewriter, op.getLoc(),
+                                              cast<TypedAttr>(op.getValue()));
     rewriter.replaceOpWithNewOp<OptimizationBarrierOp>(op,
                                                        stdConst.getResult());
     return success();
@@ -993,9 +995,9 @@
     auto fusedLoc = rewriter.getFusedLoc({parentOp.getLoc(), op.getLoc()});
     auto newOffset = rewriter.createOrFold<arith::AddIOp>(
         fusedLoc, parentOp.getSourceOffset(), op.getSourceOffset());
-    auto newOp = rewriter.create<BufferSubspanOp>(
-        fusedLoc, parentOp.getSource(), parentOp.getSourceSize(), newOffset,
-        op.getResultSize());
+    auto newOp = BufferSubspanOp::create(
+        rewriter, fusedLoc, parentOp.getSource(), parentOp.getSourceSize(),
+        newOffset, op.getResultSize());
     rewriter.replaceOp(op, newOp.getResult());
     return success();
   }
@@ -1065,8 +1067,8 @@
         trueSubspan.getResultSize() != falseSubspan.getResultSize()) {
       return failure();
     }
-    auto offsetSelectOp = rewriter.create<mlir::arith::SelectOp>(
-        op.getLoc(), op.getCondition(), trueSubspan.getSourceOffset(),
+    auto offsetSelectOp = mlir::arith::SelectOp::create(
+        rewriter, op.getLoc(), op.getCondition(), trueSubspan.getSourceOffset(),
         falseSubspan.getSourceOffset());
     rewriter.replaceOpWithNewOp<IREE::Util::BufferSubspanOp>(
         op, op.getResult().getType(), trueSubspan.getSource(),
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp
index 1d41709..6a71f3b 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp
@@ -49,11 +49,11 @@
   for (size_t i = 0; i < count; ++i) {
     caseValues.push_back(caseBuilder(loc, i, builder));
   }
-  Value result = builder.create<arith::ConstantIndexOp>(loc, -1);
+  Value result = arith::ConstantIndexOp::create(builder, loc, -1);
   for (int i = count - 1; i >= 0; --i) {
-    result = builder.create<arith::SelectOp>(
-        loc, caseValues[i], builder.create<arith::ConstantIndexOp>(loc, i),
-        result);
+    result = arith::SelectOp::create(
+        builder, loc, caseValues[i],
+        arith::ConstantIndexOp::create(builder, loc, i), result);
   }
   return result;
 }
@@ -1911,10 +1911,10 @@
                            IREE::Util::TiedOpInterface::kUntiedIndex);
   }
 
-  return builder.create<IREE::Util::CallOp>(
-      getLoc(), newResultTypes, getCallee(), newOperands,
-      builder.getIndexArrayAttr(newTiedOperands), getArgAttrsAttr(),
-      getResAttrsAttr());
+  return IREE::Util::CallOp::create(builder, getLoc(), newResultTypes,
+                                    getCallee(), newOperands,
+                                    builder.getIndexArrayAttr(newTiedOperands),
+                                    getArgAttrsAttr(), getResAttrsAttr());
 }
 
 //===----------------------------------------------------------------------===//
@@ -2013,12 +2013,13 @@
   // TODO(benvanik): create with the immutable flag if the global is immutable.
   // Today we avoid this and let analysis add the immutable flag when safe
   // (not in initializers/etc).
-  return builder.create<IREE::Util::GlobalLoadOp>(loc, getType(), getSymName());
+  return IREE::Util::GlobalLoadOp::create(builder, loc, getType(),
+                                          getSymName());
 }
 
 IREE::Util::GlobalStoreOpInterface
 GlobalOp::createStoreOp(Location loc, Value value, OpBuilder &builder) {
-  return builder.create<IREE::Util::GlobalStoreOp>(loc, value, getSymName());
+  return IREE::Util::GlobalStoreOp::create(builder, loc, value, getSymName());
 }
 
 void GlobalAddressOp::getAsmResultNames(
diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.cpp b/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.cpp
index e3a5277..6734c65 100644
--- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilTypes.cpp
@@ -48,8 +48,8 @@
                                    Value resourceSize, Value subrangeOffset,
                                    Value subrangeLength,
                                    OpBuilder &builder) const {
-  return builder.create<IREE::Util::BufferSubspanOp>(
-      loc, resource, resourceSize, subrangeOffset, subrangeLength);
+  return IREE::Util::BufferSubspanOp::create(
+      builder, loc, resource, resourceSize, subrangeOffset, subrangeLength);
 }
 
 //===----------------------------------------------------------------------===//
@@ -839,7 +839,7 @@
     if (ShapedType::isDynamic(dim)) {
       dims.push_back(dynamicDims[dynamicIdx++]);
     } else {
-      dims.push_back(builder.create<arith::ConstantIndexOp>(loc, dim));
+      dims.push_back(arith::ConstantIndexOp::create(builder, loc, dim));
     }
   }
   return dims;
diff --git a/compiler/src/iree/compiler/Dialect/Util/TransformOps/UtilTransformOps.cpp b/compiler/src/iree/compiler/Dialect/Util/TransformOps/UtilTransformOps.cpp
index 108cdee..7cbae6a 100644
--- a/compiler/src/iree/compiler/Dialect/Util/TransformOps/UtilTransformOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/TransformOps/UtilTransformOps.cpp
@@ -440,8 +440,8 @@
     replacements = terminator->getOperands();
     rewriter.eraseOp(terminator);
   } else {
-    auto callOp = rewriter.create<IREE::Util::CallOp>(
-        insertionPoint->getLoc(), targetFunction.getResultTypes(),
+    auto callOp = IREE::Util::CallOp::create(
+        rewriter, insertionPoint->getLoc(), targetFunction.getResultTypes(),
         targetFunction.getName(), inputs, /*tied_operands=*/ArrayAttr{},
         /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr);
     exceptedUser = callOp;
diff --git a/compiler/src/iree/compiler/Dialect/Util/Transforms/CombineInitializers.cpp b/compiler/src/iree/compiler/Dialect/Util/Transforms/CombineInitializers.cpp
index 8e8904b..4acdc24 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Transforms/CombineInitializers.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Transforms/CombineInitializers.cpp
@@ -56,7 +56,7 @@
     // we are combining - this ensures that module initialization order is
     // preserved.
     OpBuilder builder(initializerOps.front());
-    auto newOp = builder.create<IREE::Util::InitializerOp>(fusedLoc);
+    auto newOp = IREE::Util::InitializerOp::create(builder, fusedLoc);
     builder.setInsertionPointToStart(newOp.addEntryBlock());
     InlinerInterface inlinerInterface(&getContext());
     for (auto initializerOp : initializerOps) {
@@ -74,7 +74,7 @@
       builder.setInsertionPointToEnd(&newOp.back());
       initializerOp.erase();
     }
-    builder.create<IREE::Util::ReturnOp>(fusedLoc);
+    IREE::Util::ReturnOp::create(builder, fusedLoc);
   }
 };
 
diff --git a/compiler/src/iree/compiler/Dialect/Util/Transforms/FoldGlobals.cpp b/compiler/src/iree/compiler/Dialect/Util/Transforms/FoldGlobals.cpp
index 7710343..7abbdf5 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Transforms/FoldGlobals.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Transforms/FoldGlobals.cpp
@@ -186,10 +186,10 @@
                                     OpBuilder &builder) {
   if (arith::ConstantOp::isBuildableWith(attr, type)) {
     // Common case fast-path.
-    return builder.create<arith::ConstantOp>(loc, type, cast<TypedAttr>(attr));
+    return arith::ConstantOp::create(builder, loc, type, cast<TypedAttr>(attr));
   } else if (mlir::func::ConstantOp::isBuildableWith(attr, type)) {
-    return builder.create<mlir::func::ConstantOp>(
-        loc, type, llvm::cast<FlatSymbolRefAttr>(attr));
+    return mlir::func::ConstantOp::create(builder, loc, type,
+                                          llvm::cast<FlatSymbolRefAttr>(attr));
   }
   // Fallback that asks a dialect to materialize things. This may fail!
   auto *op = attr.getDialect().materializeConstant(builder, attr, type, loc);
diff --git a/compiler/src/iree/compiler/Dialect/Util/Transforms/HoistIntoGlobals.cpp b/compiler/src/iree/compiler/Dialect/Util/Transforms/HoistIntoGlobals.cpp
index b0bf3ff..98fd7b4 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Transforms/HoistIntoGlobals.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Transforms/HoistIntoGlobals.cpp
@@ -187,8 +187,8 @@
 
     // No existing mapping - create a new global.
     OpBuilder moduleBuilder(topLevelOp);
-    auto initializerOp =
-        moduleBuilder.create<IREE::Util::InitializerOp>(originalValue.getLoc());
+    auto initializerOp = IREE::Util::InitializerOp::create(
+        moduleBuilder, originalValue.getLoc());
     initializerOp->setDialectAttrs(dialectAttrs);
     auto initializerBuilder =
         OpBuilder::atBlockEnd(initializerOp.addEntryBlock());
@@ -288,8 +288,8 @@
         // Allow the storage type of the global to differ from the local type.
         globalType = hoistableType.getPreferredStorageType();
       }
-      auto globalOp = moduleBuilder.create<IREE::Util::GlobalOp>(
-          loc, getHoistedName(globalType), false, globalType);
+      auto globalOp = IREE::Util::GlobalOp::create(
+          moduleBuilder, loc, getHoistedName(globalType), false, globalType);
       moduleSymbols.insert(globalOp);
       SymbolTable::setSymbolVisibility(globalOp,
                                        SymbolTable::Visibility::Private);
@@ -319,7 +319,7 @@
       globalOp.createStoreOp(loc, clonedResult, initializerBuilder);
     }
 
-    initializerBuilder.create<IREE::Util::ReturnOp>(loc);
+    IREE::Util::ReturnOp::create(initializerBuilder, loc);
     return success();
   }
 
diff --git a/compiler/src/iree/compiler/Dialect/Util/Transforms/IPO.cpp b/compiler/src/iree/compiler/Dialect/Util/Transforms/IPO.cpp
index 2a5d83e..c8cf8f9 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Transforms/IPO.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Transforms/IPO.cpp
@@ -413,8 +413,8 @@
 
   // Immutable global loads are represented as constant symbol refs.
   if (auto globalRef = dyn_cast<SymbolRefAttr>(constantValue.attr)) {
-    op = builder.create<IREE::Util::GlobalLoadOp>(
-        constantValue.loc.value(), constantValue.type,
+    op = IREE::Util::GlobalLoadOp::create(
+        builder, constantValue.loc.value(), constantValue.type,
         globalRef.getLeafReference().getValue(),
         /*is_immutable=*/true);
   }
@@ -423,9 +423,9 @@
   // themselves.
   if (arith::ConstantOp::isBuildableWith(constantValue.attr,
                                          constantValue.type)) {
-    op = builder.create<arith::ConstantOp>(constantValue.loc.value(),
-                                           constantValue.type,
-                                           cast<TypedAttr>(constantValue.attr));
+    op = arith::ConstantOp::create(builder, constantValue.loc.value(),
+                                   constantValue.type,
+                                   cast<TypedAttr>(constantValue.attr));
   }
 
   // Try the attr and type dialects to see if they can materialize.
diff --git a/compiler/src/iree/compiler/Dialect/Util/Transforms/OptimizeIntArithmetic.cpp b/compiler/src/iree/compiler/Dialect/Util/Transforms/OptimizeIntArithmetic.cpp
index 2a291b5..bd6a278 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Transforms/OptimizeIntArithmetic.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Transforms/OptimizeIntArithmetic.cpp
@@ -174,8 +174,8 @@
       for (auto &operand : producer->getOpOperands()) {
         if (operand.get().getType() != inType)
           continue;
-        Value newOperand = rewriter.create<arith::IndexCastUIOp>(
-            producer->getLoc(), outType, operand.get());
+        Value newOperand = arith::IndexCastUIOp::create(
+            rewriter, producer->getLoc(), outType, operand.get());
         operand.set(newOperand);
       }
       producer->getResult(0).setType(outType);
@@ -229,15 +229,15 @@
       newArgs.push_back(arg.getDefiningOp<arith::IndexCastUIOp>().getIn());
     }
     ArrayAttr assumptions = op.getAssumptionsAttr();
-    auto newOp = rewriter.create<Util::AssumeIntOp>(
-        op.getLoc(), ValueTypeRange<ArrayRef<Value>>{newArgs}, newArgs,
-        assumptions);
+    auto newOp = Util::AssumeIntOp::create(
+        rewriter, op.getLoc(), ValueTypeRange<ArrayRef<Value>>{newArgs},
+        newArgs, assumptions);
     SmallVector<Value> replacements(newOp.getResults());
     for (auto [newRes, oldRes] :
          llvm::zip_equal(replacements, op.getResults())) {
       if (newRes.getType() != oldRes.getType()) {
-        newRes = rewriter.create<arith::IndexCastUIOp>(
-            op.getLoc(), oldRes.getType(), newRes);
+        newRes = arith::IndexCastUIOp::create(rewriter, op.getLoc(),
+                                              oldRes.getType(), newRes);
       }
       // Preserve assumption state.
       auto *oldState = solver.lookupState<IntegerValueRangeLattice>(oldRes);
@@ -280,9 +280,9 @@
     Type i32 = rewriter.getI32Type();
     auto doCastDown = [&](Value v) -> Value {
       if (srcType.isIndex())
-        return rewriter.create<arith::IndexCastUIOp>(loc, i32, v);
+        return arith::IndexCastUIOp::create(rewriter, loc, i32, v);
       else
-        return rewriter.create<arith::TruncIOp>(loc, i32, v);
+        return arith::TruncIOp::create(rewriter, loc, i32, v);
     };
     Value newLb = doCastDown(forOp.getLowerBound());
     Value newUb = doCastDown(forOp.getUpperBound());
@@ -293,9 +293,9 @@
       Value castBackOp;
       if (srcType.isIndex()) {
         castBackOp =
-            rewriter.create<arith::IndexCastUIOp>(iv.getLoc(), srcType, iv);
+            arith::IndexCastUIOp::create(rewriter, iv.getLoc(), srcType, iv);
       } else {
-        castBackOp = rewriter.create<arith::ExtUIOp>(iv.getLoc(), srcType, iv);
+        castBackOp = arith::ExtUIOp::create(rewriter, iv.getLoc(), srcType, iv);
       }
       (void)solver.getOrCreateState<IntegerValueRangeLattice>(castBackOp)
           ->join(*ivState);
diff --git a/compiler/src/iree/compiler/Dialect/Util/Transforms/Patterns.cpp b/compiler/src/iree/compiler/Dialect/Util/Transforms/Patterns.cpp
index e7c722d..f1b20ae 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Transforms/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Transforms/Patterns.cpp
@@ -334,13 +334,13 @@
                                 PatternRewriter &rewriter) const override {
     if (switchOp.getNumCases() != 1)
       return failure();
-    Value caseValue = rewriter.create<arith::ConstantIndexOp>(
-        switchOp.getLoc(), switchOp.getCases().front());
+    Value caseValue = arith::ConstantIndexOp::create(
+        rewriter, switchOp.getLoc(), switchOp.getCases().front());
     Value isCaseValue = rewriter.createOrFold<arith::CmpIOp>(
         switchOp.getLoc(), arith::CmpIPredicate::eq, switchOp.getArg(),
         caseValue);
-    auto ifOp = rewriter.create<scf::IfOp>(
-        switchOp.getLoc(), switchOp.getResultTypes(), isCaseValue);
+    auto ifOp = scf::IfOp::create(rewriter, switchOp.getLoc(),
+                                  switchOp.getResultTypes(), isCaseValue);
     rewriter.inlineRegionBefore(switchOp.getCaseRegions().front(),
                                 ifOp.getThenRegion(),
                                 ifOp.getThenRegion().begin());
@@ -412,8 +412,8 @@
     SmallVector<Type> newResultTypes;
     llvm::append_range(newResultTypes, prevOp.getResultTypes());
     llvm::append_range(newResultTypes, nextOp.getResultTypes());
-    auto newOp = rewriter.create<scf::IndexSwitchOp>(
-        rewriter.getFusedLoc({prevOp.getLoc(), nextOp.getLoc()}),
+    auto newOp = scf::IndexSwitchOp::create(
+        rewriter, rewriter.getFusedLoc({prevOp.getLoc(), nextOp.getLoc()}),
         newResultTypes, prevOp.getArg(), prevOp.getCases(),
         prevOp.getNumCases());
     SmallVector<std::pair<Value, Value>> resultReplacements;
@@ -470,7 +470,8 @@
       }
 
       // Add the merged yield containing results from both regions.
-      targetBuilder.create<scf::YieldOp>(
+      scf::YieldOp::create(
+          targetBuilder,
           targetBuilder.getFusedLoc(yieldA.getLoc(), yieldB.getLoc()),
           yieldValues);
     };
diff --git a/compiler/src/iree/compiler/Dialect/Util/Transforms/PropagateSubranges.cpp b/compiler/src/iree/compiler/Dialect/Util/Transforms/PropagateSubranges.cpp
index ae8c1f0..29cb421 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Transforms/PropagateSubranges.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Transforms/PropagateSubranges.cpp
@@ -78,24 +78,24 @@
     builder.setInsertionPointAfter(global.resourceOp);
 
     auto sizeName = (global.resourceOp.getName() + "__storage_size").str();
-    auto sizeOp = builder.create<IREE::Util::GlobalOp>(
-        global.resourceOp.getLoc(), sizeName,
+    auto sizeOp = IREE::Util::GlobalOp::create(
+        builder, global.resourceOp.getLoc(), sizeName,
         /*isMutable=*/true, indexType);
     sizeOp.setVisibility(global.resourceOp.getVisibility());
     symbolTable.insert(sizeOp);
     global.resourceSizeOp = sizeOp;
 
     auto offsetName = (global.resourceOp.getName() + "__offset").str();
-    auto offsetOp = builder.create<IREE::Util::GlobalOp>(
-        global.resourceOp.getLoc(), offsetName,
+    auto offsetOp = IREE::Util::GlobalOp::create(
+        builder, global.resourceOp.getLoc(), offsetName,
         /*isMutable=*/true, indexType);
     offsetOp.setVisibility(global.resourceOp.getVisibility());
     symbolTable.insert(offsetOp);
     global.subrangeOffsetOp = offsetOp;
 
     auto lengthName = (global.resourceOp.getName() + "__length").str();
-    auto lengthOp = builder.create<IREE::Util::GlobalOp>(
-        global.resourceOp.getLoc(), lengthName,
+    auto lengthOp = IREE::Util::GlobalOp::create(
+        builder, global.resourceOp.getLoc(), lengthName,
         /*isMutable=*/true, indexType);
     lengthOp.setVisibility(global.resourceOp.getVisibility());
     symbolTable.insert(lengthOp);
@@ -383,17 +383,16 @@
   auto subrange = consumeSubrange(op.getLoc(), op.getStoredGlobalValue(),
                                   subrangeMap, indexSet, builder);
   auto &expandedGlobal = globalMap[op.getGlobalName()];
-  builder.create<IREE::Util::GlobalStoreOp>(
-      op.getLoc(), subrange.resource, expandedGlobal.resourceOp.getName());
-  builder.create<IREE::Util::GlobalStoreOp>(
-      op.getLoc(), subrange.resourceSize,
-      expandedGlobal.resourceSizeOp.getName());
-  builder.create<IREE::Util::GlobalStoreOp>(
-      op.getLoc(), subrange.subrangeOffset,
-      expandedGlobal.subrangeOffsetOp.getName());
-  builder.create<IREE::Util::GlobalStoreOp>(
-      op.getLoc(), subrange.subrangeLength,
-      expandedGlobal.subrangeLengthOp.getName());
+  IREE::Util::GlobalStoreOp::create(builder, op.getLoc(), subrange.resource,
+                                    expandedGlobal.resourceOp.getName());
+  IREE::Util::GlobalStoreOp::create(builder, op.getLoc(), subrange.resourceSize,
+                                    expandedGlobal.resourceSizeOp.getName());
+  IREE::Util::GlobalStoreOp::create(builder, op.getLoc(),
+                                    subrange.subrangeOffset,
+                                    expandedGlobal.subrangeOffsetOp.getName());
+  IREE::Util::GlobalStoreOp::create(builder, op.getLoc(),
+                                    subrange.subrangeLength,
+                                    expandedGlobal.subrangeLengthOp.getName());
   op.erase();
 }
 
@@ -516,7 +515,7 @@
   OpBuilder builder(op);
   auto operands = expandOperands(op.getLoc(), op.getOperands(), subrangeMap,
                                  indexSet, builder);
-  builder.create<IREE::Util::ReturnOp>(op.getLoc(), operands);
+  IREE::Util::ReturnOp::create(builder, op.getLoc(), operands);
   op.erase();
 }
 
@@ -536,7 +535,7 @@
   OpBuilder builder(op);
   auto operands = expandOperands(op.getLoc(), op.getDestOperands(), subrangeMap,
                                  indexSet, builder);
-  builder.create<mlir::cf::BranchOp>(op.getLoc(), op.getDest(), operands);
+  mlir::cf::BranchOp::create(builder, op.getLoc(), op.getDest(), operands);
   op.erase();
 }
 
@@ -545,8 +544,8 @@
   if (!usesResources(op))
     return;
   OpBuilder builder(op);
-  builder.create<mlir::cf::CondBranchOp>(
-      op.getLoc(), op.getCondition(), op.getTrueDest(),
+  mlir::cf::CondBranchOp::create(
+      builder, op.getLoc(), op.getCondition(), op.getTrueDest(),
       expandOperands(op.getLoc(), op.getTrueDestOperands(), subrangeMap,
                      indexSet, builder),
       op.getFalseDest(),
@@ -567,8 +566,8 @@
         return expandOperands(op.getLoc(), operands, subrangeMap, indexSet,
                               builder);
       }));
-  builder.create<mlir::cf::SwitchOp>(
-      op.getLoc(), op.getFlag(), op.getDefaultDestination(),
+  mlir::cf::SwitchOp::create(
+      builder, op.getLoc(), op.getFlag(), op.getDefaultDestination(),
       expandOperands(op.getLoc(), op.getDefaultOperands(), subrangeMap,
                      indexSet, builder),
       op.getCaseValuesAttr(), op.getCaseDestinations(),
diff --git a/compiler/src/iree/compiler/Dialect/Util/Transforms/TestConversion.cpp b/compiler/src/iree/compiler/Dialect/Util/Transforms/TestConversion.cpp
index a02fac6..b22593d 100644
--- a/compiler/src/iree/compiler/Dialect/Util/Transforms/TestConversion.cpp
+++ b/compiler/src/iree/compiler/Dialect/Util/Transforms/TestConversion.cpp
@@ -26,7 +26,7 @@
 
 static Value buildUnrealizedConversionCastOp(OpBuilder &builder, Type toType,
                                              ValueRange inputs, Location loc) {
-  return builder.create<UnrealizedConversionCastOp>(loc, toType, inputs)
+  return UnrealizedConversionCastOp::create(builder, loc, toType, inputs)
       .getResult(0);
 }
 
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/ArithToVM/Patterns.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/ArithToVM/Patterns.cpp
index 4aeba0e..6425846 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/ArithToVM/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/ArithToVM/Patterns.cpp
@@ -537,14 +537,14 @@
       if (dstType.isInteger(32)) {
         rewriter.replaceOpWithNewOp<IREE::VM::SelectI32Op>(
             srcOp, dstType, adaptor.getIn(),
-            rewriter.create<IREE::VM::ConstI32Op>(srcOp.getLoc(), 0xFFFFFFFFu),
-            rewriter.create<IREE::VM::ConstI32ZeroOp>(srcOp.getLoc()));
+            IREE::VM::ConstI32Op::create(rewriter, srcOp.getLoc(), 0xFFFFFFFFu),
+            IREE::VM::ConstI32ZeroOp::create(rewriter, srcOp.getLoc()));
       } else if (dstType.isInteger(64)) {
         rewriter.replaceOpWithNewOp<IREE::VM::SelectI64Op>(
             srcOp, dstType, adaptor.getIn(),
-            rewriter.create<IREE::VM::ConstI64Op>(srcOp.getLoc(),
-                                                  0xFFFFFFFFFFFFFFFFull),
-            rewriter.create<IREE::VM::ConstI64ZeroOp>(srcOp.getLoc()));
+            IREE::VM::ConstI64Op::create(rewriter, srcOp.getLoc(),
+                                         0xFFFFFFFFFFFFFFFFull),
+            IREE::VM::ConstI64ZeroOp::create(rewriter, srcOp.getLoc()));
       } else {
         return rewriter.notifyMatchFailure(srcOp,
                                            "unsupported i1 sign extension");
@@ -672,8 +672,9 @@
     }
 
     if (srcType.getIntOrFloatBitWidth() < 32) {
-      input = rewriter.create<arith::ExtSIOp>(
-          srcOp.getLoc(), IntegerType::get(this->getContext(), 32), input);
+      input = arith::ExtSIOp::create(rewriter, srcOp.getLoc(),
+                                     IntegerType::get(this->getContext(), 32),
+                                     input);
     }
 
     rewriter.replaceOpWithNewOp<IREE::VM::CastSI32F32Op>(srcOp, resultType,
@@ -719,8 +720,9 @@
     }
 
     if (srcType.getIntOrFloatBitWidth() < 32) {
-      input = rewriter.create<arith::ExtUIOp>(
-          srcOp.getLoc(), IntegerType::get(this->getContext(), 32), input);
+      input = arith::ExtUIOp::create(rewriter, srcOp.getLoc(),
+                                     IntegerType::get(this->getContext(), 32),
+                                     input);
     }
 
     rewriter.replaceOpWithNewOp<IREE::VM::CastUI32F32Op>(srcOp, resultType,
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.cpp
index 32cf8b2..aad682d 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/ImportUtils.cpp
@@ -119,26 +119,26 @@
   if (llvm::isa<FloatType>(sourceType) && llvm::isa<IntegerType>(targetType) &&
       sourceType.getIntOrFloatBitWidth() ==
           targetType.getIntOrFloatBitWidth()) {
-    return builder.create<mlir::arith::BitcastOp>(value.getLoc(), targetType,
-                                                  value);
+    return mlir::arith::BitcastOp::create(builder, value.getLoc(), targetType,
+                                          value);
   } else if (sourceIsInteger &&
              (targetType.isSignedInteger() || targetType.isSignlessInteger())) {
     if (targetType.getIntOrFloatBitWidth() >
         sourceType.getIntOrFloatBitWidth()) {
-      return builder.create<mlir::arith::ExtSIOp>(value.getLoc(), targetType,
-                                                  value);
+      return mlir::arith::ExtSIOp::create(builder, value.getLoc(), targetType,
+                                          value);
     } else {
-      return builder.create<mlir::arith::TruncIOp>(value.getLoc(), targetType,
-                                                   value);
+      return mlir::arith::TruncIOp::create(builder, value.getLoc(), targetType,
+                                           value);
     }
   } else if (sourceIsInteger && targetType.isUnsignedInteger()) {
     if (targetType.getIntOrFloatBitWidth() >
         sourceType.getIntOrFloatBitWidth()) {
-      return builder.create<mlir::arith::ExtUIOp>(value.getLoc(), targetType,
-                                                  value);
+      return mlir::arith::ExtUIOp::create(builder, value.getLoc(), targetType,
+                                          value);
     } else {
-      return builder.create<mlir::arith::TruncIOp>(value.getLoc(), targetType,
-                                                   value);
+      return mlir::arith::TruncIOp::create(builder, value.getLoc(), targetType,
+                                           value);
     }
   } else {
     return value;
@@ -175,8 +175,8 @@
     // conversions can do their job. If we want to remove the dependency
     // from standard ops in the future we could instead go directly to
     // one of the vm constant ops.
-    auto constValue = builder.create<mlir::arith::ConstantOp>(
-        loc, inputType,
+    auto constValue = mlir::arith::ConstantOp::create(
+        builder, loc, inputType,
         IntegerAttr::get(inputType, APInt(inputType.getIntOrFloatBitWidth(),
                                           intAttr.getValue().getSExtValue())));
     return {{constValue}};
@@ -185,16 +185,16 @@
     APFloat value = floatAttr.getValue();
     value.convert(llvm::cast<FloatType>(inputType).getFloatSemantics(),
                   llvm::RoundingMode::NearestTiesToEven, &lossy);
-    auto constValue = builder.create<mlir::arith::ConstantOp>(
-        loc, inputType, FloatAttr::get(inputType, value));
+    auto constValue = mlir::arith::ConstantOp::create(
+        builder, loc, inputType, FloatAttr::get(inputType, value));
     return {{constValue}};
   } else if (auto elementsAttr =
                  llvm::dyn_cast<DenseIntElementsAttr>(attrValue)) {
     SmallVector<Value> elementValues;
     elementValues.reserve(elementsAttr.getNumElements());
     for (auto intAttr : elementsAttr.getValues<Attribute>()) {
-      elementValues.push_back(builder.create<mlir::arith::ConstantOp>(
-          loc, elementsAttr.getType().getElementType(),
+      elementValues.push_back(mlir::arith::ConstantOp::create(
+          builder, loc, elementsAttr.getType().getElementType(),
           cast<TypedAttr>(intAttr)));
     }
     return elementValues;
@@ -209,7 +209,7 @@
     }
     return allValues;
   } else if (auto strAttr = llvm::dyn_cast<StringAttr>(attrValue)) {
-    return {{builder.create<IREE::VM::RodataInlineOp>(loc, strAttr)}};
+    return {{IREE::VM::RodataInlineOp::create(builder, loc, strAttr)}};
   }
 
   // This may be a custom dialect type. As we can't trivially access the storage
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/StandardToVM/Patterns.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/StandardToVM/Patterns.cpp
index 91e4bdf..01da5c4 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/StandardToVM/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/StandardToVM/Patterns.cpp
@@ -38,7 +38,7 @@
 
     StringRef name = srcOp.getName() ? *srcOp.getName() : "module";
     auto newModuleOp =
-        rewriter.create<IREE::VM::ModuleOp>(srcOp.getLoc(), name);
+        IREE::VM::ModuleOp::create(rewriter, srcOp.getLoc(), name);
     assert(!newModuleOp.getBodyRegion().empty());
     if (auto version = srcOp->getAttrOfType<IntegerAttr>("vm.version")) {
       newModuleOp.setVersionAttr(version);
@@ -57,7 +57,7 @@
     rewriter.eraseOp(srcOp);
     OpBuilder::InsertionGuard g(rewriter);
     rewriter.setInsertionPointToEnd(&newModuleOp.getBodyRegion().front());
-    rewriter.create<IREE::VM::ModuleTerminatorOp>(srcOp.getLoc());
+    IREE::VM::ModuleTerminatorOp::create(rewriter, srcOp.getLoc());
     return success();
   }
 };
@@ -128,8 +128,8 @@
 
     // Create new function with converted argument and result types.
     // Note that attributes are dropped. Consider preserving some if needed.
-    auto newFuncOp = rewriter.create<IREE::VM::FuncOp>(
-        srcOp.getLoc(), srcOp.getName(), *newFuncType);
+    auto newFuncOp = IREE::VM::FuncOp::create(rewriter, srcOp.getLoc(),
+                                              srcOp.getName(), *newFuncType);
     rewriter.inlineRegionBefore(srcOp.getBody(), newFuncOp.getFunctionBody(),
                                 newFuncOp.end());
 
@@ -149,8 +149,8 @@
     // materialize high level API-friendly wrappers.
     if (srcOp.isPublic()) {
       StringRef exportName = newFuncOp.getName();
-      auto exportOp = rewriter.create<IREE::VM::ExportOp>(
-          srcOp.getLoc(), newFuncOp, exportName);
+      auto exportOp = IREE::VM::ExportOp::create(rewriter, srcOp.getLoc(),
+                                                 newFuncOp, exportName);
       exportOp->setDialectAttrs(srcOp->getDialectAttrs());
     }
 
@@ -217,8 +217,8 @@
 
     // Create new function with converted argument and result types.
     // Note that attributes are dropped. Consider preserving some if needed.
-    auto importOp = rewriter.create<IREE::VM::ImportOp>(
-        srcOp.getLoc(), srcOp.getName(), newSignature);
+    auto importOp = IREE::VM::ImportOp::create(rewriter, srcOp.getLoc(),
+                                               srcOp.getName(), newSignature);
     importOp.setSymVisibilityAttr(srcOp.getSymVisibilityAttr());
 
     // If there is a fallback then the import is optional.
@@ -291,8 +291,8 @@
     }
 
     // Otherwise this is a direct call to an internal function.
-    auto newOp = rewriter.create<IREE::VM::CallOp>(loc, calleeName, resultTypes,
-                                                   operands);
+    auto newOp = IREE::VM::CallOp::create(rewriter, loc, calleeName,
+                                          resultTypes, operands);
     return llvm::to_vector_of<Value>(newOp->getResults());
   }
 
@@ -323,8 +323,8 @@
       StringRef fallbackName, ConversionPatternRewriter &rewriter) const {
     // Check whether the import resolved and if so call it. Otherwise we call
     // the fallback which should not require any conversion.
-    Value resolved = rewriter.create<IREE::VM::ImportResolvedOp>(
-        loc, rewriter.getI32Type(), calleeName);
+    Value resolved = IREE::VM::ImportResolvedOp::create(
+        rewriter, loc, rewriter.getI32Type(), calleeName);
 
     // We'll be making the call via two blocks and then joining again on a block
     // that takes the results in target form.
@@ -340,16 +340,15 @@
 
     // Insert the branch to each block.
     rewriter.setInsertionPointAfterValue(resolved);
-    rewriter.create<IREE::VM::CondBranchOp>(loc, resolved, resolvedBlock,
-                                            ValueRange{}, fallbackBlock,
-                                            ValueRange{});
+    IREE::VM::CondBranchOp::create(rewriter, loc, resolved, resolvedBlock,
+                                   ValueRange{}, fallbackBlock, ValueRange{});
 
     // Resolved: make call to the import as normal.
     rewriter.setInsertionPointToStart(resolvedBlock);
     auto importResults =
         convertMandatoryImportCallOp(rootOp, loc, calleeName, operands,
                                      resultTypes, importSignature, rewriter);
-    rewriter.create<IREE::VM::BranchOp>(loc, exitBlock, importResults);
+    IREE::VM::BranchOp::create(rewriter, loc, exitBlock, importResults);
 
     // Not resolved: call fallback as a normal function.
     rewriter.setInsertionPointToStart(fallbackBlock);
@@ -357,7 +356,7 @@
                                          resultTypes, importTable, rewriter);
     if (failed(fallbackResults))
       return failure();
-    rewriter.create<IREE::VM::BranchOp>(loc, exitBlock, *fallbackResults);
+    IREE::VM::BranchOp::create(rewriter, loc, exitBlock, *fallbackResults);
 
     return exitResults;
   }
@@ -378,8 +377,8 @@
     }
 
     // Direct call to mandatory import.
-    auto newOp = rewriter.create<IREE::VM::CallOp>(
-        loc, calleeName, importSignature.getResults(), importArgs);
+    auto newOp = IREE::VM::CallOp::create(
+        rewriter, loc, calleeName, importSignature.getResults(), importArgs);
 
     // Marshal results from import types.
     SmallVector<Value> callResults;
@@ -419,8 +418,8 @@
   LogicalResult
   matchAndRewrite(cf::AssertOp srcOp, OpAdaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
-    auto status = rewriter.create<IREE::VM::ConstI32Op>(
-        srcOp.getLoc(),
+    auto status = IREE::VM::ConstI32Op::create(
+        rewriter, srcOp.getLoc(),
         rewriter.getIntegerAttr(
             rewriter.getIntegerType(32),
             static_cast<int32_t>(IREE::Util::StatusCode::FailedPrecondition)));
@@ -500,10 +499,10 @@
     // avoid holes at the start of the table.
     Value index = adaptor.getFlag();
     if (minValue > 0) {
-      index = rewriter.create<IREE::VM::SubI32Op>(
-          srcOp.getLoc(), rewriter.getI32Type(), index,
-          rewriter.create<IREE::VM::ConstI32Op>(
-              srcOp.getLoc(), static_cast<int32_t>(minValue)));
+      index = IREE::VM::SubI32Op::create(
+          rewriter, srcOp.getLoc(), rewriter.getI32Type(), index,
+          IREE::VM::ConstI32Op::create(rewriter, srcOp.getLoc(),
+                                       static_cast<int32_t>(minValue)));
       for (auto &[i, value] : caseValues) {
         value -= minValue;
       }
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp
index ed634da..b1c14fc 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/TypeConverter.cpp
@@ -109,7 +109,7 @@
         !llvm::isa<IntegerType>(inputs.front().getType())) {
       return nullptr;
     }
-    return builder.create<arith::IndexCastOp>(loc, type, inputs.front());
+    return arith::IndexCastOp::create(builder, loc, type, inputs.front());
   });
 
   addTargetMaterialization(
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertBufferOps.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertBufferOps.cpp
index 75ced6b..2dfab56 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertBufferOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertBufferOps.cpp
@@ -58,7 +58,7 @@
       alignment.has_value()
           ? static_cast<int32_t>(alignment.value().getZExtValue())
           : 0;
-  return builder.create<IREE::VM::ConstI32Op>(loc, alignmentValue);
+  return IREE::VM::ConstI32Op::create(builder, loc, alignmentValue);
 }
 
 struct BufferAllocOpConversion
@@ -101,12 +101,12 @@
     auto resultType =
         getTypeConverter()->convertType(sliceOp.getResult().getType());
     auto sliceLength = castToI64(adaptor.getResultSize(), rewriter);
-    Value newBuffer = rewriter.create<IREE::VM::BufferAllocOp>(
-        sliceOp.getLoc(), resultType, sliceLength,
+    Value newBuffer = IREE::VM::BufferAllocOp::create(
+        rewriter, sliceOp.getLoc(), resultType, sliceLength,
         getAlignment(sliceOp.getLoc(), adaptor.getAlignment(), rewriter));
-    Value zero = rewriter.create<IREE::VM::ConstI64ZeroOp>(sliceOp.getLoc());
-    rewriter.create<IREE::VM::BufferCopyOp>(
-        sliceOp.getLoc(), adaptor.getSource(),
+    Value zero = IREE::VM::ConstI64ZeroOp::create(rewriter, sliceOp.getLoc());
+    IREE::VM::BufferCopyOp::create(
+        rewriter, sliceOp.getLoc(), adaptor.getSource(),
         castToI64(adaptor.getSourceOffset(), rewriter), newBuffer, zero,
         sliceLength);
     rewriter.replaceOp(sliceOp, newBuffer);
@@ -120,8 +120,8 @@
   LogicalResult
   matchAndRewrite(IREE::Util::BufferSizeOp sizeOp, OpAdaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
-    Value size = rewriter.create<IREE::VM::BufferLengthOp>(
-        sizeOp.getLoc(), rewriter.getI64Type(), adaptor.getOperand());
+    Value size = IREE::VM::BufferLengthOp::create(
+        rewriter, sizeOp.getLoc(), rewriter.getI64Type(), adaptor.getOperand());
     rewriter.replaceOp(sizeOp, castToIndex(size, rewriter));
     return success();
   }
@@ -165,7 +165,7 @@
     return offset;
   return builder.createOrFold<IREE::VM::DivI64SOp>(
       loc, offset.getType(), offset,
-      builder.create<IREE::VM::ConstI64Op>(loc, scale));
+      IREE::VM::ConstI64Op::create(builder, loc, scale));
 }
 
 struct BufferFillOpConversion
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 39dc7c0..fbec03d 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertGlobalOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertGlobalOps.cpp
@@ -20,7 +20,7 @@
   LogicalResult
   matchAndRewrite(IREE::Util::InitializerOp op, OpAdaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
-    auto newOp = rewriter.create<IREE::VM::InitializerOp>(op.getLoc());
+    auto newOp = IREE::VM::InitializerOp::create(rewriter, op.getLoc());
     rewriter.cloneRegionBefore(op.getBody(), newOp.getBody(),
                                newOp.getBody().begin());
 
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 ac75982..f6a4b7b 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertListOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertListOps.cpp
@@ -43,8 +43,8 @@
     if (initialCapacity) {
       initialCapacity = castToI32(initialCapacity, rewriter);
     } else {
-      initialCapacity = rewriter.create<IREE::VM::ConstI32Op>(
-          srcOp.getLoc(), rewriter.getI32IntegerAttr(0));
+      initialCapacity = IREE::VM::ConstI32Op::create(
+          rewriter, srcOp.getLoc(), rewriter.getI32IntegerAttr(0));
     }
     rewriter.replaceOpWithNewOp<IREE::VM::ListAllocOp>(
         srcOp, typeConverter->convertType(srcOp.getResult().getType()),
@@ -59,8 +59,8 @@
   LogicalResult
   matchAndRewrite(IREE::Util::ListSizeOp srcOp, OpAdaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
-    Value size = rewriter.create<IREE::VM::ListSizeOp>(
-        srcOp.getLoc(), rewriter.getI32Type(), adaptor.getList());
+    Value size = IREE::VM::ListSizeOp::create(
+        rewriter, srcOp.getLoc(), rewriter.getI32Type(), adaptor.getList());
     rewriter.replaceOp(srcOp, castToIndex(size, rewriter));
     return success();
   }
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertStructuralOps.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertStructuralOps.cpp
index 30ead91..083f058 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertStructuralOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertStructuralOps.cpp
@@ -22,7 +22,7 @@
   LogicalResult
   matchAndRewrite(IREE::Util::InitializerOp op, OpAdaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
-    auto newOp = rewriter.create<IREE::VM::InitializerOp>(op.getLoc());
+    auto newOp = IREE::VM::InitializerOp::create(rewriter, op.getLoc());
     rewriter.cloneRegionBefore(op.getBody(), newOp.getBody(),
                                newOp.getBody().begin());
 
@@ -103,8 +103,8 @@
 
     // Create new function with converted argument and result types.
     // Note that attributes are dropped. Consider preserving some if needed.
-    auto newFuncOp = rewriter.create<IREE::VM::FuncOp>(
-        srcOp.getLoc(), srcOp.getName(), *newFuncType);
+    auto newFuncOp = IREE::VM::FuncOp::create(rewriter, srcOp.getLoc(),
+                                              srcOp.getName(), *newFuncType);
     rewriter.inlineRegionBefore(srcOp.getBody(), newFuncOp.getFunctionBody(),
                                 newFuncOp.end());
 
@@ -124,8 +124,8 @@
     // materialize high level API-friendly wrappers.
     if (srcOp.isPublic()) {
       StringRef exportName = newFuncOp.getName();
-      auto exportOp = rewriter.create<IREE::VM::ExportOp>(
-          srcOp.getLoc(), newFuncOp, exportName);
+      auto exportOp = IREE::VM::ExportOp::create(rewriter, srcOp.getLoc(),
+                                                 newFuncOp, exportName);
       exportOp->setDialectAttrs(srcOp->getDialectAttrs());
     }
 
@@ -194,8 +194,8 @@
 
     // Create new function with converted argument and result types.
     // Note that attributes are dropped. Consider preserving some if needed.
-    auto importOp = rewriter.create<IREE::VM::ImportOp>(
-        srcOp.getLoc(), srcOp.getName(), newSignature);
+    auto importOp = IREE::VM::ImportOp::create(rewriter, srcOp.getLoc(),
+                                               srcOp.getName(), newSignature);
     importOp.setSymVisibilityAttr(srcOp.getSymVisibilityAttr());
 
     // If there is a fallback then the import is optional.
@@ -266,8 +266,8 @@
     }
 
     // Otherwise this is a direct call to an internal function.
-    auto newOp = rewriter.create<IREE::VM::CallOp>(loc, calleeName, resultTypes,
-                                                   operands);
+    auto newOp = IREE::VM::CallOp::create(rewriter, loc, calleeName,
+                                          resultTypes, operands);
     return llvm::to_vector_of<Value>(newOp.getResults());
   }
 
@@ -298,8 +298,8 @@
       StringRef fallbackName, ConversionPatternRewriter &rewriter) const {
     // Check whether the import resolved and if so call it. Otherwise we call
     // the fallback which should not require any conversion.
-    Value resolved = rewriter.create<IREE::VM::ImportResolvedOp>(
-        loc, rewriter.getI32Type(), calleeName);
+    Value resolved = IREE::VM::ImportResolvedOp::create(
+        rewriter, loc, rewriter.getI32Type(), calleeName);
 
     // We'll be making the call via two blocks and then joining again on a block
     // that takes the results in target form.
@@ -315,16 +315,15 @@
 
     // Insert the branch to each block.
     rewriter.setInsertionPointAfterValue(resolved);
-    rewriter.create<IREE::VM::CondBranchOp>(loc, resolved, resolvedBlock,
-                                            ValueRange{}, fallbackBlock,
-                                            ValueRange{});
+    IREE::VM::CondBranchOp::create(rewriter, loc, resolved, resolvedBlock,
+                                   ValueRange{}, fallbackBlock, ValueRange{});
 
     // Resolved: make call to the import as normal.
     rewriter.setInsertionPointToStart(resolvedBlock);
     auto importResults =
         convertMandatoryImportCallOp(rootOp, loc, calleeName, operands,
                                      resultTypes, importSignature, rewriter);
-    rewriter.create<IREE::VM::BranchOp>(loc, exitBlock, importResults);
+    IREE::VM::BranchOp::create(rewriter, loc, exitBlock, importResults);
 
     // Not resolved: call fallback as a normal function.
     rewriter.setInsertionPointToStart(fallbackBlock);
@@ -332,7 +331,7 @@
                                          resultTypes, rewriter);
     if (failed(fallbackResults))
       return failure();
-    rewriter.create<IREE::VM::BranchOp>(loc, exitBlock, *fallbackResults);
+    IREE::VM::BranchOp::create(rewriter, loc, exitBlock, *fallbackResults);
 
     return exitResults;
   }
@@ -353,8 +352,8 @@
     }
 
     // Direct call to mandatory import.
-    auto newOp = rewriter.create<IREE::VM::CallOp>(
-        loc, calleeName, importSignature.getResults(), importArgs);
+    auto newOp = IREE::VM::CallOp::create(
+        rewriter, loc, calleeName, importSignature.getResults(), importArgs);
 
     // Marshal results from import types.
     SmallVector<Value> callResults;
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 755a94e..58ef6ff 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp
@@ -87,7 +87,7 @@
   auto newFuncType = mlir::FunctionType::get(
       ctx, {inputTypes}, {emitc::OpaqueType::get(ctx, "iree_status_t")});
 
-  auto newFuncOp = builder.create<mlir::emitc::FuncOp>(loc, name, newFuncType);
+  auto newFuncOp = mlir::emitc::FuncOp::create(builder, loc, name, newFuncType);
   newFuncOp.setSpecifiersAttr(
       builder.getArrayAttr({builder.getStringAttr("static")}));
   newFuncOp.setPrivate();
@@ -271,11 +271,11 @@
         builder, location, emitc::OpaqueType::get(ctx, "iree_vm_ref_t"));
 
     StringRef callee = isMove ? "iree_vm_ref_move" : "iree_vm_ref_retain";
-    builder.create<emitc::CallOpaqueOp>(
-        /*location=*/location,
-        /*type=*/TypeRange{},
-        /*callee=*/callee,
-        /*operands=*/ArrayRef<Value>{srcRef, tmpPtr});
+    emitc::CallOpaqueOp::create(builder,
+                                /*location=*/location,
+                                /*type=*/TypeRange{},
+                                /*callee=*/callee,
+                                /*operands=*/ArrayRef<Value>{srcRef, tmpPtr});
 
     tmpMapping.map(srcRef, tmpPtr);
   }
@@ -285,11 +285,11 @@
 
     StringRef callee = isMove ? "iree_vm_ref_move" : "iree_vm_ref_assign";
 
-    builder.create<emitc::CallOpaqueOp>(
-        /*location=*/location,
-        /*type=*/TypeRange{},
-        /*callee=*/callee,
-        /*operands=*/ArrayRef<Value>{tmpRef, destRef});
+    emitc::CallOpaqueOp::create(builder,
+                                /*location=*/location,
+                                /*type=*/TypeRange{},
+                                /*callee=*/callee,
+                                /*operands=*/ArrayRef<Value>{tmpRef, destRef});
   }
 
   return success();
@@ -333,19 +333,19 @@
     ArrayAttr args, ArrayRef<Value> operands,
     const std::function<void(emitc::CallOpaqueOp &)> &failureBlockBuilder,
     bool negateCondition = false) {
-  auto callOp = builder.create<emitc::CallOpaqueOp>(
-      /*location=*/location,
-      /*type=*/type,
-      /*callee=*/callee,
-      /*operands=*/operands,
-      /*args=*/args);
+  auto callOp = emitc::CallOpaqueOp::create(builder,
+                                            /*location=*/location,
+                                            /*type=*/type,
+                                            /*callee=*/callee,
+                                            /*operands=*/operands,
+                                            /*args=*/args);
 
   Type boolType = builder.getIntegerType(1);
 
-  auto conditionI1 = builder.create<emitc::CastOp>(
-      /*location=*/location,
-      /*type=*/boolType,
-      /*operand=*/callOp.getResult(0));
+  auto conditionI1 = emitc::CastOp::create(builder,
+                                           /*location=*/location,
+                                           /*type=*/boolType,
+                                           /*operand=*/callOp.getResult(0));
 
   // Start by splitting the block into two. The part before will contain the
   // condition, and the part after will contain the continuation point.
@@ -364,8 +364,8 @@
   }
 
   builder.setInsertionPointToEnd(condBlock);
-  builder.create<mlir::cf::CondBranchOp>(
-      location, conditionI1.getResult(),
+  mlir::cf::CondBranchOp::create(
+      builder, location, conditionI1.getResult(),
       negateCondition ? failureBlock : continuationBlock,
       negateCondition ? continuationBlock : failureBlock);
 
@@ -386,7 +386,7 @@
 
     releaseRefs(builder, location, funcOp, moduleAnalysis);
 
-    builder.create<mlir::emitc::ReturnOp>(location, callOp.getResult(0));
+    mlir::emitc::ReturnOp::create(builder, location, callOp.getResult(0));
   };
 
   auto ctx = builder.getContext();
@@ -409,7 +409,8 @@
 
     releaseRefs(builder, location, funcOp, moduleAnalysis);
 
-    auto statusOp = builder.create<emitc::CallOpaqueOp>(
+    auto statusOp = emitc::CallOpaqueOp::create(
+        builder,
         /*location=*/location,
         /*type=*/emitc::OpaqueType::get(ctx, "iree_status_t"),
         /*callee=*/"iree_make_status",
@@ -418,7 +419,7 @@
         ArrayAttr::get(ctx, {emitc::OpaqueAttr::get(
                                 ctx, "IREE_STATUS_INVALID_ARGUMENT")}));
 
-    builder.create<mlir::emitc::ReturnOp>(location, statusOp.getResult(0));
+    mlir::emitc::ReturnOp::create(builder, location, statusOp.getResult(0));
   };
 
   return failableCall(builder, location, type, callee, args, operands,
@@ -434,17 +435,17 @@
     ArrayRef<Value> operands,
     const std::function<void(mlir::emitc::CallOp &)> &failureBlockBuilder,
     bool negateCondition = false) {
-  auto callOp = builder.create<mlir::emitc::CallOp>(
-      /*location=*/location,
-      /*callee=*/callee,
-      /*operands=*/operands);
+  auto callOp = mlir::emitc::CallOp::create(builder,
+                                            /*location=*/location,
+                                            /*callee=*/callee,
+                                            /*operands=*/operands);
 
   Type boolType = builder.getIntegerType(1);
 
-  auto conditionI1 = builder.create<emitc::CastOp>(
-      /*location=*/location,
-      /*type=*/boolType,
-      /*operand=*/callOp.getResult(0));
+  auto conditionI1 = emitc::CastOp::create(builder,
+                                           /*location=*/location,
+                                           /*type=*/boolType,
+                                           /*operand=*/callOp.getResult(0));
 
   // Start by splitting the block into two. The part before will contain the
   // condition, and the part after will contain the continuation point.
@@ -463,8 +464,8 @@
   }
 
   builder.setInsertionPointToEnd(condBlock);
-  builder.create<mlir::cf::CondBranchOp>(
-      location, conditionI1.getResult(),
+  mlir::cf::CondBranchOp::create(
+      builder, location, conditionI1.getResult(),
       negateCondition ? failureBlock : continuationBlock,
       negateCondition ? continuationBlock : failureBlock);
 
@@ -485,7 +486,7 @@
 
     releaseRefs(builder, location, funcOp, moduleAnalysis);
 
-    builder.create<mlir::emitc::ReturnOp>(location, callOp.getResult(0));
+    mlir::emitc::ReturnOp::create(builder, location, callOp.getResult(0));
   };
 
   return failableCall(builder, location, callee, operands, blockBuilder,
@@ -512,8 +513,8 @@
         ctx, {emitc::PointerType::get(emitc::OpaqueType::get(ctx, "void"))},
         {});
 
-    auto funcOp = builder.create<mlir::emitc::FuncOp>(
-        loc, moduleName + "_destroy", funcType);
+    auto funcOp = mlir::emitc::FuncOp::create(
+        builder, loc, moduleName + "_destroy", funcType);
     funcOp.setSpecifiersAttr(
         builder.getArrayAttr({builder.getStringAttr("static")}));
     funcOp.setPrivate();
@@ -527,7 +528,8 @@
 
     std::string moduleTypeName = std::string("struct ") + moduleName + "_t";
 
-    auto castedModuleOp = builder.create<emitc::CastOp>(
+    auto castedModuleOp = emitc::CastOp::create(
+        builder,
         /*location=*/loc,
         /*type=*/
         emitc::PointerType::get(emitc::OpaqueType::get(ctx, moduleTypeName)),
@@ -542,14 +544,15 @@
         /*memberName=*/"allocator",
         /*operand=*/castedModuleOpLValue);
 
-    builder.create<emitc::CallOpaqueOp>(
+    emitc::CallOpaqueOp::create(
+        builder,
         /*location=*/loc,
         /*type=*/TypeRange{},
         /*callee=*/"iree_allocator_free",
         /*operands=*/
         ArrayRef<Value>{allocatorOp, castedModuleOp.getResult()});
 
-    builder.create<mlir::emitc::ReturnOp>(loc, nullptr);
+    mlir::emitc::ReturnOp::create(builder, loc, nullptr);
   }
 
   // iree_status_t alloc_state(void*, iree_allocator_t,
@@ -568,8 +571,8 @@
              emitc::OpaqueType::get(ctx, "iree_vm_module_state_t")))},
         {emitc::OpaqueType::get(ctx, "iree_status_t")});
 
-    auto funcOp = builder.create<mlir::emitc::FuncOp>(
-        loc, moduleName + "_alloc_state", funcType);
+    auto funcOp = mlir::emitc::FuncOp::create(
+        builder, loc, moduleName + "_alloc_state", funcType);
     funcOp.setSpecifiersAttr(
         builder.getArrayAttr({builder.getStringAttr("static")}));
     funcOp.setPrivate();
@@ -598,12 +601,13 @@
 
     Value statePtr = emitc_builders::addressOf(builder, loc, state);
 
-    auto voidPtr = builder.create<emitc::CastOp>(
-        /*location=*/loc,
-        /*type=*/
-        emitc::PointerType::get(
-            emitc::PointerType::get(emitc::OpaqueType::get(ctx, "void"))),
-        /*operand=*/statePtr);
+    auto voidPtr =
+        emitc::CastOp::create(builder,
+                              /*location=*/loc,
+                              /*type=*/
+                              emitc::PointerType::get(emitc::PointerType::get(
+                                  emitc::OpaqueType::get(ctx, "void"))),
+                              /*operand=*/statePtr);
 
     returnIfError(builder, loc, "iree_allocator_malloc", {},
                   {allocatorArg, stateSize, voidPtr.getResult()},
@@ -631,7 +635,8 @@
       auto rodataPointerRValue =
           emitc_builders::asRValue(builder, loc, rodataPointer);
 
-      auto bufferVoid = builder.create<emitc::CastOp>(
+      auto bufferVoid = emitc::CastOp::create(
+          builder,
           /*location=*/loc,
           /*type=*/emitc::PointerType::get(emitc::OpaqueType::get(ctx, "void")),
           /*operand=*/rodataPointerRValue);
@@ -639,13 +644,15 @@
       Value bufferSize = emitc_builders::sizeOf(
           builder, loc, emitc::OpaqueAttr::get(ctx, bufferName));
 
-      auto byteSpan = builder.create<emitc::CallOpaqueOp>(
+      auto byteSpan = emitc::CallOpaqueOp::create(
+          builder,
           /*location=*/loc,
           /*type=*/emitc::OpaqueType::get(ctx, "iree_byte_span_t"),
           /*callee=*/"iree_make_byte_span",
           /*operands=*/ArrayRef<Value>{bufferVoid.getResult(), bufferSize});
 
-      auto allocator = builder.create<emitc::CallOpaqueOp>(
+      auto allocator = emitc::CallOpaqueOp::create(
+          builder,
           /*location=*/loc,
           /*type=*/emitc::OpaqueType::get(ctx, "iree_allocator_t"),
           /*callee=*/"iree_allocator_null",
@@ -661,7 +668,8 @@
       auto buffer = emitc_builders::arrayElementAddress(
           builder, loc, /*index=*/ordinal, /*operand=*/buffers);
 
-      builder.create<emitc::CallOpaqueOp>(
+      emitc::CallOpaqueOp::create(
+          builder,
           /*location=*/loc,
           /*type=*/TypeRange{},
           /*callee=*/"iree_vm_buffer_initialize",
@@ -675,14 +683,16 @@
                                builder.getIndexAttr(2)}));
     }
 
-    auto baseStateOp = builder.create<emitc::CastOp>(
-        /*location=*/loc,
-        /*type=*/
-        emitc::PointerType::get(
-            emitc::OpaqueType::get(ctx, "iree_vm_module_state_t")),
-        /*operand=*/stateRValue);
+    auto baseStateOp =
+        emitc::CastOp::create(builder,
+                              /*location=*/loc,
+                              /*type=*/
+                              emitc::PointerType::get(emitc::OpaqueType::get(
+                                  ctx, "iree_vm_module_state_t")),
+                              /*operand=*/stateRValue);
 
-    builder.create<emitc::CallOpaqueOp>(
+    emitc::CallOpaqueOp::create(
+        builder,
         /*location=*/loc,
         /*type=*/TypeRange{},
         /*callee=*/"EMITC_DEREF_ASSIGN_VALUE",
@@ -690,7 +700,7 @@
 
     auto status = emitc_builders::ireeOkStatus(builder, loc);
 
-    builder.create<mlir::emitc::ReturnOp>(loc, status);
+    mlir::emitc::ReturnOp::create(builder, loc, status);
   }
 
   // void free_state(void*, iree_vm_module_state_t*)
@@ -706,8 +716,8 @@
              emitc::OpaqueType::get(ctx, "iree_vm_module_state_t"))},
         {});
 
-    auto funcOp = builder.create<mlir::emitc::FuncOp>(
-        loc, moduleName + "_free_state", funcType);
+    auto funcOp = mlir::emitc::FuncOp::create(
+        builder, loc, moduleName + "_free_state", funcType);
     funcOp.setSpecifiersAttr(
         builder.getArrayAttr({builder.getStringAttr("static")}));
     funcOp.setPrivate();
@@ -724,12 +734,13 @@
     std::string moduleStateTypeName =
         std::string("struct ") + moduleName + "_state_t";
 
-    auto stateOp = builder.create<emitc::CastOp>(
-        /*location=*/loc,
-        /*type=*/
-        emitc::PointerType::get(
-            emitc::OpaqueType::get(ctx, moduleStateTypeName)),
-        /*operand=*/moduleStateArg);
+    auto stateOp =
+        emitc::CastOp::create(builder,
+                              /*location=*/loc,
+                              /*type=*/
+                              emitc::PointerType::get(emitc::OpaqueType::get(
+                                  ctx, moduleStateTypeName)),
+                              /*operand=*/moduleStateArg);
 
     auto stateOpLValue =
         emitc_builders::asLValue(builder, loc, stateOp.getResult());
@@ -766,13 +777,14 @@
         /*memberName=*/"allocator",
         /*operand=*/stateOpLValue);
 
-    builder.create<emitc::CallOpaqueOp>(
+    emitc::CallOpaqueOp::create(
+        builder,
         /*location=*/loc,
         /*type=*/TypeRange{},
         /*callee=*/"iree_allocator_free",
         /*operands=*/ArrayRef<Value>{allocatorOp, stateOp.getResult()});
 
-    builder.create<mlir::emitc::ReturnOp>(loc, nullptr);
+    mlir::emitc::ReturnOp::create(builder, loc, nullptr);
   }
 
   // iree_status_t fork_state(
@@ -798,8 +810,8 @@
              emitc::OpaqueType::get(ctx, "iree_vm_module_state_t")))},
         {emitc::OpaqueType::get(ctx, "iree_status_t")});
 
-    auto funcOp = builder.create<mlir::emitc::FuncOp>(
-        loc, moduleName + "_fork_state", funcType);
+    auto funcOp = mlir::emitc::FuncOp::create(
+        builder, loc, moduleName + "_fork_state", funcType);
     funcOp.setSpecifiersAttr(
         builder.getArrayAttr({builder.getStringAttr("static")}));
     funcOp.setPrivate();
@@ -812,7 +824,8 @@
 
     // TODO: someone will need to do what the bytecode module does in order to
     // support forking. For now we don't support forking emitc contexts.
-    auto statusOp = builder.create<emitc::CallOpaqueOp>(
+    auto statusOp = emitc::CallOpaqueOp::create(
+        builder,
         /*location=*/loc,
         /*type=*/emitc::OpaqueType::get(ctx, "iree_status_t"),
         /*callee=*/"iree_make_status",
@@ -821,7 +834,7 @@
         ArrayAttr::get(
             ctx, {emitc::OpaqueAttr::get(ctx, "IREE_STATUS_UNIMPLEMENTED")}));
 
-    builder.create<mlir::emitc::ReturnOp>(loc, statusOp.getResult(0));
+    mlir::emitc::ReturnOp::create(builder, loc, statusOp.getResult(0));
   }
 
   // iree_status_t resolve_import(
@@ -852,8 +865,8 @@
         },
         {emitc::OpaqueType::get(ctx, "iree_status_t")});
 
-    auto funcOp = builder.create<mlir::emitc::FuncOp>(
-        loc, moduleName + "_resolve_import", funcType);
+    auto funcOp = mlir::emitc::FuncOp::create(
+        builder, loc, moduleName + "_resolve_import", funcType);
     funcOp.setSpecifiersAttr(
         builder.getArrayAttr({builder.getStringAttr("static")}));
     funcOp.setPrivate();
@@ -872,12 +885,13 @@
     std::string moduleStateTypeName =
         std::string("struct ") + moduleName + "_state_t";
 
-    auto stateOp = builder.create<emitc::CastOp>(
-        /*location=*/loc,
-        /*type=*/
-        emitc::PointerType::get(
-            emitc::OpaqueType::get(ctx, moduleStateTypeName)),
-        /*operand=*/moduleStateArg);
+    auto stateOp =
+        emitc::CastOp::create(builder,
+                              /*location=*/loc,
+                              /*type=*/
+                              emitc::PointerType::get(emitc::OpaqueType::get(
+                                  ctx, moduleStateTypeName)),
+                              /*operand=*/moduleStateArg);
 
     auto stateOpLValue =
         emitc_builders::asLValue(builder, loc, stateOp.getResult());
@@ -894,7 +908,8 @@
     auto import = emitc_builders::arrayElementAddress(
         builder, loc, /*index=*/ordinalArg, /*operand=*/imports);
 
-    builder.create<emitc::CallOpaqueOp>(
+    emitc::CallOpaqueOp::create(
+        builder,
         /*location=*/loc,
         /*type=*/TypeRange{},
         /*callee=*/"EMITC_DEREF_ASSIGN_PTR",
@@ -902,7 +917,7 @@
 
     auto status = emitc_builders::ireeOkStatus(builder, loc);
 
-    builder.create<mlir::emitc::ReturnOp>(loc, status);
+    mlir::emitc::ReturnOp::create(builder, loc, status);
   }
 
   // iree_status_t create(
@@ -930,8 +945,8 @@
             emitc::OpaqueType::get(ctx, "iree_status_t"),
         });
 
-    auto funcOp = builder.create<mlir::emitc::FuncOp>(
-        loc, moduleName + "_create", funcType);
+    auto funcOp = mlir::emitc::FuncOp::create(builder, loc,
+                                              moduleName + "_create", funcType);
     funcOp.setPublic();
 
     // This function needs an iree_vm_native_module_descriptor_t that is emitted
@@ -959,12 +974,13 @@
 
     Value modulePtr = emitc_builders::addressOf(builder, loc, module);
 
-    auto voidPtr = builder.create<emitc::CastOp>(
-        /*location=*/loc,
-        /*type=*/
-        emitc::PointerType::get(
-            emitc::PointerType::get(emitc::OpaqueType::get(ctx, "void"))),
-        /*operand=*/modulePtr);
+    auto voidPtr =
+        emitc::CastOp::create(builder,
+                              /*location=*/loc,
+                              /*type=*/
+                              emitc::PointerType::get(emitc::PointerType::get(
+                                  emitc::OpaqueType::get(ctx, "void"))),
+                              /*operand=*/modulePtr);
 
     returnIfError(builder, loc, "iree_allocator_malloc", {},
                   {allocatorArg, moduleSize, voidPtr.getResult()},
@@ -1013,7 +1029,8 @@
 
     Value vmModulePtr = emitc_builders::addressOf(builder, loc, vmModule);
 
-    auto vmInitializeStatus = builder.create<emitc::CallOpaqueOp>(
+    auto vmInitializeStatus = emitc::CallOpaqueOp::create(
+        builder,
         /*location=*/loc,
         /*type=*/emitc::OpaqueType::get(ctx, "iree_status_t"),
         /*callee=*/"iree_vm_module_initialize",
@@ -1023,7 +1040,8 @@
 
     Type boolType = builder.getIntegerType(1);
 
-    auto vmInitializeIsOk = builder.create<emitc::CallOpaqueOp>(
+    auto vmInitializeIsOk = emitc::CallOpaqueOp::create(
+        builder,
         /*location=*/loc,
         /*type=*/boolType,
         /*callee=*/"iree_status_is_ok",
@@ -1042,7 +1060,8 @@
       Region *parentRegion = condBlock->getParent();
       failureBlock = builder.createBlock(parentRegion, parentRegion->end());
 
-      builder.create<emitc::CallOpaqueOp>(
+      emitc::CallOpaqueOp::create(
+          builder,
           /*location=*/loc,
           /*type=*/TypeRange{},
           /*callee=*/"iree_allocator_free",
@@ -1050,14 +1069,14 @@
           ArrayRef<Value>{allocatorArg,
                           emitc_builders::asRValue(builder, loc, module)});
 
-      builder.create<mlir::emitc::ReturnOp>(loc,
-                                            vmInitializeStatus.getResult(0));
+      mlir::emitc::ReturnOp::create(builder, loc,
+                                    vmInitializeStatus.getResult(0));
     }
 
     builder.setInsertionPointToEnd(condBlock);
 
-    builder.create<mlir::cf::CondBranchOp>(loc, vmInitializeIsOk.getResult(0),
-                                           continuationBlock, failureBlock);
+    mlir::cf::CondBranchOp::create(builder, loc, vmInitializeIsOk.getResult(0),
+                                   continuationBlock, failureBlock);
 
     builder.setInsertionPointToStart(continuationBlock);
 
@@ -1067,8 +1086,8 @@
       // The type doesn't matter, the result gets inlined into it's uses anyway.
       Type type = emitc::PointerType::get(emitc::OpaqueType::get(ctx, "void"));
 
-      Value funcPtr = builder.create<emitc::LiteralOp>(
-          loc, type, moduleName + "_" + funcName);
+      Value funcPtr = emitc::LiteralOp::create(builder, loc, type,
+                                               moduleName + "_" + funcName);
       emitc_builders::structMemberAssign(builder, loc,
                                          /*memberName=*/funcName,
                                          /*operand=*/vmModule,
@@ -1077,7 +1096,8 @@
 
     std::string descriptorPtr = "&" + moduleName + "_descriptor_";
 
-    auto status = builder.create<emitc::CallOpaqueOp>(
+    auto status = emitc::CallOpaqueOp::create(
+        builder,
         /*location=*/loc,
         /*type=*/emitc::OpaqueType::get(ctx, "iree_status_t"),
         /*callee=*/"iree_vm_native_module_create",
@@ -1089,7 +1109,7 @@
                              builder.getIndexAttr(1), builder.getIndexAttr(2),
                              builder.getIndexAttr(3)}));
 
-    builder.create<mlir::emitc::ReturnOp>(loc, status.getResult(0));
+    mlir::emitc::ReturnOp::create(builder, loc, status.getResult(0));
   }
 
   return success();
@@ -1122,33 +1142,33 @@
     emitc_builders::preprocessorDirective(builder, loc, emitc_builders::DEFINE,
                                           includeGuard);
 
-    builder.create<emitc::IncludeOp>(loc, "iree/vm/api.h");
+    emitc::IncludeOp::create(builder, loc, "iree/vm/api.h");
 
     emitc_builders::preprocessorDirective(builder, loc, emitc_builders::IFDEF,
                                           "__cplusplus");
-    builder.create<emitc::VerbatimOp>(loc, "extern \"C\" {");
+    emitc::VerbatimOp::create(builder, loc, "extern \"C\" {");
     emitc_builders::preprocessorDirective(builder, loc, emitc_builders::ENDIF,
                                           "//  __cplusplus");
 
     // Emit declarations for public functions.
     for (auto funcOp : moduleOp.getOps<mlir::emitc::FuncOp>()) {
       if (funcOp.isPublic()) {
-        builder.create<emitc::DeclareFuncOp>(loc, funcOp.getName());
+        emitc::DeclareFuncOp::create(builder, loc, funcOp.getName());
       }
     }
 
     emitc_builders::preprocessorDirective(builder, loc, emitc_builders::IFDEF,
                                           "__cplusplus");
-    builder.create<emitc::VerbatimOp>(loc, "}  // extern \"C\"");
+    emitc::VerbatimOp::create(builder, loc, "}  // extern \"C\"");
     emitc_builders::preprocessorDirective(builder, loc, emitc_builders::ENDIF,
                                           "//  __cplusplus");
     emitc_builders::preprocessorDirective(builder, loc, emitc_builders::ENDIF,
                                           std::string("//  ") + includeGuard);
     emitc_builders::preprocessorDirective(builder, loc, emitc_builders::IF,
                                           "defined(EMITC_IMPLEMENTATION)");
-    builder.create<emitc::IncludeOp>(loc, "iree/vm/ops.h");
-    builder.create<emitc::IncludeOp>(loc, "iree/vm/ops_emitc.h");
-    builder.create<emitc::IncludeOp>(loc, "iree/vm/shims_emitc.h");
+    emitc::IncludeOp::create(builder, loc, "iree/vm/ops.h");
+    emitc::IncludeOp::create(builder, loc, "iree/vm/ops_emitc.h");
+    emitc::IncludeOp::create(builder, loc, "iree/vm/shims_emitc.h");
 
     // Rodata ops.
     for (auto rodataOp : moduleOp.getOps<IREE::VM::RodataOp>()) {
@@ -1182,7 +1202,7 @@
             static_cast<unsigned int>(static_cast<unsigned char>(value)));
       }
       stmt += "};";
-      builder.create<emitc::VerbatimOp>(loc, stmt);
+      emitc::VerbatimOp::create(builder, loc, stmt);
       opsToRemove.push_back(rodataOp.getOperation());
     }
 
@@ -1225,12 +1245,12 @@
     StringRef beginCallTypedef =
         "typedef iree_status_t(*begin_call_t)(void*, iree_vm_stack_t*, "
         "iree_vm_function_call_t);";
-    builder.create<emitc::VerbatimOp>(loc, beginCallTypedef);
+    emitc::VerbatimOp::create(builder, loc, beginCallTypedef);
 
     // Emit declarations for private functions.
     for (auto funcOp : moduleOp.getOps<mlir::emitc::FuncOp>()) {
       if (funcOp.isPrivate()) {
-        builder.create<emitc::DeclareFuncOp>(loc, funcOp.getName());
+        emitc::DeclareFuncOp::create(builder, loc, funcOp.getName());
       }
     }
 
@@ -1265,7 +1285,7 @@
       }
     }
     deps += "};";
-    builder.create<emitc::VerbatimOp>(loc, deps);
+    emitc::VerbatimOp::create(builder, loc, deps);
 
     // Imports.
     SmallVector<IREE::VM::ImportOp> importOps(
@@ -1292,7 +1312,7 @@
       }
     }
     imports += "};";
-    builder.create<emitc::VerbatimOp>(loc, imports);
+    emitc::VerbatimOp::create(builder, loc, imports);
 
     for (auto op : moduleOp.getOps<IREE::VM::ImportOp>()) {
       opsToRemove.push_back(op);
@@ -1332,7 +1352,7 @@
       }
     }
     exports += "};";
-    builder.create<emitc::VerbatimOp>(loc, exports);
+    emitc::VerbatimOp::create(builder, loc, exports);
 
     // Functions.
     std::string functionName = moduleOp.getName().str() + "_funcs_";
@@ -1355,7 +1375,7 @@
       }
     }
     functions += "};";
-    builder.create<emitc::VerbatimOp>(loc, functions);
+    emitc::VerbatimOp::create(builder, loc, functions);
 
     // Module descriptor.
     // TODO(simon-camp): support module-level reflection attributes
@@ -1386,7 +1406,7 @@
         + std::to_string(exportedFunctions.size()) + "," + functionName + "," +
         "};";
 
-    builder.create<emitc::VerbatimOp>(loc, descriptor);
+    emitc::VerbatimOp::create(builder, loc, descriptor);
 
     // Move functions marked as `emitAtEnd` to the end of the module.
     auto funcs =
@@ -1412,7 +1432,7 @@
   // the conversion pass should be changed to replace the vm.module
   // with a builtin.module.
   builder.setInsertionPointToStart(&moduleOp.getBlock());
-  auto innerModule = builder.create<mlir::ModuleOp>(loc);
+  auto innerModule = mlir::ModuleOp::create(builder, loc);
 
   IRRewriter rewriter(moduleOp.getContext());
 
@@ -1634,7 +1654,7 @@
         ctx, {inputTypes}, {emitc::OpaqueType::get(ctx, "iree_status_t")});
 
     auto newFuncOp =
-        rewriter.create<mlir::emitc::FuncOp>(loc, newFuncName, newFuncType);
+        mlir::emitc::FuncOp::create(rewriter, loc, newFuncName, newFuncType);
     newFuncOp.setSpecifiersAttr(
         rewriter.getArrayAttr({rewriter.getStringAttr("static")}));
     newFuncOp.setPrivate();
@@ -1716,7 +1736,7 @@
 
       auto status = emitc_builders::ireeOkStatus(rewriter, loc);
 
-      rewriter.create<mlir::emitc::ReturnOp>(loc, status);
+      mlir::emitc::ReturnOp::create(rewriter, loc, status);
     }
 
     rewriter.eraseOp(exportOp);
@@ -1742,18 +1762,20 @@
     std::string moduleStateTypeName =
         std::string("struct ") + moduleOp.getName().str() + "_state_t";
 
-    auto moduleCasted = rewriter.create<emitc::CastOp>(
+    auto moduleCasted = emitc::CastOp::create(
+        rewriter,
         /*location=*/loc,
         /*type=*/
         emitc::PointerType::get(emitc::OpaqueType::get(ctx, moduleTypeName)),
         /*operand=*/module);
 
-    auto moduleStateCasted = rewriter.create<emitc::CastOp>(
-        /*location=*/loc,
-        /*type=*/
-        emitc::PointerType::get(
-            emitc::OpaqueType::get(ctx, moduleStateTypeName)),
-        /*operand=*/moduleState);
+    auto moduleStateCasted =
+        emitc::CastOp::create(rewriter,
+                              /*location=*/loc,
+                              /*type=*/
+                              emitc::PointerType::get(emitc::OpaqueType::get(
+                                  ctx, moduleStateTypeName)),
+                              /*operand=*/moduleState);
 
     return {{moduleCasted.getResult(), moduleStateCasted.getResult()}};
   }
@@ -1868,7 +1890,8 @@
       // cast
       std::string argumentsType =
           std::string("struct ") + argumentStruct.name.value();
-      auto arguments = rewriter.create<emitc::CastOp>(
+      auto arguments = emitc::CastOp::create(
+          rewriter,
           /*location=*/loc,
           /*type=*/
           emitc::PointerType::get(emitc::OpaqueType::get(ctx, argumentsType)),
@@ -1896,7 +1919,8 @@
       // cast
       std::string resultType =
           std::string("struct ") + resultStruct.name.value();
-      auto results = rewriter.create<emitc::CastOp>(
+      auto results = emitc::CastOp::create(
+          rewriter,
           /*location=*/loc,
           /*type=*/
           emitc::PointerType::get(emitc::OpaqueType::get(ctx, resultType)),
@@ -1937,11 +1961,11 @@
         std::string memberName = "arg" + std::to_string(input.index());
         auto memberPtr = emitc_builders::structPtrMemberAddress(
             rewriter, loc, ptrType, memberName, value);
-        rewriter.create<emitc::CallOpaqueOp>(
-            /*location=*/memberPtr.getLoc(),
-            /*type=*/TypeRange{},
-            /*callee=*/"iree_vm_ref_retain_inplace",
-            /*operands=*/ArrayRef<Value>{memberPtr});
+        emitc::CallOpaqueOp::create(rewriter,
+                                    /*location=*/memberPtr.getLoc(),
+                                    /*type=*/TypeRange{},
+                                    /*callee=*/"iree_vm_ref_retain_inplace",
+                                    /*operands=*/ArrayRef<Value>{memberPtr});
         argumentStruct.callArguments.push_back(memberPtr);
       } else {
         Type memberType = input.value();
@@ -2085,7 +2109,8 @@
           cast<mlir::emitc::FuncOp>(failureBlock->getParentOp());
       releaseRefs(builder, location, funcOp, typeConverter.analysis);
 
-      auto statusOp = builder.create<emitc::CallOpaqueOp>(
+      auto statusOp = emitc::CallOpaqueOp::create(
+          builder,
           /*location=*/location,
           /*type=*/emitc::OpaqueType::get(ctx, "iree_status_t"),
           /*callee=*/"iree_make_status",
@@ -2093,12 +2118,12 @@
           /*args=*/
           ArrayAttr::get(
               ctx, {emitc::OpaqueAttr::get(ctx, "IREE_STATUS_NOT_FOUND")}));
-      builder.create<mlir::emitc::ReturnOp>(location, statusOp.getResult(0));
+      mlir::emitc::ReturnOp::create(builder, location, statusOp.getResult(0));
     }
 
     builder.setInsertionPointToEnd(condBlock);
-    builder.create<cf::CondBranchOp>(location, conditionI1, failureBlock,
-                                     continuationBlock);
+    cf::CondBranchOp::create(builder, location, conditionI1, failureBlock,
+                             continuationBlock);
 
     builder.setInsertionPointToStart(continuationBlock);
   }
@@ -2127,8 +2152,8 @@
              << "Failed to build function type for wrapper";
     }
 
-    auto newFuncOp = builder.create<mlir::emitc::FuncOp>(
-        loc, newFuncName.value(), newFuncType.value());
+    auto newFuncOp = mlir::emitc::FuncOp::create(
+        builder, loc, newFuncName.value(), newFuncType.value());
     newFuncOp.setSpecifiersAttr(
         builder.getArrayAttr({builder.getStringAttr("static")}));
     newFuncOp.setPrivate();
@@ -2184,7 +2209,7 @@
 
       auto status = emitc_builders::ireeOkStatus(builder, loc);
 
-      builder.create<mlir::emitc::ReturnOp>(loc, status);
+      mlir::emitc::ReturnOp::create(builder, loc, status);
     }
 
     return success();
@@ -2390,11 +2415,11 @@
                                /*operand=*/uint8Ptr)
                            .getResult();
 
-        builder.create<emitc::CallOpaqueOp>(
-            /*location=*/loc,
-            /*type=*/TypeRange{},
-            /*callee=*/"iree_vm_ref_assign",
-            /*operands=*/ArrayRef<Value>{arg, refPtr});
+        emitc::CallOpaqueOp::create(builder,
+                                    /*location=*/loc,
+                                    /*type=*/TypeRange{},
+                                    /*callee=*/"iree_vm_ref_assign",
+                                    /*operands=*/ArrayRef<Value>{arg, refPtr});
       } else {
         auto argLValue = emitc_builders::asLValue(builder, loc, arg);
         assert(!isa<emitc::PointerType>(argType));
@@ -2435,8 +2460,8 @@
     // The last N arguments are the results.
     size_t resultOffset = funcOp.getNumArguments() - resultTypes.size();
 
-    auto results = builder.create<emitc::MemberOp>(
-        loc,
+    auto results = emitc::MemberOp::create(
+        builder, loc,
         /*type=*/
         emitc::LValueType::get(emitc::OpaqueType::get(ctx, "iree_byte_span_t")),
         /*memberName=*/"results",
@@ -2465,11 +2490,11 @@
                                /*operand=*/uint8Ptr)
                            .getResult();
 
-        builder.create<emitc::CallOpaqueOp>(
-            /*location=*/loc,
-            /*type=*/TypeRange{},
-            /*callee=*/"iree_vm_ref_move",
-            /*operands=*/ArrayRef<Value>{refPtr, arg});
+        emitc::CallOpaqueOp::create(builder,
+                                    /*location=*/loc,
+                                    /*type=*/TypeRange{},
+                                    /*callee=*/"iree_vm_ref_move",
+                                    /*operands=*/ArrayRef<Value>{refPtr, arg});
       } else {
         Type valueType = llvm::cast<emitc::PointerType>(argType).getPointee();
         Value size =
@@ -2501,8 +2526,8 @@
     auto ctx = builder.getContext();
 
     // RETURN_IF_ERROR(import->module->begin_call(import->module, stack, call));
-    auto im = builder.create<emitc::MemberOfPtrOp>(
-        loc,
+    auto im = emitc::MemberOfPtrOp::create(
+        builder, loc,
         /*type=*/
         emitc::LValueType::get(emitc::PointerType::get(
             emitc::OpaqueType::get(ctx, "iree_vm_module_t"))),
@@ -2815,7 +2840,8 @@
     auto [ref, refPtr] = emitc_builders::allocZeroInitializedVar(
         builder, loc, emitc::OpaqueType::get(ctx, "iree_vm_ref_t"));
 
-    builder.create<emitc::CallOpaqueOp>(
+    emitc::CallOpaqueOp::create(
+        builder,
         /*location=*/loc,
         /*type=*/TypeRange{},
         /*callee=*/"iree_vm_ref_assign",
@@ -2962,12 +2988,12 @@
     Value refResult = this->getModuleAnalysis().lookupRef(selectOp.getResult());
 
     Type boolType = rewriter.getI1Type();
-    auto condition = rewriter.create<IREE::VM::CmpNZI32Op>(
-        loc, rewriter.getI32Type(), selectOp.getCondition());
-    auto conditionI1 = rewriter.create<emitc::CastOp>(
-        /*location=*/loc,
-        /*type=*/boolType,
-        /*operand=*/condition.getResult());
+    auto condition = IREE::VM::CmpNZI32Op::create(
+        rewriter, loc, rewriter.getI32Type(), selectOp.getCondition());
+    auto conditionI1 = emitc::CastOp::create(rewriter,
+                                             /*location=*/loc,
+                                             /*type=*/boolType,
+                                             /*operand=*/condition.getResult());
 
     auto *continueBlock =
         rewriter.splitBlock(selectOp->getBlock(), Block::iterator(selectOp));
@@ -2986,7 +3012,7 @@
                     rewriter.getIndexAttr(1), rewriter.getIndexAttr(2)}),
           /*operands=*/ArrayRef<Value>{refTrue, resultTypeAsRef, refResult},
           this->getModuleAnalysis());
-      rewriter.create<IREE::VM::BranchOp>(loc, continueBlock);
+      IREE::VM::BranchOp::create(rewriter, loc, continueBlock);
     }
 
     Block *falseBlock = nullptr;
@@ -3003,12 +3029,12 @@
                     rewriter.getIndexAttr(1), rewriter.getIndexAttr(2)}),
           /*operands=*/ArrayRef<Value>{refFalse, resultTypeAsRef, refResult},
           this->getModuleAnalysis());
-      rewriter.create<IREE::VM::BranchOp>(loc, continueBlock);
+      IREE::VM::BranchOp::create(rewriter, loc, continueBlock);
     }
 
     rewriter.setInsertionPointAfterValue(conditionI1);
-    rewriter.create<mlir::cf::CondBranchOp>(loc, conditionI1.getResult(),
-                                            trueBlock, falseBlock);
+    mlir::cf::CondBranchOp::create(rewriter, loc, conditionI1.getResult(),
+                                   trueBlock, falseBlock);
     rewriter.replaceOp(selectOp, refResult);
 
     return success();
@@ -3105,7 +3131,8 @@
         rewriter, loc, /*index=*/rodataOp.getOrdinal()->getZExtValue(),
         /*operand=*/rodataBuffersPtr);
 
-    auto typeIdOp = rewriter.create<emitc::CallOpaqueOp>(
+    auto typeIdOp = emitc::CallOpaqueOp::create(
+        rewriter,
         /*location=*/loc,
         /*type=*/emitc::OpaqueType::get(ctx, "iree_vm_ref_type_t"),
         /*callee=*/"iree_vm_buffer_type",
@@ -3190,7 +3217,7 @@
                                   /*isMove=*/false))) {
         return op.emitError() << "moving of multiple refs failed";
       }
-      rewriter.create<mlir::cf::BranchOp>(loc, op.getDest(), nonRefOperands);
+      mlir::cf::BranchOp::create(rewriter, loc, op.getDest(), nonRefOperands);
     }
 
     rewriter.replaceOpWithNewOp<mlir::cf::BranchOp>(op, destDispatch);
@@ -3251,12 +3278,12 @@
 
     Type boolType = rewriter.getI1Type();
 
-    auto condition = rewriter.create<IREE::VM::CmpNZI32Op>(
-        loc, rewriter.getI32Type(), op.getCondition());
-    auto conditionI1 = rewriter.create<emitc::CastOp>(
-        /*location=*/loc,
-        /*type=*/boolType,
-        /*operand=*/condition.getResult());
+    auto condition = IREE::VM::CmpNZI32Op::create(
+        rewriter, loc, rewriter.getI32Type(), op.getCondition());
+    auto conditionI1 = emitc::CastOp::create(rewriter,
+                                             /*location=*/loc,
+                                             /*type=*/boolType,
+                                             /*operand=*/condition.getResult());
 
     // If we don't have ref block arguments, we can convert the operation
     // directly.
@@ -3273,8 +3300,8 @@
       trueDestDispatch = rewriter.createBlock(trueDest);
 
       // Let the BranchOpConversion handle ref block arguments.
-      rewriter.create<IREE::VM::BranchOp>(loc, op.getTrueDest(),
-                                          op.getTrueOperands());
+      IREE::VM::BranchOp::create(rewriter, loc, op.getTrueDest(),
+                                 op.getTrueOperands());
     }
 
     Block *falseDestDispatch;
@@ -3283,8 +3310,8 @@
       falseDestDispatch = rewriter.createBlock(falseDest);
 
       // Let the BranchOpConversion handle ref block arguments.
-      rewriter.create<IREE::VM::BranchOp>(loc, op.getFalseDest(),
-                                          op.getFalseOperands());
+      IREE::VM::BranchOp::create(rewriter, loc, op.getFalseDest(),
+                                 op.getFalseOperands());
     }
 
     rewriter.replaceOpWithNewOp<mlir::cf::CondBranchOp>(
@@ -3313,16 +3340,16 @@
         caseBlocks.push_back(rewriter.createBlock(nextBlock));
       caseBlocks.push_back(rewriter.createBlock(nextBlock)); // default
     }
-    rewriter.create<IREE::VM::BranchOp>(op.getLoc(), caseBlocks.front());
+    IREE::VM::BranchOp::create(rewriter, op.getLoc(), caseBlocks.front());
     for (size_t i = 0; i < caseDestinations.size(); ++i) {
       rewriter.setInsertionPointToStart(caseBlocks[i]);
-      Value cmp = rewriter.create<IREE::VM::CmpEQI32Op>(
-          op.getLoc(), rewriter.getI32Type(), adaptor.getIndex(),
-          rewriter.create<IREE::VM::ConstI32Op>(op.getLoc(), i));
+      Value cmp = IREE::VM::CmpEQI32Op::create(
+          rewriter, op.getLoc(), rewriter.getI32Type(), adaptor.getIndex(),
+          IREE::VM::ConstI32Op::create(rewriter, op.getLoc(), i));
       auto caseOperands = adaptor.getCaseOperands();
-      rewriter.create<IREE::VM::CondBranchOp>(
-          op.getLoc(), cmp, caseDestinations[i], caseOperands[i],
-          caseBlocks[i + 1], ValueRange{});
+      IREE::VM::CondBranchOp::create(rewriter, op.getLoc(), cmp,
+                                     caseDestinations[i], caseOperands[i],
+                                     caseBlocks[i + 1], ValueRange{});
     }
     rewriter.setInsertionPointToStart(caseBlocks.back());
     rewriter.replaceOpWithNewOp<IREE::VM::BranchOp>(
@@ -3363,7 +3390,8 @@
 
         refMapping.map(operandRef, resultArgument);
       } else {
-        rewriter.create<emitc::CallOpaqueOp>(
+        emitc::CallOpaqueOp::create(
+            rewriter,
             /*location=*/loc,
             /*type=*/TypeRange{},
             /*callee=*/"EMITC_DEREF_ASSIGN_VALUE",
@@ -3444,10 +3472,10 @@
                               .getResult();
 
     auto i32Type = rewriter.getIntegerType(32);
-    auto conditionI32 = rewriter.create<emitc::CastOp>(
-        /*location=*/loc,
-        /*type=*/i32Type,
-        /*operand=*/invConditionI1);
+    auto conditionI32 = emitc::CastOp::create(rewriter,
+                                              /*location=*/loc,
+                                              /*type=*/i32Type,
+                                              /*operand=*/invConditionI1);
 
     rewriter.replaceOp(op, {conditionI32.getResult()});
 
@@ -3479,7 +3507,7 @@
 
       auto status = emitc_builders::ireeOkStatus(rewriter, loc);
 
-      rewriter.create<mlir::emitc::ReturnOp>(loc, status);
+      mlir::emitc::ReturnOp::create(rewriter, loc, status);
     }
     Block *failureBlock;
     {
@@ -3500,10 +3528,11 @@
                                        /*memberName=*/"size",
                                        /*operand=*/messageLValue);
 
-      auto messageSizeIntOp = rewriter.create<emitc::CastOp>(
-          /*location=*/loc,
-          /*type=*/emitc::OpaqueType::get(ctx, "int"),
-          /*operand=*/messageSize);
+      auto messageSizeIntOp =
+          emitc::CastOp::create(rewriter,
+                                /*location=*/loc,
+                                /*type=*/emitc::OpaqueType::get(ctx, "int"),
+                                /*operand=*/messageSize);
 
       Type charPtr =
           emitc::PointerType::get(emitc::OpaqueType::get(ctx, "const char"));
@@ -3513,7 +3542,8 @@
                                        /*memberName=*/"data",
                                        /*operand=*/messageLValue);
 
-      auto status = rewriter.create<emitc::CallOpaqueOp>(
+      auto status = emitc::CallOpaqueOp::create(
+          rewriter,
           /*location=*/loc,
           /*type=*/emitc::OpaqueType::get(ctx, "iree_status_t"),
           /*callee=*/"iree_status_allocate_f",
@@ -3528,14 +3558,14 @@
                emitc::OpaqueAttr::get(ctx, "\"%.*s\""),
                rewriter.getIndexAttr(0), rewriter.getIndexAttr(1)}));
 
-      rewriter.create<mlir::emitc::ReturnOp>(loc, status.getResult(0));
+      mlir::emitc::ReturnOp::create(rewriter, loc, status.getResult(0));
     }
 
     Type boolType = rewriter.getIntegerType(1);
-    auto condition = rewriter.create<emitc::CastOp>(
-        /*location=*/loc,
-        /*type=*/boolType,
-        /*operand=*/op.getStatus());
+    auto condition = emitc::CastOp::create(rewriter,
+                                           /*location=*/loc,
+                                           /*type=*/boolType,
+                                           /*operand=*/op.getStatus());
 
     rewriter.replaceOpWithNewOp<mlir::cf::CondBranchOp>(
         op, condition.getResult(), failureBlock, passthroughBlock);
@@ -4325,12 +4355,12 @@
 
       emitc_builders::ireeVmRefRelease(rewriter, loc, ref);
 
-      rewriter.create<mlir::cf::BranchOp>(loc, continuationBlock);
+      mlir::cf::BranchOp::create(rewriter, loc, continuationBlock);
     }
 
     rewriter.setInsertionPointToEnd(condBlock);
-    rewriter.create<cf::CondBranchOp>(loc, invalidType, failureBlock,
-                                      continuationBlock);
+    cf::CondBranchOp::create(rewriter, loc, invalidType, failureBlock,
+                             continuationBlock);
 
     rewriter.replaceOp(getOp, ref);
 
@@ -4361,7 +4391,8 @@
       return setOp.emitOpError() << " not handled";
     }
 
-    auto valueOp = rewriter.create<emitc::CallOpaqueOp>(
+    auto valueOp = emitc::CallOpaqueOp::create(
+        rewriter,
         /*location=*/loc,
         /*type=*/emitc::OpaqueType::get(ctx, "iree_vm_value_t"),
         /*callee=*/valueConstructor.value(),
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp
index 74c4fdc..0a375dc 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/EmitCBuilders.cpp
@@ -77,14 +77,14 @@
 TypedValue<emitc::LValueType> asLValue(OpBuilder builder, Location loc,
                                        Value value) {
   auto var = allocateVariable(builder, loc, value.getType());
-  builder.create<emitc::AssignOp>(loc, var, value);
+  emitc::AssignOp::create(builder, loc, var, value);
   return var;
 }
 
 Value asRValue(OpBuilder builder, Location loc,
                TypedValue<emitc::LValueType> value) {
-  return builder.create<emitc::LoadOp>(loc, value.getType().getValueType(),
-                                       value);
+  return emitc::LoadOp::create(builder, loc, value.getType().getValueType(),
+                               value);
 }
 
 void asRValues(OpBuilder builder, Location location,
@@ -154,17 +154,18 @@
 
 void memcpy(OpBuilder builder, Location location, Value dest, Value src,
             Value count) {
-  builder.create<emitc::CallOpaqueOp>(
-      /*location=*/location,
-      /*type=*/TypeRange{},
-      /*callee=*/"memcpy",
-      /*operands=*/ArrayRef<Value>{dest, src, count});
+  emitc::CallOpaqueOp::create(builder,
+                              /*location=*/location,
+                              /*type=*/TypeRange{},
+                              /*callee=*/"memcpy",
+                              /*operands=*/ArrayRef<Value>{dest, src, count});
 }
 
 void memset(OpBuilder builder, Location location, Value dest, int ch,
             Value count) {
   auto ctx = builder.getContext();
-  builder.create<emitc::CallOpaqueOp>(
+  emitc::CallOpaqueOp::create(
+      builder,
       /*location=*/location,
       /*type=*/TypeRange{},
       /*callee=*/"memset",
@@ -180,9 +181,9 @@
   auto ctx = builder.getContext();
   Type type = emitc::OpaqueType::get(ctx, "iree_host_size_t");
   Value indexValue =
-      builder.create<emitc::LiteralOp>(location, type, std::to_string(index));
+      emitc::LiteralOp::create(builder, location, type, std::to_string(index));
   TypedValue<emitc::LValueType> subscript =
-      builder.create<emitc::SubscriptOp>(location, operand, indexValue);
+      emitc::SubscriptOp::create(builder, location, operand, indexValue);
   return builder
       .create<emitc::LoadOp>(location, subscript.getType().getValueType(),
                              subscript)
@@ -194,14 +195,14 @@
   auto ctx = builder.getContext();
   Type type = emitc::OpaqueType::get(ctx, "iree_host_size_t");
   Value indexValue =
-      builder.create<emitc::LiteralOp>(location, type, std::to_string(index));
+      emitc::LiteralOp::create(builder, location, type, std::to_string(index));
   return arrayElementAddress(builder, location, indexValue, operand);
 }
 
 Value arrayElementAddress(OpBuilder builder, Location location, Value index,
                           TypedValue<emitc::PointerType> operand) {
   TypedValue<emitc::LValueType> subscript =
-      builder.create<emitc::SubscriptOp>(location, operand, index);
+      emitc::SubscriptOp::create(builder, location, operand, index);
   return addressOf(builder, location, subscript);
 }
 
@@ -211,10 +212,10 @@
   auto ctx = builder.getContext();
   Type type = emitc::OpaqueType::get(ctx, "iree_host_size_t");
   Value indexValue =
-      builder.create<emitc::LiteralOp>(location, type, std::to_string(index));
+      emitc::LiteralOp::create(builder, location, type, std::to_string(index));
   TypedValue<emitc::LValueType> subscript =
-      builder.create<emitc::SubscriptOp>(location, array, indexValue);
-  builder.create<emitc::AssignOp>(location, subscript, value);
+      emitc::SubscriptOp::create(builder, location, array, indexValue);
+  emitc::AssignOp::create(builder, location, subscript, value);
 }
 
 void structDefinition(OpBuilder builder, Location location,
@@ -229,7 +230,7 @@
   }
   decl += "};";
 
-  builder.create<emitc::VerbatimOp>(location, StringAttr::get(ctx, decl));
+  emitc::VerbatimOp::create(builder, location, StringAttr::get(ctx, decl));
 }
 
 Value structMember(OpBuilder builder, Location location, Type type,
@@ -239,15 +240,15 @@
           .create<emitc::MemberOp>(location, emitc::LValueType::get(type),
                                    memberName, operand)
           .getResult();
-  return builder.create<emitc::LoadOp>(location, type, member).getResult();
+  return emitc::LoadOp::create(builder, location, type, member).getResult();
 }
 
 TypedValue<emitc::PointerType>
 structMemberAddress(OpBuilder builder, Location location,
                     emitc::PointerType type, StringRef memberName,
                     TypedValue<emitc::LValueType> operand) {
-  auto member = builder.create<emitc::MemberOp>(location, type.getPointee(),
-                                                memberName, operand);
+  auto member = emitc::MemberOp::create(builder, location, type.getPointee(),
+                                        memberName, operand);
   return addressOf(
       builder, location,
       llvm::cast<TypedValue<emitc::LValueType>>(member.getResult()));
@@ -256,25 +257,27 @@
 void structMemberAssign(OpBuilder builder, Location location,
                         StringRef memberName, TypedValue<mlir::Type> operand,
                         Value data) {
-  Value member = builder.create<emitc::MemberOp>(
-      location, emitc::LValueType::get(data.getType()), memberName, operand);
-  builder.create<emitc::AssignOp>(location, member, data);
+  Value member = emitc::MemberOp::create(builder, location,
+                                         emitc::LValueType::get(data.getType()),
+                                         memberName, operand);
+  emitc::AssignOp::create(builder, location, member, data);
 }
 
 Value structPtrMember(OpBuilder builder, Location location, Type type,
                       StringRef memberName,
                       TypedValue<emitc::LValueType> operand) {
-  TypedValue<mlir::Type> member = builder.create<emitc::MemberOfPtrOp>(
-      location, emitc::LValueType::get(type), memberName, operand);
-  return builder.create<emitc::LoadOp>(location, type, member).getResult();
+  TypedValue<mlir::Type> member = emitc::MemberOfPtrOp::create(
+      builder, location, emitc::LValueType::get(type), memberName, operand);
+  return emitc::LoadOp::create(builder, location, type, member).getResult();
 }
 
 TypedValue<emitc::PointerType>
 structPtrMemberAddress(OpBuilder builder, Location location,
                        emitc::PointerType type, StringRef memberName,
                        TypedValue<emitc::LValueType> operand) {
-  auto member = builder.create<emitc::MemberOfPtrOp>(
-      location, emitc::LValueType::get(type.getPointee()), memberName, operand);
+  auto member = emitc::MemberOfPtrOp::create(
+      builder, location, emitc::LValueType::get(type.getPointee()), memberName,
+      operand);
   return addressOf(
       builder, location,
       llvm::cast<TypedValue<emitc::LValueType>>(member.getResult()));
@@ -283,9 +286,10 @@
 void structPtrMemberAssign(OpBuilder builder, Location location,
                            StringRef memberName,
                            TypedValue<emitc::LValueType> operand, Value data) {
-  Value member = builder.create<emitc::MemberOfPtrOp>(
-      location, emitc::LValueType::get(data.getType()), memberName, operand);
-  builder.create<emitc::AssignOp>(location, member, data);
+  Value member = emitc::MemberOfPtrOp::create(
+      builder, location, emitc::LValueType::get(data.getType()), memberName,
+      operand);
+  emitc::AssignOp::create(builder, location, member, data);
 }
 
 Value ireeMakeCstringView(OpBuilder builder, Location location,
@@ -332,11 +336,11 @@
 }
 
 void ireeVmRefRelease(OpBuilder builder, Location location, Value operand) {
-  builder.create<emitc::CallOpaqueOp>(
-      /*location=*/location,
-      /*type=*/TypeRange{},
-      /*callee=*/"iree_vm_ref_release",
-      /*operands=*/ArrayRef<Value>{operand});
+  emitc::CallOpaqueOp::create(builder,
+                              /*location=*/location,
+                              /*type=*/TypeRange{},
+                              /*callee=*/"iree_vm_ref_release",
+                              /*operands=*/ArrayRef<Value>{operand});
 }
 
 emitc::VerbatimOp preprocessorDirective(OpBuilder builder, Location location,
@@ -349,7 +353,7 @@
     t += value;
   }
 
-  return builder.create<emitc::VerbatimOp>(location, t);
+  return emitc::VerbatimOp::create(builder, location, t);
 }
 
 } // namespace mlir::iree_compiler::emitc_builders
diff --git a/compiler/src/iree/compiler/Dialect/VM/IR/VMDialect.cpp b/compiler/src/iree/compiler/Dialect/VM/IR/VMDialect.cpp
index bc70ae4..969e5d7 100644
--- a/compiler/src/iree/compiler/Dialect/VM/IR/VMDialect.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/IR/VMDialect.cpp
@@ -101,7 +101,8 @@
 
     // Replace the return with a branch to the dest.
     OpBuilder builder(op);
-    builder.create<VM::BranchOp>(op->getLoc(), newDest, returnOp.getOperands());
+    VM::BranchOp::create(builder, op->getLoc(), newDest,
+                         returnOp.getOperands());
     op->erase();
   }
 
@@ -264,32 +265,32 @@
   if (ConstI32Op::isBuildableWith(typedValue, type)) {
     auto convertedValue = ConstI32Op::convertConstValue(typedValue);
     if (llvm::cast<IntegerAttr>(convertedValue).getValue() == 0) {
-      return builder.create<VM::ConstI32ZeroOp>(loc);
+      return VM::ConstI32ZeroOp::create(builder, loc);
     }
-    return builder.create<VM::ConstI32Op>(loc, convertedValue);
+    return VM::ConstI32Op::create(builder, loc, convertedValue);
   } else if (ConstI64Op::isBuildableWith(typedValue, type)) {
     auto convertedValue = ConstI64Op::convertConstValue(typedValue);
     if (llvm::cast<IntegerAttr>(convertedValue).getValue() == 0) {
-      return builder.create<VM::ConstI64ZeroOp>(loc);
+      return VM::ConstI64ZeroOp::create(builder, loc);
     }
-    return builder.create<VM::ConstI64Op>(loc, convertedValue);
+    return VM::ConstI64Op::create(builder, loc, convertedValue);
   } else if (ConstF32Op::isBuildableWith(typedValue, type)) {
     auto convertedValue = ConstF32Op::convertConstValue(typedValue);
     if (llvm::cast<FloatAttr>(convertedValue).getValue().isZero()) {
-      return builder.create<VM::ConstF32ZeroOp>(loc);
+      return VM::ConstF32ZeroOp::create(builder, loc);
     }
-    return builder.create<VM::ConstF32Op>(loc, convertedValue);
+    return VM::ConstF32Op::create(builder, loc, convertedValue);
   } else if (ConstF64Op::isBuildableWith(typedValue, type)) {
     auto convertedValue = ConstF64Op::convertConstValue(typedValue);
     if (llvm::cast<FloatAttr>(convertedValue).getValue().isZero()) {
-      return builder.create<VM::ConstF64ZeroOp>(loc);
+      return VM::ConstF64ZeroOp::create(builder, loc);
     }
-    return builder.create<VM::ConstF64Op>(loc, convertedValue);
+    return VM::ConstF64Op::create(builder, loc, convertedValue);
   } else if (llvm::isa<IREE::VM::RefType>(type)) {
     // The only constant type we support for refs is null so we can just
     // emit that here.
     // TODO(benvanik): relace unit attr with a proper null ref attr.
-    return builder.create<VM::ConstRefZeroOp>(loc, type);
+    return VM::ConstRefZeroOp::create(builder, loc, type);
   }
   // TODO(benvanik): handle other constant value types.
   return nullptr;
diff --git a/compiler/src/iree/compiler/Dialect/VM/IR/VMOpFolders.cpp b/compiler/src/iree/compiler/Dialect/VM/IR/VMOpFolders.cpp
index bac9fda..304b45e 100644
--- a/compiler/src/iree/compiler/Dialect/VM/IR/VMOpFolders.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/IR/VMOpFolders.cpp
@@ -2800,7 +2800,7 @@
   LogicalResult matchAndRewrite(T op,
                                 PatternRewriter &rewriter) const override {
     rewriter.replaceOpWithNewOp<U>(op, op.getType(), op.getOperand(),
-                                   rewriter.create<CZ>(op.getLoc()));
+                                   CZ::create(rewriter, op.getLoc()));
     return success();
   }
 };
@@ -2903,7 +2903,7 @@
     Attribute rhs;
     if (matchPattern(op.getRhs(), m_Constant(&rhs))) {
       auto cmpNz =
-          rewriter.create<CmpNZRefOp>(op.getLoc(), op.getType(), op.getLhs());
+          CmpNZRefOp::create(rewriter, op.getLoc(), op.getType(), op.getLhs());
       rewriter.replaceOpWithNewOp<XorI32Op>(
           op, op.getType(), cmpNz,
           rewriter.createOrFold<IREE::VM::ConstI32Op>(op.getLoc(), 1));
@@ -3204,8 +3204,8 @@
         rewriter.createBlock(block, {op.getStatus().getType()}, {op.getLoc()});
     block->moveBefore(failBlock);
     rewriter.setInsertionPointToStart(failBlock);
-    rewriter.create<FailOp>(op.getLoc(), failBlock->getArgument(0),
-                            op.getMessage().value_or(""));
+    FailOp::create(rewriter, op.getLoc(), failBlock->getArgument(0),
+                   op.getMessage().value_or(""));
 
     // Replace the original cond_fail with our cond_branch, splitting the block
     // and continuing if the condition is not taken.
diff --git a/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.cpp b/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.cpp
index 2526d4f..3f2dce8 100644
--- a/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.cpp
@@ -423,56 +423,56 @@
 
 IREE::Util::GlobalLoadOpInterface
 GlobalI32Op::createLoadOp(Location loc, OpBuilder &builder) {
-  return builder.create<IREE::VM::GlobalLoadI32Op>(loc, builder.getI32Type(),
-                                                   getGlobalName());
+  return IREE::VM::GlobalLoadI32Op::create(builder, loc, builder.getI32Type(),
+                                           getGlobalName());
 }
 IREE::Util::GlobalStoreOpInterface
 GlobalI32Op::createStoreOp(Location loc, Value value, OpBuilder &builder) {
-  return builder.create<IREE::VM::GlobalStoreI32Op>(loc, value,
-                                                    getGlobalName());
+  return IREE::VM::GlobalStoreI32Op::create(builder, loc, value,
+                                            getGlobalName());
 }
 
 IREE::Util::GlobalLoadOpInterface
 GlobalI64Op::createLoadOp(Location loc, OpBuilder &builder) {
-  return builder.create<IREE::VM::GlobalLoadI64Op>(loc, builder.getI64Type(),
-                                                   getGlobalName());
+  return IREE::VM::GlobalLoadI64Op::create(builder, loc, builder.getI64Type(),
+                                           getGlobalName());
 }
 IREE::Util::GlobalStoreOpInterface
 GlobalI64Op::createStoreOp(Location loc, Value value, OpBuilder &builder) {
-  return builder.create<IREE::VM::GlobalStoreI64Op>(loc, value,
-                                                    getGlobalName());
+  return IREE::VM::GlobalStoreI64Op::create(builder, loc, value,
+                                            getGlobalName());
 }
 
 IREE::Util::GlobalLoadOpInterface
 GlobalF32Op::createLoadOp(Location loc, OpBuilder &builder) {
-  return builder.create<IREE::VM::GlobalLoadF32Op>(loc, builder.getF32Type(),
-                                                   getGlobalName());
+  return IREE::VM::GlobalLoadF32Op::create(builder, loc, builder.getF32Type(),
+                                           getGlobalName());
 }
 IREE::Util::GlobalStoreOpInterface
 GlobalF32Op::createStoreOp(Location loc, Value value, OpBuilder &builder) {
-  return builder.create<IREE::VM::GlobalStoreF32Op>(loc, value,
-                                                    getGlobalName());
+  return IREE::VM::GlobalStoreF32Op::create(builder, loc, value,
+                                            getGlobalName());
 }
 
 IREE::Util::GlobalLoadOpInterface
 GlobalF64Op::createLoadOp(Location loc, OpBuilder &builder) {
-  return builder.create<IREE::VM::GlobalLoadF64Op>(loc, builder.getF64Type(),
-                                                   getGlobalName());
+  return IREE::VM::GlobalLoadF64Op::create(builder, loc, builder.getF64Type(),
+                                           getGlobalName());
 }
 IREE::Util::GlobalStoreOpInterface
 GlobalF64Op::createStoreOp(Location loc, Value value, OpBuilder &builder) {
-  return builder.create<IREE::VM::GlobalStoreF64Op>(loc, value,
-                                                    getGlobalName());
+  return IREE::VM::GlobalStoreF64Op::create(builder, loc, value,
+                                            getGlobalName());
 }
 
 IREE::Util::GlobalLoadOpInterface
 GlobalRefOp::createLoadOp(Location loc, OpBuilder &builder) {
-  return builder.create<IREE::VM::GlobalLoadRefOp>(loc, getType(),
-                                                   getSymName());
+  return IREE::VM::GlobalLoadRefOp::create(builder, loc, getType(),
+                                           getSymName());
 }
 IREE::Util::GlobalStoreOpInterface
 GlobalRefOp::createStoreOp(Location loc, Value value, OpBuilder &builder) {
-  return builder.create<IREE::VM::GlobalStoreRefOp>(loc, value, getSymName());
+  return IREE::VM::GlobalStoreRefOp::create(builder, loc, value, getSymName());
 }
 
 template <typename T>
diff --git a/compiler/src/iree/compiler/Dialect/VM/Transforms/GlobalInitialization.cpp b/compiler/src/iree/compiler/Dialect/VM/Transforms/GlobalInitialization.cpp
index 3f14453..dc8034b 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Transforms/GlobalInitialization.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Transforms/GlobalInitialization.cpp
@@ -36,9 +36,9 @@
   OpBuilder funcBuilder(moduleOp.getContext());
   if (!funcOp) {
     // Create a new empty function.
-    funcOp = moduleBuilder.create<IREE::VM::FuncOp>(
-        moduleBuilder.getUnknownLoc(), name,
-        moduleBuilder.getFunctionType({}, {}));
+    funcOp =
+        IREE::VM::FuncOp::create(moduleBuilder, moduleBuilder.getUnknownLoc(),
+                                 name, moduleBuilder.getFunctionType({}, {}));
     funcBuilder = OpBuilder::atBlockEnd(funcOp.addEntryBlock());
     return std::make_tuple(funcOp, funcBuilder);
   }
@@ -80,7 +80,7 @@
 
   // Add vm.export if needed.
   OpBuilder moduleBuilder(funcOp);
-  moduleBuilder.create<IREE::VM::ExportOp>(funcOp.getLoc(), funcOp);
+  IREE::VM::ExportOp::create(moduleBuilder, funcOp.getLoc(), funcOp);
 }
 
 // Updates the mutability of globals based on whether they are stored anywhere
@@ -185,8 +185,8 @@
     }
 
     // Add returns to the initializers.
-    initBuilder.create<IREE::VM::ReturnOp>(initBuilder.getUnknownLoc());
-    deinitBuilder.create<IREE::VM::ReturnOp>(deinitBuilder.getUnknownLoc());
+    IREE::VM::ReturnOp::create(initBuilder, initBuilder.getUnknownLoc());
+    IREE::VM::ReturnOp::create(deinitBuilder, deinitBuilder.getUnknownLoc());
 
     // Correct mutability of all globals.
     fixupGlobalMutability(moduleOp, symbolTable);
@@ -265,10 +265,10 @@
     if (auto integerType = llvm::dyn_cast<IntegerType>(value.getType())) {
       switch (integerType.getIntOrFloatBitWidth()) {
       case 32:
-        builder.create<IREE::VM::GlobalStoreI32Op>(loc, value, symName);
+        IREE::VM::GlobalStoreI32Op::create(builder, loc, value, symName);
         return success();
       case 64:
-        builder.create<IREE::VM::GlobalStoreI64Op>(loc, value, symName);
+        IREE::VM::GlobalStoreI64Op::create(builder, loc, value, symName);
         return success();
       default:
         return failure();
@@ -276,10 +276,10 @@
     } else if (auto floatType = llvm::dyn_cast<FloatType>(value.getType())) {
       switch (floatType.getIntOrFloatBitWidth()) {
       case 32:
-        builder.create<IREE::VM::GlobalStoreF32Op>(loc, value, symName);
+        IREE::VM::GlobalStoreF32Op::create(builder, loc, value, symName);
         return success();
       case 64:
-        builder.create<IREE::VM::GlobalStoreF64Op>(loc, value, symName);
+        IREE::VM::GlobalStoreF64Op::create(builder, loc, value, symName);
         return success();
       default:
         return failure();
diff --git a/compiler/src/iree/compiler/Dialect/VM/Transforms/HoistInlinedRodata.cpp b/compiler/src/iree/compiler/Dialect/VM/Transforms/HoistInlinedRodata.cpp
index 9c3eada..3b3d83a 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Transforms/HoistInlinedRodata.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Transforms/HoistInlinedRodata.cpp
@@ -42,9 +42,9 @@
       } else {
         moduleBuilder.setInsertionPointToStart(&moduleOp.getBlock());
       }
-      auto rodataOp = moduleBuilder.create<IREE::VM::RodataOp>(
-          inlineOp.getLoc(), inferConstantName(parentOp, inlineOp),
-          inlineOp.getValue());
+      auto rodataOp = IREE::VM::RodataOp::create(
+          moduleBuilder, inlineOp.getLoc(),
+          inferConstantName(parentOp, inlineOp), inlineOp.getValue());
       if (auto alignmentAttr = inlineOp.getAlignmentAttr()) {
         rodataOp.setAlignmentAttr(alignmentAttr);
       }
@@ -83,8 +83,8 @@
   void replaceInlineOpWithRodataRef(IREE::VM::RodataInlineOp inlineOp,
                                     IREE::VM::RodataOp rodataOp) {
     OpBuilder builder(inlineOp);
-    auto refOp =
-        builder.create<IREE::VM::ConstRefRodataOp>(inlineOp.getLoc(), rodataOp);
+    auto refOp = IREE::VM::ConstRefRodataOp::create(builder, inlineOp.getLoc(),
+                                                    rodataOp);
     inlineOp.replaceAllUsesWith(refOp.getValue());
     inlineOp.erase();
   }
diff --git a/compiler/src/iree/compiler/Dialect/VM/Transforms/OrdinalAllocation.cpp b/compiler/src/iree/compiler/Dialect/VM/Transforms/OrdinalAllocation.cpp
index 1db0406..cea7740 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Transforms/OrdinalAllocation.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Transforms/OrdinalAllocation.cpp
@@ -115,7 +115,7 @@
 
       OpBuilder builder(op);
       auto ordinalOp =
-          builder.create<IREE::VM::ConstI32Op>(op.getLoc(), ordinal);
+          IREE::VM::ConstI32Op::create(builder, op.getLoc(), ordinal);
       op.getReturnedGlobalRef().replaceAllUsesWith(ordinalOp);
 
       deadOps.push_back(op);
diff --git a/compiler/src/iree/compiler/Dialect/VM/Transforms/ReifyRodataTables.cpp b/compiler/src/iree/compiler/Dialect/VM/Transforms/ReifyRodataTables.cpp
index a28023f..50c66dc 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Transforms/ReifyRodataTables.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Transforms/ReifyRodataTables.cpp
@@ -60,18 +60,18 @@
       IREE::VM::RefType::get(rewriter.getType<IREE::VM::BufferType>());
   IREE::VM::RodataInlineOp tableRodata;
   if constexpr (std::is_same<IntTy, int32_t>()) {
-    tableRodata = rewriter.create<IREE::VM::RodataInlineOp>(
-        tableOp.getLoc(), refType, rewriter.getI32VectorAttr(table));
+    tableRodata = IREE::VM::RodataInlineOp::create(
+        rewriter, tableOp.getLoc(), refType, rewriter.getI32VectorAttr(table));
   } else {
-    tableRodata = rewriter.create<IREE::VM::RodataInlineOp>(
-        tableOp.getLoc(), refType, rewriter.getI64VectorAttr(table));
+    tableRodata = IREE::VM::RodataInlineOp::create(
+        rewriter, tableOp.getLoc(), refType, rewriter.getI64VectorAttr(table));
   }
   if (auto tableNameAttr = tableOp.getTableNameAttr()) {
     tableRodata.setNameAttr(tableNameAttr);
   }
 
-  auto dataRodata = rewriter.create<IREE::VM::RodataInlineOp>(
-      tableOp.getLoc(), refType,
+  auto dataRodata = IREE::VM::RodataInlineOp::create(
+      rewriter, tableOp.getLoc(), refType,
       IREE::Util::CompositeAttr::get(rewriter.getContext(), dataAttrs));
   if (auto dataNameAttr = tableOp.getDataNameAttr()) {
     dataRodata.setNameAttr(dataNameAttr);
diff --git a/compiler/src/iree/compiler/Dialect/VM/Transforms/ResolveRodataLoads.cpp b/compiler/src/iree/compiler/Dialect/VM/Transforms/ResolveRodataLoads.cpp
index 7e09b9d..d52ac42 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Transforms/ResolveRodataLoads.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Transforms/ResolveRodataLoads.cpp
@@ -78,8 +78,8 @@
     for (auto loadOp : globalInfo->getLoads()) {
       OpBuilder builder(loadOp);
       auto loadedValue = loadOp.getLoadedGlobalValue();
-      auto zeroRefOp = builder.create<IREE::VM::ConstRefZeroOp>(
-          loadOp.getLoc(), loadedValue.getType());
+      auto zeroRefOp = IREE::VM::ConstRefZeroOp::create(
+          builder, loadOp.getLoc(), loadedValue.getType());
       loadedValue.replaceAllUsesWith(zeroRefOp.getResult());
       deadOps.insert(loadOp);
     }
@@ -99,7 +99,7 @@
   for (auto loadOp : globalInfo->getLoads()) {
     OpBuilder builder(loadOp);
     auto rodataRefOp =
-        builder.create<IREE::VM::ConstRefRodataOp>(loadOp.getLoc(), rodataOp);
+        IREE::VM::ConstRefRodataOp::create(builder, loadOp.getLoc(), rodataOp);
     auto loadedValue = loadOp.getLoadedGlobalValue();
     loadedValue.replaceAllUsesWith(rodataRefOp.getResult());
     deadOps.insert(loadOp);
diff --git a/compiler/src/iree/compiler/Dialect/VMVX/Conversion/HALToVMVX/ConvertHALToVMVX.cpp b/compiler/src/iree/compiler/Dialect/VMVX/Conversion/HALToVMVX/ConvertHALToVMVX.cpp
index 2f1aa4f..5bba941 100644
--- a/compiler/src/iree/compiler/Dialect/VMVX/Conversion/HALToVMVX/ConvertHALToVMVX.cpp
+++ b/compiler/src/iree/compiler/Dialect/VMVX/Conversion/HALToVMVX/ConvertHALToVMVX.cpp
@@ -117,8 +117,8 @@
     Value workgroupDimI32 =
         op->getParentOfType<mlir::FunctionOpInterface>().getArgument(
             kEntryArgWorkgroupX + dim);
-    Value workgroupDim = rewriter.create<arith::IndexCastOp>(
-        op.getLoc(), rewriter.getIndexType(), workgroupDimI32);
+    Value workgroupDim = arith::IndexCastOp::create(
+        rewriter, op.getLoc(), rewriter.getIndexType(), workgroupDimI32);
     rewriter.replaceOp(op, workgroupDim);
     return success();
   }
@@ -141,8 +141,8 @@
     Value workgroupDimI32 =
         op->getParentOfType<mlir::FunctionOpInterface>().getArgument(
             kEntryArgWorkgroupSizeX + dim);
-    Value workgroupDim = rewriter.create<arith::IndexCastOp>(
-        op.getLoc(), rewriter.getIndexType(), workgroupDimI32);
+    Value workgroupDim = arith::IndexCastOp::create(
+        rewriter, op.getLoc(), rewriter.getIndexType(), workgroupDimI32);
     rewriter.replaceOp(op, workgroupDim);
     return success();
   }
@@ -165,8 +165,8 @@
     Value workgroupDimI32 =
         op->getParentOfType<mlir::FunctionOpInterface>().getArgument(
             kEntryArgWorkgroupCountX + dim);
-    Value workgroupDim = rewriter.create<arith::IndexCastOp>(
-        op.getLoc(), rewriter.getIndexType(), workgroupDimI32);
+    Value workgroupDim = arith::IndexCastOp::create(
+        rewriter, op.getLoc(), rewriter.getIndexType(), workgroupDimI32);
     rewriter.replaceOp(op, workgroupDim);
     return success();
   }
@@ -187,7 +187,7 @@
     // HACK: we could find the total push constant count and avoid this size op
     // but it'd require walking all the way up to the hal.executable export.
     auto constantsSize =
-        rewriter.create<IREE::Util::BufferSizeOp>(op.getLoc(), constantsArg);
+        IREE::Util::BufferSizeOp::create(rewriter, op.getLoc(), constantsArg);
     auto resultType = getTypeConverter()->convertType(op.getResult().getType());
 
     // Index -> byte offset.
diff --git a/compiler/src/iree/compiler/Dialect/VMVX/Transforms/MaterializeConstants.cpp b/compiler/src/iree/compiler/Dialect/VMVX/Transforms/MaterializeConstants.cpp
index 59442c4..268f02e 100644
--- a/compiler/src/iree/compiler/Dialect/VMVX/Transforms/MaterializeConstants.cpp
+++ b/compiler/src/iree/compiler/Dialect/VMVX/Transforms/MaterializeConstants.cpp
@@ -81,8 +81,8 @@
                             .str();
 
       // Placeholder ordinal that'll be updated during linking.
-      auto ordinalGlobalOp = moduleBuilder.create<IREE::Util::GlobalOp>(
-          globalLoc, globalName + "_ordinal", /*isMutable=*/true,
+      auto ordinalGlobalOp = IREE::Util::GlobalOp::create(
+          moduleBuilder, globalLoc, globalName + "_ordinal", /*isMutable=*/true,
           moduleBuilder.getI32Type());
       ordinalGlobalOp.setPrivate();
       ordinalGlobalOp->setAttr(
@@ -90,8 +90,8 @@
       ordinalGlobalOps.push_back(ordinalGlobalOp);
 
       // Value initialized in the constant setter built below.
-      auto valueGlobalOp = moduleBuilder.create<IREE::Util::GlobalOp>(
-          globalLoc, globalName, /*isMutable=*/true, globalType);
+      auto valueGlobalOp = IREE::Util::GlobalOp::create(
+          moduleBuilder, globalLoc, globalName, /*isMutable=*/true, globalType);
       valueGlobalOp.setPrivate();
       valueGlobalOps.push_back(valueGlobalOp);
       for (auto loadOp : loadOps) {
@@ -104,35 +104,37 @@
 
     // Create the setter function the runtime will use to push the constants.
     auto bufferType = IREE::Util::BufferType::get(context);
-    auto setterOp = moduleBuilder.create<func::FuncOp>(
-        FusedLoc::get(context, allLoadLocs), kConstantBlockSetterName,
-        moduleBuilder.getFunctionType({bufferType}, {}));
+    auto setterOp =
+        func::FuncOp::create(moduleBuilder, FusedLoc::get(context, allLoadLocs),
+                             kConstantBlockSetterName,
+                             moduleBuilder.getFunctionType({bufferType}, {}));
     setterOp.setPublic();
     auto setterBuilder = OpBuilder::atBlockBegin(setterOp.addEntryBlock());
     Value buffer = setterOp.getArgument(0);
-    Value bufferSize = setterBuilder.create<arith::ConstantIndexOp>(
-        buffer.getLoc(), allLoadOps.size() * sizeof(uint32_t));
-    Value elementSizeIndex = setterBuilder.create<arith::ConstantIndexOp>(
-        buffer.getLoc(), sizeof(uint32_t));
-    Value elementSizeI32 = setterBuilder.create<arith::ConstantIntOp>(
-        buffer.getLoc(), sizeof(uint32_t), 32);
+    Value bufferSize = arith::ConstantIndexOp::create(
+        setterBuilder, buffer.getLoc(), allLoadOps.size() * sizeof(uint32_t));
+    Value elementSizeIndex = arith::ConstantIndexOp::create(
+        setterBuilder, buffer.getLoc(), sizeof(uint32_t));
+    Value elementSizeI32 = arith::ConstantIntOp::create(
+        setterBuilder, buffer.getLoc(), sizeof(uint32_t), 32);
     for (auto [ordinalGlobalOp, valueGlobalOp] :
          llvm::zip_equal(ordinalGlobalOps, valueGlobalOps)) {
       Value loadedOrdinal =
           ordinalGlobalOp.createLoadOp(ordinalGlobalOp.getLoc(), setterBuilder)
               .getLoadedGlobalValue();
-      Value bufferOffset = setterBuilder.create<arith::MulIOp>(
-          loadedOrdinal.getLoc(), loadedOrdinal, elementSizeI32);
-      Value loadedValue = setterBuilder.create<IREE::Util::BufferLoadOp>(
-          valueGlobalOp.getLoc(), loadedOrdinal.getType(), buffer, bufferSize,
-          setterBuilder.create<arith::IndexCastOp>(bufferOffset.getLoc(),
-                                                   setterBuilder.getIndexType(),
-                                                   bufferOffset),
+      Value bufferOffset = arith::MulIOp::create(
+          setterBuilder, loadedOrdinal.getLoc(), loadedOrdinal, elementSizeI32);
+      Value loadedValue = IREE::Util::BufferLoadOp::create(
+          setterBuilder, valueGlobalOp.getLoc(), loadedOrdinal.getType(),
+          buffer, bufferSize,
+          arith::IndexCastOp::create(setterBuilder, bufferOffset.getLoc(),
+                                     setterBuilder.getIndexType(),
+                                     bufferOffset),
           elementSizeIndex);
       valueGlobalOp.createStoreOp(valueGlobalOp.getLoc(), loadedValue,
                                   setterBuilder);
     }
-    setterBuilder.create<func::ReturnOp>(setterOp.getLoc());
+    func::ReturnOp::create(setterBuilder, setterOp.getLoc());
   }
 };
 } // namespace
diff --git a/compiler/src/iree/compiler/Dialect/VMVX/Transforms/ResolveBufferDescriptors.cpp b/compiler/src/iree/compiler/Dialect/VMVX/Transforms/ResolveBufferDescriptors.cpp
index 3c1cd32..952eed7 100644
--- a/compiler/src/iree/compiler/Dialect/VMVX/Transforms/ResolveBufferDescriptors.cpp
+++ b/compiler/src/iree/compiler/Dialect/VMVX/Transforms/ResolveBufferDescriptors.cpp
@@ -249,8 +249,8 @@
     for (int i = 0; i < sourceRank; i++) {
       sizeStrideTypes.push_back(indexType);
     }
-    auto sourceDesc = rewriter.create<GetBufferDescriptorOp>(
-        loc, op.getBaseBuffer().getType(), indexType, sizeStrideTypes,
+    auto sourceDesc = GetBufferDescriptorOp::create(
+        rewriter, loc, op.getBaseBuffer().getType(), indexType, sizeStrideTypes,
         sizeStrideTypes, source);
 
     FailureOr<DescriptorInfo> resultDescriptor =