diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCLOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCLOps.td
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCLOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCLOps.td
@@ -73,6 +73,18 @@
   let hasVerifier = 0;
 }
 
+// Base class for OpenCL misc ops.
+class SPIRV_CLMiscOp<string mnemonic, int opcode, Type resultType,
+                     list<Trait> traits = []> :
+  SPIRV_CLOp<mnemonic, opcode, !listconcat([Pure], traits)> {
+
+  let results = (outs
+    SPIRV_ScalarOrVectorOf<resultType>:$result
+  );
+
+  let hasVerifier = 0;
+}
+
 // Base class for OpenCL Binary arithmetic ops where operand types and
 // return type matches.
 class SPIRV_CLBinaryArithmeticOp<string mnemonic, int opcode, Type type,
@@ -777,4 +789,44 @@
   }];
 }
 
+def SPIRV_CLPrintfOp : SPIRV_CLMiscOp<"printf", 184, SPIRV_Integer > {
+  let summary = [{
+    The printf extended instruction writes output to an implementation-
+    defined stream such as stdout under control of the string pointed to by
+    format that specifies how subsequent arguments are converted for output.
+    If there are insufficient arguments for the format, the behavior is
+    undefined. If the format is exhausted while arguments remain, the excess
+    arguments are evaluated (as always) but are otherwise ignored.  The
+    printf instruction returns when the end of the format string is
+    encountered
+  }];
+
+  let description = [{
+    printf returns 0 if it was executed successfully and -1 otherwise
+
+    Result Type must be i32.
+
+    format must be a pointer(constant) to i8.
+
+    <!-- End of AutoGen section -->
+
+    #### Example:
+
+    ```mlir
+    %0 = spirv.CL.printf %0 %1 %2 : (!spirv.ptr<i8, UniformConstant>, (i32, i32)) -> i32
+
+    ```
+  }];
+
+  let arguments = (ins
+    SPIRV_AnyPtr:$format,
+    Variadic<SPIRV_Type>:$arguments
+  );
+
+  let assemblyFormat = [{
+  $format `,` $arguments  attr-dict `:`  `(` type($format) `,` `(` type($arguments) `)` `)` `->` type($result)
+  }];
+
+  let hasVerifier = 0;
+}
 #endif // MLIR_DIALECT_SPIRV_IR_CL_OPS
diff --git a/mlir/test/Dialect/SPIRV/IR/ocl-ops.mlir b/mlir/test/Dialect/SPIRV/IR/ocl-ops.mlir
--- a/mlir/test/Dialect/SPIRV/IR/ocl-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/ocl-ops.mlir
@@ -247,3 +247,16 @@
   %0 = spirv.CL.rint %arg0 : vector<3xf16>
   return
 }
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.CL.printf
+//===----------------------------------------------------------------------===//
+// CHECK-LABEL: func.func @printf(
+func.func @printf(%arg0 : !spirv.ptr<i8, UniformConstant>, %arg1 : i32, %arg2 : i32) -> i32 {
+  // CHECK: spirv.CL.printf {{%.*}}, {{%.*}}, {{%.*}} : (!spirv.ptr<i8, UniformConstant>, (i32, i32)) -> i32
+  %0 = spirv.CL.printf %arg0, %arg1, %arg2 : (!spirv.ptr<i8, UniformConstant>, (i32, i32)) -> i32
+  return %0 : i32
+}
+