diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py
--- a/clang/test/lit.cfg.py
+++ b/clang/test/lit.cfg.py
@@ -380,16 +380,15 @@
 elif platform.system() == "AIX":
     config.environment["AIXTHREAD_STK"] = "4194304"
 
-# The llvm-nm tool supports an environment variable "OBJECT_MODE" on AIX OS, which
+# Some tools support an environment variable "OBJECT_MODE" on AIX OS, which
 # controls the kind of objects they will support. If there is no "OBJECT_MODE"
 # environment variable specified, the default behaviour is to support 32-bit
 # objects only. In order to not affect most test cases, which expect to support
 # 32-bit and 64-bit objects by default, set the environment variable
-# "OBJECT_MODE" to 'any' for llvm-nm on AIX OS.
+# "OBJECT_MODE" to '32_64' by default on AIX OS.
 
-if "system-aix" in config.available_features:
-    config.substitutions.append(("llvm-nm", "env OBJECT_MODE=any llvm-nm"))
-    config.substitutions.append(("llvm-ar", "env OBJECT_MODE=any llvm-ar"))
+if 'system-aix' in config.available_features:
+   config.environment["OBJECT_MODE"] = "32_64"
 
 # It is not realistically possible to account for all options that could
 # possibly be present in system and user configuration files, so disable
diff --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h
--- a/llvm/include/llvm/Object/Archive.h
+++ b/llvm/include/llvm/Object/Archive.h
@@ -411,12 +411,17 @@
   uint64_t FirstChildOffset = 0;
   uint64_t LastChildOffset = 0;
   std::string MergedGlobalSymtabBuf;
+  bool Has32BitGlobalSymtab = false;
+  bool Has64BitGlobalSymtab = false;
 
 public:
   BigArchive(MemoryBufferRef Source, Error &Err);
   uint64_t getFirstChildOffset() const override { return FirstChildOffset; }
   uint64_t getLastChildOffset() const { return LastChildOffset; }
   bool isEmpty() const override { return getFirstChildOffset() == 0; }
+
+  bool has32BitGlobalSymtab() { return Has32BitGlobalSymtab; }
+  bool has64BitGlobalSymtab() { return Has64BitGlobalSymtab; }
 };
 
 } // end namespace object
diff --git a/llvm/include/llvm/Object/ArchiveWriter.h b/llvm/include/llvm/Object/ArchiveWriter.h
--- a/llvm/include/llvm/Object/ArchiveWriter.h
+++ b/llvm/include/llvm/Object/ArchiveWriter.h
@@ -40,8 +40,27 @@
 
 Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To);
 
+class WriteSymTabType {
+public:
+  enum BitMode {
+    None,  // Not write Symbol table.
+    Both,  // Write both 32-bit and 64-bit symbol table.
+    Bit32, // Only write the 32-bit symbol table.
+    Bit64  // Only write the 64-bit symbol table.
+  };
+
+  WriteSymTabType(bool PrintSym) { Value = PrintSym ? Both : None; }
+  void operator=(bool PrintSym) { Value = PrintSym ? Both : None; }
+  operator bool() { return Value != None; }
+  void setBitMode(BitMode BM) { Value = BM; }
+  BitMode getBitMode() { return Value; }
+
+private:
+  BitMode Value;
+};
+
 Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
-                   bool WriteSymtab, object::Archive::Kind Kind,
+                   WriteSymTabType WriteSymtab, object::Archive::Kind Kind,
                    bool Deterministic, bool Thin,
                    std::unique_ptr<MemoryBuffer> OldArchiveBuf = nullptr,
                    bool IsEC = false);
@@ -49,8 +68,9 @@
 // writeArchiveToBuffer is similar to writeArchive but returns the Archive in a
 // buffer instead of writing it out to a file.
 Expected<std::unique_ptr<MemoryBuffer>>
-writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers, bool WriteSymtab,
-                     object::Archive::Kind Kind, bool Deterministic, bool Thin);
+writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers,
+                     WriteSymTabType WriteSymtab, object::Archive::Kind Kind,
+                     bool Deterministic, bool Thin);
 }
 
 #endif
diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp
--- a/llvm/lib/Object/Archive.cpp
+++ b/llvm/lib/Object/Archive.cpp
@@ -1392,6 +1392,8 @@
                                   GlobSymtab32Loc, GlobSymtab32Size, "32-bit");
     if (Err)
       return;
+
+    Has32BitGlobalSymtab = true;
   }
 
   if (GlobSymtab64Offset) {
@@ -1400,6 +1402,8 @@
                                   GlobSymtab64Loc, GlobSymtab64Size, "64-bit");
     if (Err)
       return;
+
+    Has64BitGlobalSymtab = true;
   }
 
   SmallVector<GlobalSymtabInfo> SymtabInfos;
diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp
--- a/llvm/lib/Object/ArchiveWriter.cpp
+++ b/llvm/lib/Object/ArchiveWriter.cpp
@@ -680,7 +680,7 @@
 static Expected<std::vector<MemberData>>
 computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
                   object::Archive::Kind Kind, bool Thin, bool Deterministic,
-                  bool NeedSymbols, SymMap *SymMap,
+                  WriteSymTabType NeedSymbols, SymMap *SymMap,
                   ArrayRef<NewArchiveMember> NewMembers) {
   static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
 
@@ -860,7 +860,8 @@
 
 static Error writeArchiveToStream(raw_ostream &Out,
                                   ArrayRef<NewArchiveMember> NewMembers,
-                                  bool WriteSymtab, object::Archive::Kind Kind,
+                                  WriteSymTabType WriteSymtab,
+                                  object::Archive::Kind Kind,
                                   bool Deterministic, bool Thin, bool IsEC) {
   assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode");
 
@@ -1041,11 +1042,17 @@
     // the offset to the 32-bit global symbol table, and the 'GlobSym64Offset'
     // contains the offset to the 64-bit global symbol table.
     uint64_t GlobalSymbolOffset =
-        (WriteSymtab && NumSyms32 > 0) ? MemberTableEndOffset : 0;
+        (WriteSymtab &&
+         (WriteSymtab.getBitMode() != WriteSymTabType::BitMode::Bit64) &&
+         NumSyms32 > 0)
+            ? MemberTableEndOffset
+            : 0;
 
     uint64_t GlobalSymbolOffset64 = 0;
     uint64_t NumSyms64 = NumSyms - NumSyms32;
-    if (WriteSymtab && NumSyms64 > 0) {
+    if (WriteSymtab &&
+        (WriteSymtab.getBitMode() != WriteSymTabType::BitMode::Bit32) &&
+        NumSyms64 > 0) {
       if (GlobalSymbolOffset == 0)
         GlobalSymbolOffset64 = MemberTableEndOffset;
       else
@@ -1121,7 +1128,7 @@
 }
 
 Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
-                   bool WriteSymtab, object::Archive::Kind Kind,
+                   WriteSymTabType WriteSymtab, object::Archive::Kind Kind,
                    bool Deterministic, bool Thin,
                    std::unique_ptr<MemoryBuffer> OldArchiveBuf, bool IsEC) {
   Expected<sys::fs::TempFile> Temp =
@@ -1153,9 +1160,9 @@
 }
 
 Expected<std::unique_ptr<MemoryBuffer>>
-writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers, bool WriteSymtab,
-                     object::Archive::Kind Kind, bool Deterministic,
-                     bool Thin) {
+writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers,
+                     WriteSymTabType WriteSymtab, object::Archive::Kind Kind,
+                     bool Deterministic, bool Thin) {
   SmallVector<char, 0> ArchiveBufferVector;
   raw_svector_ostream ArchiveStream(ArchiveBufferVector);
 
diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py
--- a/llvm/test/lit.cfg.py
+++ b/llvm/test/lit.cfg.py
@@ -642,6 +642,6 @@
 # environment variable specified, the default behaviour is to support 32-bit
 # objects only. In order to not affect most test cases, which expect to support
 # 32-bit and 64-bit objects by default, set the environment variable
-# "OBJECT_MODE" to 'any' by default on AIX OS.
-if "system-aix" in config.available_features:
-    config.environment["OBJECT_MODE"] = "any"
+# "OBJECT_MODE" to '32_64' by default on AIX OS.
+if 'system-aix' in config.available_features:
+    config.environment['OBJECT_MODE'] = '32_64'
diff --git a/llvm/test/tools/llvm-ranlib/aix-X-option.test b/llvm/test/tools/llvm-ranlib/aix-X-option.test
new file mode 100644
--- /dev/null
+++ b/llvm/test/tools/llvm-ranlib/aix-X-option.test
@@ -0,0 +1,130 @@
+## REQUIRES: system-aix
+## Test the -X option.
+## The option specifies the type of object file on which llvm-ranlib will operate.
+
+# RUN: rm -rf %t && mkdir %t && cd %t
+# RUN: yaml2obj --docnum=1 -DFLAG=0x1DF %s -o t32_1.o
+# RUN: yaml2obj --docnum=1 -DFLAG=0x1F7 %s -o t64_1.o
+# RUN: yaml2obj --docnum=2 -DFLAG=0x1DF %s -o t32_2.o
+# RUN: yaml2obj --docnum=2 -DFLAG=0x1F7 %s -o t64_2.o
+
+# RUN: llvm-ar qS t_all.a t32_1.o t64_1.o t32_2.o t64_2.o
+# RUN: cp t_all.a t_X32.a
+# RUN: cp t_all.a t_X64.a
+# RUN: cp t_all.a t_X32_64.a
+
+## Test the OBJECT_MODE environment variable when adding symbol table.
+# RUN: unset OBJECT_MODE
+# RUN: llvm-ranlib t_X32.a
+# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32 --implicit-check-not="in t64" %s
+# RUN: cp t_all.a t_X32.a
+# RUN: env OBJECT_MODE=32 llvm-ranlib t_X32.a
+# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32 --implicit-check-not="in t64" %s
+
+# RUN: env OBJECT_MODE=64 llvm-ranlib t_X64.a
+# RUN: llvm-nm --print-armap t_X64.a 2>&1 | FileCheck --check-prefixes=GLOB64 --implicit-check-not="in t32" %s
+
+# RUN: env OBJECT_MODE=32_64 llvm-ranlib t_X32_64.a
+# RUN: llvm-nm --print-armap t_X32_64.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s
+# RUN: cp t_all.a t_X32_64.a
+# RUN: env OBJECT_MODE=any llvm-ranlib t_X32_64.a
+# RUN: llvm-nm --print-armap t_X32_64.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s
+
+# RUN: cp t_all.a t_X32.a
+# RUN: cp t_all.a t_X64.a
+# RUN: cp t_all.a t_X32_64.a
+
+## Test the -X option when adding symbol table.
+# RUN: llvm-ranlib -X32 t_X32.a
+# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32 --implicit-check-not="in t64" %s
+# RUN: llvm-ranlib -X64 t_X32.a
+# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s
+
+# RUN: llvm-ranlib -X64 t_X64.a
+# RUN: llvm-nm --print-armap t_X64.a 2>&1 | FileCheck --check-prefixes=GLOB64 --implicit-check-not="in t32" %s
+# RUN: llvm-ranlib -X32 t_X64.a
+# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s
+
+# RUN: llvm-ranlib -X32_64 t_X32_64.a
+# RUN: llvm-nm --print-armap t_X32_64.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s
+# RUN: cp t_all.a t_X32_64.a
+# RUN: llvm-ranlib -X32_64 t_X32_64.a
+# RUN: llvm-nm --print-armap t_X32_64.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s
+
+# RUN: cp t_all.a t_X32.a
+# RUN: cp t_all.a t_X64.a
+
+## Test that the -X option will override the "OBJECT_MODE" environment variable.
+# RUN: env OBJECT_MODE=32_64 llvm-ranlib -X32 t_X32.a
+# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32 --implicit-check-not="in t64" %s
+
+# RUN: env OBJECT_MODE=32 llvm-ranlib -X64 t_X64.a
+# RUN: llvm-nm --print-armap t_X64.a 2>&1 | FileCheck --check-prefixes=GLOB64 --implicit-check-not="in t32" %s
+
+# GLOB32:      sym1_0x1DF in t32_1.o
+# GLOB32-NEXT: sym2_0x1DF in t32_1.o
+# GLOB32-NEXT: sym3_0x1DF in t32_2.o
+# GLOB32-NEXT: sym4_0x1DF in t32_2.o
+
+# GLOB64:      sym1_0x1F7 in t64_1.o
+# GLOB64-NEXT: sym2_0x1F7 in t64_1.o
+# GLOB64-NEXT: sym3_0x1F7 in t64_2.o
+# GLOB64-NEXT: sym4_0x1F7 in t64_2.o
+
+## Test invalid -X option and OBJECT_MODE enviornment var.
+# RUN: not env OBJECT_MODE= llvm-ranlib t_X32.a 2>&1 | FileCheck --implicit-check-not="error:"  --check-prefixes=INVALID-OBJECT-MODE %s
+# RUN: not env OBJECT_MODE="" llvm-ranlib t_X32.a 2>&1 | FileCheck --implicit-check-not="error:"  --check-prefixes=INVALID-OBJECT-MODE %s
+# RUN: not env OBJECT_MODE=31 llvm-ranlib t_X64.a 2>&1 | FileCheck --implicit-check-not="error:"  --check-prefixes=INVALID-OBJECT-MODE %s
+# RUN: not llvm-ranlib -X t_X64.a 2>&1 | FileCheck --implicit-check-not="error:"  --check-prefixes=INVALID-X-OPTION %s
+# RUN: not llvm-ranlib -X31 t_X64.a 2>&1 | FileCheck --implicit-check-not="error:"  --check-prefixes=INVALID-X-OPTION %s
+
+# INVALID-OBJECT-MODE: error: the OBJECT_MODE environment variable has an invalid value. OBJECT_MODE must be 32, 64, 32_64, or any
+# INVALID-X-OPTION: error: the specified object mode is not valid. Specify -X32, -X64, -X32_64, or -Xany
+
+--- !XCOFF
+FileHeader:
+  MagicNumber:       [[FLAG]]
+Sections:
+  - Name:            .data
+    Flags:           [ STYP_DATA ]
+Symbols:
+  - Name:            sym1_[[FLAG]]
+    Section:         .data
+    Type:            0x4000
+    StorageClass:    C_EXT
+    AuxEntries:
+     - Type:                   AUX_CSECT
+       SymbolAlignmentAndType: 0x09
+       StorageMappingClass:    XMC_RW
+  - Name:            sym2_[[FLAG]]
+    Section:         .data
+    Type:            0x4000
+    StorageClass:    C_EXT
+    AuxEntries:
+     - Type:                   AUX_CSECT
+       SymbolAlignmentAndType: 0x09
+       StorageMappingClass:    XMC_RW
+
+--- !XCOFF
+FileHeader:
+  MagicNumber:       [[FLAG]]
+Sections:
+  - Name:            .text
+    Flags:           [ STYP_DATA ]
+Symbols:
+  - Name:            sym3_[[FLAG]]
+    Section:         .text
+    Type:            0x4000
+    StorageClass:    C_EXT
+    AuxEntries:
+     - Type:                   AUX_CSECT
+       SymbolAlignmentAndType: 0x09
+       StorageMappingClass:    XMC_PR
+  - Name:            sym4_[[FLAG]]
+    Section:         .text
+    Type:            0x4000
+    StorageClass:    C_EXT
+    AuxEntries:
+     - Type:                   AUX_CSECT
+       SymbolAlignmentAndType: 0x09
+       StorageMappingClass:    XMC_PR
diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp
--- a/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -61,15 +61,18 @@
 static StringRef Stem;
 
 static void printRanLibHelp(StringRef ToolName) {
-  outs() << "OVERVIEW: LLVM ranlib\n\n"
-         << "Generate an index for archives\n\n"
-         << "USAGE: " + ToolName + " archive...\n\n"
-         << "OPTIONS:\n"
-         << "  -h --help             - Display available options\n"
-         << "  -v --version          - Display the version of this program\n"
-         << "  -D                    - Use zero for timestamps and uids/gids "
-            "(default)\n"
-         << "  -U                    - Use actual timestamps and uids/gids\n";
+  outs()
+      << "OVERVIEW: LLVM ranlib\n\n"
+      << "Generate an index for archives\n\n"
+      << "USAGE: " + ToolName + " archive...\n\n"
+      << "OPTIONS:\n"
+      << "  -h --help             - Display available options\n"
+      << "  -v --version          - Display the version of this program\n"
+      << "  -D                    - Use zero for timestamps and uids/gids "
+         "(default)\n"
+      << "  -U                    - Use actual timestamps and uids/gids\n"
+      << "  -X{32|64|32_64|any}       - Specifies which archive symbol tables "
+         "should be generated if they do not already exist (AIX OS only)\n";
 }
 
 static void printArHelp(StringRef ToolName) {
@@ -225,7 +228,7 @@
 static bool CompareFullPath = false;      ///< 'P' modifier
 static bool OnlyUpdate = false;           ///< 'u' modifier
 static bool Verbose = false;              ///< 'v' modifier
-static bool Symtab = true;                ///< 's' modifier
+static WriteSymTabType Symtab = true;     ///< 's' modifier
 static bool Deterministic = true;         ///< 'D' and 'U' modifiers
 static bool Thin = false;                 ///< 'T' modifier
 static bool AddLibrary = false;           ///< 'L' modifier
@@ -1074,9 +1077,27 @@
   // In summary, we only need to update the symbol table if we have none.
   // This is actually very common because of broken build systems that think
   // they have to run ranlib.
-  if (OldArchive->hasSymbolTable())
-    return;
+  if (OldArchive->hasSymbolTable()) {
+    if (OldArchive->kind() != object::Archive::K_AIXBIG)
+      return;
 
+    // For archives in the Big Archive format, the bit mode option specifies
+    // which symbol table to generate. The presence of a symbol table that does
+    // not match the specified bit mode does not prevent creation of the symbol
+    // table that has been requested.
+    if (OldArchive->kind() == object::Archive::K_AIXBIG) {
+      BigArchive *BigArc = dyn_cast<BigArchive>(OldArchive);
+      if (BigArc->has32BitGlobalSymtab() &&
+          Symtab.getBitMode() == WriteSymTabType::BitMode::Bit32)
+        return;
+
+      if (BigArc->has64BitGlobalSymtab() &&
+          Symtab.getBitMode() == WriteSymTabType::BitMode::Bit64)
+        return;
+
+      Symtab.setBitMode(WriteSymTabType::BitMode::Both);
+    }
+  }
   if (OldArchive->isThin())
     Thin = true;
   performWriteOperation(CreateSymTab, OldArchive, nullptr, nullptr);
@@ -1389,6 +1410,8 @@
 
 static int ranlib_main(int argc, char **argv) {
   std::vector<StringRef> Archives;
+
+  bool HasAIXXOption = false;
   for (int i = 1; i < argc; ++i) {
     StringRef arg(argv[i]);
     if (handleGenericOption(arg)) {
@@ -1406,6 +1429,29 @@
         } else if (arg.front() == 'v') {
           cl::PrintVersionMessage();
           return 0;
+        } else if (arg.front() == 'X') {
+          if (object::Archive::getDefaultKindForHost() ==
+              object::Archive::K_AIXBIG) {
+            HasAIXXOption = true;
+            arg.consume_front("X");
+            const char *Xarg = arg.data();
+            if (Xarg[0] == '\0') {
+              if (argv[i + 1][0] != '-')
+                BitMode = getBitMode(argv[++i]);
+              else
+                BitMode = BitModeTy::Unknown;
+            } else
+              BitMode = getBitMode(arg.data());
+
+            if (BitMode == BitModeTy::Unknown)
+              fail(
+                  Twine("the specified object mode is not valid. Specify -X32, "
+                        "-X64, -X32_64, or -Xany"));
+          } else {
+            fail(Twine("-") + Twine(arg) +
+                 " option not supported on non AIX OS");
+          }
+          break;
         } else {
           // TODO: GNU ranlib also supports a -t flag
           fail("Invalid option: '-" + arg + "'");
@@ -1417,6 +1463,32 @@
     }
   }
 
+  if (object::Archive::getDefaultKindForHost() == object::Archive::K_AIXBIG) {
+    // If not specify -X option, get BitMode from enviorment variable
+    // "OBJECT_MODE" for AIX OS if specify.
+    if (!HasAIXXOption) {
+      char *EnvObjectMode = getenv("OBJECT_MODE");
+      if (EnvObjectMode) {
+        BitMode = getBitMode(EnvObjectMode);
+        if (BitMode == BitModeTy::Unknown)
+          fail("the OBJECT_MODE environment variable has an invalid value. "
+               "OBJECT_MODE must be 32, 64, 32_64, or any");
+      }
+    }
+
+    switch (BitMode) {
+    case BitModeTy::Bit32:
+      Symtab.setBitMode(WriteSymTabType::BitMode::Bit32);
+      break;
+    case BitModeTy::Bit64:
+      Symtab.setBitMode(WriteSymTabType::BitMode::Bit64);
+      break;
+    default:
+      Symtab = true;
+      break;
+    }
+  }
+
   for (StringRef Archive : Archives) {
     ArchiveName = Archive.str();
     performOperation(CreateSymTab);