[clang] [MC][RISCV] Add assembly syntax highlighting for RISCV (PR #65853)

Yingwei Zheng via cfe-commits cfe-commits at lists.llvm.org
Sun Sep 10 14:45:13 PDT 2023


=?utf-8?q?Björn_Schäpers?= <bjoern at hazardy.de>,Mehdi Amini
 <joker.eph at gmail.com>,Vitaly Buka <vitalybuka at google.com>,Vitaly Buka
 <vitalybuka at google.com>,Vitaly Buka <vitalybuka at google.com>,Mehdi Amini
 <joker.eph at gmail.com>,Shilei Tian <i at tianshilei.me>,"Kazushi (Jam) Marukawa"
 <marukawa at nec.com>,Fabian Mora <fmora.dev at gmail.com>,Kazushi Marukawa
 <marukawa at nec.com>,Jonas Devlieghere <jonas at devlieghere.com>,Jan Svoboda
 <jan_svoboda at apple.com>,Jan Svoboda <jan_svoboda at apple.com>,Alex Brachet
 <abrachet at google.com>,Jan Svoboda <jan_svoboda at apple.com>,Jan Svoboda
 <jan_svoboda at apple.com>,Jan Svoboda <jan_svoboda at apple.com>,Jan Svoboda
 <jan_svoboda at apple.com>,Jan Svoboda <jan_svoboda at apple.com>,Fangrui Song
 <i at maskray.me>,Matt Arsenault <Matthew.Arsenault at amd.com>,Younan Zhang
 <zyn7109 at gmail.com>,Brad Smith <brad at comstyle.com>,Christian Sigg
 <chsigg at users.noreply.github.com>,David Green <david.green at arm.com>,David
 Green <david.green at arm.com>,Piotr Zegar <me at piotrzegar.pl>,Ignat Loskutov
 <ignat.loskutov at gmail.com>,Alex Brachet <abrachet at google.com>,Congcong Cai
 <congcongcai0907 at 163.com>,Congcong Cai <congcongcai0907 at 163.com>,Jan Svoboda
 <jan_svoboda at apple.com>,Jan Svoboda <jan_svoboda at apple.com>,Yingwei Zheng
 <dtcxzyw2333 at gmail.com>,Simon Pilgrim <llvm-dev at redking.me.uk>,Piotr Zegar
 <me at piotrzegar.pl>,Jan Svoboda <jan_svoboda at apple.com>,Jan Svoboda
 <jan_svoboda at apple.com>,Mark de Wever <koraq at xs4all.nl>,Jan Svoboda
 <jan_svoboda at apple.com>,Jay Foad <jay.foad at amd.com>,Yingwei Zheng
 <dtcxzyw2333 at gmail.com>,Yingwei Zheng <dtcxzyw2333 at gmail.com>,Simon Pilgrim
 <llvm-dev at redking.me.uk>,Yingwei Zheng <dtcxzyw2333 at gmail.com>,Fangrui Song
 <i at maskray.me>,Owen Pan <owenpiano at gmail.com>,Billy Laws <blaws05 at gmail.com>,Fangrui
 Song <i at maskray.me>,Tianlan Zhou <bobby825 at 126.com>,Yingwei Zheng
 <dtcxzyw2333 at gmail.com>


https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/65853:

>From c777bb8674a911a59a8ce70029ca95596b1a63ff Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 10 Sep 2023 01:40:05 +0800
Subject: [PATCH 01/62] [MC][RISCV] Add assembly syntax highlighting for RISCV

---
 .../RISCV/MCTargetDesc/RISCVInstPrinter.cpp   | 45 ++++++++++---------
 llvm/test/MC/Disassembler/RISCV/colored.txt   | 23 ++++++++++
 2 files changed, 47 insertions(+), 21 deletions(-)
 create mode 100644 llvm/test/MC/Disassembler/RISCV/colored.txt

diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
index 8e98abd65aab7b9..d0a77b1248d8c99 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
@@ -16,6 +16,7 @@
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCSymbol.h"
@@ -75,7 +76,7 @@ void RISCVInstPrinter::printInst(const MCInst *MI, uint64_t Address,
 }
 
 void RISCVInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const {
-  O << getRegisterName(Reg);
+  markup(O, Markup::Register) << getRegisterName(Reg);
 }
 
 void RISCVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
@@ -90,7 +91,7 @@ void RISCVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
   }
 
   if (MO.isImm()) {
-    O << MO.getImm();
+    markup(O, Markup::Immediate) << MO.getImm();
     return;
   }
 
@@ -110,9 +111,9 @@ void RISCVInstPrinter::printBranchOperand(const MCInst *MI, uint64_t Address,
     uint64_t Target = Address + MO.getImm();
     if (!STI.hasFeature(RISCV::Feature64Bit))
       Target &= 0xffffffff;
-    O << formatHex(Target);
+    markup(O, Markup::Target) << formatHex(Target);
   } else {
-    O << MO.getImm();
+    markup(O, Markup::Target) << MO.getImm();
   }
 }
 
@@ -123,11 +124,11 @@ void RISCVInstPrinter::printCSRSystemRegister(const MCInst *MI, unsigned OpNo,
   auto SiFiveReg = RISCVSysReg::lookupSiFiveRegByEncoding(Imm);
   auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
   if (SiFiveReg && SiFiveReg->haveVendorRequiredFeatures(STI.getFeatureBits()))
-    O << SiFiveReg->Name;
+    markup(O, Markup::Register) << SiFiveReg->Name;
   else if (SysReg && SysReg->haveRequiredFeatures(STI.getFeatureBits()))
-    O << SysReg->Name;
+    markup(O, Markup::Register) << SysReg->Name;
   else
-    O << Imm;
+    markup(O, Markup::Register) << Imm;
 }
 
 void RISCVInstPrinter::printFenceArg(const MCInst *MI, unsigned OpNo,
@@ -162,11 +163,11 @@ void RISCVInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNo,
                                          raw_ostream &O) {
   unsigned Imm = MI->getOperand(OpNo).getImm();
   if (Imm == 1) {
-    O << "min";
+    markup(O, Markup::Immediate) << "min";
   } else if (Imm == 30) {
-    O << "inf";
+    markup(O, Markup::Immediate) << "inf";
   } else if (Imm == 31) {
-    O << "nan";
+    markup(O, Markup::Immediate) << "nan";
   } else {
     float FPVal = RISCVLoadFPImm::getFPImm(Imm);
     // If the value is an integer, print a .0 fraction. Otherwise, use %g to
@@ -174,9 +175,9 @@ void RISCVInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNo,
     // if it is shorter than printing as a decimal. The smallest value requires
     // 12 digits of precision including the decimal.
     if (FPVal == (int)(FPVal))
-      O << format("%.1f", FPVal);
+      markup(O, Markup::Immediate) << format("%.1f", FPVal);
     else
-      O << format("%.12g", FPVal);
+      markup(O, Markup::Immediate) << format("%.12g", FPVal);
   }
 }
 
@@ -208,19 +209,20 @@ void RISCVInstPrinter::printVTypeI(const MCInst *MI, unsigned OpNo,
 void RISCVInstPrinter::printRlist(const MCInst *MI, unsigned OpNo,
                                   const MCSubtargetInfo &STI, raw_ostream &O) {
   unsigned Imm = MI->getOperand(OpNo).getImm();
-  O << "{";
+  auto OS = markup(O, Markup::Register);
+  OS << "{";
   switch (Imm) {
   case RISCVZC::RLISTENCODE::RA:
-    O << (ArchRegNames ? "x1" : "ra");
+    OS << (ArchRegNames ? "x1" : "ra");
     break;
   case RISCVZC::RLISTENCODE::RA_S0:
-    O << (ArchRegNames ? "x1, x8" : "ra, s0");
+    OS << (ArchRegNames ? "x1, x8" : "ra, s0");
     break;
   case RISCVZC::RLISTENCODE::RA_S0_S1:
-    O << (ArchRegNames ? "x1, x8-x9" : "ra, s0-s1");
+    OS << (ArchRegNames ? "x1, x8-x9" : "ra, s0-s1");
     break;
   case RISCVZC::RLISTENCODE::RA_S0_S2:
-    O << (ArchRegNames ? "x1, x8-x9, x18" : "ra, s0-s2");
+    OS << (ArchRegNames ? "x1, x8-x9, x18" : "ra, s0-s2");
     break;
   case RISCVZC::RLISTENCODE::RA_S0_S3:
   case RISCVZC::RLISTENCODE::RA_S0_S4:
@@ -229,16 +231,16 @@ void RISCVInstPrinter::printRlist(const MCInst *MI, unsigned OpNo,
   case RISCVZC::RLISTENCODE::RA_S0_S7:
   case RISCVZC::RLISTENCODE::RA_S0_S8:
   case RISCVZC::RLISTENCODE::RA_S0_S9:
-    O << (ArchRegNames ? "x1, x8-x9, x18-" : "ra, s0-")
-      << getRegisterName(RISCV::X19 + (Imm - RISCVZC::RLISTENCODE::RA_S0_S3));
+    OS << (ArchRegNames ? "x1, x8-x9, x18-" : "ra, s0-")
+       << getRegisterName(RISCV::X19 + (Imm - RISCVZC::RLISTENCODE::RA_S0_S3));
     break;
   case RISCVZC::RLISTENCODE::RA_S0_S11:
-    O << (ArchRegNames ? "x1, x8-x9, x18-x27" : "ra, s0-s11");
+    OS << (ArchRegNames ? "x1, x8-x9, x18-x27" : "ra, s0-s11");
     break;
   default:
     llvm_unreachable("invalid register list");
   }
-  O << "}";
+  OS << "}";
 }
 
 void RISCVInstPrinter::printSpimm(const MCInst *MI, unsigned OpNo,
@@ -256,6 +258,7 @@ void RISCVInstPrinter::printSpimm(const MCInst *MI, unsigned OpNo,
   if (Opcode == RISCV::CM_PUSH)
     Spimm = -Spimm;
 
+  auto OS = markup(O, Markup::Immediate);
   RISCVZC::printSpimm(Spimm, O);
 }
 
diff --git a/llvm/test/MC/Disassembler/RISCV/colored.txt b/llvm/test/MC/Disassembler/RISCV/colored.txt
new file mode 100644
index 000000000000000..10d52b525cd90c9
--- /dev/null
+++ b/llvm/test/MC/Disassembler/RISCV/colored.txt
@@ -0,0 +1,23 @@
+# RUN: llvm-mc -triple=riscv64 -mattr=+zcmp,+experimental-zfa --cdis %s | FileCheck %s --strict-whitespace --match-full-lines
+
+# Registers and immediates
+0x03 0xe0 0x40 0x00
+# CHECK:	lwu	zero, 4(ra)
+
+# Branch targets
+0x63 0x00 0xb5 0x04
+# CHECK-NEXT:	beq	a0, a1, 64
+
+# CSRs
+0xf3 0x23 0x10 0xf1
+# CHECK-NEXT:	csrr	t2, mvendorid
+
+# FP immediates
+0xd3 0x00 0x1f 0xf0
+# CHECK-NEXT:	fli.s	ft1, inf
+0xd3 0x80 0x1e 0xf0
+# CHECK-NEXT:	fli.s	ft1, 65536.0
+
+# Rlist and spimm
+0x62 0xbe
+# CHECK-NEXT:	cm.popret	{ra, s0-s1}, 32

>From 3709c82383434302dc6265d7b3ea39b6344f831b Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Fri, 8 Sep 2023 21:37:04 -0700
Subject: [PATCH 02/62] [clang] NFCI: Use `FileEntryRef` in
 `diagnoseFrameworkInclude()`

---
 clang/lib/Lex/HeaderSearch.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp
index f5f4bbf85fa92c2..ec7cb583b6f810c 100644
--- a/clang/lib/Lex/HeaderSearch.cpp
+++ b/clang/lib/Lex/HeaderSearch.cpp
@@ -818,7 +818,7 @@ static bool isFrameworkStylePath(StringRef Path, bool &IsPrivateHeader,
 static void
 diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc,
                          StringRef Includer, StringRef IncludeFilename,
-                         const FileEntry *IncludeFE, bool isAngled = false,
+                         FileEntryRef IncludeFE, bool isAngled = false,
                          bool FoundByHeaderMap = false) {
   bool IsIncluderPrivateHeader = false;
   SmallString<128> FromFramework, ToFramework;
@@ -828,7 +828,7 @@ diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc,
     return;
   bool IsIncludeePrivateHeader = false;
   bool IsIncludeeInFramework =
-      isFrameworkStylePath(IncludeFE->getName(), IsIncludeePrivateHeader,
+      isFrameworkStylePath(IncludeFE.getName(), IsIncludeePrivateHeader,
                            ToFramework, ToIncludeSpelling);
 
   if (!isAngled && !FoundByHeaderMap) {
@@ -965,7 +965,7 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
         if (First) {
           diagnoseFrameworkInclude(Diags, IncludeLoc,
                                    IncluderAndDir.second.getName(), Filename,
-                                   &FE->getFileEntry());
+                                   *FE);
           return FE;
         }
 
@@ -1119,9 +1119,9 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
 
     bool FoundByHeaderMap = !IsMapped ? false : *IsMapped;
     if (!Includers.empty())
-      diagnoseFrameworkInclude(
-          Diags, IncludeLoc, Includers.front().second.getName(), Filename,
-          &File->getFileEntry(), isAngled, FoundByHeaderMap);
+      diagnoseFrameworkInclude(Diags, IncludeLoc,
+                               Includers.front().second.getName(), Filename,
+                               *File, isAngled, FoundByHeaderMap);
 
     // Remember this location for the next lookup we do.
     cacheLookupSuccess(CacheLookup, It, IncludeLoc);

>From 449f95d722b9a9a89e5234416c2587ba1f2d1c7a Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 08:43:26 -0700
Subject: [PATCH 03/62] [clang] NFCI: Use `FileEntryRef` in `ModuleMapParser`

---
 clang/include/clang/Lex/ModuleMap.h |  2 +-
 clang/lib/Lex/HeaderSearch.cpp      | 14 ++++++--------
 clang/lib/Lex/ModuleMap.cpp         |  8 ++++----
 3 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h
index 8f3f234036d26c0..05f30dd2eaa373f 100644
--- a/clang/include/clang/Lex/ModuleMap.h
+++ b/clang/include/clang/Lex/ModuleMap.h
@@ -721,7 +721,7 @@ class ModuleMap {
   ///        that caused us to load this module map file, if any.
   ///
   /// \returns true if an error occurred, false otherwise.
-  bool parseModuleMapFile(const FileEntry *File, bool IsSystem,
+  bool parseModuleMapFile(FileEntryRef File, bool IsSystem,
                           DirectoryEntryRef HomeDir, FileID ID = FileID(),
                           unsigned *Offset = nullptr,
                           SourceLocation ExternModuleLoc = SourceLocation());
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp
index ec7cb583b6f810c..699cd9ae03adc51 100644
--- a/clang/lib/Lex/HeaderSearch.cpp
+++ b/clang/lib/Lex/HeaderSearch.cpp
@@ -1660,8 +1660,8 @@ bool HeaderSearch::findUsableModuleForFrameworkHeader(
   return true;
 }
 
-static const FileEntry *getPrivateModuleMap(FileEntryRef File,
-                                            FileManager &FileMgr) {
+static OptionalFileEntryRef getPrivateModuleMap(FileEntryRef File,
+                                                FileManager &FileMgr) {
   StringRef Filename = llvm::sys::path::filename(File.getName());
   SmallString<128>  PrivateFilename(File.getDir().getName());
   if (Filename == "module.map")
@@ -1669,10 +1669,8 @@ static const FileEntry *getPrivateModuleMap(FileEntryRef File,
   else if (Filename == "module.modulemap")
     llvm::sys::path::append(PrivateFilename, "module.private.modulemap");
   else
-    return nullptr;
-  if (auto File = FileMgr.getFile(PrivateFilename))
-    return *File;
-  return nullptr;
+    return std::nullopt;
+  return FileMgr.getOptionalFileRef(PrivateFilename);
 }
 
 bool HeaderSearch::loadModuleMapFile(FileEntryRef File, bool IsSystem,
@@ -1738,8 +1736,8 @@ HeaderSearch::loadModuleMapFileImpl(FileEntryRef File, bool IsSystem,
   }
 
   // Try to load a corresponding private module map.
-  if (const FileEntry *PMMFile = getPrivateModuleMap(File, FileMgr)) {
-    if (ModMap.parseModuleMapFile(PMMFile, IsSystem, Dir)) {
+  if (OptionalFileEntryRef PMMFile = getPrivateModuleMap(File, FileMgr)) {
+    if (ModMap.parseModuleMapFile(*PMMFile, IsSystem, Dir)) {
       LoadedModuleMaps[File] = false;
       return LMM_InvalidModuleMap;
     }
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index f8b767e1b5eb804..7a759a2039d158c 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -1490,7 +1490,7 @@ namespace clang {
     ModuleMap ⤅
 
     /// The current module map file.
-    const FileEntry *ModuleMapFile;
+    FileEntryRef ModuleMapFile;
 
     /// Source location of most recent parsed module declaration
     SourceLocation CurrModuleDeclLoc;
@@ -1562,7 +1562,7 @@ namespace clang {
   public:
     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
                              const TargetInfo *Target, DiagnosticsEngine &Diags,
-                             ModuleMap &Map, const FileEntry *ModuleMapFile,
+                             ModuleMap &Map, FileEntryRef ModuleMapFile,
                              DirectoryEntryRef Directory, bool IsSystem)
         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
           ModuleMapFile(ModuleMapFile), Directory(Directory),
@@ -2095,7 +2095,7 @@ void ModuleMapParser::parseModuleDecl() {
     ActiveModule->NoUndeclaredIncludes = true;
   ActiveModule->Directory = Directory;
 
-  StringRef MapFileName(ModuleMapFile->getName());
+  StringRef MapFileName(ModuleMapFile.getName());
   if (MapFileName.endswith("module.private.modulemap") ||
       MapFileName.endswith("module_private.map")) {
     ActiveModule->ModuleMapIsPrivate = true;
@@ -3077,7 +3077,7 @@ bool ModuleMapParser::parseModuleMapFile() {
   } while (true);
 }
 
-bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
+bool ModuleMap::parseModuleMapFile(FileEntryRef File, bool IsSystem,
                                    DirectoryEntryRef Dir, FileID ID,
                                    unsigned *Offset,
                                    SourceLocation ExternModuleLoc) {

>From ba4fd7759ade22c67372f14f9dd13ff3f3324ca5 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 08:43:50 -0700
Subject: [PATCH 04/62] [clang] NFCI: Use `FileEntryRef` in `ModuleMap`

---
 clang/include/clang/Lex/ModuleMap.h   | 4 ++--
 clang/lib/Lex/ModuleMap.cpp           | 2 +-
 clang/lib/Serialization/ASTReader.cpp | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h
index 05f30dd2eaa373f..a25a790e544e238 100644
--- a/clang/include/clang/Lex/ModuleMap.h
+++ b/clang/include/clang/Lex/ModuleMap.h
@@ -194,7 +194,7 @@ class ModuleMap {
     }
   };
 
-  using AdditionalModMapsSet = llvm::SmallPtrSet<const FileEntry *, 1>;
+  using AdditionalModMapsSet = llvm::SmallPtrSet<FileEntryRef, 1>;
 
 private:
   friend class ModuleMapParser;
@@ -653,7 +653,7 @@ class ModuleMap {
     return &I->second;
   }
 
-  void addAdditionalModuleMapFile(const Module *M, const FileEntry *ModuleMap);
+  void addAdditionalModuleMapFile(const Module *M, FileEntryRef ModuleMap);
 
   /// Resolve all of the unresolved exports in the given module.
   ///
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index 7a759a2039d158c..39af2e8df106a66 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -1339,7 +1339,7 @@ ModuleMap::canonicalizeModuleMapPath(SmallVectorImpl<char> &Path) {
 }
 
 void ModuleMap::addAdditionalModuleMapFile(const Module *M,
-                                           const FileEntry *ModuleMap) {
+                                           FileEntryRef ModuleMap) {
   AdditionalModMaps[M].insert(ModuleMap);
 }
 
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 576da09095002b0..0cfecddc198db5a 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -4096,13 +4096,13 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
     // Check any additional module map files (e.g. module.private.modulemap)
     // that are not in the pcm.
     if (auto *AdditionalModuleMaps = Map.getAdditionalModuleMapFiles(M)) {
-      for (const FileEntry *ModMap : *AdditionalModuleMaps) {
+      for (FileEntryRef ModMap : *AdditionalModuleMaps) {
         // Remove files that match
         // Note: SmallPtrSet::erase is really remove
         if (!AdditionalStoredMaps.erase(ModMap)) {
           if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities))
             Diag(diag::err_module_different_modmap)
-              << F.ModuleName << /*new*/0 << ModMap->getName();
+              << F.ModuleName << /*new*/0 << ModMap.getName();
           return OutOfDate;
         }
       }

>From 315e5492560facdf8609e7eb627b57558eab4d67 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 09:53:34 -0700
Subject: [PATCH 05/62] [clang][tools] Use `FileEntryRef` in
 `include_cleaner::Header`

---
 .../clang-tidy/misc/IncludeCleanerCheck.cpp   |  4 +--
 clang-tools-extra/clangd/IncludeCleaner.cpp   |  2 +-
 .../clangd/unittests/IncludeCleanerTests.cpp  |  7 ++---
 .../include/clang-include-cleaner/Record.h    |  8 +++---
 .../include/clang-include-cleaner/Types.h     |  6 ++---
 .../include-cleaner/lib/Analysis.cpp          |  2 +-
 .../include-cleaner/lib/FindHeaders.cpp       | 26 +++++++++----------
 .../include-cleaner/lib/HTMLReport.cpp        |  2 +-
 .../include-cleaner/lib/Record.cpp            | 14 +++++-----
 .../include-cleaner/lib/Types.cpp             |  6 ++---
 .../unittests/AnalysisTest.cpp                | 24 ++++++++---------
 .../unittests/FindHeadersTest.cpp             | 11 ++++----
 .../unittests/IncludeSpellerTest.cpp          | 11 +++++---
 .../include-cleaner/unittests/RecordTest.cpp  |  4 +--
 .../include-cleaner/unittests/TypesTest.cpp   |  5 ++--
 15 files changed, 68 insertions(+), 64 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
index 8e460cb38826eb1..fed19bdcc291436 100644
--- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -101,7 +101,7 @@ bool IncludeCleanerCheck::shouldIgnore(const include_cleaner::Header &H) {
     case include_cleaner::Header::Verbatim:
       return R.match(H.verbatim());
     case include_cleaner::Header::Physical:
-      return R.match(H.physical()->tryGetRealPathName());
+      return R.match(H.physical().getFileEntry().tryGetRealPathName());
     }
     llvm_unreachable("Unknown Header kind.");
   });
@@ -145,7 +145,7 @@ void IncludeCleanerCheck::check(const MatchFinder::MatchResult &Result) {
              for (const include_cleaner::Header &H : Providers) {
                if (H.kind() == include_cleaner::Header::Physical &&
                    (H.physical() == MainFile ||
-                    H.physical()->getDir() == ResourceDir)) {
+                    H.physical().getDir() == ResourceDir)) {
                  Satisfied = true;
                  continue;
                }
diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp b/clang-tools-extra/clangd/IncludeCleaner.cpp
index a6e01eb72821d22..d3ee7591edf09d8 100644
--- a/clang-tools-extra/clangd/IncludeCleaner.cpp
+++ b/clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -410,7 +410,7 @@ IncludeCleanerFindings computeIncludeCleanerFindings(ParsedAST &AST) {
         for (const auto &H : Providers) {
           if (H.kind() == include_cleaner::Header::Physical &&
               (H.physical() == MainFile || H.physical() == PreamblePatch ||
-               H.physical()->getLastRef().getDir() == ResourceDir)) {
+               H.physical().getDir() == ResourceDir)) {
             Satisfied = true;
             continue;
           }
diff --git a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
index 48c9c3f576640dc..b90bab70c4d90a8 100644
--- a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -167,7 +167,8 @@ TEST(IncludeCleaner, ComputeMissingHeaders) {
   size_t End = llvm::cantFail(positionToOffset(MainFile.code(), Range.end));
   syntax::FileRange BRange{SM.getMainFileID(), static_cast<unsigned int>(Start),
                            static_cast<unsigned int>(End)};
-  include_cleaner::Header Header{*SM.getFileManager().getFile("b.h")};
+  include_cleaner::Header Header{
+      *SM.getFileManager().getOptionalFileRef("b.h")};
   MissingIncludeDiagInfo BInfo{B, BRange, {Header}};
   EXPECT_THAT(Findings.MissingIncludes, ElementsAre(BInfo));
 }
@@ -474,8 +475,8 @@ TEST(IncludeCleaner, IsPreferredProvider) {
   auto &IncludeDef2 = AST.getIncludeStructure().MainFileIncludes[2];
 
   auto &FM = AST.getSourceManager().getFileManager();
-  auto *DeclH = &FM.getOptionalFileRef("decl.h")->getFileEntry();
-  auto *DefH = &FM.getOptionalFileRef("def.h")->getFileEntry();
+  auto DeclH = *FM.getOptionalFileRef("decl.h");
+  auto DefH = *FM.getOptionalFileRef("def.h");
 
   auto Includes = convertIncludes(AST);
   std::vector<include_cleaner::Header> Providers = {
diff --git a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Record.h b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Record.h
index 08bc1dbdfad42aa..2e0b462ce16df10 100644
--- a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Record.h
+++ b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Record.h
@@ -67,10 +67,10 @@ class PragmaIncludes {
 
   /// Returns all direct exporter headers for the given header file.
   /// Returns empty if there is none.
-  llvm::SmallVector<const FileEntry *> getExporters(const FileEntry *File,
-                                                    FileManager &FM) const;
-  llvm::SmallVector<const FileEntry *> getExporters(tooling::stdlib::Header,
-                                                    FileManager &FM) const;
+  llvm::SmallVector<FileEntryRef> getExporters(const FileEntry *File,
+                                               FileManager &FM) const;
+  llvm::SmallVector<FileEntryRef> getExporters(tooling::stdlib::Header,
+                                               FileManager &FM) const;
 
   /// Returns true if the given file is a self-contained file.
   bool isSelfContained(const FileEntry *File) const;
diff --git a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h
index cd3fd8600060b5c..7d5c19872d5a851 100644
--- a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h
+++ b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h
@@ -122,7 +122,7 @@ struct Header {
     Verbatim,
   };
 
-  Header(const FileEntry *FE) : Storage(FE) {}
+  Header(FileEntryRef FE) : Storage(FE) {}
   Header(tooling::stdlib::Header H) : Storage(H) {}
   Header(StringRef VerbatimSpelling) : Storage(VerbatimSpelling) {}
 
@@ -130,7 +130,7 @@ struct Header {
   bool operator==(const Header &RHS) const { return Storage == RHS.Storage; }
   bool operator<(const Header &RHS) const;
 
-  const FileEntry *physical() const { return std::get<Physical>(Storage); }
+  FileEntryRef physical() const { return std::get<Physical>(Storage); }
   tooling::stdlib::Header standard() const {
     return std::get<Standard>(Storage);
   }
@@ -142,7 +142,7 @@ struct Header {
 
 private:
   // Order must match Kind enum!
-  std::variant<const FileEntry *, tooling::stdlib::Header, StringRef> Storage;
+  std::variant<FileEntryRef, tooling::stdlib::Header, StringRef> Storage;
 
   // Disambiguation tag to make sure we can call the right constructor from
   // DenseMapInfo methods.
diff --git a/clang-tools-extra/include-cleaner/lib/Analysis.cpp b/clang-tools-extra/include-cleaner/lib/Analysis.cpp
index 8c6a23d283d3a09..09365c36f9f2c55 100644
--- a/clang-tools-extra/include-cleaner/lib/Analysis.cpp
+++ b/clang-tools-extra/include-cleaner/lib/Analysis.cpp
@@ -95,7 +95,7 @@ analyze(llvm::ArrayRef<Decl *> ASTRoots,
              for (const Header &H : Providers) {
                if (H.kind() == Header::Physical &&
                    (H.physical() == MainFile ||
-                    H.physical()->getDir() == ResourceDir)) {
+                    H.physical().getDir() == ResourceDir)) {
                  Satisfied = true;
                }
                for (const Include *I : Inc.match(H)) {
diff --git a/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp b/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
index f46dae3b3d50cbb..0f91ad57f0c51d3 100644
--- a/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
+++ b/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
@@ -63,7 +63,7 @@ llvm::StringRef basename(llvm::StringRef Header) {
 bool nameMatch(llvm::StringRef DeclName, Header H) {
   switch (H.kind()) {
   case Header::Physical:
-    return basename(H.physical()->getName()).equals_insensitive(DeclName);
+    return basename(H.physical().getName()).equals_insensitive(DeclName);
   case Header::Standard:
     return basename(H.standard().name()).equals_insensitive(DeclName);
   case Header::Verbatim:
@@ -101,7 +101,7 @@ hintedHeadersForStdHeaders(llvm::ArrayRef<tooling::stdlib::Header> Headers,
     Results.emplace_back(H, Hints::PublicHeader | Hints::OriginHeader);
     if (!PI)
       continue;
-    for (const auto *Export : PI->getExporters(H, SM.getFileManager()))
+    for (FileEntryRef Export : PI->getExporters(H, SM.getFileManager()))
       Results.emplace_back(Header(Export), isPublicHeader(Export, *PI));
   }
   // StandardLibrary returns headers in preference order, so only mark the
@@ -186,31 +186,31 @@ llvm::SmallVector<Hinted<Header>> findHeaders(const SymbolLocation &Loc,
   switch (Loc.kind()) {
   case SymbolLocation::Physical: {
     FileID FID = SM.getFileID(SM.getExpansionLoc(Loc.physical()));
-    const FileEntry *FE = SM.getFileEntryForID(FID);
+    OptionalFileEntryRef FE = SM.getFileEntryRefForID(FID);
     if (!FE)
       return {};
     if (!PI)
-      return {{FE, Hints::PublicHeader | Hints::OriginHeader}};
+      return {{*FE, Hints::PublicHeader | Hints::OriginHeader}};
     bool IsOrigin = true;
-    std::queue<const FileEntry *> Exporters;
+    std::queue<FileEntryRef> Exporters;
     while (FE) {
-      Results.emplace_back(FE,
-                           isPublicHeader(FE, *PI) |
+      Results.emplace_back(*FE,
+                           isPublicHeader(*FE, *PI) |
                                (IsOrigin ? Hints::OriginHeader : Hints::None));
-      for (const auto *Export : PI->getExporters(FE, SM.getFileManager()))
+      for (FileEntryRef Export : PI->getExporters(*FE, SM.getFileManager()))
         Exporters.push(Export);
 
-      if (auto Verbatim = PI->getPublic(FE); !Verbatim.empty()) {
+      if (auto Verbatim = PI->getPublic(*FE); !Verbatim.empty()) {
         Results.emplace_back(Verbatim,
                              Hints::PublicHeader | Hints::PreferredHeader);
         break;
       }
-      if (PI->isSelfContained(FE) || FID == SM.getMainFileID())
+      if (PI->isSelfContained(*FE) || FID == SM.getMainFileID())
         break;
 
       // Walkup the include stack for non self-contained headers.
       FID = SM.getDecomposedIncludedLoc(FID).first;
-      FE = SM.getFileEntryForID(FID);
+      FE = SM.getFileEntryRefForID(FID);
       IsOrigin = false;
     }
     // Now traverse provider trees rooted at exporters.
@@ -219,12 +219,12 @@ llvm::SmallVector<Hinted<Header>> findHeaders(const SymbolLocation &Loc,
     // being exported in this header.
     std::set<const FileEntry *> SeenExports;
     while (!Exporters.empty()) {
-      auto *Export = Exporters.front();
+      FileEntryRef Export = Exporters.front();
       Exporters.pop();
       if (!SeenExports.insert(Export).second) // In case of cyclic exports
         continue;
       Results.emplace_back(Export, isPublicHeader(Export, *PI));
-      for (const auto *Export : PI->getExporters(Export, SM.getFileManager()))
+      for (FileEntryRef Export : PI->getExporters(Export, SM.getFileManager()))
         Exporters.push(Export);
     }
     return Results;
diff --git a/clang-tools-extra/include-cleaner/lib/HTMLReport.cpp b/clang-tools-extra/include-cleaner/lib/HTMLReport.cpp
index 1bb4080b7e2b879..195f658a0af9208 100644
--- a/clang-tools-extra/include-cleaner/lib/HTMLReport.cpp
+++ b/clang-tools-extra/include-cleaner/lib/HTMLReport.cpp
@@ -390,7 +390,7 @@ class Reporter {
       OS << "<tr><th>Header</th><td>";
       switch (H.kind()) {
       case Header::Physical:
-        printFilename(H.physical()->getName());
+        printFilename(H.physical().getName());
         break;
       case Header::Standard:
         OS << "stdlib " << H.standard().name();
diff --git a/clang-tools-extra/include-cleaner/lib/Record.cpp b/clang-tools-extra/include-cleaner/lib/Record.cpp
index d7237325f701bb8..f3253fec01bf9a5 100644
--- a/clang-tools-extra/include-cleaner/lib/Record.cpp
+++ b/clang-tools-extra/include-cleaner/lib/Record.cpp
@@ -224,7 +224,7 @@ class PragmaIncludes::RecordPragma : public PPCallbacks, public CommentHandler {
         IncludedHeader = *StandardHeader;
       }
     if (!IncludedHeader && File)
-      IncludedHeader = &File->getFileEntry();
+      IncludedHeader = *File;
     checkForExport(HashFID, HashLine, std::move(IncludedHeader), File);
     checkForKeep(HashLine, File);
   }
@@ -243,7 +243,7 @@ class PragmaIncludes::RecordPragma : public PPCallbacks, public CommentHandler {
       if (IncludedHeader) {
         switch (IncludedHeader->kind()) {
         case Header::Physical:
-          Out->IWYUExportBy[IncludedHeader->physical()->getUniqueID()]
+          Out->IWYUExportBy[IncludedHeader->physical().getUniqueID()]
               .push_back(Top.Path);
           break;
         case Header::Standard:
@@ -393,18 +393,18 @@ llvm::StringRef PragmaIncludes::getPublic(const FileEntry *F) const {
   return It->getSecond();
 }
 
-static llvm::SmallVector<const FileEntry *>
+static llvm::SmallVector<FileEntryRef>
 toFileEntries(llvm::ArrayRef<StringRef> FileNames, FileManager &FM) {
-  llvm::SmallVector<const FileEntry *> Results;
+  llvm::SmallVector<FileEntryRef> Results;
 
   for (auto FName : FileNames) {
     // FIMXE: log the failing cases?
-    if (auto FE = expectedToOptional(FM.getFileRef(FName)))
+    if (auto FE = FM.getOptionalFileRef(FName))
       Results.push_back(*FE);
   }
   return Results;
 }
-llvm::SmallVector<const FileEntry *>
+llvm::SmallVector<FileEntryRef>
 PragmaIncludes::getExporters(const FileEntry *File, FileManager &FM) const {
   auto It = IWYUExportBy.find(File->getUniqueID());
   if (It == IWYUExportBy.end())
@@ -412,7 +412,7 @@ PragmaIncludes::getExporters(const FileEntry *File, FileManager &FM) const {
 
   return toFileEntries(It->getSecond(), FM);
 }
-llvm::SmallVector<const FileEntry *>
+llvm::SmallVector<FileEntryRef>
 PragmaIncludes::getExporters(tooling::stdlib::Header StdHeader,
                              FileManager &FM) const {
   auto It = StdIWYUExportBy.find(StdHeader);
diff --git a/clang-tools-extra/include-cleaner/lib/Types.cpp b/clang-tools-extra/include-cleaner/lib/Types.cpp
index 2061fdc443886c0..cb8a55ed13e5d00 100644
--- a/clang-tools-extra/include-cleaner/lib/Types.cpp
+++ b/clang-tools-extra/include-cleaner/lib/Types.cpp
@@ -48,7 +48,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S) {
 llvm::StringRef Header::resolvedPath() const {
   switch (kind()) {
   case include_cleaner::Header::Physical:
-    return physical()->tryGetRealPathName();
+    return physical().getFileEntry().tryGetRealPathName();
   case include_cleaner::Header::Standard:
     return standard().name().trim("<>\"");
   case include_cleaner::Header::Verbatim:
@@ -60,7 +60,7 @@ llvm::StringRef Header::resolvedPath() const {
 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Header &H) {
   switch (H.kind()) {
   case Header::Physical:
-    return OS << H.physical()->getName();
+    return OS << H.physical().getName();
   case Header::Standard:
     return OS << H.standard().name();
   case Header::Verbatim:
@@ -198,7 +198,7 @@ bool Header::operator<(const Header &RHS) const {
     return kind() < RHS.kind();
   switch (kind()) {
   case Header::Physical:
-    return physical()->getName() < RHS.physical()->getName();
+    return physical().getName() < RHS.physical().getName();
   case Header::Standard:
     return standard().name() < RHS.standard().name();
   case Header::Verbatim:
diff --git a/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp b/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
index 0b03c643a94c1ab..6558b6808768464 100644
--- a/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -112,10 +112,10 @@ TEST_F(WalkUsedTest, Basic) {
 
   TestAST AST(Inputs);
   auto &SM = AST.sourceManager();
-  auto HeaderFile = Header(AST.fileManager().getFile("header.h").get());
-  auto PrivateFile = Header(AST.fileManager().getFile("private.h").get());
+  auto HeaderFile = Header(*AST.fileManager().getOptionalFileRef("header.h"));
+  auto PrivateFile = Header(*AST.fileManager().getOptionalFileRef("private.h"));
   auto PublicFile = Header("\"path/public.h\"");
-  auto MainFile = Header(SM.getFileEntryForID(SM.getMainFileID()));
+  auto MainFile = Header(*SM.getFileEntryRefForID(SM.getMainFileID()));
   auto VectorSTL = Header(*tooling::stdlib::Header::named("<vector>"));
   auto UtilitySTL = Header(*tooling::stdlib::Header::named("<utility>"));
   EXPECT_THAT(
@@ -152,9 +152,9 @@ TEST_F(WalkUsedTest, MultipleProviders) {
 
   TestAST AST(Inputs);
   auto &SM = AST.sourceManager();
-  auto HeaderFile1 = Header(AST.fileManager().getFile("header1.h").get());
-  auto HeaderFile2 = Header(AST.fileManager().getFile("header2.h").get());
-  auto MainFile = Header(SM.getFileEntryForID(SM.getMainFileID()));
+  auto HeaderFile1 = Header(*AST.fileManager().getOptionalFileRef("header1.h"));
+  auto HeaderFile2 = Header(*AST.fileManager().getOptionalFileRef("header2.h"));
+  auto MainFile = Header(*SM.getFileEntryRefForID(SM.getMainFileID()));
   EXPECT_THAT(
       offsetToProviders(AST),
       Contains(Pair(Code.point("foo"),
@@ -173,8 +173,8 @@ TEST_F(WalkUsedTest, MacroRefs) {
   TestAST AST(Inputs);
   auto &SM = AST.sourceManager();
   auto &PP = AST.preprocessor();
-  const auto *HdrFile = SM.getFileManager().getFile("hdr.h").get();
-  auto MainFile = Header(SM.getFileEntryForID(SM.getMainFileID()));
+  auto HdrFile = *SM.getFileManager().getOptionalFileRef("hdr.h");
+  auto MainFile = Header(*SM.getFileEntryRefForID(SM.getMainFileID()));
 
   auto HdrID = SM.translateFile(HdrFile);
 
@@ -490,9 +490,9 @@ TEST_F(WalkUsedTest, TemplateDecls) {
       guard("template<typename T> struct Foo<T*> {};");
   TestAST AST(Inputs);
   auto &SM = AST.sourceManager();
-  const auto *Fwd = SM.getFileManager().getFile("fwd.h").get();
-  const auto *Def = SM.getFileManager().getFile("def.h").get();
-  const auto *Partial = SM.getFileManager().getFile("partial.h").get();
+  auto Fwd = *SM.getFileManager().getOptionalFileRef("fwd.h");
+  auto Def = *SM.getFileManager().getOptionalFileRef("def.h");
+  auto Partial = *SM.getFileManager().getOptionalFileRef("partial.h");
 
   EXPECT_THAT(
       offsetToProviders(AST),
@@ -524,7 +524,7 @@ TEST_F(WalkUsedTest, IgnoresIdentityMacros) {
 
   TestAST AST(Inputs);
   auto &SM = AST.sourceManager();
-  auto MainFile = Header(SM.getFileEntryForID(SM.getMainFileID()));
+  auto MainFile = Header(*SM.getFileEntryRefForID(SM.getMainFileID()));
   EXPECT_THAT(offsetToProviders(AST),
               UnorderedElementsAre(
                   // FIXME: we should have a reference from stdin to header.h
diff --git a/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp b/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp
index 89910e72beb4632..4cdcde1184a0a9e 100644
--- a/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp
@@ -63,8 +63,8 @@ class FindHeadersTest : public testing::Test {
             /*Line=*/1, /*Col=*/1),
         AST->sourceManager(), &PI);
   }
-  const FileEntry *physicalHeader(llvm::StringRef FileName) {
-    return AST->fileManager().getFile(FileName).get();
+  FileEntryRef physicalHeader(llvm::StringRef FileName) {
+    return *AST->fileManager().getOptionalFileRef(FileName);
   };
 };
 
@@ -409,9 +409,10 @@ TEST_F(HeadersForSymbolTest, MainFile) {
   buildAST();
   auto &SM = AST->sourceManager();
   // FIXME: Symbols provided by main file should be treated specially.
-  EXPECT_THAT(headersForFoo(),
-              ElementsAre(physicalHeader("public_complete.h"),
-                          Header(SM.getFileEntryForID(SM.getMainFileID()))));
+  EXPECT_THAT(
+      headersForFoo(),
+      ElementsAre(physicalHeader("public_complete.h"),
+                  Header(*SM.getFileEntryRefForID(SM.getMainFileID()))));
 }
 
 TEST_F(HeadersForSymbolTest, PreferExporterOfPrivate) {
diff --git a/clang-tools-extra/include-cleaner/unittests/IncludeSpellerTest.cpp b/clang-tools-extra/include-cleaner/unittests/IncludeSpellerTest.cpp
index 361320a2f48f38d..a548868071a1229 100644
--- a/clang-tools-extra/include-cleaner/unittests/IncludeSpellerTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/IncludeSpellerTest.cpp
@@ -47,7 +47,8 @@ class DummyIncludeSpeller : public IncludeSpeller {
       return "<bits/stdc++.h>";
     if (Input.H.kind() != Header::Physical)
       return "";
-    llvm::StringRef AbsolutePath = Input.H.physical()->tryGetRealPathName();
+    llvm::StringRef AbsolutePath =
+        Input.H.physical().getFileEntry().tryGetRealPathName();
     std::string RootWithSeparator{testRoot()};
     RootWithSeparator += llvm::sys::path::get_separator();
     if (!AbsolutePath.consume_front(llvm::StringRef{RootWithSeparator}))
@@ -70,10 +71,12 @@ TEST(IncludeSpeller, IsRelativeToTestRoot) {
   const auto *MainFile = AST.sourceManager().getFileEntryForID(
       AST.sourceManager().getMainFileID());
 
-  EXPECT_EQ("\"foo.h\"", spellHeader({Header{*FM.getFile(testPath("foo.h"))},
-                                      HS, MainFile}));
+  EXPECT_EQ("\"foo.h\"",
+            spellHeader({Header{*FM.getOptionalFileRef(testPath("foo.h"))}, HS,
+                         MainFile}));
   EXPECT_EQ("<header.h>",
-            spellHeader({Header{*FM.getFile("dir/header.h")}, HS, MainFile}));
+            spellHeader({Header{*FM.getOptionalFileRef("dir/header.h")}, HS,
+                         MainFile}));
 }
 
 TEST(IncludeSpeller, CanOverrideSystemHeaders) {
diff --git a/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp b/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp
index 69bec04ed60194c..4f3b5c7ace65ebd 100644
--- a/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp
@@ -53,9 +53,9 @@ MATCHER_P(named, N, "") {
 }
 
 MATCHER_P(FileNamed, N, "") {
-  if (arg->tryGetRealPathName() == N)
+  if (arg.getFileEntry().tryGetRealPathName() == N)
     return true;
-  *result_listener << arg->tryGetRealPathName().str();
+  *result_listener << arg.getFileEntry().tryGetRealPathName().str();
   return false;
 }
 
diff --git a/clang-tools-extra/include-cleaner/unittests/TypesTest.cpp b/clang-tools-extra/include-cleaner/unittests/TypesTest.cpp
index 56b5fbe603adb80..609563da488e3b5 100644
--- a/clang-tools-extra/include-cleaner/unittests/TypesTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/TypesTest.cpp
@@ -40,9 +40,8 @@ TEST(RecordedIncludesTest, Match) {
   Inc.add(Include{"vector", B, SourceLocation(), 5});
   Inc.add(Include{"missing", std::nullopt, SourceLocation(), 6});
 
-  EXPECT_THAT(Inc.match(&A.getFileEntry()), ElementsAre(line(1), line(2)));
-  EXPECT_THAT(Inc.match(&B.getFileEntry()),
-              ElementsAre(line(3), line(4), line(5)));
+  EXPECT_THAT(Inc.match(A), ElementsAre(line(1), line(2)));
+  EXPECT_THAT(Inc.match(B), ElementsAre(line(3), line(4), line(5)));
   EXPECT_THAT(Inc.match(*tooling::stdlib::Header::named("<vector>")),
               ElementsAre(line(4), line(5)));
 }

>From d42abdb44b0e24d6101095d0825896234e592493 Mon Sep 17 00:00:00 2001
From: Tyler Lanphear <tylanphear at gmail.com>
Date: Sat, 9 Sep 2023 10:12:42 -0700
Subject: [PATCH 06/62] [GlobalOpt] Handle DL.getAllocaAddrSpace() != 0
 (#65847)

Fix crash on RAUW due to locals and globals having different address
spaces. This is the intent of the original code, but it assumes the
alloca address space is 0. This patch fixes the code to check that the
global's address space matches `DL.getAllocaAddrSpace()` instead.

Fixes #65155
---
 llvm/lib/Transforms/IPO/GlobalOpt.cpp         |  2 +-
 .../global_alloca_diff_addrspaces.ll          | 22 +++++++++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/Transforms/GlobalOpt/global_alloca_diff_addrspaces.ll

diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
index 3be19f46ee8478d..658db532835a504 100644
--- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
@@ -1453,7 +1453,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
   if (!GS.HasMultipleAccessingFunctions &&
       GS.AccessingFunction &&
       GV->getValueType()->isSingleValueType() &&
-      GV->getType()->getAddressSpace() == 0 &&
+      GV->getType()->getAddressSpace() == DL.getAllocaAddrSpace() &&
       !GV->isExternallyInitialized() &&
       GS.AccessingFunction->doesNotRecurse() &&
       isPointerValueDeadOnEntryToFunction(GS.AccessingFunction, GV,
diff --git a/llvm/test/Transforms/GlobalOpt/global_alloca_diff_addrspaces.ll b/llvm/test/Transforms/GlobalOpt/global_alloca_diff_addrspaces.ll
new file mode 100644
index 000000000000000..f3e0a3e78bee4b1
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/global_alloca_diff_addrspaces.ll
@@ -0,0 +1,22 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; RUN: opt -S -passes=globalopt < %s | FileCheck %s
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8"
+
+; Check that we don't convert the global into an alloca if their respective address
+; spaces differ, and the alloca addrspace is non-zero.
+
+ at x = internal global i32 poison
+
+; Function Attrs: norecurse
+define void @test(i32 %0) #0 {
+; CHECK-LABEL: define void @test(
+; CHECK-SAME: i32 [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret void
+;
+entry:
+  store i32 %0, ptr @x, align 4
+  ret void
+}
+
+attributes #0 = { norecurse }

>From 424452062a235adfd2f2bfdca7480c180e99d83e Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Sat, 9 Sep 2023 10:55:31 -0700
Subject: [PATCH 07/62] [llvm] Add CODE_OF_CONDUCT.md (#65816)

Add a CODE_OF_CONDUCT.md file to the root of the repository. The file
itself references the LLVM Community Code of Conduct. GitHub will
recognize this file and put a link to it to the right of the repository,
similar to the license and security policy, making the CoC easier to
discover.
---
 CODE_OF_CONDUCT.md | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 CODE_OF_CONDUCT.md

diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000000..0c653c0601520c7
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,3 @@
+# Code of Conduct
+
+The LLVM Community Code of Conduct can be found at https://llvm.org/docs/CodeOfConduct.html.

>From 0f0ccddf5514a49c2893fc41e90bd4a1dbc8330d Mon Sep 17 00:00:00 2001
From: Joseph Huber <35342157+jhuber6 at users.noreply.github.com>
Date: Sat, 9 Sep 2023 13:27:07 -0500
Subject: [PATCH 08/62] [libc] Implement stdio writing functions for the GPU
 port (#65809)

Summary:
This patch implements fwrite, putc, putchar, and fputc on the GPU. These
are very straightforward, the main difference for the GPU implementation
is that we are currently ignoring `errno`. This patch also introduces a
minimal smoke test for `putc` that is an exact copy of the `puts` test
except we print the string char by char. This also modifies the `fopen`
test to use `fwrite` to mirror its use of `fread` so that it is tested
as well.
---
 libc/config/gpu/entrypoints.txt               |  4 ++
 libc/docs/gpu/support.rst                     |  8 ++-
 libc/src/stdio/CMakeLists.txt                 | 70 ++-----------------
 libc/src/stdio/generic/CMakeLists.txt         | 65 +++++++++++++++++
 libc/src/stdio/{ => generic}/fputc.cpp        |  0
 libc/src/stdio/{ => generic}/fwrite.cpp       |  0
 .../stdio/{ => generic}/fwrite_unlocked.cpp   |  0
 libc/src/stdio/{ => generic}/putc.cpp         |  0
 libc/src/stdio/{ => generic}/putchar.cpp      |  0
 libc/src/stdio/gpu/CMakeLists.txt             | 44 ++++++++++++
 libc/src/stdio/gpu/fputc.cpp                  | 26 +++++++
 libc/src/stdio/gpu/fwrite.cpp                 | 26 +++++++
 libc/src/stdio/gpu/putc.cpp                   | 26 +++++++
 libc/src/stdio/gpu/putchar.cpp                | 26 +++++++
 libc/test/src/stdio/CMakeLists.txt            | 16 ++++-
 libc/test/src/stdio/fopen_test.cpp            |  4 +-
 libc/test/src/stdio/fputc_test.cpp            | 30 ++++++++
 17 files changed, 275 insertions(+), 70 deletions(-)
 rename libc/src/stdio/{ => generic}/fputc.cpp (100%)
 rename libc/src/stdio/{ => generic}/fwrite.cpp (100%)
 rename libc/src/stdio/{ => generic}/fwrite_unlocked.cpp (100%)
 rename libc/src/stdio/{ => generic}/putc.cpp (100%)
 rename libc/src/stdio/{ => generic}/putchar.cpp (100%)
 create mode 100644 libc/src/stdio/gpu/fputc.cpp
 create mode 100644 libc/src/stdio/gpu/fwrite.cpp
 create mode 100644 libc/src/stdio/gpu/putc.cpp
 create mode 100644 libc/src/stdio/gpu/putchar.cpp
 create mode 100644 libc/test/src/stdio/fputc_test.cpp

diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt
index bf59ba6b0a3eaa6..0e314c60870c6ae 100644
--- a/libc/config/gpu/entrypoints.txt
+++ b/libc/config/gpu/entrypoints.txt
@@ -88,6 +88,10 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdio.fclose
     libc.src.stdio.fread
     libc.src.stdio.fputs
+    libc.src.stdio.fwrite
+    libc.src.stdio.fputc
+    libc.src.stdio.putc
+    libc.src.stdio.putchar
     libc.src.stdio.stdin
     libc.src.stdio.stdout
     libc.src.stdio.stderr
diff --git a/libc/docs/gpu/support.rst b/libc/docs/gpu/support.rst
index 3e8de03050332d1..fabdfb968a741ad 100644
--- a/libc/docs/gpu/support.rst
+++ b/libc/docs/gpu/support.rst
@@ -118,20 +118,24 @@ strtoumax      |check|
 =============  =========  ============
 
 stdio.h
---------
+-------
 
 =============  =========  ============
 Function Name  Available  RPC Required
 =============  =========  ============
 puts           |check|    |check|
 fputs          |check|    |check|
+fputc          |check|    |check|
+fwrite         |check|    |check|
+putc           |check|    |check|
+putchar        |check|    |check|
 fclose         |check|    |check|
 fopen          |check|    |check|
 fread          |check|    |check|
 =============  =========  ============
 
 time.h
---------
+------
 
 =============  =========  ============
 Function Name  Available  RPC Required
diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt
index 79863f83c1e5e7d..740ec106da2e4d7 100644
--- a/libc/src/stdio/CMakeLists.txt
+++ b/libc/src/stdio/CMakeLists.txt
@@ -229,71 +229,6 @@ add_entrypoint_object(
     libc.src.__support.File.platform_file
 )
 
-add_entrypoint_object(
-  fwrite_unlocked
-  SRCS
-    fwrite_unlocked.cpp
-  HDRS
-    fwrite_unlocked.h
-  DEPENDS
-    libc.src.errno.errno
-    libc.include.stdio
-    libc.src.__support.File.file
-    libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
-  fwrite
-  SRCS
-    fwrite.cpp
-  HDRS
-    fwrite.h
-  DEPENDS
-    libc.src.errno.errno
-    libc.include.stdio
-    libc.src.__support.File.file
-    libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
-  fputc
-  SRCS
-    fputc.cpp
-  HDRS
-    fputc.h
-  DEPENDS
-    libc.src.errno.errno
-    libc.include.stdio
-    libc.src.__support.File.file
-    libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
-  putc
-  SRCS
-    putc.cpp
-  HDRS
-    putc.h
-  DEPENDS
-    libc.src.errno.errno
-    libc.include.stdio
-    libc.src.__support.File.file
-    libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
-  putchar
-  SRCS
-    putchar.cpp
-  HDRS
-    putchar.h
-  DEPENDS
-    libc.src.errno.errno
-    libc.include.stdio
-    libc.src.__support.File.file
-    libc.src.__support.File.platform_file
-)
-
 add_entrypoint_object(
   fseek
   SRCS
@@ -538,6 +473,11 @@ add_stdio_entrypoint_object(fread_unlocked)
 add_stdio_entrypoint_object(fread)
 add_stdio_entrypoint_object(puts)
 add_stdio_entrypoint_object(fputs)
+add_stdio_entrypoint_object(fwrite_unlocked)
+add_stdio_entrypoint_object(fwrite)
+add_stdio_entrypoint_object(fputc)
+add_stdio_entrypoint_object(putc)
+add_stdio_entrypoint_object(putchar)
 add_stdio_entrypoint_object(stdin)
 add_stdio_entrypoint_object(stdout)
 add_stdio_entrypoint_object(stderr)
diff --git a/libc/src/stdio/generic/CMakeLists.txt b/libc/src/stdio/generic/CMakeLists.txt
index 8d14d9fbf6f2497..e40e2cc9e04d3e3 100644
--- a/libc/src/stdio/generic/CMakeLists.txt
+++ b/libc/src/stdio/generic/CMakeLists.txt
@@ -75,6 +75,71 @@ add_entrypoint_object(
     libc.src.__support.File.platform_stdout
 )
 
+add_entrypoint_object(
+  fwrite_unlocked
+  SRCS
+    fwrite_unlocked.cpp
+  HDRS
+    ../fwrite_unlocked.h
+  DEPENDS
+    libc.src.errno.errno
+    libc.include.stdio
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+  fwrite
+  SRCS
+    fwrite.cpp
+  HDRS
+    ../fwrite.h
+  DEPENDS
+    libc.src.errno.errno
+    libc.include.stdio
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+  fputc
+  SRCS
+    fputc.cpp
+  HDRS
+    ../fputc.h
+  DEPENDS
+    libc.src.errno.errno
+    libc.include.stdio
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+  putc
+  SRCS
+    putc.cpp
+  HDRS
+    ../putc.h
+  DEPENDS
+    libc.src.errno.errno
+    libc.include.stdio
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+  putchar
+  SRCS
+    putchar.cpp
+  HDRS
+    ../putchar.h
+  DEPENDS
+    libc.src.errno.errno
+    libc.include.stdio
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
+)
+
 add_entrypoint_object(
   stdin
   SRCS
diff --git a/libc/src/stdio/fputc.cpp b/libc/src/stdio/generic/fputc.cpp
similarity index 100%
rename from libc/src/stdio/fputc.cpp
rename to libc/src/stdio/generic/fputc.cpp
diff --git a/libc/src/stdio/fwrite.cpp b/libc/src/stdio/generic/fwrite.cpp
similarity index 100%
rename from libc/src/stdio/fwrite.cpp
rename to libc/src/stdio/generic/fwrite.cpp
diff --git a/libc/src/stdio/fwrite_unlocked.cpp b/libc/src/stdio/generic/fwrite_unlocked.cpp
similarity index 100%
rename from libc/src/stdio/fwrite_unlocked.cpp
rename to libc/src/stdio/generic/fwrite_unlocked.cpp
diff --git a/libc/src/stdio/putc.cpp b/libc/src/stdio/generic/putc.cpp
similarity index 100%
rename from libc/src/stdio/putc.cpp
rename to libc/src/stdio/generic/putc.cpp
diff --git a/libc/src/stdio/putchar.cpp b/libc/src/stdio/generic/putchar.cpp
similarity index 100%
rename from libc/src/stdio/putchar.cpp
rename to libc/src/stdio/generic/putchar.cpp
diff --git a/libc/src/stdio/gpu/CMakeLists.txt b/libc/src/stdio/gpu/CMakeLists.txt
index 458dd86175021c4..d35b1925c6a47a0 100644
--- a/libc/src/stdio/gpu/CMakeLists.txt
+++ b/libc/src/stdio/gpu/CMakeLists.txt
@@ -61,6 +61,50 @@ add_entrypoint_object(
     .gpu_file
 )
 
+add_entrypoint_object(
+  fwrite
+  SRCS
+    fwrite.cpp
+  HDRS
+    ../fwrite.h
+  DEPENDS
+    libc.include.stdio
+    .gpu_file
+)
+
+add_entrypoint_object(
+  fputc
+  SRCS
+    fputc.cpp
+  HDRS
+    ../fputc.h
+  DEPENDS
+    libc.include.stdio
+    .gpu_file
+)
+
+add_entrypoint_object(
+  putc
+  SRCS
+    putc.cpp
+  HDRS
+    ../putc.h
+  DEPENDS
+    libc.include.stdio
+    .gpu_file
+)
+
+add_entrypoint_object(
+  putchar
+  SRCS
+    putchar.cpp
+  HDRS
+    ../putchar.h
+  DEPENDS
+    libc.include.stdio
+    .gpu_file
+)
+
 add_entrypoint_object(
   stdin
   SRCS
diff --git a/libc/src/stdio/gpu/fputc.cpp b/libc/src/stdio/gpu/fputc.cpp
new file mode 100644
index 000000000000000..90d238972972ec0
--- /dev/null
+++ b/libc/src/stdio/gpu/fputc.cpp
@@ -0,0 +1,26 @@
+//===-- GPU implementation of fputc ---------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "file.h"
+#include "src/stdio/fputc.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, fputc, (int c, ::FILE *stream)) {
+  unsigned char uc = static_cast<unsigned char>(c);
+
+  size_t written = file::write(stream, &uc, 1);
+  if (1 != written)
+    return EOF;
+
+  return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/gpu/fwrite.cpp b/libc/src/stdio/gpu/fwrite.cpp
new file mode 100644
index 000000000000000..fccaabd0673ec5c
--- /dev/null
+++ b/libc/src/stdio/gpu/fwrite.cpp
@@ -0,0 +1,26 @@
+//===-- GPU implementation of fwrite --------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/fwrite.h"
+#include "file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(size_t, fwrite,
+                   (const void *__restrict buffer, size_t size, size_t nmemb,
+                    ::FILE *stream)) {
+  if (size == 0 || nmemb == 0)
+    return 0;
+
+  auto result = file::write(stream, buffer, size * nmemb);
+  return result / size;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/gpu/putc.cpp b/libc/src/stdio/gpu/putc.cpp
new file mode 100644
index 000000000000000..d450edb6596df1c
--- /dev/null
+++ b/libc/src/stdio/gpu/putc.cpp
@@ -0,0 +1,26 @@
+//===-- GPU implementation of putc ----------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/putc.h"
+#include "file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, putc, (int c, ::FILE *stream)) {
+  unsigned char uc = static_cast<unsigned char>(c);
+
+  size_t written = file::write(stream, &uc, 1);
+  if (1 != written)
+    return EOF;
+
+  return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/gpu/putchar.cpp b/libc/src/stdio/gpu/putchar.cpp
new file mode 100644
index 000000000000000..df577544b8ba405
--- /dev/null
+++ b/libc/src/stdio/gpu/putchar.cpp
@@ -0,0 +1,26 @@
+//===-- GPU implementation of putchar -------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "file.h"
+#include "src/stdio/putchar.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, putchar, (int c)) {
+  unsigned char uc = static_cast<unsigned char>(c);
+
+  size_t written = file::write(stdout, &uc, 1);
+  if (1 != written)
+    return EOF;
+
+  return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/test/src/stdio/CMakeLists.txt b/libc/test/src/stdio/CMakeLists.txt
index 01590f9acb8545f..6090dc1f46c87ef 100644
--- a/libc/test/src/stdio/CMakeLists.txt
+++ b/libc/test/src/stdio/CMakeLists.txt
@@ -271,6 +271,20 @@ add_libc_test(
     libc.src.stdio.stderr
 )
 
+add_libc_test(
+  fputc_test
+  HERMETIC_TEST_ONLY # writes to libc's stdout and stderr
+  SUITE
+    libc_stdio_unittests
+  SRCS
+    fputc_test.cpp
+  DEPENDS
+    libc.src.stdio.fputc
+    libc.src.stdio.putchar
+    libc.src.stdio.stdout
+    libc.src.stdio.stderr
+)
+
 add_libc_test(
   fopen_test
   SUITE
@@ -279,7 +293,7 @@ add_libc_test(
     fopen_test.cpp
   DEPENDS
     libc.src.stdio.fread
-    libc.src.stdio.fputs
+    libc.src.stdio.fwrite
     libc.src.stdio.fclose
     libc.src.stdio.fopen
 )
diff --git a/libc/test/src/stdio/fopen_test.cpp b/libc/test/src/stdio/fopen_test.cpp
index 8e8a1c9638f5be6..f0de8caf673cc7e 100644
--- a/libc/test/src/stdio/fopen_test.cpp
+++ b/libc/test/src/stdio/fopen_test.cpp
@@ -9,7 +9,7 @@
 #include "src/__support/File/file.h"
 #include "src/stdio/fclose.h"
 #include "src/stdio/fopen.h"
-#include "src/stdio/fputs.h"
+#include "src/stdio/fwrite.h"
 #include "src/stdio/fread.h"
 
 #include "test/UnitTest/Test.h"
@@ -21,7 +21,7 @@ TEST(LlvmLibcFOpenTest, PrintToFile) {
   ASSERT_FALSE(file == nullptr);
 
   static constexpr char STRING[] = "A simple string written to a file\n";
-  result = __llvm_libc::fputs(STRING, file);
+  result = __llvm_libc::fwrite(STRING, 1, sizeof(STRING) - 1, file);
   EXPECT_GE(result, 0);
 
   ASSERT_EQ(0, __llvm_libc::fclose(file));
diff --git a/libc/test/src/stdio/fputc_test.cpp b/libc/test/src/stdio/fputc_test.cpp
new file mode 100644
index 000000000000000..e5aa7c713463bf2
--- /dev/null
+++ b/libc/test/src/stdio/fputc_test.cpp
@@ -0,0 +1,30 @@
+//===-- Unittests for fputc / putchar -------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/File/file.h"
+#include "src/stdio/fputc.h"
+#include "src/stdio/putchar.h"
+
+#include "test/UnitTest/Test.h"
+
+TEST(LlvmLibcPutcTest, PrintOut) {
+  int result;
+
+  constexpr char simple[] = "A simple string written to stdout\n";
+  for (const char &c : simple) {
+    result = __llvm_libc::putchar(c);
+    EXPECT_GE(result, 0);
+  }
+
+  constexpr char more[] = "A simple string written to stderr\n";
+  for (const char &c : simple) {
+    result =
+        __llvm_libc::fputc(c, reinterpret_cast<FILE *>(__llvm_libc::stderr));
+  }
+  EXPECT_GE(result, 0);
+}

>From 5a2baf2c50d1da167891576418508d6095d511c4 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 11:37:34 -0700
Subject: [PATCH 09/62] [clang][tools] Remove path separator assumption

After 98e6deb6 the 'HeadersForSymbolTest.IWYUTransitiveExportWithPrivate' test in 'ClangIncludeCleanerTest' started failing. This is most likely because `FileEntryRef::getName()` now starts with ".\" on Windows, whereas `FileEntry::getName()` did not. This commit fixes assumption of forward slash separators.
---
 clang-tools-extra/include-cleaner/lib/FindHeaders.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp b/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
index 0f91ad57f0c51d3..06e5e1812ba7218 100644
--- a/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
+++ b/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
@@ -50,8 +50,7 @@ llvm::SmallVector<Header> ranked(llvm::SmallVector<Hinted<Header>> Headers) {
 // name.
 llvm::StringRef basename(llvm::StringRef Header) {
   Header = Header.trim("<>\"");
-  if (auto LastSlash = Header.rfind('/'); LastSlash != Header.npos)
-    Header = Header.drop_front(LastSlash + 1);
+  Header = llvm::sys::path::filename(Header);
   // Drop everything after first `.` (dot).
   // foo.h -> foo
   // foo.cu.h -> foo

>From 49e0fb5a6512a16c0b31c313efe3c394b2d32df6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eymen=20=C3=9Cnay?= <eymenunay at outlook.com>
Date: Sat, 9 Sep 2023 12:58:50 -0700
Subject: [PATCH 10/62] [jitlink][rtdyld][checker] Re-apply 4b17c81d5a5 with
 fixes.

This re-applies 4b17c81d5a5, "[jitlink/rtdydl][checker] Add TargetFlag
dependent disassembler switching support", which was reverted in
4871a9ca546 due to bot failures.

The patch has been updated to add missing plumbing for Subtarget Features and
a CPU string, which should fix the failing tests.

https://reviews.llvm.org/D158280
---
 .../llvm/ExecutionEngine/JITLink/JITLink.h    |   6 +-
 .../llvm/ExecutionEngine/JITLink/aarch32.h    |   3 +
 .../llvm/ExecutionEngine/RuntimeDyldChecker.h |  27 ++-
 llvm/lib/ExecutionEngine/JITLink/aarch32.cpp  |  13 +-
 .../Orc/ObjectLinkingLayer.cpp                |   2 +-
 .../RuntimeDyld/RuntimeDyldChecker.cpp        | 163 ++++++++++++++++--
 .../RuntimeDyld/RuntimeDyldCheckerImpl.h      |  18 +-
 .../Targets/RuntimeDyldCOFFThumb.h            |  22 +++
 .../JITLink/AArch32/ELF_static_thumb_reloc.s  |   2 -
 .../RuntimeDyld/ARM/COFF_Thumb.s              |   2 +-
 llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp |  11 +-
 llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp  |  11 +-
 .../tools/llvm-jitlink/llvm-jitlink-macho.cpp |  13 +-
 llvm/tools/llvm-jitlink/llvm-jitlink.cpp      |  14 +-
 llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp        |   4 +-
 15 files changed, 250 insertions(+), 61 deletions(-)

diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
index 48268aa9f6899b9..ab4441fbec4606d 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
@@ -623,10 +623,8 @@ class Symbol {
     this->S = static_cast<uint8_t>(S);
   }
 
-  /// Check whether the given target flags are set for this Symbol.
-  bool hasTargetFlags(TargetFlagsType Flags) const {
-    return static_cast<TargetFlagsType>(TargetFlags) & Flags;
-  }
+  /// Get the target flags of this Symbol.
+  TargetFlagsType getTargetFlags() const { return TargetFlags; }
 
   /// Set the target flags for this Symbol.
   void setTargetFlags(TargetFlagsType Flags) {
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
index b21c9e2a1cd8260..d1d54c0ca633362 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
@@ -23,6 +23,9 @@ namespace llvm {
 namespace jitlink {
 namespace aarch32 {
 
+/// Check whether the given target flags are set for this Symbol.
+bool hasTargetFlags(Symbol &Sym, TargetFlagsType Flags);
+
 /// JITLink-internal AArch32 fixup kinds
 enum EdgeKind_aarch32 : Edge::Kind {
 
diff --git a/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
index 5904250c9a72208..85df587bff50c87 100644
--- a/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
+++ b/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
@@ -12,6 +12,8 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ExecutionEngine/JITSymbol.h"
 #include "llvm/Support/Endian.h"
+#include "llvm/TargetParser/SubtargetFeature.h"
+#include "llvm/TargetParser/Triple.h"
 #include <optional>
 
 #include <cstdint>
@@ -29,6 +31,9 @@ class RuntimeDyld;
 class RuntimeDyldCheckerImpl;
 class raw_ostream;
 
+/// Holds target-specific properties for a symbol.
+using TargetFlagsType = uint8_t;
+
 /// RuntimeDyld invariant checker for verifying that RuntimeDyld has
 ///        correctly applied relocations.
 ///
@@ -78,10 +83,11 @@ class RuntimeDyldChecker {
   public:
     MemoryRegionInfo() = default;
 
-    /// Constructor for symbols/sections with content.
-    MemoryRegionInfo(ArrayRef<char> Content, JITTargetAddress TargetAddress)
+    /// Constructor for symbols/sections with content and TargetFlag.
+    MemoryRegionInfo(ArrayRef<char> Content, JITTargetAddress TargetAddress,
+                     TargetFlagsType TargetFlags)
         : ContentPtr(Content.data()), Size(Content.size()),
-          TargetAddress(TargetAddress) {}
+          TargetAddress(TargetAddress), TargetFlags(TargetFlags) {}
 
     /// Constructor for zero-fill symbols/sections.
     MemoryRegionInfo(uint64_t Size, JITTargetAddress TargetAddress)
@@ -127,10 +133,20 @@ class RuntimeDyldChecker {
     /// Return the target address for this region.
     JITTargetAddress getTargetAddress() const { return TargetAddress; }
 
+    /// Get the target flags for this Symbol.
+    TargetFlagsType getTargetFlags() const { return TargetFlags; }
+
+    /// Set the target flags for this Symbol.
+    void setTargetFlags(TargetFlagsType Flags) {
+      assert(Flags <= 1 && "Add more bits to store more than one flag");
+      TargetFlags = Flags;
+    }
+
   private:
     const char *ContentPtr = nullptr;
     uint64_t Size = 0;
     JITTargetAddress TargetAddress = 0;
+    TargetFlagsType TargetFlags = 0;
   };
 
   using IsSymbolValidFunction = std::function<bool(StringRef Symbol)>;
@@ -148,9 +164,8 @@ class RuntimeDyldChecker {
                      GetSectionInfoFunction GetSectionInfo,
                      GetStubInfoFunction GetStubInfo,
                      GetGOTInfoFunction GetGOTInfo,
-                     support::endianness Endianness,
-                     MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
-                     raw_ostream &ErrStream);
+                     support::endianness Endianness, Triple TT, StringRef CPU,
+                     SubtargetFeatures TF, raw_ostream &ErrStream);
   ~RuntimeDyldChecker();
 
   /// Check a single expression against the attached RuntimeDyld
diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
index e9221a898ff63da..01c9e8b4fd9d18e 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
@@ -25,6 +25,11 @@ namespace llvm {
 namespace jitlink {
 namespace aarch32 {
 
+/// Check whether the given target flags are set for this Symbol.
+bool hasTargetFlags(Symbol &Sym, TargetFlagsType Flags) {
+  return static_cast<TargetFlagsType>(Sym.getTargetFlags()) & Flags;
+}
+
 /// Encode 22-bit immediate value for branch instructions without J1J2 range
 /// extension (formats B T4, BL T1 and BLX T2).
 ///
@@ -287,7 +292,7 @@ Error applyFixupData(LinkGraph &G, Block &B, const Edge &E) {
   int64_t Addend = E.getAddend();
   Symbol &TargetSymbol = E.getTarget();
   uint64_t TargetAddress = TargetSymbol.getAddress().getValue();
-  assert(!TargetSymbol.hasTargetFlags(ThumbSymbol));
+  assert(!hasTargetFlags(TargetSymbol, ThumbSymbol));
 
   // Regular data relocations have size 4, alignment 1 and write the full 32-bit
   // result to the place; no need for overflow checking. There are three
@@ -341,14 +346,14 @@ Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
   int64_t Addend = E.getAddend();
   Symbol &TargetSymbol = E.getTarget();
   uint64_t TargetAddress = TargetSymbol.getAddress().getValue();
-  if (TargetSymbol.hasTargetFlags(ThumbSymbol))
+  if (hasTargetFlags(TargetSymbol, ThumbSymbol))
     TargetAddress |= 0x01;
 
   switch (Kind) {
   case Thumb_Jump24: {
     if (!checkOpcode<Thumb_Jump24>(R))
       return makeUnexpectedOpcodeError(G, R, Kind);
-    if (!(TargetSymbol.hasTargetFlags(ThumbSymbol)))
+    if (!hasTargetFlags(TargetSymbol, ThumbSymbol))
       return make_error<JITLinkError>("Branch relocation needs interworking "
                                       "stub when bridging to ARM: " +
                                       StringRef(G.getEdgeKindName(Kind)));
@@ -375,7 +380,7 @@ Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
 
     // The call instruction itself is Thumb. The call destination can either be
     // Thumb or Arm. We use BL to stay in Thumb and BLX to change to Arm.
-    bool TargetIsArm = !TargetSymbol.hasTargetFlags(ThumbSymbol);
+    bool TargetIsArm = !hasTargetFlags(TargetSymbol, ThumbSymbol);
     bool InstrIsBlx = (R.Lo & FixupInfo<Thumb_Call>::LoBitNoBlx) == 0;
     if (TargetIsArm != InstrIsBlx) {
       if (LLVM_LIKELY(TargetIsArm)) {
diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
index a29f3d1c3aec8da..3d77f82e65696a8 100644
--- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
@@ -46,7 +46,7 @@ ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) {
   case Triple::armeb:
   case Triple::thumb:
   case Triple::thumbeb:
-    if (Sym.hasTargetFlags(aarch32::ThumbSymbol)) {
+    if (hasTargetFlags(Sym, aarch32::ThumbSymbol)) {
       // Set LSB to indicate thumb target
       assert(Sym.isCallable() && "Only callable symbols can have thumb flag");
       assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear");
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
index ab561ecd0057984..e99f637bb4b2c4c 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
@@ -10,9 +10,16 @@
 #include "RuntimeDyldCheckerImpl.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
 #include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/MSVCErrorWorkarounds.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -25,6 +32,19 @@
 
 using namespace llvm;
 
+namespace {
+struct TargetInfo {
+  const Target *TheTarget;
+  std::unique_ptr<MCSubtargetInfo> STI;
+  std::unique_ptr<MCRegisterInfo> MRI;
+  std::unique_ptr<MCAsmInfo> MAI;
+  std::unique_ptr<MCContext> Ctx;
+  std::unique_ptr<MCDisassembler> Disassembler;
+  std::unique_ptr<MCInstrInfo> MII;
+  std::unique_ptr<MCInstPrinter> InstPrinter;
+};
+} // anonymous namespace
+
 namespace llvm {
 
 // Helper class that implements the language evaluated by RuntimeDyldChecker.
@@ -276,6 +296,20 @@ class RuntimeDyldCheckerExprEval {
           "");
 
     unsigned OpIdx = OpIdxExpr.getValue();
+
+    auto printInst = [this](StringRef Symbol, MCInst Inst,
+                            raw_string_ostream &ErrMsgStream) {
+      auto TT = Checker.getTripleForSymbol(Checker.getTargetFlag(Symbol));
+      auto TI = getTargetInfo(TT, Checker.getCPU(), Checker.getFeatures());
+      if (auto E = TI.takeError()) {
+        errs() << "Error obtaining instruction printer: "
+               << toString(std::move(E)) << "\n";
+        return std::make_pair(EvalResult(ErrMsgStream.str()), "");
+      }
+      Inst.dump_pretty(ErrMsgStream, TI->InstPrinter.get());
+      return std::make_pair(EvalResult(ErrMsgStream.str()), "");
+    };
+
     if (OpIdx >= Inst.getNumOperands()) {
       std::string ErrMsg;
       raw_string_ostream ErrMsgStream(ErrMsg);
@@ -284,8 +318,8 @@ class RuntimeDyldCheckerExprEval {
                    << "'. Instruction has only "
                    << format("%i", Inst.getNumOperands())
                    << " operands.\nInstruction is:\n  ";
-      Inst.dump_pretty(ErrMsgStream, Checker.InstPrinter);
-      return std::make_pair(EvalResult(ErrMsgStream.str()), "");
+
+      return printInst(Symbol, Inst, ErrMsgStream);
     }
 
     const MCOperand &Op = Inst.getOperand(OpIdx);
@@ -294,9 +328,8 @@ class RuntimeDyldCheckerExprEval {
       raw_string_ostream ErrMsgStream(ErrMsg);
       ErrMsgStream << "Operand '" << format("%i", OpIdx) << "' of instruction '"
                    << Symbol << "' is not an immediate.\nInstruction is:\n  ";
-      Inst.dump_pretty(ErrMsgStream, Checker.InstPrinter);
 
-      return std::make_pair(EvalResult(ErrMsgStream.str()), "");
+      return printInst(Symbol, Inst, ErrMsgStream);
     }
 
     return std::make_pair(EvalResult(Op.getImm()), RemainingExpr);
@@ -687,31 +720,100 @@ class RuntimeDyldCheckerExprEval {
 
   bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size,
                   int64_t Offset) const {
-    MCDisassembler *Dis = Checker.Disassembler;
+    auto TT = Checker.getTripleForSymbol(Checker.getTargetFlag(Symbol));
+    auto TI = getTargetInfo(TT, Checker.getCPU(), Checker.getFeatures());
+
+    if (auto E = TI.takeError()) {
+      errs() << "Error obtaining disassembler: " << toString(std::move(E))
+             << "\n";
+      return false;
+    }
+
     StringRef SymbolMem = Checker.getSymbolContent(Symbol);
     ArrayRef<uint8_t> SymbolBytes(SymbolMem.bytes_begin() + Offset,
                                   SymbolMem.size() - Offset);
 
     MCDisassembler::DecodeStatus S =
-        Dis->getInstruction(Inst, Size, SymbolBytes, 0, nulls());
+        TI->Disassembler->getInstruction(Inst, Size, SymbolBytes, 0, nulls());
 
     return (S == MCDisassembler::Success);
   }
+
+  Expected<TargetInfo> getTargetInfo(const Triple &TT, const StringRef &CPU,
+                                     const SubtargetFeatures &TF) const {
+
+    auto TripleName = TT.str();
+    std::string ErrorStr;
+    const Target *TheTarget =
+        TargetRegistry::lookupTarget(TripleName, ErrorStr);
+    if (!TheTarget)
+      return make_error<StringError>("Error accessing target '" + TripleName +
+                                         "': " + ErrorStr,
+                                     inconvertibleErrorCode());
+
+    std::unique_ptr<MCSubtargetInfo> STI(
+        TheTarget->createMCSubtargetInfo(TripleName, CPU, TF.getString()));
+    if (!STI)
+      return make_error<StringError>("Unable to create subtarget for " +
+                                         TripleName,
+                                     inconvertibleErrorCode());
+
+    std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
+    if (!MRI)
+      return make_error<StringError>("Unable to create target register info "
+                                     "for " +
+                                         TripleName,
+                                     inconvertibleErrorCode());
+
+    MCTargetOptions MCOptions;
+    std::unique_ptr<MCAsmInfo> MAI(
+        TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
+    if (!MAI)
+      return make_error<StringError>("Unable to create target asm info " +
+                                         TripleName,
+                                     inconvertibleErrorCode());
+
+    auto Ctx = std::make_unique<MCContext>(Triple(TripleName), MAI.get(),
+                                           MRI.get(), STI.get());
+
+    std::unique_ptr<MCDisassembler> Disassembler(
+        TheTarget->createMCDisassembler(*STI, *Ctx));
+    if (!Disassembler)
+      return make_error<StringError>("Unable to create disassembler for " +
+                                         TripleName,
+                                     inconvertibleErrorCode());
+
+    std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
+    if (!MII)
+      return make_error<StringError>("Unable to create instruction info for" +
+                                         TripleName,
+                                     inconvertibleErrorCode());
+
+    std::unique_ptr<MCInstPrinter> InstPrinter(TheTarget->createMCInstPrinter(
+        Triple(TripleName), 0, *MAI, *MII, *MRI));
+    if (!InstPrinter)
+      return make_error<StringError>(
+          "Unable to create instruction printer for" + TripleName,
+          inconvertibleErrorCode());
+
+    return TargetInfo({TheTarget, std::move(STI), std::move(MRI),
+                       std::move(MAI), std::move(Ctx), std::move(Disassembler),
+                       std::move(MII), std::move(InstPrinter)});
+  }
 };
 } // namespace llvm
 
 RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl(
     IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
     GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,
-    GetGOTInfoFunction GetGOTInfo, support::endianness Endianness,
-    MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
-    raw_ostream &ErrStream)
+    GetGOTInfoFunction GetGOTInfo, support::endianness Endianness, Triple TT,
+    StringRef CPU, SubtargetFeatures TF, raw_ostream &ErrStream)
     : IsSymbolValid(std::move(IsSymbolValid)),
       GetSymbolInfo(std::move(GetSymbolInfo)),
       GetSectionInfo(std::move(GetSectionInfo)),
       GetStubInfo(std::move(GetStubInfo)), GetGOTInfo(std::move(GetGOTInfo)),
-      Endianness(Endianness), Disassembler(Disassembler),
-      InstPrinter(InstPrinter), ErrStream(ErrStream) {}
+      Endianness(Endianness), TT(std::move(TT)), CPU(std::move(CPU)),
+      TF(std::move(TF)), ErrStream(ErrStream) {}
 
 bool RuntimeDyldCheckerImpl::check(StringRef CheckExpr) const {
   CheckExpr = CheckExpr.trim();
@@ -822,6 +924,36 @@ StringRef RuntimeDyldCheckerImpl::getSymbolContent(StringRef Symbol) const {
   return {SymInfo->getContent().data(), SymInfo->getContent().size()};
 }
 
+TargetFlagsType RuntimeDyldCheckerImpl::getTargetFlag(StringRef Symbol) const {
+  auto SymInfo = GetSymbolInfo(Symbol);
+  if (!SymInfo) {
+    logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
+    return TargetFlagsType{};
+  }
+  return SymInfo->getTargetFlags();
+}
+
+Triple
+RuntimeDyldCheckerImpl::getTripleForSymbol(TargetFlagsType Flag) const {
+  Triple TheTriple = TT;
+
+  switch (TT.getArch()) {
+  case Triple::ArchType::arm:
+    if (~Flag & 0x1)
+      return TT;
+    TheTriple.setArchName((Twine("thumb") + TT.getArchName().substr(3)).str());
+    return TheTriple;
+  case Triple::ArchType::thumb:
+    if (Flag & 0x1)
+      return TT;
+    TheTriple.setArchName((Twine("arm") + TT.getArchName().substr(5)).str());
+    return TheTriple;
+
+  default:
+    return TT;
+  }
+}
+
 std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getSectionAddr(
     StringRef FileName, StringRef SectionName, bool IsInsideLoad) const {
 
@@ -884,14 +1016,13 @@ std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubOrGOTAddrFor(
 RuntimeDyldChecker::RuntimeDyldChecker(
     IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
     GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,
-    GetGOTInfoFunction GetGOTInfo, support::endianness Endianness,
-    MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
-    raw_ostream &ErrStream)
+    GetGOTInfoFunction GetGOTInfo, support::endianness Endianness, Triple TT,
+    StringRef CPU, SubtargetFeatures TF, raw_ostream &ErrStream)
     : Impl(::std::make_unique<RuntimeDyldCheckerImpl>(
           std::move(IsSymbolValid), std::move(GetSymbolInfo),
           std::move(GetSectionInfo), std::move(GetStubInfo),
-          std::move(GetGOTInfo), Endianness, Disassembler, InstPrinter,
-          ErrStream)) {}
+          std::move(GetGOTInfo), Endianness, std::move(TT), std::move(CPU),
+          std::move(TF), ErrStream)) {}
 
 RuntimeDyldChecker::~RuntimeDyldChecker() = default;
 
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
index f564b0035bffdec..d2a969b0f211980 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
@@ -13,6 +13,9 @@
 
 namespace llvm {
 
+/// Holds target-specific properties for a symbol.
+using TargetFlagsType = uint8_t;
+
 class RuntimeDyldCheckerImpl {
   friend class RuntimeDyldChecker;
   friend class RuntimeDyldCheckerExprEval;
@@ -28,9 +31,8 @@ class RuntimeDyldCheckerImpl {
   RuntimeDyldCheckerImpl(
       IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
       GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,
-      GetGOTInfoFunction GetGOTInfo, support::endianness Endianness,
-      MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
-      llvm::raw_ostream &ErrStream);
+      GetGOTInfoFunction GetGOTInfo, support::endianness Endianness, Triple TT,
+      StringRef CPU, SubtargetFeatures TF, llvm::raw_ostream &ErrStream);
 
   bool check(StringRef CheckExpr) const;
   bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
@@ -49,6 +51,11 @@ class RuntimeDyldCheckerImpl {
 
   StringRef getSymbolContent(StringRef Symbol) const;
 
+  TargetFlagsType getTargetFlag(StringRef Symbol) const;
+  Triple getTripleForSymbol(TargetFlagsType Flag) const;
+  StringRef getCPU() const { return CPU; }
+  SubtargetFeatures getFeatures() const { return TF; }
+
   std::pair<uint64_t, std::string> getSectionAddr(StringRef FileName,
                                                   StringRef SectionName,
                                                   bool IsInsideLoad) const;
@@ -65,8 +72,9 @@ class RuntimeDyldCheckerImpl {
   GetStubInfoFunction GetStubInfo;
   GetGOTInfoFunction GetGOTInfo;
   support::endianness Endianness;
-  MCDisassembler *Disassembler;
-  MCInstPrinter *InstPrinter;
+  Triple TT;
+  std::string CPU;
+  SubtargetFeatures TF;
   llvm::raw_ostream &ErrStream;
 };
 }
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h
index 22f1cf33158c8be..a3e66c6bc0ecdf8 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h
@@ -54,6 +54,28 @@ class RuntimeDyldCOFFThumb : public RuntimeDyldCOFF {
     return 16; // 8-byte load instructions, 4-byte jump, 4-byte padding
   }
 
+  Expected<JITSymbolFlags> getJITSymbolFlags(const SymbolRef &SR) override {
+
+    auto Flags = RuntimeDyldImpl::getJITSymbolFlags(SR);
+
+    if (!Flags) {
+      return Flags.takeError();
+    }
+    auto SectionIterOrErr = SR.getSection();
+    if (!SectionIterOrErr) {
+      return SectionIterOrErr.takeError();
+    }
+    SectionRef Sec = *SectionIterOrErr.get();
+    const object::COFFObjectFile *COFFObjPtr =
+        cast<object::COFFObjectFile>(Sec.getObject());
+    const coff_section *CoffSec = COFFObjPtr->getCOFFSection(Sec);
+    bool isThumb = CoffSec->Characteristics & COFF::IMAGE_SCN_MEM_16BIT;
+
+    Flags->getTargetFlags() = isThumb;
+
+    return Flags;
+  }
+
   Align getStubAlignment() override { return Align(1); }
 
   Expected<object::relocation_iterator>
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_static_thumb_reloc.s b/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_static_thumb_reloc.s
index 76c5f5807f7b86c..b0d6db045efd216 100644
--- a/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_static_thumb_reloc.s
+++ b/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_static_thumb_reloc.s
@@ -4,8 +4,6 @@
 # RUN: llvm-jitlink -noexec -slab-address 0x76ff0000 -slab-allocate 10Kb \
 # RUN:              -slab-page-size 4096 -show-entry-es -check %s %t.o
 
-# This test requires the RuntimeDyldChecker fix from review D158280
-# XFAIL: *
 
 	.text
 	.syntax unified
diff --git a/llvm/test/ExecutionEngine/RuntimeDyld/ARM/COFF_Thumb.s b/llvm/test/ExecutionEngine/RuntimeDyld/ARM/COFF_Thumb.s
index aec4fdad4c58868..b4946880ff15523 100644
--- a/llvm/test/ExecutionEngine/RuntimeDyld/ARM/COFF_Thumb.s
+++ b/llvm/test/ExecutionEngine/RuntimeDyld/ARM/COFF_Thumb.s
@@ -101,7 +101,7 @@ rel11:
 	bx r0
 	trap
 
-	.data
+	.text
 
 	.p2align 2
 
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp
index 415aee76b186345..283e655205d7809 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp
@@ -118,7 +118,8 @@ Error registerCOFFGraphInfo(Session &S, LinkGraph &G) {
         if (Sym->getSize() != 0) {
           if (auto TS = getCOFFGOTTarget(G, Sym->getBlock()))
             FileInfo.GOTEntryInfos[TS->getName()] = {
-                Sym->getSymbolContent(), Sym->getAddress().getValue()};
+                Sym->getSymbolContent(), Sym->getAddress().getValue(),
+                Sym->getTargetFlags()};
           else
             return TS.takeError();
         }
@@ -130,7 +131,8 @@ Error registerCOFFGraphInfo(Session &S, LinkGraph &G) {
 
         if (auto TS = getCOFFStubTarget(G, Sym->getBlock()))
           FileInfo.StubInfos[TS->getName()] = {Sym->getSymbolContent(),
-                                               Sym->getAddress().getValue()};
+                                               Sym->getAddress().getValue(),
+                                               Sym->getTargetFlags()};
         else
           return TS.takeError();
         SectionContainsContent = true;
@@ -143,7 +145,8 @@ Error registerCOFFGraphInfo(Session &S, LinkGraph &G) {
           SectionContainsZeroFill = true;
         } else {
           S.SymbolInfos[Sym->getName()] = {Sym->getSymbolContent(),
-                                           Sym->getAddress().getValue()};
+                                           Sym->getAddress().getValue(),
+                                           Sym->getTargetFlags()};
           SectionContainsContent = true;
         }
       }
@@ -164,7 +167,7 @@ Error registerCOFFGraphInfo(Session &S, LinkGraph &G) {
     else
       FileInfo.SectionInfos[Sec.getName()] = {
           ArrayRef<char>(FirstSym->getBlock().getContent().data(), SecSize),
-          SecAddr.getValue()};
+          SecAddr.getValue(), FirstSym->getTargetFlags()};
   }
 
   return Error::success();
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
index 5200dbcf9036619..7881660d1a73851 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
@@ -120,7 +120,8 @@ Error registerELFGraphInfo(Session &S, LinkGraph &G) {
         if (Sym->getSize() != 0) {
           if (auto TS = getELFGOTTarget(G, Sym->getBlock()))
             FileInfo.GOTEntryInfos[TS->getName()] = {
-                Sym->getSymbolContent(), Sym->getAddress().getValue()};
+                Sym->getSymbolContent(), Sym->getAddress().getValue(),
+                Sym->getTargetFlags()};
           else
             return TS.takeError();
         }
@@ -132,7 +133,8 @@ Error registerELFGraphInfo(Session &S, LinkGraph &G) {
 
         if (auto TS = getELFStubTarget(G, Sym->getBlock()))
           FileInfo.StubInfos[TS->getName()] = {Sym->getSymbolContent(),
-                                               Sym->getAddress().getValue()};
+                                               Sym->getAddress().getValue(),
+                                               Sym->getTargetFlags()};
         else
           return TS.takeError();
         SectionContainsContent = true;
@@ -145,7 +147,8 @@ Error registerELFGraphInfo(Session &S, LinkGraph &G) {
           SectionContainsZeroFill = true;
         } else {
           S.SymbolInfos[Sym->getName()] = {Sym->getSymbolContent(),
-                                           Sym->getAddress().getValue()};
+                                           Sym->getAddress().getValue(),
+                                           Sym->getTargetFlags()};
           SectionContainsContent = true;
         }
       }
@@ -170,7 +173,7 @@ Error registerELFGraphInfo(Session &S, LinkGraph &G) {
     else
       FileInfo.SectionInfos[Sec.getName()] = {
           ArrayRef<char>(FirstSym->getBlock().getContent().data(), SecSize),
-          SecAddr.getValue()};
+          SecAddr.getValue(), FirstSym->getTargetFlags()};
   }
 
   return Error::success();
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp
index bcb2f251ece1c0c..7dcadd94c2365a4 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp
@@ -117,8 +117,9 @@ Error registerMachOGraphInfo(Session &S, LinkGraph &G) {
                                          inconvertibleErrorCode());
 
         if (auto TS = getMachOGOTTarget(G, Sym->getBlock()))
-          FileInfo.GOTEntryInfos[TS->getName()] = {
-              Sym->getSymbolContent(), Sym->getAddress().getValue()};
+          FileInfo.GOTEntryInfos[TS->getName()] = {Sym->getSymbolContent(),
+                                                   Sym->getAddress().getValue(),
+                                                   Sym->getTargetFlags()};
         else
           return TS.takeError();
         SectionContainsContent = true;
@@ -129,7 +130,8 @@ Error registerMachOGraphInfo(Session &S, LinkGraph &G) {
 
         if (auto TS = getMachOStubTarget(G, Sym->getBlock()))
           FileInfo.StubInfos[TS->getName()] = {Sym->getSymbolContent(),
-                                               Sym->getAddress().getValue()};
+                                               Sym->getAddress().getValue(),
+                                               Sym->getTargetFlags()};
         else
           return TS.takeError();
         SectionContainsContent = true;
@@ -140,7 +142,8 @@ Error registerMachOGraphInfo(Session &S, LinkGraph &G) {
           SectionContainsZeroFill = true;
         } else {
           S.SymbolInfos[Sym->getName()] = {Sym->getSymbolContent(),
-                                           Sym->getAddress().getValue()};
+                                           Sym->getAddress().getValue(),
+                                           Sym->getTargetFlags()};
           SectionContainsContent = true;
         }
       }
@@ -160,7 +163,7 @@ Error registerMachOGraphInfo(Session &S, LinkGraph &G) {
     else
       FileInfo.SectionInfos[Sec.getName()] = {
           ArrayRef<char>(FirstSym->getBlock().getContent().data(), SecSize),
-          SecAddr.getValue()};
+          SecAddr.getValue(), FirstSym->getTargetFlags()};
   }
 
   return Error::success();
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index 00dd5206d75a756..64806b554ee7c0b 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -1388,7 +1388,8 @@ static Error addAbsoluteSymbols(Session &S,
       return Err;
 
     // Register the absolute symbol with the session symbol infos.
-    S.SymbolInfos[Name] = {ArrayRef<char>(), Addr};
+    S.SymbolInfos[Name] = {ArrayRef<char>(), Addr,
+                           AbsDef.getFlags().getTargetFlags()};
   }
 
   return Error::success();
@@ -1856,15 +1857,12 @@ getTargetInfo(const Triple &TT,
           std::move(MAI), std::move(Ctx), std::move(Disassembler),
           std::move(MII), std::move(MIA), std::move(InstPrinter)};
 }
-
-static Error runChecks(Session &S) {
+static Error runChecks(Session &S, Triple TT, SubtargetFeatures Features) {
   if (CheckFiles.empty())
     return Error::success();
 
   LLVM_DEBUG(dbgs() << "Running checks...\n");
 
-  auto TI = getTargetInfo(S.ES.getTargetTriple(), S.Features);
-
   auto IsSymbolValid = [&S](StringRef Symbol) {
     return S.isSymbolRegistered(Symbol);
   };
@@ -1888,7 +1886,7 @@ static Error runChecks(Session &S) {
   RuntimeDyldChecker Checker(
       IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo, GetGOTInfo,
       S.ES.getTargetTriple().isLittleEndian() ? support::little : support::big,
-      TI.Disassembler.get(), TI.InstPrinter.get(), dbgs());
+      TT, StringRef(), Features, dbgs());
 
   std::string CheckLineStart = "# " + CheckName + ":";
   for (auto &CheckFile : CheckFiles) {
@@ -2000,7 +1998,7 @@ int main(int argc, char *argv[]) {
   auto [TT, Features] = getFirstFileTripleAndFeatures();
   ExitOnErr(sanitizeArguments(TT, argv[0]));
 
-  auto S = ExitOnErr(Session::Create(std::move(TT), std::move(Features)));
+  auto S = ExitOnErr(Session::Create(TT, Features));
 
   enableStatistics(*S, !OrcRuntime.empty());
 
@@ -2036,7 +2034,7 @@ int main(int argc, char *argv[]) {
     exit(1);
   }
 
-  ExitOnErr(runChecks(*S));
+  ExitOnErr(runChecks(*S, std::move(TT), std::move(Features)));
 
   int Result = 0;
   if (!NoExec) {
diff --git a/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp b/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
index df82fb04e8e680c..d947be7f1fd87d7 100644
--- a/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -892,6 +892,8 @@ static int linkAndVerify() {
         StringRef SecContent = Dyld.getSectionContent(SectionID);
         uint64_t SymSize = SecContent.size() - (CSymAddr - SecContent.data());
         SymInfo.setContent(ArrayRef<char>(CSymAddr, SymSize));
+        SymInfo.setTargetFlags(
+            Dyld.getSymbol(Symbol).getFlags().getTargetFlags());
       }
     }
     return SymInfo;
@@ -977,7 +979,7 @@ static int linkAndVerify() {
       Checker = std::make_unique<RuntimeDyldChecker>(
           IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo,
           GetStubInfo, Obj.isLittleEndian() ? support::little : support::big,
-          Disassembler.get(), InstPrinter.get(), dbgs());
+          TheTriple, MCPU, SubtargetFeatures(), dbgs());
 
     auto FileName = sys::path::filename(InputFile);
     MemMgr.setSectionIDsMap(&FileToSecIDMap[FileName]);

>From 5010bea63032f4f4ca9fec9fa988e9498c690ae4 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 14 Aug 2023 14:27:29 -0400
Subject: [PATCH 11/62] clang: Add __builtin_exp10* and use new llvm.exp10
 intrinsic

https://reviews.llvm.org/D157911
---
 clang/docs/ReleaseNotes.rst                    |  3 +++
 clang/include/clang/Basic/Builtins.def         |  5 +++++
 clang/lib/CodeGen/CGBuiltin.cpp                | 11 ++++++++++-
 clang/test/CodeGen/constrained-math-builtins.c | 12 ++++++++++++
 clang/test/CodeGen/math-builtins.c             | 11 +++++++++++
 clang/test/CodeGenOpenCL/builtins-f16.cl       |  3 +++
 6 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5c2c5cf4fb2c349..fe857941171fa3d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -377,6 +377,9 @@ Floating Point Support in Clang
   semantics. If ``math-errno`` is disabled in the current TU, clang will
   re-enable ``math-errno`` in the presense of
   ``#pragma float_control(precise,on)``.
+- Add ``__builtin_exp10``, ``__builtin_exp10f``,
+  ``__builtin_exp10f16``, ``__builtin_exp10l`` and
+  ``__builtin_exp10f128`` builtins.
 
 AST Matchers
 ------------
diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
index f5374537a0242c7..586dcf05170eb58 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -245,6 +245,11 @@ BUILTIN(__builtin_exp2f, "ff"  , "Fne")
 BUILTIN(__builtin_exp2f16, "hh"  , "Fne")
 BUILTIN(__builtin_exp2l, "LdLd", "Fne")
 BUILTIN(__builtin_exp2f128, "LLdLLd"  , "Fne")
+BUILTIN(__builtin_exp10 , "dd"  , "Fne")
+BUILTIN(__builtin_exp10f, "ff"  , "Fne")
+BUILTIN(__builtin_exp10f16, "hh"  , "Fne")
+BUILTIN(__builtin_exp10l, "LdLd", "Fne")
+BUILTIN(__builtin_exp10f128, "LLdLLd"  , "Fne")
 BUILTIN(__builtin_expm1 , "dd", "Fne")
 BUILTIN(__builtin_expm1f, "ff", "Fne")
 BUILTIN(__builtin_expm1l, "LdLd", "Fne")
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 5f9199d7cadee24..df0c4cc6354d0f2 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2433,7 +2433,16 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
       return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E,
                                    Intrinsic::exp2,
                                    Intrinsic::experimental_constrained_exp2));
-
+    case Builtin::BI__builtin_exp10:
+    case Builtin::BI__builtin_exp10f:
+    case Builtin::BI__builtin_exp10f16:
+    case Builtin::BI__builtin_exp10l:
+    case Builtin::BI__builtin_exp10f128: {
+      // TODO: strictfp support
+      if (Builder.getIsFPConstrained())
+        break;
+      return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::exp10));
+    }
     case Builtin::BIfabs:
     case Builtin::BIfabsf:
     case Builtin::BIfabsl:
diff --git a/clang/test/CodeGen/constrained-math-builtins.c b/clang/test/CodeGen/constrained-math-builtins.c
index 88ae8f58a7e20e5..981cc3ac36bd907 100644
--- a/clang/test/CodeGen/constrained-math-builtins.c
+++ b/clang/test/CodeGen/constrained-math-builtins.c
@@ -64,6 +64,13 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c, _
 // CHECK: call x86_fp80 @llvm.experimental.constrained.exp2.f80(x86_fp80 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
 // CHECK: call fp128 @llvm.experimental.constrained.exp2.f128(fp128 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
 
+  __builtin_exp10(f);       __builtin_exp10f(f);      __builtin_exp10l(f); __builtin_exp10f128(f);
+
+// CHECK: call double @exp10(double noundef %{{.*}})
+// CHECK: call float @exp10f(float noundef %{{.*}})
+// CHECK: call x86_fp80 @exp10l(x86_fp80 noundef %{{.*}})
+// CHECK: call fp128 @exp10f128(fp128 noundef %{{.*}})
+
   __builtin_floor(f);      __builtin_floorf(f);     __builtin_floorl(f); __builtin_floorf128(f);
 
 // CHECK: call double @llvm.experimental.constrained.floor.f64(double %{{.*}}, metadata !"fpexcept.strict")
@@ -223,6 +230,11 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c, _
 // CHECK: declare x86_fp80 @llvm.experimental.constrained.exp2.f80(x86_fp80, metadata, metadata)
 // CHECK: declare fp128 @llvm.experimental.constrained.exp2.f128(fp128, metadata, metadata)
 
+// CHECK: declare double @exp10(double noundef)
+// CHECK: declare float @exp10f(float noundef)
+// CHECK: declare x86_fp80 @exp10l(x86_fp80 noundef)
+// CHECK: declare fp128 @exp10f128(fp128 noundef)
+
 // CHECK: declare double @llvm.experimental.constrained.floor.f64(double, metadata)
 // CHECK: declare float @llvm.experimental.constrained.floor.f32(float, metadata)
 // CHECK: declare x86_fp80 @llvm.experimental.constrained.floor.f80(x86_fp80, metadata)
diff --git a/clang/test/CodeGen/math-builtins.c b/clang/test/CodeGen/math-builtins.c
index 257da44b5888a1a..962e311698f5755 100644
--- a/clang/test/CodeGen/math-builtins.c
+++ b/clang/test/CodeGen/math-builtins.c
@@ -318,6 +318,17 @@ __builtin_exp2(f);       __builtin_exp2f(f);      __builtin_exp2l(f); __builtin_
 // HAS_ERRNO: declare x86_fp80 @exp2l(x86_fp80 noundef) [[NOT_READNONE]]
 // HAS_ERRNO: declare fp128 @exp2f128(fp128 noundef) [[NOT_READNONE]]
 
+__builtin_exp10(f);       __builtin_exp10f(f);      __builtin_exp10l(f); __builtin_exp10f128(f);
+
+// NO__ERRNO: declare double @llvm.exp10.f64(double) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare float @llvm.exp10.f32(float) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare x86_fp80 @llvm.exp10.f80(x86_fp80) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare fp128 @llvm.exp10.f128(fp128) [[READNONE_INTRINSIC]]
+// HAS_ERRNO: declare double @exp10(double noundef) [[NOT_READNONE]]
+// HAS_ERRNO: declare float @exp10f(float noundef) [[NOT_READNONE]]
+// HAS_ERRNO: declare x86_fp80 @exp10l(x86_fp80 noundef) [[NOT_READNONE]]
+// HAS_ERRNO: declare fp128 @exp10f128(fp128 noundef) [[NOT_READNONE]]
+
 __builtin_expm1(f);      __builtin_expm1f(f);     __builtin_expm1l(f); __builtin_expm1f128(f);
 
 // NO__ERRNO: declare double @expm1(double noundef) [[READNONE]]
diff --git a/clang/test/CodeGenOpenCL/builtins-f16.cl b/clang/test/CodeGenOpenCL/builtins-f16.cl
index caf20742ca846bb..adf7cdde154f513 100644
--- a/clang/test/CodeGenOpenCL/builtins-f16.cl
+++ b/clang/test/CodeGenOpenCL/builtins-f16.cl
@@ -24,6 +24,9 @@ void test_half_builtins(half h0, half h1, half h2, int i0) {
   // CHECK: call half @llvm.exp2.f16(half %h0)
   res = __builtin_exp2f16(h0);
 
+  // CHECK: call half @llvm.exp10.f16(half %h0)
+  res = __builtin_exp10f16(h0);
+
   // CHECK: call half @llvm.floor.f16(half %h0)
   res = __builtin_floorf16(h0);
 

>From 883d32870e542dcf7c7b6d6d8a75a32e96496233 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Sch=C3=A4pers?= <bjoern at hazardy.de>
Date: Sat, 9 Sep 2023 22:31:58 +0200
Subject: [PATCH 12/62] [clang-format] BreakBeforeNoexceptSpecifier option
 added (#65808)

It really bugs me that it breaks to
``` c++
...) noexcept(
    noexcept(condition)...
```

This is a fix for people like me.
---
 clang/docs/ClangFormatStyleOptions.rst     | 48 ++++++++++++++++++++++
 clang/docs/ReleaseNotes.rst                |  1 +
 clang/include/clang/Format/Format.h        | 43 +++++++++++++++++++
 clang/lib/Format/Format.cpp                | 14 +++++++
 clang/lib/Format/TokenAnnotator.cpp        | 11 +++++
 clang/unittests/Format/ConfigParseTest.cpp |  8 ++++
 clang/unittests/Format/FormatTest.cpp      | 46 +++++++++++++++++++++
 7 files changed, 171 insertions(+)

diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index df27f6166d37105..44bffa41d1cde95 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1108,6 +1108,54 @@ the configuration (without a prefix: ``Auto``).
                     int d,
                     int e);
 
+.. _AllowBreakBeforeNoexceptSpecifier:
+
+**AllowBreakBeforeNoexceptSpecifier** (``BreakBeforeNoexceptSpecifierStyle``) :versionbadge:`clang-format 18` :ref:`¶ <AllowBreakBeforeNoexceptSpecifier>`
+  Controls if there could be a line break before a ``noexcept`` specifier.
+
+  Possible values:
+
+  * ``BBNSS_Never`` (in configuration: ``Never``)
+    No line break allowed.
+
+    .. code-block:: c++
+
+      void foo(int arg1,
+               double arg2) noexcept;
+
+      void bar(int arg1, double arg2) noexcept(
+          noexcept(baz(arg1)) &&
+          noexcept(baz(arg2)));
+
+  * ``BBNSS_OnlyWithParen`` (in configuration: ``OnlyWithParen``)
+    For a simple ``noexcept`` there is no line break allowed, but when we
+    have a condition it is.
+
+    .. code-block:: c++
+
+      void foo(int arg1,
+               double arg2) noexcept;
+
+      void bar(int arg1, double arg2)
+          noexcept(noexcept(baz(arg1)) &&
+                   noexcept(baz(arg2)));
+
+  * ``BBNSS_Always`` (in configuration: ``Always``)
+    Line breaks are allowed. But note that because of the associated
+    penalties ``clang-format`` often prefers not to break before the
+    ``noexcept``.
+
+    .. code-block:: c++
+
+      void foo(int arg1,
+               double arg2) noexcept;
+
+      void bar(int arg1, double arg2)
+          noexcept(noexcept(baz(arg1)) &&
+                   noexcept(baz(arg2)));
+
+
+
 .. _AllowShortBlocksOnASingleLine:
 
 **AllowShortBlocksOnASingleLine** (``ShortBlockStyle``) :versionbadge:`clang-format 3.5` :ref:`¶ <AllowShortBlocksOnASingleLine>`
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index fe857941171fa3d..cc8b2c3808933cb 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -389,6 +389,7 @@ AST Matchers
 
 clang-format
 ------------
+- Add ``AllowBreakBeforeNoexceptSpecifier`` option.
 
 libclang
 --------
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 7ebde3c174d2640..e0444966b3eabc7 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -593,6 +593,47 @@ struct FormatStyle {
   /// \version 3.3
   bool AllowAllParametersOfDeclarationOnNextLine;
 
+  /// Different ways to break before a noexcept specifier.
+  enum BreakBeforeNoexceptSpecifierStyle : int8_t {
+    /// No line break allowed.
+    /// \code
+    ///   void foo(int arg1,
+    ///            double arg2) noexcept;
+    ///
+    ///   void bar(int arg1, double arg2) noexcept(
+    ///       noexcept(baz(arg1)) &&
+    ///       noexcept(baz(arg2)));
+    /// \endcode
+    BBNSS_Never,
+    /// For a simple ``noexcept`` there is no line break allowed, but when we
+    /// have a condition it is.
+    /// \code
+    ///   void foo(int arg1,
+    ///            double arg2) noexcept;
+    ///
+    ///   void bar(int arg1, double arg2)
+    ///       noexcept(noexcept(baz(arg1)) &&
+    ///                noexcept(baz(arg2)));
+    /// \endcode
+    BBNSS_OnlyWithParen,
+    /// Line breaks are allowed. But note that because of the associated
+    /// penalties ``clang-format`` often prefers not to break before the
+    /// ``noexcept``.
+    /// \code
+    ///   void foo(int arg1,
+    ///            double arg2) noexcept;
+    ///
+    ///   void bar(int arg1, double arg2)
+    ///       noexcept(noexcept(baz(arg1)) &&
+    ///                noexcept(baz(arg2)));
+    /// \endcode
+    BBNSS_Always,
+  };
+
+  /// Controls if there could be a line break before a ``noexcept`` specifier.
+  /// \version 18
+  BreakBeforeNoexceptSpecifierStyle AllowBreakBeforeNoexceptSpecifier;
+
   /// Different styles for merging short blocks containing at most one
   /// statement.
   enum ShortBlockStyle : int8_t {
@@ -4576,6 +4617,8 @@ struct FormatStyle {
            AllowAllArgumentsOnNextLine == R.AllowAllArgumentsOnNextLine &&
            AllowAllParametersOfDeclarationOnNextLine ==
                R.AllowAllParametersOfDeclarationOnNextLine &&
+           AllowBreakBeforeNoexceptSpecifier ==
+               R.AllowBreakBeforeNoexceptSpecifier &&
            AllowShortBlocksOnASingleLine == R.AllowShortBlocksOnASingleLine &&
            AllowShortCaseLabelsOnASingleLine ==
                R.AllowShortCaseLabelsOnASingleLine &&
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 339af30e38a7a8f..8e9be6752ce5870 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -59,6 +59,16 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
 
 namespace llvm {
 namespace yaml {
+template <>
+struct ScalarEnumerationTraits<FormatStyle::BreakBeforeNoexceptSpecifierStyle> {
+  static void enumeration(IO &IO,
+                          FormatStyle::BreakBeforeNoexceptSpecifierStyle &Value) {
+    IO.enumCase(Value, "Never", FormatStyle::BBNSS_Never);
+    IO.enumCase(Value, "OnlyWithParen", FormatStyle::BBNSS_OnlyWithParen);
+    IO.enumCase(Value, "Always", FormatStyle::BBNSS_Always);
+  }
+};
+
 template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
   static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
     IO.enumCase(Value, "None",
@@ -260,6 +270,7 @@ struct ScalarEnumerationTraits<FormatStyle::BreakBeforeInlineASMColonStyle> {
     IO.enumCase(Value, "Always", FormatStyle::BBIAS_Always);
   }
 };
+
 template <>
 struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
   static void
@@ -904,6 +915,8 @@ template <> struct MappingTraits<FormatStyle> {
                    Style.AllowAllArgumentsOnNextLine);
     IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
                    Style.AllowAllParametersOfDeclarationOnNextLine);
+    IO.mapOptional("AllowBreakBeforeNoexceptSpecifier",
+                   Style.AllowBreakBeforeNoexceptSpecifier);
     IO.mapOptional("AllowShortBlocksOnASingleLine",
                    Style.AllowShortBlocksOnASingleLine);
     IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
@@ -1448,6 +1461,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
   LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
   LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always;
   LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;
+  LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;
   LLVMStyle.BreakBeforeTernaryOperators = true;
   LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
   LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 3e0599eb540a95f..2bb6565193cec83 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5654,6 +5654,17 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
       return !isItAnEmptyLambdaAllowed(Right, ShortLambdaOption);
   }
 
+  if (Right.is(tok::kw_noexcept) && Right.is(TT_TrailingAnnotation)) {
+    switch (Style.AllowBreakBeforeNoexceptSpecifier) {
+    case FormatStyle::BBNSS_Never:
+      return false;
+    case FormatStyle::BBNSS_Always:
+      return true;
+    case FormatStyle::BBNSS_OnlyWithParen:
+      return Right.Next && Right.Next->is(tok::l_paren);
+    }
+  }
+
   return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
                       tok::kw_class, tok::kw_struct, tok::comment) ||
          Right.isMemberAccess() ||
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index b3b6755cadee4ba..dedaf546ea5ff4f 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -953,6 +953,14 @@ TEST(ConfigParseTest, ParsesConfiguration) {
               FormatStyle::RPS_ReturnStatement);
   CHECK_PARSE("RemoveParentheses: Leave", RemoveParentheses,
               FormatStyle::RPS_Leave);
+
+  CHECK_PARSE("AllowBreakBeforeNoexceptSpecifier: Always",
+              AllowBreakBeforeNoexceptSpecifier, FormatStyle::BBNSS_Always);
+  CHECK_PARSE("AllowBreakBeforeNoexceptSpecifier: OnlyWithParen",
+              AllowBreakBeforeNoexceptSpecifier,
+              FormatStyle::BBNSS_OnlyWithParen);
+  CHECK_PARSE("AllowBreakBeforeNoexceptSpecifier: Never",
+              AllowBreakBeforeNoexceptSpecifier, FormatStyle::BBNSS_Never);
 }
 
 TEST(ConfigParseTest, ParsesConfigurationWithLanguages) {
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index cb4703804ebb36e..96c2dbf11eecdd4 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -26239,6 +26239,52 @@ TEST_F(FormatTest, RemoveParentheses) {
                Style);
 }
 
+TEST_F(FormatTest, AllowBreakBeforeNoexceptSpecifier) {
+  auto Style = getLLVMStyleWithColumns(35);
+
+  EXPECT_EQ(Style.AllowBreakBeforeNoexceptSpecifier, FormatStyle::BBNSS_Never);
+  verifyFormat("void foo(int arg1,\n"
+               "         double arg2) noexcept;",
+               Style);
+
+  // The following line does not fit within the 35 column limit, but that's what
+  // happens with no break allowed.
+  verifyFormat("void bar(int arg1, double arg2) noexcept(\n"
+               "    noexcept(baz(arg1)) &&\n"
+               "    noexcept(baz(arg2)));",
+               Style);
+
+  verifyFormat("void aVeryLongFunctionNameWithoutAnyArguments() noexcept;",
+               Style);
+
+  Style.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Always;
+  verifyFormat("void foo(int arg1,\n"
+               "         double arg2) noexcept;",
+               Style);
+
+  verifyFormat("void bar(int arg1, double arg2)\n"
+               "    noexcept(noexcept(baz(arg1)) &&\n"
+               "             noexcept(baz(arg2)));",
+               Style);
+
+  verifyFormat("void aVeryLongFunctionNameWithoutAnyArguments()\n"
+               "    noexcept;",
+               Style);
+
+  Style.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_OnlyWithParen;
+  verifyFormat("void foo(int arg1,\n"
+               "         double arg2) noexcept;",
+               Style);
+
+  verifyFormat("void bar(int arg1, double arg2)\n"
+               "    noexcept(noexcept(baz(arg1)) &&\n"
+               "             noexcept(baz(arg2)));",
+               Style);
+
+  verifyFormat("void aVeryLongFunctionNameWithoutAnyArguments() noexcept;",
+               Style);
+}
+
 } // namespace
 } // namespace test
 } // namespace format

>From 7a34f0b2cbc8387da2e7956499567ab49a5cf983 Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Sat, 9 Sep 2023 13:51:27 -0700
Subject: [PATCH 13/62] Switch MLIR to use the internal LIT shell by default 
 (#65415)

---
 .../Dialect/SparseTensor/CPU/dense_output.mlir         |  8 ++++----
 .../Dialect/SparseTensor/CPU/sparse_flatten.mlir       |  8 ++++----
 .../Dialect/SparseTensor/CPU/sparse_matvec.mlir        | 10 +++++-----
 .../Dialect/SparseTensor/CPU/sparse_mttkrp.mlir        |  8 ++++----
 .../Dialect/SparseTensor/CPU/sparse_out_simple.mlir    |  6 +++---
 .../SparseTensor/CPU/sparse_sampled_matmul.mlir        |  8 ++++----
 .../Dialect/SparseTensor/CPU/sparse_sorted_coo.mlir    |  8 ++++----
 .../Dialect/SparseTensor/CPU/sparse_spmm.mlir          |  8 ++++----
 .../Dialect/SparseTensor/CPU/sparse_sum.mlir           |  8 ++++----
 .../Dialect/SparseTensor/CPU/sparse_sum_c32.mlir       |  8 ++++----
 mlir/test/lit.cfg.py                                   |  9 ++++++++-
 11 files changed, 48 insertions(+), 41 deletions(-)

diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/dense_output.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/dense_output.mlir
index 674a1a78862eb49..7ee385263d314e6 100644
--- a/mlir/test/Integration/Dialect/SparseTensor/CPU/dense_output.mlir
+++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/dense_output.mlir
@@ -18,18 +18,18 @@
 //--------------------------------------------------------------------------------------------------
 
 // REDEFINE: %{env} = TENSOR0="%mlir_src_dir/test/Integration/data/test.mtx"
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation and vectorization.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false vl=2 reassociate-fp-reductions=true enable-index-optimizations=true
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation and VLA vectorization.
-// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | %{env} %{run_sve} | FileCheck %s %}
+// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | env %{env} %{run_sve} | FileCheck %s %}
 
 !Filename = !llvm.ptr<i8>
 
diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_flatten.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_flatten.mlir
index 238f0da0a9531ce..56a26ec08b61028 100644
--- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_flatten.mlir
+++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_flatten.mlir
@@ -18,18 +18,18 @@
 //--------------------------------------------------------------------------------------------------
 
 // REDEFINE: %{env} = TENSOR0="%mlir_src_dir/test/Integration/data/test.tns"
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation and vectorization.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false vl=2 reassociate-fp-reductions=true enable-index-optimizations=true
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation and VLA vectorization.
-// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | %{env} %{run_sve} | FileCheck %s %}
+// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | env %{env} %{run_sve} | FileCheck %s %}
 
 !Filename = !llvm.ptr<i8>
 
diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_matvec.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_matvec.mlir
index 4b9818890e6fbe2..cc3be3c823f53f2 100644
--- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_matvec.mlir
+++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_matvec.mlir
@@ -18,23 +18,23 @@
 //--------------------------------------------------------------------------------------------------
 
 // REDEFINE: %{env} = TENSOR0="%mlir_src_dir/test/Integration/data/wide.mtx"
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with parallelization strategy.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=true parallelization-strategy=any-storage-any-loop
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation and parallelization strategy.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false parallelization-strategy=any-storage-any-loop
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation and vectorization.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false vl=2 reassociate-fp-reductions=true enable-index-optimizations=true
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation and, if available, VLA
 // vectorization.
diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_mttkrp.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_mttkrp.mlir
index c48cdb10c6c0b65..e91fa97586b8c4a 100644
--- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_mttkrp.mlir
+++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_mttkrp.mlir
@@ -18,19 +18,19 @@
 //--------------------------------------------------------------------------------------------------
 
 // REDEFINE: %{env} = TENSOR0=%mlir_src_dir/test/Integration/data/mttkrp_b.tns
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation and vectorization.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false vl=2 reassociate-fp-reductions=true enable-index-optimizations=true
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation and, if available, VLA
 // vectorization.
-// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | %{env} %{run_sve} | FileCheck %s %}
+// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | env %{env} %{run_sve} | FileCheck %s %}
 
 !Filename = !llvm.ptr<i8>
 
diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_out_simple.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_out_simple.mlir
index fd36c815235b8ef..91b6b1517d8dbfe 100644
--- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_out_simple.mlir
+++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_out_simple.mlir
@@ -18,15 +18,15 @@
 //--------------------------------------------------------------------------------------------------
 
 // REDEFINE: %{env} = TENSOR0="%mlir_src_dir/test/Integration/data/test.mtx"
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation and vectorization.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false vl=2 reassociate-fp-reductions=true enable-index-optimizations=true
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation and, if available, VLA
 // vectorization.
-// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | %{env} %{run_sve} | FileCheck %s %}
+// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | env %{env} %{run_sve} | FileCheck %s %}
 
 !Filename = !llvm.ptr<i8>
 
diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sampled_matmul.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sampled_matmul.mlir
index b9f10ac34b731d8..491fadf4616c02d 100644
--- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sampled_matmul.mlir
+++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sampled_matmul.mlir
@@ -18,19 +18,19 @@
 //--------------------------------------------------------------------------------------------------
 
 // REDEFINE: %{env} = TENSOR0="%mlir_src_dir/test/Integration/data/test.mtx"
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation and vectorization.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false vl=2 reassociate-fp-reductions=true enable-index-optimizations=true
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation and, if available, VLA
 // vectorization.
-// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | %{env} %{run_sve} | FileCheck %s %}
+// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | env %{env} %{run_sve} | FileCheck %s %}
 
 !Filename = !llvm.ptr<i8>
 
diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sorted_coo.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sorted_coo.mlir
index 06209829918c4dd..177272e45a10c5c 100644
--- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sorted_coo.mlir
+++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sorted_coo.mlir
@@ -19,18 +19,18 @@
 
 // REDEFINE: %{env} = TENSOR0="%mlir_src_dir/test/Integration/data/wide.mtx" \
 // REDEFINE: TENSOR1="%mlir_src_dir/test/Integration/data/mttkrp_b.tns"
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false enable-buffer-initialization=true
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with vectorization.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false vl=4 enable-buffer-initialization=true
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with  VLA vectorization.
-// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | %{env} %{run_sve} | FileCheck %s %}
+// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | env %{env} %{run_sve} | FileCheck %s %}
 
 !Filename = !llvm.ptr<i8>
 
diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_spmm.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_spmm.mlir
index a2926607599d5ed..59ea9a8114c53a8 100644
--- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_spmm.mlir
+++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_spmm.mlir
@@ -18,18 +18,18 @@
 //--------------------------------------------------------------------------------------------------
 
 // REDEFINE: %{env} = TENSOR0="%mlir_src_dir/test/Integration/data/wide.mtx"
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with vectorization.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false vl=2 reassociate-fp-reductions=true enable-index-optimizations=true
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with  VLA vectorization.
-// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | %{env} %{run_sve} | FileCheck %s %}
+// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | env %{env} %{run_sve} | FileCheck %s %}
 
 !Filename = !llvm.ptr<i8>
 
diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sum.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sum.mlir
index bb2d1e5b88fcac8..a00f4d0018a20f7 100644
--- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sum.mlir
+++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sum.mlir
@@ -18,18 +18,18 @@
 //--------------------------------------------------------------------------------------------------
 
 // REDEFINE: %{env} = TENSOR0=%mlir_src_dir/test/Integration/data/test_symmetric.mtx
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with vectorization.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false vl=2 reassociate-fp-reductions=true enable-index-optimizations=true
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with  VLA vectorization.
-// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | %{env} %{run_sve} | FileCheck %s %}
+// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | env %{env} %{run_sve} | FileCheck %s %}
 
 // TODO: The test currently only operates on the triangular part of the
 // symmetric matrix.
diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sum_c32.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sum_c32.mlir
index 0d75dc5f5e03822..10a05b6a7ba01c6 100644
--- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sum_c32.mlir
+++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_sum_c32.mlir
@@ -18,18 +18,18 @@
 //--------------------------------------------------------------------------------------------------
 
 // REDEFINE: %{env} = TENSOR0="%mlir_src_dir/test/Integration/data/test_symmetric_complex.mtx"
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with direct IR generation.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with vectorization.
 // REDEFINE: %{sparse_compiler_opts} = enable-runtime-library=false vl=2 reassociate-fp-reductions=true enable-index-optimizations=true
-// RUN: %{compile} | %{env} %{run} | FileCheck %s
+// RUN: %{compile} | env %{env} %{run} | FileCheck %s
 //
 // Do the same run, but now with  VLA vectorization.
-// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | %{env} %{run_sve} | FileCheck %s %}
+// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | env %{env} %{run_sve} | FileCheck %s %}
 
 // TODO: The test currently only operates on the triangular part of the
 // symmetric matrix.
diff --git a/mlir/test/lit.cfg.py b/mlir/test/lit.cfg.py
index f265ac794c6f6db..da8488373862c36 100644
--- a/mlir/test/lit.cfg.py
+++ b/mlir/test/lit.cfg.py
@@ -18,7 +18,14 @@
 # name: The name of this test suite.
 config.name = "MLIR"
 
-config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell)
+# We prefer the lit internal shell which provides a better user experience on failures
+# unless the user explicitly disables it with LIT_USE_INTERNAL_SHELL=0 env var.
+use_lit_shell = True
+lit_shell_env = os.environ.get("LIT_USE_INTERNAL_SHELL")
+if lit_shell_env:
+  use_lit_shell = not lit.util.pythonize_bool(lit_shell_env)
+
+config.test_format = lit.formats.ShTest(execute_external=not use_lit_shell)
 
 # suffixes: A list of file extensions to treat as test files.
 config.suffixes = [

>From f90ded8ab9c83b1956c0829be845d4fa6eb80324 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Sat, 9 Sep 2023 13:23:03 -0700
Subject: [PATCH 14/62] [NFC][sanitizer] Return nullptr instead of 0

---
 .../lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
index cc02c77bccdc91d..d78dab93487f1b6 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
@@ -199,7 +199,7 @@ static char *DemangleAlloc(const char *name, bool always_alloc) {
 #endif
   if (always_alloc)
     return internal_strdup(name);
-  return 0;
+  return nullptr;
 }
 
 const char *LibbacktraceSymbolizer::Demangle(const char *name) {

>From 32db74aaafed963d6df645ce144a286c9711a00d Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Sat, 9 Sep 2023 13:27:11 -0700
Subject: [PATCH 15/62] [NFC][sanitizer] Clarify nullability of
 Symbolizer::Demangle result

---
 compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h      | 2 +-
 .../lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp    | 5 ++++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h
index df24aaca3abf645..d0b0f827200e950 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h
@@ -136,7 +136,7 @@ class Symbolizer final {
 
   // Release internal caches (if any).
   void Flush();
-  // Attempts to demangle the provided C++ mangled name.
+  // Attempts to demangle the provided C++ mangled name. Never returns nullptr.
   const char *Demangle(const char *name);
 
   // Allow user to install hooks that would be called before/after Symbolizer
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
index a6f82ced2036731..d910aef3f741627 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
@@ -159,13 +159,16 @@ void Symbolizer::Flush() {
 }
 
 const char *Symbolizer::Demangle(const char *name) {
+  CHECK(name);
   Lock l(&mu_);
   for (auto &tool : tools_) {
     SymbolizerScope sym_scope(this);
     if (const char *demangled = tool.Demangle(name))
       return demangled;
   }
-  return PlatformDemangle(name);
+  if (const char *demangled = PlatformDemangle(name))
+    return demangled;
+  return name;
 }
 
 bool Symbolizer::FindModuleNameAndOffsetForAddress(uptr address,

>From 25d7fe52a283fb1044e4b9dff18fae6d170362b0 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Sat, 9 Sep 2023 13:38:48 -0700
Subject: [PATCH 16/62] [NFC][sanitizer] Return nullptr from PlatformDemangle

Use fallback name only on the top level, in Symbolizer::Demangle or
DlAddrSymbolizer. This makes PlatformDemangle to be more consistent with
SymbolizerTool and the loop in Symbolizer::Demangle which iterates over
all availible options.
---
 compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h     | 2 +-
 .../lib/sanitizer_common/sanitizer_symbolizer_mac.cpp       | 5 ++++-
 .../sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp | 2 +-
 .../lib/sanitizer_common/sanitizer_symbolizer_win.cpp       | 4 +---
 .../sanitizer_common/tests/sanitizer_symbolizer_test.cpp    | 6 +++---
 5 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h
index d0b0f827200e950..7fb7928dce0d8d4 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h
@@ -187,7 +187,7 @@ class Symbolizer final {
   // If stale, need to reload the modules before looking up addresses.
   bool modules_fresh_;
 
-  // Platform-specific default demangler, must not return nullptr.
+  // Platform-specific default demangler, returns nullptr on failure.
   const char *PlatformDemangle(const char *name);
 
   static Symbolizer *symbolizer_;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp
index a9c958b2d100136..f1cc0b5e1e8ac0a 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp
@@ -42,7 +42,8 @@ bool DlAddrSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
   }
 
   const char *demangled = DemangleSwiftAndCXX(info.dli_sname);
-  if (!demangled) return false;
+  if (!demangled)
+    demangled = info.dli_sname;
   stack->info.function = internal_strdup(demangled);
   return true;
 }
@@ -52,6 +53,8 @@ bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) {
   int result = dladdr((const void *)addr, &info);
   if (!result) return false;
   const char *demangled = DemangleSwiftAndCXX(info.dli_sname);
+  if (!demangled)
+    demangled = info.dli_sname;
   datainfo->name = internal_strdup(demangled);
   datainfo->start = (uptr)info.dli_saddr;
   return true;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
index 1a5e38faea88747..1317facec170416 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
@@ -56,7 +56,7 @@ const char *DemangleCXXABI(const char *name) {
           __cxxabiv1::__cxa_demangle(name, 0, 0, 0))
       return demangled_name;
 
-  return name;
+  return nullptr;
 }
 
 // As of now, there are no headers for the Swift runtime. Once they are
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cpp
index ae2d3be19ef38d0..56cde2dcef1e0a9 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cpp
@@ -175,9 +175,7 @@ const char *WinSymbolizerTool::Demangle(const char *name) {
     return name;
 }
 
-const char *Symbolizer::PlatformDemangle(const char *name) {
-  return name;
-}
+const char *Symbolizer::PlatformDemangle(const char *name) { return nullptr; }
 
 namespace {
 struct ScopedHandle {
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cpp
index 1e70c146b46ceb1..b8267e400799798 100644
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cpp
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cpp
@@ -58,13 +58,13 @@ TEST(Symbolizer, ExtractTokenUpToDelimiter) {
 TEST(Symbolizer, DemangleSwiftAndCXX) {
   // Swift names are not demangled in default llvm build because Swift
   // runtime is not linked in.
-  EXPECT_STREQ("_TtSd", DemangleSwiftAndCXX("_TtSd"));
+  EXPECT_STREQ(nullptr, DemangleSwiftAndCXX("_TtSd"));
   // Check that the rest demangles properly.
   EXPECT_STREQ("f1(char*, int)", DemangleSwiftAndCXX("_Z2f1Pci"));
 #if !SANITIZER_FREEBSD // QoI issue with libcxxrt on FreeBSD
-  EXPECT_STREQ("foo", DemangleSwiftAndCXX("foo"));
+  EXPECT_STREQ(nullptr, DemangleSwiftAndCXX("foo"));
 #endif
-  EXPECT_STREQ("", DemangleSwiftAndCXX(""));
+  EXPECT_STREQ(nullptr, DemangleSwiftAndCXX(""));
 }
 #endif
 

>From fcab65f74b056aaf24b56b60fc3cfce5bcc4441c Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Sat, 9 Sep 2023 15:28:42 -0700
Subject: [PATCH 17/62] Fix MLIR integration test that requires ARM SVE to
 reproduce

Fix-forward for a9f30097586e914e074111d966c1408e82d04a8d
---
 .../Integration/Dialect/SparseTensor/CPU/sparse_matvec.mlir     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_matvec.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_matvec.mlir
index cc3be3c823f53f2..65b5e5610a55be0 100644
--- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_matvec.mlir
+++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_matvec.mlir
@@ -38,7 +38,7 @@
 //
 // Do the same run, but now with direct IR generation and, if available, VLA
 // vectorization.
-// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | %{env} %{run_sve} | FileCheck %s %}
+// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | env %{env} %{run_sve} | FileCheck %s %}
 
 !Filename = !llvm.ptr<i8>
 

>From 12401a81b795cc4798101a0b26d110864758da95 Mon Sep 17 00:00:00 2001
From: Shilei Tian <i at tianshilei.me>
Date: Sat, 9 Sep 2023 18:51:58 -0400
Subject: [PATCH 18/62] [Clang][OpenMP] Emit unroll directive w/o captured stmt
 (#65862)

The front end doesn't create captured stmt for unroll directive. This
leads to
a crash when `-fopenmp-simd` is used, as reported in #63570.

Fix #63570.
---
 clang/lib/CodeGen/CGStmtOpenMP.cpp |  3 ++-
 clang/test/OpenMP/bug63570.c       | 10 ++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/OpenMP/bug63570.c

diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 6eca0a5ccab41d7..a4e80a4a9e1fd75 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -8064,7 +8064,8 @@ void CodeGenFunction::EmitSimpleOMPExecutableDirective(
       D.getDirectiveKind() == OMPD_critical ||
       D.getDirectiveKind() == OMPD_section ||
       D.getDirectiveKind() == OMPD_master ||
-      D.getDirectiveKind() == OMPD_masked) {
+      D.getDirectiveKind() == OMPD_masked ||
+      D.getDirectiveKind() == OMPD_unroll) {
     EmitStmt(D.getAssociatedStmt());
   } else {
     auto LPCRegion =
diff --git a/clang/test/OpenMP/bug63570.c b/clang/test/OpenMP/bug63570.c
new file mode 100644
index 000000000000000..f61a2ee49b388d0
--- /dev/null
+++ b/clang/test/OpenMP/bug63570.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -verify -fopenmp -x c -triple x86_64-apple-darwin10 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c -triple x86_64-apple-darwin10 %s
+// expected-no-diagnostics
+
+void f(float *a, float *b) {
+#pragma omp unroll
+  for (int i = 0; i < 128; i++) {
+    a[i] = b[i];
+  }
+}

>From b15d7d492bf825d9903bea6b5d8b311d43f47f0d Mon Sep 17 00:00:00 2001
From: "Kazushi (Jam) Marukawa" <marukawa at nec.com>
Date: Sat, 20 Nov 2021 21:45:52 +0900
Subject: [PATCH 19/62] [OpenMP][VE] Support OpenMP runtime on VE

Support OpenMP runtime library on VE.  This patch makes OpenMP compilable
for VE architecture.  Almost all tests run correctly on VE.

Reviewed By: tianshilei1992

Differential Revision: https://reviews.llvm.org/D159401
---
 openmp/runtime/CMakeLists.txt                 |   9 +-
 .../runtime/cmake/LibompGetArchitecture.cmake |   2 +
 openmp/runtime/cmake/LibompUtils.cmake        |   2 +
 openmp/runtime/src/kmp.h                      |   4 +
 openmp/runtime/src/kmp_affinity.h             |  11 +
 openmp/runtime/src/kmp_os.h                   |   4 +-
 openmp/runtime/src/kmp_platform.h             |   6 +-
 openmp/runtime/src/kmp_runtime.cpp            |   2 +-
 .../thirdparty/ittnotify/ittnotify_config.h   |   6 +
 openmp/runtime/src/z_Linux_asm.S              | 197 +++++++++++++++++-
 openmp/runtime/src/z_Linux_util.cpp           |   2 +-
 openmp/runtime/test/ompt/callback.h           |   7 +
 12 files changed, 243 insertions(+), 9 deletions(-)

diff --git a/openmp/runtime/CMakeLists.txt b/openmp/runtime/CMakeLists.txt
index 2b7a3eb5bfce932..4441c4babdc07c0 100644
--- a/openmp/runtime/CMakeLists.txt
+++ b/openmp/runtime/CMakeLists.txt
@@ -30,7 +30,7 @@ if(${OPENMP_STANDALONE_BUILD})
   # If adding a new architecture, take a look at cmake/LibompGetArchitecture.cmake
   libomp_get_architecture(LIBOMP_DETECTED_ARCH)
   set(LIBOMP_ARCH ${LIBOMP_DETECTED_ARCH} CACHE STRING
-    "The architecture to build for (x86_64/i386/arm/ppc64/ppc64le/aarch64/mic/mips/mips64/riscv64/loongarch64).")
+    "The architecture to build for (x86_64/i386/arm/ppc64/ppc64le/aarch64/mic/mips/mips64/riscv64/loongarch64/ve).")
   # Should assertions be enabled?  They are on by default.
   set(LIBOMP_ENABLE_ASSERTIONS TRUE CACHE BOOL
     "enable assertions?")
@@ -63,6 +63,8 @@ else() # Part of LLVM build
     set(LIBOMP_ARCH riscv64)
   elseif(LIBOMP_NATIVE_ARCH MATCHES "loongarch64")
     set(LIBOMP_ARCH loongarch64)
+  elseif(LIBOMP_NATIVE_ARCH MATCHES "ve")
+    set(LIBOMP_ARCH ve)
   else()
     # last ditch effort
     libomp_get_architecture(LIBOMP_ARCH)
@@ -83,7 +85,7 @@ if(LIBOMP_ARCH STREQUAL "aarch64")
   endif()
 endif()
 
-libomp_check_variable(LIBOMP_ARCH 32e x86_64 32 i386 arm ppc64 ppc64le aarch64 aarch64_a64fx mic mips mips64 riscv64 loongarch64)
+libomp_check_variable(LIBOMP_ARCH 32e x86_64 32 i386 arm ppc64 ppc64le aarch64 aarch64_a64fx mic mips mips64 riscv64 loongarch64 ve)
 
 set(LIBOMP_LIB_TYPE normal CACHE STRING
   "Performance,Profiling,Stubs library (normal/profile/stubs)")
@@ -162,6 +164,7 @@ set(MIPS64 FALSE)
 set(MIPS FALSE)
 set(RISCV64 FALSE)
 set(LOONGARCH64 FALSE)
+set(VE FALSE)
 if("${LIBOMP_ARCH}" STREQUAL "i386" OR "${LIBOMP_ARCH}" STREQUAL "32")    # IA-32 architecture
   set(IA32 TRUE)
 elseif("${LIBOMP_ARCH}" STREQUAL "x86_64" OR "${LIBOMP_ARCH}" STREQUAL "32e") # Intel(R) 64 architecture
@@ -188,6 +191,8 @@ elseif("${LIBOMP_ARCH}" STREQUAL "riscv64") # RISCV64 architecture
     set(RISCV64 TRUE)
 elseif("${LIBOMP_ARCH}" STREQUAL "loongarch64") # LoongArch64 architecture
     set(LOONGARCH64 TRUE)
+elseif("${LIBOMP_ARCH}" STREQUAL "ve") # VE architecture
+    set(VE TRUE)
 endif()
 
 # Set some flags based on build_type
diff --git a/openmp/runtime/cmake/LibompGetArchitecture.cmake b/openmp/runtime/cmake/LibompGetArchitecture.cmake
index c338493bad538ec..98bfce9ae990a7b 100644
--- a/openmp/runtime/cmake/LibompGetArchitecture.cmake
+++ b/openmp/runtime/cmake/LibompGetArchitecture.cmake
@@ -49,6 +49,8 @@ function(libomp_get_architecture return_arch)
       #error ARCHITECTURE=riscv64
     #elif defined(__loongarch__) && __loongarch_grlen == 64
       #error ARCHITECTURE=loongarch64
+    #elif defined(__ve__)
+      #error ARCHITECTURE=ve
     #else
       #error ARCHITECTURE=UnknownArchitecture
     #endif
diff --git a/openmp/runtime/cmake/LibompUtils.cmake b/openmp/runtime/cmake/LibompUtils.cmake
index b5ffc97fca3d217..0151ca0ea826bd7 100644
--- a/openmp/runtime/cmake/LibompUtils.cmake
+++ b/openmp/runtime/cmake/LibompUtils.cmake
@@ -111,6 +111,8 @@ function(libomp_get_legal_arch return_arch_string)
     set(${return_arch_string} "RISCV64" PARENT_SCOPE)
   elseif(${LOONGARCH64})
     set(${return_arch_string} "LOONGARCH64" PARENT_SCOPE)
+  elseif(${VE})
+    set(${return_arch_string} "VE" PARENT_SCOPE)
   else()
     set(${return_arch_string} "${LIBOMP_ARCH}" PARENT_SCOPE)
     libomp_warning_say("libomp_get_legal_arch(): Warning: Unknown architecture: Using ${LIBOMP_ARCH}")
diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h
index 33895f8fbb1e36f..f6bfa242aaa55f3 100644
--- a/openmp/runtime/src/kmp.h
+++ b/openmp/runtime/src/kmp.h
@@ -1170,6 +1170,10 @@ extern void __kmp_init_target_task();
 #elif KMP_ARCH_X86_64
 #define KMP_DEFAULT_STKSIZE ((size_t)(4 * 1024 * 1024))
 #define KMP_BACKUP_STKSIZE ((size_t)(2 * 1024 * 1024))
+#elif KMP_ARCH_VE
+// Minimum stack size for pthread for VE is 4MB.
+//   https://www.hpc.nec/documents/veos/en/glibc/Difference_Points_glibc.htm
+#define KMP_DEFAULT_STKSIZE ((size_t)(4 * 1024 * 1024))
 #else
 #define KMP_DEFAULT_STKSIZE ((size_t)(1024 * 1024))
 #endif
diff --git a/openmp/runtime/src/kmp_affinity.h b/openmp/runtime/src/kmp_affinity.h
index fbc0d400de772e0..97808b528538097 100644
--- a/openmp/runtime/src/kmp_affinity.h
+++ b/openmp/runtime/src/kmp_affinity.h
@@ -286,6 +286,17 @@ class KMPHwlocAffinity : public KMPAffinity {
 #elif __NR_sched_getaffinity != 123
 #error Wrong code for getaffinity system call.
 #endif /* __NR_sched_getaffinity */
+#elif KMP_ARCH_VE
+#ifndef __NR_sched_setaffinity
+#define __NR_sched_setaffinity 203
+#elif __NR_sched_setaffinity != 203
+#error Wrong code for setaffinity system call.
+#endif /* __NR_sched_setaffinity */
+#ifndef __NR_sched_getaffinity
+#define __NR_sched_getaffinity 204
+#elif __NR_sched_getaffinity != 204
+#error Wrong code for getaffinity system call.
+#endif /* __NR_sched_getaffinity */
 #else
 #error Unknown or unsupported architecture
 #endif /* KMP_ARCH_* */
diff --git a/openmp/runtime/src/kmp_os.h b/openmp/runtime/src/kmp_os.h
index fec589ab6018a9c..2c632112a8d8e35 100644
--- a/openmp/runtime/src/kmp_os.h
+++ b/openmp/runtime/src/kmp_os.h
@@ -178,7 +178,7 @@ typedef unsigned long long kmp_uint64;
 #if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS
 #define KMP_SIZE_T_SPEC KMP_UINT32_SPEC
 #elif KMP_ARCH_X86_64 || KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 ||                 \
-    KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64
+    KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || KMP_ARCH_VE
 #define KMP_SIZE_T_SPEC KMP_UINT64_SPEC
 #else
 #error "Can't determine size_t printf format specifier."
@@ -1043,7 +1043,7 @@ extern kmp_real64 __kmp_xchg_real64(volatile kmp_real64 *p, kmp_real64 v);
 #endif /* KMP_OS_WINDOWS */
 
 #if KMP_ARCH_PPC64 || KMP_ARCH_ARM || KMP_ARCH_AARCH64 || KMP_ARCH_MIPS ||     \
-    KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64
+    KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || KMP_ARCH_VE
 #if KMP_OS_WINDOWS
 #undef KMP_MB
 #define KMP_MB() std::atomic_thread_fence(std::memory_order_seq_cst)
diff --git a/openmp/runtime/src/kmp_platform.h b/openmp/runtime/src/kmp_platform.h
index fcfd8bc5d8d9ae3..1a2197d338342ac 100644
--- a/openmp/runtime/src/kmp_platform.h
+++ b/openmp/runtime/src/kmp_platform.h
@@ -93,6 +93,7 @@
 #define KMP_ARCH_MIPS64 0
 #define KMP_ARCH_RISCV64 0
 #define KMP_ARCH_LOONGARCH64 0
+#define KMP_ARCH_VE 0
 
 #if KMP_OS_WINDOWS
 #if defined(_M_AMD64) || defined(__x86_64)
@@ -142,6 +143,9 @@
 #elif defined __loongarch__ && __loongarch_grlen == 64
 #undef KMP_ARCH_LOONGARCH64
 #define KMP_ARCH_LOONGARCH64 1
+#elif defined __ve__
+#undef KMP_ARCH_VE
+#define KMP_ARCH_VE 1
 #endif
 #endif
 
@@ -206,7 +210,7 @@
 // TODO: Fixme - This is clever, but really fugly
 #if (1 != KMP_ARCH_X86 + KMP_ARCH_X86_64 + KMP_ARCH_ARM + KMP_ARCH_PPC64 +     \
               KMP_ARCH_AARCH64 + KMP_ARCH_MIPS + KMP_ARCH_MIPS64 +             \
-              KMP_ARCH_RISCV64 + KMP_ARCH_LOONGARCH64)
+              KMP_ARCH_RISCV64 + KMP_ARCH_LOONGARCH64 + KMP_ARCH_VE)
 #error Unknown or unsupported architecture
 #endif
 
diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp
index 6a1ba97311dcc68..385fb6bc49cc5c7 100644
--- a/openmp/runtime/src/kmp_runtime.cpp
+++ b/openmp/runtime/src/kmp_runtime.cpp
@@ -8830,7 +8830,7 @@ __kmp_determine_reduction_method(
     int atomic_available = FAST_REDUCTION_ATOMIC_METHOD_GENERATED;
 
 #if KMP_ARCH_X86_64 || KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 ||                   \
-    KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64
+    KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || KMP_ARCH_VE
 
 #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||     \
     KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_DARWIN || KMP_OS_HURD
diff --git a/openmp/runtime/src/thirdparty/ittnotify/ittnotify_config.h b/openmp/runtime/src/thirdparty/ittnotify/ittnotify_config.h
index a452b7643bdb436..ff37eb4ed175e67 100644
--- a/openmp/runtime/src/thirdparty/ittnotify/ittnotify_config.h
+++ b/openmp/runtime/src/thirdparty/ittnotify/ittnotify_config.h
@@ -162,6 +162,10 @@
 #define ITT_ARCH_ARM64 6
 #endif /* ITT_ARCH_ARM64 */
 
+#ifndef ITT_ARCH_VE
+#define ITT_ARCH_VE 8
+#endif /* ITT_ARCH_VE */
+
 #ifndef ITT_ARCH
 #if defined _M_IX86 || defined __i386__
 #define ITT_ARCH ITT_ARCH_IA32
@@ -175,6 +179,8 @@
 #define ITT_ARCH ITT_ARCH_ARM64
 #elif defined __powerpc64__
 #define ITT_ARCH ITT_ARCH_PPC64
+#elif defined __ve__
+#define ITT_ARCH ITT_ARCH_VE
 #endif
 #endif
 
diff --git a/openmp/runtime/src/z_Linux_asm.S b/openmp/runtime/src/z_Linux_asm.S
index 27b063f09e7a16d..2c0df6e3b08505a 100644
--- a/openmp/runtime/src/z_Linux_asm.S
+++ b/openmp/runtime/src/z_Linux_asm.S
@@ -2060,6 +2060,198 @@ __kmp_invoke_microtask:
 
 #endif /* KMP_ARCH_LOONGARCH64 */
 
+#if KMP_ARCH_VE
+
+//------------------------------------------------------------------------
+//
+// typedef void (*microtask_t)(int *gtid, int *tid, ...);
+//
+// int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc,
+//                            void *p_argv[]
+// #if OMPT_SUPPORT
+//                            ,
+//                            void **exit_frame_ptr
+// #endif
+//                            ) {
+// #if OMPT_SUPPORT
+//   *exit_frame_ptr = OMPT_GET_FRAME_ADDRESS(0);
+// #endif
+//
+//   (*pkfn)(&gtid, &tid, argv[0], ...);
+//
+//   return 1;
+// }
+//
+// Parameters:
+//   s0: pkfn
+//   s1: gtid
+//   s2: tid
+//   s3: argc
+//   s4: p_argv
+//   s5: exit_frame_ptr
+//
+// Locals:
+//   __gtid: gtid param pushed on stack so can pass &gtid to pkfn
+//   __tid: tid param pushed on stack so can pass &tid to pkfn
+//
+// Temp. registers:
+//
+//  s34: used to calculate the dynamic stack size
+//  s35: used as temporary for stack placement calculation
+//  s36: used as temporary for stack arguments
+//  s37: used as temporary for number of remaining pkfn parms
+//  s38: used to traverse p_argv array
+//
+// return: s0 (always 1/TRUE)
+//
+
+__gtid = -4
+__tid = -8
+
+// -- Begin __kmp_invoke_microtask
+// mark_begin;
+	.text
+	.globl	__kmp_invoke_microtask
+	// A function requires 8 bytes align.
+	.p2align	3
+	.type	__kmp_invoke_microtask, at function
+__kmp_invoke_microtask:
+	.cfi_startproc
+
+	// First, save fp and lr.  VE stores them at caller stack frame.
+	st	%fp, 0(, %sp)
+	st	%lr, 8(, %sp)
+	or	%fp, 0, %sp
+	.cfi_def_cfa	%fp, 0
+	.cfi_offset	%lr, 8
+	.cfi_offset	%fp, 0
+
+	// Compute the dynamic stack size:
+	//
+	// - We need 8 bytes for storing 'gtid' and 'tid', so we can pass them
+	//   by reference
+	// - We need 8 bytes for whole arguments.  We have two + 'argc'
+	//   arguments (condider &gtid and &tid).  We need to reserve
+	//   (argc + 2) * 8 bytes.
+	// - We need 176 bytes for RSA and others
+	//
+	// The total number of bytes is then (argc + 2) * 8 + 8 + 176.
+	//
+	// |------------------------------|
+	// | return address of callee     | 8(%fp)
+	// |------------------------------|
+	// | frame pointer of callee      | 0(%fp)
+	// |------------------------------| <------------------ %fp
+	// | __tid / __gtid               | -8(%fp) / -4(%fp)
+	// |------------------------------|
+	// | argc+2 for arguments         | 176(%sp)
+	// |------------------------------|
+	// | RSA                          |
+	// |------------------------------|
+	// | return address               |
+	// |------------------------------|
+	// | frame pointer                |
+	// |------------------------------| <------------------ %sp
+
+	adds.w.sx	%s34, 2, %s3
+	sll	%s34, %s34, 3
+	lea	%s34, 184(, %s34)
+	subs.l	%sp, %sp, %s34
+
+	// Align the stack to 16 bytes.
+	and	%sp, -16, %sp
+
+	// Save pkfn.
+	or	%s12, 0, %s0
+
+	// Call host to allocate stack if it is necessary.
+	brge.l	%sp, %sl, .L_kmp_pass
+	ld	%s61, 24(, %tp)
+	lea	%s63, 0x13b
+	shm.l	%s63, 0(%s61)
+	shm.l	%sl, 8(%s61)
+	shm.l	%sp, 16(%s61)
+	monc
+
+.L_kmp_pass:
+	lea	%s35, 176(, %sp)
+	adds.w.sx	%s37, 0, %s3
+	or	%s38, 0, %s4
+
+#if OMPT_SUPPORT
+	// Save frame pointer into exit_frame.
+	st	%fp, 0(%s5)
+#endif
+
+	// Prepare arguments for the pkfn function (first 8 using s0-s7
+	// registers, but need to store stack also because of varargs).
+
+	stl	%s1, __gtid(%fp)
+	stl	%s2, __tid(%fp)
+
+	adds.l	%s0, __gtid, %fp
+	st	%s0, 0(, %s35)
+	adds.l	%s1, __tid, %fp
+	st	%s1, 8(, %s35)
+
+	breq.l	0, %s37, .L_kmp_call
+	ld	%s2, 0(, %s38)
+	st	%s2, 16(, %s35)
+
+	breq.l	1, %s37, .L_kmp_call
+	ld	%s3, 8(, %s38)
+	st	%s3, 24(, %s35)
+
+	breq.l	2, %s37, .L_kmp_call
+	ld	%s4, 16(, %s38)
+	st	%s4, 32(, %s35)
+
+	breq.l	3, %s37, .L_kmp_call
+	ld	%s5, 24(, %s38)
+	st	%s5, 40(, %s35)
+
+	breq.l	4, %s37, .L_kmp_call
+	ld	%s6, 32(, %s38)
+	st	%s6, 48(, %s35)
+
+	breq.l	5, %s37, .L_kmp_call
+	ld	%s7, 40(, %s38)
+	st	%s7, 56(, %s35)
+
+	breq.l	6, %s37, .L_kmp_call
+
+	// Prepare any additional argument passed through the stack.
+	adds.l	%s37, -6, %s37
+	lea	%s38, 48(, %s38)
+	lea	%s35, 64(, %s35)
+.L_kmp_loop:
+	ld	%s36, 0(, %s38)
+	st	%s36, 0(, %s35)
+	adds.l	%s37, -1, %s37
+	adds.l	%s38, 8, %s38
+	adds.l	%s35, 8, %s35
+	brne.l	0, %s37, .L_kmp_loop
+
+.L_kmp_call:
+	// Call pkfn function.
+	bsic	%lr, (, %s12)
+
+	// Return value.
+	lea	%s0, 1
+
+	// Restore stack and return.
+	or	%sp, 0, %fp
+	ld	%lr, 8(, %sp)
+	ld	%fp, 0(, %sp)
+	b.l.t	(, %lr)
+.Lfunc_end0:
+	.size	__kmp_invoke_microtask, .Lfunc_end0-__kmp_invoke_microtask
+	.cfi_endproc
+
+// -- End  __kmp_invoke_microtask
+
+#endif /* KMP_ARCH_VE */
+
 #if KMP_ARCH_ARM || KMP_ARCH_MIPS
     .data
     COMMON .gomp_critical_user_, 32, 3
@@ -2073,7 +2265,8 @@ __kmp_unnamed_critical_addr:
 #endif
 #endif /* KMP_ARCH_ARM */
 
-#if KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 || KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64
+#if KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 || KMP_ARCH_MIPS64 ||                   \
+    KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || KMP_ARCH_VE
 #ifndef KMP_PREFIX_UNDERSCORE
 # define KMP_PREFIX_UNDERSCORE(x) x
 #endif
@@ -2088,7 +2281,7 @@ KMP_PREFIX_UNDERSCORE(__kmp_unnamed_critical_addr):
     .size KMP_PREFIX_UNDERSCORE(__kmp_unnamed_critical_addr),8
 #endif
 #endif /* KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 || KMP_ARCH_MIPS64 ||
-          KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 */
+          KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || KMP_ARCH_VE */
 
 #if KMP_OS_LINUX
 # if KMP_ARCH_ARM || KMP_ARCH_AARCH64
diff --git a/openmp/runtime/src/z_Linux_util.cpp b/openmp/runtime/src/z_Linux_util.cpp
index ad3cb05fc37acdb..11d9ac8dc44792f 100644
--- a/openmp/runtime/src/z_Linux_util.cpp
+++ b/openmp/runtime/src/z_Linux_util.cpp
@@ -2456,7 +2456,7 @@ int __kmp_get_load_balance(int max) {
 #if !(KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_MIC ||                            \
       ((KMP_OS_LINUX || KMP_OS_DARWIN) && KMP_ARCH_AARCH64) ||                 \
       KMP_ARCH_PPC64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 ||            \
-      KMP_ARCH_ARM)
+      KMP_ARCH_ARM || KMP_ARCH_VE)
 
 // we really only need the case with 1 argument, because CLANG always build
 // a struct of pointers to shared variables referenced in the outlined function
diff --git a/openmp/runtime/test/ompt/callback.h b/openmp/runtime/test/ompt/callback.h
index 8180b3d2663f769..c5266e230c26f77 100644
--- a/openmp/runtime/test/ompt/callback.h
+++ b/openmp/runtime/test/ompt/callback.h
@@ -221,6 +221,13 @@ ompt_label_##id:
   printf("%" PRIu64 ": current_address=%p or %p or %p\n",                      \
          ompt_get_thread_data()->value, ((char *)addr) - 4,                    \
          ((char *)addr) - 8, ((char *)addr) - 12)
+#elif KMP_ARCH_VE
+// On VE the NOP instruction is 8 byte long. In addition, the compiler inserts
+// a ??? instruction for non-void runtime functions which is ? bytes long.
+#define print_possible_return_addresses(addr)                                  \
+  printf("%" PRIu64 ": current_address=%p or %p\n",                            \
+         ompt_get_thread_data()->value, ((char *)addr) - 8,                    \
+         ((char *)addr) - 8)
 #else
 #error Unsupported target architecture, cannot determine address offset!
 #endif

>From 32adaab953aa388af646f927b03d5e11a9407aa6 Mon Sep 17 00:00:00 2001
From: Fabian Mora <fmora.dev at gmail.com>
Date: Sat, 9 Sep 2023 19:59:20 -0400
Subject: [PATCH 20/62] [mlir][gpu] Add a symbol table field to TargetOptions
 and adjust GpuModuleToBinary (#65797)

This patch adds the option of building an optional symbol table for the
top operation in the `gpu-module-to-binary` pass. The table is not
created by default as most targets don't need it; instead, it is lazily
built. The table is passed through a callback in `TargetOptions`.

This patch is required to integrate #65539 .
---
 .../Dialect/GPU/IR/CompilationInterfaces.h    | 23 ++++++++++++++----
 .../mlir/Dialect/GPU/Transforms/Passes.td     |  8 ++++---
 mlir/lib/Dialect/GPU/IR/GPUDialect.cpp        | 24 +++++++++++--------
 .../Dialect/GPU/Transforms/ModuleToBinary.cpp | 19 ++++++++++++++-
 4 files changed, 56 insertions(+), 18 deletions(-)

diff --git a/mlir/include/mlir/Dialect/GPU/IR/CompilationInterfaces.h b/mlir/include/mlir/Dialect/GPU/IR/CompilationInterfaces.h
index e0bf560dbd98b92..a1f64be57fa699d 100644
--- a/mlir/include/mlir/Dialect/GPU/IR/CompilationInterfaces.h
+++ b/mlir/include/mlir/Dialect/GPU/IR/CompilationInterfaces.h
@@ -20,6 +20,7 @@ class IRBuilderBase;
 }
 
 namespace mlir {
+class SymbolTable;
 namespace LLVM {
 class ModuleTranslation;
 }
@@ -55,11 +56,13 @@ class TargetOptions {
   } CompilationTarget;
 
   /// Constructor initializing the toolkit path, the list of files to link to,
-  /// extra command line options & the compilation target. The default
-  /// compilation target is `binary`.
+  /// extra command line options, the compilation target and a callback for
+  /// obtaining the parent symbol table. The default compilation target is
+  /// `binOrFatbin`.
   TargetOptions(StringRef toolkitPath = {},
                 ArrayRef<std::string> linkFiles = {}, StringRef cmdOptions = {},
-                CompilationTarget compilationTarget = binOrFatbin);
+                CompilationTarget compilationTarget = binOrFatbin,
+                function_ref<SymbolTable *()> getSymbolTableCallback = {});
 
   /// Returns the typeID.
   TypeID getTypeID() const;
@@ -80,12 +83,20 @@ class TargetOptions {
   /// Returns the compilation target.
   CompilationTarget getCompilationTarget() const;
 
+  /// Returns the result of the `getSymbolTableCallback` callback or a nullptr
+  /// if no callback was provided.
+  /// Note: The callback itself can return nullptr. It is up to the target how
+  /// to react to getting a nullptr, e.g., emitting an error or constructing the
+  /// table.
+  SymbolTable *getSymbolTable() const;
+
 protected:
   /// Derived classes must use this constructor to initialize `typeID` to the
   /// appropiate value: ie. `TargetOptions(TypeID::get<DerivedClass>())`.
   TargetOptions(TypeID typeID, StringRef toolkitPath = {},
                 ArrayRef<std::string> linkFiles = {}, StringRef cmdOptions = {},
-                CompilationTarget compilationTarget = binOrFatbin);
+                CompilationTarget compilationTarget = binOrFatbin,
+                function_ref<SymbolTable *()> getSymbolTableCallback = {});
 
   /// Path to the target toolkit.
   std::string toolkitPath;
@@ -100,6 +111,10 @@ class TargetOptions {
   /// Compilation process target representation.
   CompilationTarget compilationTarget;
 
+  /// Callback for obtaining the parent symbol table of all the GPU modules
+  /// being serialized.
+  function_ref<SymbolTable *()> getSymbolTableCallback;
+
 private:
   TypeID typeID;
 };
diff --git a/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td b/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
index ba8a6266604e46c..0bfb2750992058f 100644
--- a/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
@@ -64,9 +64,11 @@ def GpuModuleToBinaryPass
     with an object for every target.
 
     The `format` argument can have the following values:
-    1. `offloading`, `llvm`: producing an offloading representation.
-    2. `assembly`, `isa`: producing assembly code.
-    3. `binary`, `bin`: producing binaries.
+    1. `offloading`, `llvm`: produces an offloading representation.
+    2. `assembly`, `isa`: produces assembly code.
+    3. `binary`, `bin`: produces binaries.
+    4. `fatbinary`, `fatbin`: produces fatbinaries.
+    5. `binOrFatbin`: produces bins or fatbins, the target decides which.
   }];
   let options = [
     Option<"offloadingHandler", "handler", "Attribute", "nullptr",
diff --git a/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp b/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp
index ad36b44763339f6..fde379cd0afe13f 100644
--- a/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp
+++ b/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp
@@ -1993,20 +1993,20 @@ gpu::SelectObjectAttr::verify(function_ref<InFlightDiagnostic()> emitError,
 // GPU target options
 //===----------------------------------------------------------------------===//
 
-TargetOptions::TargetOptions(StringRef toolkitPath,
-                             ArrayRef<std::string> linkFiles,
-                             StringRef cmdOptions,
-                             CompilationTarget compilationTarget)
+TargetOptions::TargetOptions(
+    StringRef toolkitPath, ArrayRef<std::string> linkFiles,
+    StringRef cmdOptions, CompilationTarget compilationTarget,
+    function_ref<SymbolTable *()> getSymbolTableCallback)
     : TargetOptions(TypeID::get<TargetOptions>(), toolkitPath, linkFiles,
-                    cmdOptions, compilationTarget) {}
+                    cmdOptions, compilationTarget, getSymbolTableCallback) {}
 
-TargetOptions::TargetOptions(TypeID typeID, StringRef toolkitPath,
-                             ArrayRef<std::string> linkFiles,
-                             StringRef cmdOptions,
-                             CompilationTarget compilationTarget)
+TargetOptions::TargetOptions(
+    TypeID typeID, StringRef toolkitPath, ArrayRef<std::string> linkFiles,
+    StringRef cmdOptions, CompilationTarget compilationTarget,
+    function_ref<SymbolTable *()> getSymbolTableCallback)
     : toolkitPath(toolkitPath.str()), linkFiles(linkFiles),
       cmdOptions(cmdOptions.str()), compilationTarget(compilationTarget),
-      typeID(typeID) {}
+      getSymbolTableCallback(getSymbolTableCallback), typeID(typeID) {}
 
 TypeID TargetOptions::getTypeID() const { return typeID; }
 
@@ -2016,6 +2016,10 @@ ArrayRef<std::string> TargetOptions::getLinkFiles() const { return linkFiles; }
 
 StringRef TargetOptions::getCmdOptions() const { return cmdOptions; }
 
+SymbolTable *TargetOptions::getSymbolTable() const {
+  return getSymbolTableCallback ? getSymbolTableCallback() : nullptr;
+}
+
 std::pair<llvm::BumpPtrAllocator, SmallVector<const char *>>
 TargetOptions::tokenizeCmdOptions() const {
   std::pair<llvm::BumpPtrAllocator, SmallVector<const char *>> options;
diff --git a/mlir/lib/Dialect/GPU/Transforms/ModuleToBinary.cpp b/mlir/lib/Dialect/GPU/Transforms/ModuleToBinary.cpp
index 06b7dee6941e1f4..e29a1f0c3248d04 100644
--- a/mlir/lib/Dialect/GPU/Transforms/ModuleToBinary.cpp
+++ b/mlir/lib/Dialect/GPU/Transforms/ModuleToBinary.cpp
@@ -66,9 +66,26 @@ void GpuModuleToBinaryPass::runOnOperation() {
                          .Default(-1);
   if (targetFormat == -1)
     getOperation()->emitError() << "Invalid format specified.";
+
+  // Lazy symbol table builder callback.
+  std::optional<SymbolTable> parentTable;
+  auto lazyTableBuilder = [&]() -> SymbolTable * {
+    // Build the table if it has not been built.
+    if (!parentTable) {
+      Operation *table = SymbolTable::getNearestSymbolTable(getOperation());
+      // It's up to the target attribute to determine if failing to find a
+      // symbol table is an error.
+      if (!table)
+        return nullptr;
+      parentTable = SymbolTable(table);
+    }
+    return &parentTable.value();
+  };
+
   TargetOptions targetOptions(
       toolkitPath, linkFiles, cmdOptions,
-      static_cast<TargetOptions::CompilationTarget>(targetFormat));
+      static_cast<TargetOptions::CompilationTarget>(targetFormat),
+      lazyTableBuilder);
   if (failed(transformGpuModulesToBinaries(
           getOperation(),
           offloadingHandler ? dyn_cast<OffloadingLLVMTranslationAttrInterface>(

>From 3a3393cc7f8146af317cc7d20ddc1673c4ddf9f2 Mon Sep 17 00:00:00 2001
From: Kazushi Marukawa <marukawa at nec.com>
Date: Sun, 10 Sep 2023 12:07:16 +0900
Subject: [PATCH 21/62] [OpenMP][test][VE] Change to use VE_LD_LIBRARY_PATH for
 VE (#65869)

Change to use VE_LD_LIBRARY_PATH for VE instead of LD_LIBRARY_PATH. The
VE is connected to the host, and compiled test programs for VE is
invoked on the host and transferred to the VE. If programs are compiled
for the host, we use LD_LIBRARY_PATH. Otherwise, we use
VE_LD_LIBRARY_PATH.
---
 openmp/runtime/test/lit.cfg | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/openmp/runtime/test/lit.cfg b/openmp/runtime/test/lit.cfg
index ab69819530d4a03..650d3853e851112 100644
--- a/openmp/runtime/test/lit.cfg
+++ b/openmp/runtime/test/lit.cfg
@@ -12,12 +12,16 @@ if 'PYLINT_IMPORT' in os.environ:
     lit_config = object()
 
 def prepend_dynamic_library_path(path):
+    target_arch = getattr(config, 'target_arch', None)
     if config.operating_system == 'Windows':
         name = 'PATH'
         sep = ';'
     elif config.operating_system == 'Darwin':
         name = 'DYLD_LIBRARY_PATH'
         sep = ':'
+    elif target_arch == 've':
+        name = 'VE_LD_LIBRARY_PATH'
+        sep = ':'
     else:
         name = 'LD_LIBRARY_PATH'
         sep = ':'

>From 645cd6a464f786f15d22a494825ed8b45439e9cb Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Sat, 9 Sep 2023 20:00:34 -0700
Subject: [PATCH 22/62] [lldb] Reinstate default constructor for
 SBCommandInterpreter

The default constructor for SBCommandInterpreter was (unintentionally)
made protected in 27b6a4e63afe. The goal of the patch was to make the
constructor taking an lldb_private type protected, but due to the
presence of a default argument, this ctor also served as the default
constructor. The latter should remain public.

This commit reinstates the original behavior by removing the default
argument and having an explicit, public default constructor.
---
 lldb/include/lldb/API/SBCommandInterpreter.h | 6 +++---
 lldb/source/API/SBCommandInterpreter.cpp     | 4 ++++
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/lldb/include/lldb/API/SBCommandInterpreter.h b/lldb/include/lldb/API/SBCommandInterpreter.h
index 3330a6f20034ca0..b7f5b3bf3396e43 100644
--- a/lldb/include/lldb/API/SBCommandInterpreter.h
+++ b/lldb/include/lldb/API/SBCommandInterpreter.h
@@ -30,6 +30,7 @@ class SBCommandInterpreter {
     eBroadcastBitAsynchronousErrorData = (1 << 4)
   };
 
+  SBCommandInterpreter();
   SBCommandInterpreter(const lldb::SBCommandInterpreter &rhs);
 
   ~SBCommandInterpreter();
@@ -317,9 +318,8 @@ class SBCommandInterpreter {
 protected:
   friend class lldb_private::CommandPluginInterfaceImplementation;
 
-  SBCommandInterpreter(
-      lldb_private::CommandInterpreter *interpreter_ptr =
-          nullptr); // Access using SBDebugger::GetCommandInterpreter();
+  /// Access using SBDebugger::GetCommandInterpreter();
+  SBCommandInterpreter(lldb_private::CommandInterpreter *interpreter_ptr);
   lldb_private::CommandInterpreter &ref();
 
   lldb_private::CommandInterpreter *get();
diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp
index 396c0eef0603d3c..d275da933919e53 100644
--- a/lldb/source/API/SBCommandInterpreter.cpp
+++ b/lldb/source/API/SBCommandInterpreter.cpp
@@ -83,6 +83,10 @@ class CommandPluginInterfaceImplementation : public CommandObjectParsed {
 };
 } // namespace lldb_private
 
+SBCommandInterpreter::SBCommandInterpreter() : m_opaque_ptr() {
+  LLDB_INSTRUMENT_VA(this);
+}
+
 SBCommandInterpreter::SBCommandInterpreter(CommandInterpreter *interpreter)
     : m_opaque_ptr(interpreter) {
   LLDB_INSTRUMENT_VA(this, interpreter);

>From 0246ef58ca477422cc5476c23f6d33a8f77322a8 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 09:32:08 -0700
Subject: [PATCH 23/62] [clang] NFCI: Use `FileEntryRef` in
 `suggestPathToFileForDiagnostics()`

---
 clang-tools-extra/clang-include-fixer/IncludeFixer.cpp | 3 ++-
 clang/include/clang/Lex/HeaderSearch.h                 | 2 +-
 clang/include/clang/Lex/Preprocessor.h                 | 4 ++--
 clang/lib/Lex/HeaderSearch.cpp                         | 7 ++-----
 clang/lib/Lex/PPDirectives.cpp                         | 8 ++++----
 clang/lib/Sema/SemaLookup.cpp                          | 7 ++++---
 6 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp b/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp
index 1bb5cf756b95b49..354f35cbadbeb94 100644
--- a/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp
+++ b/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp
@@ -307,7 +307,8 @@ std::string IncludeFixerSemaSource::minimizeInclude(
 
   // Get the FileEntry for the include.
   StringRef StrippedInclude = Include.trim("\"<>");
-  auto Entry = SourceManager.getFileManager().getFile(StrippedInclude);
+  auto Entry =
+      SourceManager.getFileManager().getOptionalFileRef(StrippedInclude);
 
   // If the file doesn't exist return the path from the database.
   // FIXME: This should never happen.
diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h
index 059b143535faaba..cec3a31c94800cd 100644
--- a/clang/include/clang/Lex/HeaderSearch.h
+++ b/clang/include/clang/Lex/HeaderSearch.h
@@ -870,7 +870,7 @@ class HeaderSearch {
   ///
   /// \param IsAngled If non-null, filled in to indicate whether the suggested
   ///        path should be referenced as <Header.h> instead of "Header.h".
-  std::string suggestPathToFileForDiagnostics(const FileEntry *File,
+  std::string suggestPathToFileForDiagnostics(FileEntryRef File,
                                               llvm::StringRef MainFile,
                                               bool *IsAngled = nullptr) const;
 
diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h
index 9efe439bc5f2192..bc1d94a61508d8d 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -2718,8 +2718,8 @@ class Preprocessor {
   /// \return A file that can be #included to provide the desired effect. Null
   ///         if no such file could be determined or if a #include is not
   ///         appropriate (eg, if a module should be imported instead).
-  const FileEntry *getHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
-                                                    SourceLocation MLoc);
+  OptionalFileEntryRef getHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
+                                                        SourceLocation MLoc);
 
   bool isRecordingPreamble() const {
     return PreambleConditionalStack.isRecording();
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp
index 699cd9ae03adc51..83ed2a991d2bd02 100644
--- a/clang/lib/Lex/HeaderSearch.cpp
+++ b/clang/lib/Lex/HeaderSearch.cpp
@@ -1923,11 +1923,8 @@ void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
 }
 
 std::string HeaderSearch::suggestPathToFileForDiagnostics(
-    const FileEntry *File, llvm::StringRef MainFile, bool *IsAngled) const {
-  // FIXME: We assume that the path name currently cached in the FileEntry is
-  // the most appropriate one for this analysis (and that it's spelled the
-  // same way as the corresponding header search path).
-  return suggestPathToFileForDiagnostics(File->getName(), /*WorkingDir=*/"",
+    FileEntryRef File, llvm::StringRef MainFile, bool *IsAngled) const {
+  return suggestPathToFileForDiagnostics(File.getName(), /*WorkingDir=*/"",
                                          MainFile, IsAngled);
 }
 
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index a4db8e7a84c07d5..7bb4dd3bc7eb690 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -874,7 +874,7 @@ Module *Preprocessor::getModuleForLocation(SourceLocation Loc,
              : HeaderInfo.lookupModule(getLangOpts().CurrentModule, Loc);
 }
 
-const FileEntry *
+OptionalFileEntryRef
 Preprocessor::getHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
                                                SourceLocation Loc) {
   Module *IncM = getModuleForLocation(
@@ -920,7 +920,7 @@ Preprocessor::getHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
       // make a particular module visible. Let the caller know they should
       // suggest an import instead.
       if (getLangOpts().ObjC || getLangOpts().CPlusPlusModules)
-        return nullptr;
+        return std::nullopt;
 
       // If this is an accessible, non-textual header of M's top-level module
       // that transitively includes the given location and makes the
@@ -931,7 +931,7 @@ Preprocessor::getHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
     // FIXME: If we're bailing out due to a private header, we shouldn't suggest
     // an import either.
     if (InPrivateHeader)
-      return nullptr;
+      return std::nullopt;
 
     // If the header is includable and has an include guard, assume the
     // intended way to expose its contents is by #include, not by importing a
@@ -942,7 +942,7 @@ Preprocessor::getHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
     Loc = SM.getIncludeLoc(ID);
   }
 
-  return nullptr;
+  return std::nullopt;
 }
 
 OptionalFileEntryRef Preprocessor::LookupFile(
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 7dd96e3155e1dd4..324a57095560b79 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -5699,7 +5699,7 @@ void Sema::diagnoseMissingImport(SourceLocation Loc, const NamedDecl *Decl,
 
 /// Get a "quoted.h" or <angled.h> include path to use in a diagnostic
 /// suggesting the addition of a #include of the specified file.
-static std::string getHeaderNameForHeader(Preprocessor &PP, const FileEntry *E,
+static std::string getHeaderNameForHeader(Preprocessor &PP, FileEntryRef E,
                                           llvm::StringRef IncludingFile) {
   bool IsAngled = false;
   auto Path = PP.getHeaderSearchInfo().suggestPathToFileForDiagnostics(
@@ -5732,11 +5732,12 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, const NamedDecl *Decl,
 
   // Try to find a suitable header-name to #include.
   std::string HeaderName;
-  if (const FileEntry *Header =
+  if (OptionalFileEntryRef Header =
           PP.getHeaderToIncludeForDiagnostics(UseLoc, DeclLoc)) {
     if (const FileEntry *FE =
             SourceMgr.getFileEntryForID(SourceMgr.getFileID(UseLoc)))
-      HeaderName = getHeaderNameForHeader(PP, Header, FE->tryGetRealPathName());
+      HeaderName =
+          getHeaderNameForHeader(PP, *Header, FE->tryGetRealPathName());
   }
 
   // If we have a #include we should suggest, or if all definition locations

>From c71d4f458ff347c78f5df00b27fc2b33864f7bef Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 10:12:34 -0700
Subject: [PATCH 24/62] [clang] NFCI: Use `FileEntryRef` in `Sarif.cpp`

---
 clang/lib/Basic/Sarif.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Basic/Sarif.cpp b/clang/lib/Basic/Sarif.cpp
index e2af25c8143b33e..e71f4b3337fcef4 100644
--- a/clang/lib/Basic/Sarif.cpp
+++ b/clang/lib/Basic/Sarif.cpp
@@ -36,8 +36,8 @@ using namespace llvm;
 using clang::detail::SarifArtifact;
 using clang::detail::SarifArtifactLocation;
 
-static StringRef getFileName(const FileEntry &FE) {
-  StringRef Filename = FE.tryGetRealPathName();
+static StringRef getFileName(FileEntryRef FE) {
+  StringRef Filename = FE.getFileEntry().tryGetRealPathName();
   if (Filename.empty())
     Filename = FE.getName();
   return Filename;
@@ -215,8 +215,8 @@ SarifDocumentWriter::createPhysicalLocation(const CharSourceRange &R) {
   assert(R.isCharRange() &&
          "Cannot create a physicalLocation from a token range!");
   FullSourceLoc Start{R.getBegin(), SourceMgr};
-  const FileEntry *FE = Start.getExpansionLoc().getFileEntry();
-  assert(FE != nullptr && "Diagnostic does not exist within a valid file!");
+  OptionalFileEntryRef FE = Start.getExpansionLoc().getFileEntryRef();
+  assert(FE && "Diagnostic does not exist within a valid file!");
 
   const std::string &FileURI = fileNameToURI(getFileName(*FE));
   auto I = CurrentArtifacts.find(FileURI);

>From 6bbca311c74c900ffcbd0fa245f26ce4e0fd3ec1 Mon Sep 17 00:00:00 2001
From: Alex Brachet <abrachet at google.com>
Date: Sun, 10 Sep 2023 00:00:08 -0400
Subject: [PATCH 25/62] [Haiku] Don't assume clang was build with libstdc++ as
 default (#65871)

This test fails with `CLANG_DEFAULT_CXX_STDLIB=libc++`
---
 clang/test/Driver/haiku.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/Driver/haiku.cpp b/clang/test/Driver/haiku.cpp
index f022013d1ef79b7..64018e8236b2824 100644
--- a/clang/test/Driver/haiku.cpp
+++ b/clang/test/Driver/haiku.cpp
@@ -1,5 +1,5 @@
 // Check the C++ header path (libstdc++)
-// RUN: %clangxx --target=x86_64-unknown-haiku -### %s 2>&1 \
+// RUN: %clangxx --target=x86_64-unknown-haiku --stdlib=libstdc++ -### %s 2>&1 \
 // RUN:   --sysroot=%S/Inputs/haiku_x86_64_tree \
 // RUN:   | FileCheck --check-prefix=CHECK-LIBSTDCXX-HEADER-PATH %s
 // CHECK-LIBSTDCXX-HEADER-PATH: "-internal-isystem" "[[SYSROOT:[^"]+]]/boot/system/develop/headers/c++"

>From 6d5399c076ba3b9755542b43593b69e4f86b067a Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 10:14:57 -0700
Subject: [PATCH 26/62] [clang] NFCI: Use `FileEntryRef` in
 `LookupSubframeworkHeader()`

---
 clang/include/clang/Lex/HeaderSearch.h | 2 +-
 clang/lib/Lex/HeaderSearch.cpp         | 6 ++----
 clang/lib/Lex/PPDirectives.cpp         | 6 +++---
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h
index cec3a31c94800cd..347c4ecd2934132 100644
--- a/clang/include/clang/Lex/HeaderSearch.h
+++ b/clang/include/clang/Lex/HeaderSearch.h
@@ -501,7 +501,7 @@ class HeaderSearch {
   /// HIToolbox is a subframework within Carbon.framework.  If so, return
   /// the FileEntry for the designated file, otherwise return null.
   OptionalFileEntryRef LookupSubframeworkHeader(
-      StringRef Filename, const FileEntry *ContextFileEnt,
+      StringRef Filename, FileEntryRef ContextFileEnt,
       SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
       Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule);
 
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp
index 83ed2a991d2bd02..e7195cbe9141340 100644
--- a/clang/lib/Lex/HeaderSearch.cpp
+++ b/clang/lib/Lex/HeaderSearch.cpp
@@ -1178,11 +1178,9 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
 /// is a subframework within Carbon.framework.  If so, return the FileEntry
 /// for the designated file, otherwise return null.
 OptionalFileEntryRef HeaderSearch::LookupSubframeworkHeader(
-    StringRef Filename, const FileEntry *ContextFileEnt,
+    StringRef Filename, FileEntryRef ContextFileEnt,
     SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
     Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) {
-  assert(ContextFileEnt && "No context file?");
-
   // Framework names must have a '/' in the filename.  Find it.
   // FIXME: Should we permit '\' on Windows?
   size_t SlashPos = Filename.find('/');
@@ -1190,7 +1188,7 @@ OptionalFileEntryRef HeaderSearch::LookupSubframeworkHeader(
     return std::nullopt;
 
   // Look up the base framework name of the ContextFileEnt.
-  StringRef ContextName = ContextFileEnt->getName();
+  StringRef ContextName = ContextFileEnt.getName();
 
   // If the context info wasn't a framework, couldn't be a subframework.
   const unsigned DotFrameworkLen = 10;
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 7bb4dd3bc7eb690..7edcb0577c2b25a 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -1041,14 +1041,14 @@ OptionalFileEntryRef Preprocessor::LookupFile(
     return FE;
   }
 
-  const FileEntry *CurFileEnt;
+  OptionalFileEntryRef CurFileEnt;
   // Otherwise, see if this is a subframework header.  If so, this is relative
   // to one of the headers on the #include stack.  Walk the list of the current
   // headers on the #include stack and pass them to HeaderInfo.
   if (IsFileLexer()) {
     if ((CurFileEnt = CurPPLexer->getFileEntry())) {
       if (OptionalFileEntryRef FE = HeaderInfo.LookupSubframeworkHeader(
-              Filename, CurFileEnt, SearchPath, RelativePath, RequestingModule,
+              Filename, *CurFileEnt, SearchPath, RelativePath, RequestingModule,
               SuggestedModule)) {
         if (SuggestedModule && !LangOpts.AsmPreprocessor)
           HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
@@ -1063,7 +1063,7 @@ OptionalFileEntryRef Preprocessor::LookupFile(
     if (IsFileLexer(ISEntry)) {
       if ((CurFileEnt = ISEntry.ThePPLexer->getFileEntry())) {
         if (OptionalFileEntryRef FE = HeaderInfo.LookupSubframeworkHeader(
-                Filename, CurFileEnt, SearchPath, RelativePath,
+                Filename, *CurFileEnt, SearchPath, RelativePath,
                 RequestingModule, SuggestedModule)) {
           if (SuggestedModule && !LangOpts.AsmPreprocessor)
             HeaderInfo.getModuleMap().diagnoseHeaderInclusion(

>From 61e73e786611161c21056522c93028f941c14f6a Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 10:17:01 -0700
Subject: [PATCH 27/62] [clang] NFCI: Use `FileEntryRef` in `ModuleManager`

---
 clang/lib/Serialization/ModuleManager.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp
index 5b099b740e1d330..112d27e179dc3d0 100644
--- a/clang/lib/Serialization/ModuleManager.cpp
+++ b/clang/lib/Serialization/ModuleManager.cpp
@@ -143,15 +143,15 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
   // being consistent across operating systems and across subsequent accesses
   // to the Modules map.
   auto implicitModuleNamesMatch = [](ModuleKind Kind, const ModuleFile *MF,
-                                     const FileEntry *Entry) -> bool {
+                                     FileEntryRef Entry) -> bool {
     if (Kind != MK_ImplicitModule)
       return true;
-    return Entry->getName() == MF->FileName;
+    return Entry.getName() == MF->FileName;
   };
 
   // Check whether we already loaded this module, before
   if (ModuleFile *ModuleEntry = Modules.lookup(Entry)) {
-    if (implicitModuleNamesMatch(Type, ModuleEntry, Entry)) {
+    if (implicitModuleNamesMatch(Type, ModuleEntry, *Entry)) {
       // Check the stored signature.
       if (checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr))
         return OutOfDate;

>From 51e101c3e5800dad5dfd140506ce667cea657461 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 10:29:21 -0700
Subject: [PATCH 28/62] [clang] NFCI: Use `FileEntryRef` in `GlobalModuleIndex`

---
 clang/lib/Serialization/GlobalModuleIndex.cpp | 35 +++++++++----------
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp
index 92417c7bf1d5241..b4a49972ace2ee6 100644
--- a/clang/lib/Serialization/GlobalModuleIndex.cpp
+++ b/clang/lib/Serialization/GlobalModuleIndex.cpp
@@ -405,15 +405,15 @@ namespace {
     const PCHContainerReader &PCHContainerRdr;
 
     /// Mapping from files to module file information.
-    typedef llvm::MapVector<const FileEntry *, ModuleFileInfo> ModuleFilesMap;
+    using ModuleFilesMap = llvm::MapVector<FileEntryRef, ModuleFileInfo>;
 
     /// Information about each of the known module files.
     ModuleFilesMap ModuleFiles;
 
     /// Mapping from the imported module file to the imported
     /// information.
-    typedef std::multimap<const FileEntry *, ImportedModuleFileInfo>
-        ImportedModuleFilesMap;
+    using ImportedModuleFilesMap =
+        std::multimap<FileEntryRef, ImportedModuleFileInfo>;
 
     /// Information about each importing of a module file.
     ImportedModuleFilesMap ImportedModuleFiles;
@@ -430,9 +430,8 @@ namespace {
     void emitBlockInfoBlock(llvm::BitstreamWriter &Stream);
 
     /// Retrieve the module file information for the given file.
-    ModuleFileInfo &getModuleFileInfo(const FileEntry *File) {
-      llvm::MapVector<const FileEntry *, ModuleFileInfo>::iterator Known
-        = ModuleFiles.find(File);
+    ModuleFileInfo &getModuleFileInfo(FileEntryRef File) {
+      auto Known = ModuleFiles.find(File);
       if (Known != ModuleFiles.end())
         return Known->second;
 
@@ -448,7 +447,7 @@ namespace {
         : FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr) {}
 
     /// Load the contents of the given module file into the builder.
-    llvm::Error loadModuleFile(const FileEntry *File);
+    llvm::Error loadModuleFile(FileEntryRef File);
 
     /// Write the index to the given bitstream.
     /// \returns true if an error occurred, false otherwise.
@@ -519,7 +518,7 @@ namespace {
   };
 }
 
-llvm::Error GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
+llvm::Error GlobalModuleIndexBuilder::loadModuleFile(FileEntryRef File) {
   // Open the module file.
 
   auto Buffer = FileMgr.getBufferForFile(File, /*isVolatile=*/true);
@@ -653,9 +652,9 @@ llvm::Error GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
         Idx += Length;
 
         // Find the imported module file.
-        auto DependsOnFile
-          = FileMgr.getFile(ImportedFile, /*OpenFile=*/false,
-                            /*CacheFailure=*/false);
+        auto DependsOnFile =
+            FileMgr.getOptionalFileRef(ImportedFile, /*OpenFile=*/false,
+                                       /*CacheFailure=*/false);
 
         if (!DependsOnFile)
           return llvm::createStringError(std::errc::bad_file_descriptor,
@@ -754,14 +753,14 @@ class IdentifierIndexWriterTrait {
 
 bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
   for (auto MapEntry : ImportedModuleFiles) {
-    auto *File = MapEntry.first;
+    auto File = MapEntry.first;
     ImportedModuleFileInfo &Info = MapEntry.second;
     if (getModuleFileInfo(File).Signature) {
       if (getModuleFileInfo(File).Signature != Info.StoredSignature)
         // Verify Signature.
         return true;
-    } else if (Info.StoredSize != File->getSize() ||
-               Info.StoredModTime != File->getModificationTime())
+    } else if (Info.StoredSize != File.getSize() ||
+               Info.StoredModTime != File.getModificationTime())
       // Verify Size and ModTime.
       return true;
   }
@@ -792,11 +791,11 @@ bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
        M != MEnd; ++M) {
     Record.clear();
     Record.push_back(M->second.ID);
-    Record.push_back(M->first->getSize());
-    Record.push_back(M->first->getModificationTime());
+    Record.push_back(M->first.getSize());
+    Record.push_back(M->first.getModificationTime());
 
     // File name
-    StringRef Name(M->first->getName());
+    StringRef Name(M->first.getName());
     Record.push_back(Name.size());
     Record.append(Name.begin(), Name.end());
 
@@ -892,7 +891,7 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr,
     }
 
     // If we can't find the module file, skip it.
-    auto ModuleFile = FileMgr.getFile(D->path());
+    auto ModuleFile = FileMgr.getOptionalFileRef(D->path());
     if (!ModuleFile)
       continue;
 

>From 7c13b3b17c21727a9e80330d757e620facc81782 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 12:47:12 -0700
Subject: [PATCH 29/62] [clang] NFCI: Use `FileEntryRef` in
 `ModuleMapCallbacks`

---
 clang/include/clang/Lex/ModuleMap.h   | 4 ++--
 clang/lib/Frontend/DependencyFile.cpp | 2 +-
 clang/lib/Lex/ModuleMap.cpp           | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h
index a25a790e544e238..0da1cdc97a75cc6 100644
--- a/clang/include/clang/Lex/ModuleMap.h
+++ b/clang/include/clang/Lex/ModuleMap.h
@@ -57,8 +57,8 @@ class ModuleMapCallbacks {
   /// contents.
   /// \param File The file itself.
   /// \param IsSystem Whether this is a module map from a system include path.
-  virtual void moduleMapFileRead(SourceLocation FileStart,
-                                 const FileEntry &File, bool IsSystem) {}
+  virtual void moduleMapFileRead(SourceLocation FileStart, FileEntryRef File,
+                                 bool IsSystem) {}
 
   /// Called when a header is added during module map parsing.
   ///
diff --git a/clang/lib/Frontend/DependencyFile.cpp b/clang/lib/Frontend/DependencyFile.cpp
index 44268e71dc241b6..1140c09dbb985b6 100644
--- a/clang/lib/Frontend/DependencyFile.cpp
+++ b/clang/lib/Frontend/DependencyFile.cpp
@@ -105,7 +105,7 @@ struct DepCollectorMMCallbacks : public ModuleMapCallbacks {
   DependencyCollector &DepCollector;
   DepCollectorMMCallbacks(DependencyCollector &DC) : DepCollector(DC) {}
 
-  void moduleMapFileRead(SourceLocation Loc, const FileEntry &Entry,
+  void moduleMapFileRead(SourceLocation Loc, FileEntryRef Entry,
                          bool IsSystem) override {
     StringRef Filename = Entry.getName();
     DepCollector.maybeAddDependency(Filename,
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index 39af2e8df106a66..b4483cd1a55c469 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -3120,7 +3120,7 @@ bool ModuleMap::parseModuleMapFile(FileEntryRef File, bool IsSystem,
 
   // Notify callbacks that we parsed it.
   for (const auto &Cb : Callbacks)
-    Cb->moduleMapFileRead(Start, *File, IsSystem);
+    Cb->moduleMapFileRead(Start, File, IsSystem);
 
   return Result;
 }

>From 28be7fe19d76b2c0a0b46d773c7525cd2240f133 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 12:51:30 -0700
Subject: [PATCH 30/62] [clang] NFCI: Use `FileEntryRef` in `CreateHeaderMap()`

---
 clang/include/clang/Lex/HeaderSearch.h | 4 ++--
 clang/lib/Lex/HeaderSearch.cpp         | 4 ++--
 clang/lib/Lex/InitHeaderSearch.cpp     | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h
index 347c4ecd2934132..2e9c1f0329cf6b7 100644
--- a/clang/include/clang/Lex/HeaderSearch.h
+++ b/clang/include/clang/Lex/HeaderSearch.h
@@ -316,7 +316,7 @@ class HeaderSearch {
   std::unique_ptr<IncludeAliasMap> IncludeAliases;
 
   /// This is a mapping from FileEntry -> HeaderMap, uniquing headermaps.
-  std::vector<std::pair<const FileEntry *, std::unique_ptr<HeaderMap>>> HeaderMaps;
+  std::vector<std::pair<FileEntryRef, std::unique_ptr<HeaderMap>>> HeaderMaps;
 
   /// The mapping between modules and headers.
   mutable ModuleMap ModMap;
@@ -573,7 +573,7 @@ class HeaderSearch {
 
   /// This method returns a HeaderMap for the specified
   /// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
-  const HeaderMap *CreateHeaderMap(const FileEntry *FE);
+  const HeaderMap *CreateHeaderMap(FileEntryRef FE);
 
   /// Get filenames for all registered header maps.
   void getHeaderMapFileNames(SmallVectorImpl<std::string> &Names) const;
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp
index e7195cbe9141340..4deabf2c49bb8e0 100644
--- a/clang/lib/Lex/HeaderSearch.cpp
+++ b/clang/lib/Lex/HeaderSearch.cpp
@@ -144,7 +144,7 @@ std::vector<bool> HeaderSearch::computeUserEntryUsage() const {
 
 /// CreateHeaderMap - This method returns a HeaderMap for the specified
 /// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
-const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
+const HeaderMap *HeaderSearch::CreateHeaderMap(FileEntryRef FE) {
   // We expect the number of headermaps to be small, and almost always empty.
   // If it ever grows, use of a linear search should be re-evaluated.
   if (!HeaderMaps.empty()) {
@@ -167,7 +167,7 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
 void HeaderSearch::getHeaderMapFileNames(
     SmallVectorImpl<std::string> &Names) const {
   for (auto &HM : HeaderMaps)
-    Names.push_back(std::string(HM.first->getName()));
+    Names.push_back(std::string(HM.first.getName()));
 }
 
 std::string HeaderSearch::getCachedModuleFileName(Module *Module) {
diff --git a/clang/lib/Lex/InitHeaderSearch.cpp b/clang/lib/Lex/InitHeaderSearch.cpp
index 2aaaca89a6a3ac8..1f4c7a6d67b7f79 100644
--- a/clang/lib/Lex/InitHeaderSearch.cpp
+++ b/clang/lib/Lex/InitHeaderSearch.cpp
@@ -167,7 +167,7 @@ bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
   // Check to see if this is an apple-style headermap (which are not allowed to
   // be frameworks).
   if (!isFramework) {
-    if (auto FE = FM.getFile(MappedPathStr)) {
+    if (auto FE = FM.getOptionalFileRef(MappedPathStr)) {
       if (const HeaderMap *HM = Headers.CreateHeaderMap(*FE)) {
         // It is a headermap, add it to the search path.
         IncludePath.emplace_back(

>From c8ebd223e0ad7924aa39c7bce3cb18e60f244021 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sat, 9 Sep 2023 23:47:01 -0700
Subject: [PATCH 31/62] [ELF] Priorize the last catch-all pattern in version
 scripts

When there are multiple catch-all patterns (i.e. a single `*`), GNU ld and gold
select the last pattern. Match their behavior.

This change was inspired by a correction made by Michael Kerrisk to a blog post
I wrote at https://maskray.me/blog/2020-11-26-all-about-symbol-versioning ,
following the current lld rules.

Note: GNU ld prefers global: patterns to local: patterns, which might seem
awkward (https://www.airs.com/blog/archives/300). gold doesn't follow this
behavior, and we do not either.
---
 lld/ELF/SymbolTable.cpp                     | 2 +-
 lld/test/ELF/version-script-reassign-glob.s | 7 +++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 0437095c8638150..fe7edd5b0eb49aa 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -313,7 +313,7 @@ void SymbolTable::scanVersionScript() {
 
   // Then, assign versions to "*". In GNU linkers they have lower priority than
   // other wildcards.
-  for (VersionDefinition &v : config->versionDefinitions) {
+  for (VersionDefinition &v : llvm::reverse(config->versionDefinitions)) {
     for (SymbolVersion &pat : v.nonLocalPatterns)
       if (pat.hasWildcard && pat.name == "*")
         assignWildcard(pat, v.id, v.name);
diff --git a/lld/test/ELF/version-script-reassign-glob.s b/lld/test/ELF/version-script-reassign-glob.s
index e25cdacae89a9fc..39d19a26fc44984 100644
--- a/lld/test/ELF/version-script-reassign-glob.s
+++ b/lld/test/ELF/version-script-reassign-glob.s
@@ -9,11 +9,18 @@
 # RUN: ld.lld --version-script %t.ver %t.o -shared -o %t.so --fatal-warnings
 # RUN: llvm-readelf --dyn-syms %t.so | FileCheck --check-prefix=BAR %s
 
+# RUN: echo 'bar1 { *; }; bar2 { *; };' > %t2.ver
+# RUN: ld.lld --version-script %t2.ver %t.o -shared -o %t2.so --fatal-warnings
+# RUN: llvm-readelf --dyn-syms %t2.so | FileCheck --check-prefix=BAR2 %s
+
 ## If both a non-* glob and a * match, non-* wins.
 ## This is GNU linkers' behavior. We don't feel strongly this should be supported.
 # FOO: GLOBAL DEFAULT 7 foo@@foo
 
 # BAR: GLOBAL DEFAULT 7 foo@@bar
 
+## When there are multiple * patterns, the last wins.
+# BAR2: GLOBAL DEFAULT 7 foo@@bar2
+
 .globl foo
 foo:

>From c08bca0e7a4f9cd6d838638411bd9389770bfec0 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 12 Jun 2023 08:10:47 -0400
Subject: [PATCH 32/62] AMDGPU: Implement llvm.get.fpmode

Currently s_getreg_b32 is missing the possible mode use. Really we
need separate pseudos for mode-only accesses, but leave this as a
pre-existing issue.

https://reviews.llvm.org/D152710
---
 llvm/docs/AMDGPUUsage.rst                   |   7 +
 llvm/docs/LangRef.rst                       |   1 +
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp   |   4 +
 llvm/lib/Target/AMDGPU/SOPInstructions.td   |  62 ++
 llvm/test/CodeGen/AMDGPU/llvm.get.fpmode.ll | 697 ++++++++++++++++++++
 5 files changed, 771 insertions(+)
 create mode 100644 llvm/test/CodeGen/AMDGPU/llvm.get.fpmode.ll

diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst
index 31cafb4d5e3ae88..f733c514ffbee47 100644
--- a/llvm/docs/AMDGPUUsage.rst
+++ b/llvm/docs/AMDGPUUsage.rst
@@ -999,6 +999,13 @@ The AMDGPU backend implements the following LLVM IR intrinsics.
   :ref:`llvm.stacksave.p5 <int_stacksave>`         Implemented, must use the alloca address space.
   :ref:`llvm.stackrestore.p5 <int_stackrestore>`   Implemented, must use the alloca address space.
 
+  :ref:`llvm.get.fpmode.i32 <int_get_fpmode>`      The natural floating-point mode type is i32. This
+                                                   implemented by extracting relevant bits out of the MODE
+                                                   register with s_getreg_b32. The first 10 bits are the
+                                                   core floating-point mode. Bits 12:18 are the exception
+                                                   mask. On gfx9+, bit 23 is FP16_OVFL. Bitfields not
+                                                   relevant to floating-point instructions are 0s.
+
   :ref:`llvm.get.rounding<int_get_rounding>`       AMDGPU supports two separately controllable rounding
                                                    modes depending on the floating-point type. One
                                                    controls float, and the other controls both double and
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 7a2878b8823fb0f..dc5c84de420d76c 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -25660,6 +25660,7 @@ The '``llvm.reset.fpenv``' intrinsic sets the current floating-point environment
 to default state. It is similar to the call 'fesetenv(FE_DFL_ENV)', except it
 does not return any value.
 
+.. _int_get_fpmode:
 
 '``llvm.get.fpmode``' Intrinsic
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index b5af88af1d558f5..1020878955f7fce 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -757,6 +757,10 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::STACKSAVE, MVT::Other, Custom);
   setOperationAction(ISD::GET_ROUNDING, MVT::i32, Custom);
 
+  // TODO: Could move this to custom lowering, could benefit from combines on
+  // extract of relevant bits.
+  setOperationAction(ISD::GET_FPMODE, MVT::i32, Legal);
+
   setTargetDAGCombine({ISD::ADD,
                        ISD::UADDO_CARRY,
                        ISD::SUB,
diff --git a/llvm/lib/Target/AMDGPU/SOPInstructions.td b/llvm/lib/Target/AMDGPU/SOPInstructions.td
index 175045a8a893e92..229aa9c75d16d2d 100644
--- a/llvm/lib/Target/AMDGPU/SOPInstructions.td
+++ b/llvm/lib/Target/AMDGPU/SOPInstructions.td
@@ -870,6 +870,8 @@ def S_CBRANCH_I_FORK : SOPK_Pseudo <
 
 // This is hasSideEffects to allow its use in readcyclecounter selection.
 // FIXME: Need to truncate immediate to 16-bits.
+// FIXME: Missing mode register use. Should have separate pseudos for
+// known may read MODE and only read MODE.
 def S_GETREG_B32 : SOPK_Pseudo <
   "s_getreg_b32",
   (outs SReg_32:$sdst), (ins hwreg:$simm16),
@@ -1424,6 +1426,66 @@ def : GCNPat <
     (S_WAIT_EVENT (i16 0))
 >;
 
+// The first 10 bits of the mode register are the core FP mode on all
+// subtargets.
+//
+// The high bits include additional fields, intermixed with some
+// non-floating point environment information. We extract the full
+// register and clear non-relevant bits.
+//
+// EXCP_EN covers floating point exceptions, but also some other
+// non-FP exceptions.
+//
+// Bits 12-18 cover the relevant exception mask on all subtargets.
+//
+// FIXME: Bit 18 is int_div0, should this be in the FP environment? I
+// think the only source is v_rcp_iflag_i32.
+//
+// On GFX9+:
+// Bit 23 is the additional FP16_OVFL mode.
+//
+// Bits 19, 20, and 21 cover non-FP exceptions and differ between
+// gfx9/10/11, so we ignore them here.
+
+// TODO: Would it be cheaper to emit multiple s_getreg_b32 calls for
+// the ranges and combine the results?
+
+defvar fp_round_mask = !add(!shl(1, 4), -1);
+defvar fp_denorm_mask = !shl(!add(!shl(1, 4), -1), 4);
+defvar dx10_clamp_mask = !shl(1, 8);
+defvar ieee_mode_mask = !shl(1, 9);
+
+// Covers fp_round, fp_denorm, dx10_clamp, and IEEE bit.
+defvar fpmode_mask =
+  !or(fp_round_mask, fp_denorm_mask, dx10_clamp_mask, ieee_mode_mask);
+
+defvar fp_excp_en_mask = !shl(!add(!shl(1, 7), -1), 12);
+defvar fp16_ovfl = !shl(1, 23);
+defvar fpmode_mask_gfx6plus = !or(fpmode_mask, fp_excp_en_mask);
+defvar fpmode_mask_gfx9plus = !or(fpmode_mask_gfx6plus, fp16_ovfl);
+
+class GetFPModePat<int fpmode_mask> : GCNPat<
+  (i32 get_fpmode),
+  (S_AND_B32 (i32 fpmode_mask),
+             (S_GETREG_B32 getHwRegImm<
+                HWREG.MODE, 0,
+                !add(!logtwo(fpmode_mask), 1)>.ret))
+>;
+
+// TODO: Might be worth moving to custom lowering so the and is
+// exposed to demanded bits optimizations. Most users probably only
+// care about the rounding or denorm mode bits. We also can reduce the
+// demanded read from the getreg immediate.
+let SubtargetPredicate = isGFX9Plus in {
+// Last bit = FP16_OVFL
+def : GetFPModePat<fpmode_mask_gfx9plus>;
+}
+
+// Last bit = EXCP_EN.int_div0
+let SubtargetPredicate = isNotGFX9Plus in {
+def : GetFPModePat<fpmode_mask_gfx6plus>;
+}
+
 //===----------------------------------------------------------------------===//
 // SOP2 Patterns
 //===----------------------------------------------------------------------===//
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.get.fpmode.ll b/llvm/test/CodeGen/AMDGPU/llvm.get.fpmode.ll
new file mode 100644
index 000000000000000..a665e58adb8a1b1
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/llvm.get.fpmode.ll
@@ -0,0 +1,697 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc -march=amdgcn -mcpu=tahiti < %s | FileCheck -check-prefixes=GCN,GFX678,GFX6 %s
+; RUN: llc -march=amdgcn -mcpu=hawaii < %s | FileCheck -check-prefixes=GCN,GFX678,GFX7 %s
+; RUN: llc -march=amdgcn -mcpu=fiji < %s | FileCheck -check-prefixes=GCN,GFX678,GFX8 %s
+; RUN: llc -march=amdgcn -mcpu=gfx900 < %s | FileCheck -check-prefixes=GCN,GFX9 %s
+; RUN: llc -march=amdgcn -mcpu=gfx1030 < %s | FileCheck -check-prefixes=GCN,GFX1011,GFX10 %s
+; RUN: llc -march=amdgcn -mcpu=gfx1100 -amdgpu-enable-delay-alu=0 < %s | FileCheck -check-prefixes=GCN,GFX1011,GFX11 %s
+
+declare i32 @llvm.get.fpmode.i32()
+
+define i32 @func_fpmode_i32() {
+; GFX678-LABEL: func_fpmode_i32:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: func_fpmode_i32:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: func_fpmode_i32:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: func_fpmode_i32:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  ret i32 %fpmode
+}
+
+define i32 @strictfp_func_fpmode_i32() strictfp {
+; GFX678-LABEL: strictfp_func_fpmode_i32:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: strictfp_func_fpmode_i32:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: strictfp_func_fpmode_i32:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: strictfp_func_fpmode_i32:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  ret i32 %fpmode
+}
+
+define amdgpu_kernel void @kernel_fpmode_i32(ptr addrspace(1) %ptr) {
+; GFX6-LABEL: kernel_fpmode_i32:
+; GFX6:       ; %bb.0:
+; GFX6-NEXT:    s_load_dwordx2 s[0:1], s[0:1], 0x9
+; GFX6-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX6-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX6-NEXT:    s_mov_b32 s3, 0xf000
+; GFX6-NEXT:    s_mov_b32 s2, -1
+; GFX6-NEXT:    v_mov_b32_e32 v0, s4
+; GFX6-NEXT:    s_waitcnt lgkmcnt(0)
+; GFX6-NEXT:    buffer_store_dword v0, off, s[0:3], 0
+; GFX6-NEXT:    s_endpgm
+;
+; GFX7-LABEL: kernel_fpmode_i32:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_load_dwordx2 s[0:1], s[0:1], 0x9
+; GFX7-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX7-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX7-NEXT:    s_mov_b32 s3, 0xf000
+; GFX7-NEXT:    s_mov_b32 s2, -1
+; GFX7-NEXT:    v_mov_b32_e32 v0, s4
+; GFX7-NEXT:    s_waitcnt lgkmcnt(0)
+; GFX7-NEXT:    buffer_store_dword v0, off, s[0:3], 0
+; GFX7-NEXT:    s_endpgm
+;
+; GFX8-LABEL: kernel_fpmode_i32:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_load_dwordx2 s[0:1], s[0:1], 0x24
+; GFX8-NEXT:    s_getreg_b32 s2, hwreg(HW_REG_MODE, 0, 19)
+; GFX8-NEXT:    s_and_b32 s2, 0x7f3ff, s2
+; GFX8-NEXT:    v_mov_b32_e32 v2, s2
+; GFX8-NEXT:    s_waitcnt lgkmcnt(0)
+; GFX8-NEXT:    v_mov_b32_e32 v0, s0
+; GFX8-NEXT:    v_mov_b32_e32 v1, s1
+; GFX8-NEXT:    flat_store_dword v[0:1], v2
+; GFX8-NEXT:    s_endpgm
+;
+; GFX9-LABEL: kernel_fpmode_i32:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_load_dwordx2 s[0:1], s[0:1], 0x24
+; GFX9-NEXT:    s_getreg_b32 s2, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s2, 0x87f3ff, s2
+; GFX9-NEXT:    v_mov_b32_e32 v0, 0
+; GFX9-NEXT:    v_mov_b32_e32 v1, s2
+; GFX9-NEXT:    s_waitcnt lgkmcnt(0)
+; GFX9-NEXT:    global_store_dword v0, v1, s[0:1]
+; GFX9-NEXT:    s_endpgm
+;
+; GFX10-LABEL: kernel_fpmode_i32:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_load_dwordx2 s[0:1], s[0:1], 0x24
+; GFX10-NEXT:    s_getreg_b32 s2, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    v_mov_b32_e32 v0, 0
+; GFX10-NEXT:    s_and_b32 s2, 0x87f3ff, s2
+; GFX10-NEXT:    v_mov_b32_e32 v1, s2
+; GFX10-NEXT:    s_waitcnt lgkmcnt(0)
+; GFX10-NEXT:    global_store_dword v0, v1, s[0:1]
+; GFX10-NEXT:    s_endpgm
+;
+; GFX11-LABEL: kernel_fpmode_i32:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_load_b64 s[0:1], s[0:1], 0x24
+; GFX11-NEXT:    s_getreg_b32 s2, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s2, 0x87f3ff, s2
+; GFX11-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s2
+; GFX11-NEXT:    s_waitcnt lgkmcnt(0)
+; GFX11-NEXT:    global_store_b32 v0, v1, s[0:1]
+; GFX11-NEXT:    s_nop 0
+; GFX11-NEXT:    s_sendmsg sendmsg(MSG_DEALLOC_VGPRS)
+; GFX11-NEXT:    s_endpgm
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  store i32 %fpmode, ptr addrspace(1) %ptr
+  ret void
+}
+
+; TODO: We should be able to reduce the demanded bits and ask for less
+; from s_getreg_b32
+define i32 @func_fpmode_i32_denormonly() {
+; GFX678-LABEL: func_fpmode_i32_denormonly:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    s_and_b32 s4, s4, 0xf0
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: func_fpmode_i32_denormonly:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    s_and_b32 s4, s4, 0xf0
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: func_fpmode_i32_denormonly:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    s_and_b32 s4, s4, 0xf0
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: func_fpmode_i32_denormonly:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    s_and_b32 s0, s0, 0xf0
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  %denorm.only = and i32 %fpmode, 240
+  ret i32 %denorm.only
+}
+
+define i32 @func_fpmode_i32_roundonly() {
+; GFX678-LABEL: func_fpmode_i32_roundonly:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    s_and_b32 s4, s4, 15
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: func_fpmode_i32_roundonly:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    s_and_b32 s4, s4, 15
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: func_fpmode_i32_roundonly:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    s_and_b32 s4, s4, 15
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: func_fpmode_i32_roundonly:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    s_and_b32 s0, s0, 15
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  %round.only = and i32 %fpmode, 15
+  ret i32 %round.only
+}
+
+define i32 @func_fpmode_i32_round_denorm_only() {
+; GFX678-LABEL: func_fpmode_i32_round_denorm_only:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    s_and_b32 s4, s4, 0xff
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: func_fpmode_i32_round_denorm_only:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    s_and_b32 s4, s4, 0xff
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: func_fpmode_i32_round_denorm_only:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    s_and_b32 s4, s4, 0xff
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: func_fpmode_i32_round_denorm_only:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    s_and_b32 s0, s0, 0xff
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  %round.denorm.only = and i32 %fpmode, 255
+  ret i32 %round.denorm.only
+}
+
+define i32 @func_fpmode_i32_round_denorm_dx10_ieee() {
+; GFX678-LABEL: func_fpmode_i32_round_denorm_dx10_ieee:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    s_and_b32 s4, s4, 0x3ff
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: func_fpmode_i32_round_denorm_dx10_ieee:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    s_and_b32 s4, s4, 0x3ff
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: func_fpmode_i32_round_denorm_dx10_ieee:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    s_and_b32 s4, s4, 0x3ff
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: func_fpmode_i32_round_denorm_dx10_ieee:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    s_and_b32 s0, s0, 0x3ff
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  %core.mode = and i32 %fpmode, 1023
+  ret i32 %core.mode
+}
+
+define i32 @func_fpmode_i32_excp_en() {
+; GFX678-LABEL: func_fpmode_i32_excp_en:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    s_and_b32 s4, s4, 0x7f000
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: func_fpmode_i32_excp_en:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    s_and_b32 s4, s4, 0x7f000
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: func_fpmode_i32_excp_en:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    s_and_b32 s4, s4, 0x7f000
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: func_fpmode_i32_excp_en:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    s_and_b32 s0, s0, 0x7f000
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  %core.mode = and i32 %fpmode, 520192
+  ret i32 %core.mode
+}
+
+; Mask for all bits used on gfx6+
+define i32 @func_fpmode_i32_environment_gfx6() {
+; GFX678-LABEL: func_fpmode_i32_environment_gfx6:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    s_and_b32 s4, s4, 0x7f3ff
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: func_fpmode_i32_environment_gfx6:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    s_and_b32 s4, s4, 0x7f3ff
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: func_fpmode_i32_environment_gfx6:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    s_and_b32 s4, s4, 0x7f3ff
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: func_fpmode_i32_environment_gfx6:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    s_and_b32 s0, s0, 0x7f3ff
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  %core.mode = and i32 %fpmode, 521215
+  ret i32 %core.mode
+}
+
+; Mask for all bits used on gfx9+
+define i32 @func_fpmode_i32_environment_gfx9() {
+; GFX678-LABEL: func_fpmode_i32_environment_gfx9:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    s_and_b32 s4, s4, 0x87f3ff
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: func_fpmode_i32_environment_gfx9:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    s_and_b32 s4, s4, 0x87f3ff
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: func_fpmode_i32_environment_gfx9:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    s_and_b32 s4, s4, 0x87f3ff
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: func_fpmode_i32_environment_gfx9:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    s_and_b32 s0, s0, 0x87f3ff
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  %core.mode = and i32 %fpmode, 8909823
+  ret i32 %core.mode
+}
+
+define i32 @func_fpmode_i32_denormf32only() {
+; GFX678-LABEL: func_fpmode_i32_denormf32only:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    s_and_b32 s4, s4, 48
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: func_fpmode_i32_denormf32only:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    s_and_b32 s4, s4, 48
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: func_fpmode_i32_denormf32only:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    s_and_b32 s4, s4, 48
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: func_fpmode_i32_denormf32only:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    s_and_b32 s0, s0, 48
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  %denorm.only = and i32 %fpmode, 48
+  ret i32 %denorm.only
+}
+
+define i32 @func_fpmode_i32_denormf32only_0() {
+; GFX678-LABEL: func_fpmode_i32_denormf32only_0:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    s_and_b32 s4, s4, 32
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: func_fpmode_i32_denormf32only_0:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    s_and_b32 s4, s4, 32
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: func_fpmode_i32_denormf32only_0:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    s_and_b32 s4, s4, 32
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: func_fpmode_i32_denormf32only_0:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    s_and_b32 s0, s0, 32
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  %denorm.only = and i32 %fpmode, 32
+  ret i32 %denorm.only
+}
+
+define i32 @func_fpmode_i32_denormf32only_1() {
+; GFX678-LABEL: func_fpmode_i32_denormf32only_1:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    s_and_b32 s4, s4, 64
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: func_fpmode_i32_denormf32only_1:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    s_and_b32 s4, s4, 64
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: func_fpmode_i32_denormf32only_1:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    s_and_b32 s4, s4, 64
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: func_fpmode_i32_denormf32only_1:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    s_and_b32 s0, s0, 64
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  %denorm.only = and i32 %fpmode, 64
+  ret i32 %denorm.only
+}
+
+define i32 @func_fpmode_i32_denormf64f16only() {
+; GFX678-LABEL: func_fpmode_i32_denormf64f16only:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    s_and_b32 s4, s4, 0xc0
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: func_fpmode_i32_denormf64f16only:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    s_and_b32 s4, s4, 0xc0
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: func_fpmode_i32_denormf64f16only:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    s_and_b32 s4, s4, 0xc0
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: func_fpmode_i32_denormf64f16only:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    s_and_b32 s0, s0, 0xc0
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  %denorm.only = and i32 %fpmode, 192
+  ret i32 %denorm.only
+}
+
+define i32 @func_fpmode_i32_dx10_clamp_only() {
+; GFX678-LABEL: func_fpmode_i32_dx10_clamp_only:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    s_and_b32 s4, s4, 0x100
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: func_fpmode_i32_dx10_clamp_only:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    s_and_b32 s4, s4, 0x100
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: func_fpmode_i32_dx10_clamp_only:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    s_and_b32 s4, s4, 0x100
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: func_fpmode_i32_dx10_clamp_only:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    s_and_b32 s0, s0, 0x100
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  %dx10.only = and i32 %fpmode, 256
+  ret i32 %dx10.only
+}
+
+define i32 @func_fpmode_i32_ieee_only() {
+; GFX678-LABEL: func_fpmode_i32_ieee_only:
+; GFX678:       ; %bb.0:
+; GFX678-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX678-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 19)
+; GFX678-NEXT:    s_and_b32 s4, 0x7f3ff, s4
+; GFX678-NEXT:    s_and_b32 s4, s4, 0x200
+; GFX678-NEXT:    v_mov_b32_e32 v0, s4
+; GFX678-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX9-LABEL: func_fpmode_i32_ieee_only:
+; GFX9:       ; %bb.0:
+; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX9-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX9-NEXT:    s_and_b32 s4, s4, 0x200
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
+; GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: func_fpmode_i32_ieee_only:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    s_getreg_b32 s4, hwreg(HW_REG_MODE, 0, 24)
+; GFX10-NEXT:    s_and_b32 s4, 0x87f3ff, s4
+; GFX10-NEXT:    s_and_b32 s4, s4, 0x200
+; GFX10-NEXT:    v_mov_b32_e32 v0, s4
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: func_fpmode_i32_ieee_only:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_getreg_b32 s0, hwreg(HW_REG_MODE, 0, 24)
+; GFX11-NEXT:    s_and_b32 s0, 0x87f3ff, s0
+; GFX11-NEXT:    s_and_b32 s0, s0, 0x200
+; GFX11-NEXT:    v_mov_b32_e32 v0, s0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fpmode = call i32 @llvm.get.fpmode.i32()
+  %ieee.only = and i32 %fpmode, 512
+  ret i32 %ieee.only
+}
+
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; GCN: {{.*}}
+; GFX1011: {{.*}}

>From 418002de52e7db5d5b51d445df5aecb50e950a85 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Sat, 26 Aug 2023 18:26:44 +0800
Subject: [PATCH 33/62] [clangd] Show parameter hints for operator()

Closes https://github.com/clangd/clangd/issues/1742

Reviewed By: nridge

Differential Revision: https://reviews.llvm.org/D158926
---
 clang-tools-extra/clangd/InlayHints.cpp       | 31 +++++++++++++--
 .../clangd/unittests/InlayHintTests.cpp       | 38 ++++++++++++++++++-
 2 files changed, 64 insertions(+), 5 deletions(-)

diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp
index 56f85ee155cb236..e6e5e11b889bff8 100644
--- a/clang-tools-extra/clangd/InlayHints.cpp
+++ b/clang-tools-extra/clangd/InlayHints.cpp
@@ -586,11 +586,13 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
     if (!Cfg.InlayHints.Parameters)
       return true;
 
-    // Do not show parameter hints for operator calls written using operator
-    // syntax or user-defined literals. (Among other reasons, the resulting
+    bool IsFunctor = isFunctionObjectCallExpr(E);
+    // Do not show parameter hints for user-defined literals or
+    // operator calls except for operator(). (Among other reasons, the resulting
     // hints can look awkward, e.g. the expression can itself be a function
     // argument and then we'd get two hints side by side).
-    if (isa<CXXOperatorCallExpr>(E) || isa<UserDefinedLiteral>(E))
+    if ((isa<CXXOperatorCallExpr>(E) && !IsFunctor) ||
+        isa<UserDefinedLiteral>(E))
       return true;
 
     auto CalleeDecls = Resolver->resolveCalleeOfCallExpr(E);
@@ -607,7 +609,22 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
     else
       return true;
 
-    processCall(Callee, {E->getArgs(), E->getNumArgs()});
+    // N4868 [over.call.object]p3 says,
+    // The argument list submitted to overload resolution consists of the
+    // argument expressions present in the function call syntax preceded by the
+    // implied object argument (E).
+    //
+    // However, we don't have the implied object argument for static
+    // operator() per clang::Sema::BuildCallToObjectOfClassType.
+    llvm::ArrayRef<const Expr *> Args = {E->getArgs(), E->getNumArgs()};
+    if (IsFunctor)
+      // We don't have the implied object argument through
+      // a function pointer either.
+      if (const CXXMethodDecl *Method =
+              dyn_cast_or_null<CXXMethodDecl>(Callee.Decl);
+          Method && Method->isInstance())
+        Args = Args.drop_front(1);
+    processCall(Callee, Args);
     return true;
   }
 
@@ -1203,6 +1220,12 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
     return Range{HintStart, HintEnd};
   }
 
+  static bool isFunctionObjectCallExpr(CallExpr *E) noexcept {
+    if (auto *CallExpr = dyn_cast<CXXOperatorCallExpr>(E))
+      return CallExpr->getOperator() == OverloadedOperatorKind::OO_Call;
+    return false;
+  }
+
   std::vector<InlayHint> &Results;
   ASTContext &AST;
   const syntax::TokenBuffer &Tokens;
diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
index 1d12db3661c9ebb..a8c3546eb80cc85 100644
--- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
+++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
@@ -89,7 +89,7 @@ void assertHintsWithHeader(InlayHintKind Kind, llvm::StringRef AnnotatedSource,
                            ExpectedHints... Expected) {
   Annotations Source(AnnotatedSource);
   TestTU TU = TestTU::withCode(Source.code());
-  TU.ExtraArgs.push_back("-std=c++20");
+  TU.ExtraArgs.push_back("-std=c++23");
   TU.HeaderCode = HeaderContent;
   auto AST = TU.build();
 
@@ -807,6 +807,42 @@ TEST(ParameterHints, Operator) {
   )cpp");
 }
 
+TEST(ParameterHints, FunctionCallOperator) {
+  assertParameterHints(R"cpp(
+    struct W {
+      void operator()(int x);
+    };
+    struct S : W {
+      using W::operator();
+      static void operator()(int x, int y);
+    };
+    void bar() {
+      auto l1 = [](int x) {};
+      auto l2 = [](int x) static {};
+
+      S s;
+      s($1[[1]]);
+      s.operator()($2[[1]]);
+      s.operator()($3[[1]], $4[[2]]);
+      S::operator()($5[[1]], $6[[2]]);
+
+      l1($7[[1]]);
+      l1.operator()($8[[1]]);
+      l2($9[[1]]);
+      l2.operator()($10[[1]]);
+
+      void (*ptr)(int a, int b) = &S::operator();
+      ptr($11[[1]], $12[[2]]);
+    }
+  )cpp",
+                       ExpectedHint{"x: ", "1"}, ExpectedHint{"x: ", "2"},
+                       ExpectedHint{"x: ", "3"}, ExpectedHint{"y: ", "4"},
+                       ExpectedHint{"x: ", "5"}, ExpectedHint{"y: ", "6"},
+                       ExpectedHint{"x: ", "7"}, ExpectedHint{"x: ", "8"},
+                       ExpectedHint{"x: ", "9"}, ExpectedHint{"x: ", "10"},
+                       ExpectedHint{"a: ", "11"}, ExpectedHint{"b: ", "12"});
+}
+
 TEST(ParameterHints, Macros) {
   // Handling of macros depends on where the call's argument list comes from.
 

>From 9bd5ca9ea5cb45ebfc93d436f6e74247753d7f20 Mon Sep 17 00:00:00 2001
From: Brad Smith <brad at comstyle.com>
Date: Sun, 10 Sep 2023 04:35:58 -0400
Subject: [PATCH 34/62] [Driver] Replace usage of -Bshareable linker flag with
 -shared (#65842)

The two flags mean the same thing for the bfd / lld linkers so just use
the same flag consistently everywhere.
---
 clang/lib/Driver/ToolChains/DragonFly.cpp |  2 +-
 clang/lib/Driver/ToolChains/FreeBSD.cpp   |  2 +-
 clang/lib/Driver/ToolChains/NetBSD.cpp    |  2 +-
 clang/test/Driver/freebsd.c               |  1 +
 clang/test/Driver/netbsd.c                | 12 ++++++------
 5 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/DragonFly.cpp b/clang/lib/Driver/ToolChains/DragonFly.cpp
index 6f46864105e9c0c..900be9e305c902a 100644
--- a/clang/lib/Driver/ToolChains/DragonFly.cpp
+++ b/clang/lib/Driver/ToolChains/DragonFly.cpp
@@ -69,7 +69,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     if (Args.hasArg(options::OPT_rdynamic))
       CmdArgs.push_back("-export-dynamic");
     if (Args.hasArg(options::OPT_shared))
-      CmdArgs.push_back("-Bshareable");
+      CmdArgs.push_back("-shared");
     else if (!Args.hasArg(options::OPT_r)) {
       CmdArgs.push_back("-dynamic-linker");
       CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index b6e025aac29b046..4c46861bbbd74ef 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -161,7 +161,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     if (Args.hasArg(options::OPT_rdynamic))
       CmdArgs.push_back("-export-dynamic");
     if (Args.hasArg(options::OPT_shared)) {
-      CmdArgs.push_back("-Bshareable");
+      CmdArgs.push_back("-shared");
     } else if (!Args.hasArg(options::OPT_r)) {
       CmdArgs.push_back("-dynamic-linker");
       CmdArgs.push_back("/libexec/ld-elf.so.1");
diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp
index ceabb06c14105b3..1ec8f1b7da4c662 100644
--- a/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -139,7 +139,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     if (Args.hasArg(options::OPT_rdynamic))
       CmdArgs.push_back("-export-dynamic");
     if (Args.hasArg(options::OPT_shared)) {
-      CmdArgs.push_back("-Bshareable");
+      CmdArgs.push_back("-shared");
     } else if (!Args.hasArg(options::OPT_r)) {
       Args.AddAllArgs(CmdArgs, options::OPT_pie);
       CmdArgs.push_back("-dynamic-linker");
diff --git a/clang/test/Driver/freebsd.c b/clang/test/Driver/freebsd.c
index 28a888fedf3fe18..8ac0cb011638a8a 100644
--- a/clang/test/Driver/freebsd.c
+++ b/clang/test/Driver/freebsd.c
@@ -128,6 +128,7 @@
 // RUN: %clang --target=x86_64-pc-freebsd -shared %s \
 // RUN:   --sysroot=%S/Inputs/multiarch_freebsd64_tree -### 2>&1 \
 // RUN:   | FileCheck --check-prefix=CHECK-SHARED %s
+// CHECK-SHARED: ld{{.*}}" "--eh-frame-hdr" "-shared"
 // CHECK-SHARED: crti.o
 // CHECK-SHARED: crtbeginS.o
 
diff --git a/clang/test/Driver/netbsd.c b/clang/test/Driver/netbsd.c
index 4daa35a4a7f94fc..67c048c6e91515f 100644
--- a/clang/test/Driver/netbsd.c
+++ b/clang/test/Driver/netbsd.c
@@ -116,20 +116,20 @@
 
 // STATIC: ld{{.*}}" "--eh-frame-hdr"
 // STATIC-NOT: "-pie"
-// STATIC-NOT: "-Bshareable"
+// STATIC-NOT: "-shared"
 // STATIC: "-dynamic-linker" "/libexec/ld.elf_so"
 // STATIC-NOT: "-pie"
-// STATIC-NOT: "-Bshareable"
+// STATIC-NOT: "-shared"
 // STATIC: "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
 // STATIC: "{{.*}}/usr/lib{{/|\\\\}}crti.o" "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o"
 // STATIC: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
 
 // STATIC-PIE: ld{{.*}}" "--eh-frame-hdr"
 // STATIC-PIE-NOT: "-dynamic-linker" "/libexec/ld.elf_so"
-// STATIC-PIE-NOT: "-Bshareable"
+// STATIC-PIE-NOT: "-shared"
 // STATIC-PIE: "-pie"
 // STATIC-PIE-NOT: "-dynamic-linker" "/libexec/ld.elf_so"
-// STATIC-PIE-NOT: "-Bshareable"
+// STATIC-PIE-NOT: "-shared"
 // STATIC-PIE: "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
 // STATIC-PIE: "{{.*}}/usr/lib{{/|\\\\}}crti.o" "{{.*}}/usr/lib{{/|\\\\}}crtbeginS.o"
 // STATIC-PIE: "{{.*}}/usr/lib{{/|\\\\}}crtendS.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
@@ -142,9 +142,9 @@
 // SHARED: "{{.*}}/usr/lib{{/|\\\\}}crtendS.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
 
 // PIE: ld{{.*}}" "--eh-frame-hdr"
-// PIE-NOT: "-Bshareable"
+// PIE-NOT: "-shared"
 // PIE: "-pie" "-dynamic-linker" "/libexec/ld.elf_so"
-// PIE-NOT: "-Bshareable"
+// PIE-NOT: "-shared"
 // PIE: "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
 // PIE: "{{.*}}/usr/lib{{/|\\\\}}crtbeginS.o"
 // PIE: "{{.*}}/usr/lib{{/|\\\\}}crtendS.o"

>From 0c68acea33d456f1fe8c876d12716a446dbb4506 Mon Sep 17 00:00:00 2001
From: Christian Sigg <chsigg at users.noreply.github.com>
Date: Sun, 10 Sep 2023 12:25:19 +0200
Subject: [PATCH 35/62] Fix logic to detect cl::option equality. (#65754)

This is a new attempt of https://reviews.llvm.org/D159481, this time as
GitHub PR.

`GenericOptionValue::compare()` should return `true` for a match.

- `OptionValueBase::compare()` always returns `false` and shouldn't
match anything.
- `OptionValueCopy::compare()` returns `false` if not `Valid` which
corresponds to no match.

Also adding some tests.
---
 llvm/include/llvm/Support/CommandLine.h      |  6 ++-
 llvm/lib/Support/CommandLine.cpp             |  4 +-
 llvm/unittests/Support/CommandLineTest.cpp   | 49 ++++++++++++++++----
 mlir/test/Pass/pipeline-options-parsing.mlir | 12 +++--
 mlir/test/lib/Pass/TestPassManager.cpp       | 11 +++++
 5 files changed, 64 insertions(+), 18 deletions(-)

diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h
index d2079fead66808c..49f4a668ae416fe 100644
--- a/llvm/include/llvm/Support/CommandLine.h
+++ b/llvm/include/llvm/Support/CommandLine.h
@@ -552,6 +552,7 @@ struct OptionValueBase : public GenericOptionValue {
   // Some options may take their value from a different data type.
   template <class DT> void setValue(const DT & /*V*/) {}
 
+  // Returns whether this instance matches the argument.
   bool compare(const DataType & /*V*/) const { return false; }
 
   bool compare(const GenericOptionValue & /*V*/) const override {
@@ -587,7 +588,8 @@ template <class DataType> class OptionValueCopy : public GenericOptionValue {
     Value = V;
   }
 
-  bool compare(const DataType &V) const { return Valid && (Value != V); }
+  // Returns whether this instance matches V.
+  bool compare(const DataType &V) const { return Valid && (Value == V); }
 
   bool compare(const GenericOptionValue &V) const override {
     const OptionValueCopy<DataType> &VC =
@@ -1442,7 +1444,7 @@ class opt
   }
 
   void printOptionValue(size_t GlobalWidth, bool Force) const override {
-    if (Force || this->getDefault().compare(this->getValue())) {
+    if (Force || !this->getDefault().compare(this->getValue())) {
       cl::printOptionDiff<ParserClass>(*this, Parser, this->getValue(),
                                        this->getDefault(), GlobalWidth);
     }
diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp
index d3efb8b67be5c67..55633d7cafa4791 100644
--- a/llvm/lib/Support/CommandLine.cpp
+++ b/llvm/lib/Support/CommandLine.cpp
@@ -2181,7 +2181,7 @@ void generic_parser_base::printGenericOptionDiff(
 
   unsigned NumOpts = getNumOptions();
   for (unsigned i = 0; i != NumOpts; ++i) {
-    if (Value.compare(getOptionValue(i)))
+    if (!Value.compare(getOptionValue(i)))
       continue;
 
     outs() << "= " << getOption(i);
@@ -2189,7 +2189,7 @@ void generic_parser_base::printGenericOptionDiff(
     size_t NumSpaces = MaxOptWidth > L ? MaxOptWidth - L : 0;
     outs().indent(NumSpaces) << " (default: ";
     for (unsigned j = 0; j != NumOpts; ++j) {
-      if (Default.compare(getOptionValue(j)))
+      if (!Default.compare(getOptionValue(j)))
         continue;
       outs() << getOption(j);
       break;
diff --git a/llvm/unittests/Support/CommandLineTest.cpp b/llvm/unittests/Support/CommandLineTest.cpp
index 4f7cb40263b37fd..41cc8260acfedf7 100644
--- a/llvm/unittests/Support/CommandLineTest.cpp
+++ b/llvm/unittests/Support/CommandLineTest.cpp
@@ -1294,7 +1294,8 @@ struct AutoDeleteFile {
   }
 };
 
-class PrintOptionInfoTest : public ::testing::Test {
+template <void (*Func)(const cl::Option &)>
+class PrintOptionTestBase : public ::testing::Test {
 public:
   // Return std::string because the output of a failing EXPECT check is
   // unreadable for StringRef. It also avoids any lifetime issues.
@@ -1309,7 +1310,7 @@ class PrintOptionInfoTest : public ::testing::Test {
 
       StackOption<OptionValue> TestOption(Opt, cl::desc(HelpText),
                                           OptionAttributes...);
-      printOptionInfo(TestOption, 26);
+      Func(TestOption);
       outs().flush();
     }
     auto Buffer = MemoryBuffer::getFile(File.FilePath);
@@ -1321,14 +1322,15 @@ class PrintOptionInfoTest : public ::testing::Test {
   enum class OptionValue { Val };
   const StringRef Opt = "some-option";
   const StringRef HelpText = "some help";
+};
 
-private:
   // This is a workaround for cl::Option sub-classes having their
   // printOptionInfo functions private.
-  void printOptionInfo(const cl::Option &O, size_t Width) {
-    O.printOptionInfo(Width);
-  }
-};
+void printOptionInfo(const cl::Option &O) {
+  O.printOptionInfo(/*GlobalWidth=*/26);
+}
+
+using PrintOptionInfoTest = PrintOptionTestBase<printOptionInfo>;
 
 TEST_F(PrintOptionInfoTest, PrintOptionInfoValueOptionalWithoutSentinel) {
   std::string Output =
@@ -1402,7 +1404,7 @@ TEST_F(PrintOptionInfoTest, PrintOptionInfoMultilineValueDescription) {
                                     "which has a really long description\n"
                                     "thus it is multi-line."),
                          clEnumValN(OptionValue::Val, "",
-                                    "This is an unnamed enum value option\n"
+                                    "This is an unnamed enum value\n"
                                     "Should be indented as well")));
 
   // clang-format off
@@ -1411,11 +1413,40 @@ TEST_F(PrintOptionInfoTest, PrintOptionInfoMultilineValueDescription) {
              "    =v1                 -   This is the first enum value\n"
              "                            which has a really long description\n"
              "                            thus it is multi-line.\n"
-             "    =<empty>            -   This is an unnamed enum value option\n"
+             "    =<empty>            -   This is an unnamed enum value\n"
              "                            Should be indented as well\n").str());
   // clang-format on
 }
 
+void printOptionValue(const cl::Option &O) {
+  O.printOptionValue(/*GlobalWidth=*/12, /*Force=*/true);
+}
+
+using PrintOptionValueTest = PrintOptionTestBase<printOptionValue>;
+
+TEST_F(PrintOptionValueTest, PrintOptionDefaultValue) {
+  std::string Output =
+      runTest(cl::init(OptionValue::Val),
+              cl::values(clEnumValN(OptionValue::Val, "v1", "desc1")));
+
+  EXPECT_EQ(Output, ("    --" + Opt + " = v1       (default: v1)\n").str());
+}
+
+TEST_F(PrintOptionValueTest, PrintOptionNoDefaultValue) {
+  std::string Output =
+      runTest(cl::values(clEnumValN(OptionValue::Val, "v1", "desc1")));
+
+  // Note: the option still has a (zero-initialized) value, but the default
+  // is invalid and doesn't match any value.
+  EXPECT_EQ(Output, ("    --" + Opt + " = v1       (default: )\n").str());
+}
+
+TEST_F(PrintOptionValueTest, PrintOptionUnknownValue) {
+  std::string Output = runTest(cl::init(OptionValue::Val));
+
+  EXPECT_EQ(Output, ("    --" + Opt + " = *unknown option value*\n").str());
+}
+
 class GetOptionWidthTest : public ::testing::Test {
 public:
   enum class OptionValue { Val };
diff --git a/mlir/test/Pass/pipeline-options-parsing.mlir b/mlir/test/Pass/pipeline-options-parsing.mlir
index 33bef75ee94a2b0..34313cd55660333 100644
--- a/mlir/test/Pass/pipeline-options-parsing.mlir
+++ b/mlir/test/Pass/pipeline-options-parsing.mlir
@@ -2,16 +2,18 @@
 // RUN: not mlir-opt %s -pass-pipeline='builtin.module(builtin.module(test-module-pass{test-option=3}))' 2>&1 | FileCheck --check-prefix=CHECK_ERROR_2 %s
 // RUN: not mlir-opt %s -pass-pipeline='builtin.module(builtin.module(func.func(test-options-pass{list=3}), test-module-pass{invalid-option=3}))' 2>&1 | FileCheck --check-prefix=CHECK_ERROR_3 %s
 // RUN: not mlir-opt %s -pass-pipeline='builtin.module(test-options-pass{list=3 list=notaninteger})' 2>&1 | FileCheck --check-prefix=CHECK_ERROR_4 %s
+// RUN: not mlir-opt %s -pass-pipeline='builtin.module(test-options-pass{enum=invalid})' 2>&1 | FileCheck --check-prefix=CHECK_ERROR_5 %s
 // RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(test-options-pass{list=1,2,3,4 list=5 string=value1 string=value2}))'
 // RUN: mlir-opt %s -verify-each=false -pass-pipeline='builtin.module(func.func(test-options-pass{string-list=a list=1,2,3,4 string-list=b,c list=5 string-list=d string=nested_pipeline{arg1=10 arg2=" {} " arg3=true}}))' -dump-pass-pipeline 2>&1 | FileCheck --check-prefix=CHECK_1 %s
-// RUN: mlir-opt %s -verify-each=false -test-options-pass-pipeline='list=1 string-list=a,b' -dump-pass-pipeline 2>&1 | FileCheck --check-prefix=CHECK_2 %s
-// RUN: mlir-opt %s -verify-each=false -pass-pipeline='builtin.module(builtin.module(func.func(test-options-pass{list=3}), func.func(test-options-pass{list=1,2,3,4})))' -dump-pass-pipeline 2>&1 | FileCheck --check-prefix=CHECK_3 %s
+// RUN: mlir-opt %s -verify-each=false -test-options-pass-pipeline='list=1 string-list=a,b enum=one' -dump-pass-pipeline 2>&1 | FileCheck --check-prefix=CHECK_2 %s
+// RUN: mlir-opt %s -verify-each=false -pass-pipeline='builtin.module(builtin.module(func.func(test-options-pass{list=3}), func.func(test-options-pass{enum=one list=1,2,3,4})))' -dump-pass-pipeline 2>&1 | FileCheck --check-prefix=CHECK_3 %s
 
 // CHECK_ERROR_1: missing closing '}' while processing pass options
 // CHECK_ERROR_2: no such option test-option
 // CHECK_ERROR_3: no such option invalid-option
 // CHECK_ERROR_4: 'notaninteger' value invalid for integer argument
+// CHECK_ERROR_5: for the --enum option: Cannot find option named 'invalid'!
 
-// CHECK_1: test-options-pass{list=1,2,3,4,5 string=nested_pipeline{arg1=10 arg2=" {} " arg3=true} string-list=a,b,c,d}
-// CHECK_2: test-options-pass{list=1 string= string-list=a,b}
-// CHECK_3: builtin.module(builtin.module(func.func(test-options-pass{list=3 string= }),func.func(test-options-pass{list=1,2,3,4 string= })))
+// CHECK_1: test-options-pass{enum=zero list=1,2,3,4,5 string=nested_pipeline{arg1=10 arg2=" {} " arg3=true} string-list=a,b,c,d}
+// CHECK_2: test-options-pass{enum=one list=1 string= string-list=a,b}
+// CHECK_3: builtin.module(builtin.module(func.func(test-options-pass{enum=zero list=3 string= }),func.func(test-options-pass{enum=one list=1,2,3,4 string= })))
diff --git a/mlir/test/lib/Pass/TestPassManager.cpp b/mlir/test/lib/Pass/TestPassManager.cpp
index b9cd217839bb9c8..3b24cf44e211080 100644
--- a/mlir/test/lib/Pass/TestPassManager.cpp
+++ b/mlir/test/lib/Pass/TestPassManager.cpp
@@ -53,6 +53,8 @@ struct TestOptionsPass
     : public PassWrapper<TestOptionsPass, OperationPass<func::FuncOp>> {
   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestOptionsPass)
 
+  enum Enum {};
+
   struct Options : public PassPipelineOptions<Options> {
     ListOption<int> listOption{*this, "list",
                                llvm::cl::desc("Example list option")};
@@ -60,6 +62,10 @@ struct TestOptionsPass
         *this, "string-list", llvm::cl::desc("Example string list option")};
     Option<std::string> stringOption{*this, "string",
                                      llvm::cl::desc("Example string option")};
+    Option<Enum> enumOption{
+        *this, "enum", llvm::cl::desc("Example enum option"),
+        llvm::cl::values(clEnumValN(0, "zero", "Example zero value"),
+                         clEnumValN(1, "one", "Example one value"))};
   };
   TestOptionsPass() = default;
   TestOptionsPass(const TestOptionsPass &) : PassWrapper() {}
@@ -67,6 +73,7 @@ struct TestOptionsPass
     listOption = options.listOption;
     stringOption = options.stringOption;
     stringListOption = options.stringListOption;
+    enumOption = options.enumOption;
   }
 
   void runOnOperation() final {}
@@ -81,6 +88,10 @@ struct TestOptionsPass
       *this, "string-list", llvm::cl::desc("Example string list option")};
   Option<std::string> stringOption{*this, "string",
                                    llvm::cl::desc("Example string option")};
+  Option<Enum> enumOption{
+      *this, "enum", llvm::cl::desc("Example enum option"),
+      llvm::cl::values(clEnumValN(0, "zero", "Example zero value"),
+                       clEnumValN(1, "one", "Example one value"))};
 };
 
 /// A test pass that always aborts to enable testing the crash recovery

>From 6a66242e2e1cf1674154f034ae962a40ffb0a3fa Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Sun, 10 Sep 2023 12:48:44 +0100
Subject: [PATCH 36/62] [AArch64][GlobalISel] Fix || / && precedence warning in
 assert. NFC

---
 llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 3f55adef3e05ff9..94d0dbca838dedf 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -2653,7 +2653,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
       }
       }
 
-      assert(DefSize == 32 || DefSize == 64 && "Unexpected const def size");
+      assert((DefSize == 32 || DefSize == 64) && "Unexpected const def size");
       // Either emit a FMOV, or emit a copy to emit a normal mov.
       const Register DefGPRReg = MRI.createVirtualRegister(
           DefSize == 32 ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass);

>From bf535afd8b0b09ff18a4dc69d440fa69756fd507 Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Sun, 10 Sep 2023 13:02:35 +0100
Subject: [PATCH 37/62] [AArch64] Add GlobalISel coverage for BIT/BIF/BSL. NFC

Some of the 1x vector types are expanded to scalar, but the others that do not
require constants looks OK.
---
 llvm/test/CodeGen/AArch64/aarch64-bif-gen.ll  |   81 +-
 llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll  |   83 +-
 .../AArch64/neon-bitwise-instructions.ll      | 2452 ++++++++++++-----
 3 files changed, 1897 insertions(+), 719 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/aarch64-bif-gen.ll b/llvm/test/CodeGen/AArch64/aarch64-bif-gen.ll
index b5a05974f72beb6..cd93332210eda32 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-bif-gen.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-bif-gen.ll
@@ -1,15 +1,27 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu -global-isel < %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI
 
 ; BIF Bitwise Insert if False
 ;
 ; 8-bit vectors tests
 
 define <1 x i8> @test_bitf_v1i8(<1 x i8> %A, <1 x i8> %B, <1 x i8> %C) {
-; CHECK-LABEL: test_bitf_v1i8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bif v0.8b, v1.8b, v2.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: test_bitf_v1i8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bif v0.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: test_bitf_v1i8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    fmov x10, d2
+; CHECK-GI-NEXT:    bic w9, w9, w10
+; CHECK-GI-NEXT:    and w8, w10, w8
+; CHECK-GI-NEXT:    orr w8, w9, w8
+; CHECK-GI-NEXT:    fmov s0, w8
+; CHECK-GI-NEXT:    ret
   %neg = xor <1 x i8> %C, <i8 -1>
   %and = and <1 x i8> %neg, %B
   %and1 = and <1 x i8> %C, %A
@@ -20,10 +32,21 @@ define <1 x i8> @test_bitf_v1i8(<1 x i8> %A, <1 x i8> %B, <1 x i8> %C) {
 ; 16-bit vectors tests
 
 define <1 x i16> @test_bitf_v1i16(<1 x i16> %A, <1 x i16> %B, <1 x i16> %C) {
-; CHECK-LABEL: test_bitf_v1i16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bif v0.8b, v1.8b, v2.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: test_bitf_v1i16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bif v0.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: test_bitf_v1i16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    fmov x10, d2
+; CHECK-GI-NEXT:    bic w9, w9, w10
+; CHECK-GI-NEXT:    and w8, w10, w8
+; CHECK-GI-NEXT:    orr w8, w9, w8
+; CHECK-GI-NEXT:    fmov s0, w8
+; CHECK-GI-NEXT:    ret
   %neg = xor <1 x i16> %C, <i16 -1>
   %and = and <1 x i16> %neg, %B
   %and1 = and <1 x i16> %C, %A
@@ -34,10 +57,23 @@ define <1 x i16> @test_bitf_v1i16(<1 x i16> %A, <1 x i16> %B, <1 x i16> %C) {
 ; 32-bit vectors tests
 
 define <1 x i32> @test_bitf_v1i32(<1 x i32> %A, <1 x i32> %B, <1 x i32> %C) {
-; CHECK-LABEL: test_bitf_v1i32:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bif v0.8b, v1.8b, v2.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: test_bitf_v1i32:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bif v0.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: test_bitf_v1i32:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    fmov x10, d2
+; CHECK-GI-NEXT:    bic w9, w9, w10
+; CHECK-GI-NEXT:    and w8, w10, w8
+; CHECK-GI-NEXT:    orr w8, w9, w8
+; CHECK-GI-NEXT:    fmov s0, w8
+; CHECK-GI-NEXT:    mov v0.s[1], w8
+; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-GI-NEXT:    ret
   %neg = xor <1 x i32> %C, <i32 -1>
   %and = and <1 x i32> %neg, %B
   %and1 = and <1 x i32> %C, %A
@@ -48,10 +84,21 @@ define <1 x i32> @test_bitf_v1i32(<1 x i32> %A, <1 x i32> %B, <1 x i32> %C) {
 ; 64-bit vectors tests
 
 define <1 x i64> @test_bitf_v1i64(<1 x i64> %A, <1 x i64> %B, <1 x i64> %C) {
-; CHECK-LABEL: test_bitf_v1i64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bif v0.8b, v1.8b, v2.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: test_bitf_v1i64:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bif v0.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: test_bitf_v1i64:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d2
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    fmov x10, d0
+; CHECK-GI-NEXT:    bic x9, x9, x8
+; CHECK-GI-NEXT:    and x8, x8, x10
+; CHECK-GI-NEXT:    orr x8, x9, x8
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
   %neg = xor <1 x i64> %C, <i64 -1>
   %and = and <1 x i64> %neg, %B
   %and1 = and <1 x i64> %C, %A
diff --git a/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll b/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll
index 92fd446ebe8f588..b4ddff76f25b870 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll
@@ -1,15 +1,29 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu -global-isel -global-isel-abort=2 < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+
+; CHECK-GI:       warning: Instruction selection used fallback path for test_bit_sink_operand
 
 ; BIT Bitwise Insert if True
 ;
 ; 8-bit vectors tests
 
 define <1 x i8> @test_bit_v1i8(<1 x i8> %A, <1 x i8> %B, <1 x i8> %C) {
-; CHECK-LABEL: test_bit_v1i8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bit v0.8b, v1.8b, v2.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: test_bit_v1i8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bit v0.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: test_bit_v1i8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    fmov x10, d2
+; CHECK-GI-NEXT:    and w9, w10, w9
+; CHECK-GI-NEXT:    bic w8, w8, w10
+; CHECK-GI-NEXT:    orr w8, w9, w8
+; CHECK-GI-NEXT:    fmov s0, w8
+; CHECK-GI-NEXT:    ret
   %and = and <1 x i8> %C, %B
   %neg = xor <1 x i8> %C, <i8 -1>
   %and1 = and <1 x i8> %neg, %A
@@ -20,10 +34,21 @@ define <1 x i8> @test_bit_v1i8(<1 x i8> %A, <1 x i8> %B, <1 x i8> %C) {
 ; 16-bit vectors tests
 
 define <1 x i16> @test_bit_v1i16(<1 x i16> %A, <1 x i16> %B, <1 x i16> %C) {
-; CHECK-LABEL: test_bit_v1i16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bit v0.8b, v1.8b, v2.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: test_bit_v1i16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bit v0.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: test_bit_v1i16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    fmov x10, d2
+; CHECK-GI-NEXT:    and w9, w10, w9
+; CHECK-GI-NEXT:    bic w8, w8, w10
+; CHECK-GI-NEXT:    orr w8, w9, w8
+; CHECK-GI-NEXT:    fmov s0, w8
+; CHECK-GI-NEXT:    ret
   %and = and <1 x i16> %C, %B
   %neg = xor <1 x i16> %C, <i16 -1>
   %and1 = and <1 x i16> %neg, %A
@@ -34,10 +59,23 @@ define <1 x i16> @test_bit_v1i16(<1 x i16> %A, <1 x i16> %B, <1 x i16> %C) {
 ; 32-bit vectors tests
 
 define <1 x i32> @test_bit_v1i32(<1 x i32> %A, <1 x i32> %B, <1 x i32> %C) {
-; CHECK-LABEL: test_bit_v1i32:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bit v0.8b, v1.8b, v2.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: test_bit_v1i32:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bit v0.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: test_bit_v1i32:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    fmov x10, d2
+; CHECK-GI-NEXT:    and w9, w10, w9
+; CHECK-GI-NEXT:    bic w8, w8, w10
+; CHECK-GI-NEXT:    orr w8, w9, w8
+; CHECK-GI-NEXT:    fmov s0, w8
+; CHECK-GI-NEXT:    mov v0.s[1], w8
+; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-GI-NEXT:    ret
   %and = and <1 x i32> %C, %B
   %neg = xor <1 x i32> %C, <i32 -1>
   %and1 = and <1 x i32> %neg, %A
@@ -48,10 +86,21 @@ define <1 x i32> @test_bit_v1i32(<1 x i32> %A, <1 x i32> %B, <1 x i32> %C) {
 ; 64-bit vectors tests
 
 define <1 x i64> @test_bit_v1i64(<1 x i64> %A, <1 x i64> %B, <1 x i64> %C) {
-; CHECK-LABEL: test_bit_v1i64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bit v0.8b, v1.8b, v2.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: test_bit_v1i64:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bit v0.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: test_bit_v1i64:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d2
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    fmov x10, d0
+; CHECK-GI-NEXT:    and x9, x8, x9
+; CHECK-GI-NEXT:    bic x8, x10, x8
+; CHECK-GI-NEXT:    orr x8, x9, x8
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
   %and = and <1 x i64> %C, %B
   %neg = xor <1 x i64> %C, <i64 -1>
   %and1 = and <1 x i64> %neg, %A
diff --git a/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll b/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
index 221a1eb693ffa46..47de57a68be96a4 100644
--- a/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
+++ b/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc < %s -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -mattr=+neon | FileCheck %s
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu -global-isel < %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI
 
 define <8 x i8> @and8xi8(<8 x i8> %a, <8 x i8> %b) {
 ; CHECK-LABEL: and8xi8:
@@ -58,11 +59,22 @@ define <16 x i8> @xor16xi8(<16 x i8> %a, <16 x i8> %b) {
 }
 
 define <8 x i8> @bsl8xi8_const(<8 x i8> %a, <8 x i8> %b)  {
-; CHECK-LABEL: bsl8xi8_const:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    movi d2, #0x00ffff0000ffff
-; CHECK-NEXT:    bif v0.8b, v1.8b, v2.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bsl8xi8_const:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    movi d2, #0x00ffff0000ffff
+; CHECK-SD-NEXT:    bif v0.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bsl8xi8_const:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI6_1
+; CHECK-GI-NEXT:    adrp x9, .LCPI6_0
+; CHECK-GI-NEXT:    ldr d2, [x8, :lo12:.LCPI6_1]
+; CHECK-GI-NEXT:    ldr d3, [x9, :lo12:.LCPI6_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v2.8b
+; CHECK-GI-NEXT:    and v1.8b, v1.8b, v3.8b
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i8> %a, < i8 -1, i8 -1, i8 0, i8 0, i8 -1, i8 -1, i8 0, i8 0 >
 	%tmp2 = and <8 x i8> %b, < i8 0, i8 0, i8 -1, i8 -1, i8 0, i8 0, i8 -1, i8 -1 >
 	%tmp3 = or <8 x i8> %tmp1, %tmp2
@@ -70,11 +82,22 @@ define <8 x i8> @bsl8xi8_const(<8 x i8> %a, <8 x i8> %b)  {
 }
 
 define <16 x i8> @bsl16xi8_const(<16 x i8> %a, <16 x i8> %b) {
-; CHECK-LABEL: bsl16xi8_const:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    movi v2.2d, #0x000000ffffffff
-; CHECK-NEXT:    bif v0.16b, v1.16b, v2.16b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bsl16xi8_const:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    movi v2.2d, #0x000000ffffffff
+; CHECK-SD-NEXT:    bif v0.16b, v1.16b, v2.16b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bsl16xi8_const:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI7_1
+; CHECK-GI-NEXT:    adrp x9, .LCPI7_0
+; CHECK-GI-NEXT:    ldr q2, [x8, :lo12:.LCPI7_1]
+; CHECK-GI-NEXT:    ldr q3, [x9, :lo12:.LCPI7_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v2.16b
+; CHECK-GI-NEXT:    and v1.16b, v1.16b, v3.16b
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <16 x i8> %a, < i8 -1, i8 -1, i8 -1, i8 -1, i8 0, i8 0, i8 0, i8 0, i8 -1, i8 -1, i8 -1, i8 -1, i8 0, i8 0, i8 0, i8 0 >
 	%tmp2 = and <16 x i8> %b, < i8 0, i8 0, i8 0, i8 0, i8 -1, i8 -1, i8 -1, i8 -1, i8 0, i8 0, i8 0, i8 0, i8 -1, i8 -1, i8 -1, i8 -1 >
 	%tmp3 = or <16 x i8> %tmp1, %tmp2
@@ -122,255 +145,451 @@ define <16 x i8> @bic16xi8(<16 x i8> %a, <16 x i8> %b) {
 }
 
 define <2 x i32> @orrimm2s_lsl0(<2 x i32> %a) {
-; CHECK-LABEL: orrimm2s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orrimm2s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orrimm2s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI12_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI12_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <2 x i32> %a, < i32 255, i32 255>
 	ret <2 x i32> %tmp1
 }
 
 define <2 x i32> @orrimm2s_lsl8(<2 x i32> %a) {
-; CHECK-LABEL: orrimm2s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orrimm2s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orrimm2s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI13_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI13_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <2 x i32> %a, < i32 65280, i32 65280>
 	ret <2 x i32> %tmp1
 }
 
 define <2 x i32> @orrimm2s_lsl16(<2 x i32> %a) {
-; CHECK-LABEL: orrimm2s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orrimm2s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orrimm2s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI14_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI14_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <2 x i32> %a, < i32 16711680, i32 16711680>
 	ret <2 x i32> %tmp1
 }
 
 define <2 x i32> @orrimm2s_lsl24(<2 x i32> %a) {
-; CHECK-LABEL: orrimm2s_lsl24:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orrimm2s_lsl24:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orrimm2s_lsl24:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI15_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI15_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <2 x i32> %a, < i32 4278190080, i32 4278190080>
 	ret <2 x i32> %tmp1
 }
 
 define <4 x i32> @orrimm4s_lsl0(<4 x i32> %a) {
-; CHECK-LABEL: orrimm4s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orrimm4s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orrimm4s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI16_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI16_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <4 x i32> %a, < i32 255, i32 255, i32 255, i32 255>
 	ret <4 x i32> %tmp1
 }
 
 define <4 x i32> @orrimm4s_lsl8(<4 x i32> %a) {
-; CHECK-LABEL: orrimm4s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orrimm4s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orrimm4s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI17_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI17_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <4 x i32> %a, < i32 65280, i32 65280, i32 65280, i32 65280>
 	ret <4 x i32> %tmp1
 }
 
 define <4 x i32> @orrimm4s_lsl16(<4 x i32> %a) {
-; CHECK-LABEL: orrimm4s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orrimm4s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orrimm4s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI18_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI18_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <4 x i32> %a, < i32 16711680, i32 16711680, i32 16711680, i32 16711680>
 	ret <4 x i32> %tmp1
 }
 
 define <4 x i32> @orrimm4s_lsl24(<4 x i32> %a) {
-; CHECK-LABEL: orrimm4s_lsl24:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orrimm4s_lsl24:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orrimm4s_lsl24:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI19_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI19_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <4 x i32> %a, < i32 4278190080, i32 4278190080, i32 4278190080, i32 4278190080>
 	ret <4 x i32> %tmp1
 }
 
 define <4 x i16> @orrimm4h_lsl0(<4 x i16> %a) {
-; CHECK-LABEL: orrimm4h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orrimm4h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orrimm4h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI20_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI20_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <4 x i16> %a, < i16 255, i16 255, i16 255, i16 255 >
 	ret <4 x i16> %tmp1
 }
 
 define <4 x i16> @orrimm4h_lsl8(<4 x i16> %a) {
-; CHECK-LABEL: orrimm4h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orrimm4h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orrimm4h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI21_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI21_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <4 x i16> %a, < i16 65280, i16 65280, i16 65280, i16 65280 >
 	ret <4 x i16> %tmp1
 }
 
 define <8 x i16> @orrimm8h_lsl0(<8 x i16> %a) {
-; CHECK-LABEL: orrimm8h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.8h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orrimm8h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.8h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orrimm8h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI22_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI22_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <8 x i16> %a, < i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255 >
 	ret <8 x i16> %tmp1
 }
 
 define <8 x i16> @orrimm8h_lsl8(<8 x i16> %a) {
-; CHECK-LABEL: orrimm8h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.8h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orrimm8h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.8h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orrimm8h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI23_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI23_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <8 x i16> %a, < i16 65280, i16 65280, i16 65280, i16 65280, i16 65280, i16 65280, i16 65280, i16 65280 >
 	ret <8 x i16> %tmp1
 }
 
 define <2 x i32> @bicimm2s_lsl0(<2 x i32> %a) {
-; CHECK-LABEL: bicimm2s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm2s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm2s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI24_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI24_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <2 x i32> %a, < i32 4294967279, i32 4294967279 >
 	ret <2 x i32> %tmp1
 }
 
 define <2 x i32> @bicimm2s_lsl8(<2 x i32> %a) {
-; CHECK-LABEL: bicimm2s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #16, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm2s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #16, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm2s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI25_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI25_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <2 x i32> %a, < i32 4294963199, i32  4294963199 >
 	ret <2 x i32> %tmp1
 }
 
 define <2 x i32> @bicimm2s_lsl16(<2 x i32> %a) {
-; CHECK-LABEL: bicimm2s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #16, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm2s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #16, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm2s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI26_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI26_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <2 x i32> %a, < i32 4293918719, i32 4293918719 >
 	ret <2 x i32> %tmp1
 }
 
 define <2 x i32> @bicimm2s_lsl124(<2 x i32> %a) {
-; CHECK-LABEL: bicimm2s_lsl124:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #16, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm2s_lsl124:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #16, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm2s_lsl124:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI27_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI27_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <2 x i32> %a, < i32 4026531839, i32  4026531839>
 	ret <2 x i32> %tmp1
 }
 
 define <4 x i32> @bicimm4s_lsl0(<4 x i32> %a) {
-; CHECK-LABEL: bicimm4s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm4s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm4s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI28_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI28_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i32> %a, < i32 4294967279, i32 4294967279, i32 4294967279, i32 4294967279 >
 	ret <4 x i32> %tmp1
 }
 
 define <4 x i32> @bicimm4s_lsl8(<4 x i32> %a) {
-; CHECK-LABEL: bicimm4s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #16, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm4s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #16, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm4s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI29_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI29_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i32> %a, < i32 4294963199, i32  4294963199, i32  4294963199, i32  4294963199 >
 	ret <4 x i32> %tmp1
 }
 
 define <4 x i32> @bicimm4s_lsl16(<4 x i32> %a) {
-; CHECK-LABEL: bicimm4s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #16, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm4s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #16, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm4s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI30_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI30_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i32> %a, < i32 4293918719, i32 4293918719, i32 4293918719, i32 4293918719 >
 	ret <4 x i32> %tmp1
 }
 
 define <4 x i32> @bicimm4s_lsl124(<4 x i32> %a) {
-; CHECK-LABEL: bicimm4s_lsl124:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #16, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm4s_lsl124:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #16, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm4s_lsl124:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI31_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI31_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i32> %a, < i32 4026531839, i32  4026531839, i32  4026531839, i32  4026531839>
 	ret <4 x i32> %tmp1
 }
 
 define <4 x i16> @bicimm4h_lsl0_a(<4 x i16> %a) {
-; CHECK-LABEL: bicimm4h_lsl0_a:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4h, #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm4h_lsl0_a:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4h, #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm4h_lsl0_a:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI32_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI32_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i16> %a, < i16 4294967279, i16  4294967279, i16  4294967279, i16  4294967279 >
 	ret <4 x i16> %tmp1
 }
 
 define <4 x i16> @bicimm4h_lsl0_b(<4 x i16> %a) {
-; CHECK-LABEL: bicimm4h_lsl0_b:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm4h_lsl0_b:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm4h_lsl0_b:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI33_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI33_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i16> %a, < i16 65280, i16  65280, i16  65280, i16 65280 >
 	ret <4 x i16> %tmp1
 }
 
 define <4 x i16> @bicimm4h_lsl8_a(<4 x i16> %a) {
-; CHECK-LABEL: bicimm4h_lsl8_a:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4h, #16, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm4h_lsl8_a:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4h, #16, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm4h_lsl8_a:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI34_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI34_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i16> %a, < i16 4294963199, i16  4294963199, i16  4294963199, i16  4294963199>
 	ret <4 x i16> %tmp1
 }
 
 define <4 x i16> @bicimm4h_lsl8_b(<4 x i16> %a) {
-; CHECK-LABEL: bicimm4h_lsl8_b:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm4h_lsl8_b:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm4h_lsl8_b:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI35_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI35_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i16> %a, < i16 255, i16 255, i16 255, i16 255>
 	ret <4 x i16> %tmp1
 }
 
 define <8 x i16> @bicimm8h_lsl0_a(<8 x i16> %a) {
-; CHECK-LABEL: bicimm8h_lsl0_a:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.8h, #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm8h_lsl0_a:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.8h, #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm8h_lsl0_a:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI36_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI36_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i16> %a, < i16 4294967279, i16  4294967279, i16  4294967279, i16  4294967279,
    i16  4294967279, i16  4294967279, i16  4294967279, i16  4294967279 >
 	ret <8 x i16> %tmp1
 }
 
 define <8 x i16> @bicimm8h_lsl0_b(<8 x i16> %a) {
-; CHECK-LABEL: bicimm8h_lsl0_b:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.8h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm8h_lsl0_b:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.8h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm8h_lsl0_b:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI37_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI37_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i16> %a, < i16 65280, i16  65280, i16  65280, i16 65280, i16 65280, i16  65280, i16  65280, i16 65280 >
 	ret <8 x i16> %tmp1
 }
 
 define <8 x i16> @bicimm8h_lsl8_a(<8 x i16> %a) {
-; CHECK-LABEL: bicimm8h_lsl8_a:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.8h, #16, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm8h_lsl8_a:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.8h, #16, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm8h_lsl8_a:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI38_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI38_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i16> %a, < i16 4294963199, i16  4294963199, i16  4294963199, i16  4294963199,
    i16  4294963199, i16  4294963199, i16  4294963199, i16  4294963199>
 	ret <8 x i16> %tmp1
 }
 
 define <8 x i16> @bicimm8h_lsl8_b(<8 x i16> %a) {
-; CHECK-LABEL: bicimm8h_lsl8_b:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.8h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bicimm8h_lsl8_b:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.8h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bicimm8h_lsl8_b:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI39_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI39_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i16> %a, < i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>
 	ret <8 x i16> %tmp1
 }
@@ -394,10 +613,18 @@ define <4 x i16> @and4xi16(<4 x i16> %a, <4 x i16> %b) {
 }
 
 define <1 x i64> @and1xi64(<1 x i64> %a, <1 x i64> %b) {
-; CHECK-LABEL: and1xi64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    and v0.8b, v0.8b, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and1xi64:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and1xi64:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    and x8, x8, x9
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <1 x i64> %a, %b;
 	ret <1 x i64> %tmp1
 }
@@ -448,10 +675,18 @@ define <4 x i16> @orr4xi16(<4 x i16> %a, <4 x i16> %b) {
 }
 
 define <1 x i64> @orr1xi64(<1 x i64> %a, <1 x i64> %b) {
-; CHECK-LABEL: orr1xi64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.8b, v0.8b, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr1xi64:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr1xi64:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    orr x8, x8, x9
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <1 x i64> %a, %b;
 	ret <1 x i64> %tmp1
 }
@@ -502,10 +737,18 @@ define <4 x i16> @eor4xi16(<4 x i16> %a, <4 x i16> %b) {
 }
 
 define <1 x i64> @eor1xi64(<1 x i64> %a, <1 x i64> %b) {
-; CHECK-LABEL: eor1xi64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    eor v0.8b, v0.8b, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: eor1xi64:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    eor v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: eor1xi64:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    eor x8, x8, x9
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = xor <1 x i64> %a, %b;
 	ret <1 x i64> %tmp1
 }
@@ -559,10 +802,18 @@ define <4 x i16> @bic4xi16(<4 x i16> %a, <4 x i16> %b)  {
 }
 
 define <1 x i64> @bic1xi64(<1 x i64> %a, <1 x i64> %b)  {
-; CHECK-LABEL: bic1xi64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.8b, v0.8b, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bic1xi64:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bic1xi64:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d1
+; CHECK-GI-NEXT:    fmov x9, d0
+; CHECK-GI-NEXT:    bic x8, x9, x8
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
   %tmp1 = xor <1 x i64> %b, < i64 -1>
   %tmp2 = and <1 x i64> %a, %tmp1
   ret <1 x i64> %tmp2
@@ -619,10 +870,18 @@ define <4 x i16> @orn4xi16(<4 x i16> %a, <4 x i16> %b)  {
 }
 
 define <1 x i64> @orn1xi64(<1 x i64> %a, <1 x i64> %b)  {
-; CHECK-LABEL: orn1xi64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orn v0.8b, v0.8b, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orn1xi64:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orn v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orn1xi64:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d1
+; CHECK-GI-NEXT:    fmov x9, d0
+; CHECK-GI-NEXT:    orn x8, x9, x8
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
   %tmp1 = xor <1 x i64> %b, < i64 -1>
   %tmp2 = or <1 x i64> %a, %tmp1
   ret <1 x i64> %tmp2
@@ -659,11 +918,22 @@ define <2 x i64> @orn2xi64(<2 x i64> %a, <2 x i64> %b)  {
 }
 
 define <2 x i32> @bsl2xi32_const(<2 x i32> %a, <2 x i32> %b)  {
-; CHECK-LABEL: bsl2xi32_const:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    movi d2, #0x000000ffffffff
-; CHECK-NEXT:    bif v0.8b, v1.8b, v2.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bsl2xi32_const:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    movi d2, #0x000000ffffffff
+; CHECK-SD-NEXT:    bif v0.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bsl2xi32_const:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI70_1
+; CHECK-GI-NEXT:    adrp x9, .LCPI70_0
+; CHECK-GI-NEXT:    ldr d2, [x8, :lo12:.LCPI70_1]
+; CHECK-GI-NEXT:    ldr d3, [x9, :lo12:.LCPI70_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v2.8b
+; CHECK-GI-NEXT:    and v1.8b, v1.8b, v3.8b
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <2 x i32> %a, < i32 -1, i32 0 >
 	%tmp2 = and <2 x i32> %b, < i32 0, i32 -1 >
 	%tmp3 = or <2 x i32> %tmp1, %tmp2
@@ -672,11 +942,22 @@ define <2 x i32> @bsl2xi32_const(<2 x i32> %a, <2 x i32> %b)  {
 
 
 define <4 x i16> @bsl4xi16_const(<4 x i16> %a, <4 x i16> %b)  {
-; CHECK-LABEL: bsl4xi16_const:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    movi d2, #0x00ffff0000ffff
-; CHECK-NEXT:    bif v0.8b, v1.8b, v2.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bsl4xi16_const:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    movi d2, #0x00ffff0000ffff
+; CHECK-SD-NEXT:    bif v0.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bsl4xi16_const:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI71_1
+; CHECK-GI-NEXT:    adrp x9, .LCPI71_0
+; CHECK-GI-NEXT:    ldr d2, [x8, :lo12:.LCPI71_1]
+; CHECK-GI-NEXT:    ldr d3, [x9, :lo12:.LCPI71_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v2.8b
+; CHECK-GI-NEXT:    and v1.8b, v1.8b, v3.8b
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i16> %a, < i16 -1, i16 0, i16 -1,i16 0 >
 	%tmp2 = and <4 x i16> %b, < i16 0, i16 -1,i16 0, i16 -1 >
 	%tmp3 = or <4 x i16> %tmp1, %tmp2
@@ -684,11 +965,21 @@ define <4 x i16> @bsl4xi16_const(<4 x i16> %a, <4 x i16> %b)  {
 }
 
 define <1 x i64> @bsl1xi64_const(<1 x i64> %a, <1 x i64> %b)  {
-; CHECK-LABEL: bsl1xi64_const:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    movi d2, #0xffffffffffffff00
-; CHECK-NEXT:    bif v0.8b, v1.8b, v2.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bsl1xi64_const:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    movi d2, #0xffffffffffffff00
+; CHECK-SD-NEXT:    bif v0.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bsl1xi64_const:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    and x8, x8, #0xffffffffffffff00
+; CHECK-GI-NEXT:    and x9, x9, #0xff
+; CHECK-GI-NEXT:    orr x8, x8, x9
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <1 x i64> %a, < i64 -256 >
 	%tmp2 = and <1 x i64> %b, < i64 255 >
 	%tmp3 = or <1 x i64> %tmp1, %tmp2
@@ -696,11 +987,22 @@ define <1 x i64> @bsl1xi64_const(<1 x i64> %a, <1 x i64> %b)  {
 }
 
 define <4 x i32> @bsl4xi32_const(<4 x i32> %a, <4 x i32> %b)  {
-; CHECK-LABEL: bsl4xi32_const:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    movi v2.2d, #0x000000ffffffff
-; CHECK-NEXT:    bif v0.16b, v1.16b, v2.16b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bsl4xi32_const:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    movi v2.2d, #0x000000ffffffff
+; CHECK-SD-NEXT:    bif v0.16b, v1.16b, v2.16b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bsl4xi32_const:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI73_1
+; CHECK-GI-NEXT:    adrp x9, .LCPI73_0
+; CHECK-GI-NEXT:    ldr q2, [x8, :lo12:.LCPI73_1]
+; CHECK-GI-NEXT:    ldr q3, [x9, :lo12:.LCPI73_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v2.16b
+; CHECK-GI-NEXT:    and v1.16b, v1.16b, v3.16b
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i32> %a, < i32 -1, i32 0, i32 -1, i32 0 >
 	%tmp2 = and <4 x i32> %b, < i32 0, i32 -1, i32 0, i32 -1 >
 	%tmp3 = or <4 x i32> %tmp1, %tmp2
@@ -708,11 +1010,22 @@ define <4 x i32> @bsl4xi32_const(<4 x i32> %a, <4 x i32> %b)  {
 }
 
 define <8 x i16> @bsl8xi16_const(<8 x i16> %a, <8 x i16> %b)  {
-; CHECK-LABEL: bsl8xi16_const:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    movi v2.2d, #0x000000ffffffff
-; CHECK-NEXT:    bif v0.16b, v1.16b, v2.16b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bsl8xi16_const:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    movi v2.2d, #0x000000ffffffff
+; CHECK-SD-NEXT:    bif v0.16b, v1.16b, v2.16b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bsl8xi16_const:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI74_1
+; CHECK-GI-NEXT:    adrp x9, .LCPI74_0
+; CHECK-GI-NEXT:    ldr q2, [x8, :lo12:.LCPI74_1]
+; CHECK-GI-NEXT:    ldr q3, [x9, :lo12:.LCPI74_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v2.16b
+; CHECK-GI-NEXT:    and v1.16b, v1.16b, v3.16b
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i16> %a, < i16 -1, i16 -1, i16 0,i16 0, i16 -1, i16 -1, i16 0,i16 0 >
 	%tmp2 = and <8 x i16> %b, < i16 0, i16 0, i16 -1, i16 -1, i16 0, i16 0, i16 -1, i16 -1 >
 	%tmp3 = or <8 x i16> %tmp1, %tmp2
@@ -720,12 +1033,23 @@ define <8 x i16> @bsl8xi16_const(<8 x i16> %a, <8 x i16> %b)  {
 }
 
 define <2 x i64> @bsl2xi64_const(<2 x i64> %a, <2 x i64> %b)  {
-; CHECK-LABEL: bsl2xi64_const:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp x8, .LCPI75_0
-; CHECK-NEXT:    ldr q2, [x8, :lo12:.LCPI75_0]
-; CHECK-NEXT:    bif v0.16b, v1.16b, v2.16b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bsl2xi64_const:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    adrp x8, .LCPI75_0
+; CHECK-SD-NEXT:    ldr q2, [x8, :lo12:.LCPI75_0]
+; CHECK-SD-NEXT:    bif v0.16b, v1.16b, v2.16b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bsl2xi64_const:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI75_1
+; CHECK-GI-NEXT:    adrp x9, .LCPI75_0
+; CHECK-GI-NEXT:    ldr q2, [x8, :lo12:.LCPI75_1]
+; CHECK-GI-NEXT:    ldr q3, [x9, :lo12:.LCPI75_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v2.16b
+; CHECK-GI-NEXT:    and v1.16b, v1.16b, v3.16b
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <2 x i64> %a, < i64 -1, i64 0 >
 	%tmp2 = and <2 x i64> %b, < i64 0, i64 -1 >
 	%tmp3 = or <2 x i64> %tmp1, %tmp2
@@ -770,10 +1094,21 @@ define <2 x i32> @bsl2xi32(<2 x i32> %v1, <2 x i32> %v2, <2 x i32> %v3) {
 }
 
 define <1 x i64> @bsl1xi64(<1 x i64> %v1, <1 x i64> %v2, <1 x i64> %v3) {
-; CHECK-LABEL: bsl1xi64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bsl v0.8b, v1.8b, v2.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bsl1xi64:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bsl v0.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bsl1xi64:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    fmov x10, d2
+; CHECK-GI-NEXT:    and x9, x8, x9
+; CHECK-GI-NEXT:    bic x8, x10, x8
+; CHECK-GI-NEXT:    orr x8, x9, x8
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
   %1 = and <1 x i64> %v1, %v2
   %2 = xor <1 x i64> %v1, <i64 -1>
   %3 = and <1 x i64> %2, %v3
@@ -818,233 +1153,380 @@ define <4 x i32> @bsl4xi32(<4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) {
 }
 
 define <8 x i8> @vselect_constant_cond_zero_v8i8(<8 x i8> %a) {
-; CHECK-LABEL: vselect_constant_cond_zero_v8i8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    movi d1, #0x00000000ff00ff
-; CHECK-NEXT:    and v0.8b, v0.8b, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_constant_cond_zero_v8i8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    movi d1, #0x00000000ff00ff
+; CHECK-SD-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_constant_cond_zero_v8i8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI83_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI83_0]
+; CHECK-GI-NEXT:    shl v1.8b, v1.8b, #7
+; CHECK-GI-NEXT:    sshr v1.8b, v1.8b, #7
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
   %b = select <8 x i1> <i1 true, i1 false, i1 true, i1 false, i1 false, i1 false, i1 false, i1 false>, <8 x i8> %a, <8 x i8> zeroinitializer
   ret <8 x i8> %b
 }
 
 define <4 x i16> @vselect_constant_cond_zero_v4i16(<4 x i16> %a) {
-; CHECK-LABEL: vselect_constant_cond_zero_v4i16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    movi d1, #0xffff00000000ffff
-; CHECK-NEXT:    and v0.8b, v0.8b, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_constant_cond_zero_v4i16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    movi d1, #0xffff00000000ffff
+; CHECK-SD-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_constant_cond_zero_v4i16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI84_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI84_0]
+; CHECK-GI-NEXT:    shl v1.4h, v1.4h, #15
+; CHECK-GI-NEXT:    sshr v1.4h, v1.4h, #15
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
   %b = select <4 x i1> <i1 true, i1 false, i1 false, i1 true>, <4 x i16> %a, <4 x i16> zeroinitializer
   ret <4 x i16> %b
 }
 
 define <4 x i32> @vselect_constant_cond_zero_v4i32(<4 x i32> %a) {
-; CHECK-LABEL: vselect_constant_cond_zero_v4i32:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp x8, .LCPI85_0
-; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI85_0]
-; CHECK-NEXT:    and v0.16b, v0.16b, v1.16b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_constant_cond_zero_v4i32:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    adrp x8, .LCPI85_0
+; CHECK-SD-NEXT:    ldr q1, [x8, :lo12:.LCPI85_0]
+; CHECK-SD-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_constant_cond_zero_v4i32:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI85_1
+; CHECK-GI-NEXT:    adrp x9, .LCPI85_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI85_1]
+; CHECK-GI-NEXT:    ldr d2, [x9, :lo12:.LCPI85_0]
+; CHECK-GI-NEXT:    mov v1.d[1], v2.d[0]
+; CHECK-GI-NEXT:    shl v1.4s, v1.4s, #31
+; CHECK-GI-NEXT:    sshr v1.4s, v1.4s, #31
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
   %b = select <4 x i1> <i1 true, i1 false, i1 false, i1 true>, <4 x i32> %a, <4 x i32> zeroinitializer
   ret <4 x i32> %b
 }
 
 define <8 x i8> @vselect_constant_cond_v8i8(<8 x i8> %a, <8 x i8> %b) {
-; CHECK-LABEL: vselect_constant_cond_v8i8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    movi d2, #0xffffffffff00ff00
-; CHECK-NEXT:    movi d3, #0x00000000ff00ff
-; CHECK-NEXT:    and v1.8b, v1.8b, v2.8b
-; CHECK-NEXT:    and v0.8b, v0.8b, v3.8b
-; CHECK-NEXT:    orr v0.8b, v0.8b, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_constant_cond_v8i8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    movi d2, #0xffffffffff00ff00
+; CHECK-SD-NEXT:    movi d3, #0x00000000ff00ff
+; CHECK-SD-NEXT:    and v1.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    and v0.8b, v0.8b, v3.8b
+; CHECK-SD-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_constant_cond_v8i8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI86_0
+; CHECK-GI-NEXT:    ldr d2, [x8, :lo12:.LCPI86_0]
+; CHECK-GI-NEXT:    shl v2.8b, v2.8b, #7
+; CHECK-GI-NEXT:    sshr v2.8b, v2.8b, #7
+; CHECK-GI-NEXT:    bif v0.8b, v1.8b, v2.8b
+; CHECK-GI-NEXT:    ret
   %c = select <8 x i1> <i1 true, i1 false, i1 true, i1 false, i1 false, i1 false, i1 false, i1 false>, <8 x i8> %a, <8 x i8> %b
   ret <8 x i8> %c
 }
 
 define <4 x i16> @vselect_constant_cond_v4i16(<4 x i16> %a, <4 x i16> %b) {
-; CHECK-LABEL: vselect_constant_cond_v4i16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    movi d2, #0x00ffffffff0000
-; CHECK-NEXT:    movi d3, #0xffff00000000ffff
-; CHECK-NEXT:    and v1.8b, v1.8b, v2.8b
-; CHECK-NEXT:    and v0.8b, v0.8b, v3.8b
-; CHECK-NEXT:    orr v0.8b, v0.8b, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_constant_cond_v4i16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    movi d2, #0x00ffffffff0000
+; CHECK-SD-NEXT:    movi d3, #0xffff00000000ffff
+; CHECK-SD-NEXT:    and v1.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    and v0.8b, v0.8b, v3.8b
+; CHECK-SD-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_constant_cond_v4i16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI87_0
+; CHECK-GI-NEXT:    ldr d2, [x8, :lo12:.LCPI87_0]
+; CHECK-GI-NEXT:    shl v2.4h, v2.4h, #15
+; CHECK-GI-NEXT:    sshr v2.4h, v2.4h, #15
+; CHECK-GI-NEXT:    bif v0.8b, v1.8b, v2.8b
+; CHECK-GI-NEXT:    ret
   %c = select <4 x i1> <i1 true, i1 false, i1 false, i1 true>, <4 x i16> %a, <4 x i16> %b
   ret <4 x i16> %c
 }
 
 define <4 x i32> @vselect_constant_cond_v4i32(<4 x i32> %a, <4 x i32> %b) {
-; CHECK-LABEL: vselect_constant_cond_v4i32:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp x8, .LCPI88_0
-; CHECK-NEXT:    ldr q2, [x8, :lo12:.LCPI88_0]
-; CHECK-NEXT:    bif v0.16b, v1.16b, v2.16b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_constant_cond_v4i32:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    adrp x8, .LCPI88_0
+; CHECK-SD-NEXT:    ldr q2, [x8, :lo12:.LCPI88_0]
+; CHECK-SD-NEXT:    bif v0.16b, v1.16b, v2.16b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_constant_cond_v4i32:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI88_1
+; CHECK-GI-NEXT:    adrp x9, .LCPI88_0
+; CHECK-GI-NEXT:    ldr d2, [x8, :lo12:.LCPI88_1]
+; CHECK-GI-NEXT:    ldr d3, [x9, :lo12:.LCPI88_0]
+; CHECK-GI-NEXT:    mov v2.d[1], v3.d[0]
+; CHECK-GI-NEXT:    shl v2.4s, v2.4s, #31
+; CHECK-GI-NEXT:    sshr v2.4s, v2.4s, #31
+; CHECK-GI-NEXT:    bif v0.16b, v1.16b, v2.16b
+; CHECK-GI-NEXT:    ret
   %c = select <4 x i1> <i1 true, i1 false, i1 false, i1 true>, <4 x i32> %a, <4 x i32> %b
   ret <4 x i32> %c
 }
 
-; CHECK: .byte   0
-; CHECK: .byte   8
-; CHECK: .byte   2
-; CHECK: .byte   9
-; CHECK: .byte   4
-; CHECK: .byte   5
-; CHECK: .byte   6
-; CHECK: .byte   7
+; CHECK-SD: .byte   0
+; CHECK-SD: .byte   8
+; CHECK-SD: .byte   2
+; CHECK-SD: .byte   9
+; CHECK-SD: .byte   4
+; CHECK-SD: .byte   5
+; CHECK-SD: .byte   6
+; CHECK-SD: .byte   7
 define <8 x i8> @vselect_equivalent_shuffle_v8i8(<8 x i8> %a, <8 x i8> %b) {
-; CHECK-LABEL: vselect_equivalent_shuffle_v8i8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-NEXT:    // kill: def $d1 killed $d1 def $q1
-; CHECK-NEXT:    adrp x8, .LCPI89_0
-; CHECK-NEXT:    mov v0.d[1], v1.d[0]
-; CHECK-NEXT:    ldr d1, [x8, :lo12:.LCPI89_0]
-; CHECK-NEXT:    tbl v0.8b, { v0.16b }, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_equivalent_shuffle_v8i8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-SD-NEXT:    // kill: def $d1 killed $d1 def $q1
+; CHECK-SD-NEXT:    adrp x8, .LCPI89_0
+; CHECK-SD-NEXT:    mov v0.d[1], v1.d[0]
+; CHECK-SD-NEXT:    ldr d1, [x8, :lo12:.LCPI89_0]
+; CHECK-SD-NEXT:    tbl v0.8b, { v0.16b }, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_equivalent_shuffle_v8i8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-GI-NEXT:    // kill: def $d1 killed $d1 def $q1
+; CHECK-GI-NEXT:    adrp x8, .LCPI89_0
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI89_0]
+; CHECK-GI-NEXT:    tbl v0.16b, { v0.16b }, v1.16b
+; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-GI-NEXT:    ret
   %c = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 9, i32 4, i32 5, i32 6, i32 7>
   ret <8 x i8> %c
 }
 
 define <8 x i8> @vselect_equivalent_shuffle_v8i8_zero(<8 x i8> %a) {
-; CHECK-LABEL: vselect_equivalent_shuffle_v8i8_zero:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    movi d1, #0xffffffff00ff00ff
-; CHECK-NEXT:    and v0.8b, v0.8b, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_equivalent_shuffle_v8i8_zero:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    movi d1, #0xffffffff00ff00ff
+; CHECK-SD-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_equivalent_shuffle_v8i8_zero:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    movi v1.2d, #0000000000000000
+; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-GI-NEXT:    adrp x8, .LCPI90_0
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI90_0]
+; CHECK-GI-NEXT:    tbl v0.16b, { v0.16b }, v1.16b
+; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-GI-NEXT:    ret
   %c = shufflevector <8 x i8> %a, <8 x i8> zeroinitializer, <8 x i32> <i32 0, i32 8, i32 2, i32 9, i32 4, i32 5, i32 6, i32 7>
   ret <8 x i8> %c
 }
 
-; CHECK-LABEL: .LCPI91_0:
-; CHECK-NEXT: .byte   0
-; CHECK-NEXT: .byte   255
-; CHECK-NEXT: .byte   2
-; CHECK-NEXT: .byte   255
-; CHECK-NEXT: .byte   4
-; CHECK-NEXT: .byte   5
-; CHECK-NEXT: .byte   6
-; CHECK-NEXT: .byte   7
+; CHECK-SD-LABEL: .LCPI91_0:
+; CHECK-SD-NEXT: .byte   0
+; CHECK-SD-NEXT: .byte   255
+; CHECK-SD-NEXT: .byte   2
+; CHECK-SD-NEXT: .byte   255
+; CHECK-SD-NEXT: .byte   4
+; CHECK-SD-NEXT: .byte   5
+; CHECK-SD-NEXT: .byte   6
+; CHECK-SD-NEXT: .byte   7
 define <8 x i8> @vselect_equivalent_shuffle_v8i8_zeroswap(<8 x i8> %a) {
-; CHECK-LABEL: vselect_equivalent_shuffle_v8i8_zeroswap:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-NEXT:    adrp x8, .LCPI91_0
-; CHECK-NEXT:    mov v0.d[1], v0.d[0]
-; CHECK-NEXT:    ldr d1, [x8, :lo12:.LCPI91_0]
-; CHECK-NEXT:    tbl v0.8b, { v0.16b }, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_equivalent_shuffle_v8i8_zeroswap:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-SD-NEXT:    adrp x8, .LCPI91_0
+; CHECK-SD-NEXT:    mov v0.d[1], v0.d[0]
+; CHECK-SD-NEXT:    ldr d1, [x8, :lo12:.LCPI91_0]
+; CHECK-SD-NEXT:    tbl v0.8b, { v0.16b }, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_equivalent_shuffle_v8i8_zeroswap:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    movi v1.2d, #0000000000000000
+; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-GI-NEXT:    adrp x8, .LCPI91_0
+; CHECK-GI-NEXT:    mov v1.d[1], v0.d[0]
+; CHECK-GI-NEXT:    ldr d0, [x8, :lo12:.LCPI91_0]
+; CHECK-GI-NEXT:    tbl v0.16b, { v1.16b }, v0.16b
+; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-GI-NEXT:    ret
   %c = shufflevector <8 x i8> zeroinitializer, <8 x i8> %a, <8 x i32> <i32 8, i32 0, i32 10, i32 1, i32 12, i32 13, i32 14, i32 15>
   ret <8 x i8> %c
 }
 
-; CHECK-LABEL: .LCPI92_0:
-; CHECK-NEXT: .byte   0
-; CHECK-NEXT: .byte   1
-; CHECK-NEXT: .byte   16
-; CHECK-NEXT: .byte   17
-; CHECK-NEXT: .byte   4
-; CHECK-NEXT: .byte   5
-; CHECK-NEXT: .byte   18
-; CHECK-NEXT: .byte   19
-; CHECK-NEXT: .byte   8
-; CHECK-NEXT: .byte   9
-; CHECK-NEXT: .byte   10
-; CHECK-NEXT: .byte   11
-; CHECK-NEXT: .byte   12
-; CHECK-NEXT: .byte   13
-; CHECK-NEXT: .byte   14
-; CHECK-NEXT: .byte   15
+; CHECK-SD-LABEL: .LCPI92_0:
+; CHECK-SD-NEXT: .byte   0
+; CHECK-SD-NEXT: .byte   1
+; CHECK-SD-NEXT: .byte   16
+; CHECK-SD-NEXT: .byte   17
+; CHECK-SD-NEXT: .byte   4
+; CHECK-SD-NEXT: .byte   5
+; CHECK-SD-NEXT: .byte   18
+; CHECK-SD-NEXT: .byte   19
+; CHECK-SD-NEXT: .byte   8
+; CHECK-SD-NEXT: .byte   9
+; CHECK-SD-NEXT: .byte   10
+; CHECK-SD-NEXT: .byte   11
+; CHECK-SD-NEXT: .byte   12
+; CHECK-SD-NEXT: .byte   13
+; CHECK-SD-NEXT: .byte   14
+; CHECK-SD-NEXT: .byte   15
 define <8 x i16> @vselect_equivalent_shuffle_v8i16(<8 x i16> %a, <8 x i16> %b) {
-; CHECK-LABEL: vselect_equivalent_shuffle_v8i16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp x8, .LCPI92_0
-; CHECK-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
-; CHECK-NEXT:    ldr q2, [x8, :lo12:.LCPI92_0]
-; CHECK-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
-; CHECK-NEXT:    tbl v0.16b, { v0.16b, v1.16b }, v2.16b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_equivalent_shuffle_v8i16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    adrp x8, .LCPI92_0
+; CHECK-SD-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
+; CHECK-SD-NEXT:    ldr q2, [x8, :lo12:.LCPI92_0]
+; CHECK-SD-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
+; CHECK-SD-NEXT:    tbl v0.16b, { v0.16b, v1.16b }, v2.16b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_equivalent_shuffle_v8i16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI92_0
+; CHECK-GI-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
+; CHECK-GI-NEXT:    ldr q2, [x8, :lo12:.LCPI92_0]
+; CHECK-GI-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
+; CHECK-GI-NEXT:    tbl v0.16b, { v0.16b, v1.16b }, v2.16b
+; CHECK-GI-NEXT:    ret
   %c = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 9, i32 4, i32 5, i32 6, i32 7>
   ret <8 x i16> %c
 }
 
-; CHECK-LABEL: .LCPI93_0:
-; CHECK-NEXT: .hword 65535 // 0xffff
-; CHECK-NEXT: .hword 0 // 0x0
-; CHECK-NEXT: .hword 65535 // 0xffff
-; CHECK-NEXT: .hword 0 // 0x0
-; CHECK-NEXT: .hword 65535 // 0xffff
-; CHECK-NEXT: .hword 65535 // 0xffff
-; CHECK-NEXT: .hword 65535 // 0xffff
-; CHECK-NEXT: .hword 65535 // 0xffff
+; CHECK-SD-LABEL: .LCPI93_0:
+; CHECK-SD-NEXT: .hword 65535 // 0xffff
+; CHECK-SD-NEXT: .hword 0 // 0x0
+; CHECK-SD-NEXT: .hword 65535 // 0xffff
+; CHECK-SD-NEXT: .hword 0 // 0x0
+; CHECK-SD-NEXT: .hword 65535 // 0xffff
+; CHECK-SD-NEXT: .hword 65535 // 0xffff
+; CHECK-SD-NEXT: .hword 65535 // 0xffff
+; CHECK-SD-NEXT: .hword 65535 // 0xffff
 define <8 x i16> @vselect_equivalent_shuffle_v8i16_zero(<8 x i16> %a) {
-; CHECK-LABEL: vselect_equivalent_shuffle_v8i16_zero:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp x8, .LCPI93_0
-; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI93_0]
-; CHECK-NEXT:    and v0.16b, v0.16b, v1.16b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_equivalent_shuffle_v8i16_zero:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    adrp x8, .LCPI93_0
+; CHECK-SD-NEXT:    ldr q1, [x8, :lo12:.LCPI93_0]
+; CHECK-SD-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_equivalent_shuffle_v8i16_zero:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    // kill: def $q0 killed $q0 def $q0_q1
+; CHECK-GI-NEXT:    adrp x8, .LCPI93_0
+; CHECK-GI-NEXT:    movi v1.2d, #0000000000000000
+; CHECK-GI-NEXT:    ldr q2, [x8, :lo12:.LCPI93_0]
+; CHECK-GI-NEXT:    tbl v0.16b, { v0.16b, v1.16b }, v2.16b
+; CHECK-GI-NEXT:    ret
   %c = shufflevector <8 x i16> %a, <8 x i16> zeroinitializer, <8 x i32> <i32 0, i32 8, i32 2, i32 9, i32 4, i32 5, i32 6, i32 7>
   ret <8 x i16> %c
 }
 
-; CHECK: .byte   0
-; CHECK: .byte   1
-; CHECK: .byte   255
-; CHECK: .byte   255
-; CHECK: .byte   4
-; CHECK: .byte   5
-; CHECK: .byte   255
-; CHECK: .byte   255
-; CHECK: .byte   8
-; CHECK: .byte   9
-; CHECK: .byte   10
-; CHECK: .byte   11
-; CHECK: .byte   12
-; CHECK: .byte   13
-; CHECK: .byte   14
-; CHECK: .byte   15
+; CHECK-SD: .byte   0
+; CHECK-SD: .byte   1
+; CHECK-SD: .byte   255
+; CHECK-SD: .byte   255
+; CHECK-SD: .byte   4
+; CHECK-SD: .byte   5
+; CHECK-SD: .byte   255
+; CHECK-SD: .byte   255
+; CHECK-SD: .byte   8
+; CHECK-SD: .byte   9
+; CHECK-SD: .byte   10
+; CHECK-SD: .byte   11
+; CHECK-SD: .byte   12
+; CHECK-SD: .byte   13
+; CHECK-SD: .byte   14
+; CHECK-SD: .byte   15
 define <8 x i16> @vselect_equivalent_shuffle_v8i16_zeroswap(<8 x i16> %a) {
-; CHECK-LABEL: vselect_equivalent_shuffle_v8i16_zeroswap:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp x8, .LCPI94_0
-; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI94_0]
-; CHECK-NEXT:    tbl v0.16b, { v0.16b }, v1.16b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_equivalent_shuffle_v8i16_zeroswap:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    adrp x8, .LCPI94_0
+; CHECK-SD-NEXT:    ldr q1, [x8, :lo12:.LCPI94_0]
+; CHECK-SD-NEXT:    tbl v0.16b, { v0.16b }, v1.16b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_equivalent_shuffle_v8i16_zeroswap:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    // kill: def $q0 killed $q0 def $q31_q0
+; CHECK-GI-NEXT:    adrp x8, .LCPI94_0
+; CHECK-GI-NEXT:    movi v31.2d, #0000000000000000
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI94_0]
+; CHECK-GI-NEXT:    tbl v0.16b, { v31.16b, v0.16b }, v1.16b
+; CHECK-GI-NEXT:    ret
   %c = shufflevector <8 x i16> zeroinitializer, <8 x i16> %a, <8 x i32> <i32 8, i32 0, i32 10, i32 1, i32 12, i32 13, i32 14, i32 15>
   ret <8 x i16> %c
 }
 
 define <4 x i16> @vselect_equivalent_shuffle_v4i16(<4 x i16> %a, <4 x i16> %b) {
-; CHECK-LABEL: vselect_equivalent_shuffle_v4i16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-NEXT:    // kill: def $d1 killed $d1 def $q1
-; CHECK-NEXT:    mov v0.h[1], v1.h[0]
-; CHECK-NEXT:    mov v0.h[2], v1.h[1]
-; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_equivalent_shuffle_v4i16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-SD-NEXT:    // kill: def $d1 killed $d1 def $q1
+; CHECK-SD-NEXT:    mov v0.h[1], v1.h[0]
+; CHECK-SD-NEXT:    mov v0.h[2], v1.h[1]
+; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_equivalent_shuffle_v4i16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-GI-NEXT:    // kill: def $d1 killed $d1 def $q1
+; CHECK-GI-NEXT:    adrp x8, .LCPI95_0
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI95_0]
+; CHECK-GI-NEXT:    tbl v0.16b, { v0.16b }, v1.16b
+; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-GI-NEXT:    ret
   %c = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 5, i32 3>
   ret <4 x i16> %c
 }
 
 define <4 x i32> @vselect_equivalent_shuffle_v4i32(<4 x i32> %a, <4 x i32> %b) {
-; CHECK-LABEL: vselect_equivalent_shuffle_v4i32:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    mov v0.s[1], v1.s[0]
-; CHECK-NEXT:    mov v0.s[2], v1.s[1]
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_equivalent_shuffle_v4i32:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    mov v0.s[1], v1.s[0]
+; CHECK-SD-NEXT:    mov v0.s[2], v1.s[1]
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_equivalent_shuffle_v4i32:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI96_0
+; CHECK-GI-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
+; CHECK-GI-NEXT:    ldr q2, [x8, :lo12:.LCPI96_0]
+; CHECK-GI-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
+; CHECK-GI-NEXT:    tbl v0.16b, { v0.16b, v1.16b }, v2.16b
+; CHECK-GI-NEXT:    ret
   %c = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 4, i32 5, i32 3>
   ret <4 x i32> %c
 }
 
 define <8 x i8> @vselect_cmp_ne(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) {
-; CHECK-LABEL: vselect_cmp_ne:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmeq v0.8b, v0.8b, v1.8b
-; CHECK-NEXT:    bsl v0.8b, v2.8b, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_cmp_ne:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    cmeq v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT:    bsl v0.8b, v2.8b, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_cmp_ne:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    cmeq v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    mvn v0.8b, v0.8b
+; CHECK-GI-NEXT:    bsl v0.8b, v1.8b, v2.8b
+; CHECK-GI-NEXT:    ret
   %cmp = icmp ne <8 x i8> %a, %b
   %d = select <8 x i1> %cmp, <8 x i8> %b, <8 x i8> %c
   ret <8 x i8> %d
@@ -1062,34 +1544,57 @@ define <8 x i8> @vselect_cmp_eq(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) {
 }
 
 define <8 x i8> @vselect_cmpz_ne(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) {
-; CHECK-LABEL: vselect_cmpz_ne:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmeq v0.8b, v0.8b, #0
-; CHECK-NEXT:    bsl v0.8b, v2.8b, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_cmpz_ne:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    cmeq v0.8b, v0.8b, #0
+; CHECK-SD-NEXT:    bsl v0.8b, v2.8b, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_cmpz_ne:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    movi v3.2d, #0000000000000000
+; CHECK-GI-NEXT:    cmeq v0.8b, v0.8b, v3.8b
+; CHECK-GI-NEXT:    mvn v0.8b, v0.8b
+; CHECK-GI-NEXT:    bsl v0.8b, v1.8b, v2.8b
+; CHECK-GI-NEXT:    ret
   %cmp = icmp ne <8 x i8> %a, zeroinitializer
   %d = select <8 x i1> %cmp, <8 x i8> %b, <8 x i8> %c
   ret <8 x i8> %d
 }
 
 define <8 x i8> @vselect_cmpz_eq(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) {
-; CHECK-LABEL: vselect_cmpz_eq:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmeq v0.8b, v0.8b, #0
-; CHECK-NEXT:    bsl v0.8b, v1.8b, v2.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_cmpz_eq:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    cmeq v0.8b, v0.8b, #0
+; CHECK-SD-NEXT:    bsl v0.8b, v1.8b, v2.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_cmpz_eq:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    movi v3.2d, #0000000000000000
+; CHECK-GI-NEXT:    cmeq v0.8b, v0.8b, v3.8b
+; CHECK-GI-NEXT:    bsl v0.8b, v1.8b, v2.8b
+; CHECK-GI-NEXT:    ret
   %cmp = icmp eq <8 x i8> %a, zeroinitializer
   %d = select <8 x i1> %cmp, <8 x i8> %b, <8 x i8> %c
   ret <8 x i8> %d
 }
 
 define <8 x i8> @vselect_tst(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) {
-; CHECK-LABEL: vselect_tst:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    and v0.8b, v0.8b, v1.8b
-; CHECK-NEXT:    cmeq v0.8b, v0.8b, #0
-; CHECK-NEXT:    bsl v0.8b, v2.8b, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vselect_tst:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT:    cmeq v0.8b, v0.8b, #0
+; CHECK-SD-NEXT:    bsl v0.8b, v2.8b, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vselect_tst:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    movi v3.2d, #0000000000000000
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    cmeq v0.8b, v0.8b, v3.8b
+; CHECK-GI-NEXT:    bsl v0.8b, v2.8b, v1.8b
+; CHECK-GI-NEXT:    ret
   %tmp3 = and <8 x i8> %a, %b
   %tmp4 = icmp eq <8 x i8> %tmp3, zeroinitializer
   %d = select <8 x i1> %tmp4, <8 x i8> %c, <8 x i8> %b
@@ -1097,10 +1602,18 @@ define <8 x i8> @vselect_tst(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) {
 }
 
 define <8 x i8> @sext_tst(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) {
-; CHECK-LABEL: sext_tst:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmtst v0.8b, v0.8b, v1.8b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: sext_tst:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    cmtst v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: sext_tst:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    movi v2.2d, #0000000000000000
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    cmeq v0.8b, v0.8b, v2.8b
+; CHECK-GI-NEXT:    mvn v0.8b, v0.8b
+; CHECK-GI-NEXT:    ret
   %tmp3 = and <8 x i8> %a, %b
   %tmp4 = icmp ne <8 x i8> %tmp3, zeroinitializer
   %d = sext <8 x i1> %tmp4 to <8 x i8>
@@ -1120,372 +1633,660 @@ define <2 x i64> @bsl2xi64(<2 x i64> %v1, <2 x i64> %v2, <2 x i64> %v3) {
 }
 
 define <8 x i8> @orrimm8b_as_orrimm4h_lsl0(<8 x i8> %a) {
-; CHECK-LABEL: orrimm8b_as_orrimm4h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orrimm8b_as_orrimm4h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orrimm8b_as_orrimm4h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI104_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI104_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
   %val = or <8 x i8> %a, <i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0>
   ret <8 x i8> %val
 }
 
 define <8 x i8> @orrimm8b_as_orimm4h_lsl8(<8 x i8> %a) {
-; CHECK-LABEL: orrimm8b_as_orimm4h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orrimm8b_as_orimm4h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orrimm8b_as_orimm4h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI105_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI105_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
   %val = or <8 x i8> %a, <i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255>
   ret <8 x i8> %val
 }
 
 define <16 x i8> @orimm16b_as_orrimm8h_lsl0(<16 x i8> %a) {
-; CHECK-LABEL: orimm16b_as_orrimm8h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.8h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orimm16b_as_orrimm8h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.8h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orimm16b_as_orrimm8h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI106_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI106_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
   %val = or <16 x i8> %a, <i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0>
   ret <16 x i8> %val
 }
 
 define <16 x i8> @orimm16b_as_orrimm8h_lsl8(<16 x i8> %a) {
-; CHECK-LABEL: orimm16b_as_orrimm8h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.8h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orimm16b_as_orrimm8h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.8h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orimm16b_as_orrimm8h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI107_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI107_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
   %val = or <16 x i8> %a, <i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255>
   ret <16 x i8> %val
 }
 
 define <8 x i8> @and8imm2s_lsl0(<8 x i8> %a) {
-; CHECK-LABEL: and8imm2s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and8imm2s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and8imm2s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI108_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI108_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i8> %a, < i8 0, i8 255, i8 255, i8 255, i8 0, i8 255, i8 255, i8 255>
 	ret <8 x i8> %tmp1
 }
 
 define <8 x i8> @and8imm2s_lsl8(<8 x i8> %a) {
-; CHECK-LABEL: and8imm2s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and8imm2s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and8imm2s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI109_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI109_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i8> %a, < i8 255, i8 0, i8 255, i8 255, i8 255, i8 0, i8 255, i8 255>
 	ret <8 x i8> %tmp1
 }
 
 define <8 x i8> @and8imm2s_lsl16(<8 x i8> %a) {
-; CHECK-LABEL: and8imm2s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #255, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and8imm2s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #255, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and8imm2s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI110_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI110_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i8> %a, < i8 255, i8 255, i8 0, i8 255, i8 255, i8 255, i8 0, i8 255>
 	ret <8 x i8> %tmp1
 }
 
 define <8 x i8> @and8imm2s_lsl24(<8 x i8> %a) {
-; CHECK-LABEL: and8imm2s_lsl24:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #254, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and8imm2s_lsl24:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #254, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and8imm2s_lsl24:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI111_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI111_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i8> %a, < i8 255, i8 255, i8 255, i8 1, i8 255, i8 255, i8 255, i8 1>
 	ret <8 x i8> %tmp1
 }
 
 define <4 x i16> @and16imm2s_lsl0(<4 x i16> %a) {
-; CHECK-LABEL: and16imm2s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and16imm2s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and16imm2s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI112_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI112_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i16> %a, < i16 65280, i16 65535, i16 65280, i16 65535>
 	ret <4 x i16> %tmp1
 }
 
 define <4 x i16> @and16imm2s_lsl8(<4 x i16> %a) {
-; CHECK-LABEL: and16imm2s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and16imm2s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and16imm2s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI113_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI113_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i16> %a, < i16 255, i16 65535, i16 255, i16 65535>
 	ret <4 x i16> %tmp1
 }
 
 define <4 x i16> @and16imm2s_lsl16(<4 x i16> %a) {
-; CHECK-LABEL: and16imm2s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #255, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and16imm2s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #255, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and16imm2s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI114_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI114_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i16> %a, < i16 65535, i16 65280, i16 65535, i16 65280>
 	ret <4 x i16> %tmp1
 }
 
 define <4 x i16> @and16imm2s_lsl24(<4 x i16> %a) {
-; CHECK-LABEL: and16imm2s_lsl24:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #254, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and16imm2s_lsl24:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #254, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and16imm2s_lsl24:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI115_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI115_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i16> %a, < i16 65535, i16 511, i16 65535, i16 511>
 	ret <4 x i16> %tmp1
 }
 
 
 define <1 x i64> @and64imm2s_lsl0(<1 x i64> %a) {
-; CHECK-LABEL: and64imm2s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and64imm2s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and64imm2s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    and x8, x8, #0xffffff00ffffff00
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <1 x i64> %a, < i64 -1095216660736>
 	ret <1 x i64> %tmp1
 }
 
 define <1 x i64> @and64imm2s_lsl8(<1 x i64> %a) {
-; CHECK-LABEL: and64imm2s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and64imm2s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and64imm2s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    and x8, x8, #0xffff00ffffff00ff
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <1 x i64> %a, < i64 -280375465148161>
 	ret <1 x i64> %tmp1
 }
 
 define <1 x i64> @and64imm2s_lsl16(<1 x i64> %a) {
-; CHECK-LABEL: and64imm2s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #255, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and64imm2s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #255, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and64imm2s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    and x8, x8, #0xff00ffffff00ffff
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <1 x i64> %a, < i64 -71776119077928961>
 	ret <1 x i64> %tmp1
 }
 
 define <1 x i64> @and64imm2s_lsl24(<1 x i64> %a) {
-; CHECK-LABEL: and64imm2s_lsl24:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.2s, #254, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and64imm2s_lsl24:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.2s, #254, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and64imm2s_lsl24:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    and x8, x8, #0x1ffffff01ffffff
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <1 x i64> %a, < i64 144115183814443007>
 	ret <1 x i64> %tmp1
 }
 
 define <16 x i8> @and8imm4s_lsl0(<16 x i8> %a) {
-; CHECK-LABEL: and8imm4s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and8imm4s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and8imm4s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI120_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI120_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <16 x i8> %a, < i8 0, i8 255, i8 255, i8 255, i8 0, i8 255, i8 255, i8 255, i8 0, i8 255, i8 255, i8 255, i8 0, i8 255, i8 255, i8 255>
 	ret <16 x i8> %tmp1
 }
 
 define <16 x i8> @and8imm4s_lsl8(<16 x i8> %a) {
-; CHECK-LABEL: and8imm4s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and8imm4s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and8imm4s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI121_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI121_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <16 x i8> %a, < i8 255, i8 0, i8 255, i8 255, i8 255, i8 0, i8 255, i8 255, i8 255, i8 0, i8 255, i8 255, i8 255, i8 0, i8 255, i8 255>
 	ret <16 x i8> %tmp1
 }
 
 define <16 x i8> @and8imm4s_lsl16(<16 x i8> %a) {
-; CHECK-LABEL: and8imm4s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #255, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and8imm4s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #255, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and8imm4s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI122_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI122_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <16 x i8> %a, < i8 255, i8 255, i8 0, i8 255, i8 255, i8 255, i8 0, i8 255, i8 255, i8 255, i8 0, i8 255, i8 255, i8 255, i8 0, i8 255>
 	ret <16 x i8> %tmp1
 }
 
 define <16 x i8> @and8imm4s_lsl24(<16 x i8> %a) {
-; CHECK-LABEL: and8imm4s_lsl24:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #254, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and8imm4s_lsl24:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #254, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and8imm4s_lsl24:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI123_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI123_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <16 x i8> %a, < i8 255, i8 255, i8 255, i8 1, i8 255, i8 255, i8 255, i8 1, i8 255, i8 255, i8 255, i8 1, i8 255, i8 255, i8 255, i8 1>
 	ret <16 x i8> %tmp1
 }
 
 define <8 x i16> @and16imm4s_lsl0(<8 x i16> %a) {
-; CHECK-LABEL: and16imm4s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and16imm4s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and16imm4s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI124_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI124_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i16> %a, < i16 65280, i16 65535, i16 65280, i16 65535, i16 65280, i16 65535, i16 65280, i16 65535>
 	ret <8 x i16> %tmp1
 }
 
 define <8 x i16> @and16imm4s_lsl8(<8 x i16> %a) {
-; CHECK-LABEL: and16imm4s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and16imm4s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and16imm4s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI125_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI125_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i16> %a, < i16 255, i16 65535, i16 255, i16 65535, i16 255, i16 65535, i16 255, i16 65535>
 	ret <8 x i16> %tmp1
 }
 
 define <8 x i16> @and16imm4s_lsl16(<8 x i16> %a) {
-; CHECK-LABEL: and16imm4s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #255, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and16imm4s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #255, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and16imm4s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI126_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI126_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i16> %a, < i16 65535, i16 65280, i16 65535, i16 65280, i16 65535, i16 65280, i16 65535, i16 65280>
 	ret <8 x i16> %tmp1
 }
 
 define <8 x i16> @and16imm4s_lsl24(<8 x i16> %a) {
-; CHECK-LABEL: and16imm4s_lsl24:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #254, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and16imm4s_lsl24:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #254, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and16imm4s_lsl24:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI127_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI127_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i16> %a, < i16 65535, i16 511, i16 65535, i16 511, i16 65535, i16 511, i16 65535, i16 511>
 	ret <8 x i16> %tmp1
 }
 
 define <2 x i64> @and64imm4s_lsl0(<2 x i64> %a) {
-; CHECK-LABEL: and64imm4s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and64imm4s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and64imm4s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI128_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI128_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <2 x i64> %a, < i64 -1095216660736, i64 -1095216660736>
 	ret <2 x i64> %tmp1
 }
 
 define <2 x i64> @and64imm4s_lsl8(<2 x i64> %a) {
-; CHECK-LABEL: and64imm4s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and64imm4s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and64imm4s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI129_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI129_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <2 x i64> %a, < i64 -280375465148161, i64 -280375465148161>
 	ret <2 x i64> %tmp1
 }
 
 define <2 x i64> @and64imm4s_lsl16(<2 x i64> %a) {
-; CHECK-LABEL: and64imm4s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #255, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and64imm4s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #255, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and64imm4s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI130_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI130_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <2 x i64> %a, < i64 -71776119077928961, i64 -71776119077928961>
 	ret <2 x i64> %tmp1
 }
 
 define <2 x i64> @and64imm4s_lsl24(<2 x i64> %a) {
-; CHECK-LABEL: and64imm4s_lsl24:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4s, #254, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and64imm4s_lsl24:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4s, #254, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and64imm4s_lsl24:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI131_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI131_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <2 x i64> %a, < i64 144115183814443007, i64 144115183814443007>
 	ret <2 x i64> %tmp1
 }
 
 define <8 x i8> @and8imm4h_lsl0(<8 x i8> %a) {
-; CHECK-LABEL: and8imm4h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and8imm4h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and8imm4h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI132_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI132_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i8> %a, < i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255>
 	ret <8 x i8> %tmp1
 }
 
 define <8 x i8> @and8imm4h_lsl8(<8 x i8> %a) {
-; CHECK-LABEL: and8imm4h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and8imm4h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and8imm4h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI133_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI133_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <8 x i8> %a, < i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0>
 	ret <8 x i8> %tmp1
 }
 
 define <2 x i32> @and16imm4h_lsl0(<2 x i32> %a) {
-; CHECK-LABEL: and16imm4h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and16imm4h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and16imm4h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI134_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI134_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <2 x i32> %a, < i32 4278255360, i32 4278255360>
 	ret <2 x i32> %tmp1
 }
 
 define <2 x i32> @and16imm4h_lsl8(<2 x i32> %a) {
-; CHECK-LABEL: and16imm4h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and16imm4h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and16imm4h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI135_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI135_0]
+; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <2 x i32> %a, < i32 16711935, i32 16711935>
 	ret <2 x i32> %tmp1
 }
 
 define <1 x i64> @and64imm4h_lsl0(<1 x i64> %a) {
-; CHECK-LABEL: and64imm4h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and64imm4h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and64imm4h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    and x8, x8, #0xff00ff00ff00ff00
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <1 x i64> %a, < i64 -71777214294589696>
 	ret <1 x i64> %tmp1
 }
 
 define <1 x i64> @and64imm4h_lsl8(<1 x i64> %a) {
-; CHECK-LABEL: and64imm4h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.4h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and64imm4h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.4h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and64imm4h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    and x8, x8, #0xff00ff00ff00ff
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <1 x i64> %a, < i64 71777214294589695>
 	ret <1 x i64> %tmp1
 }
 
 define <16 x i8> @and8imm8h_lsl0(<16 x i8> %a) {
-; CHECK-LABEL: and8imm8h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.8h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and8imm8h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.8h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and8imm8h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI138_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI138_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <16 x i8> %a, < i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255 >
 	ret <16 x i8> %tmp1
 }
 
 define <16 x i8> @and8imm8h_lsl8(<16 x i8> %a) {
-; CHECK-LABEL: and8imm8h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.8h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and8imm8h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.8h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and8imm8h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI139_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI139_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <16 x i8> %a, <i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0 >
 	ret <16 x i8> %tmp1
 }
 
 define <4 x i32> @and16imm8h_lsl0(<4 x i32> %a) {
-; CHECK-LABEL: and16imm8h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.8h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and16imm8h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.8h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and16imm8h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI140_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI140_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i32> %a, < i32 4278255360, i32 4278255360, i32 4278255360, i32 4278255360>
 	ret <4 x i32> %tmp1
 }
 
 define <4 x i32> @and16imm8h_lsl8(<4 x i32> %a) {
-; CHECK-LABEL: and16imm8h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.8h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and16imm8h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.8h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and16imm8h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI141_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI141_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <4 x i32> %a, < i32 16711935, i32 16711935, i32 16711935, i32 16711935>
 	ret <4 x i32> %tmp1
 }
 
 define <2 x i64> @and64imm8h_lsl0(<2 x i64> %a) {
-; CHECK-LABEL: and64imm8h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.8h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and64imm8h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.8h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and64imm8h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI142_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI142_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <2 x i64> %a, < i64 -71777214294589696, i64 -71777214294589696>
 	ret <2 x i64> %tmp1
 }
 
 define <2 x i64> @and64imm8h_lsl8(<2 x i64> %a) {
-; CHECK-LABEL: and64imm8h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.8h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: and64imm8h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.8h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: and64imm8h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI143_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI143_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = and <2 x i64> %a, < i64 71777214294589695, i64 71777214294589695>
 	ret <2 x i64> %tmp1
 }
 
 define <8 x i16> @bic_shifted_knownbits(<8 x i16> %v) {
-; CHECK-LABEL: bic_shifted_knownbits:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    ushr v0.8h, v0.8h, #9
-; CHECK-NEXT:    bic v0.8h, #126
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bic_shifted_knownbits:
+; CHECK-SD:       // %bb.0: // %entry
+; CHECK-SD-NEXT:    ushr v0.8h, v0.8h, #9
+; CHECK-SD-NEXT:    bic v0.8h, #126
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bic_shifted_knownbits:
+; CHECK-GI:       // %bb.0: // %entry
+; CHECK-GI-NEXT:    adrp x8, .LCPI144_0
+; CHECK-GI-NEXT:    ushr v0.8h, v0.8h, #9
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI144_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 entry:
   %vshr_n = lshr <8 x i16> %v, <i16 9, i16 9, i16 9, i16 9, i16 9, i16 9, i16 9, i16 9>
   %and.i = and <8 x i16> %vshr_n, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
@@ -1493,14 +2294,24 @@ entry:
 }
 
 define <8 x i32> @bic_shifted_knownbits2(<8 x i16> %v) {
-; CHECK-LABEL: bic_shifted_knownbits2:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    ushll v2.4s, v0.4h, #0
-; CHECK-NEXT:    ushll2 v1.4s, v0.8h, #0
-; CHECK-NEXT:    bic v2.4s, #255, lsl #8
-; CHECK-NEXT:    bic v1.4s, #255, lsl #8
-; CHECK-NEXT:    mov v0.16b, v2.16b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bic_shifted_knownbits2:
+; CHECK-SD:       // %bb.0: // %entry
+; CHECK-SD-NEXT:    ushll v2.4s, v0.4h, #0
+; CHECK-SD-NEXT:    ushll2 v1.4s, v0.8h, #0
+; CHECK-SD-NEXT:    bic v2.4s, #255, lsl #8
+; CHECK-SD-NEXT:    bic v1.4s, #255, lsl #8
+; CHECK-SD-NEXT:    mov v0.16b, v2.16b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bic_shifted_knownbits2:
+; CHECK-GI:       // %bb.0: // %entry
+; CHECK-GI-NEXT:    adrp x8, .LCPI145_0
+; CHECK-GI-NEXT:    ushll v1.4s, v0.4h, #0
+; CHECK-GI-NEXT:    ushll2 v2.4s, v0.8h, #0
+; CHECK-GI-NEXT:    ldr q3, [x8, :lo12:.LCPI145_0]
+; CHECK-GI-NEXT:    and v0.16b, v1.16b, v3.16b
+; CHECK-GI-NEXT:    and v1.16b, v2.16b, v3.16b
+; CHECK-GI-NEXT:    ret
 entry:
   %vshr_n = zext <8 x i16> %v to <8 x i32>
   %and.i = and <8 x i32> %vshr_n, <i32 4293918975, i32 4293918975, i32 4293918975, i32 4293918975, i32 4293918975, i32 4293918975, i32 4293918975, i32 4293918975>
@@ -1508,12 +2319,21 @@ entry:
 }
 
 define <8 x i32> @bic_shifted_knownbits3(<8 x i16> %v) {
-; CHECK-LABEL: bic_shifted_knownbits3:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    bic v0.8h, #255, lsl #8
-; CHECK-NEXT:    ushll2 v1.4s, v0.8h, #0
-; CHECK-NEXT:    ushll v0.4s, v0.4h, #0
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bic_shifted_knownbits3:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    bic v0.8h, #255, lsl #8
+; CHECK-SD-NEXT:    ushll2 v1.4s, v0.8h, #0
+; CHECK-SD-NEXT:    ushll v0.4s, v0.4h, #0
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bic_shifted_knownbits3:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI146_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI146_0]
+; CHECK-GI-NEXT:    and v1.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ushll v0.4s, v1.4h, #0
+; CHECK-GI-NEXT:    ushll2 v1.4s, v1.8h, #0
+; CHECK-GI-NEXT:    ret
   %a = and <8 x i16> %v, <i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>
   %and.i = zext <8 x i16> %a to <8 x i32>
   ret <8 x i32> %and.i
@@ -1521,13 +2341,23 @@ define <8 x i32> @bic_shifted_knownbits3(<8 x i16> %v) {
 
 
 define <8 x i32> @bic_shifted_knownbits4(<8 x i32> %v) {
-; CHECK-LABEL: bic_shifted_knownbits4:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    shl v1.4s, v1.4s, #8
-; CHECK-NEXT:    shl v0.4s, v0.4s, #8
-; CHECK-NEXT:    bic v0.4s, #255, lsl #8
-; CHECK-NEXT:    bic v1.4s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: bic_shifted_knownbits4:
+; CHECK-SD:       // %bb.0: // %entry
+; CHECK-SD-NEXT:    shl v1.4s, v1.4s, #8
+; CHECK-SD-NEXT:    shl v0.4s, v0.4s, #8
+; CHECK-SD-NEXT:    bic v0.4s, #255, lsl #8
+; CHECK-SD-NEXT:    bic v1.4s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: bic_shifted_knownbits4:
+; CHECK-GI:       // %bb.0: // %entry
+; CHECK-GI-NEXT:    adrp x8, .LCPI147_0
+; CHECK-GI-NEXT:    shl v0.4s, v0.4s, #8
+; CHECK-GI-NEXT:    shl v1.4s, v1.4s, #8
+; CHECK-GI-NEXT:    ldr q2, [x8, :lo12:.LCPI147_0]
+; CHECK-GI-NEXT:    and v0.16b, v0.16b, v2.16b
+; CHECK-GI-NEXT:    and v1.16b, v1.16b, v2.16b
+; CHECK-GI-NEXT:    ret
 entry:
   %vshr_n = shl <8 x i32> %v, <i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8>
   %and.i = and <8 x i32> %vshr_n, <i32 4294901760, i32 4294901760, i32 4294901760, i32 4294901760, i32 4294901760, i32 4294901760, i32 4294901760, i32 4294901760>
@@ -1535,325 +2365,577 @@ entry:
 }
 
 define <8 x i8> @orr8imm2s_lsl0(<8 x i8> %a) {
-; CHECK-LABEL: orr8imm2s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr8imm2s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr8imm2s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI148_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI148_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <8 x i8> %a, < i8 255, i8 0, i8 0, i8 0, i8 255, i8 0, i8 0, i8 0>
 	ret <8 x i8> %tmp1
 }
 
 define <8 x i8> @orr8imm2s_lsl8(<8 x i8> %a) {
-; CHECK-LABEL: orr8imm2s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr8imm2s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr8imm2s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI149_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI149_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <8 x i8> %a, < i8 0, i8 255, i8 0, i8 0, i8 0, i8 255, i8 0, i8 0>
 	ret <8 x i8> %tmp1
 }
 
 define <8 x i8> @orr8imm2s_lsl16(<8 x i8> %a) {
-; CHECK-LABEL: orr8imm2s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr8imm2s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr8imm2s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI150_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI150_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <8 x i8> %a, < i8 0, i8 0, i8 255, i8 0, i8 0, i8 0, i8 255, i8 0>
 	ret <8 x i8> %tmp1
 }
 
 define <8 x i8> @orr8imm2s_lsl24(<8 x i8> %a) {
-; CHECK-LABEL: orr8imm2s_lsl24:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr8imm2s_lsl24:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr8imm2s_lsl24:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI151_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI151_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <8 x i8> %a, < i8 0, i8 0, i8 0, i8 255, i8 0, i8 0, i8 0, i8 255>
 	ret <8 x i8> %tmp1
 }
 
 define <4 x i16> @orr16imm2s_lsl0(<4 x i16> %a) {
-; CHECK-LABEL: orr16imm2s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr16imm2s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr16imm2s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI152_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI152_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <4 x i16> %a, < i16 255, i16 0, i16 255, i16 0>
 	ret <4 x i16> %tmp1
 }
 
 define <4 x i16> @orr16imm2s_lsl8(<4 x i16> %a) {
-; CHECK-LABEL: orr16imm2s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr16imm2s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr16imm2s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI153_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI153_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <4 x i16> %a, < i16 65280, i16 0, i16 65280, i16 0>
 	ret <4 x i16> %tmp1
 }
 
 define <4 x i16> @orr16imm2s_lsl16(<4 x i16> %a) {
-; CHECK-LABEL: orr16imm2s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr16imm2s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr16imm2s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI154_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI154_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <4 x i16> %a, < i16 0, i16 255, i16 0, i16 255>
 	ret <4 x i16> %tmp1
 }
 
 define <4 x i16> @orr16imm2s_lsl24(<4 x i16> %a) {
-; CHECK-LABEL: orr16imm2s_lsl24:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr16imm2s_lsl24:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr16imm2s_lsl24:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI155_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI155_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <4 x i16> %a, < i16 0, i16 65280, i16 0, i16 65280>
 	ret <4 x i16> %tmp1
 }
 
 define <1 x i64> @orr64imm2s_lsl0(<1 x i64> %a) {
-; CHECK-LABEL: orr64imm2s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr64imm2s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr64imm2s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    orr x8, x8, #0xff000000ff
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <1 x i64> %a, < i64 1095216660735>
 	ret <1 x i64> %tmp1
 }
 
 define <1 x i64> @orr64imm2s_lsl8(<1 x i64> %a) {
-; CHECK-LABEL: orr64imm2s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr64imm2s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr64imm2s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    orr x8, x8, #0xff000000ff00
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <1 x i64> %a, < i64 280375465148160>
 	ret <1 x i64> %tmp1
 }
 
 define <1 x i64> @orr64imm2s_lsl16(<1 x i64> %a) {
-; CHECK-LABEL: orr64imm2s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr64imm2s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr64imm2s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    orr x8, x8, #0xff000000ff0000
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <1 x i64> %a, < i64 71776119077928960>
 	ret <1 x i64> %tmp1
 }
 
 define <1 x i64> @orr64imm2s_lsl24(<1 x i64> %a) {
-; CHECK-LABEL: orr64imm2s_lsl24:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.2s, #255, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr64imm2s_lsl24:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.2s, #255, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr64imm2s_lsl24:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    orr x8, x8, #0xff000000ff000000
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <1 x i64> %a, < i64 -72057589759737856>
 	ret <1 x i64> %tmp1
 }
 
 define <16 x i8> @orr8imm4s_lsl0(<16 x i8> %a) {
-; CHECK-LABEL: orr8imm4s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr8imm4s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr8imm4s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI160_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI160_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <16 x i8> %a, < i8 255, i8 0, i8 0, i8 0, i8 255, i8 0, i8 0, i8 0, i8 255, i8 0, i8 0, i8 0, i8 255, i8 0, i8 0, i8 0>
 	ret <16 x i8> %tmp1
 }
 
 define <16 x i8> @orr8imm4s_lsl8(<16 x i8> %a) {
-; CHECK-LABEL: orr8imm4s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr8imm4s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr8imm4s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI161_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI161_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <16 x i8> %a, < i8 0, i8 255, i8 0, i8 0, i8 0, i8 255, i8 0, i8 0, i8 0, i8 255, i8 0, i8 0, i8 0, i8 255, i8 0, i8 0>
 	ret <16 x i8> %tmp1
 }
 
 define <16 x i8> @orr8imm4s_lsl16(<16 x i8> %a) {
-; CHECK-LABEL: orr8imm4s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr8imm4s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr8imm4s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI162_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI162_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <16 x i8> %a, < i8 0, i8 0, i8 255, i8 0, i8 0, i8 0, i8 255, i8 0, i8 0, i8 0, i8 255, i8 0, i8 0, i8 0, i8 255, i8 0>
 	ret <16 x i8> %tmp1
 }
 
 define <16 x i8> @orr8imm4s_lsl24(<16 x i8> %a) {
-; CHECK-LABEL: orr8imm4s_lsl24:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr8imm4s_lsl24:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr8imm4s_lsl24:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI163_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI163_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <16 x i8> %a, < i8 0, i8 0, i8 0, i8 255, i8 0, i8 0, i8 0, i8 255, i8 0, i8 0, i8 0, i8 255, i8 0, i8 0, i8 0, i8 255>
 	ret <16 x i8> %tmp1
 }
 
 define <8 x i16> @orr16imm4s_lsl0(<8 x i16> %a) {
-; CHECK-LABEL: orr16imm4s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr16imm4s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr16imm4s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI164_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI164_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <8 x i16> %a, < i16 255, i16 0, i16 255, i16 0, i16 255, i16 0, i16 255, i16 0>
 	ret <8 x i16> %tmp1
 }
 
 define <8 x i16> @orr16imm4s_lsl8(<8 x i16> %a) {
-; CHECK-LABEL: orr16imm4s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr16imm4s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr16imm4s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI165_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI165_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <8 x i16> %a, < i16 65280, i16 0, i16 65280, i16 0, i16 65280, i16 0, i16 65280, i16 0>
 	ret <8 x i16> %tmp1
 }
 
 define <8 x i16> @orr16imm4s_lsl16(<8 x i16> %a) {
-; CHECK-LABEL: orr16imm4s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr16imm4s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr16imm4s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI166_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI166_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <8 x i16> %a, < i16 0, i16 255, i16 0, i16 255, i16 0, i16 255, i16 0, i16 255>
 	ret <8 x i16> %tmp1
 }
 
 define <8 x i16> @orr16imm4s_lsl24(<8 x i16> %a) {
-; CHECK-LABEL: orr16imm4s_lsl24:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr16imm4s_lsl24:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr16imm4s_lsl24:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI167_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI167_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <8 x i16> %a, < i16 0, i16 65280, i16 0, i16 65280, i16 0, i16 65280, i16 0, i16 65280>
 	ret <8 x i16> %tmp1
 }
 
 define <2 x i64> @orr64imm4s_lsl0(<2 x i64> %a) {
-; CHECK-LABEL: orr64imm4s_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr64imm4s_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr64imm4s_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI168_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI168_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <2 x i64> %a, < i64 1095216660735, i64 1095216660735>
 	ret <2 x i64> %tmp1
 }
 
 define <2 x i64> @orr64imm4s_lsl8(<2 x i64> %a) {
-; CHECK-LABEL: orr64imm4s_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr64imm4s_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr64imm4s_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI169_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI169_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <2 x i64> %a, < i64 280375465148160, i64 280375465148160>
 	ret <2 x i64> %tmp1
 }
 
 define <2 x i64> @orr64imm4s_lsl16(<2 x i64> %a) {
-; CHECK-LABEL: orr64imm4s_lsl16:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255, lsl #16
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr64imm4s_lsl16:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255, lsl #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr64imm4s_lsl16:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI170_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI170_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <2 x i64> %a, < i64 71776119077928960, i64 71776119077928960>
 	ret <2 x i64> %tmp1
 }
 
 define <2 x i64> @orr64imm4s_lsl24(<2 x i64> %a) {
-; CHECK-LABEL: orr64imm4s_lsl24:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4s, #255, lsl #24
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr64imm4s_lsl24:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4s, #255, lsl #24
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr64imm4s_lsl24:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI171_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI171_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <2 x i64> %a, < i64 -72057589759737856, i64 -72057589759737856>
 	ret <2 x i64> %tmp1
 }
 
 define <8 x i8> @orr8imm4h_lsl0(<8 x i8> %a) {
-; CHECK-LABEL: orr8imm4h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr8imm4h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr8imm4h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI172_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI172_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <8 x i8> %a, < i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0>
 	ret <8 x i8> %tmp1
 }
 
 define <8 x i8> @orr8imm4h_lsl8(<8 x i8> %a) {
-; CHECK-LABEL: orr8imm4h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr8imm4h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr8imm4h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI173_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI173_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <8 x i8> %a, < i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255>
 	ret <8 x i8> %tmp1
 }
 
 define <2 x i32> @orr16imm4h_lsl0(<2 x i32> %a) {
-; CHECK-LABEL: orr16imm4h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr16imm4h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr16imm4h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI174_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI174_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <2 x i32> %a, < i32 16711935, i32 16711935>
 	ret <2 x i32> %tmp1
 }
 
 define <2 x i32> @orr16imm4h_lsl8(<2 x i32> %a) {
-; CHECK-LABEL: orr16imm4h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr16imm4h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr16imm4h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI175_0
+; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI175_0]
+; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <2 x i32> %a, < i32 4278255360, i32 4278255360>
 	ret <2 x i32> %tmp1
 }
 
 define <1 x i64> @orr64imm4h_lsl0(<1 x i64> %a) {
-; CHECK-LABEL: orr64imm4h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr64imm4h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr64imm4h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    orr x8, x8, #0xff00ff00ff00ff
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <1 x i64> %a, < i64 71777214294589695>
 	ret <1 x i64> %tmp1
 }
 
 define <1 x i64> @orr64imm4h_lsl8(<1 x i64> %a) {
-; CHECK-LABEL: orr64imm4h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.4h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr64imm4h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.4h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr64imm4h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    orr x8, x8, #0xff00ff00ff00ff00
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <1 x i64> %a, < i64 -71777214294589696>
 	ret <1 x i64> %tmp1
 }
 
 define <16 x i8> @orr8imm8h_lsl0(<16 x i8> %a) {
-; CHECK-LABEL: orr8imm8h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.8h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr8imm8h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.8h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr8imm8h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI178_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI178_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <16 x i8> %a, < i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0>
 	ret <16 x i8> %tmp1
 }
 
 define <16 x i8> @orr8imm8h_lsl8(<16 x i8> %a) {
-; CHECK-LABEL: orr8imm8h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.8h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr8imm8h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.8h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr8imm8h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI179_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI179_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <16 x i8> %a, < i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255, i8 0, i8 255>
 	ret <16 x i8> %tmp1
 }
 
 define <4 x i32> @orr16imm8h_lsl0(<4 x i32> %a) {
-; CHECK-LABEL: orr16imm8h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.8h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr16imm8h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.8h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr16imm8h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI180_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI180_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <4 x i32> %a, < i32 16711935, i32 16711935, i32 16711935, i32 16711935>
 	ret <4 x i32> %tmp1
 }
 
 define <4 x i32> @orr16imm8h_lsl8(<4 x i32> %a) {
-; CHECK-LABEL: orr16imm8h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.8h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr16imm8h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.8h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr16imm8h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI181_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI181_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <4 x i32> %a, < i32 4278255360, i32 4278255360, i32 4278255360, i32 4278255360>
 	ret <4 x i32> %tmp1
 }
 
 define <2 x i64> @orr64imm8h_lsl0(<2 x i64> %a) {
-; CHECK-LABEL: orr64imm8h_lsl0:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.8h, #255
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr64imm8h_lsl0:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.8h, #255
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr64imm8h_lsl0:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI182_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI182_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <2 x i64> %a, < i64 71777214294589695, i64 71777214294589695>
 	ret <2 x i64> %tmp1
 }
 
 define <2 x i64> @orr64imm8h_lsl8(<2 x i64> %a) {
-; CHECK-LABEL: orr64imm8h_lsl8:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr v0.8h, #255, lsl #8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: orr64imm8h_lsl8:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    orr v0.8h, #255, lsl #8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: orr64imm8h_lsl8:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI183_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI183_0]
+; CHECK-GI-NEXT:    orr v0.16b, v0.16b, v1.16b
+; CHECK-GI-NEXT:    ret
 	%tmp1 = or <2 x i64> %a, < i64 -71777214294589696, i64 -71777214294589696>
 	ret <2 x i64> %tmp1
 }

>From 054e2e39a871eedc1ce0a677c2f5f4d845107ad4 Mon Sep 17 00:00:00 2001
From: Piotr Zegar <me at piotrzegar.pl>
Date: Sun, 10 Sep 2023 12:22:24 +0000
Subject: [PATCH 38/62] [clang-tidy] Add IgnoreTypes option to
 modernize-use-nullptr

New option added and configured in a way, so types
related to std::strong_ordering would be ignored.

Fixes: #63478

Reviewed By: ccotter

Differential Revision: https://reviews.llvm.org/D158928
---
 .../clang-tidy/modernize/UseNullptrCheck.cpp  | 19 ++++++++---
 .../clang-tidy/modernize/UseNullptrCheck.h    |  1 +
 .../clang-tidy/utils/Matchers.cpp             | 28 ++++++++++++++++
 clang-tools-extra/clang-tidy/utils/Matchers.h | 22 +++++++++++++
 clang-tools-extra/docs/ReleaseNotes.rst       |  6 +++-
 .../checks/modernize/use-nullptr.rst          |  6 ++++
 .../checkers/modernize/use-nullptr-cxx20.cpp  | 33 ++++++++++++++++---
 7 files changed, 104 insertions(+), 11 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
index efffc0c80fed8d1..6a003a347badacf 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -7,6 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "UseNullptrCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -33,11 +35,13 @@ AST_MATCHER(Type, sugaredNullptrType) {
 /// to null within.
 /// Finding sequences of explicit casts is necessary so that an entire sequence
 /// can be replaced instead of just the inner-most implicit cast.
-StatementMatcher makeCastSequenceMatcher() {
-  StatementMatcher ImplicitCastToNull = implicitCastExpr(
+StatementMatcher makeCastSequenceMatcher(llvm::ArrayRef<StringRef> NameList) {
+  auto ImplicitCastToNull = implicitCastExpr(
       anyOf(hasCastKind(CK_NullToPointer), hasCastKind(CK_NullToMemberPointer)),
       unless(hasImplicitDestinationType(qualType(substTemplateTypeParmType()))),
-      unless(hasSourceExpression(hasType(sugaredNullptrType()))));
+      unless(hasSourceExpression(hasType(sugaredNullptrType()))),
+      unless(hasImplicitDestinationType(
+          qualType(matchers::matchesAnyListedTypeName(NameList)))));
 
   auto IsOrHasDescendant = [](auto InnerMatcher) {
     return anyOf(InnerMatcher, hasDescendant(InnerMatcher));
@@ -477,16 +481,21 @@ class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> {
 
 UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
-      NullMacrosStr(Options.get("NullMacros", "NULL")) {
+      NullMacrosStr(Options.get("NullMacros", "NULL")),
+      IgnoredTypes(utils::options::parseStringList(Options.get(
+          "IgnoredTypes",
+          "std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec"))) {
   StringRef(NullMacrosStr).split(NullMacros, ",");
 }
 
 void UseNullptrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "NullMacros", NullMacrosStr);
+  Options.store(Opts, "IgnoredTypes",
+                utils::options::serializeStringList(IgnoredTypes));
 }
 
 void UseNullptrCheck::registerMatchers(MatchFinder *Finder) {
-  Finder->addMatcher(makeCastSequenceMatcher(), this);
+  Finder->addMatcher(makeCastSequenceMatcher(IgnoredTypes), this);
 }
 
 void UseNullptrCheck::check(const MatchFinder::MatchResult &Result) {
diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h
index a8d2a8c0667bbdf..6c32a4edb4ff96e 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h
@@ -28,6 +28,7 @@ class UseNullptrCheck : public ClangTidyCheck {
 private:
   const StringRef NullMacrosStr;
   SmallVector<StringRef, 1> NullMacros;
+  std::vector<StringRef> IgnoredTypes;
 };
 
 } // namespace clang::tidy::modernize
diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.cpp b/clang-tools-extra/clang-tidy/utils/Matchers.cpp
index 440038e36d76437..7e89cae1c3316e4 100644
--- a/clang-tools-extra/clang-tidy/utils/Matchers.cpp
+++ b/clang-tools-extra/clang-tidy/utils/Matchers.cpp
@@ -17,4 +17,32 @@ bool NotIdenticalStatementsPredicate::operator()(
                                         Nodes.getNodeAs<Stmt>(ID), *Context);
 }
 
+MatchesAnyListedTypeNameMatcher::MatchesAnyListedTypeNameMatcher(
+    llvm::ArrayRef<StringRef> NameList)
+    : NameMatchers(NameList.begin(), NameList.end()) {}
+
+MatchesAnyListedTypeNameMatcher::~MatchesAnyListedTypeNameMatcher() = default;
+
+bool MatchesAnyListedTypeNameMatcher::matches(
+    const QualType &Node, ast_matchers::internal::ASTMatchFinder *Finder,
+    ast_matchers::internal::BoundNodesTreeBuilder *Builder) const {
+
+  if (NameMatchers.empty())
+    return false;
+
+  PrintingPolicy PrintingPolicyWithSuppressedTag(
+      Finder->getASTContext().getLangOpts());
+  PrintingPolicyWithSuppressedTag.PrintCanonicalTypes = true;
+  PrintingPolicyWithSuppressedTag.SuppressElaboration = true;
+  PrintingPolicyWithSuppressedTag.SuppressScope = false;
+  PrintingPolicyWithSuppressedTag.SuppressTagKeyword = true;
+  PrintingPolicyWithSuppressedTag.SuppressUnwrittenScope = true;
+  std::string TypeName =
+      Node.getUnqualifiedType().getAsString(PrintingPolicyWithSuppressedTag);
+
+  return llvm::any_of(NameMatchers, [&TypeName](const llvm::Regex &NM) {
+    return NM.isValid() && NM.match(TypeName);
+  });
+}
+
 } // namespace clang::tidy::matchers
diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.h b/clang-tools-extra/clang-tidy/utils/Matchers.h
index cbb187899a4b79a..386ea738fbba508 100644
--- a/clang-tools-extra/clang-tidy/utils/Matchers.h
+++ b/clang-tools-extra/clang-tidy/utils/Matchers.h
@@ -158,6 +158,28 @@ AST_MATCHER_P(Stmt, isStatementIdenticalToBoundNode, std::string, ID) {
   return Builder->removeBindings(Predicate);
 }
 
+// A matcher implementation that matches a list of type name regular expressions
+// against a QualType.
+class MatchesAnyListedTypeNameMatcher
+    : public ast_matchers::internal::MatcherInterface<QualType> {
+public:
+  explicit MatchesAnyListedTypeNameMatcher(llvm::ArrayRef<StringRef> NameList);
+  ~MatchesAnyListedTypeNameMatcher() override;
+  bool matches(
+      const QualType &Node, ast_matchers::internal::ASTMatchFinder *Finder,
+      ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override;
+
+private:
+  std::vector<llvm::Regex> NameMatchers;
+};
+
+// Returns a matcher that matches QualType against a list of provided regular.
+inline ::clang::ast_matchers::internal::Matcher<QualType>
+matchesAnyListedTypeName(llvm::ArrayRef<StringRef> NameList) {
+  return ::clang::ast_matchers::internal::makeMatcher(
+      new MatchesAnyListedTypeNameMatcher(NameList));
+}
+
 } // namespace clang::tidy::matchers
 
 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 998e763d792af6b..c1a36ac0f92a96a 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -227,7 +227,7 @@ Changes in existing checks
   `DeduplicateFindings` to output one finding per symbol occurrence.
 
 - Improved :doc:`misc-include-cleaner
-  <clang-tidy/checks/misc/include-cleaner>` check to avoid fixes insert 
+  <clang-tidy/checks/misc/include-cleaner>` check to avoid fixes insert
   same include header multiple times.
 
 - Improved :doc:`misc-redundant-expression
@@ -242,6 +242,10 @@ Changes in existing checks
   <clang-tidy/checks/modernize/use-equals-delete>` check to ignore
   false-positives when special member function is actually used or implicit.
 
+- Improved :doc:`modernize-use-nullptr
+  <clang-tidy/checks/modernize/use-nullptr>` check by adding option
+  `IgnoredTypes` that can be used to exclude some pointer types.
+
 - Improved :doc:`modernize-use-std-print
   <clang-tidy/checks/modernize/use-std-print>` check to accurately generate
   fixes for reordering arguments.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst
index ffb1cb78dffe060..5e1ba858adf3a9c 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst
@@ -39,6 +39,12 @@ transforms to:
 Options
 -------
 
+.. option:: IgnoredTypes
+
+  Semicolon-separated list of regular expressions to match pointer types for
+  which implicit casts will be ignored. Default value:
+  `std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec`.
+
 .. option:: NullMacros
 
    Comma-separated list of macro names that will be transformed along with
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
index be59d4ed1d05698..5bc5b79b5524e2c 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
@@ -1,35 +1,51 @@
-// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t -- -- -DGCC
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t -- -- -DCLANG
 
 namespace std {
 class strong_ordering;
 
 // Mock how STD defined unspecified parameters for the operators below.
+#ifdef CLANG
 struct _CmpUnspecifiedParam {
   consteval
   _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
 };
 
+#define UNSPECIFIED_TYPE _CmpUnspecifiedParam
+#endif
+
+#ifdef GCC
+namespace __cmp_cat {
+  struct __unspec {
+    constexpr __unspec(__unspec*) noexcept { }
+  };
+}
+
+#define UNSPECIFIED_TYPE __cmp_cat::__unspec
+#endif
+
 struct strong_ordering {
   signed char value;
 
   friend constexpr bool operator==(strong_ordering v,
-                                   _CmpUnspecifiedParam) noexcept {
+                                   UNSPECIFIED_TYPE) noexcept {
     return v.value == 0;
   }
   friend constexpr bool operator<(strong_ordering v,
-                                  _CmpUnspecifiedParam) noexcept {
+                                  UNSPECIFIED_TYPE) noexcept {
     return v.value < 0;
   }
   friend constexpr bool operator>(strong_ordering v,
-                                  _CmpUnspecifiedParam) noexcept {
+                                  UNSPECIFIED_TYPE) noexcept {
     return v.value > 0;
   }
   friend constexpr bool operator>=(strong_ordering v,
-                                   _CmpUnspecifiedParam) noexcept {
+                                   UNSPECIFIED_TYPE) noexcept {
     return v.value >= 0;
   }
   static const strong_ordering equal, greater, less;
 };
+
 constexpr strong_ordering strong_ordering::equal = {0};
 constexpr strong_ordering strong_ordering::greater = {1};
 constexpr strong_ordering strong_ordering::less = {-1};
@@ -59,6 +75,13 @@ void test_cxx_rewritten_binary_ops() {
   // CHECK-FIXES: result = (a1 > ((a1 > (ptr == nullptr ? a1 : a2)) ? a1 : a2));
 }
 
+void testValidZero() {
+  A a1, a2;
+  auto result = a1 <=> a2;
+  if (result < 0) {}
+  // CHECK-FIXES: if (result < 0) {}
+}
+
 template<class T1, class T2>
 struct P {
   T1 x1;

>From c149b592785e112412009d933b1c4224490e0c70 Mon Sep 17 00:00:00 2001
From: Ignat Loskutov <ignat.loskutov at gmail.com>
Date: Sun, 10 Sep 2023 12:52:24 +0000
Subject: [PATCH 39/62] [clang-tidy] Fix DanglingHandleCheck to work in C++17
 and later mode

Due to guaranteed copy elision, not only do some nodes get removed from the AST,
but also some existing nodes change the source locations they correspond to.
Hence, the check works slightly differently in pre-C++17 and C++17-and-later modes
in terms of what gets highlighted.

Reviewed By: PiotrZSL

Differential Revision: https://reviews.llvm.org/D158371
---
 .../bugprone/DanglingHandleCheck.cpp          | 74 ++++++++-----------
 .../checkers/bugprone/dangling-handle.cpp     | 23 ++++--
 2 files changed, 48 insertions(+), 49 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp
index 82c07bdc2ba95c6..9ded699ba78e66b 100644
--- a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp
@@ -36,9 +36,9 @@ ast_matchers::internal::Matcher<Stmt> handleFromTemporaryValue(
   // If a ternary operator returns a temporary value, then both branches hold a
   // temporary value. If one of them is not a temporary then it must be copied
   // into one to satisfy the type of the operator.
-  const auto TemporaryTernary =
-      conditionalOperator(hasTrueExpression(cxxBindTemporaryExpr()),
-                          hasFalseExpression(cxxBindTemporaryExpr()));
+  const auto TemporaryTernary = conditionalOperator(
+      hasTrueExpression(ignoringParenImpCasts(cxxBindTemporaryExpr())),
+      hasFalseExpression(ignoringParenImpCasts(cxxBindTemporaryExpr())));
 
   return handleFrom(IsAHandle, anyOf(cxxBindTemporaryExpr(), TemporaryTernary));
 }
@@ -103,26 +103,17 @@ void DanglingHandleCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
 void DanglingHandleCheck::registerMatchersForVariables(MatchFinder *Finder) {
   const auto ConvertedHandle = handleFromTemporaryValue(IsAHandle);
 
-  // Find 'Handle foo(ReturnsAValue());'
+  // Find 'Handle foo(ReturnsAValue());', 'Handle foo = ReturnsAValue();'
   Finder->addMatcher(
       varDecl(hasType(hasUnqualifiedDesugaredType(
                   recordType(hasDeclaration(cxxRecordDecl(IsAHandle))))),
+              unless(parmVarDecl()),
               hasInitializer(
-                  exprWithCleanups(has(ignoringParenImpCasts(ConvertedHandle)))
+                  exprWithCleanups(ignoringElidableConstructorCall(has(
+                                       ignoringParenImpCasts(ConvertedHandle))))
                       .bind("bad_stmt"))),
       this);
 
-  // Find 'Handle foo = ReturnsAValue();'
-  Finder->addMatcher(
-      traverse(TK_AsIs,
-               varDecl(hasType(hasUnqualifiedDesugaredType(recordType(
-                           hasDeclaration(cxxRecordDecl(IsAHandle))))),
-                       unless(parmVarDecl()),
-                       hasInitializer(exprWithCleanups(
-                                          has(ignoringParenImpCasts(handleFrom(
-                                              IsAHandle, ConvertedHandle))))
-                                          .bind("bad_stmt")))),
-      this);
   // Find 'foo = ReturnsAValue();  // foo is Handle'
   Finder->addMatcher(
       traverse(TK_AsIs,
@@ -141,36 +132,35 @@ void DanglingHandleCheck::registerMatchersForVariables(MatchFinder *Finder) {
 void DanglingHandleCheck::registerMatchersForReturn(MatchFinder *Finder) {
   // Return a local.
   Finder->addMatcher(
-      traverse(
-          TK_AsIs,
-          returnStmt(
-              // The AST contains two constructor calls:
-              //   1. Value to Handle conversion.
-              //   2. Handle copy construction.
-              // We have to match both.
-              has(ignoringImplicit(handleFrom(
-                  IsAHandle,
-                  handleFrom(IsAHandle,
-                             declRefExpr(to(varDecl(
-                                 // Is function scope ...
-                                 hasAutomaticStorageDuration(),
-                                 // ... and it is a local array or Value.
-                                 anyOf(hasType(arrayType()),
-                                       hasType(hasUnqualifiedDesugaredType(
-                                           recordType(hasDeclaration(recordDecl(
-                                               unless(IsAHandle)))))))))))))),
-              // Temporary fix for false positives inside lambdas.
-              unless(hasAncestor(lambdaExpr())))
-              .bind("bad_stmt")),
+      traverse(TK_AsIs,
+               returnStmt(
+                   // The AST contains two constructor calls:
+                   //   1. Value to Handle conversion.
+                   //   2. Handle copy construction (elided in C++17+).
+                   // We have to match both.
+                   has(ignoringImplicit(ignoringElidableConstructorCall(
+                       ignoringImplicit(handleFrom(
+                           IsAHandle,
+                           declRefExpr(to(varDecl(
+                               // Is function scope ...
+                               hasAutomaticStorageDuration(),
+                               // ... and it is a local array or Value.
+                               anyOf(hasType(arrayType()),
+                                     hasType(hasUnqualifiedDesugaredType(
+                                         recordType(hasDeclaration(recordDecl(
+                                             unless(IsAHandle))))))))))))))),
+                   // Temporary fix for false positives inside lambdas.
+                   unless(hasAncestor(lambdaExpr())))
+                   .bind("bad_stmt")),
       this);
 
   // Return a temporary.
   Finder->addMatcher(
-      traverse(
-          TK_AsIs,
-          returnStmt(has(exprWithCleanups(has(ignoringParenImpCasts(handleFrom(
-                         IsAHandle, handleFromTemporaryValue(IsAHandle)))))))
-              .bind("bad_stmt")),
+      traverse(TK_AsIs,
+               returnStmt(has(exprWithCleanups(ignoringElidableConstructorCall(
+                              has(ignoringParenImpCasts(
+                                  handleFromTemporaryValue(IsAHandle)))))))
+                   .bind("bad_stmt")),
       this);
 }
 
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/dangling-handle.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/dangling-handle.cpp
index e99cc8b99d6a420..23cda5321764383 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/dangling-handle.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/dangling-handle.cpp
@@ -1,8 +1,12 @@
-// RUN: %check_clang_tidy -std=c++11,c++14 %s bugprone-dangling-handle %t -- \
+// RUN: %check_clang_tidy -std=c++11,c++14 -check-suffix=,CXX14 %s bugprone-dangling-handle %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             {bugprone-dangling-handle.HandleClasses: \
+// RUN:               'std::basic_string_view; ::llvm::StringRef;'}}"
+
+// RUN: %check_clang_tidy -std=c++17-or-later -check-suffix=,CXX17 %s bugprone-dangling-handle %t -- \
 // RUN:   -config="{CheckOptions: \
 // RUN:             {bugprone-dangling-handle.HandleClasses: \
 // RUN:               'std::basic_string_view; ::llvm::StringRef;'}}"
-// FIXME: Fix the checker to work in C++17 or later mode.
 
 namespace std {
 
@@ -84,27 +88,32 @@ std::string ReturnsAString();
 
 void Positives() {
   std::string_view view1 = std::string();
-  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
+  // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
+  // CHECK-MESSAGES-CXX17: [[@LINE-2]]:28: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
 
   std::string_view view_2 = ReturnsAString();
-  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+  // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
+  // CHECK-MESSAGES-CXX17: [[@LINE-2]]:29: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
 
   view1 = std::string();
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
 
   const std::string& str_ref = "";
   std::string_view view3 = true ? "A" : str_ref;
-  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+  // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+  // CHECK-MESSAGES-CXX17: [[@LINE-2]]:28: warning: std::basic_string_view outlives
   view3 = true ? "A" : str_ref;
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
 
   std::string_view view4(ReturnsAString());
-  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+  // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+  // CHECK-MESSAGES-CXX17: [[@LINE-2]]:26: warning: std::basic_string_view outlives
 }
 
 void OtherTypes() {
   llvm::StringRef ref = std::string();
-  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: llvm::StringRef outlives its value
+  // CHECK-MESSAGES-CXX14: [[@LINE-1]]:19: warning: llvm::StringRef outlives its value
+  // CHECK-MESSAGES-CXX17: [[@LINE-2]]:25: warning: llvm::StringRef outlives its value
 }
 
 const char static_array[] = "A";

>From d00a8d4b36021241bdcbc0b9446a4a07248ee36e Mon Sep 17 00:00:00 2001
From: Alex Brachet <abrachet at google.com>
Date: Sun, 10 Sep 2023 10:04:04 -0400
Subject: [PATCH 40/62] [Fuchsia] Disable libcxx timezone database (#65870)

tzdb is currently broken when cross compiling from non Linux to Linux.
Lets just disable it totally in our toolchain for now. We should remove
this when #65859 lands.
---
 clang/cmake/caches/Fuchsia-stage2.cmake | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake b/clang/cmake/caches/Fuchsia-stage2.cmake
index 4890040b1b6a2b4..10e5cacf51c4b7b 100644
--- a/clang/cmake/caches/Fuchsia-stage2.cmake
+++ b/clang/cmake/caches/Fuchsia-stage2.cmake
@@ -181,6 +181,9 @@ foreach(target aarch64-unknown-linux-gnu;armv7-unknown-linux-gnueabihf;i386-unkn
     set(RUNTIMES_${target}_LLVM_TOOLS_DIR "${CMAKE_BINARY_DIR}/bin" CACHE BOOL "")
     set(RUNTIMES_${target}_LLVM_ENABLE_RUNTIMES "compiler-rt;libcxx;libcxxabi;libunwind" CACHE STRING "")
 
+    # TODO: Remove this once #65859 lands.
+    set(RUNTIMES_${target}_LIBCXX_ENABLE_TIME_ZONE_DATABASE OFF CACHE STRING "")
+
     # Use .build-id link.
     list(APPEND RUNTIME_BUILD_ID_LINK "${target}")
   endif()

>From 42387f7d93531098271af1da0ffc0728d1110bdb Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Sun, 10 Sep 2023 23:13:18 +0800
Subject: [PATCH 41/62] [Demangle] demangle builtin type transformations

Fixed: https://github.com/llvm/llvm-project/issues/62127
https://reviews.llvm.org/D116203 introduced several compiler builtin
equivalents of the unary type traits. In some cases (e.g. template) those
builtin will be dependent and need to be mangle.
This patch add the check for `u{builtin}I{type}E` to demangle it.

Reviewed By: rjmccall

Differential Revision: https://reviews.llvm.org/D148465
---
 libcxxabi/src/demangle/ItaniumDemangle.h     | 27 +++++++++++++++++++-
 libcxxabi/src/demangle/ItaniumNodes.def      |  1 +
 libcxxabi/test/test_demangle.pass.cpp        |  3 +++
 llvm/include/llvm/Demangle/ItaniumDemangle.h | 27 +++++++++++++++++++-
 llvm/include/llvm/Demangle/ItaniumNodes.def  |  1 +
 5 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index c80f343cc876e99..1b4d30c84bb9c56 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -534,6 +534,23 @@ class ElaboratedTypeSpefType : public Node {
   }
 };
 
+class TransformedType : public Node {
+  StringView Transform;
+  Node *BaseType;
+public:
+  TransformedType(StringView Transform_, Node *BaseType_)
+      : Node(KTransformedType), Transform(Transform_), BaseType(BaseType_) {}
+
+  template<typename Fn> void match(Fn F) const { F(Transform, BaseType); }
+
+  void printLeft(OutputBuffer &OB) const override {
+    OB += Transform;
+    OB += '(';
+    BaseType->print(OB);
+    OB += ')';
+  }
+};
+
 struct AbiTagAttr : Node {
   Node *Base;
   std::string_view Tag;
@@ -3894,7 +3911,15 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
     // Typically, <builtin-type>s are not considered substitution candidates,
     // but the exception to that exception is vendor extended types (Itanium C++
     // ABI 5.9.1).
-    Result = make<NameType>(Res);
+    if (consumeIf('I')) {
+      Node *BaseType = parseType();
+      if (BaseType == nullptr)
+        return nullptr;
+      if (!consumeIf('E'))
+        return nullptr;
+      Result = make<TransformedType>(Res, BaseType);
+    } else
+      Result = make<NameType>(Res);
     break;
   }
   case 'D':
diff --git a/libcxxabi/src/demangle/ItaniumNodes.def b/libcxxabi/src/demangle/ItaniumNodes.def
index f615cb9fadb05e8..a54ee370a935b7a 100644
--- a/libcxxabi/src/demangle/ItaniumNodes.def
+++ b/libcxxabi/src/demangle/ItaniumNodes.def
@@ -19,6 +19,7 @@ NODE(QualType)
 NODE(ConversionOperatorType)
 NODE(PostfixQualifiedType)
 NODE(ElaboratedTypeSpefType)
+NODE(TransformedType)
 NODE(NameType)
 NODE(AbiTagAttr)
 NODE(EnableIfAttr)
diff --git a/libcxxabi/test/test_demangle.pass.cpp b/libcxxabi/test/test_demangle.pass.cpp
index 471808db5d5b8fc..891bc8b43d1bd47 100644
--- a/libcxxabi/test/test_demangle.pass.cpp
+++ b/libcxxabi/test/test_demangle.pass.cpp
@@ -30114,6 +30114,9 @@ const char* cases[][2] =
      " std::allocator<char>>::basic_string()"},
     {"_ZN1SB8ctor_tagC2Ev", "S[abi:ctor_tag]::S()"},
     {"_ZN1SB8ctor_tagD2Ev", "S[abi:ctor_tag]::~S()"},
+
+    // clang builtin type transform
+    {"_Z2f5IiEvu7__decayIT_E", "void f5<int>(__decay(int))"},
 };
 
 const unsigned N = sizeof(cases) / sizeof(cases[0]);
diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h
index 26acd38f8ae8476..e8d799e65df0d52 100644
--- a/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -528,6 +528,23 @@ class ElaboratedTypeSpefType : public Node {
   }
 };
 
+class TransformedType : public Node {
+  StringView Transform;
+  Node *BaseType;
+public:
+  TransformedType(StringView Transform_, Node *BaseType_)
+      : Node(KTransformedType), Transform(Transform_), BaseType(BaseType_) {}
+
+  template<typename Fn> void match(Fn F) const { F(Transform, BaseType); }
+
+  void printLeft(OutputBuffer &OB) const override {
+    OB += Transform;
+    OB += '(';
+    BaseType->print(OB);
+    OB += ')';
+  }
+};
+
 struct AbiTagAttr : Node {
   Node *Base;
   std::string_view Tag;
@@ -3889,7 +3906,15 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
     // Typically, <builtin-type>s are not considered substitution candidates,
     // but the exception to that exception is vendor extended types (Itanium C++
     // ABI 5.9.1).
-    Result = make<NameType>(Res);
+    if (consumeIf('I')) {
+      Node *BaseType = parseType();
+      if (BaseType == nullptr)
+        return nullptr;
+      if (!consumeIf('E'))
+        return nullptr;
+      Result = make<TransformedType>(Res, BaseType);
+    } else
+      Result = make<NameType>(Res);
     break;
   }
   case 'D':
diff --git a/llvm/include/llvm/Demangle/ItaniumNodes.def b/llvm/include/llvm/Demangle/ItaniumNodes.def
index c0e277d554ccfad..dafce502ce9e900 100644
--- a/llvm/include/llvm/Demangle/ItaniumNodes.def
+++ b/llvm/include/llvm/Demangle/ItaniumNodes.def
@@ -19,6 +19,7 @@ NODE(QualType)
 NODE(ConversionOperatorType)
 NODE(PostfixQualifiedType)
 NODE(ElaboratedTypeSpefType)
+NODE(TransformedType)
 NODE(NameType)
 NODE(AbiTagAttr)
 NODE(EnableIfAttr)

>From 4b894c4c92c977de7258d92cba86d281a687c3ab Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Sun, 10 Sep 2023 23:18:43 +0800
Subject: [PATCH 42/62] Revert "[Demangle] demangle builtin type
 transformations"

This reverts commit 31cc069b5f4cb1b120c72f4dcbaa1b5a212120df.
---
 libcxxabi/src/demangle/ItaniumDemangle.h     | 27 +-------------------
 libcxxabi/src/demangle/ItaniumNodes.def      |  1 -
 libcxxabi/test/test_demangle.pass.cpp        |  3 ---
 llvm/include/llvm/Demangle/ItaniumDemangle.h | 27 +-------------------
 llvm/include/llvm/Demangle/ItaniumNodes.def  |  1 -
 5 files changed, 2 insertions(+), 57 deletions(-)

diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index 1b4d30c84bb9c56..c80f343cc876e99 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -534,23 +534,6 @@ class ElaboratedTypeSpefType : public Node {
   }
 };
 
-class TransformedType : public Node {
-  StringView Transform;
-  Node *BaseType;
-public:
-  TransformedType(StringView Transform_, Node *BaseType_)
-      : Node(KTransformedType), Transform(Transform_), BaseType(BaseType_) {}
-
-  template<typename Fn> void match(Fn F) const { F(Transform, BaseType); }
-
-  void printLeft(OutputBuffer &OB) const override {
-    OB += Transform;
-    OB += '(';
-    BaseType->print(OB);
-    OB += ')';
-  }
-};
-
 struct AbiTagAttr : Node {
   Node *Base;
   std::string_view Tag;
@@ -3911,15 +3894,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
     // Typically, <builtin-type>s are not considered substitution candidates,
     // but the exception to that exception is vendor extended types (Itanium C++
     // ABI 5.9.1).
-    if (consumeIf('I')) {
-      Node *BaseType = parseType();
-      if (BaseType == nullptr)
-        return nullptr;
-      if (!consumeIf('E'))
-        return nullptr;
-      Result = make<TransformedType>(Res, BaseType);
-    } else
-      Result = make<NameType>(Res);
+    Result = make<NameType>(Res);
     break;
   }
   case 'D':
diff --git a/libcxxabi/src/demangle/ItaniumNodes.def b/libcxxabi/src/demangle/ItaniumNodes.def
index a54ee370a935b7a..f615cb9fadb05e8 100644
--- a/libcxxabi/src/demangle/ItaniumNodes.def
+++ b/libcxxabi/src/demangle/ItaniumNodes.def
@@ -19,7 +19,6 @@ NODE(QualType)
 NODE(ConversionOperatorType)
 NODE(PostfixQualifiedType)
 NODE(ElaboratedTypeSpefType)
-NODE(TransformedType)
 NODE(NameType)
 NODE(AbiTagAttr)
 NODE(EnableIfAttr)
diff --git a/libcxxabi/test/test_demangle.pass.cpp b/libcxxabi/test/test_demangle.pass.cpp
index 891bc8b43d1bd47..471808db5d5b8fc 100644
--- a/libcxxabi/test/test_demangle.pass.cpp
+++ b/libcxxabi/test/test_demangle.pass.cpp
@@ -30114,9 +30114,6 @@ const char* cases[][2] =
      " std::allocator<char>>::basic_string()"},
     {"_ZN1SB8ctor_tagC2Ev", "S[abi:ctor_tag]::S()"},
     {"_ZN1SB8ctor_tagD2Ev", "S[abi:ctor_tag]::~S()"},
-
-    // clang builtin type transform
-    {"_Z2f5IiEvu7__decayIT_E", "void f5<int>(__decay(int))"},
 };
 
 const unsigned N = sizeof(cases) / sizeof(cases[0]);
diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h
index e8d799e65df0d52..26acd38f8ae8476 100644
--- a/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -528,23 +528,6 @@ class ElaboratedTypeSpefType : public Node {
   }
 };
 
-class TransformedType : public Node {
-  StringView Transform;
-  Node *BaseType;
-public:
-  TransformedType(StringView Transform_, Node *BaseType_)
-      : Node(KTransformedType), Transform(Transform_), BaseType(BaseType_) {}
-
-  template<typename Fn> void match(Fn F) const { F(Transform, BaseType); }
-
-  void printLeft(OutputBuffer &OB) const override {
-    OB += Transform;
-    OB += '(';
-    BaseType->print(OB);
-    OB += ')';
-  }
-};
-
 struct AbiTagAttr : Node {
   Node *Base;
   std::string_view Tag;
@@ -3906,15 +3889,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
     // Typically, <builtin-type>s are not considered substitution candidates,
     // but the exception to that exception is vendor extended types (Itanium C++
     // ABI 5.9.1).
-    if (consumeIf('I')) {
-      Node *BaseType = parseType();
-      if (BaseType == nullptr)
-        return nullptr;
-      if (!consumeIf('E'))
-        return nullptr;
-      Result = make<TransformedType>(Res, BaseType);
-    } else
-      Result = make<NameType>(Res);
+    Result = make<NameType>(Res);
     break;
   }
   case 'D':
diff --git a/llvm/include/llvm/Demangle/ItaniumNodes.def b/llvm/include/llvm/Demangle/ItaniumNodes.def
index dafce502ce9e900..c0e277d554ccfad 100644
--- a/llvm/include/llvm/Demangle/ItaniumNodes.def
+++ b/llvm/include/llvm/Demangle/ItaniumNodes.def
@@ -19,7 +19,6 @@ NODE(QualType)
 NODE(ConversionOperatorType)
 NODE(PostfixQualifiedType)
 NODE(ElaboratedTypeSpefType)
-NODE(TransformedType)
 NODE(NameType)
 NODE(AbiTagAttr)
 NODE(EnableIfAttr)

>From 4c4a50e639d18d30e216c5449db2a205d8b68fcf Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 13:25:36 -0700
Subject: [PATCH 43/62] [clang] NFCI: Use `FileEntryRef` in `FileRemapper`
 (1/2)

---
 clang/include/clang/ARCMigrate/FileRemapper.h | 12 ++--
 clang/lib/ARCMigrate/FileRemapper.cpp         | 62 +++++++++----------
 2 files changed, 37 insertions(+), 37 deletions(-)

diff --git a/clang/include/clang/ARCMigrate/FileRemapper.h b/clang/include/clang/ARCMigrate/FileRemapper.h
index 4da68a678be2027..776ac4700b73bac 100644
--- a/clang/include/clang/ARCMigrate/FileRemapper.h
+++ b/clang/include/clang/ARCMigrate/FileRemapper.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_ARCMIGRATE_FILEREMAPPER_H
 #define LLVM_CLANG_ARCMIGRATE_FILEREMAPPER_H
 
+#include "clang/Basic/FileEntry.h"
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/PointerUnion.h"
@@ -23,7 +24,6 @@ namespace llvm {
 
 namespace clang {
   class FileManager;
-  class FileEntry;
   class DiagnosticsEngine;
   class PreprocessorOptions;
 
@@ -34,10 +34,10 @@ class FileRemapper {
   std::unique_ptr<FileManager> FileMgr;
 
   typedef llvm::PointerUnion<const FileEntry *, llvm::MemoryBuffer *> Target;
-  typedef llvm::DenseMap<const FileEntry *, Target> MappingsTy;
+  using MappingsTy = llvm::DenseMap<FileEntryRef, Target>;
   MappingsTy FromToMappings;
 
-  llvm::DenseMap<const FileEntry *, const FileEntry *> ToFromMappings;
+  llvm::DenseMap<const FileEntry *, FileEntryRef> ToFromMappings;
 
 public:
   FileRemapper();
@@ -66,10 +66,10 @@ class FileRemapper {
   void clear(StringRef outputDir = StringRef());
 
 private:
-  void remap(const FileEntry *file, std::unique_ptr<llvm::MemoryBuffer> memBuf);
-  void remap(const FileEntry *file, const FileEntry *newfile);
+  void remap(FileEntryRef file, std::unique_ptr<llvm::MemoryBuffer> memBuf);
+  void remap(FileEntryRef file, const FileEntry *newfile);
 
-  const FileEntry *getOriginalFile(StringRef filePath);
+  OptionalFileEntryRef getOriginalFile(StringRef filePath);
   void resetTarget(Target &targ);
 
   bool report(const Twine &err, DiagnosticsEngine &Diag);
diff --git a/clang/lib/ARCMigrate/FileRemapper.cpp b/clang/lib/ARCMigrate/FileRemapper.cpp
index 7e56e0683c12931..413caf1e9653d4c 100644
--- a/clang/lib/ARCMigrate/FileRemapper.cpp
+++ b/clang/lib/ARCMigrate/FileRemapper.cpp
@@ -60,7 +60,7 @@ bool FileRemapper::initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
   if (!llvm::sys::fs::exists(infoFile))
     return false;
 
-  std::vector<std::pair<const FileEntry *, const FileEntry *> > pairs;
+  std::vector<std::pair<FileEntryRef, const FileEntry *> > pairs;
 
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBuf =
       llvm::MemoryBuffer::getFile(infoFile, /*IsText=*/true);
@@ -78,7 +78,7 @@ bool FileRemapper::initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
                     Diag);
     StringRef toFilename = lines[idx+2];
 
-    llvm::ErrorOr<const FileEntry *> origFE = FileMgr->getFile(fromFilename);
+    auto origFE = FileMgr->getOptionalFileRef(fromFilename);
     if (!origFE) {
       if (ignoreIfFilesChanged)
         continue;
@@ -91,7 +91,7 @@ bool FileRemapper::initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
       return report("File does not exist: " + toFilename, Diag);
     }
 
-    if ((uint64_t)(*origFE)->getModificationTime() != timeModified) {
+    if ((uint64_t)origFE->getModificationTime() != timeModified) {
       if (ignoreIfFilesChanged)
         continue;
       return report("File was modified: " + fromFilename, Diag);
@@ -128,11 +128,11 @@ bool FileRemapper::flushToFile(StringRef outputPath, DiagnosticsEngine &Diag) {
   for (MappingsTy::iterator
          I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
 
-    const FileEntry *origFE = I->first;
-    SmallString<200> origPath = StringRef(origFE->getName());
+    FileEntryRef origFE = I->first;
+    SmallString<200> origPath = StringRef(origFE.getName());
     fs::make_absolute(origPath);
     infoOut << origPath << '\n';
-    infoOut << (uint64_t)origFE->getModificationTime() << '\n';
+    infoOut << (uint64_t)origFE.getModificationTime() << '\n';
 
     if (const FileEntry *FE = I->second.dyn_cast<const FileEntry *>()) {
       SmallString<200> newPath = StringRef(FE->getName());
@@ -143,8 +143,8 @@ bool FileRemapper::flushToFile(StringRef outputPath, DiagnosticsEngine &Diag) {
       SmallString<64> tempPath;
       int fd;
       if (fs::createTemporaryFile(
-              path::filename(origFE->getName()),
-              path::extension(origFE->getName()).drop_front(), fd, tempPath,
+              path::filename(origFE.getName()),
+              path::extension(origFE.getName()).drop_front(), fd, tempPath,
               llvm::sys::fs::OF_Text))
         return report("Could not create file: " + tempPath.str(), Diag);
 
@@ -171,14 +171,14 @@ bool FileRemapper::overwriteOriginal(DiagnosticsEngine &Diag,
 
   for (MappingsTy::iterator
          I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
-    const FileEntry *origFE = I->first;
+    FileEntryRef origFE = I->first;
     assert(I->second.is<llvm::MemoryBuffer *>());
-    if (!fs::exists(origFE->getName()))
-      return report(StringRef("File does not exist: ") + origFE->getName(),
+    if (!fs::exists(origFE.getName()))
+      return report(StringRef("File does not exist: ") + origFE.getName(),
                     Diag);
 
     std::error_code EC;
-    llvm::raw_fd_ostream Out(origFE->getName(), EC, llvm::sys::fs::OF_None);
+    llvm::raw_fd_ostream Out(origFE.getName(), EC, llvm::sys::fs::OF_None);
     if (EC)
       return report(EC.message(), Diag);
 
@@ -197,11 +197,11 @@ void FileRemapper::forEachMapping(
         CaptureBuffer) const {
   for (auto &Mapping : FromToMappings) {
     if (const FileEntry *FE = Mapping.second.dyn_cast<const FileEntry *>()) {
-      CaptureFile(Mapping.first->getName(), FE->getName());
+      CaptureFile(Mapping.first.getName(), FE->getName());
       continue;
     }
     CaptureBuffer(
-        Mapping.first->getName(),
+        Mapping.first.getName(),
         Mapping.second.get<llvm::MemoryBuffer *>()->getMemBufferRef());
   }
 }
@@ -210,10 +210,10 @@ void FileRemapper::applyMappings(PreprocessorOptions &PPOpts) const {
   for (MappingsTy::const_iterator
          I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
     if (const FileEntry *FE = I->second.dyn_cast<const FileEntry *>()) {
-      PPOpts.addRemappedFile(I->first->getName(), FE->getName());
+      PPOpts.addRemappedFile(I->first.getName(), FE->getName());
     } else {
       llvm::MemoryBuffer *mem = I->second.get<llvm::MemoryBuffer *>();
-      PPOpts.addRemappedFile(I->first->getName(), mem);
+      PPOpts.addRemappedFile(I->first.getName(), mem);
     }
   }
 
@@ -222,38 +222,38 @@ void FileRemapper::applyMappings(PreprocessorOptions &PPOpts) const {
 
 void FileRemapper::remap(StringRef filePath,
                          std::unique_ptr<llvm::MemoryBuffer> memBuf) {
-  remap(getOriginalFile(filePath), std::move(memBuf));
+  OptionalFileEntryRef File = getOriginalFile(filePath);
+  assert(File);
+  remap(*File, std::move(memBuf));
 }
 
-void FileRemapper::remap(const FileEntry *file,
+void FileRemapper::remap(FileEntryRef file,
                          std::unique_ptr<llvm::MemoryBuffer> memBuf) {
-  assert(file);
   Target &targ = FromToMappings[file];
   resetTarget(targ);
   targ = memBuf.release();
 }
 
-void FileRemapper::remap(const FileEntry *file, const FileEntry *newfile) {
-  assert(file && newfile);
+void FileRemapper::remap(FileEntryRef file, const FileEntry *newfile) {
+  assert(newfile);
   Target &targ = FromToMappings[file];
   resetTarget(targ);
   targ = newfile;
-  ToFromMappings[newfile] = file;
+  ToFromMappings.insert({newfile, file});
 }
 
-const FileEntry *FileRemapper::getOriginalFile(StringRef filePath) {
-  const FileEntry *file = nullptr;
-  if (auto fileOrErr = FileMgr->getFile(filePath))
-    file = *fileOrErr;
+OptionalFileEntryRef FileRemapper::getOriginalFile(StringRef filePath) {
+  OptionalFileEntryRef File = FileMgr->getOptionalFileRef(filePath);
+  if (!File)
+    return std::nullopt;
   // If we are updating a file that overridden an original file,
   // actually update the original file.
-  llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator
-    I = ToFromMappings.find(file);
+  auto I = ToFromMappings.find(*File);
   if (I != ToFromMappings.end()) {
-    file = I->second;
-    assert(FromToMappings.contains(file) && "Original file not in mappings!");
+    *File = I->second;
+    assert(FromToMappings.contains(*File) && "Original file not in mappings!");
   }
-  return file;
+  return File;
 }
 
 void FileRemapper::resetTarget(Target &targ) {

>From c9271a3485a20e9f5b7ef6fab282267919eaac6c Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 13:33:43 -0700
Subject: [PATCH 44/62] [clang] NFCI: Use `FileEntryRef` in `FileRemapper`
 (2/2)

---
 clang/include/clang/ARCMigrate/FileRemapper.h |  4 +--
 clang/lib/ARCMigrate/FileRemapper.cpp         | 28 ++++++++++---------
 2 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/ARCMigrate/FileRemapper.h b/clang/include/clang/ARCMigrate/FileRemapper.h
index 776ac4700b73bac..ceb3e67b5035272 100644
--- a/clang/include/clang/ARCMigrate/FileRemapper.h
+++ b/clang/include/clang/ARCMigrate/FileRemapper.h
@@ -33,7 +33,7 @@ class FileRemapper {
   // FIXME: Reuse the same FileManager for multiple ASTContexts.
   std::unique_ptr<FileManager> FileMgr;
 
-  typedef llvm::PointerUnion<const FileEntry *, llvm::MemoryBuffer *> Target;
+  typedef llvm::PointerUnion<FileEntryRef, llvm::MemoryBuffer *> Target;
   using MappingsTy = llvm::DenseMap<FileEntryRef, Target>;
   MappingsTy FromToMappings;
 
@@ -67,7 +67,7 @@ class FileRemapper {
 
 private:
   void remap(FileEntryRef file, std::unique_ptr<llvm::MemoryBuffer> memBuf);
-  void remap(FileEntryRef file, const FileEntry *newfile);
+  void remap(FileEntryRef file, FileEntryRef newfile);
 
   OptionalFileEntryRef getOriginalFile(StringRef filePath);
   void resetTarget(Target &targ);
diff --git a/clang/lib/ARCMigrate/FileRemapper.cpp b/clang/lib/ARCMigrate/FileRemapper.cpp
index 413caf1e9653d4c..bd8317e0a24515f 100644
--- a/clang/lib/ARCMigrate/FileRemapper.cpp
+++ b/clang/lib/ARCMigrate/FileRemapper.cpp
@@ -60,7 +60,7 @@ bool FileRemapper::initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
   if (!llvm::sys::fs::exists(infoFile))
     return false;
 
-  std::vector<std::pair<FileEntryRef, const FileEntry *> > pairs;
+  std::vector<std::pair<FileEntryRef, FileEntryRef>> pairs;
 
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBuf =
       llvm::MemoryBuffer::getFile(infoFile, /*IsText=*/true);
@@ -84,7 +84,7 @@ bool FileRemapper::initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
         continue;
       return report("File does not exist: " + fromFilename, Diag);
     }
-    llvm::ErrorOr<const FileEntry *> newFE = FileMgr->getFile(toFilename);
+    auto newFE = FileMgr->getOptionalFileRef(toFilename);
     if (!newFE) {
       if (ignoreIfFilesChanged)
         continue;
@@ -134,8 +134,9 @@ bool FileRemapper::flushToFile(StringRef outputPath, DiagnosticsEngine &Diag) {
     infoOut << origPath << '\n';
     infoOut << (uint64_t)origFE.getModificationTime() << '\n';
 
-    if (const FileEntry *FE = I->second.dyn_cast<const FileEntry *>()) {
-      SmallString<200> newPath = StringRef(FE->getName());
+    if (I->second.is<FileEntryRef>()) {
+      auto FE = I->second.get<FileEntryRef>();
+      SmallString<200> newPath = StringRef(FE.getName());
       fs::make_absolute(newPath);
       infoOut << newPath << '\n';
     } else {
@@ -153,10 +154,10 @@ bool FileRemapper::flushToFile(StringRef outputPath, DiagnosticsEngine &Diag) {
       newOut.write(mem->getBufferStart(), mem->getBufferSize());
       newOut.close();
 
-      auto newE = FileMgr->getFile(tempPath);
+      auto newE = FileMgr->getOptionalFileRef(tempPath);
       if (newE) {
         remap(origFE, *newE);
-        infoOut << (*newE)->getName() << '\n';
+        infoOut << newE->getName() << '\n';
       }
     }
   }
@@ -196,8 +197,9 @@ void FileRemapper::forEachMapping(
     llvm::function_ref<void(StringRef, const llvm::MemoryBufferRef &)>
         CaptureBuffer) const {
   for (auto &Mapping : FromToMappings) {
-    if (const FileEntry *FE = Mapping.second.dyn_cast<const FileEntry *>()) {
-      CaptureFile(Mapping.first.getName(), FE->getName());
+    if (Mapping.second.is<FileEntryRef>()) {
+      auto FE = Mapping.second.get<FileEntryRef>();
+      CaptureFile(Mapping.first.getName(), FE.getName());
       continue;
     }
     CaptureBuffer(
@@ -209,8 +211,9 @@ void FileRemapper::forEachMapping(
 void FileRemapper::applyMappings(PreprocessorOptions &PPOpts) const {
   for (MappingsTy::const_iterator
          I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
-    if (const FileEntry *FE = I->second.dyn_cast<const FileEntry *>()) {
-      PPOpts.addRemappedFile(I->first.getName(), FE->getName());
+    if (I->second.is<FileEntryRef>()) {
+      auto FE = I->second.get<FileEntryRef>();
+      PPOpts.addRemappedFile(I->first.getName(), FE.getName());
     } else {
       llvm::MemoryBuffer *mem = I->second.get<llvm::MemoryBuffer *>();
       PPOpts.addRemappedFile(I->first.getName(), mem);
@@ -234,8 +237,7 @@ void FileRemapper::remap(FileEntryRef file,
   targ = memBuf.release();
 }
 
-void FileRemapper::remap(FileEntryRef file, const FileEntry *newfile) {
-  assert(newfile);
+void FileRemapper::remap(FileEntryRef file, FileEntryRef newfile) {
   Target &targ = FromToMappings[file];
   resetTarget(targ);
   targ = newfile;
@@ -263,7 +265,7 @@ void FileRemapper::resetTarget(Target &targ) {
   if (llvm::MemoryBuffer *oldmem = targ.dyn_cast<llvm::MemoryBuffer *>()) {
     delete oldmem;
   } else {
-    const FileEntry *toFE = targ.get<const FileEntry *>();
+    FileEntryRef toFE = targ.get<FileEntryRef>();
     ToFromMappings.erase(toFE);
   }
 }

>From 70cc5842bfaccb597d7b05ed1c30ca506dd58c8f Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 10 Sep 2023 23:33:49 +0800
Subject: [PATCH 45/62] [InstCombine] Use m_c_And/m_c_Or instead of duplicate
 logic. NFC.

See also https://reviews.llvm.org/D153148#inline-1535588
---
 .../InstCombine/InstCombineAndOrXor.cpp       | 26 ++++++-------------
 1 file changed, 8 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 7dc0e004a0d5254..d8c2827d25831d3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2643,23 +2643,16 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
   //       with binop identity constant. But creating a select with non-constant
   //       arm may not be reversible due to poison semantics. Is that a good
   //       canonicalization?
-  Value *A;
-  if (match(Op0, m_OneUse(m_SExt(m_Value(A)))) &&
-      A->getType()->isIntOrIntVectorTy(1))
-    return SelectInst::Create(A, Op1, Constant::getNullValue(Ty));
-  if (match(Op1, m_OneUse(m_SExt(m_Value(A)))) &&
+  Value *A, *B;
+  if (match(&I, m_c_And(m_OneUse(m_SExt(m_Value(A))), m_Value(B))) &&
       A->getType()->isIntOrIntVectorTy(1))
-    return SelectInst::Create(A, Op0, Constant::getNullValue(Ty));
+    return SelectInst::Create(A, B, Constant::getNullValue(Ty));
 
   // Similarly, a 'not' of the bool translates to a swap of the select arms:
-  // ~sext(A) & Op1 --> A ? 0 : Op1
-  // Op0 & ~sext(A) --> A ? 0 : Op0
-  if (match(Op0, m_Not(m_SExt(m_Value(A)))) &&
+  // ~sext(A) & B / B & ~sext(A) --> A ? 0 : B
+  if (match(&I, m_c_And(m_Not(m_SExt(m_Value(A))), m_Value(B))) &&
       A->getType()->isIntOrIntVectorTy(1))
-    return SelectInst::Create(A, Constant::getNullValue(Ty), Op1);
-  if (match(Op1, m_Not(m_SExt(m_Value(A)))) &&
-      A->getType()->isIntOrIntVectorTy(1))
-    return SelectInst::Create(A, Constant::getNullValue(Ty), Op0);
+    return SelectInst::Create(A, Constant::getNullValue(Ty), B);
 
   // (iN X s>> (N-1)) & Y --> (X s< 0) ? Y : 0 -- with optional sext
   if (match(&I, m_c_And(m_OneUse(m_SExtOrSelf(
@@ -3603,12 +3596,9 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
   //       with binop identity constant. But creating a select with non-constant
   //       arm may not be reversible due to poison semantics. Is that a good
   //       canonicalization?
-  if (match(Op0, m_OneUse(m_SExt(m_Value(A)))) &&
-      A->getType()->isIntOrIntVectorTy(1))
-    return SelectInst::Create(A, ConstantInt::getAllOnesValue(Ty), Op1);
-  if (match(Op1, m_OneUse(m_SExt(m_Value(A)))) &&
+  if (match(&I, m_c_Or(m_OneUse(m_SExt(m_Value(A))), m_Value(B))) &&
       A->getType()->isIntOrIntVectorTy(1))
-    return SelectInst::Create(A, ConstantInt::getAllOnesValue(Ty), Op0);
+    return SelectInst::Create(A, ConstantInt::getAllOnesValue(Ty), B);
 
   // Note: If we've gotten to the point of visiting the outer OR, then the
   // inner one couldn't be simplified.  If it was a constant, then it won't

>From dbc9c7d5e88761dbb6ddb4cb599feb19cbb6f04c Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Sun, 10 Sep 2023 16:54:12 +0100
Subject: [PATCH 46/62] [X86] matchIndexRecursively - don't peek through
 multiuse sext(add_nsw(x,c)) (PR65895)

Fixes #65895
---
 llvm/lib/Target/X86/X86ISelDAGToDAG.cpp |  5 ++-
 llvm/test/CodeGen/X86/pr65895.ll        | 60 +++++++++++++++++++++++++
 2 files changed, 63 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/X86/pr65895.ll

diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index 140e5dea6a4eb64..580c45dd1a8e3da 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -2256,9 +2256,10 @@ SDValue X86DAGToDAGISel::matchIndexRecursively(SDValue N,
 
   // index: sext(add_nsw(x,c)) -> index: sext(x), disp + sext(c)
   // TODO: call matchIndexRecursively(AddSrc) if we won't corrupt sext?
-  if (Opc == ISD::SIGN_EXTEND && !VT.isVector()) {
+  if (Opc == ISD::SIGN_EXTEND && !VT.isVector() && N.hasOneUse()) {
     SDValue Src = N.getOperand(0);
-    if (Src.getOpcode() == ISD::ADD && Src->getFlags().hasNoSignedWrap()) {
+    if (Src.getOpcode() == ISD::ADD && Src->getFlags().hasNoSignedWrap() &&
+        Src.hasOneUse()) {
       if (CurDAG->isBaseWithConstantOffset(Src)) {
         SDValue AddSrc = Src.getOperand(0);
         auto *AddVal = cast<ConstantSDNode>(Src.getOperand(1));
diff --git a/llvm/test/CodeGen/X86/pr65895.ll b/llvm/test/CodeGen/X86/pr65895.ll
new file mode 100644
index 000000000000000..4fbbed4b18aff03
--- /dev/null
+++ b/llvm/test/CodeGen/X86/pr65895.ll
@@ -0,0 +1,60 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
+; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s
+
+ at a = dso_local local_unnamed_addr global i16 0, align 2
+ at c = internal unnamed_addr global i1 false, align 1
+ at b = dso_local local_unnamed_addr global i8 0, align 1
+ at d = dso_local local_unnamed_addr global i32 0, align 4
+ at e = dso_local local_unnamed_addr global i64 0, align 8
+
+define i32 @PR65895() {
+; CHECK-LABEL: PR65895:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movb $2, %al
+; CHECK-NEXT:    subb c(%rip), %al
+; CHECK-NEXT:    cmpw $0, a(%rip)
+; CHECK-NEXT:    je .LBB0_3
+; CHECK-NEXT:  # %bb.1: # %for.body.lr.ph
+; CHECK-NEXT:    movb %al, b(%rip)
+; CHECK-NEXT:    .p2align 4, 0x90
+; CHECK-NEXT:  .LBB0_2: # %for.body
+; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
+; CHECK-NEXT:    jmp .LBB0_2
+; CHECK-NEXT:  .LBB0_3: # %for.end
+; CHECK-NEXT:    addb $-3, %al
+; CHECK-NEXT:    movsbl %al, %eax
+; CHECK-NEXT:    movl %eax, d(%rip)
+; CHECK-NEXT:    leal 247(%rax,%rax,2), %eax
+; CHECK-NEXT:    movb $1, c(%rip)
+; CHECK-NEXT:    movsbq %al, %rax
+; CHECK-NEXT:    movq %rax, e(%rip)
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    retq
+entry:
+  %.pr = load i16, ptr @a, align 2
+  %tobool.not = icmp eq i16 %.pr, 0
+  %.b = load i1, ptr @c, align 1
+  %0 = select i1 %.b, i8 1, i8 2
+  br i1 %tobool.not, label %for.end, label %for.body.lr.ph
+
+for.body.lr.ph:
+  store i8 %0, ptr @b, align 1
+  br label %for.body
+
+for.body:
+  br label %for.body
+
+for.end:
+  %sub = add nsw i8 %0, -3
+  %conv2 = sext i8 %sub to i32
+  store i32 %conv2, ptr @d, align 4
+  %add = shl nsw i32 %conv2, 1
+  %sub7 = add nsw i32 %conv2, 247
+  %add8 = add nsw i32 %sub7, %add
+  %conv9 = zext i32 %add8 to i64
+  store i1 true, ptr @c, align 1
+  %sext = shl i64 %conv9, 56
+  %conv11 = ashr exact i64 %sext, 56
+  store i64 %conv11, ptr @e, align 8
+  ret i32 0
+}

>From d7455e2c221b9692234adff05a8ecac31981674f Mon Sep 17 00:00:00 2001
From: Piotr Zegar <me at piotrzegar.pl>
Date: Sun, 10 Sep 2023 18:08:51 +0200
Subject: [PATCH 47/62] [clang-tidy] Exclude bitwise operators in
 bugprone-non-zero-enum-to-bool-conversion (#65498)

Improved bugprone-non-zero-enum-to-bool-conversion check by eliminating
false positives resulting from direct usage of bitwise operators.
---
 .../NonZeroEnumToBoolConversionCheck.cpp      |  8 +++++++-
 clang-tools-extra/docs/ReleaseNotes.rst       |  4 ++++
 .../non-zero-enum-to-bool-conversion.cpp      | 20 +++++++++++++++++++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/bugprone/NonZeroEnumToBoolConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NonZeroEnumToBoolConversionCheck.cpp
index a59c4fc47c0b4e9..918b6e3824f0b1b 100644
--- a/clang-tools-extra/clang-tidy/bugprone/NonZeroEnumToBoolConversionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/NonZeroEnumToBoolConversionCheck.cpp
@@ -49,6 +49,11 @@ bool NonZeroEnumToBoolConversionCheck::isLanguageVersionSupported(
 }
 
 void NonZeroEnumToBoolConversionCheck::registerMatchers(MatchFinder *Finder) {
+  // Excluding bitwise operators (binary and overload) to avoid false-positives
+  // in code like this 'if (e & SUCCESS) {'.
+  auto ExcludedOperators = binaryOperation(hasAnyOperatorName(
+      "|", "&", "^", "<<", ">>", "~", "|=", "&=", "^=", "<<=", ">>="));
+
   Finder->addMatcher(
       castExpr(hasCastKind(CK_IntegralToBoolean),
                unless(isExpansionInSystemHeader()), hasType(booleanType()),
@@ -58,7 +63,8 @@ void NonZeroEnumToBoolConversionCheck::registerMatchers(MatchFinder *Finder) {
                                      unless(matchers::matchesAnyListedName(
                                          EnumIgnoreList)))
                                 .bind("enum"))))),
-                        unless(declRefExpr(to(enumConstantDecl()))))),
+                        unless(declRefExpr(to(enumConstantDecl()))),
+                        unless(ignoringImplicit(ExcludedOperators)))),
                unless(hasAncestor(staticAssertDecl())))
           .bind("cast"),
       this);
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index c1a36ac0f92a96a..63c644ca1a52239 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -183,6 +183,10 @@ Changes in existing checks
   <clang-tidy/checks/bugprone/lambda-function-name>` check by adding option
   `IgnoreMacros` to ignore warnings in macros.
 
+- Improved :doc:`bugprone-non-zero-enum-to-bool-conversion
+  <clang-tidy/checks/bugprone/non-zero-enum-to-bool-conversion>` check by
+  eliminating false positives resulting from direct usage of bitwise operators.
+
 - Improved :doc:`bugprone-reserved-identifier
   <clang-tidy/checks/bugprone/reserved-identifier>` check, so that it does not
   warn on macros starting with underscore and lowercase letter.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/non-zero-enum-to-bool-conversion.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/non-zero-enum-to-bool-conversion.cpp
index e0728680d4c6ad1..794e7b20c8ca53c 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/non-zero-enum-to-bool-conversion.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/non-zero-enum-to-bool-conversion.cpp
@@ -82,6 +82,14 @@ bool explicitCompare(EStatus value) {
   return value == SUCCESS;
 }
 
+bool explicitBitUsage1(EStatus value) {
+  return (value & SUCCESS);
+}
+
+bool explicitBitUsage2(EStatus value) {
+  return (value | SUCCESS);
+}
+
 bool testEnumeratorCompare() {
   return SUCCESS;
 }
@@ -104,4 +112,16 @@ bool testIgnored(IgnoredSecondEnum value) {
   return value;
 }
 
+enum CustomOperatorEnum {
+    E0 = 0x1,
+    E1 = 0x2,
+    E2 = 0x4
+};
+
+CustomOperatorEnum operator&(CustomOperatorEnum a, CustomOperatorEnum b) { return static_cast<CustomOperatorEnum>(a & b); }
+
+void testCustomOperator(CustomOperatorEnum e) {
+    if (e & E1) {}
+}
+
 }

>From ab38f5559104a242fd72f27086fa9ba10c1deb16 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 18:36:42 -0700
Subject: [PATCH 48/62] [clang] NFCI: Use `FileEntryRef` in `ASTReader`

---
 clang/lib/Serialization/ASTReader.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 0cfecddc198db5a..2289edc511e9612 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -5689,7 +5689,7 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F,
                                        "too many submodules");
 
       if (!ParentModule) {
-        if (const FileEntry *CurFile = CurrentModule->getASTFile()) {
+        if (OptionalFileEntryRef CurFile = CurrentModule->getASTFile()) {
           // Don't emit module relocation error if we have -fno-validate-pch
           if (!bool(PP.getPreprocessorOpts().DisablePCHOrModuleValidation &
                     DisableValidationForModuleKind::Module) &&

>From 88fbaf2727f27e302f4505d0362345a903cbe36f Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sat, 9 Sep 2023 19:05:17 -0700
Subject: [PATCH 49/62] [clang] NFCI: Use `FileEntryRef` in `ASTWriter`

---
 clang/lib/Serialization/ASTWriter.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index b4a68c1fdf947d8..5ba07271cd81867 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -1550,7 +1550,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
 
   // Original file name and file ID
   SourceManager &SM = Context.getSourceManager();
-  if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
+  if (auto MainFile = SM.getFileEntryRefForID(SM.getMainFileID())) {
     auto FileAbbrev = std::make_shared<BitCodeAbbrev>();
     FileAbbrev->Add(BitCodeAbbrevOp(ORIGINAL_FILE));
     FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File ID

>From 03b00f43d1bda76fcec6b85f9f2c7b72eff86e89 Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Sun, 10 Sep 2023 18:54:06 +0200
Subject: [PATCH 50/62] [libc++] Use inline instead of static in headers.

This has been tested as part of D156609.
---
 libcxx/src/std_stream.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libcxx/src/std_stream.h b/libcxx/src/std_stream.h
index 0febf42c9fff3fd..37b4ffd1b4f6c51 100644
--- a/libcxx/src/std_stream.h
+++ b/libcxx/src/std_stream.h
@@ -113,7 +113,7 @@ __stdinbuf<_CharT>::uflow()
     return __getchar(true);
 }
 
-static bool __do_getc(FILE *__fp, char *__pbuf) {
+inline bool __do_getc(FILE *__fp, char *__pbuf) {
     int __c = getc(__fp);
     if (__c == EOF)
         return false;
@@ -121,7 +121,7 @@ static bool __do_getc(FILE *__fp, char *__pbuf) {
     return true;
 }
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
-static bool __do_getc(FILE *__fp, wchar_t *__pbuf) {
+inline bool __do_getc(FILE *__fp, wchar_t *__pbuf) {
     wint_t __c = getwc(__fp);
     if (__c == WEOF)
         return false;
@@ -130,13 +130,13 @@ static bool __do_getc(FILE *__fp, wchar_t *__pbuf) {
 }
 #endif
 
-static bool __do_ungetc(int __c, FILE *__fp, char __dummy) {
+inline bool __do_ungetc(int __c, FILE *__fp, char __dummy) {
     if (ungetc(__c, __fp) == EOF)
         return false;
     return true;
 }
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
-static bool __do_ungetc(std::wint_t __c, FILE *__fp, wchar_t __dummy) {
+inline bool __do_ungetc(std::wint_t __c, FILE *__fp, wchar_t __dummy) {
     if (ungetwc(__c, __fp) == WEOF)
         return false;
     return true;
@@ -324,13 +324,13 @@ __stdoutbuf<_CharT>::__stdoutbuf(FILE* __fp, state_type* __st)
         __always_noconv_ = true;
 }
 
-static bool __do_fputc(char __c, FILE* __fp) {
+inline bool __do_fputc(char __c, FILE* __fp) {
     if (fwrite(&__c, sizeof(__c), 1, __fp) != 1)
         return false;
     return true;
 }
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
-static bool __do_fputc(wchar_t __c, FILE* __fp) {
+inline bool __do_fputc(wchar_t __c, FILE* __fp) {
     // fputwc works regardless of wide/narrow mode of stdout, while
     // fwrite of wchar_t only works if the stream actually has been set
     // into wide mode.

>From 86bcf60a636456467f14c999c2f1c2d0759f50c3 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Sun, 10 Sep 2023 09:54:26 -0700
Subject: [PATCH 51/62] [AIX][tests] Temporarily disable more Clang/Index tests

This extends 985dacea by XFAILing more tests that started failing after these commits:
* 14498a477ee9e00dc462779cee8cbc5846ca6d3a
* e644f5973b0b71baadc6d7b64596527a1dc49d17
* 89bacc0bb9f6aa66ca1951ec5c0e4c38cc661160

These failures need to be investigated. Possible cause is D151938.
---
 clang/test/Index/Core/designated-inits.c                  | 1 +
 clang/test/Index/Core/external-source-symbol-attr-cxx.cpp | 1 +
 clang/test/Index/Core/external-source-symbol-attr.m       | 1 +
 clang/test/Index/Core/index-dependent-source.cpp          | 1 +
 clang/test/Index/Core/index-instantiated-source.cpp       | 1 +
 clang/test/Index/Core/index-source-invalid-name.cpp       | 1 +
 clang/test/Index/Core/index-source.cpp                    | 1 +
 clang/test/Index/Core/index-source.m                      | 1 +
 clang/test/Index/Core/index-source.mm                     | 1 +
 clang/test/Index/Core/index-subkinds.m                    | 1 +
 clang/test/Index/ms-property.cpp                          | 1 +
 clang/test/Index/using_if_exists.cpp                      | 1 +
 12 files changed, 12 insertions(+)

diff --git a/clang/test/Index/Core/designated-inits.c b/clang/test/Index/Core/designated-inits.c
index a31cb95a4b82db7..10f48c68915fe4d 100644
--- a/clang/test/Index/Core/designated-inits.c
+++ b/clang/test/Index/Core/designated-inits.c
@@ -1,3 +1,4 @@
+// XFAIL: target={{.*}}-aix{{.*}}
 // RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s
 
 struct MyStruct {
diff --git a/clang/test/Index/Core/external-source-symbol-attr-cxx.cpp b/clang/test/Index/Core/external-source-symbol-attr-cxx.cpp
index 8ccf3c7d69496bd..b3fb31c54a74208 100644
--- a/clang/test/Index/Core/external-source-symbol-attr-cxx.cpp
+++ b/clang/test/Index/Core/external-source-symbol-attr-cxx.cpp
@@ -1,3 +1,4 @@
+// XFAIL: target={{.*}}-aix{{.*}}
 // RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s
 
 #define GEN_DECL_USR(mod_name, usr) __attribute__((external_source_symbol(language="Swift", defined_in=mod_name, USR=usr, generated_declaration)))
diff --git a/clang/test/Index/Core/external-source-symbol-attr.m b/clang/test/Index/Core/external-source-symbol-attr.m
index 1f907912737b0d7..fee80d3b0fdf6ca 100644
--- a/clang/test/Index/Core/external-source-symbol-attr.m
+++ b/clang/test/Index/Core/external-source-symbol-attr.m
@@ -1,3 +1,4 @@
+// XFAIL: target={{.*}}-aix{{.*}}
 // RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s
 
 #define EXT_DECL(mod_name) __attribute__((external_source_symbol(language="Swift", defined_in=mod_name)))
diff --git a/clang/test/Index/Core/index-dependent-source.cpp b/clang/test/Index/Core/index-dependent-source.cpp
index 8fec9abd1e926b9..eabec29a1fd7b30 100644
--- a/clang/test/Index/Core/index-dependent-source.cpp
+++ b/clang/test/Index/Core/index-dependent-source.cpp
@@ -1,3 +1,4 @@
+// XFAIL: target={{.*}}-aix{{.*}}
 // RUN: c-index-test core -print-source-symbols -- %s -std=c++14 -target x86_64-apple-macosx10.7 | FileCheck %s
 
 int invalid;
diff --git a/clang/test/Index/Core/index-instantiated-source.cpp b/clang/test/Index/Core/index-instantiated-source.cpp
index 2a67a3a3c7938e3..ccb39019ef06741 100644
--- a/clang/test/Index/Core/index-instantiated-source.cpp
+++ b/clang/test/Index/Core/index-instantiated-source.cpp
@@ -1,3 +1,4 @@
+// XFAIL: target={{.*}}-aix{{.*}}
 // RUN: c-index-test core -print-source-symbols -- %s -std=c++14 -target x86_64-apple-macosx10.7 | FileCheck %s
 // References to declarations in instantiations should be canonicalized:
 
diff --git a/clang/test/Index/Core/index-source-invalid-name.cpp b/clang/test/Index/Core/index-source-invalid-name.cpp
index 1b4b059cd1b36dc..034fd6b7009b6b7 100644
--- a/clang/test/Index/Core/index-source-invalid-name.cpp
+++ b/clang/test/Index/Core/index-source-invalid-name.cpp
@@ -1,3 +1,4 @@
+// XFAIL: target={{.*}}-aix{{.*}}
 // RUN: c-index-test core -print-source-symbols -- %s -std=c++1z -target x86_64-apple-macosx10.7 | FileCheck %s
 
 namespace rdar32474406 {
diff --git a/clang/test/Index/Core/index-source.cpp b/clang/test/Index/Core/index-source.cpp
index 8f9fbc4c8d29c4a..ed7474499dc7299 100644
--- a/clang/test/Index/Core/index-source.cpp
+++ b/clang/test/Index/Core/index-source.cpp
@@ -1,3 +1,4 @@
+// XFAIL: target={{.*}}-aix{{.*}}
 // RUN: c-index-test core -print-source-symbols -- %s -std=c++1z -target x86_64-apple-macosx10.7 | FileCheck %s
 // RUN: c-index-test core -print-source-symbols -include-locals -- %s -std=c++1z -target x86_64-apple-macosx10.7 | FileCheck -check-prefix=LOCAL %s
 
diff --git a/clang/test/Index/Core/index-source.m b/clang/test/Index/Core/index-source.m
index 07c7d207607cbd8..a551fe965bb0bd1 100644
--- a/clang/test/Index/Core/index-source.m
+++ b/clang/test/Index/Core/index-source.m
@@ -1,3 +1,4 @@
+// XFAIL: target={{.*}}-aix{{.*}}
 // RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s
 // RUN: c-index-test core -print-source-symbols -include-locals -- %s -target x86_64-apple-macosx10.7 | FileCheck -check-prefix=LOCAL %s
 
diff --git a/clang/test/Index/Core/index-source.mm b/clang/test/Index/Core/index-source.mm
index 049a0bdaf6474ec..659e16f01329095 100644
--- a/clang/test/Index/Core/index-source.mm
+++ b/clang/test/Index/Core/index-source.mm
@@ -1,3 +1,4 @@
+// XFAIL: target={{.*}}-aix{{.*}}
 // RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s
 
 @interface MyCls
diff --git a/clang/test/Index/Core/index-subkinds.m b/clang/test/Index/Core/index-subkinds.m
index 5eea046721b6c0c..d95dfe746b603a1 100644
--- a/clang/test/Index/Core/index-subkinds.m
+++ b/clang/test/Index/Core/index-subkinds.m
@@ -1,3 +1,4 @@
+// XFAIL: target={{.*}}-aix{{.*}}
 // RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s
 
 // CHECK: [[@LINE+1]]:12 | class/ObjC | XCTestCase | c:objc(cs)XCTestCase | _OBJC_CLASS_$_XCTestCase | Decl | rel: 0
diff --git a/clang/test/Index/ms-property.cpp b/clang/test/Index/ms-property.cpp
index 74b5b1399cf501c..d30d30d033d888c 100644
--- a/clang/test/Index/ms-property.cpp
+++ b/clang/test/Index/ms-property.cpp
@@ -1,3 +1,4 @@
+// XFAIL: target={{.*}}-aix{{.*}}
 // RUN: c-index-test core -print-source-symbols -- -target x86_64-apple-darwin10 -fms-extensions -fno-ms-compatibility %s | FileCheck %s
 
 // CHECK: [[@LINE+1]]:8 | struct/C++ | Simple | [[Simple_USR:.*]] | <no-cgname> | Def | rel: 0
diff --git a/clang/test/Index/using_if_exists.cpp b/clang/test/Index/using_if_exists.cpp
index ed13dad9b1f749e..73d1be739e42816 100644
--- a/clang/test/Index/using_if_exists.cpp
+++ b/clang/test/Index/using_if_exists.cpp
@@ -1,3 +1,4 @@
+// XFAIL: target={{.*}}-aix{{.*}}
 // RUN: c-index-test core -print-source-symbols -- %s -target x86_64-unknown-unknown 2>&1 | FileCheck %s
 
 namespace ns {

>From 1b6d3c3a9ac7c1bbeb2c3d3008e77698cf547109 Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Sun, 10 Sep 2023 17:48:54 +0100
Subject: [PATCH 52/62] [TwoAddressInstruction] Use member functions instead of
 static helpers

This just avoids explicitly passing around common pointers like MRI and
TII. NFC.
---
 .../lib/CodeGen/TwoAddressInstructionPass.cpp | 133 ++++++++++--------
 1 file changed, 76 insertions(+), 57 deletions(-)

diff --git a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
index c3ea76bf8cea6d4..45f61262faf9391 100644
--- a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
+++ b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
@@ -116,12 +116,33 @@ class TwoAddressInstructionPass : public MachineFunctionPass {
   // registers. e.g. r1 = move v1024.
   DenseMap<Register, Register> DstRegMap;
 
-  void removeClobberedSrcRegMap(MachineInstr *MI);
+  MachineInstr *getSingleDef(Register Reg, MachineBasicBlock *BB) const;
 
   bool isRevCopyChain(Register FromReg, Register ToReg, int Maxlen);
 
   bool noUseAfterLastDef(Register Reg, unsigned Dist, unsigned &LastDef);
 
+  bool isCopyToReg(MachineInstr &MI, Register &SrcReg, Register &DstReg,
+                   bool &IsSrcPhys, bool &IsDstPhys) const;
+
+  bool isPlainlyKilled(const MachineInstr *MI, Register Reg) const;
+  bool isPlainlyKilled(const MachineOperand &MO) const;
+
+  bool isKilled(MachineInstr &MI, Register Reg, bool allowFalsePositives) const;
+
+  MachineInstr *findOnlyInterestingUse(Register Reg, MachineBasicBlock *MBB,
+                                       bool &IsCopy, Register &DstReg,
+                                       bool &IsDstPhys) const;
+
+  bool regsAreCompatible(Register RegA, Register RegB) const;
+
+  void removeMapRegEntry(const MachineOperand &MO,
+                         DenseMap<Register, Register> &RegMap) const;
+
+  void removeClobberedSrcRegMap(MachineInstr *MI);
+
+  bool regOverlapsSet(const SmallVectorImpl<Register> &Set, Register Reg) const;
+
   bool isProfitableToCommute(Register RegA, Register RegB, Register RegC,
                              MachineInstr *MI, unsigned Dist);
 
@@ -199,8 +220,9 @@ INITIALIZE_PASS_END(TwoAddressInstructionPass, DEBUG_TYPE,
                 "Two-Address instruction pass", false, false)
 
 /// Return the MachineInstr* if it is the single def of the Reg in current BB.
-static MachineInstr *getSingleDef(Register Reg, MachineBasicBlock *BB,
-                                  const MachineRegisterInfo *MRI) {
+MachineInstr *
+TwoAddressInstructionPass::getSingleDef(Register Reg,
+                                        MachineBasicBlock *BB) const {
   MachineInstr *Ret = nullptr;
   for (MachineInstr &DefMI : MRI->def_instructions(Reg)) {
     if (DefMI.getParent() != BB || DefMI.isDebugValue())
@@ -224,7 +246,7 @@ bool TwoAddressInstructionPass::isRevCopyChain(Register FromReg, Register ToReg,
                                                int Maxlen) {
   Register TmpReg = FromReg;
   for (int i = 0; i < Maxlen; i++) {
-    MachineInstr *Def = getSingleDef(TmpReg, MBB, MRI);
+    MachineInstr *Def = getSingleDef(TmpReg, MBB);
     if (!Def || !Def->isCopy())
       return false;
 
@@ -263,9 +285,9 @@ bool TwoAddressInstructionPass::noUseAfterLastDef(Register Reg, unsigned Dist,
 /// Return true if the specified MI is a copy instruction or an extract_subreg
 /// instruction. It also returns the source and destination registers and
 /// whether they are physical registers by reference.
-static bool isCopyToReg(MachineInstr &MI, const TargetInstrInfo *TII,
-                        Register &SrcReg, Register &DstReg, bool &IsSrcPhys,
-                        bool &IsDstPhys) {
+bool TwoAddressInstructionPass::isCopyToReg(MachineInstr &MI, Register &SrcReg,
+                                            Register &DstReg, bool &IsSrcPhys,
+                                            bool &IsDstPhys) const {
   SrcReg = 0;
   DstReg = 0;
   if (MI.isCopy()) {
@@ -285,8 +307,8 @@ static bool isCopyToReg(MachineInstr &MI, const TargetInstrInfo *TII,
 
 /// Test if the given register value, which is used by the
 /// given instruction, is killed by the given instruction.
-static bool isPlainlyKilled(const MachineInstr *MI, Register Reg,
-                            LiveIntervals *LIS) {
+bool TwoAddressInstructionPass::isPlainlyKilled(const MachineInstr *MI,
+                                                Register Reg) const {
   if (LIS && Reg.isVirtual() && !LIS->isNotInMIMap(*MI)) {
     // FIXME: Sometimes tryInstructionTransform() will add instructions and
     // test whether they can be folded before keeping them. In this case it
@@ -311,8 +333,9 @@ static bool isPlainlyKilled(const MachineInstr *MI, Register Reg,
 
 /// Test if the register used by the given operand is killed by the operand's
 /// instruction.
-static bool isPlainlyKilled(const MachineOperand &MO, LiveIntervals *LIS) {
-  return MO.isKill() || isPlainlyKilled(MO.getParent(), MO.getReg(), LIS);
+bool TwoAddressInstructionPass::isPlainlyKilled(
+    const MachineOperand &MO) const {
+  return MO.isKill() || isPlainlyKilled(MO.getParent(), MO.getReg());
 }
 
 /// Test if the given register value, which is used by the given
@@ -332,15 +355,14 @@ static bool isPlainlyKilled(const MachineOperand &MO, LiveIntervals *LIS) {
 ///
 /// If allowFalsePositives is true then likely kills are treated as kills even
 /// if it can't be proven that they are kills.
-static bool isKilled(MachineInstr &MI, Register Reg,
-                     const MachineRegisterInfo *MRI, const TargetInstrInfo *TII,
-                     LiveIntervals *LIS, bool allowFalsePositives) {
+bool TwoAddressInstructionPass::isKilled(MachineInstr &MI, Register Reg,
+                                         bool allowFalsePositives) const {
   MachineInstr *DefMI = &MI;
   while (true) {
     // All uses of physical registers are likely to be kills.
     if (Reg.isPhysical() && (allowFalsePositives || MRI->hasOneUse(Reg)))
       return true;
-    if (!isPlainlyKilled(DefMI, Reg, LIS))
+    if (!isPlainlyKilled(DefMI, Reg))
       return false;
     if (Reg.isPhysical())
       return true;
@@ -354,7 +376,7 @@ static bool isKilled(MachineInstr &MI, Register Reg,
     Register SrcReg, DstReg;
     // If the def is something other than a copy, then it isn't going to
     // be coalesced, so follow the kill flag.
-    if (!isCopyToReg(*DefMI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys))
+    if (!isCopyToReg(*DefMI, SrcReg, DstReg, IsSrcPhys, IsDstPhys))
       return true;
     Reg = SrcReg;
   }
@@ -378,17 +400,15 @@ static bool isTwoAddrUse(MachineInstr &MI, Register Reg, Register &DstReg) {
 
 /// Given a register, if all its uses are in the same basic block, return the
 /// last use instruction if it's a copy or a two-address use.
-static MachineInstr *
-findOnlyInterestingUse(Register Reg, MachineBasicBlock *MBB,
-                       MachineRegisterInfo *MRI, const TargetInstrInfo *TII,
-                       bool &IsCopy, Register &DstReg, bool &IsDstPhys,
-                       LiveIntervals *LIS) {
+MachineInstr *TwoAddressInstructionPass::findOnlyInterestingUse(
+    Register Reg, MachineBasicBlock *MBB, bool &IsCopy, Register &DstReg,
+    bool &IsDstPhys) const {
   MachineOperand *UseOp = nullptr;
   for (MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {
     MachineInstr *MI = MO.getParent();
     if (MI->getParent() != MBB)
       return nullptr;
-    if (isPlainlyKilled(MI, Reg, LIS))
+    if (isPlainlyKilled(MI, Reg))
       UseOp = &MO;
   }
   if (!UseOp)
@@ -397,7 +417,7 @@ findOnlyInterestingUse(Register Reg, MachineBasicBlock *MBB,
 
   Register SrcReg;
   bool IsSrcPhys;
-  if (isCopyToReg(UseMI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) {
+  if (isCopyToReg(UseMI, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) {
     IsCopy = true;
     return &UseMI;
   }
@@ -437,8 +457,8 @@ static MCRegister getMappedReg(Register Reg,
 }
 
 /// Return true if the two registers are equal or aliased.
-static bool regsAreCompatible(Register RegA, Register RegB,
-                              const TargetRegisterInfo *TRI) {
+bool TwoAddressInstructionPass::regsAreCompatible(Register RegA,
+                                                  Register RegB) const {
   if (RegA == RegB)
     return true;
   if (!RegA || !RegB)
@@ -447,9 +467,8 @@ static bool regsAreCompatible(Register RegA, Register RegB,
 }
 
 /// From RegMap remove entries mapped to a physical register which overlaps MO.
-static void removeMapRegEntry(const MachineOperand &MO,
-                              DenseMap<Register, Register> &RegMap,
-                              const TargetRegisterInfo *TRI) {
+void TwoAddressInstructionPass::removeMapRegEntry(
+    const MachineOperand &MO, DenseMap<Register, Register> &RegMap) const {
   assert(
       (MO.isReg() || MO.isRegMask()) &&
       "removeMapRegEntry must be called with a register or regmask operand.");
@@ -497,13 +516,13 @@ void TwoAddressInstructionPass::removeClobberedSrcRegMap(MachineInstr *MI) {
       return;
 
     Register Src = MI->getOperand(1).getReg();
-    if (regsAreCompatible(Dst, getMappedReg(Src, SrcRegMap), TRI))
+    if (regsAreCompatible(Dst, getMappedReg(Src, SrcRegMap)))
       return;
   }
 
   for (const MachineOperand &MO : MI->operands()) {
     if (MO.isRegMask()) {
-      removeMapRegEntry(MO, SrcRegMap, TRI);
+      removeMapRegEntry(MO, SrcRegMap);
       continue;
     }
     if (!MO.isReg() || !MO.isDef())
@@ -511,13 +530,13 @@ void TwoAddressInstructionPass::removeClobberedSrcRegMap(MachineInstr *MI) {
     Register Reg = MO.getReg();
     if (!Reg || Reg.isVirtual())
       continue;
-    removeMapRegEntry(MO, SrcRegMap, TRI);
+    removeMapRegEntry(MO, SrcRegMap);
   }
 }
 
 // Returns true if Reg is equal or aliased to at least one register in Set.
-static bool regOverlapsSet(const SmallVectorImpl<Register> &Set, Register Reg,
-                           const TargetRegisterInfo *TRI) {
+bool TwoAddressInstructionPass::regOverlapsSet(
+    const SmallVectorImpl<Register> &Set, Register Reg) const {
   for (unsigned R : Set)
     if (TRI->regsOverlap(R, Reg))
       return true;
@@ -553,7 +572,7 @@ bool TwoAddressInstructionPass::isProfitableToCommute(Register RegA,
   // insert => %reg1030 = COPY %reg1029
   // %reg1030 = ADD8rr killed %reg1029, killed %reg1028, implicit dead %eflags
 
-  if (!isPlainlyKilled(MI, RegC, LIS))
+  if (!isPlainlyKilled(MI, RegC))
     return false;
 
   // Ok, we have something like:
@@ -570,8 +589,8 @@ bool TwoAddressInstructionPass::isProfitableToCommute(Register RegA,
   if (ToRegA) {
     MCRegister FromRegB = getMappedReg(RegB, SrcRegMap);
     MCRegister FromRegC = getMappedReg(RegC, SrcRegMap);
-    bool CompB = FromRegB && regsAreCompatible(FromRegB, ToRegA, TRI);
-    bool CompC = FromRegC && regsAreCompatible(FromRegC, ToRegA, TRI);
+    bool CompB = FromRegB && regsAreCompatible(FromRegB, ToRegA);
+    bool CompC = FromRegC && regsAreCompatible(FromRegC, ToRegA);
 
     // Compute if any of the following are true:
     // -RegB is not tied to a register and RegC is compatible with RegA.
@@ -675,7 +694,7 @@ bool TwoAddressInstructionPass::isProfitableToConv3Addr(Register RegA,
   if (!FromRegB)
     return false;
   MCRegister ToRegA = getMappedReg(RegA, DstRegMap);
-  return (ToRegA && !regsAreCompatible(FromRegB, ToRegA, TRI));
+  return (ToRegA && !regsAreCompatible(FromRegB, ToRegA));
 }
 
 /// Convert the specified two-address instruction into a three address one.
@@ -728,8 +747,8 @@ void TwoAddressInstructionPass::scanUses(Register DstReg) {
   bool IsCopy = false;
   Register NewReg;
   Register Reg = DstReg;
-  while (MachineInstr *UseMI = findOnlyInterestingUse(Reg, MBB, MRI, TII,IsCopy,
-                                                      NewReg, IsDstPhys, LIS)) {
+  while (MachineInstr *UseMI =
+             findOnlyInterestingUse(Reg, MBB, IsCopy, NewReg, IsDstPhys)) {
     if (IsCopy && !Processed.insert(UseMI).second)
       break;
 
@@ -781,7 +800,7 @@ void TwoAddressInstructionPass::processCopy(MachineInstr *MI) {
 
   bool IsSrcPhys, IsDstPhys;
   Register SrcReg, DstReg;
-  if (!isCopyToReg(*MI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys))
+  if (!isCopyToReg(*MI, SrcReg, DstReg, IsSrcPhys, IsDstPhys))
     return;
 
   if (IsDstPhys && !IsSrcPhys) {
@@ -865,7 +884,7 @@ bool TwoAddressInstructionPass::rescheduleMIBelowKill(
       Defs.push_back(MOReg);
     else {
       Uses.push_back(MOReg);
-      if (MOReg != Reg && isPlainlyKilled(MO, LIS))
+      if (MOReg != Reg && isPlainlyKilled(MO))
         Kills.push_back(MOReg);
     }
   }
@@ -876,7 +895,7 @@ bool TwoAddressInstructionPass::rescheduleMIBelowKill(
   MachineBasicBlock::iterator End = AfterMI;
   while (End != MBB->end()) {
     End = skipDebugInstructionsForward(End, MBB->end());
-    if (End->isCopy() && regOverlapsSet(Defs, End->getOperand(1).getReg(), TRI))
+    if (End->isCopy() && regOverlapsSet(Defs, End->getOperand(1).getReg()))
       Defs.push_back(End->getOperand(0).getReg());
     else
       break;
@@ -905,20 +924,20 @@ bool TwoAddressInstructionPass::rescheduleMIBelowKill(
       if (!MOReg)
         continue;
       if (MO.isDef()) {
-        if (regOverlapsSet(Uses, MOReg, TRI))
+        if (regOverlapsSet(Uses, MOReg))
           // Physical register use would be clobbered.
           return false;
-        if (!MO.isDead() && regOverlapsSet(Defs, MOReg, TRI))
+        if (!MO.isDead() && regOverlapsSet(Defs, MOReg))
           // May clobber a physical register def.
           // FIXME: This may be too conservative. It's ok if the instruction
           // is sunken completely below the use.
           return false;
       } else {
-        if (regOverlapsSet(Defs, MOReg, TRI))
+        if (regOverlapsSet(Defs, MOReg))
           return false;
-        bool isKill = isPlainlyKilled(MO, LIS);
-        if (MOReg != Reg && ((isKill && regOverlapsSet(Uses, MOReg, TRI)) ||
-                             regOverlapsSet(Kills, MOReg, TRI)))
+        bool isKill = isPlainlyKilled(MO);
+        if (MOReg != Reg && ((isKill && regOverlapsSet(Uses, MOReg)) ||
+                             regOverlapsSet(Kills, MOReg)))
           // Don't want to extend other live ranges and update kills.
           return false;
         if (MOReg == Reg && !isKill)
@@ -1044,7 +1063,7 @@ bool TwoAddressInstructionPass::rescheduleKillAboveMI(
         continue;
       if (isDefTooClose(MOReg, DI->second, MI))
         return false;
-      bool isKill = isPlainlyKilled(MO, LIS);
+      bool isKill = isPlainlyKilled(MO);
       if (MOReg == Reg && !isKill)
         return false;
       Uses.push_back(MOReg);
@@ -1079,14 +1098,14 @@ bool TwoAddressInstructionPass::rescheduleKillAboveMI(
       if (!MOReg)
         continue;
       if (MO.isUse()) {
-        if (regOverlapsSet(Defs, MOReg, TRI))
+        if (regOverlapsSet(Defs, MOReg))
           // Moving KillMI can clobber the physical register if the def has
           // not been seen.
           return false;
-        if (regOverlapsSet(Kills, MOReg, TRI))
+        if (regOverlapsSet(Kills, MOReg))
           // Don't want to extend other live ranges and update kills.
           return false;
-        if (&OtherMI != MI && MOReg == Reg && !isPlainlyKilled(MO, LIS))
+        if (&OtherMI != MI && MOReg == Reg && !isPlainlyKilled(MO))
           // We can't schedule across a use of the register in question.
           return false;
       } else {
@@ -1096,9 +1115,9 @@ bool TwoAddressInstructionPass::rescheduleKillAboveMI(
 
     for (unsigned i = 0, e = OtherDefs.size(); i != e; ++i) {
       Register MOReg = OtherDefs[i];
-      if (regOverlapsSet(Uses, MOReg, TRI))
+      if (regOverlapsSet(Uses, MOReg))
         return false;
-      if (MOReg.isPhysical() && regOverlapsSet(LiveDefs, MOReg, TRI))
+      if (MOReg.isPhysical() && regOverlapsSet(LiveDefs, MOReg))
         return false;
       // Physical register def is seen.
       llvm::erase_value(Defs, MOReg);
@@ -1169,7 +1188,7 @@ bool TwoAddressInstructionPass::tryInstructionCommute(MachineInstr *MI,
 
     // If OtherOp dies but BaseOp does not, swap the OtherOp and BaseOp
     // operands. This makes the live ranges of DstOp and OtherOp joinable.
-    bool OtherOpKilled = isKilled(*MI, OtherOpReg, MRI, TII, LIS, false);
+    bool OtherOpKilled = isKilled(*MI, OtherOpReg, false);
     bool DoCommute = !BaseOpKilled && OtherOpKilled;
 
     if (!DoCommute &&
@@ -1220,7 +1239,7 @@ tryInstructionTransform(MachineBasicBlock::iterator &mi,
   Register regB = MI.getOperand(SrcIdx).getReg();
 
   assert(regB.isVirtual() && "cannot make instruction into two-address form");
-  bool regBKilled = isKilled(MI, regB, MRI, TII, LIS, true);
+  bool regBKilled = isKilled(MI, regB, true);
 
   if (regA.isVirtual())
     scanUses(regA);
@@ -1252,7 +1271,7 @@ tryInstructionTransform(MachineBasicBlock::iterator &mi,
   // confusing the three address conversion below.
   if (Commuted) {
     regB = MI.getOperand(SrcIdx).getReg();
-    regBKilled = isKilled(MI, regB, MRI, TII, LIS, true);
+    regBKilled = isKilled(MI, regB, true);
   }
 
   if (MI.isConvertibleTo3Addr()) {

>From 3a89b56bc552185005d87e82ab352b6939ec83fb Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 11 Sep 2023 02:26:47 +0800
Subject: [PATCH 53/62] [InstCombine] Add test cases from PR62898. NFC.

This patch adds some test cases from https://github.com/llvm/llvm-project/issues/62898.

As nikic noted in the issue, we should start by implementing a generalization of the fold `smin(X, Y) < Z -> X < Z` when `Y > Z` is implied by constant folds/invariants/dom conditions.
```
define i1 @src(i32 %x, i32 %y, i32 %z) {
  %cmp = icmp sgt i32 %y, %z
  br i1 %cmp, label %if, label %end
if:
  %cond = call i32 @llvm.smin.i32(i32 %x, i32 %y)
  %tobool = icmp slt i32 %cond, %z
  ret i1 %tobool
end:
  ret i1 false
}

define i1 @tgt(i32 %x, i32 %y, i32 %z) {
  %cmp = icmp sgt i32 %y, %z
  br i1 %cmp, label %if, label %end
if:
  %tobool = icmp slt i32 %x, %z
  ret i1 %tobool
end:
  ret i1 false
}

declare i32 @llvm.smin.i32(i32, i32)
```
Alive2: https://alive2.llvm.org/ce/z/dK9vXz

This patch also adds some generalized test cases like the above.

Reviewed By: goldstein.w.n

Differential Revision: https://reviews.llvm.org/D156227
---
 llvm/test/Transforms/InstCombine/smax-icmp.ll | 593 +++++++++++
 llvm/test/Transforms/InstCombine/smin-icmp.ll | 964 ++++++++++++++++++
 llvm/test/Transforms/InstCombine/umax-icmp.ll | 593 +++++++++++
 llvm/test/Transforms/InstCombine/umin-icmp.ll | 593 +++++++++++
 4 files changed, 2743 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/smax-icmp.ll b/llvm/test/Transforms/InstCombine/smax-icmp.ll
index 830ae9bd7337f3f..9cf64a9d803d664 100644
--- a/llvm/test/Transforms/InstCombine/smax-icmp.ll
+++ b/llvm/test/Transforms/InstCombine/smax-icmp.ll
@@ -232,3 +232,596 @@ define i1 @sgt_smax4(i32 %a, i32 %y) {
   ret i1 %cmp2
 }
 
+declare void @use(i1 %c)
+
+define void @eq_smax_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @eq_smax_contextual(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp eq i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smax.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @eq_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @eq_smax_contextual_commuted(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp eq i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smax.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @slt_smax_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @slt_smax_contextual(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp slt i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smax.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @slt_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @slt_smax_contextual_commuted(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp slt i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smax.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @sle_smax_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @sle_smax_contextual(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp sle i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smax.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @sle_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @sle_smax_contextual_commuted(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp sle i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smax.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @sgt_smax_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @sgt_smax_contextual(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp sgt i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smax.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @sgt_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @sgt_smax_contextual_commuted(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp sgt i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smax.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @sge_smax_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @sge_smax_contextual(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp sge i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smax.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @sge_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @sge_smax_contextual_commuted(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp sge i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smax.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+declare i32 @llvm.smax.i32(i32, i32)
diff --git a/llvm/test/Transforms/InstCombine/smin-icmp.ll b/llvm/test/Transforms/InstCombine/smin-icmp.ll
index 7089b5469d26294..69ff8414df2a430 100644
--- a/llvm/test/Transforms/InstCombine/smin-icmp.ll
+++ b/llvm/test/Transforms/InstCombine/smin-icmp.ll
@@ -331,3 +331,967 @@ define i1 @sgt_smin4(i32 %a, i32 %y) {
   ret i1 %cmp2
 }
 
+declare void @use(i1 %c)
+
+define void @eq_smin_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @eq_smin_contextual(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp eq i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smin.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @eq_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @eq_smin_contextual_commuted(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp eq i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smin.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @slt_smin_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @slt_smin_contextual(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp slt i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smin.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @slt_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @slt_smin_contextual_commuted(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp slt i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smin.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @sle_smin_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @sle_smin_contextual(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp sle i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smin.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @sle_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @sle_smin_contextual_commuted(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp sle i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smin.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @sgt_smin_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @sgt_smin_contextual(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp sgt i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smin.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @sgt_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @sgt_smin_contextual_commuted(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp sgt i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smin.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @sge_smin_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @sge_smin_contextual(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp sge i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smin.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @sge_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @sge_smin_contextual_commuted(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp sge i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.smin.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+declare void @use_v2i1(<2 x i1> %c)
+
+; icmp pred smin(X, Y), X
+define void @eq_smin_v2i32(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: @eq_smin_v2i32(
+; CHECK-NEXT:    [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt <2 x i32> [[X]], [[Y]]
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP1]])
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> <i1 true, i1 true>)
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> zeroinitializer)
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sle <2 x i32> [[X]], [[Y]]
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], [[X]]
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule <2 x i32> [[COND]], [[X]]
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt <2 x i32> [[COND]], [[X]]
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge <2 x i32> [[COND]], [[X]]
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp sle <2 x i32> [[X]], [[Y]]
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp sgt <2 x i32> [[X]], [[Y]]
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP10]])
+; CHECK-NEXT:    ret void
+;
+  %cond = call <2 x i32> @llvm.smin.v2i32(<2 x i32> %x, <2 x i32> %y)
+  %cmp1 = icmp slt <2 x i32> %cond, %x
+  call void @use_v2i1(<2 x i1> %cmp1)
+  %cmp2 = icmp sle <2 x i32> %cond, %x
+  call void @use_v2i1(<2 x i1> %cmp2)
+  %cmp3 = icmp sgt <2 x i32> %cond, %x
+  call void @use_v2i1(<2 x i1> %cmp3)
+  %cmp4 = icmp sge <2 x i32> %cond, %x
+  call void @use_v2i1(<2 x i1> %cmp4)
+  %cmp5 = icmp ult <2 x i32> %cond, %x
+  call void @use_v2i1(<2 x i1> %cmp5)
+  %cmp6 = icmp ule <2 x i32> %cond, %x
+  call void @use_v2i1(<2 x i1> %cmp6)
+  %cmp7 = icmp ugt <2 x i32> %cond, %x
+  call void @use_v2i1(<2 x i1> %cmp7)
+  %cmp8 = icmp uge <2 x i32> %cond, %x
+  call void @use_v2i1(<2 x i1> %cmp8)
+  %cmp9 = icmp eq <2 x i32> %cond, %x
+  call void @use_v2i1(<2 x i1> %cmp9)
+  %cmp10 = icmp ne <2 x i32> %cond, %x
+  call void @use_v2i1(<2 x i1> %cmp10)
+  ret void
+}
+
+; icmp pred smin(C1, Y), C2 where C1 == C2
+define void @eq_smin_v2i32_constant(<2 x i32> %y) {
+; CHECK-LABEL: @eq_smin_v2i32_constant(
+; CHECK-NEXT:    [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> <i32 10, i32 10>)
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt <2 x i32> [[Y]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP1]])
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> <i1 true, i1 true>)
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> zeroinitializer)
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 9, i32 9>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ult <2 x i32> [[COND]], <i32 11, i32 11>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp ugt <2 x i32> [[COND]], <i32 9, i32 9>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp sgt <2 x i32> [[Y]], <i32 9, i32 9>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp slt <2 x i32> [[Y]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP10]])
+; CHECK-NEXT:    ret void
+;
+  %cond = call <2 x i32> @llvm.smin.v2i32(<2 x i32> <i32 10, i32 10>, <2 x i32> %y)
+  %cmp1 = icmp slt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp1)
+  %cmp2 = icmp sle <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp2)
+  %cmp3 = icmp sgt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp3)
+  %cmp4 = icmp sge <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp4)
+  %cmp5 = icmp ult <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp5)
+  %cmp6 = icmp ule <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp6)
+  %cmp7 = icmp ugt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp7)
+  %cmp8 = icmp uge <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp8)
+  %cmp9 = icmp eq <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp9)
+  %cmp10 = icmp ne <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp10)
+  ret void
+}
+
+; icmp pred smin(C1, Y), C2 where C1 < C2
+define void @slt_smin_v2i32_constant(<2 x i32> %y) {
+; CHECK-LABEL: @slt_smin_v2i32_constant(
+; CHECK-NEXT:    [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> <i32 5, i32 5>)
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> <i1 true, i1 true>)
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> <i1 true, i1 true>)
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> zeroinitializer)
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> zeroinitializer)
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ult <2 x i32> [[COND]], <i32 11, i32 11>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp ugt <2 x i32> [[COND]], <i32 9, i32 9>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP8]])
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> zeroinitializer)
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> <i1 true, i1 true>)
+; CHECK-NEXT:    ret void
+;
+  %cond = call <2 x i32> @llvm.smin.v2i32(<2 x i32> <i32 5, i32 5>, <2 x i32> %y)
+  %cmp1 = icmp slt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp1)
+  %cmp2 = icmp sle <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp2)
+  %cmp3 = icmp sgt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp3)
+  %cmp4 = icmp sge <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp4)
+  %cmp5 = icmp ult <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp5)
+  %cmp6 = icmp ule <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp6)
+  %cmp7 = icmp ugt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp7)
+  %cmp8 = icmp uge <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp8)
+  %cmp9 = icmp eq <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp9)
+  %cmp10 = icmp ne <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp10)
+  ret void
+}
+
+; icmp pred smin(C1, Y), C2 where C1 <= C2
+define void @sle_smin_v2i32_constant(<2 x i32> %y) {
+; CHECK-LABEL: @sle_smin_v2i32_constant(
+; CHECK-NEXT:    [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> <i32 5, i32 10>)
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt <2 x i32> [[COND]], <i32 11, i32 11>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 9, i32 9>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ult <2 x i32> [[COND]], <i32 11, i32 11>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp ugt <2 x i32> [[COND]], <i32 9, i32 9>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP10]])
+; CHECK-NEXT:    ret void
+;
+  %cond = call <2 x i32> @llvm.smin.v2i32(<2 x i32> <i32 5, i32 10>, <2 x i32> %y)
+  %cmp1 = icmp slt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp1)
+  %cmp2 = icmp sle <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp2)
+  %cmp3 = icmp sgt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp3)
+  %cmp4 = icmp sge <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp4)
+  %cmp5 = icmp ult <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp5)
+  %cmp6 = icmp ule <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp6)
+  %cmp7 = icmp ugt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp7)
+  %cmp8 = icmp uge <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp8)
+  %cmp9 = icmp eq <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp9)
+  %cmp10 = icmp ne <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp10)
+  ret void
+}
+
+; icmp pred smin(C1, Y), C2 where C1 > C2
+define void @sgt_smin_v2i32_constant(<2 x i32> %y) {
+; CHECK-LABEL: @sgt_smin_v2i32_constant(
+; CHECK-NEXT:    [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> <i32 15, i32 15>)
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt <2 x i32> [[COND]], <i32 11, i32 11>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 9, i32 9>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ult <2 x i32> [[COND]], <i32 11, i32 11>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp ugt <2 x i32> [[COND]], <i32 9, i32 9>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP10]])
+; CHECK-NEXT:    ret void
+;
+  %cond = call <2 x i32> @llvm.smin.v2i32(<2 x i32> <i32 15, i32 15>, <2 x i32> %y)
+  %cmp1 = icmp slt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp1)
+  %cmp2 = icmp sle <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp2)
+  %cmp3 = icmp sgt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp3)
+  %cmp4 = icmp sge <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp4)
+  %cmp5 = icmp ult <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp5)
+  %cmp6 = icmp ule <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp6)
+  %cmp7 = icmp ugt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp7)
+  %cmp8 = icmp uge <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp8)
+  %cmp9 = icmp eq <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp9)
+  %cmp10 = icmp ne <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp10)
+  ret void
+}
+
+; icmp pred smin(C1, Y), C2 where C1 >= C2
+define void @sge_smin_v2i32_constant(<2 x i32> %y) {
+; CHECK-LABEL: @sge_smin_v2i32_constant(
+; CHECK-NEXT:    [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> <i32 15, i32 10>)
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt <2 x i32> [[COND]], <i32 11, i32 11>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 9, i32 9>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ult <2 x i32> [[COND]], <i32 11, i32 11>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp ugt <2 x i32> [[COND]], <i32 9, i32 9>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP10]])
+; CHECK-NEXT:    ret void
+;
+  %cond = call <2 x i32> @llvm.smin.v2i32(<2 x i32> <i32 15, i32 10>, <2 x i32> %y)
+  %cmp1 = icmp slt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp1)
+  %cmp2 = icmp sle <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp2)
+  %cmp3 = icmp sgt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp3)
+  %cmp4 = icmp sge <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp4)
+  %cmp5 = icmp ult <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp5)
+  %cmp6 = icmp ule <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp6)
+  %cmp7 = icmp ugt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp7)
+  %cmp8 = icmp uge <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp8)
+  %cmp9 = icmp eq <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp9)
+  %cmp10 = icmp ne <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp10)
+  ret void
+}
+
+; icmp pred smin(C1, Y), C2 where (icmp pred' C1, C2) is not a constant splat for all pred'
+define void @unknown_smin_v2i32_constant(<2 x i32> %y) {
+; CHECK-LABEL: @unknown_smin_v2i32_constant(
+; CHECK-NEXT:    [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> <i32 5, i32 15>)
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt <2 x i32> [[COND]], <i32 11, i32 11>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 9, i32 9>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ult <2 x i32> [[COND]], <i32 11, i32 11>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp ugt <2 x i32> [[COND]], <i32 9, i32 9>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP10]])
+; CHECK-NEXT:    ret void
+;
+  %cond = call <2 x i32> @llvm.smin.v2i32(<2 x i32> <i32 5, i32 15>, <2 x i32> %y)
+  %cmp1 = icmp slt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp1)
+  %cmp2 = icmp sle <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp2)
+  %cmp3 = icmp sgt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp3)
+  %cmp4 = icmp sge <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp4)
+  %cmp5 = icmp ult <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp5)
+  %cmp6 = icmp ule <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp6)
+  %cmp7 = icmp ugt <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp7)
+  %cmp8 = icmp uge <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp8)
+  %cmp9 = icmp eq <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp9)
+  %cmp10 = icmp ne <2 x i32> %cond, <i32 10, i32 10>
+  call void @use_v2i1(<2 x i1> %cmp10)
+  ret void
+}
+
+; Test cases from PR62898
+
+define i1 @smin_or_bitwise(i32 %x) {
+; CHECK-LABEL: @smin_or_bitwise(
+; CHECK-NEXT:    [[COND:%.*]] = tail call i32 @llvm.smin.i32(i32 [[X:%.*]], i32 1)
+; CHECK-NEXT:    [[LOBIT:%.*]] = or i32 [[COND]], [[X]]
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp slt i32 [[LOBIT]], 0
+; CHECK-NEXT:    ret i1 [[TOBOOL]]
+;
+  %cond = tail call i32 @llvm.smin.i32(i32 %x, i32 1)
+  %lobit = or i32 %cond, %x
+  %tobool = icmp slt i32 %lobit, 0
+  ret i1 %tobool
+}
+
+define i1 @smin_and_bitwise(i32 %x) {
+; CHECK-LABEL: @smin_and_bitwise(
+; CHECK-NEXT:    [[COND:%.*]] = tail call i32 @llvm.smin.i32(i32 [[X:%.*]], i32 1)
+; CHECK-NEXT:    [[LOBIT:%.*]] = and i32 [[COND]], [[X]]
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp slt i32 [[LOBIT]], 0
+; CHECK-NEXT:    ret i1 [[TOBOOL]]
+;
+  %cond = tail call i32 @llvm.smin.i32(i32 %x, i32 1)
+  %lobit = and i32 %cond, %x
+  %tobool = icmp slt i32 %lobit, 0
+  ret i1 %tobool
+}
+
+declare i32 @llvm.smin.i32(i32, i32)
+declare <2 x i32> @llvm.smin.v2i32(<2 x i32>, <2 x i32>)
diff --git a/llvm/test/Transforms/InstCombine/umax-icmp.ll b/llvm/test/Transforms/InstCombine/umax-icmp.ll
index 8dccc05ac0c7d7a..16676874143ee9e 100644
--- a/llvm/test/Transforms/InstCombine/umax-icmp.ll
+++ b/llvm/test/Transforms/InstCombine/umax-icmp.ll
@@ -232,3 +232,596 @@ define i1 @ugt_umax4(i32 %a, i32 %y) {
   ret i1 %cmp2
 }
 
+declare void @use(i1 %c)
+
+define void @eq_umax_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @eq_umax_contextual(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp eq i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umax.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @eq_umax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @eq_umax_contextual_commuted(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umax.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp eq i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umax.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @ult_umax_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @ult_umax_contextual(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp ult i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umax.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @ult_umax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @ult_umax_contextual_commuted(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umax.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp ult i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umax.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @ule_umax_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @ule_umax_contextual(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp ugt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp ule i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umax.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @ule_umax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @ule_umax_contextual_commuted(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp ugt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umax.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp ule i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umax.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @ugt_umax_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @ugt_umax_contextual(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp ugt i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umax.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @ugt_umax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @ugt_umax_contextual_commuted(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umax.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp ugt i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umax.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @uge_umax_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @uge_umax_contextual(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp uge i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umax.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @uge_umax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @uge_umax_contextual_commuted(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umax.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp uge i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umax.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+declare i32 @llvm.umax.i32(i32, i32)
diff --git a/llvm/test/Transforms/InstCombine/umin-icmp.ll b/llvm/test/Transforms/InstCombine/umin-icmp.ll
index ce3f72969f9d2af..8cd0a595b6f79a9 100644
--- a/llvm/test/Transforms/InstCombine/umin-icmp.ll
+++ b/llvm/test/Transforms/InstCombine/umin-icmp.ll
@@ -232,3 +232,596 @@ define i1 @ult_umin4(i32 %a, i32 %y) {
   ret i1 %cmp2
 }
 
+declare void @use(i1 %c)
+
+define void @eq_umin_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @eq_umin_contextual(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp eq i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umin.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @eq_umin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @eq_umin_contextual_commuted(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umin.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp eq i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umin.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @ult_umin_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @ult_umin_contextual(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp ult i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umin.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @ult_umin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @ult_umin_contextual_commuted(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umin.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp ult i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umin.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @ule_umin_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @ule_umin_contextual(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp ugt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp ule i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umin.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @ule_umin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @ule_umin_contextual_commuted(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp ugt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umin.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp ule i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umin.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @ugt_umin_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @ugt_umin_contextual(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp ugt i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umin.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @ugt_umin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @ugt_umin_contextual_commuted(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umin.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp ugt i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umin.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @uge_umin_contextual(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @uge_umin_contextual(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp uge i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umin.i32(i32 %x, i32 %y)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+define void @uge_umin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @uge_umin_contextual_commuted(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.umin.i32(i32 [[Y:%.*]], i32 [[X]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP6]])
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP9]])
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 [[CMP10]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp uge i32 %x, %z
+  br i1 %cmp, label %if, label %end
+if:
+  %cond = call i32 @llvm.umin.i32(i32 %y, i32 %x)
+  %cmp1 = icmp slt i32 %cond, %z
+  call void @use(i1 %cmp1)
+  %cmp2 = icmp sle i32 %cond, %z
+  call void @use(i1 %cmp2)
+  %cmp3 = icmp sgt i32 %cond, %z
+  call void @use(i1 %cmp3)
+  %cmp4 = icmp sge i32 %cond, %z
+  call void @use(i1 %cmp4)
+  %cmp5 = icmp ult i32 %cond, %z
+  call void @use(i1 %cmp5)
+  %cmp6 = icmp ule i32 %cond, %z
+  call void @use(i1 %cmp6)
+  %cmp7 = icmp ugt i32 %cond, %z
+  call void @use(i1 %cmp7)
+  %cmp8 = icmp uge i32 %cond, %z
+  call void @use(i1 %cmp8)
+  %cmp9 = icmp eq i32 %cond, %z
+  call void @use(i1 %cmp9)
+  %cmp10 = icmp ne i32 %cond, %z
+  call void @use(i1 %cmp10)
+  ret void
+end:
+  ret void
+}
+
+declare i32 @llvm.umin.i32(i32, i32)

>From 67896928c83375023af8704d50eb0c8e84e88902 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 11 Sep 2023 02:26:48 +0800
Subject: [PATCH 54/62] [InstCombine] Generalize foldICmpWithMinMax

This patch generalizes the fold of `icmp pred min/max(X, Y), Z` to address the issue https://github.com/llvm/llvm-project/issues/62898.

For example, we can fold `smin(X, Y) < Z` into `X < Z` when `Y > Z` is implied by constant folds/invariants/dom conditions.

Alive2 (with `--disable-undef-input` due to the limitation of --smt-to=10000): https://alive2.llvm.org/ce/z/rB7qLc
You can run the standalone translation validation tool `alive-tv` locally to verify these transformations.
```
alive-tv transforms.ll --smt-to=600000 --exit-on-error
```

Reviewed By: goldstein.w.n

Differential Revision: https://reviews.llvm.org/D156238
---
 .../InstCombine/InstCombineCompares.cpp       | 193 +++++++++++-------
 .../InstCombine/InstCombineInternal.h         |   3 +
 llvm/test/Transforms/InstCombine/smax-icmp.ll | 100 ++++-----
 llvm/test/Transforms/InstCombine/smin-icmp.ll | 124 +++++------
 llvm/test/Transforms/InstCombine/umax-icmp.ll | 100 ++++-----
 llvm/test/Transforms/InstCombine/umin-icmp.ll | 100 ++++-----
 .../Transforms/LoopVectorize/X86/pr23997.ll   |  39 ++--
 .../LoopVectorize/interleaved-accesses.ll     |   5 +-
 8 files changed, 323 insertions(+), 341 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..e1b879b4c39016c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4964,88 +4964,135 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
   return nullptr;
 }
 
-/// Fold icmp Pred min|max(X, Y), X.
-static Instruction *foldICmpWithMinMax(ICmpInst &Cmp) {
-  ICmpInst::Predicate Pred = Cmp.getPredicate();
-  Value *Op0 = Cmp.getOperand(0);
-  Value *X = Cmp.getOperand(1);
-
-  // Canonicalize minimum or maximum operand to LHS of the icmp.
-  if (match(X, m_c_SMin(m_Specific(Op0), m_Value())) ||
-      match(X, m_c_SMax(m_Specific(Op0), m_Value())) ||
-      match(X, m_c_UMin(m_Specific(Op0), m_Value())) ||
-      match(X, m_c_UMax(m_Specific(Op0), m_Value()))) {
-    std::swap(Op0, X);
-    Pred = Cmp.getSwappedPredicate();
-  }
-
-  Value *Y;
-  if (match(Op0, m_c_SMin(m_Specific(X), m_Value(Y)))) {
-    // smin(X, Y)  == X --> X s<= Y
-    // smin(X, Y) s>= X --> X s<= Y
-    if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_SGE)
-      return new ICmpInst(ICmpInst::ICMP_SLE, X, Y);
-
-    // smin(X, Y) != X --> X s> Y
-    // smin(X, Y) s< X --> X s> Y
-    if (Pred == CmpInst::ICMP_NE || Pred == CmpInst::ICMP_SLT)
-      return new ICmpInst(ICmpInst::ICMP_SGT, X, Y);
-
-    // These cases should be handled in InstSimplify:
-    // smin(X, Y) s<= X --> true
-    // smin(X, Y) s> X --> false
+/// Fold icmp Pred min|max(X, Y), Z.
+Instruction *
+InstCombinerImpl::foldICmpWithMinMaxImpl(Instruction &I,
+                                         MinMaxIntrinsic *MinMax, Value *Z,
+                                         ICmpInst::Predicate Pred) {
+  Value *X = MinMax->getLHS();
+  Value *Y = MinMax->getRHS();
+  if (ICmpInst::isSigned(Pred) && !MinMax->isSigned())
     return nullptr;
-  }
-
-  if (match(Op0, m_c_SMax(m_Specific(X), m_Value(Y)))) {
-    // smax(X, Y)  == X --> X s>= Y
-    // smax(X, Y) s<= X --> X s>= Y
-    if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_SLE)
-      return new ICmpInst(ICmpInst::ICMP_SGE, X, Y);
-
-    // smax(X, Y) != X --> X s< Y
-    // smax(X, Y) s> X --> X s< Y
-    if (Pred == CmpInst::ICMP_NE || Pred == CmpInst::ICMP_SGT)
-      return new ICmpInst(ICmpInst::ICMP_SLT, X, Y);
-
-    // These cases should be handled in InstSimplify:
-    // smax(X, Y) s>= X --> true
-    // smax(X, Y) s< X --> false
+  if (ICmpInst::isUnsigned(Pred) && MinMax->isSigned())
+    return nullptr;
+  SimplifyQuery Q = SQ.getWithInstruction(&I);
+  auto IsCondKnownTrue = [](Value *Val) -> std::optional<bool> {
+    if (!Val)
+      return std::nullopt;
+    if (match(Val, m_One()))
+      return true;
+    if (match(Val, m_Zero()))
+      return false;
+    return std::nullopt;
+  };
+  auto CmpXZ = IsCondKnownTrue(simplifyICmpInst(Pred, X, Z, Q));
+  auto CmpYZ = IsCondKnownTrue(simplifyICmpInst(Pred, Y, Z, Q));
+  if (!CmpXZ.has_value() && !CmpYZ.has_value())
     return nullptr;
+  if (!CmpXZ.has_value()) {
+    std::swap(X, Y);
+    std::swap(CmpXZ, CmpYZ);
   }
 
-  if (match(Op0, m_c_UMin(m_Specific(X), m_Value(Y)))) {
-    // umin(X, Y)  == X --> X u<= Y
-    // umin(X, Y) u>= X --> X u<= Y
-    if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_UGE)
-      return new ICmpInst(ICmpInst::ICMP_ULE, X, Y);
-
-    // umin(X, Y) != X --> X u> Y
-    // umin(X, Y) u< X --> X u> Y
-    if (Pred == CmpInst::ICMP_NE || Pred == CmpInst::ICMP_ULT)
-      return new ICmpInst(ICmpInst::ICMP_UGT, X, Y);
+  switch (Pred) {
+  case ICmpInst::ICMP_EQ:
+  case ICmpInst::ICMP_NE: {
+    // If X == Z:
+    //     Expr       Result
+    // min(X, Y) == Z X <= Y
+    // max(X, Y) == Z X >= Y
+    // min(X, Y) != Z X > Y
+    // max(X, Y) != Z X < Y
+    if ((Pred == ICmpInst::ICMP_EQ) == *CmpXZ) {
+      ICmpInst::Predicate NewPred =
+          ICmpInst::getNonStrictPredicate(MinMax->getPredicate());
+      if (Pred == ICmpInst::ICMP_NE)
+        NewPred = ICmpInst::getInversePredicate(NewPred);
+      return ICmpInst::Create(Instruction::ICmp, NewPred, X, Y);
+    }
+    // Otherwise (X != Z, nofold):
+    //       Expr      Result
+    // min(X, Y) == Z X > Y || Y == Z
+    // max(X, Y) == Z X < Y || Y == Z
+    // min(X, Y) != Z X <= Y && Y != Z
+    // max(X, Y) != Z X >= Y && Y != Z
+    break;
+  }
+  case ICmpInst::ICMP_SLT:
+  case ICmpInst::ICMP_ULT:
+  case ICmpInst::ICMP_SLE:
+  case ICmpInst::ICMP_ULE:
+  case ICmpInst::ICMP_SGT:
+  case ICmpInst::ICMP_UGT:
+  case ICmpInst::ICMP_SGE:
+  case ICmpInst::ICMP_UGE: {
+    auto FoldIntoConstant = [&](bool Value) {
+      return replaceInstUsesWith(
+          I, Constant::getIntegerValue(
+                 I.getType(), APInt(1U, static_cast<uint64_t>(Value))));
+    };
+    auto FoldIntoCmpYZ = [&]() -> Instruction * {
+      if (CmpYZ.has_value())
+        return FoldIntoConstant(*CmpYZ);
+      return ICmpInst::Create(Instruction::ICmp, Pred, Y, Z);
+    };
 
-    // These cases should be handled in InstSimplify:
-    // umin(X, Y) u<= X --> true
-    // umin(X, Y) u> X --> false
-    return nullptr;
+    bool IsSame = MinMax->getPredicate() == ICmpInst::getStrictPredicate(Pred);
+    if (*CmpXZ) {
+      if (IsSame) {
+        //      Expr        Fact    Result
+        // min(X, Y) < Z    X < Z   true
+        // min(X, Y) <= Z   X <= Z  true
+        // max(X, Y) > Z    X > Z   true
+        // max(X, Y) >= Z   X >= Z  true
+        return FoldIntoConstant(true);
+      } else {
+        //      Expr        Fact    Result
+        // max(X, Y) < Z    X < Z   Y < Z
+        // max(X, Y) <= Z   X <= Z  Y <= Z
+        // min(X, Y) > Z    X > Z   Y > Z
+        // min(X, Y) >= Z   X >= Z  Y >= Z
+        return FoldIntoCmpYZ();
+      }
+    } else {
+      if (IsSame) {
+        //      Expr        Fact    Result
+        // min(X, Y) < Z    X >= Z  Y < Z
+        // min(X, Y) <= Z   X > Z   Y <= Z
+        // max(X, Y) > Z    X <= Z  Y > Z
+        // max(X, Y) >= Z   X < Z   Y >= Z
+        return FoldIntoCmpYZ();
+      } else {
+        //      Expr        Fact    Result
+        // max(X, Y) < Z    X >= Z  false
+        // max(X, Y) <= Z   X > Z   false
+        // min(X, Y) > Z    X <= Z  false
+        // min(X, Y) >= Z   X < Z   false
+        return FoldIntoConstant(false);
+      }
+    }
+    break;
+  }
+  default:
+    break;
   }
 
-  if (match(Op0, m_c_UMax(m_Specific(X), m_Value(Y)))) {
-    // umax(X, Y)  == X --> X u>= Y
-    // umax(X, Y) u<= X --> X u>= Y
-    if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_ULE)
-      return new ICmpInst(ICmpInst::ICMP_UGE, X, Y);
+  return nullptr;
+}
+Instruction *InstCombinerImpl::foldICmpWithMinMax(ICmpInst &Cmp) {
+  ICmpInst::Predicate Pred = Cmp.getPredicate();
+  Value *Lhs = Cmp.getOperand(0);
+  Value *Rhs = Cmp.getOperand(1);
 
-    // umax(X, Y) != X --> X u< Y
-    // umax(X, Y) u> X --> X u< Y
-    if (Pred == CmpInst::ICMP_NE || Pred == CmpInst::ICMP_UGT)
-      return new ICmpInst(ICmpInst::ICMP_ULT, X, Y);
+  if (MinMaxIntrinsic *MinMax = dyn_cast<MinMaxIntrinsic>(Lhs)) {
+    if (Instruction *Res = foldICmpWithMinMaxImpl(Cmp, MinMax, Rhs, Pred))
+      return Res;
+  }
 
-    // These cases should be handled in InstSimplify:
-    // umax(X, Y) u>= X --> true
-    // umax(X, Y) u< X --> false
-    return nullptr;
+  if (MinMaxIntrinsic *MinMax = dyn_cast<MinMaxIntrinsic>(Rhs)) {
+    if (Instruction *Res = foldICmpWithMinMaxImpl(
+            Cmp, MinMax, Lhs, ICmpInst::getSwappedPredicate(Pred)))
+      return Res;
   }
 
   return nullptr;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index e9e8e90d4802bec..e742564c1300acc 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -611,6 +611,9 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
   Instruction *foldICmpInstWithConstantAllowUndef(ICmpInst &Cmp,
                                                   const APInt &C);
   Instruction *foldICmpBinOp(ICmpInst &Cmp, const SimplifyQuery &SQ);
+  Instruction *foldICmpWithMinMaxImpl(Instruction &I, MinMaxIntrinsic *MinMax,
+                                      Value *Z, ICmpInst::Predicate Pred);
+  Instruction *foldICmpWithMinMax(ICmpInst &Cmp);
   Instruction *foldICmpEquality(ICmpInst &Cmp);
   Instruction *foldIRemByPowerOfTwoToBitTest(ICmpInst &I);
   Instruction *foldSignBitTest(ICmpInst &I);
diff --git a/llvm/test/Transforms/InstCombine/smax-icmp.ll b/llvm/test/Transforms/InstCombine/smax-icmp.ll
index 9cf64a9d803d664..f8df92d5470e19d 100644
--- a/llvm/test/Transforms/InstCombine/smax-icmp.ll
+++ b/llvm/test/Transforms/InstCombine/smax-icmp.ll
@@ -64,11 +64,11 @@ define i1 @eq_smax4(i32 %a, i32 %y) {
   ret i1 %cmp2
 }
 
-; smax(X, Y) <= X --> X >= Y
+; smax(X, Y) <= X --> Y <= X
 
 define i1 @sle_smax1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @sle_smax1(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp sgt i32 %x, %y
@@ -81,7 +81,7 @@ define i1 @sle_smax1(i32 %x, i32 %y) {
 
 define i1 @sle_smax2(i32 %x, i32 %y) {
 ; CHECK-LABEL: @sle_smax2(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp sgt i32 %y, %x
@@ -176,11 +176,11 @@ define i1 @ne_smax4(i32 %a, i32 %y) {
   ret i1 %cmp2
 }
 
-; smax(X, Y) > X --> X < Y
+; smax(X, Y) > X --> Y > X
 
 define i1 @sgt_smax1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @sgt_smax1(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp sgt i32 %x, %y
@@ -193,7 +193,7 @@ define i1 @sgt_smax1(i32 %x, i32 %y) {
 
 define i1 @sgt_smax2(i32 %x, i32 %y) {
 ; CHECK-LABEL: @sgt_smax2(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp sgt i32 %y, %x
@@ -240,14 +240,12 @@ define void @eq_smax_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
 ; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
@@ -256,9 +254,9 @@ define void @eq_smax_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
 ; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
-; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp sge i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
-; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp slt i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP10]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       end:
@@ -299,14 +297,12 @@ define void @eq_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
 ; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
@@ -315,9 +311,9 @@ define void @eq_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
 ; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
-; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp sge i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
-; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp slt i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP10]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       end:
@@ -358,13 +354,13 @@ define void @slt_smax_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
@@ -417,13 +413,13 @@ define void @slt_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
@@ -478,9 +474,9 @@ define void @sle_smax_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
@@ -537,9 +533,9 @@ define void @sle_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
@@ -594,14 +590,10 @@ define void @sgt_smax_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
 ; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
@@ -653,14 +645,10 @@ define void @sgt_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
 ; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
@@ -712,14 +700,12 @@ define void @sge_smax_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP2]])
 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
 ; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
@@ -771,14 +757,12 @@ define void @sge_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP1]])
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP2]])
 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
 ; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
diff --git a/llvm/test/Transforms/InstCombine/smin-icmp.ll b/llvm/test/Transforms/InstCombine/smin-icmp.ll
index 69ff8414df2a430..244dad451022ea6 100644
--- a/llvm/test/Transforms/InstCombine/smin-icmp.ll
+++ b/llvm/test/Transforms/InstCombine/smin-icmp.ll
@@ -63,11 +63,11 @@ define i1 @eq_smin4(i32 %a, i32 %y) {
   ret i1 %cmp2
 }
 
-; smin(X, Y) >= X --> X <= Y
+; smin(X, Y) >= X --> Y >= X
 
 define i1 @sge_smin1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @sge_smin1(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp slt i32 %x, %y
@@ -80,7 +80,7 @@ define i1 @sge_smin1(i32 %x, i32 %y) {
 
 define i1 @sge_smin2(i32 %x, i32 %y) {
 ; CHECK-LABEL: @sge_smin2(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp slt i32 %y, %x
@@ -175,11 +175,11 @@ define i1 @ne_smin4(i32 %a, i32 %y) {
   ret i1 %cmp2
 }
 
-; smin(X, Y) < X --> X > Y
+; smin(X, Y) < X --> Y < X
 
 define i1 @slt_smin1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @slt_smin1(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp slt i32 %x, %y
@@ -192,7 +192,7 @@ define i1 @slt_smin1(i32 %x, i32 %y) {
 
 define i1 @slt_smin2(i32 %x, i32 %y) {
 ; CHECK-LABEL: @slt_smin2(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp slt i32 %y, %x
@@ -339,13 +339,11 @@ define void @eq_smin_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
@@ -355,9 +353,9 @@ define void @eq_smin_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
 ; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
-; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp sle i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
-; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp sgt i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP10]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       end:
@@ -398,13 +396,11 @@ define void @eq_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
@@ -414,9 +410,9 @@ define void @eq_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
 ; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
-; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp sle i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
-; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp sgt i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP10]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       end:
@@ -457,14 +453,10 @@ define void @slt_smin_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
 ; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
@@ -516,14 +508,10 @@ define void @slt_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP4]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
 ; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
@@ -577,10 +565,8 @@ define void @sle_smin_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]])
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
@@ -636,10 +622,8 @@ define void @sle_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]])
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP3]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
@@ -693,13 +677,13 @@ define void @sgt_smin_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
@@ -752,13 +736,13 @@ define void @sgt_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
@@ -811,13 +795,13 @@ define void @sge_smin_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP2]])
 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
@@ -870,13 +854,13 @@ define void @sge_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]
 ; CHECK:       if:
 ; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP2]])
 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
@@ -929,11 +913,11 @@ declare void @use_v2i1(<2 x i1> %c)
 define void @eq_smin_v2i32(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: @eq_smin_v2i32(
 ; CHECK-NEXT:    [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]])
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt <2 x i32> [[X]], [[Y]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt <2 x i32> [[Y]], [[X]]
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP1]])
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> <i1 true, i1 true>)
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> zeroinitializer)
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sle <2 x i32> [[X]], [[Y]]
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge <2 x i32> [[Y]], [[X]]
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], [[X]]
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP5]])
@@ -981,7 +965,7 @@ define void @eq_smin_v2i32_constant(<2 x i32> %y) {
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP1]])
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> <i1 true, i1 true>)
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> zeroinitializer)
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 9, i32 9>
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sgt <2 x i32> [[Y]], <i32 9, i32 9>
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], <i32 10, i32 10>
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP5]])
@@ -1071,10 +1055,8 @@ define void @sle_smin_v2i32_constant(<2 x i32> %y) {
 ; CHECK-NEXT:    [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> <i32 5, i32 10>)
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt <2 x i32> [[COND]], <i32 10, i32 10>
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt <2 x i32> [[COND]], <i32 11, i32 11>
-; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 10, i32 10>
-; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP3]])
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> <i1 true, i1 true>)
+; CHECK-NEXT:    call void @use_v2i1(<2 x i1> zeroinitializer)
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 9, i32 9>
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], <i32 10, i32 10>
@@ -1119,13 +1101,13 @@ define void @sle_smin_v2i32_constant(<2 x i32> %y) {
 define void @sgt_smin_v2i32_constant(<2 x i32> %y) {
 ; CHECK-LABEL: @sgt_smin_v2i32_constant(
 ; CHECK-NEXT:    [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> <i32 15, i32 15>)
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt <2 x i32> [[Y]], <i32 10, i32 10>
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP1]])
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt <2 x i32> [[COND]], <i32 11, i32 11>
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt <2 x i32> [[Y]], <i32 11, i32 11>
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP2]])
-; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt <2 x i32> [[Y]], <i32 10, i32 10>
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 9, i32 9>
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sgt <2 x i32> [[Y]], <i32 9, i32 9>
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], <i32 10, i32 10>
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP5]])
@@ -1169,13 +1151,13 @@ define void @sgt_smin_v2i32_constant(<2 x i32> %y) {
 define void @sge_smin_v2i32_constant(<2 x i32> %y) {
 ; CHECK-LABEL: @sge_smin_v2i32_constant(
 ; CHECK-NEXT:    [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> <i32 15, i32 10>)
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt <2 x i32> [[COND]], <i32 10, i32 10>
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt <2 x i32> [[Y]], <i32 10, i32 10>
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP1]])
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt <2 x i32> [[COND]], <i32 11, i32 11>
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP2]])
 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 10, i32 10>
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP3]])
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp sgt <2 x i32> [[COND]], <i32 9, i32 9>
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp sgt <2 x i32> [[Y]], <i32 9, i32 9>
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], <i32 10, i32 10>
 ; CHECK-NEXT:    call void @use_v2i1(<2 x i1> [[CMP5]])
diff --git a/llvm/test/Transforms/InstCombine/umax-icmp.ll b/llvm/test/Transforms/InstCombine/umax-icmp.ll
index 16676874143ee9e..d6706374c49897c 100644
--- a/llvm/test/Transforms/InstCombine/umax-icmp.ll
+++ b/llvm/test/Transforms/InstCombine/umax-icmp.ll
@@ -64,11 +64,11 @@ define i1 @eq_umax4(i32 %a, i32 %y) {
   ret i1 %cmp2
 }
 
-; umax(X, Y) <= X --> X >= Y
+; umax(X, Y) <= X --> Y <= X
 
 define i1 @ule_umax1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @ule_umax1(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp ugt i32 %x, %y
@@ -81,7 +81,7 @@ define i1 @ule_umax1(i32 %x, i32 %y) {
 
 define i1 @ule_umax2(i32 %x, i32 %y) {
 ; CHECK-LABEL: @ule_umax2(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp ugt i32 %y, %x
@@ -176,11 +176,11 @@ define i1 @ne_umax4(i32 %a, i32 %y) {
   ret i1 %cmp2
 }
 
-; umax(X, Y) > X --> X < Y
+; umax(X, Y) > X --> Y > X
 
 define i1 @ugt_umax1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @ugt_umax1(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp ugt i32 %x, %y
@@ -193,7 +193,7 @@ define i1 @ugt_umax1(i32 %x, i32 %y) {
 
 define i1 @ugt_umax2(i32 %x, i32 %y) {
 ; CHECK-LABEL: @ugt_umax2(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp ugt i32 %y, %x
@@ -248,17 +248,15 @@ define void @eq_umax_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP8]])
-; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp uge i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
-; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ult i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP10]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       end:
@@ -307,17 +305,15 @@ define void @eq_umax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP8]])
-; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp uge i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
-; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ult i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP10]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       end:
@@ -366,13 +362,13 @@ define void @ult_umax_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
 ; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
@@ -425,13 +421,13 @@ define void @ult_umax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
 ; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
@@ -486,9 +482,9 @@ define void @ule_umax_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
 ; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
@@ -545,9 +541,9 @@ define void @ule_umax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
 ; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
@@ -602,14 +598,10 @@ define void @ugt_umax_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
 ; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
@@ -661,14 +653,10 @@ define void @ugt_umax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
 ; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
@@ -720,14 +708,12 @@ define void @uge_umax_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP6]])
 ; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
 ; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
@@ -779,14 +765,12 @@ define void @uge_umax_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP5]])
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP6]])
 ; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
 ; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
diff --git a/llvm/test/Transforms/InstCombine/umin-icmp.ll b/llvm/test/Transforms/InstCombine/umin-icmp.ll
index 8cd0a595b6f79a9..88a391bf18ca13e 100644
--- a/llvm/test/Transforms/InstCombine/umin-icmp.ll
+++ b/llvm/test/Transforms/InstCombine/umin-icmp.ll
@@ -64,11 +64,11 @@ define i1 @eq_umin4(i32 %a, i32 %y) {
   ret i1 %cmp2
 }
 
-; umin(X, Y) >= X --> X <= Y
+; umin(X, Y) >= X --> Y >= X
 
 define i1 @uge_umin1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @uge_umin1(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp ult i32 %x, %y
@@ -81,7 +81,7 @@ define i1 @uge_umin1(i32 %x, i32 %y) {
 
 define i1 @uge_umin2(i32 %x, i32 %y) {
 ; CHECK-LABEL: @uge_umin2(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp ult i32 %y, %x
@@ -176,11 +176,11 @@ define i1 @ne_umin4(i32 %a, i32 %y) {
   ret i1 %cmp2
 }
 
-; umin(X, Y) < X --> X > Y
+; umin(X, Y) < X --> Y < X
 
 define i1 @ult_umin1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @ult_umin1(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp ult i32 %x, %y
@@ -193,7 +193,7 @@ define i1 @ult_umin1(i32 %x, i32 %y) {
 
 define i1 @ult_umin2(i32 %x, i32 %y) {
 ; CHECK-LABEL: @ult_umin2(
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp1 = icmp ult i32 %y, %x
@@ -248,17 +248,15 @@ define void @eq_umin_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
-; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp ule i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
-; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ugt i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP10]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       end:
@@ -307,17 +305,15 @@ define void @eq_umin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
-; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp ule i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
-; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP10:%.*]] = icmp ugt i32 [[X]], [[Y]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP10]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       end:
@@ -366,14 +362,10 @@ define void @ult_umin_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
 ; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
@@ -425,14 +417,10 @@ define void @ult_umin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP8]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
 ; CHECK-NEXT:    [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]
@@ -486,10 +474,8 @@ define void @ule_umin_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
 ; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
@@ -545,10 +531,8 @@ define void @ule_umin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
 ; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[CMP7]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
 ; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
@@ -602,13 +586,13 @@ define void @ugt_umin_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
 ; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
@@ -661,13 +645,13 @@ define void @ugt_umin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
-; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP6]])
-; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
 ; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
@@ -720,13 +704,13 @@ define void @uge_umin_contextual(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
 ; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP6]])
 ; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
 ; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
@@ -779,13 +763,13 @@ define void @uge_umin_contextual_commuted(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    call void @use(i1 [[CMP3]])
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP4]])
-; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP5]])
 ; CHECK-NEXT:    [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP6]])
 ; CHECK-NEXT:    [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP7]])
-; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]
+; CHECK-NEXT:    [[CMP8:%.*]] = icmp uge i32 [[Y]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP8]])
 ; CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[CMP9]])
diff --git a/llvm/test/Transforms/LoopVectorize/X86/pr23997.ll b/llvm/test/Transforms/LoopVectorize/X86/pr23997.ll
index 04142da386dcb81..3a5db926082f093 100644
--- a/llvm/test/Transforms/LoopVectorize/X86/pr23997.ll
+++ b/llvm/test/Transforms/LoopVectorize/X86/pr23997.ll
@@ -13,11 +13,10 @@ define void @foo(ptr addrspace(1) align 8 dereferenceable_or_null(16), ptr addrs
 ; CHECK-NEXT:    [[DOT10:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[TMP0:%.*]], i64 16
 ; CHECK-NEXT:    [[DOT12:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[TMP1:%.*]], i64 16
 ; CHECK-NEXT:    [[UMAX2:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2:%.*]], i64 1)
-; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[UMAX2]], 16
+; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP2]], 16
 ; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_MEMCHECK:%.*]]
 ; CHECK:       vector.memcheck:
-; CHECK-NEXT:    [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 1)
-; CHECK-NEXT:    [[TMP3:%.*]] = shl i64 [[UMAX]], 3
+; CHECK-NEXT:    [[TMP3:%.*]] = shl i64 [[TMP2]], 3
 ; CHECK-NEXT:    [[TMP4:%.*]] = add i64 [[TMP3]], 16
 ; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr addrspace(1) [[TMP0]], i64 [[TMP4]]
 ; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i8, ptr addrspace(1) [[TMP1]], i64 [[TMP4]]
@@ -32,23 +31,23 @@ define void @foo(ptr addrspace(1) align 8 dereferenceable_or_null(16), ptr addrs
 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
 ; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[DOT12]], i64 [[INDEX]]
 ; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <4 x ptr addrspace(1)>, ptr addrspace(1) [[TMP5]], align 8, !alias.scope !0
-; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[TMP5]], i64 4
-; CHECK-NEXT:    [[WIDE_LOAD3:%.*]] = load <4 x ptr addrspace(1)>, ptr addrspace(1) [[TMP7]], align 8, !alias.scope !0
-; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[TMP5]], i64 8
-; CHECK-NEXT:    [[WIDE_LOAD4:%.*]] = load <4 x ptr addrspace(1)>, ptr addrspace(1) [[TMP9]], align 8, !alias.scope !0
-; CHECK-NEXT:    [[TMP11:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[TMP5]], i64 12
-; CHECK-NEXT:    [[WIDE_LOAD5:%.*]] = load <4 x ptr addrspace(1)>, ptr addrspace(1) [[TMP11]], align 8, !alias.scope !0
-; CHECK-NEXT:    [[TMP13:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[DOT10]], i64 [[INDEX]]
-; CHECK-NEXT:    store <4 x ptr addrspace(1)> [[WIDE_LOAD]], ptr addrspace(1) [[TMP13]], align 8, !alias.scope !3, !noalias !0
-; CHECK-NEXT:    [[TMP15:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[TMP13]], i64 4
-; CHECK-NEXT:    store <4 x ptr addrspace(1)> [[WIDE_LOAD3]], ptr addrspace(1) [[TMP15]], align 8, !alias.scope !3, !noalias !0
-; CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[TMP13]], i64 8
-; CHECK-NEXT:    store <4 x ptr addrspace(1)> [[WIDE_LOAD4]], ptr addrspace(1) [[TMP17]], align 8, !alias.scope !3, !noalias !0
-; CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[TMP13]], i64 12
-; CHECK-NEXT:    store <4 x ptr addrspace(1)> [[WIDE_LOAD5]], ptr addrspace(1) [[TMP19]], align 8, !alias.scope !3, !noalias !0
+; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[TMP5]], i64 4
+; CHECK-NEXT:    [[WIDE_LOAD3:%.*]] = load <4 x ptr addrspace(1)>, ptr addrspace(1) [[TMP6]], align 8, !alias.scope !0
+; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[TMP5]], i64 8
+; CHECK-NEXT:    [[WIDE_LOAD4:%.*]] = load <4 x ptr addrspace(1)>, ptr addrspace(1) [[TMP7]], align 8, !alias.scope !0
+; CHECK-NEXT:    [[TMP8:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[TMP5]], i64 12
+; CHECK-NEXT:    [[WIDE_LOAD5:%.*]] = load <4 x ptr addrspace(1)>, ptr addrspace(1) [[TMP8]], align 8, !alias.scope !0
+; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[DOT10]], i64 [[INDEX]]
+; CHECK-NEXT:    store <4 x ptr addrspace(1)> [[WIDE_LOAD]], ptr addrspace(1) [[TMP9]], align 8, !alias.scope !3, !noalias !0
+; CHECK-NEXT:    [[TMP10:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[TMP9]], i64 4
+; CHECK-NEXT:    store <4 x ptr addrspace(1)> [[WIDE_LOAD3]], ptr addrspace(1) [[TMP10]], align 8, !alias.scope !3, !noalias !0
+; CHECK-NEXT:    [[TMP11:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[TMP9]], i64 8
+; CHECK-NEXT:    store <4 x ptr addrspace(1)> [[WIDE_LOAD4]], ptr addrspace(1) [[TMP11]], align 8, !alias.scope !3, !noalias !0
+; CHECK-NEXT:    [[TMP12:%.*]] = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) [[TMP9]], i64 12
+; CHECK-NEXT:    store <4 x ptr addrspace(1)> [[WIDE_LOAD5]], ptr addrspace(1) [[TMP12]], align 8, !alias.scope !3, !noalias !0
 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16
-; CHECK-NEXT:    [[TMP21:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
-; CHECK-NEXT:    br i1 [[TMP21]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]]
+; CHECK-NEXT:    [[TMP13:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
+; CHECK-NEXT:    br i1 [[TMP13]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]]
 ; CHECK:       middle.block:
 ; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 [[UMAX2]], [[N_VEC]]
 ; CHECK-NEXT:    br i1 [[CMP_N]], label [[LOOPEXIT:%.*]], label [[SCALAR_PH]]
@@ -63,7 +62,7 @@ define void @foo(ptr addrspace(1) align 8 dereferenceable_or_null(16), ptr addrs
 ; CHECK-NEXT:    store ptr addrspace(1) [[V]], ptr addrspace(1) [[DOT20]], align 8
 ; CHECK-NEXT:    [[INDVARS_IV_NEXT4]] = add nuw nsw i64 [[INDVARS_IV3]], 1
 ; CHECK-NEXT:    [[DOT21:%.*]] = icmp ult i64 [[INDVARS_IV_NEXT4]], [[TMP2]]
-; CHECK-NEXT:    br i1 [[DOT21]], label [[LOOP]], label [[LOOPEXIT]], !llvm.loop [[LOOP7:![0-9]+]]
+; CHECK-NEXT:    br i1 [[DOT21]], label [[LOOP]], label [[LOOPEXIT]], !llvm.loop [[LOOP8:![0-9]+]]
 ; CHECK:       loopexit:
 ; CHECK-NEXT:    ret void
 ;
diff --git a/llvm/test/Transforms/LoopVectorize/interleaved-accesses.ll b/llvm/test/Transforms/LoopVectorize/interleaved-accesses.ll
index 4c1a9ffcce0d3ef..6e9a0e7ac0cda7d 100644
--- a/llvm/test/Transforms/LoopVectorize/interleaved-accesses.ll
+++ b/llvm/test/Transforms/LoopVectorize/interleaved-accesses.ll
@@ -481,11 +481,10 @@ for.body:                                         ; preds = %for.body, %entry
 define void @even_load_dynamic_tc(ptr noalias nocapture readonly %A, ptr noalias nocapture %B, i64 %N) {
 ; CHECK-LABEL: @even_load_dynamic_tc(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N:%.*]], i64 2)
-; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[UMAX]], 9
+; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N:%.*]], 9
 ; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
 ; CHECK:       vector.ph:
-; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[UMAX]], -1
+; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[N]], -1
 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr i64 [[TMP0]], 1
 ; CHECK-NEXT:    [[TMP2:%.*]] = add nuw i64 [[TMP1]], 1
 ; CHECK-NEXT:    [[N_MOD_VF:%.*]] = and i64 [[TMP2]], 3

>From 82bfbeb0e78985f93784065d4bcbb8068317bb1a Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Sun, 10 Sep 2023 19:45:15 +0100
Subject: [PATCH 55/62] [AArch64] ushl_sat.ll - regenerate checks. NFC.

Add missing asm comments to reduce a future diff.
---
 llvm/test/CodeGen/AArch64/ushl_sat.ll | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/ushl_sat.ll b/llvm/test/CodeGen/AArch64/ushl_sat.ll
index a2bb6d2cf4f45dd..a86803e50261129 100644
--- a/llvm/test/CodeGen/AArch64/ushl_sat.ll
+++ b/llvm/test/CodeGen/AArch64/ushl_sat.ll
@@ -74,7 +74,7 @@ define i16 @combine_shlsat_by_zero(i16 %x, i16 %y) nounwind {
 define i16 @combine_shlsat_constfold(i16 %x, i16 %y) nounwind {
 ; CHECK-LABEL: combine_shlsat_constfold:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    mov w0, #32
+; CHECK-NEXT:    mov w0, #32 // =0x20
 ; CHECK-NEXT:    ret
   %tmp = call i16 @llvm.ushl.sat.i16(i16 8, i16 2)
   ret i16 %tmp
@@ -84,7 +84,7 @@ define i16 @combine_shlsat_constfold(i16 %x, i16 %y) nounwind {
 define i16 @combine_shlsat_satmax(i16 %x, i16 %y) nounwind {
 ; CHECK-LABEL: combine_shlsat_satmax:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    mov w0, #65535
+; CHECK-NEXT:    mov w0, #65535 // =0xffff
 ; CHECK-NEXT:    ret
   %tmp = call i16 @llvm.ushl.sat.i16(i16 8, i16 15)
   ret i16 %tmp
@@ -98,8 +98,8 @@ define void @combine_shlsat_vector() nounwind {
 ; CHECK-LABEL: combine_shlsat_vector:
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
-; CHECK-NEXT:    mov w0, #32
-; CHECK-NEXT:    mov w1, #65535
+; CHECK-NEXT:    mov w0, #32 // =0x20
+; CHECK-NEXT:    mov w1, #65535 // =0xffff
 ; CHECK-NEXT:    bl sink2xi16
 ; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
 ; CHECK-NEXT:    ret

>From 93b6ad02dbe40c12bfbb312f180199731ac6602d Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 11 Sep 2023 02:52:26 +0800
Subject: [PATCH 56/62] [ConstraintElim] Add missing checks in
 test_overflow_in_negate_constraint (#65841)

This patch adds missing checks in the function
`test_overflow_in_negate_constraint`.
Related commit: 0a0181dc2061fc60b309f231a5b2f6251046c552
---
 llvm/test/Transforms/ConstraintElimination/overflows.ll | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/llvm/test/Transforms/ConstraintElimination/overflows.ll b/llvm/test/Transforms/ConstraintElimination/overflows.ll
index 1fd6bdbf6615bac..556ae0c56f9aad7 100644
--- a/llvm/test/Transforms/ConstraintElimination/overflows.ll
+++ b/llvm/test/Transforms/ConstraintElimination/overflows.ll
@@ -18,6 +18,14 @@ bb:
 }
 
 define i1 @test_overflow_in_negate_constraint(i8 %x, i64 %y) {
+; CHECK-LABEL: define i1 @test_overflow_in_negate_constraint
+; CHECK-SAME: (i8 [[X:%.*]], i64 [[Y:%.*]]) {
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[X]] to i64
+; CHECK-NEXT:    [[SHL:%.*]] = shl nuw nsw i64 [[ZEXT]], 63
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp uge i64 [[Y]], [[SHL]]
+; CHECK-NEXT:    ret i1 [[ICMP]]
+;
 bb:
   %zext = zext i8 %x to i64
   %shl = shl nuw nsw i64 %zext, 63

>From 39eff9f0bc0d89f1dcdcfd523466de0b3cfafc65 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sun, 10 Sep 2023 12:37:06 -0700
Subject: [PATCH 57/62] [Driver] Remove remnant PowerPC Darwin code

Continue the work started at https://reviews.llvm.org/D50989
---
 clang/lib/Driver/ToolChains/Darwin.cpp | 3 ---
 clang/test/Driver/bindings.c           | 2 +-
 clang/test/Driver/phases.c             | 8 ++++----
 3 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index e45424a5f712a0c..0068ca33a9fcb7e 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -53,9 +53,6 @@ llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
   // translation.
 
   return llvm::StringSwitch<llvm::Triple::ArchType>(Str)
-      .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc)
-      .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc)
-      .Case("ppc64", llvm::Triple::ppc64)
       .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
       .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
              llvm::Triple::x86)
diff --git a/clang/test/Driver/bindings.c b/clang/test/Driver/bindings.c
index cad5cb9d679e098..77afa8a115e2084 100644
--- a/clang/test/Driver/bindings.c
+++ b/clang/test/Driver/bindings.c
@@ -12,7 +12,7 @@
 // RUN: %clang -target i386-unknown-unknown -ccc-print-bindings -fsyntax-only -x c++ %s 2>&1 | FileCheck %s --check-prefix=CHECK08
 // CHECK08: "clang", inputs: ["{{.*}}bindings.c"], output: (nothing)
 
-// RUN: %clang -target i386-apple-darwin11 -ccc-print-bindings %s -S -arch ppc 2>&1 | FileCheck %s --check-prefix=CHECK11
+// RUN: %clang -target i386-apple-darwin11 -ccc-print-bindings %s -S -arch arm 2>&1 | FileCheck %s --check-prefix=CHECK11
 // CHECK11: "clang", inputs: ["{{.*}}bindings.c"], output: "bindings.s"
 
 // RUN: %clang -target powerpc-unknown-unknown -ccc-print-bindings %s -S 2>&1 | FileCheck %s --check-prefix=CHECK12
diff --git a/clang/test/Driver/phases.c b/clang/test/Driver/phases.c
index 0283800825ac62f..8d3baae541b92cc 100644
--- a/clang/test/Driver/phases.c
+++ b/clang/test/Driver/phases.c
@@ -28,25 +28,25 @@
 // BASIC: 25: linker, {4, 9, 14, 16, 19, 24}, image
 
 // Universal linked image.
-// RUN: %clang -target i386-apple-darwin9 -ccc-print-phases -x c %s -arch ppc -arch i386 2>&1 | FileCheck -check-prefix=ULI %s
+// RUN: %clang -target i386-apple-darwin9 -ccc-print-phases -x c %s -arch arm -arch i386 2>&1 | FileCheck -check-prefix=ULI %s
 // ULI: 0: input, "{{.*}}phases.c", c
 // ULI: 1: preprocessor, {0}, cpp-output
 // ULI: 2: compiler, {1}, ir
 // ULI: 3: backend, {2}, assembler
 // ULI: 4: assembler, {3}, object
 // ULI: 5: linker, {4}, image
-// ULI: 6: bind-arch, "ppc", {5}, image
+// ULI: 6: bind-arch, "arm", {5}, image
 // ULI: 7: bind-arch, "i386", {5}, image
 // ULI: 8: lipo, {6, 7}, image
 
 // Universal object file.
-// RUN: %clang -target i386-apple-darwin9 -ccc-print-phases -c -x c %s -arch ppc -arch i386 2>&1 | FileCheck -check-prefix=UOF %s
+// RUN: %clang -target i386-apple-darwin9 -ccc-print-phases -c -x c %s -arch arm -arch i386 2>&1 | FileCheck -check-prefix=UOF %s
 // UOF: 0: input, "{{.*}}phases.c", c
 // UOF: 1: preprocessor, {0}, cpp-output
 // UOF: 2: compiler, {1}, ir
 // UOF: 3: backend, {2}, assembler
 // UOF: 4: assembler, {3}, object
-// UOF: 5: bind-arch, "ppc", {4}, object
+// UOF: 5: bind-arch, "arm", {4}, object
 // UOF: 6: bind-arch, "i386", {4}, object
 // UOF: 7: lipo, {5, 6}, object
 

>From 40312d8acc0d831b177c036342679daf3daa671a Mon Sep 17 00:00:00 2001
From: Owen Pan <owenpiano at gmail.com>
Date: Sun, 10 Sep 2023 12:25:58 -0700
Subject: [PATCH 58/62] [clang-format][doc] Fix a '' (in c669541c969c) that
 meant to be ``

---
 clang/docs/ClangFormatStyleOptions.rst | 2 +-
 clang/include/clang/Format/Format.h    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 44bffa41d1cde95..d5d9faa5c78cffb 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -5514,7 +5514,7 @@ the configuration (without a prefix: ``Auto``).
 .. _SpacesInParentheses:
 
 **SpacesInParentheses** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ <SpacesInParentheses>`
-  If ``true'', spaces will be inserted after ``(`` and before ``)``.
+  If ``true``, spaces will be inserted after ``(`` and before ``)``.
   This option is **deprecated**. The previous behavior is preserved by using
   ``SpacesInParens`` with ``Custom`` and by setting all
   ``SpacesInParensOptions`` to ``true`` except for ``InCStyleCasts`` and
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index e0444966b3eabc7..c7bd356b7faeded 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4351,7 +4351,7 @@ struct FormatStyle {
     SIPO_Custom,
   };
 
-  /// If ``true'', spaces will be inserted after ``(`` and before ``)``.
+  /// If ``true``, spaces will be inserted after ``(`` and before ``)``.
   /// This option is **deprecated**. The previous behavior is preserved by using
   /// ``SpacesInParens`` with ``Custom`` and by setting all
   /// ``SpacesInParensOptions`` to ``true`` except for ``InCStyleCasts`` and

>From 42dc68072521360c44a9d2771a36965f4d97b415 Mon Sep 17 00:00:00 2001
From: Billy Laws <blaws05 at gmail.com>
Date: Sun, 10 Sep 2023 21:06:08 +0100
Subject: [PATCH 59/62] [Clang][AArch64] Define x86_64 macros for ARM64EC
 targets (#65420)

The ARM64EC ABI requires that struct layouts match between regular
x86_64 code and ARM64EC code. Ensure this is always the case by defining
the same set of macros as are set when targeting x86_64 but with the
addition of `__arm64ec__/_M_ARM64EC` macros that can be used for any
ARM64EC specific code.

More details can be found here:
https://techcommunity.microsoft.com/t5/windows-os-platform-blog/getting-to-know-arm64ec-defines-and-intrinsic-functions/ba-p/2957235
---
 clang/lib/Basic/Targets/AArch64.cpp           | 21 +++++++++++--
 .../test/Preprocessor/predefined-win-macros.c | 30 +++++++++++++++++++
 2 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index 6c43c8b592622d0..bdf5c4d98ebcea4 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -336,7 +336,18 @@ void AArch64TargetInfo::getTargetDefinesARMV94A(const LangOptions &Opts,
 void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
                                          MacroBuilder &Builder) const {
   // Target identification.
-  Builder.defineMacro("__aarch64__");
+  if (getTriple().isWindowsArm64EC()) {
+    // Define the same set of macros as would be defined on x86_64 to ensure that
+    // ARM64EC datatype layouts match those of x86_64 compiled code
+    Builder.defineMacro("__amd64__");
+    Builder.defineMacro("__amd64");
+    Builder.defineMacro("__x86_64");
+    Builder.defineMacro("__x86_64__");
+    Builder.defineMacro("__arm64ec__");
+  } else {
+    Builder.defineMacro("__aarch64__");
+  }
+
   // Inline assembly supports AArch64 flag outputs.
   Builder.defineMacro("__GCC_ASM_FLAG_OUTPUTS__");
 
@@ -1466,7 +1477,13 @@ MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
                                                 MacroBuilder &Builder) const {
   WindowsARM64TargetInfo::getTargetDefines(Opts, Builder);
-  Builder.defineMacro("_M_ARM64", "1");
+  if (getTriple().isWindowsArm64EC()) {
+    Builder.defineMacro("_M_X64", "100");
+    Builder.defineMacro("_M_AMD64", "100");
+    Builder.defineMacro("_M_ARM64EC", "1");
+  } else {
+    Builder.defineMacro("_M_ARM64", "1");
+  }
 }
 
 TargetInfo::CallingConvKind
diff --git a/clang/test/Preprocessor/predefined-win-macros.c b/clang/test/Preprocessor/predefined-win-macros.c
index 1ac249550a48927..b830dc39d477dd1 100644
--- a/clang/test/Preprocessor/predefined-win-macros.c
+++ b/clang/test/Preprocessor/predefined-win-macros.c
@@ -93,6 +93,19 @@
 // CHECK-ARM64-WIN: #define _WIN32 1
 // CHECK-ARM64-WIN: #define _WIN64 1
 
+// RUN: %clang_cc1 -triple arm64ec-windows %s -E -dM -o - \
+// RUN:   | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM64EC-WIN
+
+// CHECK-ARM64EC-WIN-NOT: #define WIN32 1
+// CHECK-ARM64EC-WIN-NOT: #define WIN64 1
+// CHECK-ARM64EC-WIN-NOT: #define WINNT 1
+// CHECK-ARM64EC-WIN-NOT: #define _M_ARM64 1
+// CHECK-ARM64EC-WIN: #define _M_AMD64 100
+// CHECK-ARM64EC-WIN: #define _M_ARM64EC 1
+// CHECK-ARM64EC-WIN: #define _M_X64 100
+// CHECK-ARM64EC-WIN: #define _WIN32 1
+// CHECK-ARM64EC-WIN: #define _WIN64 1
+
 // RUN: %clang_cc1 -triple i686-windows-gnu %s -E -dM -o - \
 // RUN:   | FileCheck -match-full-lines %s --check-prefix=CHECK-X86-MINGW
 
@@ -131,3 +144,20 @@
 // CHECK-ARM64-MINGW: #define _WIN64 1
 // CHECK-ARM64-MINGW: #define __GCC_ASM_FLAG_OUTPUTS__ 1
 // CHECK-ARM64-MINGW: #define __aarch64__ 1
+
+// RUN: %clang_cc1 -triple arm64ec-windows-gnu %s -E -dM -o - \
+// RUN:   | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM64EC-MINGW
+
+// CHECK-ARM64EC-MINGW-NOT: #define _M_ARM64EC 1
+// CHECK-ARM64EC-MINGW: #define WIN32 1
+// CHECK-ARM64EC-MINGW: #define WIN64 1
+// CHECK-ARM64EC-MINGW: #define WINNT 1
+// CHECK-ARM64EC-MINGW: #define _WIN32 1
+// CHECK-ARM64EC-MINGW: #define _WIN64 1
+// CHECK-ARM64EC-MINGW: #define __GCC_ASM_FLAG_OUTPUTS__ 1
+// CHECK-ARM64EC-MINGW-NOT: #define __aarch64__ 1
+// CHECK-ARM64EC-MINGW: #define __amd64 1
+// CHECK-ARM64EC-MINGW: #define __amd64__ 1
+// CHECK-ARM64EC-MINGW: #define __arm64ec__ 1
+// CHECK-ARM64EC-MINGW: #define __x86_64 1
+// CHECK-ARM64EC-MINGW: #define __x86_64__ 1

>From 0a4b462b8537902c3425ef00ca3dd6620423bfd5 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sun, 10 Sep 2023 13:06:27 -0700
Subject: [PATCH 60/62] [Driver] Properly report error for unsupported powerpc
 darwin/macos triples

The removal started at https://reviews.llvm.org/D50989 and
https://reviews.llvm.org/D75494 removed the Triple support. Without recognizing
Darwin triples as Mach-O, we will get assertion error in ToolChains/Darwin.h due
to the universal binary mechanism.

Fix #47698
---
 clang/test/Driver/unsupported-target-arch.c | 4 ++++
 llvm/lib/TargetParser/Triple.cpp            | 6 +++---
 llvm/unittests/TargetParser/TripleTest.cpp  | 1 +
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/clang/test/Driver/unsupported-target-arch.c b/clang/test/Driver/unsupported-target-arch.c
index 24174650151f1ce..ce1d99007f1a008 100644
--- a/clang/test/Driver/unsupported-target-arch.c
+++ b/clang/test/Driver/unsupported-target-arch.c
@@ -59,3 +59,7 @@
 // RUN: not %clang --target=thumbeb-none-elf -o %t.o %s 2> %t.err
 // RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-THUMBEB-INVALID-ENV %s
 // CHECK-THUMBEB-INVALID-ENV: warning: mismatch between architecture and environment in target triple 'thumbeb-none-elf'; did you mean 'thumbeb-none-eabi'? [-Winvalid-command-line-argument]{{$}}
+
+// RUN: not %clang --target=powerpc-apple-darwin -o /dev/null %s 2> %t.err
+// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-PPCMAC %s
+// CHECK-PPCMAC: error: unknown target triple 'unknown-apple-macosx10.4.0'{{$}}
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index 5eea4acd1c6b8de..1424229479c24ed 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -782,6 +782,8 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) {
 }
 
 static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
+  if (T.isOSDarwin())
+    return Triple::MachO;
   switch (T.getArch()) {
   case Triple::UnknownArch:
   case Triple::aarch64:
@@ -790,9 +792,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
   case Triple::thumb:
   case Triple::x86:
   case Triple::x86_64:
-    if (T.isOSDarwin())
-      return Triple::MachO;
-    else if (T.isOSWindows())
+    if (T.isOSWindows())
       return Triple::COFF;
     return Triple::ELF;
 
diff --git a/llvm/unittests/TargetParser/TripleTest.cpp b/llvm/unittests/TargetParser/TripleTest.cpp
index ce1f1dc8eb68fa0..6c9d51374a2d944 100644
--- a/llvm/unittests/TargetParser/TripleTest.cpp
+++ b/llvm/unittests/TargetParser/TripleTest.cpp
@@ -1801,6 +1801,7 @@ TEST(TripleTest, FileFormat) {
   EXPECT_EQ(Triple::MachO, Triple("i686-apple-macosx").getObjectFormat());
   EXPECT_EQ(Triple::MachO, Triple("i686-apple-ios").getObjectFormat());
   EXPECT_EQ(Triple::MachO, Triple("i686---macho").getObjectFormat());
+  EXPECT_EQ(Triple::MachO, Triple("powerpc-apple-macosx").getObjectFormat());
 
   EXPECT_EQ(Triple::COFF, Triple("i686--win32").getObjectFormat());
 

>From d66052ded3468499b0f476e23177f6964c684795 Mon Sep 17 00:00:00 2001
From: Tianlan Zhou <bobby825 at 126.com>
Date: Mon, 11 Sep 2023 04:11:06 +0800
Subject: [PATCH 61/62] Fix some typos in comments: evalute -> evaluate (NFC)
 (#65906)

---
 clang/include/clang/AST/Expr.h                         |  2 +-
 clang/lib/Serialization/ASTWriter.cpp                  |  2 +-
 .../unittests/Analysis/FlowSensitive/TransferTest.cpp  |  2 +-
 flang/include/flang/Lower/Support/Utils.h              |  2 +-
 flang/lib/Evaluate/shape.cpp                           |  2 +-
 .../include/mlir/Dialect/Linalg/IR/LinalgInterfaces.td | 10 +++++-----
 openmp/libomptarget/test/lit.cfg                       |  2 +-
 7 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index c9315de8024e2f1..fe20a84216d1f11 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -566,7 +566,7 @@ class Expr : public ValueStmt {
                                       SmallVectorImpl<
                                         PartialDiagnosticAt> &Diags);
 
-  /// isPotentialConstantExprUnevaluted - Return true if this expression might
+  /// isPotentialConstantExprUnevaluated - Return true if this expression might
   /// be usable in a constant expression in C++11 in an unevaluated context, if
   /// it were in function FD marked constexpr. Return false if the function can
   /// never produce a constant expression, along with diagnostics describing
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 5ba07271cd81867..65bee806d2c5571 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -6081,7 +6081,7 @@ void ASTRecordWriter::AddVarDeclInit(const VarDecl *VD) {
     Val |= (ES->HasConstantInitialization ? 2 : 0);
     Val |= (ES->HasConstantDestruction ? 4 : 0);
     APValue *Evaluated = VD->getEvaluatedValue();
-    // If the evaluted result is constant, emit it.
+    // If the evaluated result is constant, emit it.
     if (Evaluated && (Evaluated->isInt() || Evaluated->isFloat()))
       Val |= 8;
   }
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index ec07555d7f33b3b..cced3925c4721c5 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -5855,7 +5855,7 @@ TEST(TransferTest, AnonymousStructWithReferenceField) {
 
 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
   // This is a crash repro.
-  // `false` block may not have been processed when we try to evalute the `||`
+  // `false` block may not have been processed when we try to evaluate the `||`
   // after visiting `true`, because it is not necessary (and therefore the edge
   // is marked unreachable). Trying to get the analysis state via
   // `getEnvironment` for the subexpression still should not crash.
diff --git a/flang/include/flang/Lower/Support/Utils.h b/flang/include/flang/Lower/Support/Utils.h
index 9ab00dad51d39a5..64641ab4b6ca13e 100644
--- a/flang/include/flang/Lower/Support/Utils.h
+++ b/flang/include/flang/Lower/Support/Utils.h
@@ -89,7 +89,7 @@ namespace Fortran::lower {
 // Fortran::evaluate::Expr are functional values organized like an AST. A
 // Fortran::evaluate::Expr is meant to be moved and cloned. Using the front end
 // tools can often cause copies and extra wrapper classes to be added to any
-// Fortran::evalute::Expr. These values should not be assumed or relied upon to
+// Fortran::evaluate::Expr. These values should not be assumed or relied upon to
 // have an *object* identity. They are deeply recursive, irregular structures
 // built from a large number of classes which do not use inheritance and
 // necessitate a large volume of boilerplate code as a result.
diff --git a/flang/lib/Evaluate/shape.cpp b/flang/lib/Evaluate/shape.cpp
index ada26ac46af8363..8f4923ff96a94b0 100644
--- a/flang/lib/Evaluate/shape.cpp
+++ b/flang/lib/Evaluate/shape.cpp
@@ -1086,7 +1086,7 @@ void GetShapeHelper::AccumulateExtent(
   result = std::move(result) + std::move(n);
   if (context_) {
     // Fold during expression creation to avoid creating an expression so
-    // large we can't evalute it without overflowing the stack.
+    // large we can't evaluate it without overflowing the stack.
     result = Fold(*context_, std::move(result));
   }
 }
diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgInterfaces.td b/mlir/include/mlir/Dialect/Linalg/IR/LinalgInterfaces.td
index 4567b3f1902d728..c45ec11a46cb7cc 100644
--- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgInterfaces.td
+++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgInterfaces.td
@@ -324,7 +324,7 @@ def LinalgStructuredInterface : OpInterface<"LinalgOp"> {
         // MLIR currently does not support dependent interfaces or interface
         // inheritance. By construction all ops with StructuredOpInterface must
         // implement DestinationStyleOpInterface.
-        // TODO: reevalute the need for a cast when a better mechanism exists.
+        // TODO: reevaluate the need for a cast when a better mechanism exists.
         return getBlock()->getArguments().take_front(
             cast<DestinationStyleOpInterface>(*this->getOperation())
                 .getNumDpsInputs());
@@ -342,7 +342,7 @@ def LinalgStructuredInterface : OpInterface<"LinalgOp"> {
         // MLIR currently does not support dependent interfaces or interface
         // inheritance. By construction all ops with StructuredOpInterface must
         // implement DestinationStyleOpInterface.
-        // TODO: reevalute the need for a cast when a better mechanism exists.
+        // TODO: reevaluate the need for a cast when a better mechanism exists.
         return getBlock()->getArguments().take_back(
             cast<DestinationStyleOpInterface>(*this->getOperation())
                 .getNumDpsInits());
@@ -421,7 +421,7 @@ def LinalgStructuredInterface : OpInterface<"LinalgOp"> {
         // MLIR currently does not support dependent interfaces or interface
         // inheritance. By construction all ops with StructuredOpInterface must
         // implement DestinationStyleOpInterface.
-        // TODO: reevalute the need for a cast when a better mechanism exists.
+        // TODO: reevaluate the need for a cast when a better mechanism exists.
         return *(indexingMaps.begin() +
                  cast<DestinationStyleOpInterface>(*this->getOperation())
                      .getNumDpsInputs() +
@@ -442,7 +442,7 @@ def LinalgStructuredInterface : OpInterface<"LinalgOp"> {
         // MLIR currently does not support dependent interfaces or interface
         // inheritance. By construction all ops with StructuredOpInterface must
         // implement DestinationStyleOpInterface.
-        // TODO: reevalute the need for a cast when a better mechanism exists.
+        // TODO: reevaluate the need for a cast when a better mechanism exists.
         int64_t resultIndex =
             opOperand->getOperandNumber() -
             cast<DestinationStyleOpInterface>(*this->getOperation())
@@ -807,7 +807,7 @@ def LinalgStructuredInterface : OpInterface<"LinalgOp"> {
     // MLIR currently does not support dependent interfaces or interface
     // inheritance. By construction all ops with StructuredOpInterface must
     // implement DestinationStyleOpInterface.
-    // TODO: reevalute the need for a cast when a better mechanism exists.
+    // TODO: reevaluate the need for a cast when a better mechanism exists.
     //========================================================================//
 
     int64_t getNumDpsInputs() {
diff --git a/openmp/libomptarget/test/lit.cfg b/openmp/libomptarget/test/lit.cfg
index f54edf91574671e..a53d4e32436de12 100644
--- a/openmp/libomptarget/test/lit.cfg
+++ b/openmp/libomptarget/test/lit.cfg
@@ -45,7 +45,7 @@ def append_dynamic_library_path(name, value, sep):
     else:
         config.environment[name] = value
 
-# Evalute the environment variable which is a string boolean value.
+# Evaluate the environment variable which is a string boolean value.
 def evaluate_bool_env(env):
     env = env.lower()
     possible_true_values = ["on", "true", "1"]

>From 7106e2a568fef543ce60531f2c24950911373e6b Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 11 Sep 2023 05:39:57 +0800
Subject: [PATCH 62/62] [MC][RISCV] Only mark up register part of Rlist

---
 .../RISCV/MCTargetDesc/RISCVInstPrinter.cpp   | 45 ++++++++++++++-----
 llvm/test/MC/Disassembler/RISCV/colored.txt   | 39 +++++++++++++---
 2 files changed, 65 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
index d0a77b1248d8c99..79a8e51902d4422 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
@@ -209,20 +209,33 @@ void RISCVInstPrinter::printVTypeI(const MCInst *MI, unsigned OpNo,
 void RISCVInstPrinter::printRlist(const MCInst *MI, unsigned OpNo,
                                   const MCSubtargetInfo &STI, raw_ostream &O) {
   unsigned Imm = MI->getOperand(OpNo).getImm();
-  auto OS = markup(O, Markup::Register);
-  OS << "{";
+  O << "{";
   switch (Imm) {
   case RISCVZC::RLISTENCODE::RA:
-    OS << (ArchRegNames ? "x1" : "ra");
+    markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra");
     break;
   case RISCVZC::RLISTENCODE::RA_S0:
-    OS << (ArchRegNames ? "x1, x8" : "ra, s0");
+    markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra");
+    O << ", ";
+    markup(O, Markup::Register) << (ArchRegNames ? "x8" : "s0");
     break;
   case RISCVZC::RLISTENCODE::RA_S0_S1:
-    OS << (ArchRegNames ? "x1, x8-x9" : "ra, s0-s1");
+    markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra");
+    O << ", ";
+    markup(O, Markup::Register) << (ArchRegNames ? "x8" : "s0");
+    O << '-';
+    markup(O, Markup::Register) << (ArchRegNames ? "x9" : "s1");
     break;
   case RISCVZC::RLISTENCODE::RA_S0_S2:
-    OS << (ArchRegNames ? "x1, x8-x9, x18" : "ra, s0-s2");
+    markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra");
+    O << ", ";
+    markup(O, Markup::Register) << (ArchRegNames ? "x8" : "s0");
+    O << '-';
+    markup(O, Markup::Register) << (ArchRegNames ? "x9" : "s2");
+    if (ArchRegNames) {
+      O << ", ";
+      markup(O, Markup::Register) << "x18";
+    }
     break;
   case RISCVZC::RLISTENCODE::RA_S0_S3:
   case RISCVZC::RLISTENCODE::RA_S0_S4:
@@ -231,16 +244,23 @@ void RISCVInstPrinter::printRlist(const MCInst *MI, unsigned OpNo,
   case RISCVZC::RLISTENCODE::RA_S0_S7:
   case RISCVZC::RLISTENCODE::RA_S0_S8:
   case RISCVZC::RLISTENCODE::RA_S0_S9:
-    OS << (ArchRegNames ? "x1, x8-x9, x18-" : "ra, s0-")
-       << getRegisterName(RISCV::X19 + (Imm - RISCVZC::RLISTENCODE::RA_S0_S3));
-    break;
   case RISCVZC::RLISTENCODE::RA_S0_S11:
-    OS << (ArchRegNames ? "x1, x8-x9, x18-x27" : "ra, s0-s11");
+    markup(O, Markup::Register) << (ArchRegNames ? "x1" : "ra");
+    O << ", ";
+    markup(O, Markup::Register) << (ArchRegNames ? "x8" : "s0");
+    O << '-';
+    if (ArchRegNames) {
+      markup(O, Markup::Register) << "x9";
+      O << ", ";
+      markup(O, Markup::Register) << "x18";
+      O << '-';
+    }
+    markup(O, Markup::Register) << getRegisterName(RISCV::X19 + (Imm == RISCVZC::RLISTENCODE::RA_S0_S11 ? 8 : Imm - RISCVZC::RLISTENCODE::RA_S0_S3));
     break;
   default:
     llvm_unreachable("invalid register list");
   }
-  OS << "}";
+  O << "}";
 }
 
 void RISCVInstPrinter::printSpimm(const MCInst *MI, unsigned OpNo,
@@ -258,6 +278,7 @@ void RISCVInstPrinter::printSpimm(const MCInst *MI, unsigned OpNo,
   if (Opcode == RISCV::CM_PUSH)
     Spimm = -Spimm;
 
+  // RAII guard for ANSI color escape sequences
   auto OS = markup(O, Markup::Immediate);
   RISCVZC::printSpimm(Spimm, O);
 }
@@ -272,7 +293,7 @@ void RISCVInstPrinter::printVMaskReg(const MCInst *MI, unsigned OpNo,
     return;
   O << ", ";
   printRegName(O, MO.getReg());
-  O << ".t";
+  markup(O, Markup::Register) << ".t";
 }
 
 const char *RISCVInstPrinter::getRegisterName(MCRegister Reg) {
diff --git a/llvm/test/MC/Disassembler/RISCV/colored.txt b/llvm/test/MC/Disassembler/RISCV/colored.txt
index 10d52b525cd90c9..94d2f8170ee1289 100644
--- a/llvm/test/MC/Disassembler/RISCV/colored.txt
+++ b/llvm/test/MC/Disassembler/RISCV/colored.txt
@@ -1,23 +1,48 @@
-# RUN: llvm-mc -triple=riscv64 -mattr=+zcmp,+experimental-zfa --cdis %s | FileCheck %s --strict-whitespace --match-full-lines
+# UNSUPPORTED: system-windows
+# RUN: llvm-mc -triple=riscv64 -mattr=+zcmp,+experimental-zfa,+v --cdis %s | FileCheck %s --strict-whitespace --match-full-lines -check-prefixes=CHECK,ASM,ABINAME
+# RUN: llvm-mc -triple=riscv64 -mattr=+zcmp,+experimental-zfa,+v -M numeric --cdis %s | FileCheck %s --strict-whitespace --match-full-lines -check-prefixes=CHECK,ASM,ARCHNAME
 
+# CHECK:	.text
 # Registers and immediates
 0x03 0xe0 0x40 0x00
-# CHECK:	lwu	zero, 4(ra)
+# ABINAME-NEXT:	lwu	zero, 4(ra)
+# ARCHNAME-NEXT:	lwu	x0, 4(x1)
 
 # Branch targets
 0x63 0x00 0xb5 0x04
-# CHECK-NEXT:	beq	a0, a1, 64
+# ABINAME-NEXT:	beq	a0, a1, 64
+# ARCHNAME-NEXT:	beq	x10, x11, 64
 
 # CSRs
 0xf3 0x23 0x10 0xf1
-# CHECK-NEXT:	csrr	t2, mvendorid
+# ABINAME-NEXT:	csrr	t2, mvendorid
+# ARCHNAME-NEXT:	csrr	x7, mvendorid
 
 # FP immediates
 0xd3 0x00 0x1f 0xf0
-# CHECK-NEXT:	fli.s	ft1, inf
+# ABINAME-NEXT:	fli.s	ft1, inf
+# ARCHNAME-NEXT:	fli.s	f1, inf
 0xd3 0x80 0x1e 0xf0
-# CHECK-NEXT:	fli.s	ft1, 65536.0
+# ABINAME-NEXT:	fli.s	ft1, 65536.0
+# ARCHNAME-NEXT:	fli.s	f1, 65536.0
 
 # Rlist and spimm
+0x42 0xbe
+# ABINAME-NEXT:	cm.popret	{ra}, 16
+# ARCHNAME-NEXT:	cm.popret	{x1}, 16
+0x5e 0xbe
+# ABINAME-NEXT:	cm.popret	{ra, s0}, 64
+# ARCHNAME-NEXT:	cm.popret	{x1, x8}, 64
 0x62 0xbe
-# CHECK-NEXT:	cm.popret	{ra, s0-s1}, 32
+# ABINAME-NEXT:	cm.popret	{ra, s0-s1}, 32
+# ARCHNAME-NEXT:	cm.popret	{x1, x8-x9}, 32
+0x76 0xbe
+# ABINAME-NEXT:	cm.popret	{ra, s0-s2}, 48
+# ARCHNAME-NEXT:	cm.popret	{x1, x8-x9, x18}, 48
+0xfe 0xbe
+# ABINAME-NEXT:	cm.popret	{ra, s0-s11}, 160
+# ARCHNAME-NEXT:	cm.popret	{x1, x8-x9, x18-x27}, 160
+
+# mask registers
+0x57 0x04 0x4a 0x00
+# ASM-NEXT:	vadd.vv	v8, v4, v20, v0.t



More information about the cfe-commits mailing list