XXX
diff --git a/mlir/include/mlir/Dialect/MemRef/IR/MemRef.h b/mlir/include/mlir/Dialect/MemRef/IR/MemRef.h
index ac383ab..d9a6f51 100644
--- a/mlir/include/mlir/Dialect/MemRef/IR/MemRef.h
+++ b/mlir/include/mlir/Dialect/MemRef/IR/MemRef.h
@@ -12,6 +12,7 @@
 #include "mlir/Bytecode/BytecodeOpInterface.h"
 #include "mlir/Dialect/Arith/IR/Arith.h"
 #include "mlir/Dialect/Utils/ReshapeOpsUtils.h"
+#include "mlir/IR/BuiltinEnums.h"
 #include "mlir/IR/Dialect.h"
 #include "mlir/Interfaces/CallInterfaces.h"
 #include "mlir/Interfaces/CastInterfaces.h"
diff --git a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td
index 9321089a..1dcf0d9 100644
--- a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td
+++ b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td
@@ -154,7 +154,7 @@
       The `assume_alignment` operation takes a memref and an integer alignment
       value. It returns a new SSA value of the same memref type, but associated
       with the assumption that the underlying buffer is aligned to the given
-      alignment. 
+      alignment.
 
       If the buffer isn't aligned to the given alignment, its result is poison.
       This operation doesn't affect the semantics of a program where the
@@ -169,7 +169,7 @@
   let assemblyFormat = "$memref `,` $alignment attr-dict `:` type($memref)";
   let extraClassDeclaration = [{
     MemRefType getType() { return ::llvm::cast<MemRefType>(getResult().getType()); }
-    
+
     Value getViewSource() { return getMemref(); }
   }];
 
@@ -1160,7 +1160,7 @@
   }];
 
   let arguments = (ins SymbolNameAttr:$sym_name,
-                       OptionalAttr<StrAttr>:$sym_visibility,
+                       OptionalAttr<SymbolVisibilityAttr>:$sym_visibility,
                        MemRefTypeAttr:$type,
                        OptionalAttr<AnyAttr>:$initial_value,
                        UnitAttr:$constant,
diff --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td
index b67b8f9..2fac191 100644
--- a/mlir/include/mlir/IR/BuiltinAttributes.td
+++ b/mlir/include/mlir/IR/BuiltinAttributes.td
@@ -15,6 +15,7 @@
 #define BUILTIN_ATTRIBUTES
 
 include "mlir/IR/AttrTypeBase.td"
+include "mlir/IR/EnumAttr.td"
 include "mlir/IR/BuiltinDialect.td"
 include "mlir/IR/BuiltinAttributeInterfaces.td"
 include "mlir/IR/OpAsmInterface.td"
@@ -1203,6 +1204,47 @@
 }
 
 //===----------------------------------------------------------------------===//
+// SymbolVisibilityAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_SymbolVisibilityAttr : I32EnumAttr<
+  "SymbolVisibility", "sym_visibility", [
+    I32EnumAttrCase<"Public", 0, "public">,
+    I32EnumAttrCase<"Private", 1, "private">,
+    I32EnumAttrCase<"Nested", 2, "nested">
+]> {
+  let summary = "An Attribute representing the visibility of a symbol";
+  let description = [{
+    Syntax:
+
+    ```
+    symbol-visibility-attribute ::= `public` | `private` | `nested`
+    ```
+
+    The visibility of a symbol defines its structural reachability within the
+    IR. A symbol has one of the following visibilities:
+
+    - Public (Default): The symbol may be referenced from outside of the visible
+    IR. We cannot assume that all of the uses of this symbol are observable. If
+    the operation declares a symbol (as opposed to defining it), public
+    visibility is not allowed because symbol declarations are not intended to be
+    used from outside the visible IR.
+
+    - Private: The symbol may only be referenced from within the current symbol
+    table.
+
+    - Nested: The symbol may be referenced by operations outside of the current
+    symbol table, but not outside of the visible IR, as long as each symbol
+    table parent also defines a non-private symbol.
+
+    See [`Symbols And SymbolTables`](../SymbolsAndSymbolTables.md) for more
+    information.
+  }];
+
+  let cppNamespace = "mlir";
+}
+
+//===----------------------------------------------------------------------===//
 // TypeAttr
 //===----------------------------------------------------------------------===//
 
diff --git a/mlir/include/mlir/IR/BuiltinEnums.h b/mlir/include/mlir/IR/BuiltinEnums.h
new file mode 100644
index 0000000..4f64fd9
--- /dev/null
+++ b/mlir/include/mlir/IR/BuiltinEnums.h
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_IR_BUILTINENUMS_H
+#define MLIR_IR_BUILTINENUMS_H
+
+//===----------------------------------------------------------------------===//
+// Tablegen Enums Declarations
+//===----------------------------------------------------------------------===//
+
+namespace mlir {
+
+#define GET_ENUM_ATTRDEF_CLASSES
+#include "mlir/IR/BuiltinAttributesEnums.h.inc"
+
+} // namespace mlir
+
+
+#endif // MLIR_IR_BUILTIENUMS_H
diff --git a/mlir/include/mlir/IR/CMakeLists.txt b/mlir/include/mlir/IR/CMakeLists.txt
index 846547f..6f0c35c 100644
--- a/mlir/include/mlir/IR/CMakeLists.txt
+++ b/mlir/include/mlir/IR/CMakeLists.txt
@@ -16,6 +16,11 @@
 mlir_tablegen(BuiltinAttributes.cpp.inc -gen-attrdef-defs)
 add_public_tablegen_target(MLIRBuiltinAttributesIncGen)
 
+set(LLVM_TARGET_DEFINITIONS BuiltinAttributes.td)
+mlir_tablegen(BuiltinAttributesEnums.h.inc -gen-enum-decls)
+mlir_tablegen(BuiltinAttributesEnums.cpp.inc -gen-enum-defs)
+add_public_tablegen_target(MLIRBuiltinAttributesEnumsGen)
+
 set(LLVM_TARGET_DEFINITIONS BuiltinAttributeInterfaces.td)
 mlir_tablegen(BuiltinAttributeInterfaces.h.inc -gen-attr-interface-decls)
 mlir_tablegen(BuiltinAttributeInterfaces.cpp.inc -gen-attr-interface-defs)
diff --git a/mlir/include/mlir/IR/CommonAttrConstraints.td b/mlir/include/mlir/IR/CommonAttrConstraints.td
index 18da85a..05ea408 100644
--- a/mlir/include/mlir/IR/CommonAttrConstraints.td
+++ b/mlir/include/mlir/IR/CommonAttrConstraints.td
@@ -683,6 +683,16 @@
   let constBuilderCall = ?;
 }
 
+def SymbolVisibilityAttr : Attr<
+    CPred<"::llvm::isa<::mlir::SymbolVisibilityAttr>($_self)">,
+    "symbol visibility attribute"> {
+  let storageType = [{ ::mlir::SymbolVisibilityAttr }];
+  let returnType = [{ ::mlir::SymbolVisibilityAttr }];
+  let valueType = NoneType;
+  let constBuilderCall = "::mlir::SymbolVisibilityAttr::get($_builder.getContext(), $0)";
+  let convertFromStorage = "$_self";
+}
+
 //===----------------------------------------------------------------------===//
 // Derive attribute kinds
 //===----------------------------------------------------------------------===//