[clang] [LSAN][NFC] Add a new line to a log (PR #66305)

via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 14 09:23:41 PDT 2023


Valentin Clement =?utf-8?b?KOODkOODrOODsw=?=,
Valentin Clement =?utf-8?b?KOODkOODrOODsw=?=,Jonas Devlieghere
 <jonas at devlieghere.com>,Douglas Yung <douglas.yung at sony.com>,daisy202309
 <144047963+daisy202309 at users.noreply.github.com>,Jonas Devlieghere
 <jonas at devlieghere.com>,Mehdi Amini <joker.eph at gmail.com>,Siva Chandra
 <sivachandra at gmail.com>,Jonas Devlieghere <jonas at devlieghere.com>,
Valentin Clement =?utf-8?b?KOODkOODrOODsw=?=,Tom Stellard
 <tstellar at redhat.com>,Siva Chandra <sivachandra at gmail.com>,Tom Stellard
 <tstellar at redhat.com>,https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
 =?utf-8?q?,?=Pierre van Houtryve <pierre.vanhoutryve at amd.com>,Antonio
 Frighetto <me at antoniofrighetto.com>,Owen Pan <owenpiano at gmail.com>,Nikita
 Popov <npopov at redhat.com>,Antonio Frighetto <me at antoniofrighetto.com>,
Timm =?utf-8?q?Bäder?= <tbaeder at redhat.com>,Cullen Rhodes
 <cullen.rhodes at arm.com>,Jianjian Guan <jacquesguan at me.com>,Weining Lu
 <luweining at loongson.cn>,Matthias Springer <me at m-sp.org>,David Spickett
 <david.spickett at linaro.org>,Hans <hans at hanshq.net>,Guillaume Chatelet
 <gchatelet at google.com>,vic <victor.perez at codeplay.com>,David Green
 <david.green at arm.com>,Benjamin Kramer <benny.kra at googlemail.com>,David
 Spickett <david.spickett at linaro.org>,Bill Wendling
 <5993918+bwendling at users.noreply.github.com>,martinboehme
 <mboehme at google.com>,Sergio Afonso <safonsof at amd.com>,Sergio Afonso
 <safonsof at amd.com>,Sergio Afonso <safonsof at amd.com>,Carlo Bramini
 <carlo_bramini at users.sourceforge.net>,DonatNagyE <donat.nagy at ericsson.com>,Balazs
 Benics <benicsbalazs at gmail.com>,Balazs Benics <benicsbalazs at gmail.com>,Balazs
 Benics <benicsbalazs at gmail.com>,M Iyengar <max.iyengar at arm.com>,Martin
 Erhart <merhart at google.com>,David Spickett <david.spickett at linaro.org>,Balazs
 Benics <benicsbalazs at gmail.com>,khei4 <kk.asano.luxy at gmail.com>,Felix
 Schneider <fx.schn at gmail.com>,Felix Schneider <fx.schn at gmail.com>,Benjamin
 Kramer <benny.kra at googlemail.com>,Felix Schneider <fx.schn at gmail.com>,Oleg
 Shyshkov <shyshkov at google.com>,
Timm =?utf-8?q?Bäder?= <tbaeder at redhat.com>,Martin Erhart
 <merhart at google.com>,paulwalker-arm <paul.walker at arm.com>,Louis Dionne
 <ldionne.2 at gmail.com>,Kohei Asano <32860920+khei4 at users.noreply.github.com>,Martin
 Erhart <merhart at google.com>,sstwcw <su3e8a96kzlver at posteo.net>,Alex Brachet
 <abrachet at google.com>,Martin Erhart <merhart at google.com>,Matthias Springer
 <me at m-sp.org>,"Mikhail R. Gadelha" <mikhail at igalia.com>,Louis Dionne
 <ldionne.2 at gmail.com>,Nicolas Vasilache
 <nicolasvasilache at users.noreply.github.com>,Paul Walker <paul.walker at arm.com>
 =?utf-8?q?,?="Joel E. Denny" <jdenny.ornl at gmail.com>,Martin Erhart
 <merhart at google.com>,Matthias Springer <me at m-sp.org>,
=?utf-8?q?Björn?= Pettersson <bjorn.a.pettersson at ericsson.com>,Slava
 Zakharin <szakharin at nvidia.com>,Slava Zakharin <szakharin at nvidia.com>,Manos
 Anagnostakis <manos.anagnostakis at vrull.eu>,
Duncan P. N. =?utf-8?q?Exon Smith?=,Matt Arsenault
 <Matthew.Arsenault at amd.com>,Kirill Stoimenov <kstoimenov at google.com>;


https://github.com/kstoimenov updated https://github.com/llvm/llvm-project/pull/66305:

>From bdfde33cad308c971a3576980d4d6f3df8080ca0 Mon Sep 17 00:00:00 2001
From: Shilei Tian <i at tianshilei.me>
Date: Wed, 13 Sep 2023 20:22:59 -0400
Subject: [PATCH 01/86] [LLVM][OpenMPOpt] Fix a crash when associated function
 is nullptr (#66274)

The associated function can be a nullptr if it is an indirect call.
This causes a crash in `CheckCallee` which always assumes the callee
is a valid pointer.

Fix #66904.
---
 llvm/lib/Transforms/IPO/OpenMPOpt.cpp         |  3 +-
 .../OpenMP/indirect_call_kernel_info_crash.ll | 42 +++++++++++++++++++
 2 files changed, 44 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/Transforms/OpenMP/indirect_call_kernel_info_crash.ll

diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
index a18730ab35621ef..f945de52920ccfe 100644
--- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
+++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
@@ -5028,7 +5028,8 @@ struct AAKernelInfoCallSite : AAKernelInfo {
     const auto *AACE =
         A.getAAFor<AACallEdges>(*this, getIRPosition(), DepClassTy::OPTIONAL);
     if (!AACE || !AACE->getState().isValidState() || AACE->hasUnknownCallee()) {
-      CheckCallee(getAssociatedFunction(), /*NumCallees=*/1);
+      if (Function *F = getAssociatedFunction())
+        CheckCallee(F, /*NumCallees=*/1);
     } else {
       const auto &OptimisticEdges = AACE->getOptimisticEdges();
       for (auto *Callee : OptimisticEdges) {
diff --git a/llvm/test/Transforms/OpenMP/indirect_call_kernel_info_crash.ll b/llvm/test/Transforms/OpenMP/indirect_call_kernel_info_crash.ll
new file mode 100644
index 000000000000000..03bc31bac2034e6
--- /dev/null
+++ b/llvm/test/Transforms/OpenMP/indirect_call_kernel_info_crash.ll
@@ -0,0 +1,42 @@
+; RUN: opt -S -passes=openmp-opt < %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"
+target triple = "amdgcn-amd-amdhsa"
+
+%"struct.ompx::state::TeamStateTy" = type { %"struct.ompx::state::ICVStateTy", i32, i32, ptr }
+%"struct.ompx::state::ICVStateTy" = type { i32, i32, i32, i32, i32, i32, i32 }
+
+ at _ZN4ompx5state9TeamStateE = internal addrspace(3) global %"struct.ompx::state::TeamStateTy" undef
+
+define amdgpu_kernel void @__omp_offloading_32_70c2e76c_main_l24() {
+  %1 = tail call i32 @__kmpc_target_init(ptr null)
+  call void @__kmpc_parallel_51(ptr null, i32 0, i32 0, i32 0, i32 0, ptr @__omp_offloading_32_70c2e76c_main_l24_omp_outlined, ptr null, ptr null, i64 0)
+  ret void
+}
+
+define void @__omp_offloading_32_70c2e76c_main_l24_omp_outlined(ptr %0) {
+  call void @__kmpc_for_static_init_4()
+  br label %2
+
+2:                                                ; preds = %2, %1
+  %3 = load ptr, ptr addrspace(1) null, align 4294967296
+  %4 = call i32 %3(i32 0)
+  store i32 %4, ptr %0, align 4
+  br label %2
+}
+
+define internal i32 @__kmpc_target_init(ptr %0) {
+  store i32 0, ptr addrspace(3) @_ZN4ompx5state9TeamStateE, align 16
+  ret i32 0
+}
+
+declare void @__kmpc_parallel_51(ptr, i32, i32, i32, i32, ptr, ptr, ptr, i64)
+
+define void @__kmpc_for_static_init_4() {
+  %1 = load i32, ptr addrspace(3) @_ZN4ompx5state9TeamStateE, align 8
+  ret void
+}
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 7, !"openmp", i32 51}
+!1 = !{i32 7, !"openmp-device", i32 51}

>From 30de4b5f8a9b4a370ec575f30edef26bb62d2d4a Mon Sep 17 00:00:00 2001
From: Artem Dergachev <adergachev at apple.com>
Date: Wed, 13 Sep 2023 17:31:14 -0700
Subject: [PATCH 02/86] [analyzer] RetainRelease: Extend the workaround for
 VTCompressionSessionEncode{,MultiImage}Frame.

This is a new API that has the same ownership quirk as the old API.

This is a tiny one-liner patch; changes in plists are entirely about
line numbers.
---
 clang/lib/Analysis/RetainSummaryManager.cpp   |    5 +-
 .../retain-release.m.objc.plist               | 2562 ++++++++---------
 .../retain-release.m.objcpp.plist             | 2562 ++++++++---------
 clang/test/Analysis/retain-release.m          |   17 +
 4 files changed, 2582 insertions(+), 2564 deletions(-)

diff --git a/clang/lib/Analysis/RetainSummaryManager.cpp b/clang/lib/Analysis/RetainSummaryManager.cpp
index f759cfaf5e340ac..4cbeb0c35b6f664 100644
--- a/clang/lib/Analysis/RetainSummaryManager.cpp
+++ b/clang/lib/Analysis/RetainSummaryManager.cpp
@@ -371,8 +371,9 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
     return getPersistentSummary(RetEffect::MakeNoRet(),
                                 ScratchArgs,
                                 ArgEffect(DoNothing), ArgEffect(DoNothing));
-  } else if (FName == "VTCompressionSessionEncodeFrame") {
-    // The context argument passed to VTCompressionSessionEncodeFrame()
+  } else if (FName == "VTCompressionSessionEncodeFrame" ||
+             FName == "VTCompressionSessionEncodeMultiImageFrame") {
+    // The context argument passed to VTCompressionSessionEncodeFrame() et.al.
     // is passed to the callback specified when creating the session
     // (e.g. with VTCompressionSessionCreate()) which can release it.
     // To account for this possibility, conservatively stop tracking
diff --git a/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist b/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist
index 44f9085496b3a59..5c4ea431696f156 100644
--- a/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist
+++ b/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist
@@ -15881,12 +15881,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1456</integer>
+           <key>line</key><integer>1473</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1456</integer>
+           <key>line</key><integer>1473</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -15894,12 +15894,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1458</integer>
+           <key>line</key><integer>1475</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1458</integer>
+           <key>line</key><integer>1475</integer>
            <key>col</key><integer>31</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -15911,7 +15911,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1458</integer>
+      <key>line</key><integer>1475</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -15919,12 +15919,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1458</integer>
+         <key>line</key><integer>1475</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1459</integer>
+         <key>line</key><integer>1476</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -15944,12 +15944,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1458</integer>
+           <key>line</key><integer>1475</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1458</integer>
+           <key>line</key><integer>1475</integer>
            <key>col</key><integer>31</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -15957,12 +15957,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1460</integer>
+           <key>line</key><integer>1477</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1460</integer>
+           <key>line</key><integer>1477</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -15974,7 +15974,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1460</integer>
+      <key>line</key><integer>1477</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -15996,7 +15996,7 @@
   <key>issue_hash_function_offset</key><string>7</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1460</integer>
+   <key>line</key><integer>1477</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16004,14 +16004,14 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1448</integer>
-    <integer>1449</integer>
-    <integer>1450</integer>
-    <integer>1451</integer>
-    <integer>1456</integer>
-    <integer>1458</integer>
-    <integer>1459</integer>
-    <integer>1460</integer>
+    <integer>1465</integer>
+    <integer>1466</integer>
+    <integer>1467</integer>
+    <integer>1468</integer>
+    <integer>1473</integer>
+    <integer>1475</integer>
+    <integer>1476</integer>
+    <integer>1477</integer>
    </array>
   </dict>
   </dict>
@@ -16022,7 +16022,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1475</integer>
+      <key>line</key><integer>1492</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16030,12 +16030,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1475</integer>
+         <key>line</key><integer>1492</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1475</integer>
+         <key>line</key><integer>1492</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16055,12 +16055,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1475</integer>
+           <key>line</key><integer>1492</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1475</integer>
+           <key>line</key><integer>1492</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16068,12 +16068,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1476</integer>
+           <key>line</key><integer>1493</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1476</integer>
+           <key>line</key><integer>1493</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16085,7 +16085,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1476</integer>
+      <key>line</key><integer>1493</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16107,7 +16107,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1476</integer>
+   <key>line</key><integer>1493</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16115,9 +16115,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1474</integer>
-    <integer>1475</integer>
-    <integer>1476</integer>
+    <integer>1491</integer>
+    <integer>1492</integer>
+    <integer>1493</integer>
    </array>
   </dict>
   </dict>
@@ -16132,12 +16132,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1493</integer>
+           <key>line</key><integer>1510</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1493</integer>
+           <key>line</key><integer>1510</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16145,12 +16145,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1494</integer>
+           <key>line</key><integer>1511</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1494</integer>
+           <key>line</key><integer>1511</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16162,7 +16162,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1494</integer>
+      <key>line</key><integer>1511</integer>
       <key>col</key><integer>22</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16170,12 +16170,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1494</integer>
+         <key>line</key><integer>1511</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1494</integer>
+         <key>line</key><integer>1511</integer>
          <key>col</key><integer>53</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16195,12 +16195,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1494</integer>
+           <key>line</key><integer>1511</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1494</integer>
+           <key>line</key><integer>1511</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16208,12 +16208,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1495</integer>
+           <key>line</key><integer>1512</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1495</integer>
+           <key>line</key><integer>1512</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16225,7 +16225,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1495</integer>
+      <key>line</key><integer>1512</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16247,7 +16247,7 @@
   <key>issue_hash_function_offset</key><string>4</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1495</integer>
+   <key>line</key><integer>1512</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16255,10 +16255,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1490</integer>
-    <integer>1493</integer>
-    <integer>1494</integer>
-    <integer>1495</integer>
+    <integer>1507</integer>
+    <integer>1510</integer>
+    <integer>1511</integer>
+    <integer>1512</integer>
    </array>
   </dict>
   </dict>
@@ -16269,7 +16269,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1503</integer>
+      <key>line</key><integer>1520</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16277,12 +16277,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1503</integer>
+         <key>line</key><integer>1520</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1503</integer>
+         <key>line</key><integer>1520</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16306,7 +16306,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1503</integer>
+   <key>line</key><integer>1520</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16314,8 +16314,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1502</integer>
-    <integer>1503</integer>
+    <integer>1519</integer>
+    <integer>1520</integer>
    </array>
   </dict>
   </dict>
@@ -16330,12 +16330,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1503</integer>
+           <key>line</key><integer>1520</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1503</integer>
+           <key>line</key><integer>1520</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16343,12 +16343,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1504</integer>
+           <key>line</key><integer>1521</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1504</integer>
+           <key>line</key><integer>1521</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16360,7 +16360,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1504</integer>
+      <key>line</key><integer>1521</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16368,12 +16368,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1504</integer>
+         <key>line</key><integer>1521</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1504</integer>
+         <key>line</key><integer>1521</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16397,7 +16397,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1504</integer>
+   <key>line</key><integer>1521</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16405,9 +16405,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1502</integer>
-    <integer>1503</integer>
-    <integer>1504</integer>
+    <integer>1519</integer>
+    <integer>1520</integer>
+    <integer>1521</integer>
    </array>
   </dict>
   </dict>
@@ -16422,12 +16422,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1503</integer>
+           <key>line</key><integer>1520</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1503</integer>
+           <key>line</key><integer>1520</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16435,12 +16435,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1505</integer>
+           <key>line</key><integer>1522</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1505</integer>
+           <key>line</key><integer>1522</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16452,7 +16452,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1505</integer>
+      <key>line</key><integer>1522</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16460,12 +16460,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1505</integer>
+         <key>line</key><integer>1522</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1505</integer>
+         <key>line</key><integer>1522</integer>
          <key>col</key><integer>27</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16489,7 +16489,7 @@
   <key>issue_hash_function_offset</key><string>3</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1505</integer>
+   <key>line</key><integer>1522</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16497,10 +16497,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1502</integer>
-    <integer>1503</integer>
-    <integer>1504</integer>
-    <integer>1505</integer>
+    <integer>1519</integer>
+    <integer>1520</integer>
+    <integer>1521</integer>
+    <integer>1522</integer>
    </array>
   </dict>
   </dict>
@@ -16515,12 +16515,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1503</integer>
+           <key>line</key><integer>1520</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1503</integer>
+           <key>line</key><integer>1520</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16528,12 +16528,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1506</integer>
+           <key>line</key><integer>1523</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1506</integer>
+           <key>line</key><integer>1523</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16545,7 +16545,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1506</integer>
+      <key>line</key><integer>1523</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16553,12 +16553,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1506</integer>
+         <key>line</key><integer>1523</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1506</integer>
+         <key>line</key><integer>1523</integer>
          <key>col</key><integer>27</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16582,7 +16582,7 @@
   <key>issue_hash_function_offset</key><string>4</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1506</integer>
+   <key>line</key><integer>1523</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16590,11 +16590,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1502</integer>
-    <integer>1503</integer>
-    <integer>1504</integer>
-    <integer>1505</integer>
-    <integer>1506</integer>
+    <integer>1519</integer>
+    <integer>1520</integer>
+    <integer>1521</integer>
+    <integer>1522</integer>
+    <integer>1523</integer>
    </array>
   </dict>
   </dict>
@@ -16605,7 +16605,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1533</integer>
+      <key>line</key><integer>1550</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16613,12 +16613,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1533</integer>
+         <key>line</key><integer>1550</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1533</integer>
+         <key>line</key><integer>1550</integer>
          <key>col</key><integer>42</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16638,12 +16638,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1533</integer>
+           <key>line</key><integer>1550</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1533</integer>
+           <key>line</key><integer>1550</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16651,12 +16651,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1534</integer>
+           <key>line</key><integer>1551</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1534</integer>
+           <key>line</key><integer>1551</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16668,7 +16668,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1534</integer>
+      <key>line</key><integer>1551</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16690,7 +16690,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1534</integer>
+   <key>line</key><integer>1551</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16698,9 +16698,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1532</integer>
-    <integer>1533</integer>
-    <integer>1534</integer>
+    <integer>1549</integer>
+    <integer>1550</integer>
+    <integer>1551</integer>
    </array>
   </dict>
   </dict>
@@ -16711,7 +16711,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1537</integer>
+      <key>line</key><integer>1554</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16719,12 +16719,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1537</integer>
+         <key>line</key><integer>1554</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1537</integer>
+         <key>line</key><integer>1554</integer>
          <key>col</key><integer>44</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16744,12 +16744,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1537</integer>
+           <key>line</key><integer>1554</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1537</integer>
+           <key>line</key><integer>1554</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16757,12 +16757,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1538</integer>
+           <key>line</key><integer>1555</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1538</integer>
+           <key>line</key><integer>1555</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16774,7 +16774,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1538</integer>
+      <key>line</key><integer>1555</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16796,7 +16796,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1538</integer>
+   <key>line</key><integer>1555</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16804,9 +16804,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1536</integer>
-    <integer>1537</integer>
-    <integer>1538</integer>
+    <integer>1553</integer>
+    <integer>1554</integer>
+    <integer>1555</integer>
    </array>
   </dict>
   </dict>
@@ -16821,12 +16821,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1541</integer>
+           <key>line</key><integer>1558</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1541</integer>
+           <key>line</key><integer>1558</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16834,12 +16834,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1542</integer>
+           <key>line</key><integer>1559</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1542</integer>
+           <key>line</key><integer>1559</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16851,7 +16851,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1542</integer>
+      <key>line</key><integer>1559</integer>
       <key>col</key><integer>20</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16859,12 +16859,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1542</integer>
+         <key>line</key><integer>1559</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1542</integer>
+         <key>line</key><integer>1559</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16884,12 +16884,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1542</integer>
+           <key>line</key><integer>1559</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1542</integer>
+           <key>line</key><integer>1559</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16897,12 +16897,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1543</integer>
+           <key>line</key><integer>1560</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1543</integer>
+           <key>line</key><integer>1560</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16918,12 +16918,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1543</integer>
+           <key>line</key><integer>1560</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1543</integer>
+           <key>line</key><integer>1560</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16931,12 +16931,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1543</integer>
+           <key>line</key><integer>1560</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1543</integer>
+           <key>line</key><integer>1560</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16948,7 +16948,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1543</integer>
+      <key>line</key><integer>1560</integer>
       <key>col</key><integer>20</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16956,12 +16956,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1543</integer>
+         <key>line</key><integer>1560</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1543</integer>
+         <key>line</key><integer>1560</integer>
          <key>col</key><integer>37</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16985,7 +16985,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1543</integer>
+   <key>line</key><integer>1560</integer>
    <key>col</key><integer>20</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16993,10 +16993,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1540</integer>
-    <integer>1541</integer>
-    <integer>1542</integer>
-    <integer>1543</integer>
+    <integer>1557</integer>
+    <integer>1558</integer>
+    <integer>1559</integer>
+    <integer>1560</integer>
    </array>
   </dict>
   </dict>
@@ -17011,12 +17011,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1541</integer>
+           <key>line</key><integer>1558</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1541</integer>
+           <key>line</key><integer>1558</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17024,12 +17024,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17045,12 +17045,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17058,12 +17058,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>21</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>21</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17075,7 +17075,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1544</integer>
+      <key>line</key><integer>1561</integer>
       <key>col</key><integer>21</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17083,12 +17083,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1544</integer>
+         <key>line</key><integer>1561</integer>
          <key>col</key><integer>21</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1544</integer>
+         <key>line</key><integer>1561</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17104,7 +17104,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1544</integer>
+      <key>line</key><integer>1561</integer>
       <key>col</key><integer>20</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17112,24 +17112,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1544</integer>
+         <key>line</key><integer>1561</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1544</integer>
+         <key>line</key><integer>1561</integer>
          <key>col</key><integer>46</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>1544</integer>
+         <key>line</key><integer>1561</integer>
          <key>col</key><integer>21</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1544</integer>
+         <key>line</key><integer>1561</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17149,12 +17149,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17162,12 +17162,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17183,12 +17183,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17196,12 +17196,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1545</integer>
+           <key>line</key><integer>1562</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1545</integer>
+           <key>line</key><integer>1562</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17213,7 +17213,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1545</integer>
+      <key>line</key><integer>1562</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17235,7 +17235,7 @@
   <key>issue_hash_function_offset</key><string>4</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1545</integer>
+   <key>line</key><integer>1562</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -17243,12 +17243,12 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1540</integer>
-    <integer>1541</integer>
-    <integer>1542</integer>
-    <integer>1543</integer>
-    <integer>1544</integer>
-    <integer>1545</integer>
+    <integer>1557</integer>
+    <integer>1558</integer>
+    <integer>1559</integer>
+    <integer>1560</integer>
+    <integer>1561</integer>
+    <integer>1562</integer>
    </array>
   </dict>
   </dict>
@@ -17259,7 +17259,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1548</integer>
+      <key>line</key><integer>1565</integer>
       <key>col</key><integer>26</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17267,12 +17267,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1548</integer>
+         <key>line</key><integer>1565</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1548</integer>
+         <key>line</key><integer>1565</integer>
          <key>col</key><integer>50</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17292,12 +17292,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1548</integer>
+           <key>line</key><integer>1565</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1548</integer>
+           <key>line</key><integer>1565</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17305,12 +17305,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1549</integer>
+           <key>line</key><integer>1566</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1549</integer>
+           <key>line</key><integer>1566</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17322,7 +17322,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1549</integer>
+      <key>line</key><integer>1566</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17344,7 +17344,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1549</integer>
+   <key>line</key><integer>1566</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -17352,9 +17352,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1547</integer>
-    <integer>1548</integer>
-    <integer>1549</integer>
+    <integer>1564</integer>
+    <integer>1565</integer>
+    <integer>1566</integer>
    </array>
   </dict>
   </dict>
@@ -17365,7 +17365,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1552</integer>
+      <key>line</key><integer>1569</integer>
       <key>col</key><integer>26</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17373,12 +17373,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1552</integer>
+         <key>line</key><integer>1569</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1552</integer>
+         <key>line</key><integer>1569</integer>
          <key>col</key><integer>63</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17398,12 +17398,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1552</integer>
+           <key>line</key><integer>1569</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1552</integer>
+           <key>line</key><integer>1569</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17411,12 +17411,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1553</integer>
+           <key>line</key><integer>1570</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1553</integer>
+           <key>line</key><integer>1570</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17428,7 +17428,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1553</integer>
+      <key>line</key><integer>1570</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17450,7 +17450,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1553</integer>
+   <key>line</key><integer>1570</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -17458,9 +17458,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1551</integer>
-    <integer>1552</integer>
-    <integer>1553</integer>
+    <integer>1568</integer>
+    <integer>1569</integer>
+    <integer>1570</integer>
    </array>
   </dict>
   </dict>
@@ -17471,7 +17471,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1556</integer>
+      <key>line</key><integer>1573</integer>
       <key>col</key><integer>26</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17479,12 +17479,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1556</integer>
+         <key>line</key><integer>1573</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1556</integer>
+         <key>line</key><integer>1573</integer>
          <key>col</key><integer>63</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17504,12 +17504,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1556</integer>
+           <key>line</key><integer>1573</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1556</integer>
+           <key>line</key><integer>1573</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17517,12 +17517,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1557</integer>
+           <key>line</key><integer>1574</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1557</integer>
+           <key>line</key><integer>1574</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17538,12 +17538,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1557</integer>
+           <key>line</key><integer>1574</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1557</integer>
+           <key>line</key><integer>1574</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17551,12 +17551,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1558</integer>
+           <key>line</key><integer>1575</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1558</integer>
+           <key>line</key><integer>1575</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17568,7 +17568,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1558</integer>
+      <key>line</key><integer>1575</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17590,7 +17590,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1558</integer>
+   <key>line</key><integer>1575</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -17598,10 +17598,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1555</integer>
-    <integer>1556</integer>
-    <integer>1557</integer>
-    <integer>1558</integer>
+    <integer>1572</integer>
+    <integer>1573</integer>
+    <integer>1574</integer>
+    <integer>1575</integer>
    </array>
   </dict>
   </dict>
@@ -17612,7 +17612,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1588</integer>
+      <key>line</key><integer>1605</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17620,12 +17620,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1588</integer>
+         <key>line</key><integer>1605</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1588</integer>
+         <key>line</key><integer>1605</integer>
          <key>col</key><integer>25</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17641,7 +17641,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1588</integer>
+      <key>line</key><integer>1605</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17649,12 +17649,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1588</integer>
+         <key>line</key><integer>1605</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1588</integer>
+         <key>line</key><integer>1605</integer>
          <key>col</key><integer>25</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17678,7 +17678,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1588</integer>
+   <key>line</key><integer>1605</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -17686,8 +17686,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1587</integer>
-    <integer>1588</integer>
+    <integer>1604</integer>
+    <integer>1605</integer>
    </array>
   </dict>
   </dict>
@@ -17702,12 +17702,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17715,12 +17715,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>26</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>26</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17732,7 +17732,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1621</integer>
+      <key>line</key><integer>1638</integer>
       <key>col</key><integer>26</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17740,12 +17740,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>53</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17761,7 +17761,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1612</integer>
+      <key>line</key><integer>1629</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17779,12 +17779,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1612</integer>
+           <key>line</key><integer>1629</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1612</integer>
+           <key>line</key><integer>1629</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17792,12 +17792,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17813,12 +17813,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17826,12 +17826,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>30</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17843,7 +17843,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1613</integer>
+      <key>line</key><integer>1630</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17851,12 +17851,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1613</integer>
+         <key>line</key><integer>1630</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1613</integer>
+         <key>line</key><integer>1630</integer>
          <key>col</key><integer>32</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17872,7 +17872,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1602</integer>
+      <key>line</key><integer>1619</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17890,12 +17890,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1602</integer>
+           <key>line</key><integer>1619</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1602</integer>
+           <key>line</key><integer>1619</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17903,12 +17903,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1604</integer>
+           <key>line</key><integer>1621</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1604</integer>
+           <key>line</key><integer>1621</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17920,7 +17920,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1604</integer>
+      <key>line</key><integer>1621</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17928,12 +17928,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1604</integer>
+         <key>line</key><integer>1621</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1604</integer>
+         <key>line</key><integer>1621</integer>
          <key>col</key><integer>52</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17949,7 +17949,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1613</integer>
+      <key>line</key><integer>1630</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17957,12 +17957,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1613</integer>
+         <key>line</key><integer>1630</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1613</integer>
+         <key>line</key><integer>1630</integer>
          <key>col</key><integer>32</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17982,12 +17982,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>30</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17995,12 +17995,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18012,7 +18012,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1621</integer>
+      <key>line</key><integer>1638</integer>
       <key>col</key><integer>26</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18020,12 +18020,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>53</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18045,12 +18045,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>26</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>26</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18058,12 +18058,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>21</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>21</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18075,7 +18075,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1621</integer>
+      <key>line</key><integer>1638</integer>
       <key>col</key><integer>21</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18083,24 +18083,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>21</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>66</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>53</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18120,12 +18120,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>21</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>21</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18133,12 +18133,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18150,7 +18150,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1621</integer>
+      <key>line</key><integer>1638</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18158,12 +18158,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>66</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18187,7 +18187,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1621</integer>
+   <key>line</key><integer>1638</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -18195,13 +18195,13 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1602</integer>
-    <integer>1603</integer>
-    <integer>1604</integer>
-    <integer>1612</integer>
-    <integer>1613</integer>
+    <integer>1619</integer>
     <integer>1620</integer>
     <integer>1621</integer>
+    <integer>1629</integer>
+    <integer>1630</integer>
+    <integer>1637</integer>
+    <integer>1638</integer>
    </array>
   </dict>
   </dict>
@@ -18216,12 +18216,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18229,12 +18229,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>40</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18246,7 +18246,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1625</integer>
+      <key>line</key><integer>1642</integer>
       <key>col</key><integer>20</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18254,12 +18254,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1625</integer>
+         <key>line</key><integer>1642</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1625</integer>
+         <key>line</key><integer>1642</integer>
          <key>col</key><integer>42</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18275,7 +18275,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1602</integer>
+      <key>line</key><integer>1619</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18293,12 +18293,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1602</integer>
+           <key>line</key><integer>1619</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1602</integer>
+           <key>line</key><integer>1619</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18306,12 +18306,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1604</integer>
+           <key>line</key><integer>1621</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1604</integer>
+           <key>line</key><integer>1621</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18323,7 +18323,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1604</integer>
+      <key>line</key><integer>1621</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18331,12 +18331,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1604</integer>
+         <key>line</key><integer>1621</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1604</integer>
+         <key>line</key><integer>1621</integer>
          <key>col</key><integer>52</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18352,7 +18352,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1625</integer>
+      <key>line</key><integer>1642</integer>
       <key>col</key><integer>20</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18360,12 +18360,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1625</integer>
+         <key>line</key><integer>1642</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1625</integer>
+         <key>line</key><integer>1642</integer>
          <key>col</key><integer>42</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18385,12 +18385,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>40</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18398,12 +18398,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18415,7 +18415,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1625</integer>
+      <key>line</key><integer>1642</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18423,12 +18423,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1625</integer>
+         <key>line</key><integer>1642</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1625</integer>
+         <key>line</key><integer>1642</integer>
          <key>col</key><integer>42</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18452,7 +18452,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1625</integer>
+   <key>line</key><integer>1642</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -18460,11 +18460,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1602</integer>
-    <integer>1603</integer>
-    <integer>1604</integer>
-    <integer>1624</integer>
-    <integer>1625</integer>
+    <integer>1619</integer>
+    <integer>1620</integer>
+    <integer>1621</integer>
+    <integer>1641</integer>
+    <integer>1642</integer>
    </array>
   </dict>
   </dict>
@@ -18479,12 +18479,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18492,12 +18492,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>30</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18509,7 +18509,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1629</integer>
+      <key>line</key><integer>1646</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18517,12 +18517,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1629</integer>
+         <key>line</key><integer>1646</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1629</integer>
+         <key>line</key><integer>1646</integer>
          <key>col</key><integer>32</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18538,7 +18538,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1602</integer>
+      <key>line</key><integer>1619</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18556,12 +18556,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1602</integer>
+           <key>line</key><integer>1619</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1602</integer>
+           <key>line</key><integer>1619</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18569,12 +18569,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1604</integer>
+           <key>line</key><integer>1621</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1604</integer>
+           <key>line</key><integer>1621</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18586,7 +18586,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1604</integer>
+      <key>line</key><integer>1621</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18594,12 +18594,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1604</integer>
+         <key>line</key><integer>1621</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1604</integer>
+         <key>line</key><integer>1621</integer>
          <key>col</key><integer>52</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18615,7 +18615,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1629</integer>
+      <key>line</key><integer>1646</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18623,12 +18623,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1629</integer>
+         <key>line</key><integer>1646</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1629</integer>
+         <key>line</key><integer>1646</integer>
          <key>col</key><integer>32</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18648,12 +18648,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>30</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18661,12 +18661,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18678,7 +18678,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1629</integer>
+      <key>line</key><integer>1646</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18686,12 +18686,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1629</integer>
+         <key>line</key><integer>1646</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1629</integer>
+         <key>line</key><integer>1646</integer>
          <key>col</key><integer>32</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18715,7 +18715,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1629</integer>
+   <key>line</key><integer>1646</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -18723,11 +18723,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1602</integer>
-    <integer>1603</integer>
-    <integer>1604</integer>
-    <integer>1628</integer>
-    <integer>1629</integer>
+    <integer>1619</integer>
+    <integer>1620</integer>
+    <integer>1621</integer>
+    <integer>1645</integer>
+    <integer>1646</integer>
    </array>
   </dict>
   </dict>
@@ -18742,12 +18742,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1648</integer>
+           <key>line</key><integer>1665</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1648</integer>
+           <key>line</key><integer>1665</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18755,12 +18755,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1649</integer>
+           <key>line</key><integer>1666</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1649</integer>
+           <key>line</key><integer>1666</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18772,7 +18772,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1649</integer>
+      <key>line</key><integer>1666</integer>
       <key>col</key><integer>23</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18780,12 +18780,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1649</integer>
+         <key>line</key><integer>1666</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1649</integer>
+         <key>line</key><integer>1666</integer>
          <key>col</key><integer>82</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18805,12 +18805,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1649</integer>
+           <key>line</key><integer>1666</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1649</integer>
+           <key>line</key><integer>1666</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18818,12 +18818,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1650</integer>
+           <key>line</key><integer>1667</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1650</integer>
+           <key>line</key><integer>1667</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18835,7 +18835,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1650</integer>
+      <key>line</key><integer>1667</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18857,7 +18857,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1650</integer>
+   <key>line</key><integer>1667</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -18865,10 +18865,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1647</integer>
-    <integer>1648</integer>
-    <integer>1649</integer>
-    <integer>1650</integer>
+    <integer>1664</integer>
+    <integer>1665</integer>
+    <integer>1666</integer>
+    <integer>1667</integer>
    </array>
   </dict>
   </dict>
@@ -18883,12 +18883,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1659</integer>
+           <key>line</key><integer>1676</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1659</integer>
+           <key>line</key><integer>1676</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18896,12 +18896,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1660</integer>
+           <key>line</key><integer>1677</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1660</integer>
+           <key>line</key><integer>1677</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18913,7 +18913,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1660</integer>
+      <key>line</key><integer>1677</integer>
       <key>col</key><integer>23</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18921,12 +18921,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1660</integer>
+         <key>line</key><integer>1677</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1660</integer>
+         <key>line</key><integer>1677</integer>
          <key>col</key><integer>82</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18946,12 +18946,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1660</integer>
+           <key>line</key><integer>1677</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1660</integer>
+           <key>line</key><integer>1677</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18959,12 +18959,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18980,12 +18980,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18993,12 +18993,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19010,7 +19010,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1661</integer>
+      <key>line</key><integer>1678</integer>
       <key>col</key><integer>7</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19018,12 +19018,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1661</integer>
+         <key>line</key><integer>1678</integer>
          <key>col</key><integer>7</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1661</integer>
+         <key>line</key><integer>1678</integer>
          <key>col</key><integer>7</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19043,12 +19043,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19056,12 +19056,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1663</integer>
+           <key>line</key><integer>1680</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1663</integer>
+           <key>line</key><integer>1680</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19073,7 +19073,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1663</integer>
+      <key>line</key><integer>1680</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19095,7 +19095,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1663</integer>
+   <key>line</key><integer>1680</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -19103,11 +19103,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1658</integer>
-    <integer>1659</integer>
-    <integer>1660</integer>
-    <integer>1661</integer>
-    <integer>1663</integer>
+    <integer>1675</integer>
+    <integer>1676</integer>
+    <integer>1677</integer>
+    <integer>1678</integer>
+    <integer>1680</integer>
    </array>
   </dict>
   </dict>
@@ -19118,7 +19118,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1683</integer>
+      <key>line</key><integer>1700</integer>
       <key>col</key><integer>22</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19126,12 +19126,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1683</integer>
+         <key>line</key><integer>1700</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1683</integer>
+         <key>line</key><integer>1700</integer>
          <key>col</key><integer>53</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19151,12 +19151,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1683</integer>
+           <key>line</key><integer>1700</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1683</integer>
+           <key>line</key><integer>1700</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19164,12 +19164,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1684</integer>
+           <key>line</key><integer>1701</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1684</integer>
+           <key>line</key><integer>1701</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19181,7 +19181,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1684</integer>
+      <key>line</key><integer>1701</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19189,12 +19189,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1684</integer>
+         <key>line</key><integer>1701</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1684</integer>
+         <key>line</key><integer>1701</integer>
          <key>col</key><integer>7</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19218,7 +19218,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1684</integer>
+   <key>line</key><integer>1701</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -19226,9 +19226,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1682</integer>
-    <integer>1683</integer>
-    <integer>1684</integer>
+    <integer>1699</integer>
+    <integer>1700</integer>
+    <integer>1701</integer>
    </array>
   </dict>
   </dict>
@@ -19239,7 +19239,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1704</integer>
+      <key>line</key><integer>1721</integer>
       <key>col</key><integer>22</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19247,12 +19247,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1704</integer>
+         <key>line</key><integer>1721</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1704</integer>
+         <key>line</key><integer>1721</integer>
          <key>col</key><integer>53</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19272,12 +19272,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1704</integer>
+           <key>line</key><integer>1721</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1704</integer>
+           <key>line</key><integer>1721</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19285,12 +19285,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19302,7 +19302,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1705</integer>
+      <key>line</key><integer>1722</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19310,12 +19310,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>39</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19331,7 +19331,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1705</integer>
+      <key>line</key><integer>1722</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19349,12 +19349,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19362,12 +19362,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19379,7 +19379,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1705</integer>
+      <key>line</key><integer>1722</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19387,24 +19387,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>28</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19420,7 +19420,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1705</integer>
+      <key>line</key><integer>1722</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19428,12 +19428,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>39</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19453,12 +19453,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19466,12 +19466,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1706</integer>
+           <key>line</key><integer>1723</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1706</integer>
+           <key>line</key><integer>1723</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19483,7 +19483,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1706</integer>
+      <key>line</key><integer>1723</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19505,7 +19505,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1706</integer>
+   <key>line</key><integer>1723</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -19513,10 +19513,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1703</integer>
-    <integer>1704</integer>
-    <integer>1705</integer>
-    <integer>1706</integer>
+    <integer>1720</integer>
+    <integer>1721</integer>
+    <integer>1722</integer>
+    <integer>1723</integer>
    </array>
   </dict>
   </dict>
@@ -19531,12 +19531,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1752</integer>
+           <key>line</key><integer>1769</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1752</integer>
+           <key>line</key><integer>1769</integer>
            <key>col</key><integer>14</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19544,12 +19544,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19565,12 +19565,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19578,12 +19578,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19595,7 +19595,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1755</integer>
+      <key>line</key><integer>1772</integer>
       <key>col</key><integer>12</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19603,12 +19603,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1755</integer>
+         <key>line</key><integer>1772</integer>
          <key>col</key><integer>12</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1755</integer>
+         <key>line</key><integer>1772</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19624,7 +19624,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1755</integer>
+      <key>line</key><integer>1772</integer>
       <key>col</key><integer>12</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19632,12 +19632,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1755</integer>
+         <key>line</key><integer>1772</integer>
          <key>col</key><integer>12</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1755</integer>
+         <key>line</key><integer>1772</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19657,12 +19657,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19670,12 +19670,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1756</integer>
+           <key>line</key><integer>1773</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1756</integer>
+           <key>line</key><integer>1773</integer>
            <key>col</key><integer>23</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19691,12 +19691,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1756</integer>
+           <key>line</key><integer>1773</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1756</integer>
+           <key>line</key><integer>1773</integer>
            <key>col</key><integer>23</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19704,12 +19704,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1758</integer>
+           <key>line</key><integer>1775</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1758</integer>
+           <key>line</key><integer>1775</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19721,7 +19721,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1758</integer>
+      <key>line</key><integer>1775</integer>
       <key>col</key><integer>16</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19729,12 +19729,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1758</integer>
+         <key>line</key><integer>1775</integer>
          <key>col</key><integer>16</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1758</integer>
+         <key>line</key><integer>1775</integer>
          <key>col</key><integer>49</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19754,12 +19754,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1758</integer>
+           <key>line</key><integer>1775</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1758</integer>
+           <key>line</key><integer>1775</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19767,12 +19767,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19788,12 +19788,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19801,12 +19801,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19818,7 +19818,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1760</integer>
+      <key>line</key><integer>1777</integer>
       <key>col</key><integer>13</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19826,12 +19826,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1760</integer>
+         <key>line</key><integer>1777</integer>
          <key>col</key><integer>13</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1760</integer>
+         <key>line</key><integer>1777</integer>
          <key>col</key><integer>30</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19851,12 +19851,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19864,12 +19864,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1763</integer>
+           <key>line</key><integer>1780</integer>
            <key>col</key><integer>23</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1763</integer>
+           <key>line</key><integer>1780</integer>
            <key>col</key><integer>23</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19881,7 +19881,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1763</integer>
+      <key>line</key><integer>1780</integer>
       <key>col</key><integer>23</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19903,7 +19903,7 @@
   <key>issue_hash_function_offset</key><string>7</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1763</integer>
+   <key>line</key><integer>1780</integer>
    <key>col</key><integer>23</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -19911,15 +19911,15 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1750</integer>
-    <integer>1751</integer>
-    <integer>1752</integer>
-    <integer>1754</integer>
-    <integer>1755</integer>
-    <integer>1756</integer>
-    <integer>1758</integer>
-    <integer>1760</integer>
-    <integer>1763</integer>
+    <integer>1767</integer>
+    <integer>1768</integer>
+    <integer>1769</integer>
+    <integer>1771</integer>
+    <integer>1772</integer>
+    <integer>1773</integer>
+    <integer>1775</integer>
+    <integer>1777</integer>
+    <integer>1780</integer>
    </array>
   </dict>
   </dict>
@@ -19930,7 +19930,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1806</integer>
+      <key>line</key><integer>1823</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19938,12 +19938,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1806</integer>
+         <key>line</key><integer>1823</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1806</integer>
+         <key>line</key><integer>1823</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19959,7 +19959,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1806</integer>
+      <key>line</key><integer>1823</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19967,12 +19967,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1806</integer>
+         <key>line</key><integer>1823</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1806</integer>
+         <key>line</key><integer>1823</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19996,7 +19996,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1806</integer>
+   <key>line</key><integer>1823</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -20004,8 +20004,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1805</integer>
-    <integer>1806</integer>
+    <integer>1822</integer>
+    <integer>1823</integer>
    </array>
   </dict>
   </dict>
@@ -20016,7 +20016,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1814</integer>
+      <key>line</key><integer>1831</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20024,12 +20024,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1814</integer>
+         <key>line</key><integer>1831</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1814</integer>
+         <key>line</key><integer>1831</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20045,7 +20045,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1814</integer>
+      <key>line</key><integer>1831</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20053,12 +20053,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1814</integer>
+         <key>line</key><integer>1831</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1814</integer>
+         <key>line</key><integer>1831</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20082,7 +20082,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1814</integer>
+   <key>line</key><integer>1831</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -20090,8 +20090,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1813</integer>
-    <integer>1814</integer>
+    <integer>1830</integer>
+    <integer>1831</integer>
    </array>
   </dict>
   </dict>
@@ -20102,7 +20102,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1835</integer>
+      <key>line</key><integer>1852</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20110,12 +20110,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1835</integer>
+         <key>line</key><integer>1852</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1835</integer>
+         <key>line</key><integer>1852</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20131,7 +20131,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1835</integer>
+      <key>line</key><integer>1852</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20139,12 +20139,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1835</integer>
+         <key>line</key><integer>1852</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1835</integer>
+         <key>line</key><integer>1852</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20168,7 +20168,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1835</integer>
+   <key>line</key><integer>1852</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -20176,8 +20176,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1834</integer>
-    <integer>1835</integer>
+    <integer>1851</integer>
+    <integer>1852</integer>
    </array>
   </dict>
   </dict>
@@ -20188,7 +20188,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1847</integer>
+      <key>line</key><integer>1864</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20196,12 +20196,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1847</integer>
+         <key>line</key><integer>1864</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1847</integer>
+         <key>line</key><integer>1864</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20217,7 +20217,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1847</integer>
+      <key>line</key><integer>1864</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20225,12 +20225,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1847</integer>
+         <key>line</key><integer>1864</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1847</integer>
+         <key>line</key><integer>1864</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20254,7 +20254,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1847</integer>
+   <key>line</key><integer>1864</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -20262,8 +20262,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1846</integer>
-    <integer>1847</integer>
+    <integer>1863</integer>
+    <integer>1864</integer>
    </array>
   </dict>
   </dict>
@@ -20278,12 +20278,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1865</integer>
+           <key>line</key><integer>1882</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1865</integer>
+           <key>line</key><integer>1882</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20291,12 +20291,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1866</integer>
+           <key>line</key><integer>1883</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1866</integer>
+           <key>line</key><integer>1883</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20308,7 +20308,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1866</integer>
+      <key>line</key><integer>1883</integer>
       <key>col</key><integer>24</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20316,12 +20316,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1866</integer>
+         <key>line</key><integer>1883</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1866</integer>
+         <key>line</key><integer>1883</integer>
          <key>col</key><integer>41</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20341,12 +20341,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1866</integer>
+           <key>line</key><integer>1883</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1866</integer>
+           <key>line</key><integer>1883</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20354,12 +20354,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1867</integer>
+           <key>line</key><integer>1884</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1867</integer>
+           <key>line</key><integer>1884</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20371,7 +20371,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1867</integer>
+      <key>line</key><integer>1884</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20393,7 +20393,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1867</integer>
+   <key>line</key><integer>1884</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -20401,10 +20401,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1864</integer>
-    <integer>1865</integer>
-    <integer>1866</integer>
-    <integer>1867</integer>
+    <integer>1881</integer>
+    <integer>1882</integer>
+    <integer>1883</integer>
+    <integer>1884</integer>
    </array>
   </dict>
   </dict>
@@ -20419,12 +20419,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1889</integer>
+           <key>line</key><integer>1906</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1889</integer>
+           <key>line</key><integer>1906</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20432,12 +20432,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1891</integer>
+           <key>line</key><integer>1908</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1891</integer>
+           <key>line</key><integer>1908</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20449,7 +20449,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1891</integer>
+      <key>line</key><integer>1908</integer>
       <key>col</key><integer>22</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20457,12 +20457,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1891</integer>
+         <key>line</key><integer>1908</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1891</integer>
+         <key>line</key><integer>1908</integer>
          <key>col</key><integer>64</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20482,12 +20482,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1891</integer>
+           <key>line</key><integer>1908</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1891</integer>
+           <key>line</key><integer>1908</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20495,12 +20495,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1892</integer>
+           <key>line</key><integer>1909</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1892</integer>
+           <key>line</key><integer>1909</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20512,7 +20512,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1892</integer>
+      <key>line</key><integer>1909</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20520,24 +20520,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1892</integer>
+         <key>line</key><integer>1909</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1892</integer>
+         <key>line</key><integer>1909</integer>
          <key>col</key><integer>18</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>1892</integer>
+         <key>line</key><integer>1909</integer>
          <key>col</key><integer>4</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1892</integer>
+         <key>line</key><integer>1909</integer>
          <key>col</key><integer>9</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20557,12 +20557,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1892</integer>
+           <key>line</key><integer>1909</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1892</integer>
+           <key>line</key><integer>1909</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20570,12 +20570,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1894</integer>
+           <key>line</key><integer>1911</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1894</integer>
+           <key>line</key><integer>1911</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20591,12 +20591,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1894</integer>
+           <key>line</key><integer>1911</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1894</integer>
+           <key>line</key><integer>1911</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20604,12 +20604,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1894</integer>
+           <key>line</key><integer>1911</integer>
            <key>col</key><integer>27</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1894</integer>
+           <key>line</key><integer>1911</integer>
            <key>col</key><integer>27</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20621,7 +20621,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1894</integer>
+      <key>line</key><integer>1911</integer>
       <key>col</key><integer>27</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20629,12 +20629,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1894</integer>
+         <key>line</key><integer>1911</integer>
          <key>col</key><integer>28</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1894</integer>
+         <key>line</key><integer>1911</integer>
          <key>col</key><integer>33</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20658,7 +20658,7 @@
   <key>issue_hash_function_offset</key><string>6</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1894</integer>
+   <key>line</key><integer>1911</integer>
    <key>col</key><integer>27</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -20666,11 +20666,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1888</integer>
-    <integer>1889</integer>
-    <integer>1891</integer>
-    <integer>1892</integer>
-    <integer>1894</integer>
+    <integer>1905</integer>
+    <integer>1906</integer>
+    <integer>1908</integer>
+    <integer>1909</integer>
+    <integer>1911</integer>
    </array>
   </dict>
   </dict>
@@ -20685,12 +20685,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20698,12 +20698,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2020</integer>
+           <key>line</key><integer>2037</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2020</integer>
+           <key>line</key><integer>2037</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20715,7 +20715,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2020</integer>
+      <key>line</key><integer>2037</integer>
       <key>col</key><integer>22</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20723,12 +20723,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2020</integer>
+         <key>line</key><integer>2037</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2020</integer>
+         <key>line</key><integer>2037</integer>
          <key>col</key><integer>66</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20748,12 +20748,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2020</integer>
+           <key>line</key><integer>2037</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2020</integer>
+           <key>line</key><integer>2037</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20761,12 +20761,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20778,7 +20778,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2023</integer>
+      <key>line</key><integer>2040</integer>
       <key>col</key><integer>9</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20786,12 +20786,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2023</integer>
+         <key>line</key><integer>2040</integer>
          <key>col</key><integer>9</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2023</integer>
+         <key>line</key><integer>2040</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20815,7 +20815,7 @@
   <key>issue_hash_function_offset</key><string>3</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2023</integer>
+   <key>line</key><integer>2040</integer>
    <key>col</key><integer>9</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -20823,12 +20823,12 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2017</integer>
-    <integer>2019</integer>
-    <integer>2020</integer>
-    <integer>2021</integer>
-    <integer>2022</integer>
-    <integer>2023</integer>
+    <integer>2034</integer>
+    <integer>2036</integer>
+    <integer>2037</integer>
+    <integer>2038</integer>
+    <integer>2039</integer>
+    <integer>2040</integer>
    </array>
   </dict>
   </dict>
@@ -20843,12 +20843,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20856,12 +20856,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20877,12 +20877,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20890,12 +20890,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20911,12 +20911,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20924,12 +20924,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2029</integer>
+           <key>line</key><integer>2046</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2029</integer>
+           <key>line</key><integer>2046</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20941,7 +20941,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2029</integer>
+      <key>line</key><integer>2046</integer>
       <key>col</key><integer>23</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20949,12 +20949,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2029</integer>
+         <key>line</key><integer>2046</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2029</integer>
+         <key>line</key><integer>2046</integer>
          <key>col</key><integer>56</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20974,12 +20974,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2029</integer>
+           <key>line</key><integer>2046</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2029</integer>
+           <key>line</key><integer>2046</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20987,12 +20987,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21004,7 +21004,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2032</integer>
+      <key>line</key><integer>2049</integer>
       <key>col</key><integer>9</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -21012,12 +21012,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2032</integer>
+         <key>line</key><integer>2049</integer>
          <key>col</key><integer>9</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2032</integer>
+         <key>line</key><integer>2049</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -21041,7 +21041,7 @@
   <key>issue_hash_function_offset</key><string>12</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2032</integer>
+   <key>line</key><integer>2049</integer>
    <key>col</key><integer>9</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -21049,18 +21049,18 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2017</integer>
-    <integer>2019</integer>
-    <integer>2020</integer>
-    <integer>2021</integer>
-    <integer>2022</integer>
-    <integer>2023</integer>
-    <integer>2027</integer>
-    <integer>2028</integer>
-    <integer>2029</integer>
-    <integer>2030</integer>
-    <integer>2031</integer>
-    <integer>2032</integer>
+    <integer>2034</integer>
+    <integer>2036</integer>
+    <integer>2037</integer>
+    <integer>2038</integer>
+    <integer>2039</integer>
+    <integer>2040</integer>
+    <integer>2044</integer>
+    <integer>2045</integer>
+    <integer>2046</integer>
+    <integer>2047</integer>
+    <integer>2048</integer>
+    <integer>2049</integer>
    </array>
   </dict>
   </dict>
@@ -21075,12 +21075,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21088,12 +21088,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21109,12 +21109,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21122,12 +21122,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21143,12 +21143,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21156,12 +21156,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21177,12 +21177,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21190,12 +21190,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21211,12 +21211,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21224,12 +21224,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21245,12 +21245,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21258,12 +21258,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21275,7 +21275,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2037</integer>
+      <key>line</key><integer>2054</integer>
       <key>col</key><integer>24</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -21283,12 +21283,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2037</integer>
+         <key>line</key><integer>2054</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2037</integer>
+         <key>line</key><integer>2054</integer>
          <key>col</key><integer>27</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -21304,7 +21304,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2037</integer>
+      <key>line</key><integer>2054</integer>
       <key>col</key><integer>23</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -21312,24 +21312,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2037</integer>
+         <key>line</key><integer>2054</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2037</integer>
+         <key>line</key><integer>2054</integer>
          <key>col</key><integer>35</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2037</integer>
+         <key>line</key><integer>2054</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2037</integer>
+         <key>line</key><integer>2054</integer>
          <key>col</key><integer>27</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -21349,12 +21349,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>23</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>23</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21362,12 +21362,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21383,12 +21383,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21396,12 +21396,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21413,7 +21413,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2040</integer>
+      <key>line</key><integer>2057</integer>
       <key>col</key><integer>9</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -21421,12 +21421,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2040</integer>
+         <key>line</key><integer>2057</integer>
          <key>col</key><integer>9</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2040</integer>
+         <key>line</key><integer>2057</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -21450,7 +21450,7 @@
   <key>issue_hash_function_offset</key><string>20</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2040</integer>
+   <key>line</key><integer>2057</integer>
    <key>col</key><integer>9</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -21458,23 +21458,23 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2017</integer>
-    <integer>2019</integer>
-    <integer>2020</integer>
-    <integer>2021</integer>
-    <integer>2022</integer>
-    <integer>2023</integer>
-    <integer>2027</integer>
-    <integer>2028</integer>
-    <integer>2029</integer>
-    <integer>2030</integer>
-    <integer>2031</integer>
-    <integer>2032</integer>
+    <integer>2034</integer>
     <integer>2036</integer>
     <integer>2037</integer>
     <integer>2038</integer>
     <integer>2039</integer>
     <integer>2040</integer>
+    <integer>2044</integer>
+    <integer>2045</integer>
+    <integer>2046</integer>
+    <integer>2047</integer>
+    <integer>2048</integer>
+    <integer>2049</integer>
+    <integer>2053</integer>
+    <integer>2054</integer>
+    <integer>2055</integer>
+    <integer>2056</integer>
+    <integer>2057</integer>
    </array>
   </dict>
   </dict>
@@ -21489,12 +21489,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21502,12 +21502,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21523,12 +21523,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21536,12 +21536,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21557,12 +21557,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21570,12 +21570,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21591,12 +21591,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21604,12 +21604,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21625,12 +21625,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21638,12 +21638,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21659,12 +21659,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21672,12 +21672,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21693,12 +21693,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21706,12 +21706,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2045</integer>
+           <key>line</key><integer>2062</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2045</integer>
+           <key>line</key><integer>2062</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21723,7 +21723,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2045</integer>
+      <key>line</key><integer>2062</integer>
       <key>col</key><integer>22</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -21731,12 +21731,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2045</integer>
+         <key>line</key><integer>2062</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2045</integer>
+         <key>line</key><integer>2062</integer>
          <key>col</key><integer>57</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -21756,12 +21756,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2045</integer>
+           <key>line</key><integer>2062</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2045</integer>
+           <key>line</key><integer>2062</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21769,12 +21769,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2049</integer>
+           <key>line</key><integer>2066</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2049</integer>
+           <key>line</key><integer>2066</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21786,7 +21786,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2049</integer>
+      <key>line</key><integer>2066</integer>
       <key>col</key><integer>9</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -21794,12 +21794,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2049</integer>
+         <key>line</key><integer>2066</integer>
          <key>col</key><integer>9</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2049</integer>
+         <key>line</key><integer>2066</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -21823,7 +21823,7 @@
   <key>issue_hash_function_offset</key><string>28</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2049</integer>
+   <key>line</key><integer>2066</integer>
    <key>col</key><integer>9</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -21831,18 +21831,7 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2017</integer>
-    <integer>2019</integer>
-    <integer>2020</integer>
-    <integer>2021</integer>
-    <integer>2022</integer>
-    <integer>2023</integer>
-    <integer>2027</integer>
-    <integer>2028</integer>
-    <integer>2029</integer>
-    <integer>2030</integer>
-    <integer>2031</integer>
-    <integer>2032</integer>
+    <integer>2034</integer>
     <integer>2036</integer>
     <integer>2037</integer>
     <integer>2038</integer>
@@ -21851,8 +21840,19 @@
     <integer>2044</integer>
     <integer>2045</integer>
     <integer>2046</integer>
+    <integer>2047</integer>
     <integer>2048</integer>
     <integer>2049</integer>
+    <integer>2053</integer>
+    <integer>2054</integer>
+    <integer>2055</integer>
+    <integer>2056</integer>
+    <integer>2057</integer>
+    <integer>2061</integer>
+    <integer>2062</integer>
+    <integer>2063</integer>
+    <integer>2065</integer>
+    <integer>2066</integer>
    </array>
   </dict>
   </dict>
@@ -21867,12 +21867,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21880,12 +21880,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21901,12 +21901,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21914,12 +21914,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21935,12 +21935,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21948,12 +21948,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21969,12 +21969,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21982,12 +21982,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22003,12 +22003,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22016,12 +22016,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22037,12 +22037,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22050,12 +22050,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22071,12 +22071,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22084,12 +22084,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2049</integer>
+           <key>line</key><integer>2066</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2049</integer>
+           <key>line</key><integer>2066</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22105,12 +22105,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2049</integer>
+           <key>line</key><integer>2066</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2049</integer>
+           <key>line</key><integer>2066</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22118,12 +22118,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2053</integer>
+           <key>line</key><integer>2070</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2053</integer>
+           <key>line</key><integer>2070</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22139,12 +22139,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2053</integer>
+           <key>line</key><integer>2070</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2053</integer>
+           <key>line</key><integer>2070</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22152,12 +22152,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22173,12 +22173,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22186,12 +22186,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>28</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>28</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22203,7 +22203,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2054</integer>
+      <key>line</key><integer>2071</integer>
       <key>col</key><integer>28</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22211,12 +22211,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2054</integer>
+         <key>line</key><integer>2071</integer>
          <key>col</key><integer>28</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2054</integer>
+         <key>line</key><integer>2071</integer>
          <key>col</key><integer>35</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22232,7 +22232,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2054</integer>
+      <key>line</key><integer>2071</integer>
       <key>col</key><integer>27</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22240,24 +22240,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2054</integer>
+         <key>line</key><integer>2071</integer>
          <key>col</key><integer>27</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2054</integer>
+         <key>line</key><integer>2071</integer>
          <key>col</key><integer>43</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2054</integer>
+         <key>line</key><integer>2071</integer>
          <key>col</key><integer>28</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2054</integer>
+         <key>line</key><integer>2071</integer>
          <key>col</key><integer>35</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22277,12 +22277,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>27</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>27</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22290,12 +22290,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22311,12 +22311,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22324,12 +22324,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2058</integer>
+           <key>line</key><integer>2075</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2058</integer>
+           <key>line</key><integer>2075</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22341,7 +22341,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2058</integer>
+      <key>line</key><integer>2075</integer>
       <key>col</key><integer>9</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22349,12 +22349,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2058</integer>
+         <key>line</key><integer>2075</integer>
          <key>col</key><integer>9</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2058</integer>
+         <key>line</key><integer>2075</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22378,7 +22378,7 @@
   <key>issue_hash_function_offset</key><string>37</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2058</integer>
+   <key>line</key><integer>2075</integer>
    <key>col</key><integer>9</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -22386,18 +22386,7 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2017</integer>
-    <integer>2019</integer>
-    <integer>2020</integer>
-    <integer>2021</integer>
-    <integer>2022</integer>
-    <integer>2023</integer>
-    <integer>2027</integer>
-    <integer>2028</integer>
-    <integer>2029</integer>
-    <integer>2030</integer>
-    <integer>2031</integer>
-    <integer>2032</integer>
+    <integer>2034</integer>
     <integer>2036</integer>
     <integer>2037</integer>
     <integer>2038</integer>
@@ -22406,13 +22395,24 @@
     <integer>2044</integer>
     <integer>2045</integer>
     <integer>2046</integer>
+    <integer>2047</integer>
     <integer>2048</integer>
     <integer>2049</integer>
     <integer>2053</integer>
     <integer>2054</integer>
     <integer>2055</integer>
+    <integer>2056</integer>
     <integer>2057</integer>
-    <integer>2058</integer>
+    <integer>2061</integer>
+    <integer>2062</integer>
+    <integer>2063</integer>
+    <integer>2065</integer>
+    <integer>2066</integer>
+    <integer>2070</integer>
+    <integer>2071</integer>
+    <integer>2072</integer>
+    <integer>2074</integer>
+    <integer>2075</integer>
    </array>
   </dict>
   </dict>
@@ -22427,12 +22427,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22440,12 +22440,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22457,7 +22457,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2063</integer>
+      <key>line</key><integer>2080</integer>
       <key>col</key><integer>15</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22465,12 +22465,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2063</integer>
+         <key>line</key><integer>2080</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2063</integer>
+         <key>line</key><integer>2080</integer>
          <key>col</key><integer>16</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22486,7 +22486,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2063</integer>
+      <key>line</key><integer>2080</integer>
       <key>col</key><integer>14</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22494,24 +22494,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2063</integer>
+         <key>line</key><integer>2080</integer>
          <key>col</key><integer>14</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2063</integer>
+         <key>line</key><integer>2080</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2063</integer>
+         <key>line</key><integer>2080</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2063</integer>
+         <key>line</key><integer>2080</integer>
          <key>col</key><integer>16</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22531,12 +22531,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>14</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>14</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22544,12 +22544,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22565,12 +22565,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22578,12 +22578,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2064</integer>
+           <key>line</key><integer>2081</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2064</integer>
+           <key>line</key><integer>2081</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22599,12 +22599,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2064</integer>
+           <key>line</key><integer>2081</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2064</integer>
+           <key>line</key><integer>2081</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22612,12 +22612,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2065</integer>
+           <key>line</key><integer>2082</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2065</integer>
+           <key>line</key><integer>2082</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22629,7 +22629,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2065</integer>
+      <key>line</key><integer>2082</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22651,7 +22651,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2065</integer>
+   <key>line</key><integer>2082</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -22659,10 +22659,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2062</integer>
-    <integer>2063</integer>
-    <integer>2064</integer>
-    <integer>2065</integer>
+    <integer>2079</integer>
+    <integer>2080</integer>
+    <integer>2081</integer>
+    <integer>2082</integer>
    </array>
   </dict>
   </dict>
@@ -22677,12 +22677,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22690,12 +22690,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22707,7 +22707,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2068</integer>
+      <key>line</key><integer>2085</integer>
       <key>col</key><integer>15</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22715,12 +22715,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2068</integer>
+         <key>line</key><integer>2085</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2068</integer>
+         <key>line</key><integer>2085</integer>
          <key>col</key><integer>18</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22736,7 +22736,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2068</integer>
+      <key>line</key><integer>2085</integer>
       <key>col</key><integer>14</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22744,24 +22744,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2068</integer>
+         <key>line</key><integer>2085</integer>
          <key>col</key><integer>14</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2068</integer>
+         <key>line</key><integer>2085</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2068</integer>
+         <key>line</key><integer>2085</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2068</integer>
+         <key>line</key><integer>2085</integer>
          <key>col</key><integer>18</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22781,12 +22781,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>14</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>14</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22794,12 +22794,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22815,12 +22815,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22828,12 +22828,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2072</integer>
+           <key>line</key><integer>2089</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2072</integer>
+           <key>line</key><integer>2089</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22845,7 +22845,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2072</integer>
+      <key>line</key><integer>2089</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22853,12 +22853,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2072</integer>
+         <key>line</key><integer>2089</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2072</integer>
+         <key>line</key><integer>2089</integer>
          <key>col</key><integer>21</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22882,7 +22882,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2072</integer>
+   <key>line</key><integer>2089</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -22890,11 +22890,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2067</integer>
-    <integer>2068</integer>
-    <integer>2069</integer>
-    <integer>2071</integer>
-    <integer>2072</integer>
+    <integer>2084</integer>
+    <integer>2085</integer>
+    <integer>2086</integer>
+    <integer>2088</integer>
+    <integer>2089</integer>
    </array>
   </dict>
   </dict>
@@ -22909,12 +22909,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22922,12 +22922,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22943,12 +22943,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22956,12 +22956,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22973,7 +22973,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2071</integer>
+      <key>line</key><integer>2088</integer>
       <key>col</key><integer>12</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22981,12 +22981,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2071</integer>
+         <key>line</key><integer>2088</integer>
          <key>col</key><integer>12</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2071</integer>
+         <key>line</key><integer>2088</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23002,7 +23002,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2071</integer>
+      <key>line</key><integer>2088</integer>
       <key>col</key><integer>11</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23010,24 +23010,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2071</integer>
+         <key>line</key><integer>2088</integer>
          <key>col</key><integer>11</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2071</integer>
+         <key>line</key><integer>2088</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2071</integer>
+         <key>line</key><integer>2088</integer>
          <key>col</key><integer>12</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2071</integer>
+         <key>line</key><integer>2088</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23047,12 +23047,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23060,12 +23060,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23081,12 +23081,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23094,12 +23094,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2072</integer>
+           <key>line</key><integer>2089</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2072</integer>
+           <key>line</key><integer>2089</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23115,12 +23115,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2072</integer>
+           <key>line</key><integer>2089</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2072</integer>
+           <key>line</key><integer>2089</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23128,12 +23128,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2073</integer>
+           <key>line</key><integer>2090</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2073</integer>
+           <key>line</key><integer>2090</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23145,7 +23145,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2073</integer>
+      <key>line</key><integer>2090</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23167,7 +23167,7 @@
   <key>issue_hash_function_offset</key><string>4</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2073</integer>
+   <key>line</key><integer>2090</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -23175,12 +23175,12 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2067</integer>
-    <integer>2068</integer>
-    <integer>2069</integer>
-    <integer>2071</integer>
-    <integer>2072</integer>
-    <integer>2073</integer>
+    <integer>2084</integer>
+    <integer>2085</integer>
+    <integer>2086</integer>
+    <integer>2088</integer>
+    <integer>2089</integer>
+    <integer>2090</integer>
    </array>
   </dict>
   </dict>
@@ -23195,12 +23195,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2079</integer>
+           <key>line</key><integer>2096</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2079</integer>
+           <key>line</key><integer>2096</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23208,12 +23208,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>6</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23229,12 +23229,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>6</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23242,12 +23242,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23259,7 +23259,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2080</integer>
+      <key>line</key><integer>2097</integer>
       <key>col</key><integer>8</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23267,12 +23267,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2080</integer>
+         <key>line</key><integer>2097</integer>
          <key>col</key><integer>8</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2080</integer>
+         <key>line</key><integer>2097</integer>
          <key>col</key><integer>12</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23292,12 +23292,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23305,12 +23305,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2083</integer>
+           <key>line</key><integer>2100</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2083</integer>
+           <key>line</key><integer>2100</integer>
            <key>col</key><integer>17</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23322,7 +23322,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2083</integer>
+      <key>line</key><integer>2100</integer>
       <key>col</key><integer>21</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23330,12 +23330,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2083</integer>
+         <key>line</key><integer>2100</integer>
          <key>col</key><integer>21</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2083</integer>
+         <key>line</key><integer>2100</integer>
          <key>col</key><integer>43</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23355,12 +23355,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2083</integer>
+           <key>line</key><integer>2100</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2083</integer>
+           <key>line</key><integer>2100</integer>
            <key>col</key><integer>17</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23368,12 +23368,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2084</integer>
+           <key>line</key><integer>2101</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2084</integer>
+           <key>line</key><integer>2101</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23389,12 +23389,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2084</integer>
+           <key>line</key><integer>2101</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2084</integer>
+           <key>line</key><integer>2101</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23402,12 +23402,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2085</integer>
+           <key>line</key><integer>2102</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2085</integer>
+           <key>line</key><integer>2102</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23419,7 +23419,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2085</integer>
+      <key>line</key><integer>2102</integer>
       <key>col</key><integer>5</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23427,24 +23427,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2085</integer>
+         <key>line</key><integer>2102</integer>
          <key>col</key><integer>5</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2085</integer>
+         <key>line</key><integer>2102</integer>
          <key>col</key><integer>25</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2085</integer>
+         <key>line</key><integer>2102</integer>
          <key>col</key><integer>6</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2085</integer>
+         <key>line</key><integer>2102</integer>
          <key>col</key><integer>16</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23464,12 +23464,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2085</integer>
+           <key>line</key><integer>2102</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2085</integer>
+           <key>line</key><integer>2102</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23477,12 +23477,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2086</integer>
+           <key>line</key><integer>2103</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2086</integer>
+           <key>line</key><integer>2103</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23494,7 +23494,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2086</integer>
+      <key>line</key><integer>2103</integer>
       <key>col</key><integer>5</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23502,12 +23502,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2086</integer>
+         <key>line</key><integer>2103</integer>
          <key>col</key><integer>25</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2086</integer>
+         <key>line</key><integer>2103</integer>
          <key>col</key><integer>35</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23531,7 +23531,7 @@
   <key>issue_hash_function_offset</key><string>9</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2086</integer>
+   <key>line</key><integer>2103</integer>
    <key>col</key><integer>5</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -23539,14 +23539,14 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2076</integer>
-    <integer>2077</integer>
-    <integer>2079</integer>
-    <integer>2080</integer>
-    <integer>2083</integer>
-    <integer>2084</integer>
-    <integer>2085</integer>
-    <integer>2086</integer>
+    <integer>2093</integer>
+    <integer>2094</integer>
+    <integer>2096</integer>
+    <integer>2097</integer>
+    <integer>2100</integer>
+    <integer>2101</integer>
+    <integer>2102</integer>
+    <integer>2103</integer>
    </array>
   </dict>
   </dict>
@@ -23561,12 +23561,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2104</integer>
+           <key>line</key><integer>2121</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2104</integer>
+           <key>line</key><integer>2121</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23574,12 +23574,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2112</integer>
+           <key>line</key><integer>2129</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2112</integer>
+           <key>line</key><integer>2129</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23591,7 +23591,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2112</integer>
+      <key>line</key><integer>2129</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23599,12 +23599,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2112</integer>
+         <key>line</key><integer>2129</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2112</integer>
+         <key>line</key><integer>2129</integer>
          <key>col</key><integer>21</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23624,12 +23624,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2112</integer>
+           <key>line</key><integer>2129</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2112</integer>
+           <key>line</key><integer>2129</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23637,12 +23637,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2113</integer>
+           <key>line</key><integer>2130</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2113</integer>
+           <key>line</key><integer>2130</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23654,7 +23654,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2113</integer>
+      <key>line</key><integer>2130</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23662,12 +23662,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2113</integer>
+         <key>line</key><integer>2130</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2113</integer>
+         <key>line</key><integer>2130</integer>
          <key>col</key><integer>35</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23691,7 +23691,7 @@
   <key>issue_hash_function_offset</key><string>10</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2113</integer>
+   <key>line</key><integer>2130</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -23699,13 +23699,13 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2103</integer>
-    <integer>2104</integer>
-    <integer>2105</integer>
-    <integer>2107</integer>
-    <integer>2108</integer>
-    <integer>2112</integer>
-    <integer>2113</integer>
+    <integer>2120</integer>
+    <integer>2121</integer>
+    <integer>2122</integer>
+    <integer>2124</integer>
+    <integer>2125</integer>
+    <integer>2129</integer>
+    <integer>2130</integer>
    </array>
   </dict>
   </dict>
@@ -23720,12 +23720,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2117</integer>
+           <key>line</key><integer>2134</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2117</integer>
+           <key>line</key><integer>2134</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23733,12 +23733,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2125</integer>
+           <key>line</key><integer>2142</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2125</integer>
+           <key>line</key><integer>2142</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23750,7 +23750,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2125</integer>
+      <key>line</key><integer>2142</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23758,12 +23758,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2125</integer>
+         <key>line</key><integer>2142</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2125</integer>
+         <key>line</key><integer>2142</integer>
          <key>col</key><integer>21</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23783,12 +23783,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2125</integer>
+           <key>line</key><integer>2142</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2125</integer>
+           <key>line</key><integer>2142</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23796,12 +23796,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2126</integer>
+           <key>line</key><integer>2143</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2126</integer>
+           <key>line</key><integer>2143</integer>
            <key>col</key><integer>26</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23813,7 +23813,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2126</integer>
+      <key>line</key><integer>2143</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23821,12 +23821,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2126</integer>
+         <key>line</key><integer>2143</integer>
          <key>col</key><integer>28</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2126</integer>
+         <key>line</key><integer>2143</integer>
          <key>col</key><integer>48</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23850,7 +23850,7 @@
   <key>issue_hash_function_offset</key><string>10</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2126</integer>
+   <key>line</key><integer>2143</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -23858,13 +23858,13 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2116</integer>
-    <integer>2117</integer>
-    <integer>2118</integer>
-    <integer>2120</integer>
-    <integer>2121</integer>
-    <integer>2125</integer>
-    <integer>2126</integer>
+    <integer>2133</integer>
+    <integer>2134</integer>
+    <integer>2135</integer>
+    <integer>2137</integer>
+    <integer>2138</integer>
+    <integer>2142</integer>
+    <integer>2143</integer>
    </array>
   </dict>
   </dict>
@@ -23875,7 +23875,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2138</integer>
+      <key>line</key><integer>2155</integer>
       <key>col</key><integer>16</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23883,12 +23883,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2138</integer>
+         <key>line</key><integer>2155</integer>
          <key>col</key><integer>16</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2138</integer>
+         <key>line</key><integer>2155</integer>
          <key>col</key><integer>31</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23908,12 +23908,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2138</integer>
+           <key>line</key><integer>2155</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2138</integer>
+           <key>line</key><integer>2155</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23921,12 +23921,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2139</integer>
+           <key>line</key><integer>2156</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2139</integer>
+           <key>line</key><integer>2156</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23938,7 +23938,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2139</integer>
+      <key>line</key><integer>2156</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23960,7 +23960,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2139</integer>
+   <key>line</key><integer>2156</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -23968,9 +23968,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2137</integer>
-    <integer>2138</integer>
-    <integer>2139</integer>
+    <integer>2154</integer>
+    <integer>2155</integer>
+    <integer>2156</integer>
    </array>
   </dict>
   </dict>
@@ -23981,7 +23981,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2173</integer>
+      <key>line</key><integer>2190</integer>
       <key>col</key><integer>18</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23989,12 +23989,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2173</integer>
+         <key>line</key><integer>2190</integer>
          <key>col</key><integer>18</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2173</integer>
+         <key>line</key><integer>2190</integer>
          <key>col</key><integer>29</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24014,12 +24014,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2173</integer>
+           <key>line</key><integer>2190</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2173</integer>
+           <key>line</key><integer>2190</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24027,12 +24027,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2174</integer>
+           <key>line</key><integer>2191</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2174</integer>
+           <key>line</key><integer>2191</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24044,7 +24044,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2174</integer>
+      <key>line</key><integer>2191</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24066,7 +24066,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2174</integer>
+   <key>line</key><integer>2191</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -24074,9 +24074,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2172</integer>
-    <integer>2173</integer>
-    <integer>2174</integer>
+    <integer>2189</integer>
+    <integer>2190</integer>
+    <integer>2191</integer>
    </array>
   </dict>
   </dict>
@@ -24087,7 +24087,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2177</integer>
+      <key>line</key><integer>2194</integer>
       <key>col</key><integer>13</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24095,12 +24095,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2177</integer>
+         <key>line</key><integer>2194</integer>
          <key>col</key><integer>13</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2177</integer>
+         <key>line</key><integer>2194</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24116,7 +24116,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2177</integer>
+      <key>line</key><integer>2194</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24124,12 +24124,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2177</integer>
+         <key>line</key><integer>2194</integer>
          <key>col</key><integer>13</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2177</integer>
+         <key>line</key><integer>2194</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24153,7 +24153,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2177</integer>
+   <key>line</key><integer>2194</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -24161,8 +24161,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2176</integer>
-    <integer>2177</integer>
+    <integer>2193</integer>
+    <integer>2194</integer>
    </array>
   </dict>
   </dict>
@@ -24177,12 +24177,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24190,12 +24190,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24207,7 +24207,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2196</integer>
+      <key>line</key><integer>2213</integer>
       <key>col</key><integer>11</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24215,12 +24215,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>11</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>31</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24236,7 +24236,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2196</integer>
+      <key>line</key><integer>2213</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24244,12 +24244,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24265,7 +24265,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2189</integer>
+      <key>line</key><integer>2206</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24283,12 +24283,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2189</integer>
+           <key>line</key><integer>2206</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2189</integer>
+           <key>line</key><integer>2206</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24296,12 +24296,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24317,12 +24317,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24330,12 +24330,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24347,7 +24347,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2190</integer>
+      <key>line</key><integer>2207</integer>
       <key>col</key><integer>7</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24355,12 +24355,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2190</integer>
+         <key>line</key><integer>2207</integer>
          <key>col</key><integer>7</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2190</integer>
+         <key>line</key><integer>2207</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24380,12 +24380,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24393,12 +24393,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2191</integer>
+           <key>line</key><integer>2208</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2191</integer>
+           <key>line</key><integer>2208</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24410,7 +24410,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2196</integer>
+      <key>line</key><integer>2213</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24418,12 +24418,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24443,12 +24443,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24456,12 +24456,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24473,7 +24473,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2196</integer>
+      <key>line</key><integer>2213</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24481,12 +24481,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>6</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24510,7 +24510,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2196</integer>
+   <key>line</key><integer>2213</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -24518,11 +24518,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2189</integer>
-    <integer>2190</integer>
-    <integer>2191</integer>
-    <integer>2195</integer>
-    <integer>2196</integer>
+    <integer>2206</integer>
+    <integer>2207</integer>
+    <integer>2208</integer>
+    <integer>2212</integer>
+    <integer>2213</integer>
    </array>
   </dict>
   </dict>
@@ -24537,12 +24537,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24550,12 +24550,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>37</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24567,7 +24567,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2212</integer>
+      <key>line</key><integer>2229</integer>
       <key>col</key><integer>24</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24575,12 +24575,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>39</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24600,12 +24600,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>37</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24613,12 +24613,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>22</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24630,7 +24630,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2212</integer>
+      <key>line</key><integer>2229</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24638,24 +24638,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>40</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>39</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24675,12 +24675,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>22</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24688,12 +24688,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24705,7 +24705,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2212</integer>
+      <key>line</key><integer>2229</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24713,12 +24713,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>40</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24742,7 +24742,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2212</integer>
+   <key>line</key><integer>2229</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -24750,8 +24750,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2210</integer>
-    <integer>2212</integer>
+    <integer>2227</integer>
+    <integer>2229</integer>
    </array>
   </dict>
   </dict>
@@ -24766,12 +24766,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24779,12 +24779,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>40</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24796,7 +24796,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2217</integer>
+      <key>line</key><integer>2234</integer>
       <key>col</key><integer>24</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24804,12 +24804,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>42</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24829,12 +24829,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>40</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24842,12 +24842,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>22</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24859,7 +24859,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2217</integer>
+      <key>line</key><integer>2234</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24867,24 +24867,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>43</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>42</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24904,12 +24904,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>22</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24917,12 +24917,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24934,7 +24934,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2217</integer>
+      <key>line</key><integer>2234</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24942,12 +24942,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>43</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24971,7 +24971,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2217</integer>
+   <key>line</key><integer>2234</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -24979,8 +24979,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2215</integer>
-    <integer>2217</integer>
+    <integer>2232</integer>
+    <integer>2234</integer>
    </array>
   </dict>
   </dict>
@@ -24991,7 +24991,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2232</integer>
+      <key>line</key><integer>2249</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24999,12 +24999,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2232</integer>
+         <key>line</key><integer>2249</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2232</integer>
+         <key>line</key><integer>2249</integer>
          <key>col</key><integer>37</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25024,12 +25024,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2232</integer>
+           <key>line</key><integer>2249</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2232</integer>
+           <key>line</key><integer>2249</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25037,12 +25037,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2233</integer>
+           <key>line</key><integer>2250</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2233</integer>
+           <key>line</key><integer>2250</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25054,7 +25054,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2233</integer>
+      <key>line</key><integer>2250</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25062,24 +25062,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2233</integer>
+         <key>line</key><integer>2250</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2233</integer>
+         <key>line</key><integer>2250</integer>
          <key>col</key><integer>16</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2233</integer>
+         <key>line</key><integer>2250</integer>
          <key>col</key><integer>13</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2233</integer>
+         <key>line</key><integer>2250</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25099,12 +25099,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2233</integer>
+           <key>line</key><integer>2250</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2233</integer>
+           <key>line</key><integer>2250</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25112,12 +25112,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2236</integer>
+           <key>line</key><integer>2253</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2236</integer>
+           <key>line</key><integer>2253</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25129,7 +25129,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2236</integer>
+      <key>line</key><integer>2253</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25137,12 +25137,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2236</integer>
+         <key>line</key><integer>2253</integer>
          <key>col</key><integer>9</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2236</integer>
+         <key>line</key><integer>2253</integer>
          <key>col</key><integer>11</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25166,7 +25166,7 @@
   <key>issue_hash_function_offset</key><string>7</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2236</integer>
+   <key>line</key><integer>2253</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -25174,10 +25174,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2229</integer>
-    <integer>2232</integer>
-    <integer>2233</integer>
-    <integer>2236</integer>
+    <integer>2246</integer>
+    <integer>2249</integer>
+    <integer>2250</integer>
+    <integer>2253</integer>
    </array>
   </dict>
   </dict>
@@ -25188,7 +25188,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2241</integer>
+      <key>line</key><integer>2258</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25196,12 +25196,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2241</integer>
+         <key>line</key><integer>2258</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2241</integer>
+         <key>line</key><integer>2258</integer>
          <key>col</key><integer>37</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25221,12 +25221,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2241</integer>
+           <key>line</key><integer>2258</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2241</integer>
+           <key>line</key><integer>2258</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25234,12 +25234,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2242</integer>
+           <key>line</key><integer>2259</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2242</integer>
+           <key>line</key><integer>2259</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25251,7 +25251,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2242</integer>
+      <key>line</key><integer>2259</integer>
       <key>col</key><integer>22</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25259,24 +25259,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2242</integer>
+         <key>line</key><integer>2259</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2242</integer>
+         <key>line</key><integer>2259</integer>
          <key>col</key><integer>39</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2242</integer>
+         <key>line</key><integer>2259</integer>
          <key>col</key><integer>36</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2242</integer>
+         <key>line</key><integer>2259</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25292,7 +25292,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2242</integer>
+      <key>line</key><integer>2259</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25300,12 +25300,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2242</integer>
+         <key>line</key><integer>2259</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2242</integer>
+         <key>line</key><integer>2259</integer>
          <key>col</key><integer>18</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25325,12 +25325,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2242</integer>
+           <key>line</key><integer>2259</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2242</integer>
+           <key>line</key><integer>2259</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25338,12 +25338,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2243</integer>
+           <key>line</key><integer>2260</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2243</integer>
+           <key>line</key><integer>2260</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25355,7 +25355,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2243</integer>
+      <key>line</key><integer>2260</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25363,24 +25363,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2243</integer>
+         <key>line</key><integer>2260</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2243</integer>
+         <key>line</key><integer>2260</integer>
          <key>col</key><integer>18</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2243</integer>
+         <key>line</key><integer>2260</integer>
          <key>col</key><integer>12</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2243</integer>
+         <key>line</key><integer>2260</integer>
          <key>col</key><integer>17</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25400,12 +25400,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2243</integer>
+           <key>line</key><integer>2260</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2243</integer>
+           <key>line</key><integer>2260</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25413,12 +25413,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2244</integer>
+           <key>line</key><integer>2261</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2244</integer>
+           <key>line</key><integer>2261</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25430,7 +25430,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2244</integer>
+      <key>line</key><integer>2261</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25452,7 +25452,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2244</integer>
+   <key>line</key><integer>2261</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -25460,11 +25460,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2239</integer>
-    <integer>2241</integer>
-    <integer>2242</integer>
-    <integer>2243</integer>
-    <integer>2244</integer>
+    <integer>2256</integer>
+    <integer>2258</integer>
+    <integer>2259</integer>
+    <integer>2260</integer>
+    <integer>2261</integer>
    </array>
   </dict>
   </dict>
@@ -25475,7 +25475,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2261</integer>
+      <key>line</key><integer>2278</integer>
       <key>col</key><integer>20</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25483,12 +25483,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2261</integer>
+         <key>line</key><integer>2278</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2261</integer>
+         <key>line</key><integer>2278</integer>
          <key>col</key><integer>70</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25508,12 +25508,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2261</integer>
+           <key>line</key><integer>2278</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2261</integer>
+           <key>line</key><integer>2278</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25521,12 +25521,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2262</integer>
+           <key>line</key><integer>2279</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2262</integer>
+           <key>line</key><integer>2279</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25538,7 +25538,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2262</integer>
+      <key>line</key><integer>2279</integer>
       <key>col</key><integer>34</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25546,24 +25546,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2262</integer>
+         <key>line</key><integer>2279</integer>
          <key>col</key><integer>34</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2262</integer>
+         <key>line</key><integer>2279</integer>
          <key>col</key><integer>62</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2262</integer>
+         <key>line</key><integer>2279</integer>
          <key>col</key><integer>48</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2262</integer>
+         <key>line</key><integer>2279</integer>
          <key>col</key><integer>61</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25579,7 +25579,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2262</integer>
+      <key>line</key><integer>2279</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25587,12 +25587,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2262</integer>
+         <key>line</key><integer>2279</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2262</integer>
+         <key>line</key><integer>2279</integer>
          <key>col</key><integer>18</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25612,12 +25612,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2262</integer>
+           <key>line</key><integer>2279</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2262</integer>
+           <key>line</key><integer>2279</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25625,12 +25625,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2263</integer>
+           <key>line</key><integer>2280</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2263</integer>
+           <key>line</key><integer>2280</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25642,7 +25642,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2263</integer>
+      <key>line</key><integer>2280</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25650,24 +25650,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2263</integer>
+         <key>line</key><integer>2280</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2263</integer>
+         <key>line</key><integer>2280</integer>
          <key>col</key><integer>17</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2263</integer>
+         <key>line</key><integer>2280</integer>
          <key>col</key><integer>12</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2263</integer>
+         <key>line</key><integer>2280</integer>
          <key>col</key><integer>16</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25687,12 +25687,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2263</integer>
+           <key>line</key><integer>2280</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2263</integer>
+           <key>line</key><integer>2280</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25700,12 +25700,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2264</integer>
+           <key>line</key><integer>2281</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2264</integer>
+           <key>line</key><integer>2281</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25717,7 +25717,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2264</integer>
+      <key>line</key><integer>2281</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25739,7 +25739,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2264</integer>
+   <key>line</key><integer>2281</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -25747,11 +25747,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2260</integer>
-    <integer>2261</integer>
-    <integer>2262</integer>
-    <integer>2263</integer>
-    <integer>2264</integer>
+    <integer>2277</integer>
+    <integer>2278</integer>
+    <integer>2279</integer>
+    <integer>2280</integer>
+    <integer>2281</integer>
    </array>
   </dict>
   </dict>
@@ -25766,12 +25766,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2275</integer>
+           <key>line</key><integer>2292</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2275</integer>
+           <key>line</key><integer>2292</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25779,12 +25779,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2278</integer>
+           <key>line</key><integer>2295</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2278</integer>
+           <key>line</key><integer>2295</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25796,7 +25796,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2278</integer>
+      <key>line</key><integer>2295</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25804,12 +25804,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2278</integer>
+         <key>line</key><integer>2295</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2278</integer>
+         <key>line</key><integer>2295</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25829,12 +25829,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2278</integer>
+           <key>line</key><integer>2295</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2278</integer>
+           <key>line</key><integer>2295</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25842,12 +25842,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2279</integer>
+           <key>line</key><integer>2296</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2279</integer>
+           <key>line</key><integer>2296</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25859,7 +25859,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2279</integer>
+      <key>line</key><integer>2296</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25867,24 +25867,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2279</integer>
+         <key>line</key><integer>2296</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2279</integer>
+         <key>line</key><integer>2296</integer>
          <key>col</key><integer>27</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2279</integer>
+         <key>line</key><integer>2296</integer>
          <key>col</key><integer>17</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2279</integer>
+         <key>line</key><integer>2296</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25904,12 +25904,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2279</integer>
+           <key>line</key><integer>2296</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2279</integer>
+           <key>line</key><integer>2296</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25917,12 +25917,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2280</integer>
+           <key>line</key><integer>2297</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2280</integer>
+           <key>line</key><integer>2297</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25934,7 +25934,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2280</integer>
+      <key>line</key><integer>2297</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25956,7 +25956,7 @@
   <key>issue_hash_function_offset</key><string>6</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2280</integer>
+   <key>line</key><integer>2297</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -25964,12 +25964,12 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2274</integer>
-    <integer>2275</integer>
-    <integer>2276</integer>
-    <integer>2278</integer>
-    <integer>2279</integer>
-    <integer>2280</integer>
+    <integer>2291</integer>
+    <integer>2292</integer>
+    <integer>2293</integer>
+    <integer>2295</integer>
+    <integer>2296</integer>
+    <integer>2297</integer>
    </array>
   </dict>
   </dict>
@@ -25984,12 +25984,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2329</integer>
+           <key>line</key><integer>2346</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2329</integer>
+           <key>line</key><integer>2346</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25997,12 +25997,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2330</integer>
+           <key>line</key><integer>2347</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2330</integer>
+           <key>line</key><integer>2347</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26014,7 +26014,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2330</integer>
+      <key>line</key><integer>2347</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -26022,12 +26022,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2330</integer>
+         <key>line</key><integer>2347</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2330</integer>
+         <key>line</key><integer>2347</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -26047,12 +26047,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2330</integer>
+           <key>line</key><integer>2347</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2330</integer>
+           <key>line</key><integer>2347</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26060,12 +26060,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2331</integer>
+           <key>line</key><integer>2348</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2331</integer>
+           <key>line</key><integer>2348</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26077,7 +26077,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2331</integer>
+      <key>line</key><integer>2348</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -26085,12 +26085,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2331</integer>
+         <key>line</key><integer>2348</integer>
          <key>col</key><integer>13</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2331</integer>
+         <key>line</key><integer>2348</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -26114,7 +26114,7 @@
   <key>issue_hash_function_offset</key><string>4</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2331</integer>
+   <key>line</key><integer>2348</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -26122,10 +26122,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2327</integer>
-    <integer>2329</integer>
-    <integer>2330</integer>
-    <integer>2331</integer>
+    <integer>2344</integer>
+    <integer>2346</integer>
+    <integer>2347</integer>
+    <integer>2348</integer>
    </array>
   </dict>
   </dict>
@@ -26140,12 +26140,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2336</integer>
+           <key>line</key><integer>2353</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2336</integer>
+           <key>line</key><integer>2353</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26153,12 +26153,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2337</integer>
+           <key>line</key><integer>2354</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2337</integer>
+           <key>line</key><integer>2354</integer>
            <key>col</key><integer>14</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26170,7 +26170,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2337</integer>
+      <key>line</key><integer>2354</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -26178,12 +26178,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2337</integer>
+         <key>line</key><integer>2354</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2337</integer>
+         <key>line</key><integer>2354</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -26203,12 +26203,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2337</integer>
+           <key>line</key><integer>2354</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2337</integer>
+           <key>line</key><integer>2354</integer>
            <key>col</key><integer>14</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26216,12 +26216,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2338</integer>
+           <key>line</key><integer>2355</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2338</integer>
+           <key>line</key><integer>2355</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26233,7 +26233,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2338</integer>
+      <key>line</key><integer>2355</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -26241,12 +26241,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2338</integer>
+         <key>line</key><integer>2355</integer>
          <key>col</key><integer>13</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2338</integer>
+         <key>line</key><integer>2355</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -26270,7 +26270,7 @@
   <key>issue_hash_function_offset</key><string>4</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2338</integer>
+   <key>line</key><integer>2355</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -26278,10 +26278,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2334</integer>
-    <integer>2336</integer>
-    <integer>2337</integer>
-    <integer>2338</integer>
+    <integer>2351</integer>
+    <integer>2353</integer>
+    <integer>2354</integer>
+    <integer>2355</integer>
    </array>
   </dict>
   </dict>
diff --git a/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist b/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist
index 9e3fcc013f242cb..ccf7849e5fab69f 100644
--- a/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist
+++ b/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist
@@ -15950,12 +15950,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1456</integer>
+           <key>line</key><integer>1473</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1456</integer>
+           <key>line</key><integer>1473</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -15963,12 +15963,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1458</integer>
+           <key>line</key><integer>1475</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1458</integer>
+           <key>line</key><integer>1475</integer>
            <key>col</key><integer>31</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -15980,7 +15980,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1458</integer>
+      <key>line</key><integer>1475</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -15988,12 +15988,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1458</integer>
+         <key>line</key><integer>1475</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1459</integer>
+         <key>line</key><integer>1476</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16013,12 +16013,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1458</integer>
+           <key>line</key><integer>1475</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1458</integer>
+           <key>line</key><integer>1475</integer>
            <key>col</key><integer>31</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16026,12 +16026,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1460</integer>
+           <key>line</key><integer>1477</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1460</integer>
+           <key>line</key><integer>1477</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16043,7 +16043,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1460</integer>
+      <key>line</key><integer>1477</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16065,7 +16065,7 @@
   <key>issue_hash_function_offset</key><string>7</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1460</integer>
+   <key>line</key><integer>1477</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16073,14 +16073,14 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1448</integer>
-    <integer>1449</integer>
-    <integer>1450</integer>
-    <integer>1451</integer>
-    <integer>1456</integer>
-    <integer>1458</integer>
-    <integer>1459</integer>
-    <integer>1460</integer>
+    <integer>1465</integer>
+    <integer>1466</integer>
+    <integer>1467</integer>
+    <integer>1468</integer>
+    <integer>1473</integer>
+    <integer>1475</integer>
+    <integer>1476</integer>
+    <integer>1477</integer>
    </array>
   </dict>
   </dict>
@@ -16091,7 +16091,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1475</integer>
+      <key>line</key><integer>1492</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16099,12 +16099,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1475</integer>
+         <key>line</key><integer>1492</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1475</integer>
+         <key>line</key><integer>1492</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16124,12 +16124,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1475</integer>
+           <key>line</key><integer>1492</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1475</integer>
+           <key>line</key><integer>1492</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16137,12 +16137,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1476</integer>
+           <key>line</key><integer>1493</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1476</integer>
+           <key>line</key><integer>1493</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16154,7 +16154,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1476</integer>
+      <key>line</key><integer>1493</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16176,7 +16176,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1476</integer>
+   <key>line</key><integer>1493</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16184,9 +16184,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1474</integer>
-    <integer>1475</integer>
-    <integer>1476</integer>
+    <integer>1491</integer>
+    <integer>1492</integer>
+    <integer>1493</integer>
    </array>
   </dict>
   </dict>
@@ -16201,12 +16201,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1493</integer>
+           <key>line</key><integer>1510</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1493</integer>
+           <key>line</key><integer>1510</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16214,12 +16214,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1494</integer>
+           <key>line</key><integer>1511</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1494</integer>
+           <key>line</key><integer>1511</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16231,7 +16231,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1494</integer>
+      <key>line</key><integer>1511</integer>
       <key>col</key><integer>22</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16239,12 +16239,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1494</integer>
+         <key>line</key><integer>1511</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1494</integer>
+         <key>line</key><integer>1511</integer>
          <key>col</key><integer>53</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16264,12 +16264,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1494</integer>
+           <key>line</key><integer>1511</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1494</integer>
+           <key>line</key><integer>1511</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16277,12 +16277,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1495</integer>
+           <key>line</key><integer>1512</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1495</integer>
+           <key>line</key><integer>1512</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16294,7 +16294,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1495</integer>
+      <key>line</key><integer>1512</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16316,7 +16316,7 @@
   <key>issue_hash_function_offset</key><string>4</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1495</integer>
+   <key>line</key><integer>1512</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16324,10 +16324,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1490</integer>
-    <integer>1493</integer>
-    <integer>1494</integer>
-    <integer>1495</integer>
+    <integer>1507</integer>
+    <integer>1510</integer>
+    <integer>1511</integer>
+    <integer>1512</integer>
    </array>
   </dict>
   </dict>
@@ -16338,7 +16338,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1503</integer>
+      <key>line</key><integer>1520</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16346,12 +16346,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1503</integer>
+         <key>line</key><integer>1520</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1503</integer>
+         <key>line</key><integer>1520</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16375,7 +16375,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1503</integer>
+   <key>line</key><integer>1520</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16383,8 +16383,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1502</integer>
-    <integer>1503</integer>
+    <integer>1519</integer>
+    <integer>1520</integer>
    </array>
   </dict>
   </dict>
@@ -16399,12 +16399,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1503</integer>
+           <key>line</key><integer>1520</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1503</integer>
+           <key>line</key><integer>1520</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16412,12 +16412,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1504</integer>
+           <key>line</key><integer>1521</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1504</integer>
+           <key>line</key><integer>1521</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16429,7 +16429,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1504</integer>
+      <key>line</key><integer>1521</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16437,12 +16437,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1504</integer>
+         <key>line</key><integer>1521</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1504</integer>
+         <key>line</key><integer>1521</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16466,7 +16466,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1504</integer>
+   <key>line</key><integer>1521</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16474,9 +16474,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1502</integer>
-    <integer>1503</integer>
-    <integer>1504</integer>
+    <integer>1519</integer>
+    <integer>1520</integer>
+    <integer>1521</integer>
    </array>
   </dict>
   </dict>
@@ -16491,12 +16491,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1503</integer>
+           <key>line</key><integer>1520</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1503</integer>
+           <key>line</key><integer>1520</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16504,12 +16504,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1505</integer>
+           <key>line</key><integer>1522</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1505</integer>
+           <key>line</key><integer>1522</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16521,7 +16521,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1505</integer>
+      <key>line</key><integer>1522</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16529,12 +16529,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1505</integer>
+         <key>line</key><integer>1522</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1505</integer>
+         <key>line</key><integer>1522</integer>
          <key>col</key><integer>27</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16558,7 +16558,7 @@
   <key>issue_hash_function_offset</key><string>3</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1505</integer>
+   <key>line</key><integer>1522</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16566,10 +16566,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1502</integer>
-    <integer>1503</integer>
-    <integer>1504</integer>
-    <integer>1505</integer>
+    <integer>1519</integer>
+    <integer>1520</integer>
+    <integer>1521</integer>
+    <integer>1522</integer>
    </array>
   </dict>
   </dict>
@@ -16584,12 +16584,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1503</integer>
+           <key>line</key><integer>1520</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1503</integer>
+           <key>line</key><integer>1520</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16597,12 +16597,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1506</integer>
+           <key>line</key><integer>1523</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1506</integer>
+           <key>line</key><integer>1523</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16614,7 +16614,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1506</integer>
+      <key>line</key><integer>1523</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16622,12 +16622,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1506</integer>
+         <key>line</key><integer>1523</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1506</integer>
+         <key>line</key><integer>1523</integer>
          <key>col</key><integer>27</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16651,7 +16651,7 @@
   <key>issue_hash_function_offset</key><string>4</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1506</integer>
+   <key>line</key><integer>1523</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16659,11 +16659,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1502</integer>
-    <integer>1503</integer>
-    <integer>1504</integer>
-    <integer>1505</integer>
-    <integer>1506</integer>
+    <integer>1519</integer>
+    <integer>1520</integer>
+    <integer>1521</integer>
+    <integer>1522</integer>
+    <integer>1523</integer>
    </array>
   </dict>
   </dict>
@@ -16674,7 +16674,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1533</integer>
+      <key>line</key><integer>1550</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16682,12 +16682,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1533</integer>
+         <key>line</key><integer>1550</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1533</integer>
+         <key>line</key><integer>1550</integer>
          <key>col</key><integer>42</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16707,12 +16707,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1533</integer>
+           <key>line</key><integer>1550</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1533</integer>
+           <key>line</key><integer>1550</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16720,12 +16720,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1534</integer>
+           <key>line</key><integer>1551</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1534</integer>
+           <key>line</key><integer>1551</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16737,7 +16737,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1534</integer>
+      <key>line</key><integer>1551</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16759,7 +16759,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1534</integer>
+   <key>line</key><integer>1551</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16767,9 +16767,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1532</integer>
-    <integer>1533</integer>
-    <integer>1534</integer>
+    <integer>1549</integer>
+    <integer>1550</integer>
+    <integer>1551</integer>
    </array>
   </dict>
   </dict>
@@ -16780,7 +16780,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1537</integer>
+      <key>line</key><integer>1554</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16788,12 +16788,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1537</integer>
+         <key>line</key><integer>1554</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1537</integer>
+         <key>line</key><integer>1554</integer>
          <key>col</key><integer>44</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16813,12 +16813,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1537</integer>
+           <key>line</key><integer>1554</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1537</integer>
+           <key>line</key><integer>1554</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16826,12 +16826,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1538</integer>
+           <key>line</key><integer>1555</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1538</integer>
+           <key>line</key><integer>1555</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16843,7 +16843,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1538</integer>
+      <key>line</key><integer>1555</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16865,7 +16865,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1538</integer>
+   <key>line</key><integer>1555</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -16873,9 +16873,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1536</integer>
-    <integer>1537</integer>
-    <integer>1538</integer>
+    <integer>1553</integer>
+    <integer>1554</integer>
+    <integer>1555</integer>
    </array>
   </dict>
   </dict>
@@ -16890,12 +16890,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1541</integer>
+           <key>line</key><integer>1558</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1541</integer>
+           <key>line</key><integer>1558</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16903,12 +16903,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1542</integer>
+           <key>line</key><integer>1559</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1542</integer>
+           <key>line</key><integer>1559</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16920,7 +16920,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1542</integer>
+      <key>line</key><integer>1559</integer>
       <key>col</key><integer>20</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -16928,12 +16928,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1542</integer>
+         <key>line</key><integer>1559</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1542</integer>
+         <key>line</key><integer>1559</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -16953,12 +16953,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1542</integer>
+           <key>line</key><integer>1559</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1542</integer>
+           <key>line</key><integer>1559</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16966,12 +16966,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1543</integer>
+           <key>line</key><integer>1560</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1543</integer>
+           <key>line</key><integer>1560</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -16987,12 +16987,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1543</integer>
+           <key>line</key><integer>1560</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1543</integer>
+           <key>line</key><integer>1560</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17000,12 +17000,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1543</integer>
+           <key>line</key><integer>1560</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1543</integer>
+           <key>line</key><integer>1560</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17017,7 +17017,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1543</integer>
+      <key>line</key><integer>1560</integer>
       <key>col</key><integer>20</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17025,12 +17025,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1543</integer>
+         <key>line</key><integer>1560</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1543</integer>
+         <key>line</key><integer>1560</integer>
          <key>col</key><integer>37</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17054,7 +17054,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1543</integer>
+   <key>line</key><integer>1560</integer>
    <key>col</key><integer>20</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -17062,10 +17062,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1540</integer>
-    <integer>1541</integer>
-    <integer>1542</integer>
-    <integer>1543</integer>
+    <integer>1557</integer>
+    <integer>1558</integer>
+    <integer>1559</integer>
+    <integer>1560</integer>
    </array>
   </dict>
   </dict>
@@ -17080,12 +17080,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1541</integer>
+           <key>line</key><integer>1558</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1541</integer>
+           <key>line</key><integer>1558</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17093,12 +17093,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17114,12 +17114,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17127,12 +17127,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>21</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>21</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17144,7 +17144,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1544</integer>
+      <key>line</key><integer>1561</integer>
       <key>col</key><integer>21</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17152,12 +17152,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1544</integer>
+         <key>line</key><integer>1561</integer>
          <key>col</key><integer>21</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1544</integer>
+         <key>line</key><integer>1561</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17173,7 +17173,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1544</integer>
+      <key>line</key><integer>1561</integer>
       <key>col</key><integer>20</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17181,24 +17181,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1544</integer>
+         <key>line</key><integer>1561</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1544</integer>
+         <key>line</key><integer>1561</integer>
          <key>col</key><integer>46</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>1544</integer>
+         <key>line</key><integer>1561</integer>
          <key>col</key><integer>21</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1544</integer>
+         <key>line</key><integer>1561</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17218,12 +17218,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17231,12 +17231,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17252,12 +17252,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1544</integer>
+           <key>line</key><integer>1561</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17265,12 +17265,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1545</integer>
+           <key>line</key><integer>1562</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1545</integer>
+           <key>line</key><integer>1562</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17282,7 +17282,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1545</integer>
+      <key>line</key><integer>1562</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17304,7 +17304,7 @@
   <key>issue_hash_function_offset</key><string>4</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1545</integer>
+   <key>line</key><integer>1562</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -17312,12 +17312,12 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1540</integer>
-    <integer>1541</integer>
-    <integer>1542</integer>
-    <integer>1543</integer>
-    <integer>1544</integer>
-    <integer>1545</integer>
+    <integer>1557</integer>
+    <integer>1558</integer>
+    <integer>1559</integer>
+    <integer>1560</integer>
+    <integer>1561</integer>
+    <integer>1562</integer>
    </array>
   </dict>
   </dict>
@@ -17328,7 +17328,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1548</integer>
+      <key>line</key><integer>1565</integer>
       <key>col</key><integer>26</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17336,12 +17336,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1548</integer>
+         <key>line</key><integer>1565</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1548</integer>
+         <key>line</key><integer>1565</integer>
          <key>col</key><integer>50</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17361,12 +17361,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1548</integer>
+           <key>line</key><integer>1565</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1548</integer>
+           <key>line</key><integer>1565</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17374,12 +17374,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1549</integer>
+           <key>line</key><integer>1566</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1549</integer>
+           <key>line</key><integer>1566</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17391,7 +17391,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1549</integer>
+      <key>line</key><integer>1566</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17413,7 +17413,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1549</integer>
+   <key>line</key><integer>1566</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -17421,9 +17421,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1547</integer>
-    <integer>1548</integer>
-    <integer>1549</integer>
+    <integer>1564</integer>
+    <integer>1565</integer>
+    <integer>1566</integer>
    </array>
   </dict>
   </dict>
@@ -17434,7 +17434,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1552</integer>
+      <key>line</key><integer>1569</integer>
       <key>col</key><integer>26</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17442,12 +17442,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1552</integer>
+         <key>line</key><integer>1569</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1552</integer>
+         <key>line</key><integer>1569</integer>
          <key>col</key><integer>63</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17467,12 +17467,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1552</integer>
+           <key>line</key><integer>1569</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1552</integer>
+           <key>line</key><integer>1569</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17480,12 +17480,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1553</integer>
+           <key>line</key><integer>1570</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1553</integer>
+           <key>line</key><integer>1570</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17497,7 +17497,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1553</integer>
+      <key>line</key><integer>1570</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17519,7 +17519,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1553</integer>
+   <key>line</key><integer>1570</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -17527,9 +17527,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1551</integer>
-    <integer>1552</integer>
-    <integer>1553</integer>
+    <integer>1568</integer>
+    <integer>1569</integer>
+    <integer>1570</integer>
    </array>
   </dict>
   </dict>
@@ -17540,7 +17540,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1556</integer>
+      <key>line</key><integer>1573</integer>
       <key>col</key><integer>26</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17548,12 +17548,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1556</integer>
+         <key>line</key><integer>1573</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1556</integer>
+         <key>line</key><integer>1573</integer>
          <key>col</key><integer>63</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17573,12 +17573,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1556</integer>
+           <key>line</key><integer>1573</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1556</integer>
+           <key>line</key><integer>1573</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17586,12 +17586,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1557</integer>
+           <key>line</key><integer>1574</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1557</integer>
+           <key>line</key><integer>1574</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17607,12 +17607,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1557</integer>
+           <key>line</key><integer>1574</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1557</integer>
+           <key>line</key><integer>1574</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17620,12 +17620,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1558</integer>
+           <key>line</key><integer>1575</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1558</integer>
+           <key>line</key><integer>1575</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17637,7 +17637,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1558</integer>
+      <key>line</key><integer>1575</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17659,7 +17659,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1558</integer>
+   <key>line</key><integer>1575</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -17667,10 +17667,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1555</integer>
-    <integer>1556</integer>
-    <integer>1557</integer>
-    <integer>1558</integer>
+    <integer>1572</integer>
+    <integer>1573</integer>
+    <integer>1574</integer>
+    <integer>1575</integer>
    </array>
   </dict>
   </dict>
@@ -17681,7 +17681,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1588</integer>
+      <key>line</key><integer>1605</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17689,12 +17689,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1588</integer>
+         <key>line</key><integer>1605</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1588</integer>
+         <key>line</key><integer>1605</integer>
          <key>col</key><integer>25</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17710,7 +17710,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1588</integer>
+      <key>line</key><integer>1605</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17718,12 +17718,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1588</integer>
+         <key>line</key><integer>1605</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1588</integer>
+         <key>line</key><integer>1605</integer>
          <key>col</key><integer>25</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17747,7 +17747,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1588</integer>
+   <key>line</key><integer>1605</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -17755,8 +17755,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1587</integer>
-    <integer>1588</integer>
+    <integer>1604</integer>
+    <integer>1605</integer>
    </array>
   </dict>
   </dict>
@@ -17771,12 +17771,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17784,12 +17784,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>26</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>26</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17801,7 +17801,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1621</integer>
+      <key>line</key><integer>1638</integer>
       <key>col</key><integer>26</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17809,12 +17809,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>53</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17830,7 +17830,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1612</integer>
+      <key>line</key><integer>1629</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17848,12 +17848,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1612</integer>
+           <key>line</key><integer>1629</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1612</integer>
+           <key>line</key><integer>1629</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17861,12 +17861,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17882,12 +17882,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17895,12 +17895,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>30</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17912,7 +17912,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1613</integer>
+      <key>line</key><integer>1630</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17920,12 +17920,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1613</integer>
+         <key>line</key><integer>1630</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1613</integer>
+         <key>line</key><integer>1630</integer>
          <key>col</key><integer>32</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -17941,7 +17941,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1602</integer>
+      <key>line</key><integer>1619</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17959,12 +17959,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1602</integer>
+           <key>line</key><integer>1619</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1602</integer>
+           <key>line</key><integer>1619</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17972,12 +17972,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1604</integer>
+           <key>line</key><integer>1621</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1604</integer>
+           <key>line</key><integer>1621</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -17989,7 +17989,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1604</integer>
+      <key>line</key><integer>1621</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -17997,12 +17997,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1604</integer>
+         <key>line</key><integer>1621</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1604</integer>
+         <key>line</key><integer>1621</integer>
          <key>col</key><integer>52</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18018,7 +18018,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1613</integer>
+      <key>line</key><integer>1630</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18026,12 +18026,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1613</integer>
+         <key>line</key><integer>1630</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1613</integer>
+         <key>line</key><integer>1630</integer>
          <key>col</key><integer>32</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18051,12 +18051,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>30</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18064,12 +18064,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1613</integer>
+           <key>line</key><integer>1630</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18081,7 +18081,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1621</integer>
+      <key>line</key><integer>1638</integer>
       <key>col</key><integer>26</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18089,12 +18089,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>53</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18114,12 +18114,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>26</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>26</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18127,12 +18127,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>21</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>21</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18144,7 +18144,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1621</integer>
+      <key>line</key><integer>1638</integer>
       <key>col</key><integer>21</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18152,24 +18152,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>21</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>66</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>53</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18189,12 +18189,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>21</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>21</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18202,12 +18202,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1621</integer>
+           <key>line</key><integer>1638</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18219,7 +18219,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1621</integer>
+      <key>line</key><integer>1638</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18227,12 +18227,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1621</integer>
+         <key>line</key><integer>1638</integer>
          <key>col</key><integer>66</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18256,7 +18256,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1621</integer>
+   <key>line</key><integer>1638</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -18264,13 +18264,13 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1602</integer>
-    <integer>1603</integer>
-    <integer>1604</integer>
-    <integer>1612</integer>
-    <integer>1613</integer>
+    <integer>1619</integer>
     <integer>1620</integer>
     <integer>1621</integer>
+    <integer>1629</integer>
+    <integer>1630</integer>
+    <integer>1637</integer>
+    <integer>1638</integer>
    </array>
   </dict>
   </dict>
@@ -18285,12 +18285,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18298,12 +18298,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>40</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18315,7 +18315,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1625</integer>
+      <key>line</key><integer>1642</integer>
       <key>col</key><integer>20</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18323,12 +18323,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1625</integer>
+         <key>line</key><integer>1642</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1625</integer>
+         <key>line</key><integer>1642</integer>
          <key>col</key><integer>42</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18344,7 +18344,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1602</integer>
+      <key>line</key><integer>1619</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18362,12 +18362,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1602</integer>
+           <key>line</key><integer>1619</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1602</integer>
+           <key>line</key><integer>1619</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18375,12 +18375,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1604</integer>
+           <key>line</key><integer>1621</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1604</integer>
+           <key>line</key><integer>1621</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18392,7 +18392,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1604</integer>
+      <key>line</key><integer>1621</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18400,12 +18400,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1604</integer>
+         <key>line</key><integer>1621</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1604</integer>
+         <key>line</key><integer>1621</integer>
          <key>col</key><integer>52</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18421,7 +18421,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1625</integer>
+      <key>line</key><integer>1642</integer>
       <key>col</key><integer>20</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18429,12 +18429,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1625</integer>
+         <key>line</key><integer>1642</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1625</integer>
+         <key>line</key><integer>1642</integer>
          <key>col</key><integer>42</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18454,12 +18454,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>40</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18467,12 +18467,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1625</integer>
+           <key>line</key><integer>1642</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18484,7 +18484,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1625</integer>
+      <key>line</key><integer>1642</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18492,12 +18492,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1625</integer>
+         <key>line</key><integer>1642</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1625</integer>
+         <key>line</key><integer>1642</integer>
          <key>col</key><integer>42</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18521,7 +18521,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1625</integer>
+   <key>line</key><integer>1642</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -18529,11 +18529,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1602</integer>
-    <integer>1603</integer>
-    <integer>1604</integer>
-    <integer>1624</integer>
-    <integer>1625</integer>
+    <integer>1619</integer>
+    <integer>1620</integer>
+    <integer>1621</integer>
+    <integer>1641</integer>
+    <integer>1642</integer>
    </array>
   </dict>
   </dict>
@@ -18548,12 +18548,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18561,12 +18561,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>30</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18578,7 +18578,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1629</integer>
+      <key>line</key><integer>1646</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18586,12 +18586,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1629</integer>
+         <key>line</key><integer>1646</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1629</integer>
+         <key>line</key><integer>1646</integer>
          <key>col</key><integer>32</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18607,7 +18607,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1602</integer>
+      <key>line</key><integer>1619</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18625,12 +18625,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1602</integer>
+           <key>line</key><integer>1619</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1602</integer>
+           <key>line</key><integer>1619</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18638,12 +18638,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1604</integer>
+           <key>line</key><integer>1621</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1604</integer>
+           <key>line</key><integer>1621</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18655,7 +18655,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1604</integer>
+      <key>line</key><integer>1621</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18663,12 +18663,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1604</integer>
+         <key>line</key><integer>1621</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1604</integer>
+         <key>line</key><integer>1621</integer>
          <key>col</key><integer>52</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18684,7 +18684,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1629</integer>
+      <key>line</key><integer>1646</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18692,12 +18692,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1629</integer>
+         <key>line</key><integer>1646</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1629</integer>
+         <key>line</key><integer>1646</integer>
          <key>col</key><integer>32</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18717,12 +18717,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>30</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18730,12 +18730,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1629</integer>
+           <key>line</key><integer>1646</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18747,7 +18747,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1629</integer>
+      <key>line</key><integer>1646</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18755,12 +18755,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1629</integer>
+         <key>line</key><integer>1646</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1629</integer>
+         <key>line</key><integer>1646</integer>
          <key>col</key><integer>32</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18784,7 +18784,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1629</integer>
+   <key>line</key><integer>1646</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -18792,11 +18792,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1602</integer>
-    <integer>1603</integer>
-    <integer>1604</integer>
-    <integer>1628</integer>
-    <integer>1629</integer>
+    <integer>1619</integer>
+    <integer>1620</integer>
+    <integer>1621</integer>
+    <integer>1645</integer>
+    <integer>1646</integer>
    </array>
   </dict>
   </dict>
@@ -18811,12 +18811,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1648</integer>
+           <key>line</key><integer>1665</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1648</integer>
+           <key>line</key><integer>1665</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18824,12 +18824,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1649</integer>
+           <key>line</key><integer>1666</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1649</integer>
+           <key>line</key><integer>1666</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18841,7 +18841,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1649</integer>
+      <key>line</key><integer>1666</integer>
       <key>col</key><integer>23</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18849,12 +18849,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1649</integer>
+         <key>line</key><integer>1666</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1649</integer>
+         <key>line</key><integer>1666</integer>
          <key>col</key><integer>82</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -18874,12 +18874,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1649</integer>
+           <key>line</key><integer>1666</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1649</integer>
+           <key>line</key><integer>1666</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18887,12 +18887,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1650</integer>
+           <key>line</key><integer>1667</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1650</integer>
+           <key>line</key><integer>1667</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18904,7 +18904,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1650</integer>
+      <key>line</key><integer>1667</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18926,7 +18926,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1650</integer>
+   <key>line</key><integer>1667</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -18934,10 +18934,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1647</integer>
-    <integer>1648</integer>
-    <integer>1649</integer>
-    <integer>1650</integer>
+    <integer>1664</integer>
+    <integer>1665</integer>
+    <integer>1666</integer>
+    <integer>1667</integer>
    </array>
   </dict>
   </dict>
@@ -18952,12 +18952,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1659</integer>
+           <key>line</key><integer>1676</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1659</integer>
+           <key>line</key><integer>1676</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18965,12 +18965,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1660</integer>
+           <key>line</key><integer>1677</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1660</integer>
+           <key>line</key><integer>1677</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -18982,7 +18982,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1660</integer>
+      <key>line</key><integer>1677</integer>
       <key>col</key><integer>23</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -18990,12 +18990,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1660</integer>
+         <key>line</key><integer>1677</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1660</integer>
+         <key>line</key><integer>1677</integer>
          <key>col</key><integer>82</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19015,12 +19015,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1660</integer>
+           <key>line</key><integer>1677</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1660</integer>
+           <key>line</key><integer>1677</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19028,12 +19028,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19049,12 +19049,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19062,12 +19062,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19079,7 +19079,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1661</integer>
+      <key>line</key><integer>1678</integer>
       <key>col</key><integer>7</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19087,12 +19087,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1661</integer>
+         <key>line</key><integer>1678</integer>
          <key>col</key><integer>7</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1661</integer>
+         <key>line</key><integer>1678</integer>
          <key>col</key><integer>7</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19112,12 +19112,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1661</integer>
+           <key>line</key><integer>1678</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19125,12 +19125,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1663</integer>
+           <key>line</key><integer>1680</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1663</integer>
+           <key>line</key><integer>1680</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19142,7 +19142,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1663</integer>
+      <key>line</key><integer>1680</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19164,7 +19164,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1663</integer>
+   <key>line</key><integer>1680</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -19172,11 +19172,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1658</integer>
-    <integer>1659</integer>
-    <integer>1660</integer>
-    <integer>1661</integer>
-    <integer>1663</integer>
+    <integer>1675</integer>
+    <integer>1676</integer>
+    <integer>1677</integer>
+    <integer>1678</integer>
+    <integer>1680</integer>
    </array>
   </dict>
   </dict>
@@ -19187,7 +19187,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1683</integer>
+      <key>line</key><integer>1700</integer>
       <key>col</key><integer>22</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19195,12 +19195,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1683</integer>
+         <key>line</key><integer>1700</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1683</integer>
+         <key>line</key><integer>1700</integer>
          <key>col</key><integer>53</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19220,12 +19220,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1683</integer>
+           <key>line</key><integer>1700</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1683</integer>
+           <key>line</key><integer>1700</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19233,12 +19233,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1684</integer>
+           <key>line</key><integer>1701</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1684</integer>
+           <key>line</key><integer>1701</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19250,7 +19250,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1684</integer>
+      <key>line</key><integer>1701</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19258,12 +19258,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1684</integer>
+         <key>line</key><integer>1701</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1684</integer>
+         <key>line</key><integer>1701</integer>
          <key>col</key><integer>7</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19287,7 +19287,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1684</integer>
+   <key>line</key><integer>1701</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -19295,9 +19295,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1682</integer>
-    <integer>1683</integer>
-    <integer>1684</integer>
+    <integer>1699</integer>
+    <integer>1700</integer>
+    <integer>1701</integer>
    </array>
   </dict>
   </dict>
@@ -19308,7 +19308,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1704</integer>
+      <key>line</key><integer>1721</integer>
       <key>col</key><integer>22</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19316,12 +19316,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1704</integer>
+         <key>line</key><integer>1721</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1704</integer>
+         <key>line</key><integer>1721</integer>
          <key>col</key><integer>53</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19341,12 +19341,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1704</integer>
+           <key>line</key><integer>1721</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1704</integer>
+           <key>line</key><integer>1721</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19354,12 +19354,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19371,7 +19371,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1705</integer>
+      <key>line</key><integer>1722</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19379,12 +19379,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>39</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19400,7 +19400,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1705</integer>
+      <key>line</key><integer>1722</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19418,12 +19418,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19431,12 +19431,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>19</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19448,7 +19448,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1705</integer>
+      <key>line</key><integer>1722</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19456,24 +19456,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>28</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19489,7 +19489,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1705</integer>
+      <key>line</key><integer>1722</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19497,12 +19497,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1705</integer>
+         <key>line</key><integer>1722</integer>
          <key>col</key><integer>39</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19522,12 +19522,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1705</integer>
+           <key>line</key><integer>1722</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19535,12 +19535,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1706</integer>
+           <key>line</key><integer>1723</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1706</integer>
+           <key>line</key><integer>1723</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19552,7 +19552,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1706</integer>
+      <key>line</key><integer>1723</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19574,7 +19574,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1706</integer>
+   <key>line</key><integer>1723</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -19582,10 +19582,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1703</integer>
-    <integer>1704</integer>
-    <integer>1705</integer>
-    <integer>1706</integer>
+    <integer>1720</integer>
+    <integer>1721</integer>
+    <integer>1722</integer>
+    <integer>1723</integer>
    </array>
   </dict>
   </dict>
@@ -19600,12 +19600,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1752</integer>
+           <key>line</key><integer>1769</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1752</integer>
+           <key>line</key><integer>1769</integer>
            <key>col</key><integer>14</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19613,12 +19613,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19634,12 +19634,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19647,12 +19647,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19664,7 +19664,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1755</integer>
+      <key>line</key><integer>1772</integer>
       <key>col</key><integer>12</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19672,12 +19672,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1755</integer>
+         <key>line</key><integer>1772</integer>
          <key>col</key><integer>12</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1755</integer>
+         <key>line</key><integer>1772</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19693,7 +19693,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1755</integer>
+      <key>line</key><integer>1772</integer>
       <key>col</key><integer>12</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19701,12 +19701,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1755</integer>
+         <key>line</key><integer>1772</integer>
          <key>col</key><integer>12</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1755</integer>
+         <key>line</key><integer>1772</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19726,12 +19726,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1755</integer>
+           <key>line</key><integer>1772</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19739,12 +19739,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1756</integer>
+           <key>line</key><integer>1773</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1756</integer>
+           <key>line</key><integer>1773</integer>
            <key>col</key><integer>23</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19760,12 +19760,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1756</integer>
+           <key>line</key><integer>1773</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1756</integer>
+           <key>line</key><integer>1773</integer>
            <key>col</key><integer>23</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19773,12 +19773,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1758</integer>
+           <key>line</key><integer>1775</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1758</integer>
+           <key>line</key><integer>1775</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19790,7 +19790,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1758</integer>
+      <key>line</key><integer>1775</integer>
       <key>col</key><integer>16</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19798,12 +19798,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1758</integer>
+         <key>line</key><integer>1775</integer>
          <key>col</key><integer>16</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1758</integer>
+         <key>line</key><integer>1775</integer>
          <key>col</key><integer>49</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19823,12 +19823,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1758</integer>
+           <key>line</key><integer>1775</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1758</integer>
+           <key>line</key><integer>1775</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19836,12 +19836,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19857,12 +19857,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19870,12 +19870,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19887,7 +19887,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1760</integer>
+      <key>line</key><integer>1777</integer>
       <key>col</key><integer>13</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19895,12 +19895,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1760</integer>
+         <key>line</key><integer>1777</integer>
          <key>col</key><integer>13</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1760</integer>
+         <key>line</key><integer>1777</integer>
          <key>col</key><integer>30</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -19920,12 +19920,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1760</integer>
+           <key>line</key><integer>1777</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19933,12 +19933,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1763</integer>
+           <key>line</key><integer>1780</integer>
            <key>col</key><integer>23</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1763</integer>
+           <key>line</key><integer>1780</integer>
            <key>col</key><integer>23</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -19950,7 +19950,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1763</integer>
+      <key>line</key><integer>1780</integer>
       <key>col</key><integer>23</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -19972,7 +19972,7 @@
   <key>issue_hash_function_offset</key><string>7</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1763</integer>
+   <key>line</key><integer>1780</integer>
    <key>col</key><integer>23</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -19980,15 +19980,15 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1750</integer>
-    <integer>1751</integer>
-    <integer>1752</integer>
-    <integer>1754</integer>
-    <integer>1755</integer>
-    <integer>1756</integer>
-    <integer>1758</integer>
-    <integer>1760</integer>
-    <integer>1763</integer>
+    <integer>1767</integer>
+    <integer>1768</integer>
+    <integer>1769</integer>
+    <integer>1771</integer>
+    <integer>1772</integer>
+    <integer>1773</integer>
+    <integer>1775</integer>
+    <integer>1777</integer>
+    <integer>1780</integer>
    </array>
   </dict>
   </dict>
@@ -19999,7 +19999,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1806</integer>
+      <key>line</key><integer>1823</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20007,12 +20007,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1806</integer>
+         <key>line</key><integer>1823</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1806</integer>
+         <key>line</key><integer>1823</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20028,7 +20028,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1806</integer>
+      <key>line</key><integer>1823</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20036,12 +20036,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1806</integer>
+         <key>line</key><integer>1823</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1806</integer>
+         <key>line</key><integer>1823</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20065,7 +20065,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1806</integer>
+   <key>line</key><integer>1823</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -20073,8 +20073,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1805</integer>
-    <integer>1806</integer>
+    <integer>1822</integer>
+    <integer>1823</integer>
    </array>
   </dict>
   </dict>
@@ -20085,7 +20085,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1814</integer>
+      <key>line</key><integer>1831</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20093,12 +20093,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1814</integer>
+         <key>line</key><integer>1831</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1814</integer>
+         <key>line</key><integer>1831</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20114,7 +20114,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1814</integer>
+      <key>line</key><integer>1831</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20122,12 +20122,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1814</integer>
+         <key>line</key><integer>1831</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1814</integer>
+         <key>line</key><integer>1831</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20151,7 +20151,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1814</integer>
+   <key>line</key><integer>1831</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -20159,8 +20159,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1813</integer>
-    <integer>1814</integer>
+    <integer>1830</integer>
+    <integer>1831</integer>
    </array>
   </dict>
   </dict>
@@ -20171,7 +20171,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1835</integer>
+      <key>line</key><integer>1852</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20179,12 +20179,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1835</integer>
+         <key>line</key><integer>1852</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1835</integer>
+         <key>line</key><integer>1852</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20200,7 +20200,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1835</integer>
+      <key>line</key><integer>1852</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20208,12 +20208,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1835</integer>
+         <key>line</key><integer>1852</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1835</integer>
+         <key>line</key><integer>1852</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20237,7 +20237,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1835</integer>
+   <key>line</key><integer>1852</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -20245,8 +20245,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1834</integer>
-    <integer>1835</integer>
+    <integer>1851</integer>
+    <integer>1852</integer>
    </array>
   </dict>
   </dict>
@@ -20257,7 +20257,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1847</integer>
+      <key>line</key><integer>1864</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20265,12 +20265,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1847</integer>
+         <key>line</key><integer>1864</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1847</integer>
+         <key>line</key><integer>1864</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20286,7 +20286,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1847</integer>
+      <key>line</key><integer>1864</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20294,12 +20294,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1847</integer>
+         <key>line</key><integer>1864</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1847</integer>
+         <key>line</key><integer>1864</integer>
          <key>col</key><integer>60</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20323,7 +20323,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1847</integer>
+   <key>line</key><integer>1864</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -20331,8 +20331,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1846</integer>
-    <integer>1847</integer>
+    <integer>1863</integer>
+    <integer>1864</integer>
    </array>
   </dict>
   </dict>
@@ -20347,12 +20347,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1865</integer>
+           <key>line</key><integer>1882</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1865</integer>
+           <key>line</key><integer>1882</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20360,12 +20360,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1866</integer>
+           <key>line</key><integer>1883</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1866</integer>
+           <key>line</key><integer>1883</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20377,7 +20377,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1866</integer>
+      <key>line</key><integer>1883</integer>
       <key>col</key><integer>24</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20385,12 +20385,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1866</integer>
+         <key>line</key><integer>1883</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1866</integer>
+         <key>line</key><integer>1883</integer>
          <key>col</key><integer>41</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20410,12 +20410,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1866</integer>
+           <key>line</key><integer>1883</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1866</integer>
+           <key>line</key><integer>1883</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20423,12 +20423,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1867</integer>
+           <key>line</key><integer>1884</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1867</integer>
+           <key>line</key><integer>1884</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20440,7 +20440,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1867</integer>
+      <key>line</key><integer>1884</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20462,7 +20462,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1867</integer>
+   <key>line</key><integer>1884</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -20470,10 +20470,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1864</integer>
-    <integer>1865</integer>
-    <integer>1866</integer>
-    <integer>1867</integer>
+    <integer>1881</integer>
+    <integer>1882</integer>
+    <integer>1883</integer>
+    <integer>1884</integer>
    </array>
   </dict>
   </dict>
@@ -20488,12 +20488,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1889</integer>
+           <key>line</key><integer>1906</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1889</integer>
+           <key>line</key><integer>1906</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20501,12 +20501,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1891</integer>
+           <key>line</key><integer>1908</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1891</integer>
+           <key>line</key><integer>1908</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20518,7 +20518,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1891</integer>
+      <key>line</key><integer>1908</integer>
       <key>col</key><integer>22</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20526,12 +20526,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1891</integer>
+         <key>line</key><integer>1908</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1891</integer>
+         <key>line</key><integer>1908</integer>
          <key>col</key><integer>64</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20551,12 +20551,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1891</integer>
+           <key>line</key><integer>1908</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1891</integer>
+           <key>line</key><integer>1908</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20564,12 +20564,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1892</integer>
+           <key>line</key><integer>1909</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1892</integer>
+           <key>line</key><integer>1909</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20581,7 +20581,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1892</integer>
+      <key>line</key><integer>1909</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20589,24 +20589,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1892</integer>
+         <key>line</key><integer>1909</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1892</integer>
+         <key>line</key><integer>1909</integer>
          <key>col</key><integer>18</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>1892</integer>
+         <key>line</key><integer>1909</integer>
          <key>col</key><integer>4</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1892</integer>
+         <key>line</key><integer>1909</integer>
          <key>col</key><integer>9</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20626,12 +20626,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1892</integer>
+           <key>line</key><integer>1909</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1892</integer>
+           <key>line</key><integer>1909</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20639,12 +20639,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1894</integer>
+           <key>line</key><integer>1911</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1894</integer>
+           <key>line</key><integer>1911</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20660,12 +20660,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>1894</integer>
+           <key>line</key><integer>1911</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1894</integer>
+           <key>line</key><integer>1911</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20673,12 +20673,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>1894</integer>
+           <key>line</key><integer>1911</integer>
            <key>col</key><integer>27</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>1894</integer>
+           <key>line</key><integer>1911</integer>
            <key>col</key><integer>27</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20690,7 +20690,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>1894</integer>
+      <key>line</key><integer>1911</integer>
       <key>col</key><integer>27</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20698,12 +20698,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>1894</integer>
+         <key>line</key><integer>1911</integer>
          <key>col</key><integer>28</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>1894</integer>
+         <key>line</key><integer>1911</integer>
          <key>col</key><integer>33</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20727,7 +20727,7 @@
   <key>issue_hash_function_offset</key><string>6</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>1894</integer>
+   <key>line</key><integer>1911</integer>
    <key>col</key><integer>27</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -20735,11 +20735,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>1888</integer>
-    <integer>1889</integer>
-    <integer>1891</integer>
-    <integer>1892</integer>
-    <integer>1894</integer>
+    <integer>1905</integer>
+    <integer>1906</integer>
+    <integer>1908</integer>
+    <integer>1909</integer>
+    <integer>1911</integer>
    </array>
   </dict>
   </dict>
@@ -20754,12 +20754,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20767,12 +20767,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2020</integer>
+           <key>line</key><integer>2037</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2020</integer>
+           <key>line</key><integer>2037</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20784,7 +20784,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2020</integer>
+      <key>line</key><integer>2037</integer>
       <key>col</key><integer>22</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20792,12 +20792,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2020</integer>
+         <key>line</key><integer>2037</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2020</integer>
+         <key>line</key><integer>2037</integer>
          <key>col</key><integer>66</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20817,12 +20817,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2020</integer>
+           <key>line</key><integer>2037</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2020</integer>
+           <key>line</key><integer>2037</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20830,12 +20830,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20847,7 +20847,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2023</integer>
+      <key>line</key><integer>2040</integer>
       <key>col</key><integer>9</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -20855,12 +20855,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2023</integer>
+         <key>line</key><integer>2040</integer>
          <key>col</key><integer>9</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2023</integer>
+         <key>line</key><integer>2040</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -20884,7 +20884,7 @@
   <key>issue_hash_function_offset</key><string>3</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2023</integer>
+   <key>line</key><integer>2040</integer>
    <key>col</key><integer>9</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -20892,12 +20892,12 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2017</integer>
-    <integer>2019</integer>
-    <integer>2020</integer>
-    <integer>2021</integer>
-    <integer>2022</integer>
-    <integer>2023</integer>
+    <integer>2034</integer>
+    <integer>2036</integer>
+    <integer>2037</integer>
+    <integer>2038</integer>
+    <integer>2039</integer>
+    <integer>2040</integer>
    </array>
   </dict>
   </dict>
@@ -20912,12 +20912,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20925,12 +20925,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20946,12 +20946,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20959,12 +20959,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20980,12 +20980,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -20993,12 +20993,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2029</integer>
+           <key>line</key><integer>2046</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2029</integer>
+           <key>line</key><integer>2046</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21010,7 +21010,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2029</integer>
+      <key>line</key><integer>2046</integer>
       <key>col</key><integer>23</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -21018,12 +21018,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2029</integer>
+         <key>line</key><integer>2046</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2029</integer>
+         <key>line</key><integer>2046</integer>
          <key>col</key><integer>56</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -21043,12 +21043,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2029</integer>
+           <key>line</key><integer>2046</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2029</integer>
+           <key>line</key><integer>2046</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21056,12 +21056,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21073,7 +21073,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2032</integer>
+      <key>line</key><integer>2049</integer>
       <key>col</key><integer>9</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -21081,12 +21081,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2032</integer>
+         <key>line</key><integer>2049</integer>
          <key>col</key><integer>9</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2032</integer>
+         <key>line</key><integer>2049</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -21110,7 +21110,7 @@
   <key>issue_hash_function_offset</key><string>12</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2032</integer>
+   <key>line</key><integer>2049</integer>
    <key>col</key><integer>9</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -21118,18 +21118,18 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2017</integer>
-    <integer>2019</integer>
-    <integer>2020</integer>
-    <integer>2021</integer>
-    <integer>2022</integer>
-    <integer>2023</integer>
-    <integer>2027</integer>
-    <integer>2028</integer>
-    <integer>2029</integer>
-    <integer>2030</integer>
-    <integer>2031</integer>
-    <integer>2032</integer>
+    <integer>2034</integer>
+    <integer>2036</integer>
+    <integer>2037</integer>
+    <integer>2038</integer>
+    <integer>2039</integer>
+    <integer>2040</integer>
+    <integer>2044</integer>
+    <integer>2045</integer>
+    <integer>2046</integer>
+    <integer>2047</integer>
+    <integer>2048</integer>
+    <integer>2049</integer>
    </array>
   </dict>
   </dict>
@@ -21144,12 +21144,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21157,12 +21157,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21178,12 +21178,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21191,12 +21191,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21212,12 +21212,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21225,12 +21225,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21246,12 +21246,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21259,12 +21259,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21280,12 +21280,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21293,12 +21293,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21314,12 +21314,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21327,12 +21327,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21344,7 +21344,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2037</integer>
+      <key>line</key><integer>2054</integer>
       <key>col</key><integer>24</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -21352,12 +21352,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2037</integer>
+         <key>line</key><integer>2054</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2037</integer>
+         <key>line</key><integer>2054</integer>
          <key>col</key><integer>27</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -21373,7 +21373,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2037</integer>
+      <key>line</key><integer>2054</integer>
       <key>col</key><integer>23</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -21381,24 +21381,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2037</integer>
+         <key>line</key><integer>2054</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2037</integer>
+         <key>line</key><integer>2054</integer>
          <key>col</key><integer>35</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2037</integer>
+         <key>line</key><integer>2054</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2037</integer>
+         <key>line</key><integer>2054</integer>
          <key>col</key><integer>27</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -21418,12 +21418,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>23</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>23</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21431,12 +21431,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21452,12 +21452,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2037</integer>
+           <key>line</key><integer>2054</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21465,12 +21465,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21482,7 +21482,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2040</integer>
+      <key>line</key><integer>2057</integer>
       <key>col</key><integer>9</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -21490,12 +21490,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2040</integer>
+         <key>line</key><integer>2057</integer>
          <key>col</key><integer>9</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2040</integer>
+         <key>line</key><integer>2057</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -21519,7 +21519,7 @@
   <key>issue_hash_function_offset</key><string>20</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2040</integer>
+   <key>line</key><integer>2057</integer>
    <key>col</key><integer>9</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -21527,23 +21527,23 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2017</integer>
-    <integer>2019</integer>
-    <integer>2020</integer>
-    <integer>2021</integer>
-    <integer>2022</integer>
-    <integer>2023</integer>
-    <integer>2027</integer>
-    <integer>2028</integer>
-    <integer>2029</integer>
-    <integer>2030</integer>
-    <integer>2031</integer>
-    <integer>2032</integer>
+    <integer>2034</integer>
     <integer>2036</integer>
     <integer>2037</integer>
     <integer>2038</integer>
     <integer>2039</integer>
     <integer>2040</integer>
+    <integer>2044</integer>
+    <integer>2045</integer>
+    <integer>2046</integer>
+    <integer>2047</integer>
+    <integer>2048</integer>
+    <integer>2049</integer>
+    <integer>2053</integer>
+    <integer>2054</integer>
+    <integer>2055</integer>
+    <integer>2056</integer>
+    <integer>2057</integer>
    </array>
   </dict>
   </dict>
@@ -21558,12 +21558,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21571,12 +21571,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21592,12 +21592,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21605,12 +21605,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21626,12 +21626,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21639,12 +21639,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21660,12 +21660,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21673,12 +21673,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21694,12 +21694,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21707,12 +21707,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21728,12 +21728,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21741,12 +21741,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21762,12 +21762,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21775,12 +21775,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2045</integer>
+           <key>line</key><integer>2062</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2045</integer>
+           <key>line</key><integer>2062</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21792,7 +21792,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2045</integer>
+      <key>line</key><integer>2062</integer>
       <key>col</key><integer>22</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -21800,12 +21800,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2045</integer>
+         <key>line</key><integer>2062</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2045</integer>
+         <key>line</key><integer>2062</integer>
          <key>col</key><integer>57</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -21825,12 +21825,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2045</integer>
+           <key>line</key><integer>2062</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2045</integer>
+           <key>line</key><integer>2062</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21838,12 +21838,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2049</integer>
+           <key>line</key><integer>2066</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2049</integer>
+           <key>line</key><integer>2066</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21855,7 +21855,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2049</integer>
+      <key>line</key><integer>2066</integer>
       <key>col</key><integer>9</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -21863,12 +21863,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2049</integer>
+         <key>line</key><integer>2066</integer>
          <key>col</key><integer>9</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2049</integer>
+         <key>line</key><integer>2066</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -21892,7 +21892,7 @@
   <key>issue_hash_function_offset</key><string>28</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2049</integer>
+   <key>line</key><integer>2066</integer>
    <key>col</key><integer>9</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -21900,18 +21900,7 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2017</integer>
-    <integer>2019</integer>
-    <integer>2020</integer>
-    <integer>2021</integer>
-    <integer>2022</integer>
-    <integer>2023</integer>
-    <integer>2027</integer>
-    <integer>2028</integer>
-    <integer>2029</integer>
-    <integer>2030</integer>
-    <integer>2031</integer>
-    <integer>2032</integer>
+    <integer>2034</integer>
     <integer>2036</integer>
     <integer>2037</integer>
     <integer>2038</integer>
@@ -21920,8 +21909,19 @@
     <integer>2044</integer>
     <integer>2045</integer>
     <integer>2046</integer>
+    <integer>2047</integer>
     <integer>2048</integer>
     <integer>2049</integer>
+    <integer>2053</integer>
+    <integer>2054</integer>
+    <integer>2055</integer>
+    <integer>2056</integer>
+    <integer>2057</integer>
+    <integer>2061</integer>
+    <integer>2062</integer>
+    <integer>2063</integer>
+    <integer>2065</integer>
+    <integer>2066</integer>
    </array>
   </dict>
   </dict>
@@ -21936,12 +21936,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2019</integer>
+           <key>line</key><integer>2036</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21949,12 +21949,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21970,12 +21970,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2023</integer>
+           <key>line</key><integer>2040</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -21983,12 +21983,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22004,12 +22004,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2027</integer>
+           <key>line</key><integer>2044</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22017,12 +22017,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22038,12 +22038,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2032</integer>
+           <key>line</key><integer>2049</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22051,12 +22051,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22072,12 +22072,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2036</integer>
+           <key>line</key><integer>2053</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22085,12 +22085,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22106,12 +22106,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2040</integer>
+           <key>line</key><integer>2057</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22119,12 +22119,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22140,12 +22140,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2044</integer>
+           <key>line</key><integer>2061</integer>
            <key>col</key><integer>16</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22153,12 +22153,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2049</integer>
+           <key>line</key><integer>2066</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2049</integer>
+           <key>line</key><integer>2066</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22174,12 +22174,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2049</integer>
+           <key>line</key><integer>2066</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2049</integer>
+           <key>line</key><integer>2066</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22187,12 +22187,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2053</integer>
+           <key>line</key><integer>2070</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2053</integer>
+           <key>line</key><integer>2070</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22208,12 +22208,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2053</integer>
+           <key>line</key><integer>2070</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2053</integer>
+           <key>line</key><integer>2070</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22221,12 +22221,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22242,12 +22242,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22255,12 +22255,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>28</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>28</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22272,7 +22272,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2054</integer>
+      <key>line</key><integer>2071</integer>
       <key>col</key><integer>28</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22280,12 +22280,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2054</integer>
+         <key>line</key><integer>2071</integer>
          <key>col</key><integer>28</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2054</integer>
+         <key>line</key><integer>2071</integer>
          <key>col</key><integer>35</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22301,7 +22301,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2054</integer>
+      <key>line</key><integer>2071</integer>
       <key>col</key><integer>27</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22309,24 +22309,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2054</integer>
+         <key>line</key><integer>2071</integer>
          <key>col</key><integer>27</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2054</integer>
+         <key>line</key><integer>2071</integer>
          <key>col</key><integer>43</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2054</integer>
+         <key>line</key><integer>2071</integer>
          <key>col</key><integer>28</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2054</integer>
+         <key>line</key><integer>2071</integer>
          <key>col</key><integer>35</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22346,12 +22346,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>27</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>27</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22359,12 +22359,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22380,12 +22380,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2054</integer>
+           <key>line</key><integer>2071</integer>
            <key>col</key><integer>20</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22393,12 +22393,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2058</integer>
+           <key>line</key><integer>2075</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2058</integer>
+           <key>line</key><integer>2075</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22410,7 +22410,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2058</integer>
+      <key>line</key><integer>2075</integer>
       <key>col</key><integer>9</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22418,12 +22418,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2058</integer>
+         <key>line</key><integer>2075</integer>
          <key>col</key><integer>9</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2058</integer>
+         <key>line</key><integer>2075</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22447,7 +22447,7 @@
   <key>issue_hash_function_offset</key><string>37</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2058</integer>
+   <key>line</key><integer>2075</integer>
    <key>col</key><integer>9</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -22455,18 +22455,7 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2017</integer>
-    <integer>2019</integer>
-    <integer>2020</integer>
-    <integer>2021</integer>
-    <integer>2022</integer>
-    <integer>2023</integer>
-    <integer>2027</integer>
-    <integer>2028</integer>
-    <integer>2029</integer>
-    <integer>2030</integer>
-    <integer>2031</integer>
-    <integer>2032</integer>
+    <integer>2034</integer>
     <integer>2036</integer>
     <integer>2037</integer>
     <integer>2038</integer>
@@ -22475,13 +22464,24 @@
     <integer>2044</integer>
     <integer>2045</integer>
     <integer>2046</integer>
+    <integer>2047</integer>
     <integer>2048</integer>
     <integer>2049</integer>
     <integer>2053</integer>
     <integer>2054</integer>
     <integer>2055</integer>
+    <integer>2056</integer>
     <integer>2057</integer>
-    <integer>2058</integer>
+    <integer>2061</integer>
+    <integer>2062</integer>
+    <integer>2063</integer>
+    <integer>2065</integer>
+    <integer>2066</integer>
+    <integer>2070</integer>
+    <integer>2071</integer>
+    <integer>2072</integer>
+    <integer>2074</integer>
+    <integer>2075</integer>
    </array>
   </dict>
   </dict>
@@ -22496,12 +22496,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22509,12 +22509,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22526,7 +22526,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2063</integer>
+      <key>line</key><integer>2080</integer>
       <key>col</key><integer>15</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22534,12 +22534,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2063</integer>
+         <key>line</key><integer>2080</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2063</integer>
+         <key>line</key><integer>2080</integer>
          <key>col</key><integer>16</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22555,7 +22555,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2063</integer>
+      <key>line</key><integer>2080</integer>
       <key>col</key><integer>14</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22563,24 +22563,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2063</integer>
+         <key>line</key><integer>2080</integer>
          <key>col</key><integer>14</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2063</integer>
+         <key>line</key><integer>2080</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2063</integer>
+         <key>line</key><integer>2080</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2063</integer>
+         <key>line</key><integer>2080</integer>
          <key>col</key><integer>16</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22600,12 +22600,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>14</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>14</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22613,12 +22613,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22634,12 +22634,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2063</integer>
+           <key>line</key><integer>2080</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22647,12 +22647,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2064</integer>
+           <key>line</key><integer>2081</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2064</integer>
+           <key>line</key><integer>2081</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22668,12 +22668,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2064</integer>
+           <key>line</key><integer>2081</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2064</integer>
+           <key>line</key><integer>2081</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22681,12 +22681,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2065</integer>
+           <key>line</key><integer>2082</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2065</integer>
+           <key>line</key><integer>2082</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22698,7 +22698,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2065</integer>
+      <key>line</key><integer>2082</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22720,7 +22720,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2065</integer>
+   <key>line</key><integer>2082</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -22728,10 +22728,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2062</integer>
-    <integer>2063</integer>
-    <integer>2064</integer>
-    <integer>2065</integer>
+    <integer>2079</integer>
+    <integer>2080</integer>
+    <integer>2081</integer>
+    <integer>2082</integer>
    </array>
   </dict>
   </dict>
@@ -22746,12 +22746,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22759,12 +22759,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22776,7 +22776,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2068</integer>
+      <key>line</key><integer>2085</integer>
       <key>col</key><integer>15</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22784,12 +22784,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2068</integer>
+         <key>line</key><integer>2085</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2068</integer>
+         <key>line</key><integer>2085</integer>
          <key>col</key><integer>18</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22805,7 +22805,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2068</integer>
+      <key>line</key><integer>2085</integer>
       <key>col</key><integer>14</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22813,24 +22813,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2068</integer>
+         <key>line</key><integer>2085</integer>
          <key>col</key><integer>14</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2068</integer>
+         <key>line</key><integer>2085</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2068</integer>
+         <key>line</key><integer>2085</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2068</integer>
+         <key>line</key><integer>2085</integer>
          <key>col</key><integer>18</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22850,12 +22850,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>14</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>14</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22863,12 +22863,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22884,12 +22884,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22897,12 +22897,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2072</integer>
+           <key>line</key><integer>2089</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2072</integer>
+           <key>line</key><integer>2089</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22914,7 +22914,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2072</integer>
+      <key>line</key><integer>2089</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -22922,12 +22922,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2072</integer>
+         <key>line</key><integer>2089</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2072</integer>
+         <key>line</key><integer>2089</integer>
          <key>col</key><integer>21</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -22951,7 +22951,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2072</integer>
+   <key>line</key><integer>2089</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -22959,11 +22959,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2067</integer>
-    <integer>2068</integer>
-    <integer>2069</integer>
-    <integer>2071</integer>
-    <integer>2072</integer>
+    <integer>2084</integer>
+    <integer>2085</integer>
+    <integer>2086</integer>
+    <integer>2088</integer>
+    <integer>2089</integer>
    </array>
   </dict>
   </dict>
@@ -22978,12 +22978,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2068</integer>
+           <key>line</key><integer>2085</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -22991,12 +22991,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23012,12 +23012,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23025,12 +23025,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23042,7 +23042,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2071</integer>
+      <key>line</key><integer>2088</integer>
       <key>col</key><integer>12</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23050,12 +23050,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2071</integer>
+         <key>line</key><integer>2088</integer>
          <key>col</key><integer>12</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2071</integer>
+         <key>line</key><integer>2088</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23071,7 +23071,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2071</integer>
+      <key>line</key><integer>2088</integer>
       <key>col</key><integer>11</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23079,24 +23079,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2071</integer>
+         <key>line</key><integer>2088</integer>
          <key>col</key><integer>11</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2071</integer>
+         <key>line</key><integer>2088</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2071</integer>
+         <key>line</key><integer>2088</integer>
          <key>col</key><integer>12</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2071</integer>
+         <key>line</key><integer>2088</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23116,12 +23116,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23129,12 +23129,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23150,12 +23150,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2071</integer>
+           <key>line</key><integer>2088</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23163,12 +23163,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2072</integer>
+           <key>line</key><integer>2089</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2072</integer>
+           <key>line</key><integer>2089</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23184,12 +23184,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2072</integer>
+           <key>line</key><integer>2089</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2072</integer>
+           <key>line</key><integer>2089</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23197,12 +23197,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2073</integer>
+           <key>line</key><integer>2090</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2073</integer>
+           <key>line</key><integer>2090</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23214,7 +23214,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2073</integer>
+      <key>line</key><integer>2090</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23236,7 +23236,7 @@
   <key>issue_hash_function_offset</key><string>4</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2073</integer>
+   <key>line</key><integer>2090</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -23244,12 +23244,12 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2067</integer>
-    <integer>2068</integer>
-    <integer>2069</integer>
-    <integer>2071</integer>
-    <integer>2072</integer>
-    <integer>2073</integer>
+    <integer>2084</integer>
+    <integer>2085</integer>
+    <integer>2086</integer>
+    <integer>2088</integer>
+    <integer>2089</integer>
+    <integer>2090</integer>
    </array>
   </dict>
   </dict>
@@ -23264,12 +23264,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2079</integer>
+           <key>line</key><integer>2096</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2079</integer>
+           <key>line</key><integer>2096</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23277,12 +23277,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>6</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23298,12 +23298,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>6</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23311,12 +23311,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23328,7 +23328,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2080</integer>
+      <key>line</key><integer>2097</integer>
       <key>col</key><integer>8</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23336,12 +23336,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2080</integer>
+         <key>line</key><integer>2097</integer>
          <key>col</key><integer>8</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2080</integer>
+         <key>line</key><integer>2097</integer>
          <key>col</key><integer>12</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23361,12 +23361,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2080</integer>
+           <key>line</key><integer>2097</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23374,12 +23374,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2083</integer>
+           <key>line</key><integer>2100</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2083</integer>
+           <key>line</key><integer>2100</integer>
            <key>col</key><integer>17</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23391,7 +23391,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2083</integer>
+      <key>line</key><integer>2100</integer>
       <key>col</key><integer>21</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23399,12 +23399,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2083</integer>
+         <key>line</key><integer>2100</integer>
          <key>col</key><integer>21</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2083</integer>
+         <key>line</key><integer>2100</integer>
          <key>col</key><integer>43</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23424,12 +23424,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2083</integer>
+           <key>line</key><integer>2100</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2083</integer>
+           <key>line</key><integer>2100</integer>
            <key>col</key><integer>17</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23437,12 +23437,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2084</integer>
+           <key>line</key><integer>2101</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2084</integer>
+           <key>line</key><integer>2101</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23458,12 +23458,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2084</integer>
+           <key>line</key><integer>2101</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2084</integer>
+           <key>line</key><integer>2101</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23471,12 +23471,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2085</integer>
+           <key>line</key><integer>2102</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2085</integer>
+           <key>line</key><integer>2102</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23488,7 +23488,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2085</integer>
+      <key>line</key><integer>2102</integer>
       <key>col</key><integer>5</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23496,24 +23496,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2085</integer>
+         <key>line</key><integer>2102</integer>
          <key>col</key><integer>5</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2085</integer>
+         <key>line</key><integer>2102</integer>
          <key>col</key><integer>25</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2085</integer>
+         <key>line</key><integer>2102</integer>
          <key>col</key><integer>6</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2085</integer>
+         <key>line</key><integer>2102</integer>
          <key>col</key><integer>16</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23533,12 +23533,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2085</integer>
+           <key>line</key><integer>2102</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2085</integer>
+           <key>line</key><integer>2102</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23546,12 +23546,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2086</integer>
+           <key>line</key><integer>2103</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2086</integer>
+           <key>line</key><integer>2103</integer>
            <key>col</key><integer>9</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23563,7 +23563,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2086</integer>
+      <key>line</key><integer>2103</integer>
       <key>col</key><integer>5</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23571,12 +23571,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2086</integer>
+         <key>line</key><integer>2103</integer>
          <key>col</key><integer>25</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2086</integer>
+         <key>line</key><integer>2103</integer>
          <key>col</key><integer>35</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23600,7 +23600,7 @@
   <key>issue_hash_function_offset</key><string>9</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2086</integer>
+   <key>line</key><integer>2103</integer>
    <key>col</key><integer>5</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -23608,14 +23608,14 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2076</integer>
-    <integer>2077</integer>
-    <integer>2079</integer>
-    <integer>2080</integer>
-    <integer>2083</integer>
-    <integer>2084</integer>
-    <integer>2085</integer>
-    <integer>2086</integer>
+    <integer>2093</integer>
+    <integer>2094</integer>
+    <integer>2096</integer>
+    <integer>2097</integer>
+    <integer>2100</integer>
+    <integer>2101</integer>
+    <integer>2102</integer>
+    <integer>2103</integer>
    </array>
   </dict>
   </dict>
@@ -23630,12 +23630,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2104</integer>
+           <key>line</key><integer>2121</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2104</integer>
+           <key>line</key><integer>2121</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23643,12 +23643,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2112</integer>
+           <key>line</key><integer>2129</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2112</integer>
+           <key>line</key><integer>2129</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23660,7 +23660,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2112</integer>
+      <key>line</key><integer>2129</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23668,12 +23668,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2112</integer>
+         <key>line</key><integer>2129</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2112</integer>
+         <key>line</key><integer>2129</integer>
          <key>col</key><integer>21</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23693,12 +23693,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2112</integer>
+           <key>line</key><integer>2129</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2112</integer>
+           <key>line</key><integer>2129</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23706,12 +23706,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2113</integer>
+           <key>line</key><integer>2130</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2113</integer>
+           <key>line</key><integer>2130</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23723,7 +23723,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2113</integer>
+      <key>line</key><integer>2130</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23731,12 +23731,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2113</integer>
+         <key>line</key><integer>2130</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2113</integer>
+         <key>line</key><integer>2130</integer>
          <key>col</key><integer>35</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23760,7 +23760,7 @@
   <key>issue_hash_function_offset</key><string>10</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2113</integer>
+   <key>line</key><integer>2130</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -23768,13 +23768,13 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2103</integer>
-    <integer>2104</integer>
-    <integer>2105</integer>
-    <integer>2107</integer>
-    <integer>2108</integer>
-    <integer>2112</integer>
-    <integer>2113</integer>
+    <integer>2120</integer>
+    <integer>2121</integer>
+    <integer>2122</integer>
+    <integer>2124</integer>
+    <integer>2125</integer>
+    <integer>2129</integer>
+    <integer>2130</integer>
    </array>
   </dict>
   </dict>
@@ -23789,12 +23789,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2117</integer>
+           <key>line</key><integer>2134</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2117</integer>
+           <key>line</key><integer>2134</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23802,12 +23802,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2125</integer>
+           <key>line</key><integer>2142</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2125</integer>
+           <key>line</key><integer>2142</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23819,7 +23819,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2125</integer>
+      <key>line</key><integer>2142</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23827,12 +23827,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2125</integer>
+         <key>line</key><integer>2142</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2125</integer>
+         <key>line</key><integer>2142</integer>
          <key>col</key><integer>21</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23852,12 +23852,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2125</integer>
+           <key>line</key><integer>2142</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2125</integer>
+           <key>line</key><integer>2142</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23865,12 +23865,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2126</integer>
+           <key>line</key><integer>2143</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2126</integer>
+           <key>line</key><integer>2143</integer>
            <key>col</key><integer>26</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23882,7 +23882,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2126</integer>
+      <key>line</key><integer>2143</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23890,12 +23890,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2126</integer>
+         <key>line</key><integer>2143</integer>
          <key>col</key><integer>28</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2126</integer>
+         <key>line</key><integer>2143</integer>
          <key>col</key><integer>48</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23919,7 +23919,7 @@
   <key>issue_hash_function_offset</key><string>10</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2126</integer>
+   <key>line</key><integer>2143</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -23927,13 +23927,13 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2116</integer>
-    <integer>2117</integer>
-    <integer>2118</integer>
-    <integer>2120</integer>
-    <integer>2121</integer>
-    <integer>2125</integer>
-    <integer>2126</integer>
+    <integer>2133</integer>
+    <integer>2134</integer>
+    <integer>2135</integer>
+    <integer>2137</integer>
+    <integer>2138</integer>
+    <integer>2142</integer>
+    <integer>2143</integer>
    </array>
   </dict>
   </dict>
@@ -23944,7 +23944,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2138</integer>
+      <key>line</key><integer>2155</integer>
       <key>col</key><integer>16</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -23952,12 +23952,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2138</integer>
+         <key>line</key><integer>2155</integer>
          <key>col</key><integer>16</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2138</integer>
+         <key>line</key><integer>2155</integer>
          <key>col</key><integer>31</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -23977,12 +23977,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2138</integer>
+           <key>line</key><integer>2155</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2138</integer>
+           <key>line</key><integer>2155</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -23990,12 +23990,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2139</integer>
+           <key>line</key><integer>2156</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2139</integer>
+           <key>line</key><integer>2156</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24007,7 +24007,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2139</integer>
+      <key>line</key><integer>2156</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24029,7 +24029,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2139</integer>
+   <key>line</key><integer>2156</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -24037,9 +24037,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2137</integer>
-    <integer>2138</integer>
-    <integer>2139</integer>
+    <integer>2154</integer>
+    <integer>2155</integer>
+    <integer>2156</integer>
    </array>
   </dict>
   </dict>
@@ -24050,7 +24050,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2173</integer>
+      <key>line</key><integer>2190</integer>
       <key>col</key><integer>18</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24058,12 +24058,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2173</integer>
+         <key>line</key><integer>2190</integer>
          <key>col</key><integer>18</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2173</integer>
+         <key>line</key><integer>2190</integer>
          <key>col</key><integer>29</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24083,12 +24083,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2173</integer>
+           <key>line</key><integer>2190</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2173</integer>
+           <key>line</key><integer>2190</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24096,12 +24096,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2174</integer>
+           <key>line</key><integer>2191</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2174</integer>
+           <key>line</key><integer>2191</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24113,7 +24113,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2174</integer>
+      <key>line</key><integer>2191</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24135,7 +24135,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2174</integer>
+   <key>line</key><integer>2191</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -24143,9 +24143,9 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2172</integer>
-    <integer>2173</integer>
-    <integer>2174</integer>
+    <integer>2189</integer>
+    <integer>2190</integer>
+    <integer>2191</integer>
    </array>
   </dict>
   </dict>
@@ -24156,7 +24156,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2177</integer>
+      <key>line</key><integer>2194</integer>
       <key>col</key><integer>13</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24164,12 +24164,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2177</integer>
+         <key>line</key><integer>2194</integer>
          <key>col</key><integer>13</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2177</integer>
+         <key>line</key><integer>2194</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24185,7 +24185,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2177</integer>
+      <key>line</key><integer>2194</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24193,12 +24193,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2177</integer>
+         <key>line</key><integer>2194</integer>
          <key>col</key><integer>13</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2177</integer>
+         <key>line</key><integer>2194</integer>
          <key>col</key><integer>23</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24222,7 +24222,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2177</integer>
+   <key>line</key><integer>2194</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -24230,8 +24230,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2176</integer>
-    <integer>2177</integer>
+    <integer>2193</integer>
+    <integer>2194</integer>
    </array>
   </dict>
   </dict>
@@ -24246,12 +24246,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24259,12 +24259,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24276,7 +24276,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2196</integer>
+      <key>line</key><integer>2213</integer>
       <key>col</key><integer>11</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24284,12 +24284,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>11</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>31</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24305,7 +24305,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2196</integer>
+      <key>line</key><integer>2213</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24313,12 +24313,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24334,7 +24334,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2189</integer>
+      <key>line</key><integer>2206</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24352,12 +24352,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2189</integer>
+           <key>line</key><integer>2206</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2189</integer>
+           <key>line</key><integer>2206</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24365,12 +24365,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24386,12 +24386,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24399,12 +24399,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24416,7 +24416,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2190</integer>
+      <key>line</key><integer>2207</integer>
       <key>col</key><integer>7</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24424,12 +24424,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2190</integer>
+         <key>line</key><integer>2207</integer>
          <key>col</key><integer>7</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2190</integer>
+         <key>line</key><integer>2207</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24449,12 +24449,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2190</integer>
+           <key>line</key><integer>2207</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24462,12 +24462,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2191</integer>
+           <key>line</key><integer>2208</integer>
            <key>col</key><integer>5</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2191</integer>
+           <key>line</key><integer>2208</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24479,7 +24479,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2196</integer>
+      <key>line</key><integer>2213</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24487,12 +24487,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24512,12 +24512,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24525,12 +24525,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2196</integer>
+           <key>line</key><integer>2213</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24542,7 +24542,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2196</integer>
+      <key>line</key><integer>2213</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24550,12 +24550,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2196</integer>
+         <key>line</key><integer>2213</integer>
          <key>col</key><integer>6</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24579,7 +24579,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2196</integer>
+   <key>line</key><integer>2213</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -24587,11 +24587,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2189</integer>
-    <integer>2190</integer>
-    <integer>2191</integer>
-    <integer>2195</integer>
-    <integer>2196</integer>
+    <integer>2206</integer>
+    <integer>2207</integer>
+    <integer>2208</integer>
+    <integer>2212</integer>
+    <integer>2213</integer>
    </array>
   </dict>
   </dict>
@@ -24606,12 +24606,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24619,12 +24619,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>37</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24636,7 +24636,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2212</integer>
+      <key>line</key><integer>2229</integer>
       <key>col</key><integer>24</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24644,12 +24644,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>39</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24669,12 +24669,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>37</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24682,12 +24682,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>22</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24699,7 +24699,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2212</integer>
+      <key>line</key><integer>2229</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24707,24 +24707,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>40</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>39</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24744,12 +24744,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>22</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24757,12 +24757,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2212</integer>
+           <key>line</key><integer>2229</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24774,7 +24774,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2212</integer>
+      <key>line</key><integer>2229</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24782,12 +24782,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2212</integer>
+         <key>line</key><integer>2229</integer>
          <key>col</key><integer>40</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24811,7 +24811,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2212</integer>
+   <key>line</key><integer>2229</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -24819,8 +24819,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2210</integer>
-    <integer>2212</integer>
+    <integer>2227</integer>
+    <integer>2229</integer>
    </array>
   </dict>
   </dict>
@@ -24835,12 +24835,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24848,12 +24848,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>40</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24865,7 +24865,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2217</integer>
+      <key>line</key><integer>2234</integer>
       <key>col</key><integer>24</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24873,12 +24873,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>42</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24898,12 +24898,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>24</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>40</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24911,12 +24911,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>22</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24928,7 +24928,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2217</integer>
+      <key>line</key><integer>2234</integer>
       <key>col</key><integer>10</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -24936,24 +24936,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>10</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>43</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>24</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>42</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -24973,12 +24973,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>22</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -24986,12 +24986,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2217</integer>
+           <key>line</key><integer>2234</integer>
            <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25003,7 +25003,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2217</integer>
+      <key>line</key><integer>2234</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25011,12 +25011,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2217</integer>
+         <key>line</key><integer>2234</integer>
          <key>col</key><integer>43</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25040,7 +25040,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2217</integer>
+   <key>line</key><integer>2234</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -25048,8 +25048,8 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2215</integer>
-    <integer>2217</integer>
+    <integer>2232</integer>
+    <integer>2234</integer>
    </array>
   </dict>
   </dict>
@@ -25060,7 +25060,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2232</integer>
+      <key>line</key><integer>2249</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25068,12 +25068,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2232</integer>
+         <key>line</key><integer>2249</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2232</integer>
+         <key>line</key><integer>2249</integer>
          <key>col</key><integer>37</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25093,12 +25093,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2232</integer>
+           <key>line</key><integer>2249</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2232</integer>
+           <key>line</key><integer>2249</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25106,12 +25106,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2233</integer>
+           <key>line</key><integer>2250</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2233</integer>
+           <key>line</key><integer>2250</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25123,7 +25123,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2233</integer>
+      <key>line</key><integer>2250</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25131,24 +25131,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2233</integer>
+         <key>line</key><integer>2250</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2233</integer>
+         <key>line</key><integer>2250</integer>
          <key>col</key><integer>16</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2233</integer>
+         <key>line</key><integer>2250</integer>
          <key>col</key><integer>13</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2233</integer>
+         <key>line</key><integer>2250</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25168,12 +25168,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2233</integer>
+           <key>line</key><integer>2250</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2233</integer>
+           <key>line</key><integer>2250</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25181,12 +25181,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2236</integer>
+           <key>line</key><integer>2253</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2236</integer>
+           <key>line</key><integer>2253</integer>
            <key>col</key><integer>7</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25198,7 +25198,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2236</integer>
+      <key>line</key><integer>2253</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25206,12 +25206,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2236</integer>
+         <key>line</key><integer>2253</integer>
          <key>col</key><integer>9</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2236</integer>
+         <key>line</key><integer>2253</integer>
          <key>col</key><integer>11</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25235,7 +25235,7 @@
   <key>issue_hash_function_offset</key><string>7</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2236</integer>
+   <key>line</key><integer>2253</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -25243,10 +25243,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2229</integer>
-    <integer>2232</integer>
-    <integer>2233</integer>
-    <integer>2236</integer>
+    <integer>2246</integer>
+    <integer>2249</integer>
+    <integer>2250</integer>
+    <integer>2253</integer>
    </array>
   </dict>
   </dict>
@@ -25257,7 +25257,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2241</integer>
+      <key>line</key><integer>2258</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25265,12 +25265,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2241</integer>
+         <key>line</key><integer>2258</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2241</integer>
+         <key>line</key><integer>2258</integer>
          <key>col</key><integer>37</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25290,12 +25290,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2241</integer>
+           <key>line</key><integer>2258</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2241</integer>
+           <key>line</key><integer>2258</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25303,12 +25303,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2242</integer>
+           <key>line</key><integer>2259</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2242</integer>
+           <key>line</key><integer>2259</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25320,7 +25320,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2242</integer>
+      <key>line</key><integer>2259</integer>
       <key>col</key><integer>22</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25328,24 +25328,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2242</integer>
+         <key>line</key><integer>2259</integer>
          <key>col</key><integer>22</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2242</integer>
+         <key>line</key><integer>2259</integer>
          <key>col</key><integer>39</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2242</integer>
+         <key>line</key><integer>2259</integer>
          <key>col</key><integer>36</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2242</integer>
+         <key>line</key><integer>2259</integer>
          <key>col</key><integer>38</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25361,7 +25361,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2242</integer>
+      <key>line</key><integer>2259</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25369,12 +25369,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2242</integer>
+         <key>line</key><integer>2259</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2242</integer>
+         <key>line</key><integer>2259</integer>
          <key>col</key><integer>18</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25394,12 +25394,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2242</integer>
+           <key>line</key><integer>2259</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2242</integer>
+           <key>line</key><integer>2259</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25407,12 +25407,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2243</integer>
+           <key>line</key><integer>2260</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2243</integer>
+           <key>line</key><integer>2260</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25424,7 +25424,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2243</integer>
+      <key>line</key><integer>2260</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25432,24 +25432,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2243</integer>
+         <key>line</key><integer>2260</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2243</integer>
+         <key>line</key><integer>2260</integer>
          <key>col</key><integer>18</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2243</integer>
+         <key>line</key><integer>2260</integer>
          <key>col</key><integer>12</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2243</integer>
+         <key>line</key><integer>2260</integer>
          <key>col</key><integer>17</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25469,12 +25469,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2243</integer>
+           <key>line</key><integer>2260</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2243</integer>
+           <key>line</key><integer>2260</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25482,12 +25482,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2244</integer>
+           <key>line</key><integer>2261</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2244</integer>
+           <key>line</key><integer>2261</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25499,7 +25499,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2244</integer>
+      <key>line</key><integer>2261</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25521,7 +25521,7 @@
   <key>issue_hash_function_offset</key><string>2</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2244</integer>
+   <key>line</key><integer>2261</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -25529,11 +25529,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2239</integer>
-    <integer>2241</integer>
-    <integer>2242</integer>
-    <integer>2243</integer>
-    <integer>2244</integer>
+    <integer>2256</integer>
+    <integer>2258</integer>
+    <integer>2259</integer>
+    <integer>2260</integer>
+    <integer>2261</integer>
    </array>
   </dict>
   </dict>
@@ -25544,7 +25544,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2261</integer>
+      <key>line</key><integer>2278</integer>
       <key>col</key><integer>20</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25552,12 +25552,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2261</integer>
+         <key>line</key><integer>2278</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2261</integer>
+         <key>line</key><integer>2278</integer>
          <key>col</key><integer>70</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25577,12 +25577,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2261</integer>
+           <key>line</key><integer>2278</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2261</integer>
+           <key>line</key><integer>2278</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25590,12 +25590,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2262</integer>
+           <key>line</key><integer>2279</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2262</integer>
+           <key>line</key><integer>2279</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25607,7 +25607,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2262</integer>
+      <key>line</key><integer>2279</integer>
       <key>col</key><integer>34</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25615,24 +25615,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2262</integer>
+         <key>line</key><integer>2279</integer>
          <key>col</key><integer>34</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2262</integer>
+         <key>line</key><integer>2279</integer>
          <key>col</key><integer>62</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2262</integer>
+         <key>line</key><integer>2279</integer>
          <key>col</key><integer>48</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2262</integer>
+         <key>line</key><integer>2279</integer>
          <key>col</key><integer>61</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25648,7 +25648,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2262</integer>
+      <key>line</key><integer>2279</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25656,12 +25656,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2262</integer>
+         <key>line</key><integer>2279</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2262</integer>
+         <key>line</key><integer>2279</integer>
          <key>col</key><integer>18</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25681,12 +25681,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2262</integer>
+           <key>line</key><integer>2279</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2262</integer>
+           <key>line</key><integer>2279</integer>
            <key>col</key><integer>12</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25694,12 +25694,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2263</integer>
+           <key>line</key><integer>2280</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2263</integer>
+           <key>line</key><integer>2280</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25711,7 +25711,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2263</integer>
+      <key>line</key><integer>2280</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25719,24 +25719,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2263</integer>
+         <key>line</key><integer>2280</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2263</integer>
+         <key>line</key><integer>2280</integer>
          <key>col</key><integer>17</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2263</integer>
+         <key>line</key><integer>2280</integer>
          <key>col</key><integer>12</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2263</integer>
+         <key>line</key><integer>2280</integer>
          <key>col</key><integer>16</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25756,12 +25756,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2263</integer>
+           <key>line</key><integer>2280</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2263</integer>
+           <key>line</key><integer>2280</integer>
            <key>col</key><integer>10</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25769,12 +25769,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2264</integer>
+           <key>line</key><integer>2281</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2264</integer>
+           <key>line</key><integer>2281</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25786,7 +25786,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2264</integer>
+      <key>line</key><integer>2281</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25808,7 +25808,7 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2264</integer>
+   <key>line</key><integer>2281</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -25816,11 +25816,11 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2260</integer>
-    <integer>2261</integer>
-    <integer>2262</integer>
-    <integer>2263</integer>
-    <integer>2264</integer>
+    <integer>2277</integer>
+    <integer>2278</integer>
+    <integer>2279</integer>
+    <integer>2280</integer>
+    <integer>2281</integer>
    </array>
   </dict>
   </dict>
@@ -25835,12 +25835,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2275</integer>
+           <key>line</key><integer>2292</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2275</integer>
+           <key>line</key><integer>2292</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25848,12 +25848,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2278</integer>
+           <key>line</key><integer>2295</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2278</integer>
+           <key>line</key><integer>2295</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25865,7 +25865,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2278</integer>
+      <key>line</key><integer>2295</integer>
       <key>col</key><integer>19</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25873,12 +25873,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2278</integer>
+         <key>line</key><integer>2295</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2278</integer>
+         <key>line</key><integer>2295</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25898,12 +25898,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2278</integer>
+           <key>line</key><integer>2295</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2278</integer>
+           <key>line</key><integer>2295</integer>
            <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25911,12 +25911,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2279</integer>
+           <key>line</key><integer>2296</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2279</integer>
+           <key>line</key><integer>2296</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25928,7 +25928,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2279</integer>
+      <key>line</key><integer>2296</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -25936,24 +25936,24 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2279</integer>
+         <key>line</key><integer>2296</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2279</integer>
+         <key>line</key><integer>2296</integer>
          <key>col</key><integer>27</integer>
          <key>file</key><integer>0</integer>
         </dict>
        </array>
        <array>
         <dict>
-         <key>line</key><integer>2279</integer>
+         <key>line</key><integer>2296</integer>
          <key>col</key><integer>17</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2279</integer>
+         <key>line</key><integer>2296</integer>
          <key>col</key><integer>26</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -25973,12 +25973,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2279</integer>
+           <key>line</key><integer>2296</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2279</integer>
+           <key>line</key><integer>2296</integer>
            <key>col</key><integer>15</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -25986,12 +25986,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2280</integer>
+           <key>line</key><integer>2297</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2280</integer>
+           <key>line</key><integer>2297</integer>
            <key>col</key><integer>1</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26003,7 +26003,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2280</integer>
+      <key>line</key><integer>2297</integer>
       <key>col</key><integer>1</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -26025,7 +26025,7 @@
   <key>issue_hash_function_offset</key><string>6</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2280</integer>
+   <key>line</key><integer>2297</integer>
    <key>col</key><integer>1</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -26033,12 +26033,12 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2274</integer>
-    <integer>2275</integer>
-    <integer>2276</integer>
-    <integer>2278</integer>
-    <integer>2279</integer>
-    <integer>2280</integer>
+    <integer>2291</integer>
+    <integer>2292</integer>
+    <integer>2293</integer>
+    <integer>2295</integer>
+    <integer>2296</integer>
+    <integer>2297</integer>
    </array>
   </dict>
   </dict>
@@ -26053,12 +26053,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2329</integer>
+           <key>line</key><integer>2346</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2329</integer>
+           <key>line</key><integer>2346</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26066,12 +26066,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2330</integer>
+           <key>line</key><integer>2347</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2330</integer>
+           <key>line</key><integer>2347</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26083,7 +26083,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2330</integer>
+      <key>line</key><integer>2347</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -26091,12 +26091,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2330</integer>
+         <key>line</key><integer>2347</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2330</integer>
+         <key>line</key><integer>2347</integer>
          <key>col</key><integer>19</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -26116,12 +26116,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2330</integer>
+           <key>line</key><integer>2347</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2330</integer>
+           <key>line</key><integer>2347</integer>
            <key>col</key><integer>13</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26129,12 +26129,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2331</integer>
+           <key>line</key><integer>2348</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2331</integer>
+           <key>line</key><integer>2348</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26146,7 +26146,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2331</integer>
+      <key>line</key><integer>2348</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -26154,12 +26154,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2331</integer>
+         <key>line</key><integer>2348</integer>
          <key>col</key><integer>13</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2331</integer>
+         <key>line</key><integer>2348</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -26183,7 +26183,7 @@
   <key>issue_hash_function_offset</key><string>4</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2331</integer>
+   <key>line</key><integer>2348</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -26191,10 +26191,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2327</integer>
-    <integer>2329</integer>
-    <integer>2330</integer>
-    <integer>2331</integer>
+    <integer>2344</integer>
+    <integer>2346</integer>
+    <integer>2347</integer>
+    <integer>2348</integer>
    </array>
   </dict>
   </dict>
@@ -26209,12 +26209,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2336</integer>
+           <key>line</key><integer>2353</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2336</integer>
+           <key>line</key><integer>2353</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26222,12 +26222,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2337</integer>
+           <key>line</key><integer>2354</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2337</integer>
+           <key>line</key><integer>2354</integer>
            <key>col</key><integer>14</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26239,7 +26239,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2337</integer>
+      <key>line</key><integer>2354</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -26247,12 +26247,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2337</integer>
+         <key>line</key><integer>2354</integer>
          <key>col</key><integer>3</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2337</integer>
+         <key>line</key><integer>2354</integer>
          <key>col</key><integer>20</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -26272,12 +26272,12 @@
         <key>start</key>
          <array>
           <dict>
-           <key>line</key><integer>2337</integer>
+           <key>line</key><integer>2354</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2337</integer>
+           <key>line</key><integer>2354</integer>
            <key>col</key><integer>14</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26285,12 +26285,12 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>2338</integer>
+           <key>line</key><integer>2355</integer>
            <key>col</key><integer>3</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>2338</integer>
+           <key>line</key><integer>2355</integer>
            <key>col</key><integer>11</integer>
            <key>file</key><integer>0</integer>
           </dict>
@@ -26302,7 +26302,7 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>2338</integer>
+      <key>line</key><integer>2355</integer>
       <key>col</key><integer>3</integer>
       <key>file</key><integer>0</integer>
      </dict>
@@ -26310,12 +26310,12 @@
      <array>
        <array>
         <dict>
-         <key>line</key><integer>2338</integer>
+         <key>line</key><integer>2355</integer>
          <key>col</key><integer>13</integer>
          <key>file</key><integer>0</integer>
         </dict>
         <dict>
-         <key>line</key><integer>2338</integer>
+         <key>line</key><integer>2355</integer>
          <key>col</key><integer>15</integer>
          <key>file</key><integer>0</integer>
         </dict>
@@ -26339,7 +26339,7 @@
   <key>issue_hash_function_offset</key><string>4</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>2338</integer>
+   <key>line</key><integer>2355</integer>
    <key>col</key><integer>3</integer>
    <key>file</key><integer>0</integer>
   </dict>
@@ -26347,10 +26347,10 @@
   <dict>
    <key>0</key>
    <array>
-    <integer>2334</integer>
-    <integer>2336</integer>
-    <integer>2337</integer>
-    <integer>2338</integer>
+    <integer>2351</integer>
+    <integer>2353</integer>
+    <integer>2354</integer>
+    <integer>2355</integer>
    </array>
   </dict>
   </dict>
diff --git a/clang/test/Analysis/retain-release.m b/clang/test/Analysis/retain-release.m
index 0307395258db105..2009a4b49deffd2 100644
--- a/clang/test/Analysis/retain-release.m
+++ b/clang/test/Analysis/retain-release.m
@@ -1251,6 +1251,7 @@ void rdar11282706(pthread_key_t key) {
 typedef struct __CVBuffer *CVBufferRef;
 typedef CVBufferRef CVImageBufferRef;
 typedef CVImageBufferRef CVPixelBufferRef;
+typedef CVBufferRef CMTaggedBufferGroupRef;
 typedef void (*CVPixelBufferReleaseBytesCallback)( void *releaseRefCon, const void *baseAddress );
 
 extern CVReturn CVPixelBufferCreateWithBytes(CFAllocatorRef allocator,
@@ -1398,6 +1399,16 @@ typedef void (*VTCompressionOutputCallback)(
     void * _Nullable sourceFrameRefCon,
     VTEncodeInfoFlags * _Nullable infoFlagsOut);
 
+extern OSStatus
+VTCompressionSessionEncodeMultiImageFrame(
+    _Nonnull VTCompressionSessionRef session,
+    _Nonnull CVImageBufferRef imageBuffer,
+    CMTime presentationTimeStamp,
+    CMTime duration,
+    _Nullable CFDictionaryRef frameProperties,
+    void * _Nullable sourceFrameRefCon,
+    VTEncodeInfoFlags * _Nullable infoFlagsOut);
+
 OSStatus test_VTCompressionSessionCreateAndEncode_CallbackReleases(
     _Nullable CFAllocatorRef allocator,
     int32_t width,
@@ -1417,6 +1428,8 @@ OSStatus test_VTCompressionSessionCreateAndEncode_CallbackReleases(
   // The outputCallback is passed both contexts and so can release either.
   NSNumber *contextForCreate = [[NSNumber alloc] initWithInt:5]; // no-warning
   NSNumber *contextForEncode = [[NSNumber alloc] initWithInt:6]; // no-warning
+  NSNumber *contextForEncodeMultiFrame = [[NSNumber alloc] initWithInt:7]; // no-warning
+
 
   VTCompressionSessionRef session = 0;
   OSStatus status = VTCompressionSessionCreate(allocator,
@@ -1431,6 +1444,10 @@ OSStatus test_VTCompressionSessionCreateAndEncode_CallbackReleases(
       presentationTimeStamp, duration, frameProperties, contextForEncode,
       &encodeInfoFlags);
 
+  status = VTCompressionSessionEncodeMultiImageFrame(session, imageBuffer,
+      presentationTimeStamp, duration, frameProperties, contextForEncodeMultiFrame,
+      &encodeInfoFlags);
+
   return status;
 }
 

>From 52b3bff3ac55f862a8caadf8e5b1400e90cf3935 Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Thu, 14 Sep 2023 09:02:58 +0800
Subject: [PATCH 03/86] [Coroutine][DebugInfo] Remove the memory attributes on
 coro-async-declaration.ll (NFC) (#66088)

According to @drodriguez's reminder in
https://github.com/apple/llvm-project/pull/7168#issuecomment-1710607896,
`memory` breaks the backport to the apple branch.

And this is irrelevant to that test. Delete to get better a test case.
---
 .../Coroutines/coro-async-declaration.ll      | 19 +++----------------
 1 file changed, 3 insertions(+), 16 deletions(-)

diff --git a/llvm/test/Transforms/Coroutines/coro-async-declaration.ll b/llvm/test/Transforms/Coroutines/coro-async-declaration.ll
index 3cac3c167df3b09..aee6aa4f78a8326 100644
--- a/llvm/test/Transforms/Coroutines/coro-async-declaration.ll
+++ b/llvm/test/Transforms/Coroutines/coro-async-declaration.ll
@@ -28,7 +28,6 @@ entry:
   %4 = load i32, ptr getelementptr inbounds (%swift.async_func_pointer, ptr @"$s3foo1fyyYaFTu", i32 0, i32 1), align 8, !dbg !10
   %5 = zext i32 %4 to i64, !dbg !10
   %6 = call swiftcc ptr @swift_task_alloc(i64 %5), !dbg !10
-  call void @llvm.lifetime.start.p0(i64 -1, ptr %6), !dbg !10
   %7 = load ptr, ptr %1, align 8, !dbg !10
   %8 = getelementptr inbounds <{ ptr, ptr }>, ptr %6, i32 0, i32 0, !dbg !10
   store ptr %7, ptr %8, align 8, !dbg !10
@@ -40,7 +39,6 @@ entry:
   %13 = call ptr @__swift_async_resume_project_context(ptr %12), !dbg !10
   store ptr %13, ptr %1, align 8, !dbg !10
   call swiftcc void @swift_task_dealloc(ptr %6), !dbg !10
-  call void @llvm.lifetime.end.p0(i64 -1, ptr %6), !dbg !10
   %14 = load ptr, ptr %1, align 8, !dbg !11
   %15 = getelementptr inbounds <{ ptr, ptr }>, ptr %14, i32 0, i32 1, !dbg !11
   %16 = load ptr, ptr %15, align 8, !dbg !11
@@ -52,9 +50,6 @@ entry:
 ; Function Attrs: nounwind
 declare token @llvm.coro.id.async(i32, i32, i32, ptr) #0
 
-; Function Attrs: cold noreturn nounwind memory(inaccessiblemem: write)
-declare void @llvm.trap() #1
-
 ; Function Attrs: nounwind
 declare ptr @llvm.coro.begin(token, ptr writeonly) #0
 
@@ -62,11 +57,8 @@ declare swifttailcc void @"$s3foo1fyyYaF"(ptr swiftasync)
 
 declare swiftcc ptr @swift_task_alloc(i64)
 
-; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
-declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #2
-
 ; Function Attrs: nomerge nounwind
-declare ptr @llvm.coro.async.resume() #3
+declare ptr @llvm.coro.async.resume() #1
 
 define linkonce_odr hidden ptr @__swift_async_resume_project_context(ptr %0) !dbg !12 {
 entry:
@@ -86,13 +78,10 @@ entry:
 }
 
 ; Function Attrs: nomerge nounwind
-declare { ptr } @llvm.coro.suspend.async.sl_p0s(i32, ptr, ptr, ...) #3
+declare { ptr } @llvm.coro.suspend.async.sl_p0s(i32, ptr, ptr, ...) #1
 
 declare swiftcc void @swift_task_dealloc(ptr)
 
-; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
-declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2
-
 define internal swifttailcc void @"$s3foo3FooO3baryyYaF.0.1"(ptr %0, ptr %1) !dbg !17 {
 entry:
   musttail call swifttailcc void %0(ptr swiftasync %1), !dbg !18
@@ -103,9 +92,7 @@ entry:
 declare i1 @llvm.coro.end.async(ptr, i1, ...) #0
 
 attributes #0 = { nounwind }
-attributes #1 = { cold noreturn nounwind memory(inaccessiblemem: write) }
-attributes #2 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
-attributes #3 = { nomerge nounwind }
+attributes #1 = { nomerge nounwind }
 
 !llvm.dbg.cu = !{!0}
 !llvm.module.flags = !{!3, !4}

>From ea4ea303b9ccedd7dcc1cb4277007ffe426c86cb Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Wed, 13 Sep 2023 19:08:22 -0700
Subject: [PATCH 04/86] [ELF][test] Test the order of PPC64 .got, .toc, and
 .branch_lt

---
 lld/test/ELF/ppc64-section-layout.s | 32 +++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
 create mode 100644 lld/test/ELF/ppc64-section-layout.s

diff --git a/lld/test/ELF/ppc64-section-layout.s b/lld/test/ELF/ppc64-section-layout.s
new file mode 100644
index 000000000000000..ae5843e1608a1f4
--- /dev/null
+++ b/lld/test/ELF/ppc64-section-layout.s
@@ -0,0 +1,32 @@
+# REQUIRES: ppc
+## Test PPC64 specific section layout. See also section-layout.s.
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le %p/Inputs/shared.s -o %t1.o
+# RUN: ld.lld -shared -soname=t1.so %t1.o -o %t1.so
+# RUN: ld.lld %t.o %t1.so -o %t
+# RUN: llvm-readelf -S %t | FileCheck %s
+
+# CHECK:      .text
+# CHECK-NEXT: .tdata
+# CHECK-NEXT: .tbss
+# CHECK-NEXT: .dynamic
+# CHECK-NEXT: .got
+# CHECK-NEXT: .toc
+# CHECK-NEXT: .data
+# CHECK-NEXT: .branch_lt
+
+.globl _start
+_start:
+  addis 3, 2, bar2 at got@ha
+  ld    3, bar2 at got@l(3)
+  addis 5, 2, .Lbar at toc@ha
+  ld    5, .Lbar at toc@l(5)
+
+.section .toc,"aw", at progbits
+.Lbar:
+  .tc bar[TC], bar
+
+.section .tdata,"awT", at progbits; .space 1
+.section .tbss,"awT", at nobits; .space 1
+.section .data,"aw", at progbits; .space 1

>From fea46c2b547ae956e3ed732c75bd7b2403fa02d9 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Wed, 13 Sep 2023 19:15:42 -0700
Subject: [PATCH 05/86] [ELF][PPC64] Use the regular placement for .branch_lt

The currently rule places .branch_lt after .data, which does not make
sense. The original contributor probably wanted to place .branch_lt
before .got/.toc, but failed to notice that .got/.toc are RELRO and
placed earlier.

Remove the special case so that .branch_lt is actually closer to .toc,
alleviating the distance issue.
---
 lld/ELF/Writer.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 255f8c334b969bc..d4c667c91ab751a 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -941,12 +941,10 @@ static unsigned getSectionRank(const OutputSection &osec) {
     // their coverage by a single signed 16-bit offset from the TOC base
     // pointer.
     StringRef name = osec.name;
-    if (name == ".branch_lt")
+    if (name == ".got")
       rank |= 1;
-    else if (name == ".got")
-      rank |= 2;
     else if (name == ".toc")
-      rank |= 4;
+      rank |= 2;
   }
 
   if (config->emachine == EM_MIPS) {

>From b4952d8ae7efa63d90d2997bc2a450b49a9c421f Mon Sep 17 00:00:00 2001
From: Allen <zhongyunde at huawei.com>
Date: Thu, 14 Sep 2023 10:35:07 +0800
Subject: [PATCH 06/86] [ARM][ISel] Fix crash of ISD::FMINNUM/FMAXNUM (#65849)

The instruction of ISD::FMINNUM/FMAXNUM should be legal if HasFPARMv8 &&
HasNEON.
For the combination of armv7+fp-armv8, armv7 imply the feature HasNEON
on, and fp-armv8 matchs the feature HasFPARMv8, so it is legal

Fixes https://github.com/llvm/llvm-project/issues/65820
---
 llvm/lib/Target/ARM/ARMInstrNEON.td           |  16 +-
 .../CodeGen/ARM/minnum-maxnum-intrinsics.ll   | 468 +++++++++---------
 2 files changed, 234 insertions(+), 250 deletions(-)

diff --git a/llvm/lib/Target/ARM/ARMInstrNEON.td b/llvm/lib/Target/ARM/ARMInstrNEON.td
index 9cc083a220c0154..f31e1e9f97892fa 100644
--- a/llvm/lib/Target/ARM/ARMInstrNEON.td
+++ b/llvm/lib/Target/ARM/ARMInstrNEON.td
@@ -5711,19 +5711,19 @@ let PostEncoderMethod = "NEONThumb2V8PostEncoder", DecoderNamespace = "v8NEON" i
   def NEON_VMAXNMNDf  : N3VDIntnp<0b00110, 0b00, 0b1111, 0, 1,
                                   N3RegFrm, NoItinerary, "vmaxnm", "f32",
                                   v2f32, v2f32, fmaxnum, 1>,
-                                  Requires<[HasV8, HasNEON]>;
+                                  Requires<[HasFPARMv8, HasNEON]>;
   def NEON_VMAXNMNQf  : N3VQIntnp<0b00110, 0b00, 0b1111, 1, 1,
                                   N3RegFrm, NoItinerary, "vmaxnm", "f32",
                                   v4f32, v4f32, fmaxnum, 1>,
-                                  Requires<[HasV8, HasNEON]>;
+                                  Requires<[HasFPARMv8, HasNEON]>;
   def NEON_VMAXNMNDh  : N3VDIntnp<0b00110, 0b01, 0b1111, 0, 1,
                                   N3RegFrm, NoItinerary, "vmaxnm", "f16",
                                   v4f16, v4f16, fmaxnum, 1>,
-                                  Requires<[HasV8, HasNEON, HasFullFP16]>;
+                                  Requires<[HasFPARMv8, HasNEON, HasFullFP16]>;
   def NEON_VMAXNMNQh  : N3VQIntnp<0b00110, 0b01, 0b1111, 1, 1,
                                   N3RegFrm, NoItinerary, "vmaxnm", "f16",
                                   v8f16, v8f16, fmaxnum, 1>,
-                                  Requires<[HasV8, HasNEON, HasFullFP16]>;
+                                  Requires<[HasFPARMv8, HasNEON, HasFullFP16]>;
 }
 
 //   VMIN     : Vector Minimum
@@ -5753,19 +5753,19 @@ let PostEncoderMethod = "NEONThumb2V8PostEncoder", DecoderNamespace = "v8NEON" i
   def NEON_VMINNMNDf  : N3VDIntnp<0b00110, 0b10, 0b1111, 0, 1,
                                   N3RegFrm, NoItinerary, "vminnm", "f32",
                                   v2f32, v2f32, fminnum, 1>,
-                                  Requires<[HasV8, HasNEON]>;
+                                  Requires<[HasFPARMv8, HasNEON]>;
   def NEON_VMINNMNQf  : N3VQIntnp<0b00110, 0b10, 0b1111, 1, 1,
                                   N3RegFrm, NoItinerary, "vminnm", "f32",
                                   v4f32, v4f32, fminnum, 1>,
-                                  Requires<[HasV8, HasNEON]>;
+                                  Requires<[HasFPARMv8, HasNEON]>;
   def NEON_VMINNMNDh  : N3VDIntnp<0b00110, 0b11, 0b1111, 0, 1,
                                   N3RegFrm, NoItinerary, "vminnm", "f16",
                                   v4f16, v4f16, fminnum, 1>,
-                                  Requires<[HasV8, HasNEON, HasFullFP16]>;
+                                  Requires<[HasFPARMv8, HasNEON, HasFullFP16]>;
   def NEON_VMINNMNQh  : N3VQIntnp<0b00110, 0b11, 0b1111, 1, 1,
                                   N3RegFrm, NoItinerary, "vminnm", "f16",
                                   v8f16, v8f16, fminnum, 1>,
-                                  Requires<[HasV8, HasNEON, HasFullFP16]>;
+                                  Requires<[HasFPARMv8, HasNEON, HasFullFP16]>;
 }
 
 // Vector Pairwise Operations.
diff --git a/llvm/test/CodeGen/ARM/minnum-maxnum-intrinsics.ll b/llvm/test/CodeGen/ARM/minnum-maxnum-intrinsics.ll
index e17075d067c26bd..be741f536ac757f 100644
--- a/llvm/test/CodeGen/ARM/minnum-maxnum-intrinsics.ll
+++ b/llvm/test/CodeGen/ARM/minnum-maxnum-intrinsics.ll
@@ -1,6 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc -mtriple=armv7 -mattr=+neon %s -o - | FileCheck %s --check-prefix=ARMV7
-; RUN: llc -mtriple=armv8.2-a -mattr=+fp-armv8 %s -o - | FileCheck %s --check-prefix=ARMV8
+; RUN: llc -mtriple=armv7 -mattr=+fp-armv8 %s -o - | FileCheck %s --check-prefix=ARMV8
+; RUN: llc -mtriple=armv8.2a -mattr=+fp-armv8 %s -o - | FileCheck %s --check-prefix=ARMV8
 ; RUN: llc -mtriple=armv8.1m-none-none-eabi -mattr=+mve.fp,+fp64 %s -o - | FileCheck %s --check-prefix=ARMV8M
 
 declare float @llvm.minnum.f32(float, float)
@@ -29,7 +30,7 @@ define float @fminnum32_intrinsic(float %x, float %y) {
 ; ARMV8-NEXT:    vmov s2, r0
 ; ARMV8-NEXT:    vminnm.f32 s0, s2, s0
 ; ARMV8-NEXT:    vmov r0, s0
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fminnum32_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -59,7 +60,7 @@ define float @fminnum32_nsz_intrinsic(float %x, float %y) {
 ; ARMV8-NEXT:    vmov s2, r0
 ; ARMV8-NEXT:    vminnm.f32 s0, s2, s0
 ; ARMV8-NEXT:    vmov r0, s0
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fminnum32_nsz_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -89,7 +90,7 @@ define float @fminnum32_non_zero_intrinsic(float %x) {
 ; ARMV8-NEXT:    vmov s2, r0
 ; ARMV8-NEXT:    vminnm.f32 s0, s2, s0
 ; ARMV8-NEXT:    vmov r0, s0
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fminnum32_non_zero_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -119,7 +120,7 @@ define float @fmaxnum32_intrinsic(float %x, float %y) {
 ; ARMV8-NEXT:    vmov s2, r0
 ; ARMV8-NEXT:    vmaxnm.f32 s0, s2, s0
 ; ARMV8-NEXT:    vmov r0, s0
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnum32_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -149,7 +150,7 @@ define float @fmaxnum32_nsz_intrinsic(float %x, float %y) {
 ; ARMV8-NEXT:    vmov s2, r0
 ; ARMV8-NEXT:    vmaxnm.f32 s0, s2, s0
 ; ARMV8-NEXT:    vmov r0, s0
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnum32_nsz_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -183,7 +184,7 @@ define float @fmaxnum32_zero_intrinsic(float %x) {
 ; ARMV8-NEXT:    vmov s2, r0
 ; ARMV8-NEXT:    vmaxnm.f32 s0, s2, s0
 ; ARMV8-NEXT:    vmov r0, s0
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ; ARMV8-NEXT:    .p2align 2
 ; ARMV8-NEXT:  @ %bb.1:
 ; ARMV8-NEXT:  .LCPI5_0:
@@ -221,7 +222,7 @@ define float @fmaxnum32_non_zero_intrinsic(float %x) {
 ; ARMV8-NEXT:    vmov s2, r0
 ; ARMV8-NEXT:    vmaxnm.f32 s0, s2, s0
 ; ARMV8-NEXT:    vmov r0, s0
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnum32_non_zero_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -251,7 +252,7 @@ define double @fminnum64_intrinsic(double %x, double %y) {
 ; ARMV8-NEXT:    vmov d17, r0, r1
 ; ARMV8-NEXT:    vminnm.f64 d16, d17, d16
 ; ARMV8-NEXT:    vmov r0, r1, d16
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fminnum64_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -281,7 +282,7 @@ define double @fminnum64_nsz_intrinsic(double %x, double %y) {
 ; ARMV8-NEXT:    vmov d17, r0, r1
 ; ARMV8-NEXT:    vminnm.f64 d16, d17, d16
 ; ARMV8-NEXT:    vmov r0, r1, d16
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fminnum64_nsz_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -316,7 +317,7 @@ define double @fminnum64_zero_intrinsic(double %x) {
 ; ARMV8-NEXT:    vmov d17, r0, r1
 ; ARMV8-NEXT:    vminnm.f64 d16, d17, d16
 ; ARMV8-NEXT:    vmov r0, r1, d16
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ; ARMV8-NEXT:    .p2align 3
 ; ARMV8-NEXT:  @ %bb.1:
 ; ARMV8-NEXT:  .LCPI9_0:
@@ -356,7 +357,7 @@ define double @fminnum64_non_zero_intrinsic(double %x) {
 ; ARMV8-NEXT:    vmov d17, r0, r1
 ; ARMV8-NEXT:    vminnm.f64 d16, d17, d16
 ; ARMV8-NEXT:    vmov r0, r1, d16
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fminnum64_non_zero_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -386,7 +387,7 @@ define double at fmaxnum64_intrinsic(double %x, double %y) {
 ; ARMV8-NEXT:    vmov d17, r0, r1
 ; ARMV8-NEXT:    vmaxnm.f64 d16, d17, d16
 ; ARMV8-NEXT:    vmov r0, r1, d16
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnum64_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -416,7 +417,7 @@ define double at fmaxnum64_nsz_intrinsic(double %x, double %y) {
 ; ARMV8-NEXT:    vmov d17, r0, r1
 ; ARMV8-NEXT:    vmaxnm.f64 d16, d17, d16
 ; ARMV8-NEXT:    vmov r0, r1, d16
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnum64_nsz_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -442,16 +443,11 @@ define double @fmaxnum64_zero_intrinsic(double %x) {
 ;
 ; ARMV8-LABEL: fmaxnum64_zero_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vldr d16, .LCPI13_0
+; ARMV8-NEXT:    vmov.i32 d16, #0x0
 ; ARMV8-NEXT:    vmov d17, r0, r1
 ; ARMV8-NEXT:    vmaxnm.f64 d16, d17, d16
 ; ARMV8-NEXT:    vmov r0, r1, d16
-; ARMV8-NEXT:    mov pc, lr
-; ARMV8-NEXT:    .p2align 3
-; ARMV8-NEXT:  @ %bb.1:
-; ARMV8-NEXT:  .LCPI13_0:
-; ARMV8-NEXT:    .long 0 @ double 0
-; ARMV8-NEXT:    .long 0
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnum64_zero_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -486,7 +482,7 @@ define double @fmaxnum64_non_zero_intrinsic(double %x) {
 ; ARMV8-NEXT:    vmov d17, r0, r1
 ; ARMV8-NEXT:    vmaxnm.f64 d16, d17, d16
 ; ARMV8-NEXT:    vmov r0, r1, d16
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnum64_non_zero_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -524,23 +520,14 @@ define <4 x float> @fminnumv432_intrinsic(<4 x float> %x, <4 x float> %y) {
 ;
 ; ARMV8-LABEL: fminnumv432_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vldr s0, [sp, #4]
-; ARMV8-NEXT:    vmov s12, r1
-; ARMV8-NEXT:    vldr s2, [sp, #8]
-; ARMV8-NEXT:    vmov s10, r2
-; ARMV8-NEXT:    vminnm.f32 s0, s12, s0
-; ARMV8-NEXT:    vldr s4, [sp, #12]
-; ARMV8-NEXT:    vldr s6, [sp]
-; ARMV8-NEXT:    vmov s14, r0
-; ARMV8-NEXT:    vmov r1, s0
-; ARMV8-NEXT:    vminnm.f32 s0, s10, s2
-; ARMV8-NEXT:    vmov s8, r3
-; ARMV8-NEXT:    vminnm.f32 s6, s14, s6
-; ARMV8-NEXT:    vmov r2, s0
-; ARMV8-NEXT:    vminnm.f32 s0, s8, s4
-; ARMV8-NEXT:    vmov r0, s6
-; ARMV8-NEXT:    vmov r3, s0
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    vmov d17, r2, r3
+; ARMV8-NEXT:    vmov d16, r0, r1
+; ARMV8-NEXT:    mov r0, sp
+; ARMV8-NEXT:    vld1.64 {d18, d19}, [r0]
+; ARMV8-NEXT:    vminnm.f32 q8, q8, q9
+; ARMV8-NEXT:    vmov r0, r1, d16
+; ARMV8-NEXT:    vmov r2, r3, d17
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fminnumv432_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -570,23 +557,14 @@ define <4 x float> @fminnumv432_nsz_intrinsic(<4 x float> %x, <4 x float> %y) {
 ;
 ; ARMV8-LABEL: fminnumv432_nsz_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vldr s0, [sp, #4]
-; ARMV8-NEXT:    vmov s12, r1
-; ARMV8-NEXT:    vldr s2, [sp, #8]
-; ARMV8-NEXT:    vmov s10, r2
-; ARMV8-NEXT:    vminnm.f32 s0, s12, s0
-; ARMV8-NEXT:    vldr s4, [sp, #12]
-; ARMV8-NEXT:    vldr s6, [sp]
-; ARMV8-NEXT:    vmov s14, r0
-; ARMV8-NEXT:    vmov r1, s0
-; ARMV8-NEXT:    vminnm.f32 s0, s10, s2
-; ARMV8-NEXT:    vmov s8, r3
-; ARMV8-NEXT:    vminnm.f32 s6, s14, s6
-; ARMV8-NEXT:    vmov r2, s0
-; ARMV8-NEXT:    vminnm.f32 s0, s8, s4
-; ARMV8-NEXT:    vmov r0, s6
-; ARMV8-NEXT:    vmov r3, s0
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    vmov d17, r2, r3
+; ARMV8-NEXT:    vmov d16, r0, r1
+; ARMV8-NEXT:    mov r0, sp
+; ARMV8-NEXT:    vld1.64 {d18, d19}, [r0]
+; ARMV8-NEXT:    vminnm.f32 q8, q8, q9
+; ARMV8-NEXT:    vmov r0, r1, d16
+; ARMV8-NEXT:    vmov r2, r3, d17
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fminnumv432_nsz_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -615,20 +593,13 @@ define <4 x float> @fminnumv432_non_zero_intrinsic(<4 x float> %x) {
 ;
 ; ARMV8-LABEL: fminnumv432_non_zero_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vmov.f32 s0, #-1.000000e+00
-; ARMV8-NEXT:    vmov s4, r2
-; ARMV8-NEXT:    vmov s6, r1
-; ARMV8-NEXT:    vminnm.f32 s4, s4, s0
-; ARMV8-NEXT:    vmov s8, r0
-; ARMV8-NEXT:    vminnm.f32 s6, s6, s0
-; ARMV8-NEXT:    vmov s2, r3
-; ARMV8-NEXT:    vminnm.f32 s8, s8, s0
-; ARMV8-NEXT:    vminnm.f32 s0, s2, s0
-; ARMV8-NEXT:    vmov r0, s8
-; ARMV8-NEXT:    vmov r1, s6
-; ARMV8-NEXT:    vmov r2, s4
-; ARMV8-NEXT:    vmov r3, s0
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    vmov d17, r2, r3
+; ARMV8-NEXT:    vmov d16, r0, r1
+; ARMV8-NEXT:    vmov.f32 q9, #-1.000000e+00
+; ARMV8-NEXT:    vminnm.f32 q8, q8, q9
+; ARMV8-NEXT:    vmov r0, r1, d16
+; ARMV8-NEXT:    vmov r2, r3, d17
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fminnumv432_non_zero_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -674,25 +645,21 @@ define <4 x float> @fminnumv432_one_zero_intrinsic(<4 x float> %x) {
 ;
 ; ARMV8-LABEL: fminnumv432_one_zero_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vldr s0, .LCPI18_0
-; ARMV8-NEXT:    vmov s8, r1
-; ARMV8-NEXT:    vmov.f32 s2, #-1.000000e+00
-; ARMV8-NEXT:    vminnm.f32 s0, s8, s0
-; ARMV8-NEXT:    vmov s6, r2
-; ARMV8-NEXT:    vmov s10, r0
-; ARMV8-NEXT:    vmov r1, s0
-; ARMV8-NEXT:    vminnm.f32 s0, s6, s2
-; ARMV8-NEXT:    vmov s4, r3
-; ARMV8-NEXT:    vminnm.f32 s10, s10, s2
-; ARMV8-NEXT:    vmov r2, s0
-; ARMV8-NEXT:    vminnm.f32 s0, s4, s2
-; ARMV8-NEXT:    vmov r0, s10
-; ARMV8-NEXT:    vmov r3, s0
-; ARMV8-NEXT:    mov pc, lr
-; ARMV8-NEXT:    .p2align 2
+; ARMV8-NEXT:    vmov d17, r2, r3
+; ARMV8-NEXT:    vmov d16, r0, r1
+; ARMV8-NEXT:    adr r0, .LCPI18_0
+; ARMV8-NEXT:    vld1.64 {d18, d19}, [r0:128]
+; ARMV8-NEXT:    vminnm.f32 q8, q8, q9
+; ARMV8-NEXT:    vmov r0, r1, d16
+; ARMV8-NEXT:    vmov r2, r3, d17
+; ARMV8-NEXT:    bx lr
+; ARMV8-NEXT:    .p2align 4
 ; ARMV8-NEXT:  @ %bb.1:
 ; ARMV8-NEXT:  .LCPI18_0:
+; ARMV8-NEXT:    .long 0xbf800000 @ float -1
 ; ARMV8-NEXT:    .long 0x00000000 @ float 0
+; ARMV8-NEXT:    .long 0xbf800000 @ float -1
+; ARMV8-NEXT:    .long 0xbf800000 @ float -1
 ;
 ; ARMV8M-LABEL: fminnumv432_one_zero_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -740,23 +707,14 @@ define <4 x float> @fmaxnumv432_intrinsic(<4 x float> %x, <4 x float> %y) {
 ;
 ; ARMV8-LABEL: fmaxnumv432_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vldr s0, [sp, #4]
-; ARMV8-NEXT:    vmov s12, r1
-; ARMV8-NEXT:    vldr s2, [sp, #8]
-; ARMV8-NEXT:    vmov s10, r2
-; ARMV8-NEXT:    vmaxnm.f32 s0, s12, s0
-; ARMV8-NEXT:    vldr s4, [sp, #12]
-; ARMV8-NEXT:    vldr s6, [sp]
-; ARMV8-NEXT:    vmov s14, r0
-; ARMV8-NEXT:    vmov r1, s0
-; ARMV8-NEXT:    vmaxnm.f32 s0, s10, s2
-; ARMV8-NEXT:    vmov s8, r3
-; ARMV8-NEXT:    vmaxnm.f32 s6, s14, s6
-; ARMV8-NEXT:    vmov r2, s0
-; ARMV8-NEXT:    vmaxnm.f32 s0, s8, s4
-; ARMV8-NEXT:    vmov r0, s6
-; ARMV8-NEXT:    vmov r3, s0
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    vmov d17, r2, r3
+; ARMV8-NEXT:    vmov d16, r0, r1
+; ARMV8-NEXT:    mov r0, sp
+; ARMV8-NEXT:    vld1.64 {d18, d19}, [r0]
+; ARMV8-NEXT:    vmaxnm.f32 q8, q8, q9
+; ARMV8-NEXT:    vmov r0, r1, d16
+; ARMV8-NEXT:    vmov r2, r3, d17
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnumv432_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -786,23 +744,14 @@ define <4 x float> @fmaxnumv432_nsz_intrinsic(<4 x float> %x, <4 x float> %y) {
 ;
 ; ARMV8-LABEL: fmaxnumv432_nsz_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vldr s0, [sp, #4]
-; ARMV8-NEXT:    vmov s12, r1
-; ARMV8-NEXT:    vldr s2, [sp, #8]
-; ARMV8-NEXT:    vmov s10, r2
-; ARMV8-NEXT:    vmaxnm.f32 s0, s12, s0
-; ARMV8-NEXT:    vldr s4, [sp, #12]
-; ARMV8-NEXT:    vldr s6, [sp]
-; ARMV8-NEXT:    vmov s14, r0
-; ARMV8-NEXT:    vmov r1, s0
-; ARMV8-NEXT:    vmaxnm.f32 s0, s10, s2
-; ARMV8-NEXT:    vmov s8, r3
-; ARMV8-NEXT:    vmaxnm.f32 s6, s14, s6
-; ARMV8-NEXT:    vmov r2, s0
-; ARMV8-NEXT:    vmaxnm.f32 s0, s8, s4
-; ARMV8-NEXT:    vmov r0, s6
-; ARMV8-NEXT:    vmov r3, s0
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    vmov d17, r2, r3
+; ARMV8-NEXT:    vmov d16, r0, r1
+; ARMV8-NEXT:    mov r0, sp
+; ARMV8-NEXT:    vld1.64 {d18, d19}, [r0]
+; ARMV8-NEXT:    vmaxnm.f32 q8, q8, q9
+; ARMV8-NEXT:    vmov r0, r1, d16
+; ARMV8-NEXT:    vmov r2, r3, d17
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnumv432_nsz_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -849,24 +798,13 @@ define <4 x float> @fmaxnumv432_zero_intrinsic(<4 x float> %x) {
 ;
 ; ARMV8-LABEL: fmaxnumv432_zero_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vldr s0, .LCPI21_0
-; ARMV8-NEXT:    vmov s4, r2
-; ARMV8-NEXT:    vmov s6, r1
-; ARMV8-NEXT:    vmov s8, r0
-; ARMV8-NEXT:    vmaxnm.f32 s6, s6, s0
-; ARMV8-NEXT:    vmov s2, r3
-; ARMV8-NEXT:    vmaxnm.f32 s8, s8, s0
-; ARMV8-NEXT:    vmaxnm.f32 s4, s4, s0
-; ARMV8-NEXT:    vmaxnm.f32 s0, s2, s0
-; ARMV8-NEXT:    vmov r0, s8
-; ARMV8-NEXT:    vmov r1, s6
-; ARMV8-NEXT:    vmov r2, s4
-; ARMV8-NEXT:    vmov r3, s0
-; ARMV8-NEXT:    mov pc, lr
-; ARMV8-NEXT:    .p2align 2
-; ARMV8-NEXT:  @ %bb.1:
-; ARMV8-NEXT:  .LCPI21_0:
-; ARMV8-NEXT:    .long 0x00000000 @ float 0
+; ARMV8-NEXT:    vmov d17, r2, r3
+; ARMV8-NEXT:    vmov d16, r0, r1
+; ARMV8-NEXT:    vmov.i32 q9, #0x0
+; ARMV8-NEXT:    vmaxnm.f32 q8, q8, q9
+; ARMV8-NEXT:    vmov r0, r1, d16
+; ARMV8-NEXT:    vmov r2, r3, d17
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnumv432_zero_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -912,24 +850,13 @@ define <4 x float> @fmaxnumv432_minus_zero_intrinsic(<4 x float> %x) {
 ;
 ; ARMV8-LABEL: fmaxnumv432_minus_zero_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vldr s0, .LCPI22_0
-; ARMV8-NEXT:    vmov s4, r2
-; ARMV8-NEXT:    vmov s6, r1
-; ARMV8-NEXT:    vmov s8, r0
-; ARMV8-NEXT:    vmaxnm.f32 s6, s6, s0
-; ARMV8-NEXT:    vmov s2, r3
-; ARMV8-NEXT:    vmaxnm.f32 s8, s8, s0
-; ARMV8-NEXT:    vmaxnm.f32 s4, s4, s0
-; ARMV8-NEXT:    vmaxnm.f32 s0, s2, s0
-; ARMV8-NEXT:    vmov r0, s8
-; ARMV8-NEXT:    vmov r1, s6
-; ARMV8-NEXT:    vmov r2, s4
-; ARMV8-NEXT:    vmov r3, s0
-; ARMV8-NEXT:    mov pc, lr
-; ARMV8-NEXT:    .p2align 2
-; ARMV8-NEXT:  @ %bb.1:
-; ARMV8-NEXT:  .LCPI22_0:
-; ARMV8-NEXT:    .long 0x80000000 @ float -0
+; ARMV8-NEXT:    vmov d17, r2, r3
+; ARMV8-NEXT:    vmov d16, r0, r1
+; ARMV8-NEXT:    vmov.i32 q9, #0x80000000
+; ARMV8-NEXT:    vmaxnm.f32 q8, q8, q9
+; ARMV8-NEXT:    vmov r0, r1, d16
+; ARMV8-NEXT:    vmov r2, r3, d17
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnumv432_minus_zero_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -957,20 +884,13 @@ define <4 x float> @fmaxnumv432_non_zero_intrinsic(<4 x float> %x) {
 ;
 ; ARMV8-LABEL: fmaxnumv432_non_zero_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vmov.f32 s0, #1.000000e+00
-; ARMV8-NEXT:    vmov s4, r2
-; ARMV8-NEXT:    vmov s6, r1
-; ARMV8-NEXT:    vmaxnm.f32 s4, s4, s0
-; ARMV8-NEXT:    vmov s8, r0
-; ARMV8-NEXT:    vmaxnm.f32 s6, s6, s0
-; ARMV8-NEXT:    vmov s2, r3
-; ARMV8-NEXT:    vmaxnm.f32 s8, s8, s0
-; ARMV8-NEXT:    vmaxnm.f32 s0, s2, s0
-; ARMV8-NEXT:    vmov r0, s8
-; ARMV8-NEXT:    vmov r1, s6
-; ARMV8-NEXT:    vmov r2, s4
-; ARMV8-NEXT:    vmov r3, s0
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    vmov d17, r2, r3
+; ARMV8-NEXT:    vmov d16, r0, r1
+; ARMV8-NEXT:    vmov.f32 q9, #1.000000e+00
+; ARMV8-NEXT:    vmaxnm.f32 q8, q8, q9
+; ARMV8-NEXT:    vmov r0, r1, d16
+; ARMV8-NEXT:    vmov r2, r3, d17
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnumv432_non_zero_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -1004,15 +924,19 @@ define <2 x double> @fminnumv264_intrinsic(<2 x double> %x, <2 x double> %y) {
 ;
 ; ARMV8-LABEL: fminnumv264_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vldr d16, [sp, #8]
-; ARMV8-NEXT:    vmov d18, r2, r3
-; ARMV8-NEXT:    vldr d17, [sp]
-; ARMV8-NEXT:    vmov d19, r0, r1
-; ARMV8-NEXT:    vminnm.f64 d16, d18, d16
-; ARMV8-NEXT:    vminnm.f64 d17, d19, d17
+; ARMV8-NEXT:    mov r12, sp
+; ARMV8-NEXT:    vld1.64 {d16, d17}, [r12]
+; ARMV8-NEXT:    vmov d18, r0, r1
+; ARMV8-NEXT:    vmov d19, r2, r3
+; ARMV8-NEXT:    vcmp.f64 d16, d18
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vcmp.f64 d17, d19
+; ARMV8-NEXT:    vselgt.f64 d18, d18, d16
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vmov r0, r1, d18
+; ARMV8-NEXT:    vselgt.f64 d16, d19, d17
 ; ARMV8-NEXT:    vmov r2, r3, d16
-; ARMV8-NEXT:    vmov r0, r1, d17
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fminnumv264_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -1052,15 +976,19 @@ define <2 x double> @fminnumv264_nsz_intrinsic(<2 x double> %x, <2 x double> %y)
 ;
 ; ARMV8-LABEL: fminnumv264_nsz_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vldr d16, [sp, #8]
-; ARMV8-NEXT:    vmov d18, r2, r3
-; ARMV8-NEXT:    vldr d17, [sp]
-; ARMV8-NEXT:    vmov d19, r0, r1
-; ARMV8-NEXT:    vminnm.f64 d16, d18, d16
-; ARMV8-NEXT:    vminnm.f64 d17, d19, d17
+; ARMV8-NEXT:    mov r12, sp
+; ARMV8-NEXT:    vld1.64 {d16, d17}, [r12]
+; ARMV8-NEXT:    vmov d18, r0, r1
+; ARMV8-NEXT:    vmov d19, r2, r3
+; ARMV8-NEXT:    vcmp.f64 d16, d18
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vcmp.f64 d17, d19
+; ARMV8-NEXT:    vselgt.f64 d18, d18, d16
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vmov r0, r1, d18
+; ARMV8-NEXT:    vselgt.f64 d16, d19, d17
 ; ARMV8-NEXT:    vmov r2, r3, d16
-; ARMV8-NEXT:    vmov r0, r1, d17
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fminnumv264_nsz_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -1100,14 +1028,18 @@ define <2 x double> @fminnumv264_non_zero_intrinsic(<2 x double> %x) {
 ;
 ; ARMV8-LABEL: fminnumv264_non_zero_intrinsic:
 ; ARMV8:       @ %bb.0:
+; ARMV8-NEXT:    vmov d17, r0, r1
 ; ARMV8-NEXT:    vmov.f64 d16, #1.000000e+00
-; ARMV8-NEXT:    vmov d18, r0, r1
-; ARMV8-NEXT:    vmov d17, r2, r3
-; ARMV8-NEXT:    vminnm.f64 d18, d18, d16
-; ARMV8-NEXT:    vminnm.f64 d16, d17, d16
-; ARMV8-NEXT:    vmov r0, r1, d18
+; ARMV8-NEXT:    vcmp.f64 d16, d17
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vmov d18, r2, r3
+; ARMV8-NEXT:    vcmp.f64 d16, d18
+; ARMV8-NEXT:    vselgt.f64 d17, d17, d16
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vmov r0, r1, d17
+; ARMV8-NEXT:    vselgt.f64 d16, d18, d16
 ; ARMV8-NEXT:    vmov r2, r3, d16
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fminnumv264_non_zero_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -1146,20 +1078,19 @@ define <2 x double> @fminnumv264_one_zero_intrinsic(<2 x double> %x) {
 ;
 ; ARMV8-LABEL: fminnumv264_one_zero_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vmov.f64 d16, #-1.000000e+00
-; ARMV8-NEXT:    vldr d17, .LCPI27_0
-; ARMV8-NEXT:    vmov d18, r0, r1
 ; ARMV8-NEXT:    vmov d19, r2, r3
-; ARMV8-NEXT:    vminnm.f64 d16, d18, d16
-; ARMV8-NEXT:    vminnm.f64 d17, d19, d17
-; ARMV8-NEXT:    vmov r0, r1, d16
+; ARMV8-NEXT:    vcmp.f64 d19, #0
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vmov d18, r0, r1
+; ARMV8-NEXT:    vmov.f64 d16, #-1.000000e+00
+; ARMV8-NEXT:    vcmp.f64 d16, d18
+; ARMV8-NEXT:    vmov.i32 d17, #0x0
+; ARMV8-NEXT:    vmovlt.f64 d17, d19
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
 ; ARMV8-NEXT:    vmov r2, r3, d17
-; ARMV8-NEXT:    mov pc, lr
-; ARMV8-NEXT:    .p2align 3
-; ARMV8-NEXT:  @ %bb.1:
-; ARMV8-NEXT:  .LCPI27_0:
-; ARMV8-NEXT:    .long 0 @ double 0
-; ARMV8-NEXT:    .long 0
+; ARMV8-NEXT:    vselgt.f64 d16, d18, d16
+; ARMV8-NEXT:    vmov r0, r1, d16
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fminnumv264_one_zero_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -1204,15 +1135,19 @@ define <2 x double> @fmaxnumv264_intrinsic(<2 x double> %x, <2 x double> %y) {
 ;
 ; ARMV8-LABEL: fmaxnumv264_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vldr d16, [sp, #8]
-; ARMV8-NEXT:    vmov d18, r2, r3
-; ARMV8-NEXT:    vldr d17, [sp]
-; ARMV8-NEXT:    vmov d19, r0, r1
-; ARMV8-NEXT:    vmaxnm.f64 d16, d18, d16
-; ARMV8-NEXT:    vmaxnm.f64 d17, d19, d17
+; ARMV8-NEXT:    mov r12, sp
+; ARMV8-NEXT:    vld1.64 {d16, d17}, [r12]
+; ARMV8-NEXT:    vmov d18, r0, r1
+; ARMV8-NEXT:    vcmp.f64 d18, d16
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vmov d19, r2, r3
+; ARMV8-NEXT:    vcmp.f64 d19, d17
+; ARMV8-NEXT:    vselgt.f64 d18, d18, d16
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vmov r0, r1, d18
+; ARMV8-NEXT:    vselgt.f64 d16, d19, d17
 ; ARMV8-NEXT:    vmov r2, r3, d16
-; ARMV8-NEXT:    vmov r0, r1, d17
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnumv264_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -1252,15 +1187,19 @@ define <2 x double> @fmaxnumv264_nsz_intrinsic(<2 x double> %x, <2 x double> %y)
 ;
 ; ARMV8-LABEL: fmaxnumv264_nsz_intrinsic:
 ; ARMV8:       @ %bb.0:
-; ARMV8-NEXT:    vldr d16, [sp, #8]
-; ARMV8-NEXT:    vmov d18, r2, r3
-; ARMV8-NEXT:    vldr d17, [sp]
-; ARMV8-NEXT:    vmov d19, r0, r1
-; ARMV8-NEXT:    vmaxnm.f64 d16, d18, d16
-; ARMV8-NEXT:    vmaxnm.f64 d17, d19, d17
+; ARMV8-NEXT:    mov r12, sp
+; ARMV8-NEXT:    vld1.64 {d16, d17}, [r12]
+; ARMV8-NEXT:    vmov d18, r0, r1
+; ARMV8-NEXT:    vcmp.f64 d18, d16
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vmov d19, r2, r3
+; ARMV8-NEXT:    vcmp.f64 d19, d17
+; ARMV8-NEXT:    vselgt.f64 d18, d18, d16
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vmov r0, r1, d18
+; ARMV8-NEXT:    vselgt.f64 d16, d19, d17
 ; ARMV8-NEXT:    vmov r2, r3, d16
-; ARMV8-NEXT:    vmov r0, r1, d17
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnumv264_nsz_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -1305,23 +1244,24 @@ define <2 x double> @fmaxnumv264_zero_intrinsic(<2 x double> %x) {
 ;
 ; ARMV8-LABEL: fmaxnumv264_zero_intrinsic:
 ; ARMV8:       @ %bb.0:
+; ARMV8-NEXT:    vmov d18, r0, r1
 ; ARMV8-NEXT:    vldr d16, .LCPI30_0
-; ARMV8-NEXT:    vmov d18, r2, r3
-; ARMV8-NEXT:    vldr d17, .LCPI30_1
-; ARMV8-NEXT:    vmov d19, r0, r1
-; ARMV8-NEXT:    vmaxnm.f64 d16, d18, d16
-; ARMV8-NEXT:    vmaxnm.f64 d17, d19, d17
-; ARMV8-NEXT:    vmov r2, r3, d16
+; ARMV8-NEXT:    vcmp.f64 d18, #0
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vmov d19, r2, r3
+; ARMV8-NEXT:    vcmp.f64 d19, d16
+; ARMV8-NEXT:    vmov.i32 d17, #0x0
+; ARMV8-NEXT:    vselgt.f64 d17, d18, d17
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
 ; ARMV8-NEXT:    vmov r0, r1, d17
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    vselgt.f64 d16, d19, d16
+; ARMV8-NEXT:    vmov r2, r3, d16
+; ARMV8-NEXT:    bx lr
 ; ARMV8-NEXT:    .p2align 3
 ; ARMV8-NEXT:  @ %bb.1:
 ; ARMV8-NEXT:  .LCPI30_0:
 ; ARMV8-NEXT:    .long 0 @ double -0
 ; ARMV8-NEXT:    .long 2147483648
-; ARMV8-NEXT:  .LCPI30_1:
-; ARMV8-NEXT:    .long 0 @ double 0
-; ARMV8-NEXT:    .long 0
 ;
 ; ARMV8M-LABEL: fmaxnumv264_zero_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -1375,13 +1315,17 @@ define <2 x double> @fmaxnumv264_minus_zero_intrinsic(<2 x double> %x) {
 ; ARMV8-LABEL: fmaxnumv264_minus_zero_intrinsic:
 ; ARMV8:       @ %bb.0:
 ; ARMV8-NEXT:    vldr d16, .LCPI31_0
-; ARMV8-NEXT:    vmov d18, r0, r1
-; ARMV8-NEXT:    vmov d17, r2, r3
-; ARMV8-NEXT:    vmaxnm.f64 d18, d18, d16
-; ARMV8-NEXT:    vmaxnm.f64 d16, d17, d16
-; ARMV8-NEXT:    vmov r0, r1, d18
+; ARMV8-NEXT:    vmov d17, r0, r1
+; ARMV8-NEXT:    vmov d18, r2, r3
+; ARMV8-NEXT:    vcmp.f64 d17, d16
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vcmp.f64 d18, d16
+; ARMV8-NEXT:    vselgt.f64 d17, d17, d16
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vmov r0, r1, d17
+; ARMV8-NEXT:    vselgt.f64 d16, d18, d16
 ; ARMV8-NEXT:    vmov r2, r3, d16
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ; ARMV8-NEXT:    .p2align 3
 ; ARMV8-NEXT:  @ %bb.1:
 ; ARMV8-NEXT:  .LCPI31_0:
@@ -1431,13 +1375,17 @@ define <2 x double> @fmaxnumv264_non_zero_intrinsic(<2 x double> %x) {
 ; ARMV8-LABEL: fmaxnumv264_non_zero_intrinsic:
 ; ARMV8:       @ %bb.0:
 ; ARMV8-NEXT:    vmov.f64 d16, #1.000000e+00
-; ARMV8-NEXT:    vmov d18, r0, r1
-; ARMV8-NEXT:    vmov d17, r2, r3
-; ARMV8-NEXT:    vmaxnm.f64 d18, d18, d16
-; ARMV8-NEXT:    vmaxnm.f64 d16, d17, d16
-; ARMV8-NEXT:    vmov r0, r1, d18
+; ARMV8-NEXT:    vmov d17, r0, r1
+; ARMV8-NEXT:    vcmp.f64 d17, d16
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vmov d18, r2, r3
+; ARMV8-NEXT:    vcmp.f64 d18, d16
+; ARMV8-NEXT:    vselgt.f64 d17, d17, d16
+; ARMV8-NEXT:    vmrs APSR_nzcv, fpscr
+; ARMV8-NEXT:    vmov r0, r1, d17
+; ARMV8-NEXT:    vselgt.f64 d16, d18, d16
 ; ARMV8-NEXT:    vmov r2, r3, d16
-; ARMV8-NEXT:    mov pc, lr
+; ARMV8-NEXT:    bx lr
 ;
 ; ARMV8M-LABEL: fmaxnumv264_non_zero_intrinsic:
 ; ARMV8M:       @ %bb.0:
@@ -1456,3 +1404,39 @@ define <2 x double> @fmaxnumv264_non_zero_intrinsic(<2 x double> %x) {
   %a = call nnan <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double><double 1.0, double 1.0>)
   ret <2 x double> %a
 }
+
+define void @pr65820(ptr %y, <4 x float> %splat) {
+; ARMV7-LABEL: pr65820:
+; ARMV7:       @ %bb.0: @ %entry
+; ARMV7-NEXT:    vmov d16, r2, r3
+; ARMV7-NEXT:    vdup.32 q8, d16[0]
+; ARMV7-NEXT:    vcgt.f32 q9, q8, #0
+; ARMV7-NEXT:    vand q8, q8, q9
+; ARMV7-NEXT:    vst1.32 {d16, d17}, [r0]
+; ARMV7-NEXT:    bx lr
+;
+; ARMV8-LABEL: pr65820:
+; ARMV8:       @ %bb.0: @ %entry
+; ARMV8-NEXT:    vmov d16, r2, r3
+; ARMV8-NEXT:    vmov.i32 q9, #0x0
+; ARMV8-NEXT:    vdup.32 q8, d16[0]
+; ARMV8-NEXT:    vmaxnm.f32 q8, q8, q9
+; ARMV8-NEXT:    vst1.32 {d16, d17}, [r0]
+; ARMV8-NEXT:    bx lr
+;
+; ARMV8M-LABEL: pr65820:
+; ARMV8M:       @ %bb.0: @ %entry
+; ARMV8M-NEXT:    vmov d0, r2, r3
+; ARMV8M-NEXT:    vmov r1, s0
+; ARMV8M-NEXT:    vmov.i32 q0, #0x0
+; ARMV8M-NEXT:    vdup.32 q1, r1
+; ARMV8M-NEXT:    vmaxnm.f32 q0, q1, q0
+; ARMV8M-NEXT:    vstrw.32 q0, [r0]
+; ARMV8M-NEXT:    bx lr
+entry:
+  %broadcast.splat = shufflevector <4 x float> %splat, <4 x float> zeroinitializer, <4 x i32> zeroinitializer
+  %0 = fcmp ogt <4 x float> %broadcast.splat, zeroinitializer
+  %1 = select <4 x i1> %0, <4 x float> %broadcast.splat, <4 x float> zeroinitializer
+  store <4 x float> %1, ptr %y, align 4
+  ret void
+}

>From 62bdb77e11f4545cbfb6b7b1ce32cd6ec4217c97 Mon Sep 17 00:00:00 2001
From: Kai Luo <lkail at cn.ibm.com>
Date: Thu, 14 Sep 2023 01:49:17 +0000
Subject: [PATCH 07/86] [JITLink][PowerPC] Fix incorrect assertion of addend
 for R_PPC64_REL24

There is case that R_PPC64_REL24 with non-zero addend. The assertion is incorrectly triggered in such situation.

Reviewed By: lhames

Differential Revision: https://reviews.llvm.org/D158708
---
 llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h      |  6 ++++--
 llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp         | 10 +++++++---
 .../JITLink/ppc64/ppc64-rel24-non-zero-addend.test     |  5 +----
 3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h b/llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h
index 42ab9ddd8765b4e..88af15d61e714e1 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h
@@ -204,9 +204,11 @@ class PLTTableManager : public TableManager<PLTTableManager<Endianness>> {
       if (isExternal) {
         E.setKind(ppc64::CallBranchDeltaRestoreTOC);
         this->StubKind = LongBranchSaveR2;
+        // FIXME: We assume the addend to the external target is zero. It's
+        // quite unusual that the addend of an external target to be non-zero as
+        // if we have known the layout of the external object.
         E.setTarget(this->getEntryForTarget(G, E.getTarget()));
-        // We previously set branching to local entry. Now reverse that
-        // operation.
+        // Addend to the stub is zero.
         E.setAddend(0);
       } else
         // TODO: There are cases a local function call need a call stub.
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp
index ba66439f04086e4..5ce7a5bda840239 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp
@@ -346,9 +346,13 @@ class ELFLinkGraphBuilder_ppc64
       break;
     case ELF::R_PPC64_REL24:
       Kind = ppc64::RequestCall;
-      assert(Addend == 0 && "Addend is expected to be 0 for a function call");
-      // We assume branching to local entry, will reverse the addend if not.
-      Addend = ELF::decodePPC64LocalEntryOffset((*ObjSymbol)->st_other);
+      // Determining a target is external or not is deferred in PostPrunePass.
+      // We assume branching to local entry by default, since in PostPrunePass,
+      // we don't have any context to determine LocalEntryOffset. If it finally
+      // turns out to be an external call, we'll have a stub for the external
+      // target, the target of this edge will be the stub and its addend will be
+      // set 0.
+      Addend += ELF::decodePPC64LocalEntryOffset((*ObjSymbol)->st_other);
       break;
     case ELF::R_PPC64_REL64:
       Kind = ppc64::Delta64;
diff --git a/llvm/test/ExecutionEngine/JITLink/ppc64/ppc64-rel24-non-zero-addend.test b/llvm/test/ExecutionEngine/JITLink/ppc64/ppc64-rel24-non-zero-addend.test
index 6ee7ba407f935ed..eca0fc9097af54b 100644
--- a/llvm/test/ExecutionEngine/JITLink/ppc64/ppc64-rel24-non-zero-addend.test
+++ b/llvm/test/ExecutionEngine/JITLink/ppc64/ppc64-rel24-non-zero-addend.test
@@ -1,7 +1,4 @@
-# REQUIRES: asserts
 # RUN: yaml2obj %S/Inputs/rel24-non-zero-addend.yaml -o %t.o
-# RUN: not --crash llvm-jitlink -noexec %t.o 2>&1 | FileCheck %s
-# CHECK: Addend == 0 && "Addend is expected to be 0 for a function call"
-#
+# RUN: llvm-jitlink -noexec %t.o 2>&1
 # The object is generated from llvm/test/ExecutionEngine/MCJIT/test-global-ctors.ll,
 # containing an R_PPC64_REL24 whose addend is not zero.

>From 9130072613a6ec29a56753f98425eb71d484173d Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Wed, 13 Sep 2023 20:08:05 -0700
Subject: [PATCH 08/86] [lldb] Support Unicode in the prompt (#66312)

Account for Unicode when computing the prompt column width. Previously,
the string length (i.e. number of bytes) rather than the width of the
Glyph was used to compute the cursor position. The result was that the
cursor would be offset to the right when using a prompt containing
Unicode.
---
 lldb/include/lldb/Host/Editline.h             |  5 ++--
 .../Python/lldbsuite/test/lldbpexpect.py      |  2 ++
 lldb/source/Host/common/Editline.cpp          | 25 ++++++++++++-------
 lldb/test/API/terminal/TestEditline.py        | 11 ++++++++
 4 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/lldb/include/lldb/Host/Editline.h b/lldb/include/lldb/Host/Editline.h
index 35fd179abb509c3..64c384151facc91 100644
--- a/lldb/include/lldb/Host/Editline.h
+++ b/lldb/include/lldb/Host/Editline.h
@@ -248,9 +248,8 @@ class Editline {
   void SetCurrentLine(int line_index);
 
   /// Determines the width of the prompt in characters.  The width is guaranteed
-  /// to be the same for
-  /// all lines of the current multi-line session.
-  int GetPromptWidth();
+  /// to be the same for all lines of the current multi-line session.
+  size_t GetPromptWidth();
 
   /// Returns true if the underlying EditLine session's keybindings are
   /// Emacs-based, or false if
diff --git a/lldb/packages/Python/lldbsuite/test/lldbpexpect.py b/lldb/packages/Python/lldbsuite/test/lldbpexpect.py
index 85102db7d0a0536..9fedfa70c3f65dc 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbpexpect.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbpexpect.py
@@ -26,6 +26,7 @@ def launch(
         dimensions=None,
         run_under=None,
         post_spawn=None,
+        encoding=None,
         use_colors=False,
     ):
         logfile = getattr(sys.stdout, "buffer", sys.stdout) if self.TraceOn() else None
@@ -58,6 +59,7 @@ def launch(
             timeout=timeout,
             dimensions=dimensions,
             env=env,
+            encoding=encoding,
         )
         self.child.ptyproc.delayafterclose = timeout / 10
         self.child.ptyproc.delayafterterminate = timeout / 10
diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp
index 544804db3879eb5..e84b451435a999d 100644
--- a/lldb/source/Host/common/Editline.cpp
+++ b/lldb/source/Host/common/Editline.cpp
@@ -25,6 +25,7 @@
 #include "lldb/Utility/Timeout.h"
 
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Locale.h"
 #include "llvm/Support/Threading.h"
 
 using namespace lldb_private;
@@ -101,6 +102,10 @@ bool IsOnlySpaces(const EditLineStringType &content) {
   return true;
 }
 
+static size_t ColumnWidth(llvm::StringRef str) {
+  return llvm::sys::locale::columnWidth(str);
+}
+
 static int GetOperation(HistoryOperation op) {
   // The naming used by editline for the history operations is counter
   // intuitive to how it's used in LLDB's editline implementation.
@@ -328,14 +333,16 @@ std::string Editline::PromptForIndex(int line_index) {
   std::string continuation_prompt = prompt;
   if (m_set_continuation_prompt.length() > 0) {
     continuation_prompt = m_set_continuation_prompt;
-
     // Ensure that both prompts are the same length through space padding
-    while (continuation_prompt.length() < prompt.length()) {
-      continuation_prompt += ' ';
-    }
-    while (prompt.length() < continuation_prompt.length()) {
-      prompt += ' ';
-    }
+    const size_t prompt_width = ColumnWidth(prompt);
+    const size_t cont_prompt_width = ColumnWidth(continuation_prompt);
+    const size_t padded_prompt_width =
+        std::max(prompt_width, cont_prompt_width);
+    if (prompt_width < padded_prompt_width)
+      prompt += std::string(padded_prompt_width - prompt_width, ' ');
+    else if (cont_prompt_width < padded_prompt_width)
+      continuation_prompt +=
+          std::string(padded_prompt_width - cont_prompt_width, ' ');
   }
 
   if (use_line_numbers) {
@@ -353,7 +360,7 @@ void Editline::SetCurrentLine(int line_index) {
   m_current_prompt = PromptForIndex(line_index);
 }
 
-int Editline::GetPromptWidth() { return (int)PromptForIndex(0).length(); }
+size_t Editline::GetPromptWidth() { return ColumnWidth(PromptForIndex(0)); }
 
 bool Editline::IsEmacs() {
   const char *editor;
@@ -441,7 +448,7 @@ void Editline::DisplayInput(int firstIndex) {
 int Editline::CountRowsForLine(const EditLineStringType &content) {
   std::string prompt =
       PromptForIndex(0); // Prompt width is constant during an edit session
-  int line_length = (int)(content.length() + prompt.length());
+  int line_length = (int)(content.length() + ColumnWidth(prompt));
   return (line_length / m_terminal_width) + 1;
 }
 
diff --git a/lldb/test/API/terminal/TestEditline.py b/lldb/test/API/terminal/TestEditline.py
index 87fb3cba610c83c..4e766cff286f63a 100644
--- a/lldb/test/API/terminal/TestEditline.py
+++ b/lldb/test/API/terminal/TestEditline.py
@@ -44,3 +44,14 @@ def test_left_right_arrow(self):
             )
 
         self.quit()
+
+    @skipIfAsan
+    @skipIfEditlineSupportMissing
+    def test_prompt_unicode(self):
+        """Test that we can use Unicode in the LLDB prompt."""
+        self.launch(use_colors=True, encoding="utf-8")
+        self.child.send('settings set prompt "🐛 "\n')
+        # Check that the cursor is at position 4 ([4G)
+        # Prompt: 🐛 _
+        # Column: 1..4
+        self.child.expect(re.escape("🐛 \x1b[0m\x1b[4G"))

>From 98156163f2b95b202291ea995f20b5c583b0d205 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <yedeng.yd at linux.alibaba.com>
Date: Wed, 13 Sep 2023 16:02:51 +0800
Subject: [PATCH 09/86] [C++20] [Modules] [Serialization] Check input file
 contents with option ForceCheckCXX20ModulesInputFiles enabled

With overriden input files, e,g,. the compiler get the file from an
in-memroy buffer, the compiler can't get correct modified time information
to indicate whehter the input files are changed or not. Then, the
semantics of ForceCheckCXX20ModulesInputFiles are broken.

In this patch, if both ForceCheckCXX20ModulesInputFiles and
ValidateASTInputFilesContent and enabled, the compiler will still check the
hash value of the contents even if their modification time is the same.
---
 clang/lib/Serialization/ASTReader.cpp         |  54 ++++---
 clang/unittests/Serialization/CMakeLists.txt  |   1 +
 .../Serialization/ForceCheckFileInputTest.cpp | 144 ++++++++++++++++++
 3 files changed, 180 insertions(+), 19 deletions(-)
 create mode 100644 clang/unittests/Serialization/ForceCheckFileInputTest.cpp

diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 6842c0da79c44ef..0952244d037a77c 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -2489,6 +2489,32 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
     std::optional<int64_t> Old = std::nullopt;
     std::optional<int64_t> New = std::nullopt;
   };
+  auto HasInputContentChanged = [&](Change OriginalChange) {
+    assert(ValidateASTInputFilesContent &&
+           "We should only check the content of the inputs with "
+           "ValidateASTInputFilesContent enabled.");
+
+    if (StoredContentHash == static_cast<uint64_t>(llvm::hash_code(-1)))
+      return OriginalChange;
+
+    auto MemBuffOrError = FileMgr.getBufferForFile(*File);
+    if (!MemBuffOrError) {
+      if (!Complain)
+        return OriginalChange;
+      std::string ErrorStr = "could not get buffer for file '";
+      ErrorStr += File->getName();
+      ErrorStr += "'";
+      Error(ErrorStr);
+      return OriginalChange;
+    }
+
+    // FIXME: hash_value is not guaranteed to be stable!
+    auto ContentHash = hash_value(MemBuffOrError.get()->getBuffer());
+    if (StoredContentHash == static_cast<uint64_t>(ContentHash))
+      return Change{Change::None};
+
+    return Change{Change::Content};
+  };
   auto HasInputFileChanged = [&]() {
     if (StoredSize != File->getSize())
       return Change{Change::Size, StoredSize, File->getSize()};
@@ -2499,26 +2525,9 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
 
       // In case the modification time changes but not the content,
       // accept the cached file as legit.
-      if (ValidateASTInputFilesContent &&
-          StoredContentHash != static_cast<uint64_t>(llvm::hash_code(-1))) {
-        auto MemBuffOrError = FileMgr.getBufferForFile(*File);
-        if (!MemBuffOrError) {
-          if (!Complain)
-            return MTimeChange;
-          std::string ErrorStr = "could not get buffer for file '";
-          ErrorStr += File->getName();
-          ErrorStr += "'";
-          Error(ErrorStr);
-          return MTimeChange;
-        }
-
-        // FIXME: hash_value is not guaranteed to be stable!
-        auto ContentHash = hash_value(MemBuffOrError.get()->getBuffer());
-        if (StoredContentHash == static_cast<uint64_t>(ContentHash))
-          return Change{Change::None};
+      if (ValidateASTInputFilesContent)
+        return HasInputContentChanged(MTimeChange);
 
-        return Change{Change::Content};
-      }
       return MTimeChange;
     }
     return Change{Change::None};
@@ -2526,6 +2535,13 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
 
   bool IsOutOfDate = false;
   auto FileChange = SkipChecks ? Change{Change::None} : HasInputFileChanged();
+  // When ForceCheckCXX20ModulesInputFiles and ValidateASTInputFilesContent
+  // enabled, it is better to check the contents of the inputs. Since we can't
+  // get correct modified time information for inputs from overriden inputs.
+  if (HSOpts.ForceCheckCXX20ModulesInputFiles && ValidateASTInputFilesContent &&
+      F.StandardCXXModule && FileChange.Kind == Change::None)
+    FileChange = HasInputContentChanged(FileChange);
+
   // For an overridden file, there is nothing to validate.
   if (!Overridden && FileChange.Kind != Change::None) {
     if (Complain && !Diags.isDiagnosticInFlight()) {
diff --git a/clang/unittests/Serialization/CMakeLists.txt b/clang/unittests/Serialization/CMakeLists.txt
index d4dfb54af3d70f9..10d7de970c643da 100644
--- a/clang/unittests/Serialization/CMakeLists.txt
+++ b/clang/unittests/Serialization/CMakeLists.txt
@@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS
   )
 
 add_clang_unittest(SerializationTests
+  ForceCheckFileInputTest.cpp
   InMemoryModuleCacheTest.cpp
   ModuleCacheTest.cpp
   NoCommentsTest.cpp
diff --git a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
new file mode 100644
index 000000000000000..c1f6d40767751e4
--- /dev/null
+++ b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
@@ -0,0 +1,144 @@
+//===- unittests/Serialization/ForceCheckFileInputTest.cpp - CI tests -----===//
+//
+// 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 "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Serialization/ASTReader.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace clang;
+
+namespace {
+
+class ForceCheckFileInputTest : public ::testing::Test {
+  void SetUp() override {
+    EXPECT_FALSE(sys::fs::createUniqueDirectory("modules-test", TestDir));
+  }
+
+  void TearDown() override { sys::fs::remove_directories(TestDir); }
+
+public:
+  SmallString<256> TestDir;
+
+  void addFile(StringRef Path, StringRef Contents) {
+    EXPECT_FALSE(sys::path::is_absolute(Path));
+
+    SmallString<256> AbsPath(TestDir);
+    sys::path::append(AbsPath, Path);
+
+    EXPECT_FALSE(
+        sys::fs::create_directories(llvm::sys::path::parent_path(AbsPath)));
+
+    std::error_code EC;
+    llvm::raw_fd_ostream OS(AbsPath, EC);
+    EXPECT_FALSE(EC);
+    OS << Contents;
+  }
+};
+
+TEST_F(ForceCheckFileInputTest, ForceCheck) {
+  addFile("a.cppm", R"cpp(
+export module a;
+export int aa = 43;
+  )cpp");
+
+  std::string BMIPath = llvm::Twine(TestDir + "/a.pcm").str();
+
+  {
+    IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
+        CompilerInstance::createDiagnostics(new DiagnosticOptions());
+    CreateInvocationOptions CIOpts;
+    CIOpts.Diags = Diags;
+    CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();
+
+    const char *Args[] = {
+        "clang++",       "-std=c++20", "--precompile", "-working-directory",
+        TestDir.c_str(), "a.cppm",     "-o",           BMIPath.c_str()};
+    std::shared_ptr<CompilerInvocation> Invocation =
+        createInvocation(Args, CIOpts);
+    EXPECT_TRUE(Invocation);
+
+    auto Buf = CIOpts.VFS->getBufferForFile("a.cppm");
+    EXPECT_TRUE(Buf);
+
+    Invocation->getPreprocessorOpts().addRemappedFile("a.cppm", Buf->get());
+
+    Buf->release();
+
+    CompilerInstance Instance;
+    Instance.setDiagnostics(Diags.get());
+    Instance.setInvocation(Invocation);
+
+    if (auto VFSWithRemapping = createVFSFromCompilerInvocation(
+            Instance.getInvocation(), Instance.getDiagnostics(), CIOpts.VFS))
+      CIOpts.VFS = VFSWithRemapping;
+    Instance.createFileManager(CIOpts.VFS);
+
+    Instance.getHeaderSearchOpts().ValidateASTInputFilesContent = true;
+
+    GenerateModuleInterfaceAction Action;
+    EXPECT_TRUE(Instance.ExecuteAction(Action));
+    EXPECT_FALSE(Diags->hasErrorOccurred());
+  }
+
+  {
+    IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
+        CompilerInstance::createDiagnostics(new DiagnosticOptions());
+    CreateInvocationOptions CIOpts;
+    CIOpts.Diags = Diags;
+    CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();
+
+    std::string BMIPath = llvm::Twine(TestDir + "/a.pcm").str();
+    const char *Args[] = {
+        "clang++",       "-std=c++20", "--precompile", "-working-directory",
+        TestDir.c_str(), "a.cppm",     "-o",           BMIPath.c_str()};
+    std::shared_ptr<CompilerInvocation> Invocation =
+        createInvocation(Args, CIOpts);
+    EXPECT_TRUE(Invocation);
+
+    CompilerInstance Clang;
+
+    Clang.setInvocation(Invocation);
+    Clang.setDiagnostics(Diags.get());
+    FileManager *FM = Clang.createFileManager(CIOpts.VFS);
+    Clang.createSourceManager(*FM);
+
+    EXPECT_TRUE(Clang.createTarget());
+    Clang.createPreprocessor(TU_Complete);
+    Clang.getHeaderSearchOpts().ForceCheckCXX20ModulesInputFiles = true;
+    Clang.getHeaderSearchOpts().ValidateASTInputFilesContent = true;
+    Clang.createASTReader();
+
+    addFile("a.cppm", R"cpp(
+export module a;
+export int aa = 44;
+  )cpp");
+
+    auto ReadResult =
+        Clang.getASTReader()->ReadAST(BMIPath, serialization::MK_MainFile,
+                                      SourceLocation(), ASTReader::ARR_None);
+
+    // We shall be able to detect the content change here.
+    EXPECT_NE(ReadResult, ASTReader::Success);
+  }
+}
+
+} // anonymous namespace

>From a358b1515427ab638778ede0612b134d1b56b7e9 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Wed, 13 Sep 2023 20:28:28 -0700
Subject: [PATCH 10/86] [lldb] Fix PExpectTest when using utf-8 as the encoding

PExpect 4.6, when using 'utf-8' throws a TypeError when trying to write
to the log file:

  File "llvm-project/lldb/third_party/Python/module/pexpect-4.6/pexpect/spawnbase.py", line 126, in _log
    self.logfile.write(s)
  TypeError: a bytes-like object is required, not 'str'

This looks like a bug in PExpect to me. Since the log file is only used
for tracing, work around the issue by disabling the log file when
specifying an encoding. This should fix the Debian bot [1] which runs
the test with tracing enabled (-t).

[1] https://lab.llvm.org/buildbot/#/builders/68/builds/59955
---
 lldb/packages/Python/lldbsuite/test/lldbpexpect.py | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/lldb/packages/Python/lldbsuite/test/lldbpexpect.py b/lldb/packages/Python/lldbsuite/test/lldbpexpect.py
index 9fedfa70c3f65dc..9d216d903074737 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbpexpect.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbpexpect.py
@@ -29,7 +29,12 @@ def launch(
         encoding=None,
         use_colors=False,
     ):
-        logfile = getattr(sys.stdout, "buffer", sys.stdout) if self.TraceOn() else None
+        # Using a log file is incompatible with using utf-8 as the encoding.
+        logfile = (
+            getattr(sys.stdout, "buffer", sys.stdout)
+            if (self.TraceOn() and not encoding)
+            else None
+        )
 
         args = []
         if run_under is not None:

>From ceb4096459cbd5ba623d9098b430acb61c3f887b Mon Sep 17 00:00:00 2001
From: LLVM GN Syncbot <llvmgnsyncbot at gmail.com>
Date: Thu, 14 Sep 2023 03:34:54 +0000
Subject: [PATCH 11/86] [gn build] Port 45c160510f6c

---
 llvm/utils/gn/secondary/clang/unittests/Serialization/BUILD.gn | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/utils/gn/secondary/clang/unittests/Serialization/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/Serialization/BUILD.gn
index 0fa576aeb7aecd1..14d04dbdea121f2 100644
--- a/llvm/utils/gn/secondary/clang/unittests/Serialization/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/unittests/Serialization/BUILD.gn
@@ -14,6 +14,7 @@ unittest("SerializationTests") {
     "//llvm/lib/Support",
   ]
   sources = [
+    "ForceCheckFileInputTest.cpp",
     "InMemoryModuleCacheTest.cpp",
     "ModuleCacheTest.cpp",
     "NoCommentsTest.cpp",

>From 7a4752da1013a5c8888d962d1feb9dcbe3131b9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?=
 =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?=
 =?UTF-8?q?=E3=83=B3=29?= <clementval at gmail.com>
Date: Wed, 13 Sep 2023 20:49:54 -0700
Subject: [PATCH 12/86] [flang][openacc] Fix unstructured code in OpenACC
 region ops (#66284)

For unstructured construct, the blocks are created in advance inside the
function body. This causes issues when the unstructured construct is
inside an OpenACC region operations. This patch adds the same fix than
OpenMP lowering and re-create the blocks inside the op region.

Initial OpenMP fix: 29f167abcf7d871d17dd3f38f361916de1a12470
---
 flang/lib/Lower/DirectivesCommon.h            | 26 +++++-
 flang/lib/Lower/OpenACC.cpp                   | 87 ++++++++++++-------
 flang/lib/Lower/OpenMP.cpp                    | 27 +-----
 flang/test/Lower/OpenACC/acc-unstructured.f90 | 86 ++++++++++++++++++
 .../Lower/OpenACC/stop-stmt-in-region.f90     |  2 +-
 5 files changed, 171 insertions(+), 57 deletions(-)
 create mode 100644 flang/test/Lower/OpenACC/acc-unstructured.f90

diff --git a/flang/lib/Lower/DirectivesCommon.h b/flang/lib/Lower/DirectivesCommon.h
index 35825a20b4cf93f..efac311bec83338 100644
--- a/flang/lib/Lower/DirectivesCommon.h
+++ b/flang/lib/Lower/DirectivesCommon.h
@@ -587,7 +587,31 @@ void genOmpAccAtomicCapture(Fortran::lower::AbstractConverter &converter,
   firOpBuilder.setInsertionPointToStart(&block);
 }
 
+/// Create empty blocks for the current region.
+/// These blocks replace blocks parented to an enclosing region.
+template <typename... TerminatorOps>
+void createEmptyRegionBlocks(
+    fir::FirOpBuilder &builder,
+    std::list<Fortran::lower::pft::Evaluation> &evaluationList) {
+  mlir::Region *region = &builder.getRegion();
+  for (Fortran::lower::pft::Evaluation &eval : evaluationList) {
+    if (eval.block) {
+      if (eval.block->empty()) {
+        eval.block->erase();
+        eval.block = builder.createBlock(region);
+      } else {
+        [[maybe_unused]] mlir::Operation &terminatorOp = eval.block->back();
+        assert(mlir::isa<TerminatorOps...>(terminatorOp) &&
+               "expected terminator op");
+      }
+    }
+    if (!eval.isDirective() && eval.hasNestedEvaluations())
+      createEmptyRegionBlocks<TerminatorOps...>(builder,
+                                                eval.getNestedEvaluations());
+  }
+}
+
 } // namespace lower
 } // namespace Fortran
 
-#endif // FORTRAN_LOWER_DIRECTIVES_COMMON_H
\ No newline at end of file
+#endif // FORTRAN_LOWER_DIRECTIVES_COMMON_H
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 732765c4def59cb..180c077d39c9ee2 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -1250,16 +1250,16 @@ static void addOperand(llvm::SmallVectorImpl<mlir::Value> &operands,
 }
 
 template <typename Op, typename Terminator>
-static Op
-createRegionOp(fir::FirOpBuilder &builder, mlir::Location loc,
-               const llvm::SmallVectorImpl<mlir::Value> &operands,
-               const llvm::SmallVectorImpl<int32_t> &operandSegments) {
+static Op createRegionOp(fir::FirOpBuilder &builder, mlir::Location loc,
+                         Fortran::lower::pft::Evaluation &eval,
+                         const llvm::SmallVectorImpl<mlir::Value> &operands,
+                         const llvm::SmallVectorImpl<int32_t> &operandSegments,
+                         bool outerCombined = false) {
   llvm::ArrayRef<mlir::Type> argTy;
   Op op = builder.create<Op>(loc, argTy, operands);
   builder.createBlock(&op.getRegion());
   mlir::Block &block = op.getRegion().back();
   builder.setInsertionPointToStart(&block);
-  builder.create<Terminator>(loc);
 
   op->setAttr(Op::getOperandSegmentSizeAttr(),
               builder.getDenseI32ArrayAttr(operandSegments));
@@ -1267,6 +1267,15 @@ createRegionOp(fir::FirOpBuilder &builder, mlir::Location loc,
   // Place the insertion point to the start of the first block.
   builder.setInsertionPointToStart(&block);
 
+  // If it is an unstructured region and is not the outer region of a combined
+  // construct, create empty blocks for all evaluations.
+  if (eval.lowerAsUnstructured() && !outerCombined)
+    Fortran::lower::createEmptyRegionBlocks<mlir::acc::TerminatorOp,
+                                            mlir::acc::YieldOp>(
+        builder, eval.getNestedEvaluations());
+
+  builder.create<Terminator>(loc);
+  builder.setInsertionPointToStart(&block);
   return op;
 }
 
@@ -1347,6 +1356,7 @@ static void genWaitClause(Fortran::lower::AbstractConverter &converter,
 static mlir::acc::LoopOp
 createLoopOp(Fortran::lower::AbstractConverter &converter,
              mlir::Location currentLocation,
+             Fortran::lower::pft::Evaluation &eval,
              Fortran::semantics::SemanticsContext &semanticsContext,
              Fortran::lower::StatementContext &stmtCtx,
              const Fortran::parser::AccClauseList &accClauseList) {
@@ -1455,7 +1465,7 @@ createLoopOp(Fortran::lower::AbstractConverter &converter,
   addOperands(operands, operandSegments, cacheOperands);
 
   auto loopOp = createRegionOp<mlir::acc::LoopOp, mlir::acc::YieldOp>(
-      builder, currentLocation, operands, operandSegments);
+      builder, currentLocation, eval, operands, operandSegments);
 
   if (hasGang)
     loopOp.setHasGangAttr(builder.getUnitAttr());
@@ -1504,6 +1514,7 @@ createLoopOp(Fortran::lower::AbstractConverter &converter,
 
 static void genACC(Fortran::lower::AbstractConverter &converter,
                    Fortran::semantics::SemanticsContext &semanticsContext,
+                   Fortran::lower::pft::Evaluation &eval,
                    const Fortran::parser::OpenACCLoopConstruct &loopConstruct) {
 
   const auto &beginLoopDirective =
@@ -1518,7 +1529,7 @@ static void genACC(Fortran::lower::AbstractConverter &converter,
   if (loopDirective.v == llvm::acc::ACCD_loop) {
     const auto &accClauseList =
         std::get<Fortran::parser::AccClauseList>(beginLoopDirective.t);
-    createLoopOp(converter, currentLocation, semanticsContext, stmtCtx,
+    createLoopOp(converter, currentLocation, eval, semanticsContext, stmtCtx,
                  accClauseList);
   }
 }
@@ -1551,9 +1562,11 @@ template <typename Op>
 static Op
 createComputeOp(Fortran::lower::AbstractConverter &converter,
                 mlir::Location currentLocation,
+                Fortran::lower::pft::Evaluation &eval,
                 Fortran::semantics::SemanticsContext &semanticsContext,
                 Fortran::lower::StatementContext &stmtCtx,
-                const Fortran::parser::AccClauseList &accClauseList) {
+                const Fortran::parser::AccClauseList &accClauseList,
+                bool outerCombined = false) {
 
   // Parallel operation operands
   mlir::Value async;
@@ -1769,10 +1782,12 @@ createComputeOp(Fortran::lower::AbstractConverter &converter,
   Op computeOp;
   if constexpr (std::is_same_v<Op, mlir::acc::KernelsOp>)
     computeOp = createRegionOp<Op, mlir::acc::TerminatorOp>(
-        builder, currentLocation, operands, operandSegments);
+        builder, currentLocation, eval, operands, operandSegments,
+        outerCombined);
   else
     computeOp = createRegionOp<Op, mlir::acc::YieldOp>(
-        builder, currentLocation, operands, operandSegments);
+        builder, currentLocation, eval, operands, operandSegments,
+        outerCombined);
 
   if (addAsyncAttr)
     computeOp.setAsyncAttrAttr(builder.getUnitAttr());
@@ -1817,6 +1832,7 @@ createComputeOp(Fortran::lower::AbstractConverter &converter,
 
 static void genACCDataOp(Fortran::lower::AbstractConverter &converter,
                          mlir::Location currentLocation,
+                         Fortran::lower::pft::Evaluation &eval,
                          Fortran::semantics::SemanticsContext &semanticsContext,
                          Fortran::lower::StatementContext &stmtCtx,
                          const Fortran::parser::AccClauseList &accClauseList) {
@@ -1942,7 +1958,7 @@ static void genACCDataOp(Fortran::lower::AbstractConverter &converter,
     return;
 
   auto dataOp = createRegionOp<mlir::acc::DataOp, mlir::acc::TerminatorOp>(
-      builder, currentLocation, operands, operandSegments);
+      builder, currentLocation, eval, operands, operandSegments);
 
   dataOp.setAsyncAttr(addAsyncAttr);
   dataOp.setWaitAttr(addWaitAttr);
@@ -1971,6 +1987,7 @@ static void genACCDataOp(Fortran::lower::AbstractConverter &converter,
 static void
 genACCHostDataOp(Fortran::lower::AbstractConverter &converter,
                  mlir::Location currentLocation,
+                 Fortran::lower::pft::Evaluation &eval,
                  Fortran::semantics::SemanticsContext &semanticsContext,
                  Fortran::lower::StatementContext &stmtCtx,
                  const Fortran::parser::AccClauseList &accClauseList) {
@@ -2020,7 +2037,7 @@ genACCHostDataOp(Fortran::lower::AbstractConverter &converter,
 
   auto hostDataOp =
       createRegionOp<mlir::acc::HostDataOp, mlir::acc::TerminatorOp>(
-          builder, currentLocation, operands, operandSegments);
+          builder, currentLocation, eval, operands, operandSegments);
 
   if (addIfPresentAttr)
     hostDataOp.setIfPresentAttr(builder.getUnitAttr());
@@ -2029,6 +2046,7 @@ genACCHostDataOp(Fortran::lower::AbstractConverter &converter,
 static void
 genACC(Fortran::lower::AbstractConverter &converter,
        Fortran::semantics::SemanticsContext &semanticsContext,
+       Fortran::lower::pft::Evaluation &eval,
        const Fortran::parser::OpenACCBlockConstruct &blockConstruct) {
   const auto &beginBlockDirective =
       std::get<Fortran::parser::AccBeginBlockDirective>(blockConstruct.t);
@@ -2041,26 +2059,30 @@ genACC(Fortran::lower::AbstractConverter &converter,
   Fortran::lower::StatementContext stmtCtx;
 
   if (blockDirective.v == llvm::acc::ACCD_parallel) {
-    createComputeOp<mlir::acc::ParallelOp>(
-        converter, currentLocation, semanticsContext, stmtCtx, accClauseList);
+    createComputeOp<mlir::acc::ParallelOp>(converter, currentLocation, eval,
+                                           semanticsContext, stmtCtx,
+                                           accClauseList);
   } else if (blockDirective.v == llvm::acc::ACCD_data) {
-    genACCDataOp(converter, currentLocation, semanticsContext, stmtCtx,
+    genACCDataOp(converter, currentLocation, eval, semanticsContext, stmtCtx,
                  accClauseList);
   } else if (blockDirective.v == llvm::acc::ACCD_serial) {
-    createComputeOp<mlir::acc::SerialOp>(
-        converter, currentLocation, semanticsContext, stmtCtx, accClauseList);
+    createComputeOp<mlir::acc::SerialOp>(converter, currentLocation, eval,
+                                         semanticsContext, stmtCtx,
+                                         accClauseList);
   } else if (blockDirective.v == llvm::acc::ACCD_kernels) {
-    createComputeOp<mlir::acc::KernelsOp>(
-        converter, currentLocation, semanticsContext, stmtCtx, accClauseList);
+    createComputeOp<mlir::acc::KernelsOp>(converter, currentLocation, eval,
+                                          semanticsContext, stmtCtx,
+                                          accClauseList);
   } else if (blockDirective.v == llvm::acc::ACCD_host_data) {
-    genACCHostDataOp(converter, currentLocation, semanticsContext, stmtCtx,
-                     accClauseList);
+    genACCHostDataOp(converter, currentLocation, eval, semanticsContext,
+                     stmtCtx, accClauseList);
   }
 }
 
 static void
 genACC(Fortran::lower::AbstractConverter &converter,
        Fortran::semantics::SemanticsContext &semanticsContext,
+       Fortran::lower::pft::Evaluation &eval,
        const Fortran::parser::OpenACCCombinedConstruct &combinedConstruct) {
   const auto &beginCombinedDirective =
       std::get<Fortran::parser::AccBeginCombinedDirective>(combinedConstruct.t);
@@ -2075,18 +2097,21 @@ genACC(Fortran::lower::AbstractConverter &converter,
 
   if (combinedDirective.v == llvm::acc::ACCD_kernels_loop) {
     createComputeOp<mlir::acc::KernelsOp>(
-        converter, currentLocation, semanticsContext, stmtCtx, accClauseList);
-    createLoopOp(converter, currentLocation, semanticsContext, stmtCtx,
+        converter, currentLocation, eval, semanticsContext, stmtCtx,
+        accClauseList, /*outerCombined=*/true);
+    createLoopOp(converter, currentLocation, eval, semanticsContext, stmtCtx,
                  accClauseList);
   } else if (combinedDirective.v == llvm::acc::ACCD_parallel_loop) {
     createComputeOp<mlir::acc::ParallelOp>(
-        converter, currentLocation, semanticsContext, stmtCtx, accClauseList);
-    createLoopOp(converter, currentLocation, semanticsContext, stmtCtx,
+        converter, currentLocation, eval, semanticsContext, stmtCtx,
+        accClauseList, /*outerCombined=*/true);
+    createLoopOp(converter, currentLocation, eval, semanticsContext, stmtCtx,
                  accClauseList);
   } else if (combinedDirective.v == llvm::acc::ACCD_serial_loop) {
-    createComputeOp<mlir::acc::SerialOp>(
-        converter, currentLocation, semanticsContext, stmtCtx, accClauseList);
-    createLoopOp(converter, currentLocation, semanticsContext, stmtCtx,
+    createComputeOp<mlir::acc::SerialOp>(converter, currentLocation, eval,
+                                         semanticsContext, stmtCtx,
+                                         accClauseList, /*outerCombined=*/true);
+    createLoopOp(converter, currentLocation, eval, semanticsContext, stmtCtx,
                  accClauseList);
   } else {
     llvm::report_fatal_error("Unknown combined construct encountered");
@@ -3169,14 +3194,14 @@ void Fortran::lower::genOpenACCConstruct(
   std::visit(
       common::visitors{
           [&](const Fortran::parser::OpenACCBlockConstruct &blockConstruct) {
-            genACC(converter, semanticsContext, blockConstruct);
+            genACC(converter, semanticsContext, eval, blockConstruct);
           },
           [&](const Fortran::parser::OpenACCCombinedConstruct
                   &combinedConstruct) {
-            genACC(converter, semanticsContext, combinedConstruct);
+            genACC(converter, semanticsContext, eval, combinedConstruct);
           },
           [&](const Fortran::parser::OpenACCLoopConstruct &loopConstruct) {
-            genACC(converter, semanticsContext, loopConstruct);
+            genACC(converter, semanticsContext, eval, loopConstruct);
           },
           [&](const Fortran::parser::OpenACCStandaloneConstruct
                   &standaloneConstruct) {
diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp
index b960bb369dd4dd2..be9c0dcdbdbf485 100644
--- a/flang/lib/Lower/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP.cpp
@@ -1981,29 +1981,6 @@ static mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter,
   return converter.getFirOpBuilder().getIntegerType(loopVarTypeSize);
 }
 
-/// Create empty blocks for the current region.
-/// These blocks replace blocks parented to an enclosing region.
-static void createEmptyRegionBlocks(
-    fir::FirOpBuilder &firOpBuilder,
-    std::list<Fortran::lower::pft::Evaluation> &evaluationList) {
-  mlir::Region *region = &firOpBuilder.getRegion();
-  for (Fortran::lower::pft::Evaluation &eval : evaluationList) {
-    if (eval.block) {
-      if (eval.block->empty()) {
-        eval.block->erase();
-        eval.block = firOpBuilder.createBlock(region);
-      } else {
-        [[maybe_unused]] mlir::Operation &terminatorOp = eval.block->back();
-        assert((mlir::isa<mlir::omp::TerminatorOp>(terminatorOp) ||
-                mlir::isa<mlir::omp::YieldOp>(terminatorOp)) &&
-               "expected terminator op");
-      }
-    }
-    if (!eval.isDirective() && eval.hasNestedEvaluations())
-      createEmptyRegionBlocks(firOpBuilder, eval.getNestedEvaluations());
-  }
-}
-
 static void resetBeforeTerminator(fir::FirOpBuilder &firOpBuilder,
                                   mlir::Operation *storeOp,
                                   mlir::Block &block) {
@@ -2092,7 +2069,9 @@ static void createBodyOfOp(
   // If it is an unstructured region and is not the outer region of a combined
   // construct, create empty blocks for all evaluations.
   if (eval.lowerAsUnstructured() && !outerCombined)
-    createEmptyRegionBlocks(firOpBuilder, eval.getNestedEvaluations());
+    Fortran::lower::createEmptyRegionBlocks<mlir::omp::TerminatorOp,
+                                            mlir::omp::YieldOp>(
+        firOpBuilder, eval.getNestedEvaluations());
 
   // Insert the terminator.
   if constexpr (std::is_same_v<Op, mlir::omp::WsLoopOp> ||
diff --git a/flang/test/Lower/OpenACC/acc-unstructured.f90 b/flang/test/Lower/OpenACC/acc-unstructured.f90
new file mode 100644
index 000000000000000..bd9f3284d9fc25c
--- /dev/null
+++ b/flang/test/Lower/OpenACC/acc-unstructured.f90
@@ -0,0 +1,86 @@
+! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s
+
+subroutine test_unstructured1(a, b, c)
+  integer :: i, j, k
+  real :: a(:,:,:), b(:,:,:), c(:,:,:)
+
+  !$acc data copy(a, b, c)
+
+  !$acc kernels
+  a(:,:,:) = 0.0
+  !$acc end kernels
+
+  !$acc kernels
+  do i = 1, 10
+    do j = 1, 10
+      do k = 1, 10
+      end do
+    end do
+  end do
+  !$acc end kernels
+
+  do i = 1, 10
+    do j = 1, 10
+      do k = 1, 10
+      end do
+    end do
+
+    if (a(1,2,3) > 10) stop 'just to be unstructured'
+  end do
+
+  !$acc end data
+
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtest_unstructured1
+! CHECK: acc.data
+! CHECK: acc.kernels
+! CHECK: acc.kernels
+! CHECK: fir.call @_FortranAStopStatementText
+
+
+subroutine test_unstructured2(a, b, c)
+  integer :: i, j, k
+  real :: a(:,:,:), b(:,:,:), c(:,:,:)
+
+  !$acc parallel loop
+  do i = 1, 10
+    do j = 1, 10
+      do k = 1, 10
+        if (a(1,2,3) > 10) stop 'just to be unstructured'
+      end do
+    end do
+  end do
+
+! CHECK-LABEL: func.func @_QPtest_unstructured2
+! CHECK: acc.parallel
+! CHECK: acc.loop
+! CHECK: fir.call @_FortranAStopStatementText
+! CHECK: fir.unreachable
+! CHECK: acc.yield
+! CHECK: acc.yield
+
+end subroutine
+
+subroutine test_unstructured3(a, b, c)
+  integer :: i, j, k
+  real :: a(:,:,:), b(:,:,:), c(:,:,:)
+
+  !$acc parallel
+  do i = 1, 10
+    do j = 1, 10
+      do k = 1, 10
+        if (a(1,2,3) > 10) stop 'just to be unstructured'
+      end do
+    end do
+  end do
+  !$acc end parallel
+
+! CHECK-LABEL: func.func @_QPtest_unstructured3
+! CHECK: acc.parallel
+! CHECK: fir.call @_FortranAStopStatementText
+! CHECK: fir.unreachable
+! CHECK: acc.yield
+
+end subroutine
diff --git a/flang/test/Lower/OpenACC/stop-stmt-in-region.f90 b/flang/test/Lower/OpenACC/stop-stmt-in-region.f90
index 4b3e5632650f1cf..bec9d53b54c0f1d 100644
--- a/flang/test/Lower/OpenACC/stop-stmt-in-region.f90
+++ b/flang/test/Lower/OpenACC/stop-stmt-in-region.f90
@@ -29,7 +29,7 @@ subroutine test_stop_in_region1()
 ! CHECK:           %[[VAL_2:.*]] = arith.constant false
 ! CHECK:           %[[VAL_3:.*]] = arith.constant false
 ! CHECK:           %[[VAL_4:.*]] = fir.call @_FortranAStopStatement(%[[VAL_1]], %[[VAL_2]], %[[VAL_3]]) {{.*}} : (i32, i1, i1) -> none
-! CHECK:           acc.yield
+! CHECK:           fir.unreachable
 ! CHECK:         }
 ! CHECK:         return
 ! CHECK:       }

>From e7d986dd98b28875927f1a8f6918faee60029314 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?=
 =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?=
 =?UTF-8?q?=E3=83=B3=29?= <clementval at gmail.com>
Date: Wed, 13 Sep 2023 20:50:20 -0700
Subject: [PATCH 13/86] [flang][openacc] Support labeled DO loop after acc loop
 directive (#66294)

Make the `DoConstruct` in `OpenACCLoopConstruct` optional and move the
labeled do construct in in the canonicalization step.
---
 flang/include/flang/Parser/parse-tree.h       |  6 +++-
 flang/lib/Parser/openacc-parsers.cpp          |  4 +--
 flang/lib/Parser/unparse.cpp                  |  2 +-
 flang/lib/Semantics/canonicalize-acc.cpp      | 36 +++++++++++++------
 flang/lib/Semantics/resolve-directives.cpp    |  4 +--
 flang/test/Lower/OpenACC/acc-loop.f90         |  6 ++++
 .../Semantics/OpenACC/acc-loop-validity.f90   |  8 +++--
 7 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 5d92ecb05841767..cb4bb59bf312c7c 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4247,7 +4247,11 @@ struct OpenACCDeclarativeConstruct {
 EMPTY_CLASS(AccEndLoop);
 struct OpenACCLoopConstruct {
   TUPLE_CLASS_BOILERPLATE(OpenACCLoopConstruct);
-  std::tuple<AccBeginLoopDirective, DoConstruct, std::optional<AccEndLoop>> t;
+  OpenACCLoopConstruct(AccBeginLoopDirective &&a)
+      : t({std::move(a), std::nullopt, std::nullopt}) {}
+  std::tuple<AccBeginLoopDirective, std::optional<DoConstruct>,
+      std::optional<AccEndLoop>>
+      t;
 };
 
 struct OpenACCStandaloneConstruct {
diff --git a/flang/lib/Parser/openacc-parsers.cpp b/flang/lib/Parser/openacc-parsers.cpp
index afa12b88019bd9a..e1cbe6b86df91e9 100644
--- a/flang/lib/Parser/openacc-parsers.cpp
+++ b/flang/lib/Parser/openacc-parsers.cpp
@@ -154,9 +154,7 @@ TYPE_PARSER(construct<AccEndLoop>(startAccLine >> "END LOOP"_tok))
 
 TYPE_PARSER(construct<OpenACCLoopConstruct>(
     sourced(Parser<AccBeginLoopDirective>{} / endAccLine),
-    withMessage("A DO loop must follow the loop construct"_err_en_US,
-        Parser<DoConstruct>{}),
-    maybe(Parser<AccEndLoop>{} / endAccLine)))
+    maybe(Parser<DoConstruct>{}), maybe(Parser<AccEndLoop>{} / endAccLine)))
 
 // 2.15.1 Routine directive
 TYPE_PARSER(sourced(construct<OpenACCRoutineConstruct>(verbatim("ROUTINE"_tok),
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 398545d315e5cd5..6cac3fb5859f87b 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -1947,7 +1947,7 @@ class UnparseVisitor {
     Walk(std::get<AccBeginLoopDirective>(x.t));
     Put("\n");
     EndOpenACC();
-    Walk(std::get<DoConstruct>(x.t));
+    Walk(std::get<std::optional<DoConstruct>>(x.t));
   }
   void Unparse(const AccBeginLoopDirective &x) {
     Walk(std::get<AccLoopDirective>(x.t));
diff --git a/flang/lib/Semantics/canonicalize-acc.cpp b/flang/lib/Semantics/canonicalize-acc.cpp
index e79ab997637b083..3887e479cbce5d5 100644
--- a/flang/lib/Semantics/canonicalize-acc.cpp
+++ b/flang/lib/Semantics/canonicalize-acc.cpp
@@ -109,21 +109,37 @@ class CanonicalizationOfAcc {
 
   void RewriteOpenACCLoopConstruct(parser::OpenACCLoopConstruct &x,
       parser::Block &block, parser::Block::iterator it) {
+    parser::Block::iterator nextIt;
     auto &beginDir{std::get<parser::AccBeginLoopDirective>(x.t)};
     auto &dir{std::get<parser::AccLoopDirective>(beginDir.t)};
-    const auto &doCons{std::get<parser::DoConstruct>(x.t)};
+    auto &nestedDo{std::get<std::optional<parser::DoConstruct>>(x.t)};
+
+    if (!nestedDo) {
+      nextIt = it;
+      if (++nextIt != block.end()) {
+        if (auto *doCons{parser::Unwrap<parser::DoConstruct>(*nextIt)}) {
+          nestedDo = std::move(*doCons);
+          nextIt = block.erase(nextIt);
+        }
+      }
+    }
 
-    if (!doCons.GetLoopControl()) {
-      messages_.Say(dir.source,
-          "DO loop after the %s directive must have loop control"_err_en_US,
-          parser::ToUpperCaseLetters(dir.source.ToString()));
+    if (nestedDo) {
+      if (!nestedDo->GetLoopControl()) {
+        messages_.Say(dir.source,
+            "DO loop after the %s directive must have loop control"_err_en_US,
+            parser::ToUpperCaseLetters(dir.source.ToString()));
+        return;
+      }
+      CheckDoConcurrentClauseRestriction<parser::OpenACCLoopConstruct,
+          parser::AccBeginLoopDirective>(x, *nestedDo);
+      CheckTileClauseRestriction<parser::OpenACCLoopConstruct,
+          parser::AccBeginLoopDirective>(x, *nestedDo);
       return;
     }
-
-    CheckDoConcurrentClauseRestriction<parser::OpenACCLoopConstruct,
-        parser::AccBeginLoopDirective>(x, doCons);
-    CheckTileClauseRestriction<parser::OpenACCLoopConstruct,
-        parser::AccBeginLoopDirective>(x, doCons);
+    messages_.Say(dir.source,
+        "A DO loop must follow the %s directive"_err_en_US,
+        parser::ToUpperCaseLetters(dir.source.ToString()));
   }
 
   void RewriteOpenACCCombinedConstruct(parser::OpenACCCombinedConstruct &x,
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 9a2689c2e6c81d5..63a3e1cd31549c0 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -1153,8 +1153,8 @@ void AccAttributeVisitor::PrivatizeAssociatedLoopIndex(
     return nullptr;
   };
 
-  const auto &outer{std::get<parser::DoConstruct>(x.t)};
-  for (const parser::DoConstruct *loop{&outer}; loop && level > 0; --level) {
+  const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t)};
+  for (const parser::DoConstruct *loop{&*outer}; loop && level > 0; --level) {
     // go through all the nested do-loops and resolve index variables
     const parser::Name *iv{GetLoopIndex(*loop)};
     if (iv) {
diff --git a/flang/test/Lower/OpenACC/acc-loop.f90 b/flang/test/Lower/OpenACC/acc-loop.f90
index f902728b67100f3..ec5eff5da78e7ed 100644
--- a/flang/test/Lower/OpenACC/acc-loop.f90
+++ b/flang/test/Lower/OpenACC/acc-loop.f90
@@ -315,4 +315,10 @@ program acc_loop
 ! CHECK: %[[CACHE:.*]] = acc.cache varPtr(%{{.*}} : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"}
 ! CHECK: acc.loop cache(%[[CACHE]] : !fir.ref<!fir.array<10xf32>>)
 
+  !$acc loop
+  do 100 i=0, n
+  100 continue
+! CHECK: acc.loop
+! CHECK: fir.do_loop
+
 end program
diff --git a/flang/test/Semantics/OpenACC/acc-loop-validity.f90 b/flang/test/Semantics/OpenACC/acc-loop-validity.f90
index 906602640efacc7..205e67a4728fcbe 100644
--- a/flang/test/Semantics/OpenACC/acc-loop-validity.f90
+++ b/flang/test/Semantics/OpenACC/acc-loop-validity.f90
@@ -4,12 +4,16 @@ program openacc_clause_validity
 
   implicit none
 
-  integer :: i
+  integer :: i, n
 
   i = 0
 
+  !ERROR: A DO loop must follow the LOOP directive
   !$acc loop
-  !ERROR: A DO loop must follow the loop construct
   i = 1
 
+  !$acc loop
+  do 100 i=0, n
+  100 continue
+
 end

>From d95de7f5c7689c90ba9b260977f75abb0b104503 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?=
 =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?=
 =?UTF-8?q?=E3=83=B3=29?= <clementval at gmail.com>
Date: Wed, 13 Sep 2023 20:50:42 -0700
Subject: [PATCH 14/86] [flang][openacc] Support labeled DO loop after acc
 combined directive (#66296)

This patch adds support for labeled do loop after combined directive. It
relaxes the initial parser and canonicalize labeled do loop into the
OpenACCCombinedConstruct.
---
 flang/lib/Parser/openacc-parsers.cpp          |  3 +--
 flang/lib/Semantics/canonicalize-acc.cpp      | 20 ++++++++++++++-----
 .../test/Lower/OpenACC/acc-parallel-loop.f90  |  7 +++++++
 .../Semantics/OpenACC/acc-combined-loop.f90   | 18 ++++++++++++++---
 4 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/flang/lib/Parser/openacc-parsers.cpp b/flang/lib/Parser/openacc-parsers.cpp
index e1cbe6b86df91e9..09b30e679de0e06 100644
--- a/flang/lib/Parser/openacc-parsers.cpp
+++ b/flang/lib/Parser/openacc-parsers.cpp
@@ -255,8 +255,7 @@ TYPE_PARSER(startAccLine >>
 
 TYPE_PARSER(construct<OpenACCCombinedConstruct>(
     sourced(Parser<AccBeginCombinedDirective>{} / endAccLine),
-    withMessage("A DO loop must follow the combined construct"_err_en_US,
-        Parser<DoConstruct>{}),
+    maybe(Parser<DoConstruct>{}),
     maybe(Parser<AccEndCombinedDirective>{} / endAccLine)))
 
 } // namespace Fortran::parser
diff --git a/flang/lib/Semantics/canonicalize-acc.cpp b/flang/lib/Semantics/canonicalize-acc.cpp
index 3887e479cbce5d5..f9e44b9540dbb93 100644
--- a/flang/lib/Semantics/canonicalize-acc.cpp
+++ b/flang/lib/Semantics/canonicalize-acc.cpp
@@ -148,14 +148,24 @@ class CanonicalizationOfAcc {
     parser::Block::iterator nextIt;
     auto &beginDir{std::get<parser::AccBeginCombinedDirective>(x.t)};
     auto &dir{std::get<parser::AccCombinedDirective>(beginDir.t)};
-    const auto &doConstruct{std::get<std::optional<parser::DoConstruct>>(x.t)};
+    auto &nestedDo{std::get<std::optional<parser::DoConstruct>>(x.t)};
 
-    if (doConstruct) {
+    if (!nestedDo) {
+      nextIt = it;
+      if (++nextIt != block.end()) {
+        if (auto *doCons{parser::Unwrap<parser::DoConstruct>(*nextIt)}) {
+          nestedDo = std::move(*doCons);
+          nextIt = block.erase(nextIt);
+        }
+      }
+    }
+
+    if (nestedDo) {
       CheckDoConcurrentClauseRestriction<parser::OpenACCCombinedConstruct,
-          parser::AccBeginCombinedDirective>(x, *doConstruct);
+          parser::AccBeginCombinedDirective>(x, *nestedDo);
       CheckTileClauseRestriction<parser::OpenACCCombinedConstruct,
-          parser::AccBeginCombinedDirective>(x, *doConstruct);
-      if (!doConstruct->GetLoopControl()) {
+          parser::AccBeginCombinedDirective>(x, *nestedDo);
+      if (!nestedDo->GetLoopControl()) {
         messages_.Say(dir.source,
             "DO loop after the %s directive must have loop control"_err_en_US,
             parser::ToUpperCaseLetters(dir.source.ToString()));
diff --git a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 b/flang/test/Lower/OpenACC/acc-parallel-loop.f90
index 4490a460afe969e..b9113437f86aa07 100644
--- a/flang/test/Lower/OpenACC/acc-parallel-loop.f90
+++ b/flang/test/Lower/OpenACC/acc-parallel-loop.f90
@@ -803,4 +803,11 @@ subroutine acc_parallel_loop
 ! CHECK:        acc.yield
 ! CHECK-NEXT: }{{$}}
 
+  !$acc parallel loop
+  do 10 i=0, n
+  10 continue
+! CHECK: acc.parallel
+! CHECK: acc.loop
+! CHECK: fir.do_loop
+
 end subroutine acc_parallel_loop
diff --git a/flang/test/Semantics/OpenACC/acc-combined-loop.f90 b/flang/test/Semantics/OpenACC/acc-combined-loop.f90
index 04ff6a308d55f4c..77ff8e1cc603c80 100644
--- a/flang/test/Semantics/OpenACC/acc-combined-loop.f90
+++ b/flang/test/Semantics/OpenACC/acc-combined-loop.f90
@@ -6,16 +6,28 @@ program openacc_combined_loop
 
   i = 1
 
+  !ERROR: A DO loop must follow the PARALLEL LOOP directive
   !$acc parallel loop
-  !ERROR: A DO loop must follow the combined construct
   i = 1
 
+  !ERROR: A DO loop must follow the KERNELS LOOP directive
   !$acc kernels loop
-  !ERROR: A DO loop must follow the combined construct
   i = 1
 
+  !ERROR: A DO loop must follow the SERIAL LOOP directive
   !$acc serial loop
-  !ERROR: A DO loop must follow the combined construct
   i = 1
 
+  !$acc parallel loop
+  do 10 i=0, n
+  10 continue
+
+  !$acc kernels loop
+  do 20 i=0, n
+  20 continue
+
+  !$acc serial loop
+  do 30 i=0, n
+  30 continue
+
 end

>From f41e22573de34f79921001a945d5f3157b47ed51 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Wed, 13 Sep 2023 20:58:12 -0700
Subject: [PATCH 15/86] [lldb] Add a setting to customize the prompt color
 (#66218)

Users often want to change the look of their prompt and currently the
only way to do that is by using ANSI escape codes in the prompt itself.
This is not only tedious, it also results in extra whitespace because
our Editline wrapper, when computing the cursor column, doesn't ignore
the invisible escape codes.

We already have various *-ansi-{prefix,suffix} settings that allow the
users to customize the color of auto-suggestions and progress events,
using mnemonics like ${ansi.fg.yellow}. This patch brings the same
mechanism to the prompt.

rdar://115390406
---
 lldb/include/lldb/Core/Debugger.h      |  4 ++++
 lldb/include/lldb/Host/Editline.h      | 10 ++++++++
 lldb/source/Core/CoreProperties.td     |  8 +++++++
 lldb/source/Core/Debugger.cpp          | 19 +++++++++++++++
 lldb/source/Core/IOHandler.cpp         |  9 +++++++-
 lldb/source/Host/common/Editline.cpp   | 32 +++++++++++---------------
 lldb/test/API/terminal/TestEditline.py | 24 +++++++++++++++++++
 7 files changed, 87 insertions(+), 19 deletions(-)

diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h
index f0908eeca5f5cf5..e4ee94809cf1a09 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -289,6 +289,10 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
 
   llvm::StringRef GetPrompt() const;
 
+  llvm::StringRef GetPromptAnsiPrefix() const;
+
+  llvm::StringRef GetPromptAnsiSuffix() const;
+
   void SetPrompt(llvm::StringRef p);
   void SetPrompt(const char *) = delete;
 
diff --git a/lldb/include/lldb/Host/Editline.h b/lldb/include/lldb/Host/Editline.h
index 64c384151facc91..ba289688aa7a95e 100644
--- a/lldb/include/lldb/Host/Editline.h
+++ b/lldb/include/lldb/Host/Editline.h
@@ -211,6 +211,14 @@ class Editline {
     m_fix_indentation_callback_chars = indent_chars;
   }
 
+  void SetPromptAnsiPrefix(std::string prefix) {
+    m_prompt_ansi_prefix = std::move(prefix);
+  }
+
+  void SetPromptAnsiSuffix(std::string suffix) {
+    m_prompt_ansi_suffix = std::move(suffix);
+  }
+
   void SetSuggestionAnsiPrefix(std::string prefix) {
     m_suggestion_ansi_prefix = std::move(prefix);
   }
@@ -398,6 +406,8 @@ class Editline {
   CompleteCallbackType m_completion_callback;
   SuggestionCallbackType m_suggestion_callback;
 
+  std::string m_prompt_ansi_prefix;
+  std::string m_prompt_ansi_suffix;
   std::string m_suggestion_ansi_prefix;
   std::string m_suggestion_ansi_suffix;
 
diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td
index c7d69676f6e14c0..92884258347e9be 100644
--- a/lldb/source/Core/CoreProperties.td
+++ b/lldb/source/Core/CoreProperties.td
@@ -65,6 +65,14 @@ let Definition = "debugger" in {
     DefaultEnumValue<"OptionValueString::eOptionEncodeCharacterEscapeSequences">,
     DefaultStringValue<"(lldb) ">,
     Desc<"The debugger command line prompt displayed for the user.">;
+  def PromptAnsiPrefix: Property<"prompt-ansi-prefix", "String">,
+    Global,
+    DefaultStringValue<"${ansi.faint}">,
+    Desc<"When in a color-enabled terminal, use the ANSI terminal code specified in this format immediately before the prompt.">;
+  def PromptAnsiSuffix: Property<"prompt-ansi-suffix", "String">,
+    Global,
+    DefaultStringValue<"${ansi.normal}">,
+    Desc<"When in a color-enabled terminal, use the ANSI terminal code specified in this format immediately after the prompt.">;
   def ScriptLanguage: Property<"script-lang", "Enum">,
     Global,
     DefaultEnumValue<"eScriptLanguagePython">,
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 1e989e13d305eab..21f71e449ca5ed0 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -235,6 +235,13 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
       // use-color changed. Ping the prompt so it can reset the ansi terminal
       // codes.
       SetPrompt(GetPrompt());
+    } else if (property_path ==
+                   g_debugger_properties[ePropertyPromptAnsiPrefix].name ||
+               property_path ==
+                   g_debugger_properties[ePropertyPromptAnsiSuffix].name) {
+      // Prompt colors changed. Ping the prompt so it can reset the ansi
+      // terminal codes.
+      SetPrompt(GetPrompt());
     } else if (property_path ==
                g_debugger_properties[ePropertyUseSourceCache].name) {
       // use-source-cache changed. Wipe out the cache contents if it was
@@ -301,6 +308,18 @@ llvm::StringRef Debugger::GetPrompt() const {
       idx, g_debugger_properties[idx].default_cstr_value);
 }
 
+llvm::StringRef Debugger::GetPromptAnsiPrefix() const {
+  const uint32_t idx = ePropertyPromptAnsiPrefix;
+  return GetPropertyAtIndexAs<llvm::StringRef>(
+      idx, g_debugger_properties[idx].default_cstr_value);
+}
+
+llvm::StringRef Debugger::GetPromptAnsiSuffix() const {
+  const uint32_t idx = ePropertyPromptAnsiSuffix;
+  return GetPropertyAtIndexAs<llvm::StringRef>(
+      idx, g_debugger_properties[idx].default_cstr_value);
+}
+
 void Debugger::SetPrompt(llvm::StringRef p) {
   constexpr uint32_t idx = ePropertyPrompt;
   SetPropertyAtIndex(idx, p);
diff --git a/lldb/source/Core/IOHandler.cpp b/lldb/source/Core/IOHandler.cpp
index ac9a9bb2844594f..7272e5df43fe7e1 100644
--- a/lldb/source/Core/IOHandler.cpp
+++ b/lldb/source/Core/IOHandler.cpp
@@ -474,8 +474,15 @@ bool IOHandlerEditline::SetPrompt(llvm::StringRef prompt) {
   m_prompt = std::string(prompt);
 
 #if LLDB_ENABLE_LIBEDIT
-  if (m_editline_up)
+  if (m_editline_up) {
     m_editline_up->SetPrompt(m_prompt.empty() ? nullptr : m_prompt.c_str());
+    if (m_debugger.GetUseColor()) {
+      m_editline_up->SetPromptAnsiPrefix(
+          ansi::FormatAnsiTerminalCodes(m_debugger.GetPromptAnsiPrefix()));
+      m_editline_up->SetPromptAnsiSuffix(
+          ansi::FormatAnsiTerminalCodes(m_debugger.GetPromptAnsiSuffix()));
+    }
+  }
 #endif
   return true;
 }
diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp
index e84b451435a999d..32dd4718c68d03a 100644
--- a/lldb/source/Host/common/Editline.cpp
+++ b/lldb/source/Host/common/Editline.cpp
@@ -53,10 +53,6 @@ int setupterm(char *term, int fildes, int *errret);
 
 /// https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
 #define ESCAPE "\x1b"
-/// Faint, decreased intensity or second colour.
-#define ANSI_FAINT ESCAPE "[2m"
-/// Normal colour or normal intensity (neither bold nor faint).
-#define ANSI_UNFAINT ESCAPE "[0m"
 #define ANSI_CLEAR_BELOW ESCAPE "[J"
 #define ANSI_CLEAR_RIGHT ESCAPE "[K"
 #define ANSI_SET_COLUMN_N ESCAPE "[%dG"
@@ -431,15 +427,13 @@ void Editline::MoveCursor(CursorLocation from, CursorLocation to) {
 void Editline::DisplayInput(int firstIndex) {
   fprintf(m_output_file, ANSI_SET_COLUMN_N ANSI_CLEAR_BELOW, 1);
   int line_count = (int)m_input_lines.size();
-  const char *faint = m_color_prompts ? ANSI_FAINT : "";
-  const char *unfaint = m_color_prompts ? ANSI_UNFAINT : "";
-
   for (int index = firstIndex; index < line_count; index++) {
-    fprintf(m_output_file, "%s"
-                           "%s"
-                           "%s" EditLineStringFormatSpec " ",
-            faint, PromptForIndex(index).c_str(), unfaint,
-            m_input_lines[index].c_str());
+    fprintf(m_output_file,
+            "%s"
+            "%s"
+            "%s" EditLineStringFormatSpec " ",
+            m_prompt_ansi_prefix.c_str(), PromptForIndex(index).c_str(),
+            m_prompt_ansi_suffix.c_str(), m_input_lines[index].c_str());
     if (index < line_count - 1)
       fprintf(m_output_file, "\n");
   }
@@ -548,14 +542,16 @@ unsigned char Editline::RecallHistory(HistoryOperation op) {
 int Editline::GetCharacter(EditLineGetCharType *c) {
   const LineInfoW *info = el_wline(m_editline);
 
-  // Paint a faint version of the desired prompt over the version libedit draws
-  // (will only be requested if colors are supported)
+  // Paint a ANSI formatted version of the desired prompt over the version
+  // libedit draws. (will only be requested if colors are supported)
   if (m_needs_prompt_repaint) {
     MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
-    fprintf(m_output_file, "%s"
-                           "%s"
-                           "%s",
-            ANSI_FAINT, Prompt(), ANSI_UNFAINT);
+    fprintf(m_output_file,
+            "%s"
+            "%s"
+            "%s",
+            m_prompt_ansi_prefix.c_str(), Prompt(),
+            m_prompt_ansi_suffix.c_str());
     MoveCursor(CursorLocation::EditingPrompt, CursorLocation::EditingCursor);
     m_needs_prompt_repaint = false;
   }
diff --git a/lldb/test/API/terminal/TestEditline.py b/lldb/test/API/terminal/TestEditline.py
index 4e766cff286f63a..0c6d16ff66da04e 100644
--- a/lldb/test/API/terminal/TestEditline.py
+++ b/lldb/test/API/terminal/TestEditline.py
@@ -55,3 +55,27 @@ def test_prompt_unicode(self):
         # Prompt: 🐛 _
         # Column: 1..4
         self.child.expect(re.escape("🐛 \x1b[0m\x1b[4G"))
+
+    @skipIfAsan
+    @skipIfEditlineSupportMissing
+    def test_prompt_color(self):
+        """Test that we can change the prompt color with prompt-ansi-prefix."""
+        self.launch(use_colors=True)
+        self.child.send('settings set prompt-ansi-prefix "${ansi.fg.red}"\n')
+        # Make sure this change is reflected immediately. Check that the color
+        # is set (31) and the cursor position (8) is correct.
+        # Prompt: (lldb) _
+        # Column: 1....6.8
+        self.child.expect(re.escape("\x1b[31m(lldb) \x1b[0m\x1b[8G"))
+
+    @skipIfAsan
+    @skipIfEditlineSupportMissing
+    def test_prompt_no_color(self):
+        """Test that prompt-ansi-prefix doesn't color the prompt when colors are off."""
+        self.launch(use_colors=False)
+        self.child.send('settings set prompt-ansi-prefix "${ansi.fg.red}"\n')
+        # Send foo so we can match the newline before the prompt and the foo
+        # after the prompt.
+        self.child.send("foo")
+        # Check that there are no escape codes.
+        self.child.expect(re.escape("\n(lldb) foo"))

>From 95ad890ee28b82a6a61c18442112747f250fdf92 Mon Sep 17 00:00:00 2001
From: Douglas Yung <douglas.yung at sony.com>
Date: Wed, 13 Sep 2023 21:07:56 -0700
Subject: [PATCH 16/86] Revert "Revert "Revert "[clang] Add experimental option
 to omit the RTTI component from the vtable when -fno-rtti is used"""

This reverts commit e16474ba2cba8fa69b413a83852d06c93155f8c9.

This change is still causing a test failure on a bot: https://lab.llvm.org/buildbot/#/builders/139/builds/49666
---
 .../clang/Basic/DiagnosticDriverKinds.td      |  3 --
 clang/include/clang/Basic/LangOptions.def     |  3 --
 clang/include/clang/Driver/Options.td         |  6 ---
 clang/lib/AST/VTableBuilder.cpp               |  9 +---
 clang/lib/Driver/ToolChains/Clang.cpp         |  6 ---
 clang/lib/Frontend/CompilerInvocation.cpp     |  8 ---
 .../simple-vtable-definition.cpp              | 32 ------------
 .../OmitRTTIComponentABI/vbase-offset.cpp     | 51 -------------------
 .../OmitRTTIComponentABI/vtable-layout.cpp    | 19 -------
 .../test/Driver/omit-rtti-component-flag.cpp  |  5 --
 .../omit-rtti-component-without-no-rtti.cpp   | 15 ------
 11 files changed, 2 insertions(+), 155 deletions(-)
 delete mode 100644 clang/test/CodeGenCXX/OmitRTTIComponentABI/simple-vtable-definition.cpp
 delete mode 100644 clang/test/CodeGenCXX/OmitRTTIComponentABI/vbase-offset.cpp
 delete mode 100644 clang/test/CodeGenCXX/OmitRTTIComponentABI/vtable-layout.cpp
 delete mode 100644 clang/test/Driver/omit-rtti-component-flag.cpp
 delete mode 100644 clang/test/Driver/omit-rtti-component-without-no-rtti.cpp

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 9349ff85ca8a1d3..86567267cfb437a 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -674,9 +674,6 @@ def err_cc1_round_trip_mismatch : Error<
 def err_cc1_unbounded_vscale_min : Error<
   "minimum vscale must be an unsigned integer greater than 0">;
 
-def err_drv_using_omit_rtti_component_without_no_rtti : Error<
-  "-fexperimental-omit-vtable-rtti call only be used with -fno-rtti">;
-
 def err_drv_ssp_missing_offset_argument : Error<
   "'%0' is used without '-mstack-protector-guard-offset', and there is no default">;
 
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index e18b5b80a34e718..102209ce899d70c 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -450,9 +450,6 @@ LANGOPT(SpeculativeLoadHardening, 1, 0, "Speculative load hardening enabled")
 LANGOPT(RelativeCXXABIVTables, 1, 0,
         "Use an ABI-incompatible v-table layout that uses relative references")
 
-LANGOPT(OmitVTableRTTI, 1, 0,
-        "Use an ABI-incompatible v-table layout that omits the RTTI component")
-
 LANGOPT(VScaleMin, 32, 0, "Minimum vscale value")
 LANGOPT(VScaleMax, 32, 0, "Maximum vscale value")
 
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 553c7928c4f949e..2d42d05859bc1d3 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2671,12 +2671,6 @@ def fno_experimental_relative_cxx_abi_vtables :
   Group<f_clang_Group>, Visibility<[ClangOption, CC1Option]>,
   HelpText<"Do not use the experimental C++ class ABI for classes with virtual tables">;
 
-defm experimental_omit_vtable_rtti : BoolFOption<"experimental-omit-vtable-rtti",
-  LangOpts<"OmitVTableRTTI">, DefaultFalse,
-  PosFlag<SetTrue, [], [CC1Option], "Omit">,
-  NegFlag<SetFalse, [], [CC1Option], "Do not omit">,
-  BothFlags<[], [CC1Option], " the RTTI component from virtual tables">>;
-
 def fcxx_abi_EQ : Joined<["-"], "fc++-abi=">,
                   Group<f_clang_Group>, Visibility<[ClangOption, CC1Option]>,
                   HelpText<"C++ ABI to use. This will override the target C++ ABI.">;
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index cce0a507e8077d8..a587f9bdc758529 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -665,11 +665,7 @@ CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const {
   // vtable address point. (We subtract 3 to account for the information just
   // above the address point, the RTTI info, the offset to top, and the
   // vcall offset itself).
-  size_t NumComponentsAboveAddrPoint = 3;
-  if (Context.getLangOpts().OmitVTableRTTI)
-    NumComponentsAboveAddrPoint--;
-  int64_t OffsetIndex =
-      -(int64_t)(NumComponentsAboveAddrPoint + Components.size());
+  int64_t OffsetIndex = -(int64_t)(3 + Components.size());
 
   // Under the relative ABI, the offset widths are 32-bit ints instead of
   // pointer widths.
@@ -1673,8 +1669,7 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
   Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop));
 
   // Next, add the RTTI.
-  if (!Context.getLangOpts().OmitVTableRTTI)
-    Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
+  Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
 
   uint64_t AddressPoint = Components.size();
 
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 40e60585a8b8d6e..531677e92f73252 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5526,9 +5526,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_relative_cxx_abi_vtables,
                   options::OPT_fno_experimental_relative_cxx_abi_vtables);
 
-  Args.AddLastArg(CmdArgs, options::OPT_fexperimental_omit_vtable_rtti,
-                  options::OPT_fno_experimental_omit_vtable_rtti);
-
   // Handle segmented stacks.
   Args.addOptInFlag(CmdArgs, options::OPT_fsplit_stack,
                     options::OPT_fno_split_stack);
@@ -6010,9 +6007,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_relative_cxx_abi_vtables,
                   options::OPT_fno_experimental_relative_cxx_abi_vtables);
 
-  Args.AddLastArg(CmdArgs, options::OPT_fexperimental_omit_vtable_rtti,
-                  options::OPT_fno_experimental_omit_vtable_rtti);
-
   if (Arg *A = Args.getLastArg(options::OPT_ffuchsia_api_level_EQ))
     A->render(Args, CmdArgs);
 
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 2dd299b5d10322d..730db8e394f66f1 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4109,14 +4109,6 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
                    options::OPT_fno_experimental_relative_cxx_abi_vtables,
                    TargetCXXABI::usesRelativeVTables(T));
 
-  // RTTI is on by default.
-  bool HasRTTI = Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti, true);
-  Opts.OmitVTableRTTI =
-      Args.hasFlag(options::OPT_fexperimental_omit_vtable_rtti,
-                   options::OPT_fno_experimental_omit_vtable_rtti, false);
-  if (Opts.OmitVTableRTTI && HasRTTI)
-    Diags.Report(diag::err_drv_using_omit_rtti_component_without_no_rtti);
-
   for (const auto &A : Args.getAllArgValues(OPT_fmacro_prefix_map_EQ)) {
     auto Split = StringRef(A).split('=');
     Opts.MacroPrefixMap.insert(
diff --git a/clang/test/CodeGenCXX/OmitRTTIComponentABI/simple-vtable-definition.cpp b/clang/test/CodeGenCXX/OmitRTTIComponentABI/simple-vtable-definition.cpp
deleted file mode 100644
index 99395ba0e05ec0b..000000000000000
--- a/clang/test/CodeGenCXX/OmitRTTIComponentABI/simple-vtable-definition.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/// Check that -fexperimental-omit-vtable-rtti omits the RTTI component from
-/// the vtable.
-
-// RUN: %clang_cc1 %s -triple=aarch64-unknown-linux-gnu -fno-rtti -fexperimental-omit-vtable-rtti -S -o - -emit-llvm | FileCheck -check-prefixes=POINTER,RTTI %s
-// RUN: %clang_cc1 %s -triple=aarch64-unknown-linux-gnu -fexperimental-relative-c++-abi-vtables -fno-rtti -fexperimental-omit-vtable-rtti -S -o - -emit-llvm | FileCheck -check-prefixes=RELATIVE,RTTI %s
-
-/// Normally, the vtable would contain at least three components:
-/// - An offset to top
-/// - A pointer to the RTTI struct
-/// - A virtual function
-///
-/// Now vtables should have just two components.
-// POINTER: @_ZTV1A = unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr null, ptr @_ZN1A3fooEv] }, align 8
-// RELATIVE: @_ZTV1A.local = private unnamed_addr constant { [2 x i32] } { [2 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [2 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 1) to i64)) to i32)] }, align 4
-// RELATIVE: @_ZTV1A = unnamed_addr alias { [2 x i32] }, ptr @_ZTV1A.local
-
-/// None of these supplementary symbols should be emitted with -fno-rtti, but
-/// as a sanity check lets make sure they're not emitted also.
-// RTTI-NOT: @_ZTVN10__cxxabiv117__class_type_infoE
-// RTTI-NOT: @_ZTS1A
-// RTTI-NOT: @_ZTI1A
-
-class A {
-public:
-  virtual void foo();
-};
-
-void A::foo() {}
-
-void A_foo(A *a) {
-  a->foo();
-}
diff --git a/clang/test/CodeGenCXX/OmitRTTIComponentABI/vbase-offset.cpp b/clang/test/CodeGenCXX/OmitRTTIComponentABI/vbase-offset.cpp
deleted file mode 100644
index d490cc2dbebe52e..000000000000000
--- a/clang/test/CodeGenCXX/OmitRTTIComponentABI/vbase-offset.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/// Check that the offset to top calculation is adjusted to account for the
-/// omitted RTTI entry.
-
-// RUN: %clang_cc1 %s -triple=aarch64-unknown-linux-gnu -fexperimental-omit-vtable-rtti -fno-rtti -S -o - -emit-llvm | FileCheck -check-prefixes=POINTER %s
-// RUN: %clang_cc1 %s -triple=aarch64-unknown-linux-gnu -fexperimental-relative-c++-abi-vtables -fexperimental-omit-vtable-rtti -fno-rtti -S -o - -emit-llvm | FileCheck -check-prefixes=RELATIVE %s
-
-/// Some important things to check:
-/// - The n16 here represents the virtual thunk size. Normally this would be 24
-///   to represent 3 components (offset to top, RTTI component, vcall offset),
-///   but since one 8-byte component is removed, this is now 16.
-// POINTER-LABEL: @_ZTv0_n16_N7Derived1fEi(
-// POINTER-NEXT:  entry:
-// POINTER:        [[vtable:%.+]] = load ptr, ptr %this1, align 8
-
-/// Same here - When getting the vbase offset, we subtract 2 pointer sizes
-/// instead of 3.
-// POINTER-NEXT:   [[vbase_offset_ptr:%.+]] = getelementptr inbounds i8, ptr [[vtable]], i64 -16
-// POINTER-NEXT:   [[vbase_offset:%.+]] = load i64, ptr [[vbase_offset_ptr]], align 8
-// POINTER-NEXT:   [[adj_this:%.+]] = getelementptr inbounds i8, ptr %this1, i64 [[vbase_offset]]
-// POINTER:   [[call:%.+]] = tail call noundef i32 @_ZN7Derived1fEi(ptr noundef{{[^,]*}} [[adj_this]], i32 noundef {{.*}})
-// POINTER:   ret i32 [[call]]
-
-/// For relative vtables, it's almost the same except the offset sizes are
-/// halved.
-// RELATIVE-LABEL: @_ZTv0_n8_N7Derived1fEi(
-// RELATIVE-NEXT:  entry:
-// RELATIVE:        [[vtable:%.+]] = load ptr, ptr %this1, align 8
-// RELATIVE-NEXT:   [[vbase_offset_ptr:%.+]] = getelementptr inbounds i8, ptr [[vtable]], i64 -8
-// RELATIVE-NEXT:   [[vbase_offset:%.+]] = load i32, ptr [[vbase_offset_ptr]], align 4
-// RELATIVE-NEXT:   [[adj_this:%.+]] = getelementptr inbounds i8, ptr %this1, i32 [[vbase_offset]]
-// RELATIVE:        [[call:%.+]] = tail call noundef i32 @_ZN7Derived1fEi(ptr noundef{{[^,]*}} [[adj_this]], i32 noundef {{.*}})
-// RELATIVE:        ret i32 [[call]]
-
-class Base {
-public:
-  virtual int f(int x);
-
-private:
-  long x;
-};
-
-class Derived : public virtual Base {
-public:
-  virtual int f(int x);
-
-private:
-  long y;
-};
-
-int Base::f(int x) { return x + 1; }
-int Derived::f(int x) { return x + 2; }
diff --git a/clang/test/CodeGenCXX/OmitRTTIComponentABI/vtable-layout.cpp b/clang/test/CodeGenCXX/OmitRTTIComponentABI/vtable-layout.cpp
deleted file mode 100644
index bcc9264f5e5b84f..000000000000000
--- a/clang/test/CodeGenCXX/OmitRTTIComponentABI/vtable-layout.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-/// Ensure -fdump-vtable-layout omits the rtti component when passed -fexperimental-omit-vtable-rtti.
-
-// RUN: %clang_cc1 %s -triple=aarch64-unknown-linux-gnu -fno-rtti -fexperimental-omit-vtable-rtti -emit-llvm-only -fdump-vtable-layouts | FileCheck %s
-
-// CHECK:      Vtable for 'A' (2 entries).
-// CHECK-NEXT:    0 | offset_to_top (0)
-// CHECK-NEXT:        -- (A, 0) vtable address --
-// CHECK-NEXT:    1 | void A::foo()
-
-class A {
-public:
-  virtual void foo();
-};
-
-void A::foo() {}
-
-void A_foo(A *a) {
-  a->foo();
-}
diff --git a/clang/test/Driver/omit-rtti-component-flag.cpp b/clang/test/Driver/omit-rtti-component-flag.cpp
deleted file mode 100644
index 54b88a8775ef3d2..000000000000000
--- a/clang/test/Driver/omit-rtti-component-flag.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %clangxx --target=aarch64-unknown-linux -fno-rtti -Xclang -fexperimental-omit-vtable-rtti -c %s -### 2>&1 | FileCheck %s --check-prefix=OMIT
-// RUN: %clangxx --target=aarch64-unknown-linux -fno-rtti -Xclang -fno-experimental-omit-vtable-rtti -c %s -### 2>&1 | FileCheck %s --check-prefix=NO-OMIT
-
-// OMIT: "-fexperimental-omit-vtable-rtti"
-// NO-OMIT-NOT: "-fexperimental-omit-vtable-rtti"
diff --git a/clang/test/Driver/omit-rtti-component-without-no-rtti.cpp b/clang/test/Driver/omit-rtti-component-without-no-rtti.cpp
deleted file mode 100644
index 0c2006bcb71633a..000000000000000
--- a/clang/test/Driver/omit-rtti-component-without-no-rtti.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-/// Ensure that -fexperimental-omit-vtable-rtti is only allowed if rtti is
-/// disabled.
-
-// UNSUPPORTED: system-windows
-
-// RUN: not %clang -c -Xclang -fexperimental-omit-vtable-rtti %s 2>&1 | FileCheck -check-prefix=ERROR %s
-// RUN: not %clang -c -Xclang -fexperimental-omit-vtable-rtti -frtti %s 2>&1 | FileCheck -check-prefix=ERROR %s
-// RUN: not %clang -c -Xclang -fexperimental-omit-vtable-rtti -fno-rtti -frtti %s 2>&1 | FileCheck -check-prefix=ERROR %s
-
-// RUN: %clang -c -Xclang -fexperimental-omit-vtable-rtti -fno-rtti %s 2>&1 | FileCheck -check-prefix=NO-ERROR %s --allow-empty
-// RUN: %clang -c -Xclang -fno-experimental-omit-vtable-rtti -frtti %s 2>&1 | FileCheck -check-prefix=NO-ERROR %s --allow-empty
-// RUN: %clang -c -Xclang -fexperimental-omit-vtable-rtti -Xclang -fno-experimental-omit-vtable-rtti -frtti %s 2>&1 | FileCheck -check-prefix=NO-ERROR %s --allow-empty
-
-// ERROR: -fexperimental-omit-vtable-rtti call only be used with -fno-rtti
-// NO-ERROR-NOT: -fexperimental-omit-vtable-rtti call only be used with -fno-rtti

>From ed36b2450feb6e017b960bdb74b55d4d53de08f2 Mon Sep 17 00:00:00 2001
From: daisy202309 <144047963+daisy202309 at users.noreply.github.com>
Date: Thu, 14 Sep 2023 12:10:16 +0800
Subject: [PATCH 17/86] [AArch64][CodeGen] Fix wrong operand order when
 creating vcmla intrinsic (#65278)

Co-authored-by: lizhijin <lizhijin3 at huawei.com>
---
 .../Target/AArch64/AArch64ISelLowering.cpp    |  2 +-
 ...-deinterleaving-add-mull-fixed-contract.ll | 48 ++++++++--------
 ...plex-deinterleaving-add-mull-fixed-fast.ll | 56 +++++++++----------
 .../AArch64/complex-deinterleaving-f16-mul.ll | 32 +++++------
 .../AArch64/complex-deinterleaving-f32-mul.ll | 32 +++++------
 .../AArch64/complex-deinterleaving-f64-mul.ll | 28 +++++-----
 .../complex-deinterleaving-mixed-cases.ll     | 56 +++++++++----------
 .../complex-deinterleaving-multiuses.ll       | 46 +++++++--------
 .../complex-deinterleaving-reductions.ll      | 32 +++++------
 .../AArch64/complex-deinterleaving-splat.ll   | 32 +++++------
 .../complex-deinterleaving-uniform-cases.ll   | 16 +++---
 11 files changed, 190 insertions(+), 190 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index c65c52e39201ac6..fbadda1a8fd446d 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -26216,7 +26216,7 @@ Value *AArch64TargetLowering::createComplexDeinterleavingIR(
 
 
     return B.CreateIntrinsic(IdMap[(int)Rotation], Ty,
-                             {Accumulator, InputB, InputA});
+                             {Accumulator, InputA, InputB});
   }
 
   if (OperationType == ComplexDeinterleavingOperation::CAdd) {
diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-add-mull-fixed-contract.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-add-mull-fixed-contract.ll
index c684a18a7e0773c..09672d1be216136 100644
--- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-add-mull-fixed-contract.ll
+++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-add-mull-fixed-contract.ll
@@ -48,14 +48,14 @@ define <4 x double> @mul_add_mull(<4 x double> %a, <4 x double> %b, <4 x double>
 ; CHECK-NEXT:    movi v17.2d, #0000000000000000
 ; CHECK-NEXT:    movi v18.2d, #0000000000000000
 ; CHECK-NEXT:    movi v19.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v16.2d, v0.2d, v2.2d, #0
-; CHECK-NEXT:    fcmla v18.2d, v1.2d, v3.2d, #0
-; CHECK-NEXT:    fcmla v17.2d, v5.2d, v7.2d, #0
-; CHECK-NEXT:    fcmla v19.2d, v4.2d, v6.2d, #0
-; CHECK-NEXT:    fcmla v16.2d, v0.2d, v2.2d, #90
-; CHECK-NEXT:    fcmla v18.2d, v1.2d, v3.2d, #90
-; CHECK-NEXT:    fcmla v17.2d, v5.2d, v7.2d, #90
-; CHECK-NEXT:    fcmla v19.2d, v4.2d, v6.2d, #90
+; CHECK-NEXT:    fcmla v16.2d, v2.2d, v0.2d, #0
+; CHECK-NEXT:    fcmla v18.2d, v3.2d, v1.2d, #0
+; CHECK-NEXT:    fcmla v17.2d, v7.2d, v5.2d, #0
+; CHECK-NEXT:    fcmla v19.2d, v6.2d, v4.2d, #0
+; CHECK-NEXT:    fcmla v16.2d, v2.2d, v0.2d, #90
+; CHECK-NEXT:    fcmla v18.2d, v3.2d, v1.2d, #90
+; CHECK-NEXT:    fcmla v17.2d, v7.2d, v5.2d, #90
+; CHECK-NEXT:    fcmla v19.2d, v6.2d, v4.2d, #90
 ; CHECK-NEXT:    fadd v1.2d, v18.2d, v17.2d
 ; CHECK-NEXT:    fadd v0.2d, v16.2d, v19.2d
 ; CHECK-NEXT:    ret
@@ -94,14 +94,14 @@ define <4 x double> @mul_sub_mull(<4 x double> %a, <4 x double> %b, <4 x double>
 ; CHECK-NEXT:    movi v17.2d, #0000000000000000
 ; CHECK-NEXT:    movi v18.2d, #0000000000000000
 ; CHECK-NEXT:    movi v19.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v16.2d, v0.2d, v2.2d, #0
-; CHECK-NEXT:    fcmla v18.2d, v1.2d, v3.2d, #0
-; CHECK-NEXT:    fcmla v17.2d, v5.2d, v7.2d, #0
-; CHECK-NEXT:    fcmla v19.2d, v4.2d, v6.2d, #0
-; CHECK-NEXT:    fcmla v16.2d, v0.2d, v2.2d, #90
-; CHECK-NEXT:    fcmla v18.2d, v1.2d, v3.2d, #90
-; CHECK-NEXT:    fcmla v17.2d, v5.2d, v7.2d, #90
-; CHECK-NEXT:    fcmla v19.2d, v4.2d, v6.2d, #90
+; CHECK-NEXT:    fcmla v16.2d, v2.2d, v0.2d, #0
+; CHECK-NEXT:    fcmla v18.2d, v3.2d, v1.2d, #0
+; CHECK-NEXT:    fcmla v17.2d, v7.2d, v5.2d, #0
+; CHECK-NEXT:    fcmla v19.2d, v6.2d, v4.2d, #0
+; CHECK-NEXT:    fcmla v16.2d, v2.2d, v0.2d, #90
+; CHECK-NEXT:    fcmla v18.2d, v3.2d, v1.2d, #90
+; CHECK-NEXT:    fcmla v17.2d, v7.2d, v5.2d, #90
+; CHECK-NEXT:    fcmla v19.2d, v6.2d, v4.2d, #90
 ; CHECK-NEXT:    fsub v1.2d, v18.2d, v17.2d
 ; CHECK-NEXT:    fsub v0.2d, v16.2d, v19.2d
 ; CHECK-NEXT:    ret
@@ -140,14 +140,14 @@ define <4 x double> @mul_conj_mull(<4 x double> %a, <4 x double> %b, <4 x double
 ; CHECK-NEXT:    movi v17.2d, #0000000000000000
 ; CHECK-NEXT:    movi v18.2d, #0000000000000000
 ; CHECK-NEXT:    movi v19.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v16.2d, v0.2d, v2.2d, #0
-; CHECK-NEXT:    fcmla v18.2d, v1.2d, v3.2d, #0
-; CHECK-NEXT:    fcmla v17.2d, v7.2d, v5.2d, #0
-; CHECK-NEXT:    fcmla v19.2d, v6.2d, v4.2d, #0
-; CHECK-NEXT:    fcmla v16.2d, v0.2d, v2.2d, #90
-; CHECK-NEXT:    fcmla v18.2d, v1.2d, v3.2d, #90
-; CHECK-NEXT:    fcmla v17.2d, v7.2d, v5.2d, #270
-; CHECK-NEXT:    fcmla v19.2d, v6.2d, v4.2d, #270
+; CHECK-NEXT:    fcmla v16.2d, v2.2d, v0.2d, #0
+; CHECK-NEXT:    fcmla v18.2d, v3.2d, v1.2d, #0
+; CHECK-NEXT:    fcmla v17.2d, v5.2d, v7.2d, #0
+; CHECK-NEXT:    fcmla v19.2d, v4.2d, v6.2d, #0
+; CHECK-NEXT:    fcmla v16.2d, v2.2d, v0.2d, #90
+; CHECK-NEXT:    fcmla v18.2d, v3.2d, v1.2d, #90
+; CHECK-NEXT:    fcmla v17.2d, v5.2d, v7.2d, #270
+; CHECK-NEXT:    fcmla v19.2d, v4.2d, v6.2d, #270
 ; CHECK-NEXT:    fadd v1.2d, v18.2d, v17.2d
 ; CHECK-NEXT:    fadd v0.2d, v16.2d, v19.2d
 ; CHECK-NEXT:    ret
diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-add-mull-fixed-fast.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-add-mull-fixed-fast.ll
index 9b6a9e7adf796ff..7692b1cf0aaae1f 100644
--- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-add-mull-fixed-fast.ll
+++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-add-mull-fixed-fast.ll
@@ -7,10 +7,10 @@ target triple = "aarch64"
 define <4 x double> @mull_add(<4 x double> %a, <4 x double> %b, <4 x double> %c) {
 ; CHECK-LABEL: mull_add:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    fcmla v4.2d, v2.2d, v0.2d, #0
-; CHECK-NEXT:    fcmla v5.2d, v3.2d, v1.2d, #0
-; CHECK-NEXT:    fcmla v4.2d, v2.2d, v0.2d, #90
-; CHECK-NEXT:    fcmla v5.2d, v3.2d, v1.2d, #90
+; CHECK-NEXT:    fcmla v4.2d, v0.2d, v2.2d, #0
+; CHECK-NEXT:    fcmla v5.2d, v1.2d, v3.2d, #0
+; CHECK-NEXT:    fcmla v4.2d, v0.2d, v2.2d, #90
+; CHECK-NEXT:    fcmla v5.2d, v1.2d, v3.2d, #90
 ; CHECK-NEXT:    mov v0.16b, v4.16b
 ; CHECK-NEXT:    mov v1.16b, v5.16b
 ; CHECK-NEXT:    ret
@@ -39,14 +39,14 @@ define <4 x double> @mul_add_mull(<4 x double> %a, <4 x double> %b, <4 x double>
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v16.2d, #0000000000000000
 ; CHECK-NEXT:    movi v17.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v17.2d, v4.2d, v6.2d, #0
-; CHECK-NEXT:    fcmla v16.2d, v5.2d, v7.2d, #0
-; CHECK-NEXT:    fcmla v17.2d, v2.2d, v0.2d, #0
-; CHECK-NEXT:    fcmla v16.2d, v3.2d, v1.2d, #0
-; CHECK-NEXT:    fcmla v17.2d, v4.2d, v6.2d, #90
-; CHECK-NEXT:    fcmla v16.2d, v5.2d, v7.2d, #90
-; CHECK-NEXT:    fcmla v17.2d, v2.2d, v0.2d, #90
-; CHECK-NEXT:    fcmla v16.2d, v3.2d, v1.2d, #90
+; CHECK-NEXT:    fcmla v17.2d, v6.2d, v4.2d, #0
+; CHECK-NEXT:    fcmla v16.2d, v7.2d, v5.2d, #0
+; CHECK-NEXT:    fcmla v17.2d, v0.2d, v2.2d, #0
+; CHECK-NEXT:    fcmla v16.2d, v1.2d, v3.2d, #0
+; CHECK-NEXT:    fcmla v17.2d, v6.2d, v4.2d, #90
+; CHECK-NEXT:    fcmla v16.2d, v7.2d, v5.2d, #90
+; CHECK-NEXT:    fcmla v17.2d, v0.2d, v2.2d, #90
+; CHECK-NEXT:    fcmla v16.2d, v1.2d, v3.2d, #90
 ; CHECK-NEXT:    mov v0.16b, v17.16b
 ; CHECK-NEXT:    mov v1.16b, v16.16b
 ; CHECK-NEXT:    ret
@@ -83,14 +83,14 @@ define <4 x double> @mul_sub_mull(<4 x double> %a, <4 x double> %b, <4 x double>
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v16.2d, #0000000000000000
 ; CHECK-NEXT:    movi v17.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v17.2d, v4.2d, v6.2d, #270
-; CHECK-NEXT:    fcmla v16.2d, v5.2d, v7.2d, #270
-; CHECK-NEXT:    fcmla v17.2d, v2.2d, v0.2d, #0
-; CHECK-NEXT:    fcmla v16.2d, v3.2d, v1.2d, #0
-; CHECK-NEXT:    fcmla v17.2d, v4.2d, v6.2d, #180
-; CHECK-NEXT:    fcmla v16.2d, v5.2d, v7.2d, #180
-; CHECK-NEXT:    fcmla v17.2d, v2.2d, v0.2d, #90
-; CHECK-NEXT:    fcmla v16.2d, v3.2d, v1.2d, #90
+; CHECK-NEXT:    fcmla v17.2d, v6.2d, v4.2d, #270
+; CHECK-NEXT:    fcmla v16.2d, v7.2d, v5.2d, #270
+; CHECK-NEXT:    fcmla v17.2d, v0.2d, v2.2d, #0
+; CHECK-NEXT:    fcmla v16.2d, v1.2d, v3.2d, #0
+; CHECK-NEXT:    fcmla v17.2d, v6.2d, v4.2d, #180
+; CHECK-NEXT:    fcmla v16.2d, v7.2d, v5.2d, #180
+; CHECK-NEXT:    fcmla v17.2d, v0.2d, v2.2d, #90
+; CHECK-NEXT:    fcmla v16.2d, v1.2d, v3.2d, #90
 ; CHECK-NEXT:    mov v0.16b, v17.16b
 ; CHECK-NEXT:    mov v1.16b, v16.16b
 ; CHECK-NEXT:    ret
@@ -127,14 +127,14 @@ define <4 x double> @mul_conj_mull(<4 x double> %a, <4 x double> %b, <4 x double
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v16.2d, #0000000000000000
 ; CHECK-NEXT:    movi v17.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v17.2d, v2.2d, v0.2d, #0
-; CHECK-NEXT:    fcmla v16.2d, v3.2d, v1.2d, #0
-; CHECK-NEXT:    fcmla v17.2d, v2.2d, v0.2d, #90
-; CHECK-NEXT:    fcmla v16.2d, v3.2d, v1.2d, #90
-; CHECK-NEXT:    fcmla v17.2d, v6.2d, v4.2d, #0
-; CHECK-NEXT:    fcmla v16.2d, v7.2d, v5.2d, #0
-; CHECK-NEXT:    fcmla v17.2d, v6.2d, v4.2d, #270
-; CHECK-NEXT:    fcmla v16.2d, v7.2d, v5.2d, #270
+; CHECK-NEXT:    fcmla v17.2d, v0.2d, v2.2d, #0
+; CHECK-NEXT:    fcmla v16.2d, v1.2d, v3.2d, #0
+; CHECK-NEXT:    fcmla v17.2d, v0.2d, v2.2d, #90
+; CHECK-NEXT:    fcmla v16.2d, v1.2d, v3.2d, #90
+; CHECK-NEXT:    fcmla v17.2d, v4.2d, v6.2d, #0
+; CHECK-NEXT:    fcmla v16.2d, v5.2d, v7.2d, #0
+; CHECK-NEXT:    fcmla v17.2d, v4.2d, v6.2d, #270
+; CHECK-NEXT:    fcmla v16.2d, v5.2d, v7.2d, #270
 ; CHECK-NEXT:    mov v0.16b, v17.16b
 ; CHECK-NEXT:    mov v1.16b, v16.16b
 ; CHECK-NEXT:    ret
diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-f16-mul.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-f16-mul.ll
index 40433e2e076aa74..fbe913e5472cc23 100644
--- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-f16-mul.ll
+++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-f16-mul.ll
@@ -37,8 +37,8 @@ define <4 x half> @complex_mul_v4f16(<4 x half> %a, <4 x half> %b) {
 ; CHECK-LABEL: complex_mul_v4f16:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi d2, #0000000000000000
-; CHECK-NEXT:    fcmla v2.4h, v0.4h, v1.4h, #0
-; CHECK-NEXT:    fcmla v2.4h, v0.4h, v1.4h, #90
+; CHECK-NEXT:    fcmla v2.4h, v1.4h, v0.4h, #0
+; CHECK-NEXT:    fcmla v2.4h, v1.4h, v0.4h, #90
 ; CHECK-NEXT:    fmov d0, d2
 ; CHECK-NEXT:    ret
 entry:
@@ -61,8 +61,8 @@ define <8 x half> @complex_mul_v8f16(<8 x half> %a, <8 x half> %b) {
 ; CHECK-LABEL: complex_mul_v8f16:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v2.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v2.8h, v0.8h, v1.8h, #0
-; CHECK-NEXT:    fcmla v2.8h, v0.8h, v1.8h, #90
+; CHECK-NEXT:    fcmla v2.8h, v1.8h, v0.8h, #0
+; CHECK-NEXT:    fcmla v2.8h, v1.8h, v0.8h, #90
 ; CHECK-NEXT:    mov v0.16b, v2.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -86,10 +86,10 @@ define <16 x half> @complex_mul_v16f16(<16 x half> %a, <16 x half> %b) {
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v4.2d, #0000000000000000
 ; CHECK-NEXT:    movi v5.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v5.8h, v0.8h, v2.8h, #0
-; CHECK-NEXT:    fcmla v4.8h, v1.8h, v3.8h, #0
-; CHECK-NEXT:    fcmla v5.8h, v0.8h, v2.8h, #90
-; CHECK-NEXT:    fcmla v4.8h, v1.8h, v3.8h, #90
+; CHECK-NEXT:    fcmla v5.8h, v2.8h, v0.8h, #0
+; CHECK-NEXT:    fcmla v4.8h, v3.8h, v1.8h, #0
+; CHECK-NEXT:    fcmla v5.8h, v2.8h, v0.8h, #90
+; CHECK-NEXT:    fcmla v4.8h, v3.8h, v1.8h, #90
 ; CHECK-NEXT:    mov v0.16b, v5.16b
 ; CHECK-NEXT:    mov v1.16b, v4.16b
 ; CHECK-NEXT:    ret
@@ -116,14 +116,14 @@ define <32 x half> @complex_mul_v32f16(<32 x half> %a, <32 x half> %b) {
 ; CHECK-NEXT:    movi v17.2d, #0000000000000000
 ; CHECK-NEXT:    movi v18.2d, #0000000000000000
 ; CHECK-NEXT:    movi v19.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v16.8h, v0.8h, v4.8h, #0
-; CHECK-NEXT:    fcmla v18.8h, v1.8h, v5.8h, #0
-; CHECK-NEXT:    fcmla v17.8h, v3.8h, v7.8h, #0
-; CHECK-NEXT:    fcmla v19.8h, v2.8h, v6.8h, #0
-; CHECK-NEXT:    fcmla v16.8h, v0.8h, v4.8h, #90
-; CHECK-NEXT:    fcmla v18.8h, v1.8h, v5.8h, #90
-; CHECK-NEXT:    fcmla v17.8h, v3.8h, v7.8h, #90
-; CHECK-NEXT:    fcmla v19.8h, v2.8h, v6.8h, #90
+; CHECK-NEXT:    fcmla v16.8h, v4.8h, v0.8h, #0
+; CHECK-NEXT:    fcmla v18.8h, v5.8h, v1.8h, #0
+; CHECK-NEXT:    fcmla v17.8h, v7.8h, v3.8h, #0
+; CHECK-NEXT:    fcmla v19.8h, v6.8h, v2.8h, #0
+; CHECK-NEXT:    fcmla v16.8h, v4.8h, v0.8h, #90
+; CHECK-NEXT:    fcmla v18.8h, v5.8h, v1.8h, #90
+; CHECK-NEXT:    fcmla v17.8h, v7.8h, v3.8h, #90
+; CHECK-NEXT:    fcmla v19.8h, v6.8h, v2.8h, #90
 ; CHECK-NEXT:    mov v0.16b, v16.16b
 ; CHECK-NEXT:    mov v1.16b, v18.16b
 ; CHECK-NEXT:    mov v3.16b, v17.16b
diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-f32-mul.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-f32-mul.ll
index 05f07f6fd1c2c89..5f30d9642ce8b00 100644
--- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-f32-mul.ll
+++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-f32-mul.ll
@@ -8,8 +8,8 @@ define <2 x float> @complex_mul_v2f32(<2 x float> %a, <2 x float> %b) {
 ; CHECK-LABEL: complex_mul_v2f32:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi d2, #0000000000000000
-; CHECK-NEXT:    fcmla v2.2s, v0.2s, v1.2s, #0
-; CHECK-NEXT:    fcmla v2.2s, v0.2s, v1.2s, #90
+; CHECK-NEXT:    fcmla v2.2s, v1.2s, v0.2s, #0
+; CHECK-NEXT:    fcmla v2.2s, v1.2s, v0.2s, #90
 ; CHECK-NEXT:    fmov d0, d2
 ; CHECK-NEXT:    ret
 entry:
@@ -32,8 +32,8 @@ define <4 x float> @complex_mul_v4f32(<4 x float> %a, <4 x float> %b) {
 ; CHECK-LABEL: complex_mul_v4f32:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v2.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v2.4s, v0.4s, v1.4s, #0
-; CHECK-NEXT:    fcmla v2.4s, v0.4s, v1.4s, #90
+; CHECK-NEXT:    fcmla v2.4s, v1.4s, v0.4s, #0
+; CHECK-NEXT:    fcmla v2.4s, v1.4s, v0.4s, #90
 ; CHECK-NEXT:    mov v0.16b, v2.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -57,10 +57,10 @@ define <8 x float> @complex_mul_v8f32(<8 x float> %a, <8 x float> %b) {
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v4.2d, #0000000000000000
 ; CHECK-NEXT:    movi v5.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v5.4s, v0.4s, v2.4s, #0
-; CHECK-NEXT:    fcmla v4.4s, v1.4s, v3.4s, #0
-; CHECK-NEXT:    fcmla v5.4s, v0.4s, v2.4s, #90
-; CHECK-NEXT:    fcmla v4.4s, v1.4s, v3.4s, #90
+; CHECK-NEXT:    fcmla v5.4s, v2.4s, v0.4s, #0
+; CHECK-NEXT:    fcmla v4.4s, v3.4s, v1.4s, #0
+; CHECK-NEXT:    fcmla v5.4s, v2.4s, v0.4s, #90
+; CHECK-NEXT:    fcmla v4.4s, v3.4s, v1.4s, #90
 ; CHECK-NEXT:    mov v0.16b, v5.16b
 ; CHECK-NEXT:    mov v1.16b, v4.16b
 ; CHECK-NEXT:    ret
@@ -87,14 +87,14 @@ define <16 x float> @complex_mul_v16f32(<16 x float> %a, <16 x float> %b) {
 ; CHECK-NEXT:    movi v17.2d, #0000000000000000
 ; CHECK-NEXT:    movi v18.2d, #0000000000000000
 ; CHECK-NEXT:    movi v19.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v16.4s, v0.4s, v4.4s, #0
-; CHECK-NEXT:    fcmla v18.4s, v1.4s, v5.4s, #0
-; CHECK-NEXT:    fcmla v17.4s, v3.4s, v7.4s, #0
-; CHECK-NEXT:    fcmla v19.4s, v2.4s, v6.4s, #0
-; CHECK-NEXT:    fcmla v16.4s, v0.4s, v4.4s, #90
-; CHECK-NEXT:    fcmla v18.4s, v1.4s, v5.4s, #90
-; CHECK-NEXT:    fcmla v17.4s, v3.4s, v7.4s, #90
-; CHECK-NEXT:    fcmla v19.4s, v2.4s, v6.4s, #90
+; CHECK-NEXT:    fcmla v16.4s, v4.4s, v0.4s, #0
+; CHECK-NEXT:    fcmla v18.4s, v5.4s, v1.4s, #0
+; CHECK-NEXT:    fcmla v17.4s, v7.4s, v3.4s, #0
+; CHECK-NEXT:    fcmla v19.4s, v6.4s, v2.4s, #0
+; CHECK-NEXT:    fcmla v16.4s, v4.4s, v0.4s, #90
+; CHECK-NEXT:    fcmla v18.4s, v5.4s, v1.4s, #90
+; CHECK-NEXT:    fcmla v17.4s, v7.4s, v3.4s, #90
+; CHECK-NEXT:    fcmla v19.4s, v6.4s, v2.4s, #90
 ; CHECK-NEXT:    mov v0.16b, v16.16b
 ; CHECK-NEXT:    mov v1.16b, v18.16b
 ; CHECK-NEXT:    mov v3.16b, v17.16b
diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-f64-mul.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-f64-mul.ll
index 6df59951e2143c3..6d7b156c3b64c94 100644
--- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-f64-mul.ll
+++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-f64-mul.ll
@@ -8,8 +8,8 @@ define <2 x double> @complex_mul_v2f64(<2 x double> %a, <2 x double> %b) {
 ; CHECK-LABEL: complex_mul_v2f64:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v2.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v2.2d, v0.2d, v1.2d, #0
-; CHECK-NEXT:    fcmla v2.2d, v0.2d, v1.2d, #90
+; CHECK-NEXT:    fcmla v2.2d, v1.2d, v0.2d, #0
+; CHECK-NEXT:    fcmla v2.2d, v1.2d, v0.2d, #90
 ; CHECK-NEXT:    mov v0.16b, v2.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -33,10 +33,10 @@ define <4 x double> @complex_mul_v4f64(<4 x double> %a, <4 x double> %b) {
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v4.2d, #0000000000000000
 ; CHECK-NEXT:    movi v5.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v5.2d, v0.2d, v2.2d, #0
-; CHECK-NEXT:    fcmla v4.2d, v1.2d, v3.2d, #0
-; CHECK-NEXT:    fcmla v5.2d, v0.2d, v2.2d, #90
-; CHECK-NEXT:    fcmla v4.2d, v1.2d, v3.2d, #90
+; CHECK-NEXT:    fcmla v5.2d, v2.2d, v0.2d, #0
+; CHECK-NEXT:    fcmla v4.2d, v3.2d, v1.2d, #0
+; CHECK-NEXT:    fcmla v5.2d, v2.2d, v0.2d, #90
+; CHECK-NEXT:    fcmla v4.2d, v3.2d, v1.2d, #90
 ; CHECK-NEXT:    mov v0.16b, v5.16b
 ; CHECK-NEXT:    mov v1.16b, v4.16b
 ; CHECK-NEXT:    ret
@@ -63,14 +63,14 @@ define <8 x double> @complex_mul_v8f64(<8 x double> %a, <8 x double> %b) {
 ; CHECK-NEXT:    movi v17.2d, #0000000000000000
 ; CHECK-NEXT:    movi v18.2d, #0000000000000000
 ; CHECK-NEXT:    movi v19.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v16.2d, v0.2d, v4.2d, #0
-; CHECK-NEXT:    fcmla v18.2d, v1.2d, v5.2d, #0
-; CHECK-NEXT:    fcmla v17.2d, v3.2d, v7.2d, #0
-; CHECK-NEXT:    fcmla v19.2d, v2.2d, v6.2d, #0
-; CHECK-NEXT:    fcmla v16.2d, v0.2d, v4.2d, #90
-; CHECK-NEXT:    fcmla v18.2d, v1.2d, v5.2d, #90
-; CHECK-NEXT:    fcmla v17.2d, v3.2d, v7.2d, #90
-; CHECK-NEXT:    fcmla v19.2d, v2.2d, v6.2d, #90
+; CHECK-NEXT:    fcmla v16.2d, v4.2d, v0.2d, #0
+; CHECK-NEXT:    fcmla v18.2d, v5.2d, v1.2d, #0
+; CHECK-NEXT:    fcmla v17.2d, v7.2d, v3.2d, #0
+; CHECK-NEXT:    fcmla v19.2d, v6.2d, v2.2d, #0
+; CHECK-NEXT:    fcmla v16.2d, v4.2d, v0.2d, #90
+; CHECK-NEXT:    fcmla v18.2d, v5.2d, v1.2d, #90
+; CHECK-NEXT:    fcmla v17.2d, v7.2d, v3.2d, #90
+; CHECK-NEXT:    fcmla v19.2d, v6.2d, v2.2d, #90
 ; CHECK-NEXT:    mov v0.16b, v16.16b
 ; CHECK-NEXT:    mov v1.16b, v18.16b
 ; CHECK-NEXT:    mov v3.16b, v17.16b
diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-mixed-cases.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-mixed-cases.ll
index f7837b2367671d8..1ed9cf2db24f729 100644
--- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-mixed-cases.ll
+++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-mixed-cases.ll
@@ -9,10 +9,10 @@ define <4 x float> @mul_mul(<4 x float> %a, <4 x float> %b, <4 x float> %c) {
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v4.2d, #0000000000000000
 ; CHECK-NEXT:    movi v3.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v4.4s, v0.4s, v1.4s, #0
-; CHECK-NEXT:    fcmla v4.4s, v0.4s, v1.4s, #90
-; CHECK-NEXT:    fcmla v3.4s, v4.4s, v2.4s, #0
-; CHECK-NEXT:    fcmla v3.4s, v4.4s, v2.4s, #90
+; CHECK-NEXT:    fcmla v4.4s, v1.4s, v0.4s, #0
+; CHECK-NEXT:    fcmla v4.4s, v1.4s, v0.4s, #90
+; CHECK-NEXT:    fcmla v3.4s, v2.4s, v4.4s, #0
+; CHECK-NEXT:    fcmla v3.4s, v2.4s, v4.4s, #90
 ; CHECK-NEXT:    mov v0.16b, v3.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -130,10 +130,10 @@ define <4 x float> @mul_triangle(<4 x float> %a, <4 x float> %b) {
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v3.2d, #0000000000000000
 ; CHECK-NEXT:    movi v2.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v3.4s, v1.4s, v0.4s, #0
-; CHECK-NEXT:    fcmla v3.4s, v1.4s, v0.4s, #90
-; CHECK-NEXT:    fcmla v2.4s, v0.4s, v3.4s, #0
-; CHECK-NEXT:    fcmla v2.4s, v0.4s, v3.4s, #90
+; CHECK-NEXT:    fcmla v3.4s, v0.4s, v1.4s, #0
+; CHECK-NEXT:    fcmla v3.4s, v0.4s, v1.4s, #90
+; CHECK-NEXT:    fcmla v2.4s, v3.4s, v0.4s, #0
+; CHECK-NEXT:    fcmla v2.4s, v3.4s, v0.4s, #90
 ; CHECK-NEXT:    mov v0.16b, v2.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -166,15 +166,15 @@ define <4 x float> @mul_diamond(<4 x float> %a, <4 x float> %b, <4 x float> %c,
 ; CHECK-NEXT:    movi v4.2d, #0000000000000000
 ; CHECK-NEXT:    movi v5.2d, #0000000000000000
 ; CHECK-NEXT:    movi v6.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v4.4s, v1.4s, v0.4s, #0
-; CHECK-NEXT:    fcmla v6.4s, v2.4s, v0.4s, #0
-; CHECK-NEXT:    fcmla v4.4s, v1.4s, v0.4s, #90
+; CHECK-NEXT:    fcmla v4.4s, v0.4s, v1.4s, #0
+; CHECK-NEXT:    fcmla v6.4s, v0.4s, v2.4s, #0
+; CHECK-NEXT:    fcmla v4.4s, v0.4s, v1.4s, #90
 ; CHECK-NEXT:    movi v1.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v6.4s, v2.4s, v0.4s, #90
-; CHECK-NEXT:    fcmla v5.4s, v4.4s, v3.4s, #0
-; CHECK-NEXT:    fcmla v5.4s, v4.4s, v3.4s, #90
-; CHECK-NEXT:    fcmla v1.4s, v6.4s, v5.4s, #0
-; CHECK-NEXT:    fcmla v1.4s, v6.4s, v5.4s, #90
+; CHECK-NEXT:    fcmla v6.4s, v0.4s, v2.4s, #90
+; CHECK-NEXT:    fcmla v5.4s, v3.4s, v4.4s, #0
+; CHECK-NEXT:    fcmla v5.4s, v3.4s, v4.4s, #90
+; CHECK-NEXT:    fcmla v1.4s, v5.4s, v6.4s, #0
+; CHECK-NEXT:    fcmla v1.4s, v5.4s, v6.4s, #90
 ; CHECK-NEXT:    mov v0.16b, v1.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -220,10 +220,10 @@ define <4 x float> @mul_add90_mul(<4 x float> %a, <4 x float> %b, <4 x float> %c
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v3.2d, #0000000000000000
 ; CHECK-NEXT:    movi v4.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v4.4s, v2.4s, v0.4s, #0
-; CHECK-NEXT:    fcmla v3.4s, v1.4s, v0.4s, #0
-; CHECK-NEXT:    fcmla v4.4s, v2.4s, v0.4s, #90
-; CHECK-NEXT:    fcmla v3.4s, v1.4s, v0.4s, #90
+; CHECK-NEXT:    fcmla v4.4s, v0.4s, v2.4s, #0
+; CHECK-NEXT:    fcmla v3.4s, v0.4s, v1.4s, #0
+; CHECK-NEXT:    fcmla v4.4s, v0.4s, v2.4s, #90
+; CHECK-NEXT:    fcmla v3.4s, v0.4s, v1.4s, #90
 ; CHECK-NEXT:    fcadd v0.4s, v4.4s, v3.4s, #90
 ; CHECK-NEXT:    ret
 entry:
@@ -358,8 +358,8 @@ entry:
 define <4 x float> @mul_addequal(<4 x float> %a, <4 x float> %b, <4 x float> %c) {
 ; CHECK-LABEL: mul_addequal:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    fcmla v2.4s, v0.4s, v1.4s, #0
-; CHECK-NEXT:    fcmla v2.4s, v0.4s, v1.4s, #90
+; CHECK-NEXT:    fcmla v2.4s, v1.4s, v0.4s, #0
+; CHECK-NEXT:    fcmla v2.4s, v1.4s, v0.4s, #90
 ; CHECK-NEXT:    mov v0.16b, v2.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -386,8 +386,8 @@ define <4 x float> @mul_subequal(<4 x float> %a, <4 x float> %b, <4 x float> %c)
 ; CHECK-LABEL: mul_subequal:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v3.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v3.4s, v0.4s, v1.4s, #0
-; CHECK-NEXT:    fcmla v3.4s, v0.4s, v1.4s, #90
+; CHECK-NEXT:    fcmla v3.4s, v1.4s, v0.4s, #0
+; CHECK-NEXT:    fcmla v3.4s, v1.4s, v0.4s, #90
 ; CHECK-NEXT:    fsub v0.4s, v3.4s, v2.4s
 ; CHECK-NEXT:    ret
 entry:
@@ -415,8 +415,8 @@ define <4 x float> @mul_mulequal(<4 x float> %a, <4 x float> %b, <4 x float> %c)
 ; CHECK-LABEL: mul_mulequal:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v3.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v3.4s, v0.4s, v1.4s, #0
-; CHECK-NEXT:    fcmla v3.4s, v0.4s, v1.4s, #90
+; CHECK-NEXT:    fcmla v3.4s, v1.4s, v0.4s, #0
+; CHECK-NEXT:    fcmla v3.4s, v1.4s, v0.4s, #90
 ; CHECK-NEXT:    fmul v0.4s, v3.4s, v2.4s
 ; CHECK-NEXT:    ret
 entry:
@@ -484,8 +484,8 @@ define <4 x float> @mul_negequal(<4 x float> %a, <4 x float> %b) {
 ; CHECK-LABEL: mul_negequal:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v2.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v2.4s, v0.4s, v1.4s, #180
-; CHECK-NEXT:    fcmla v2.4s, v0.4s, v1.4s, #270
+; CHECK-NEXT:    fcmla v2.4s, v1.4s, v0.4s, #180
+; CHECK-NEXT:    fcmla v2.4s, v1.4s, v0.4s, #270
 ; CHECK-NEXT:    mov v0.16b, v2.16b
 ; CHECK-NEXT:    ret
 entry:
diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-multiuses.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-multiuses.ll
index 16dec1af60c1ca0..039025dafa0d6e8 100644
--- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-multiuses.ll
+++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-multiuses.ll
@@ -10,11 +10,11 @@ define <4 x float> @mul_triangle(<4 x float> %a, <4 x float> %b, ptr %p) {
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v3.2d, #0000000000000000
 ; CHECK-NEXT:    movi v2.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v3.4s, v1.4s, v0.4s, #0
-; CHECK-NEXT:    fcmla v3.4s, v1.4s, v0.4s, #90
-; CHECK-NEXT:    fcmla v2.4s, v0.4s, v3.4s, #0
+; CHECK-NEXT:    fcmla v3.4s, v0.4s, v1.4s, #0
+; CHECK-NEXT:    fcmla v3.4s, v0.4s, v1.4s, #90
+; CHECK-NEXT:    fcmla v2.4s, v3.4s, v0.4s, #0
 ; CHECK-NEXT:    str q3, [x0]
-; CHECK-NEXT:    fcmla v2.4s, v0.4s, v3.4s, #90
+; CHECK-NEXT:    fcmla v2.4s, v3.4s, v0.4s, #90
 ; CHECK-NEXT:    mov v0.16b, v2.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -112,10 +112,10 @@ define <4 x float> @multiple_muls_shuffle_external(<4 x float> %a, <4 x float> %
 ; CHECK-NEXT:    movi v0.2d, #0000000000000000
 ; CHECK-NEXT:    fmul v5.2s, v4.2s, v5.2s
 ; CHECK-NEXT:    fmla v17.2s, v1.2s, v4.2s
-; CHECK-NEXT:    fcmla v0.4s, v3.4s, v2.4s, #0
+; CHECK-NEXT:    fcmla v0.4s, v2.4s, v3.4s, #0
 ; CHECK-NEXT:    str d1, [x0]
 ; CHECK-NEXT:    fneg v16.2s, v5.2s
-; CHECK-NEXT:    fcmla v0.4s, v3.4s, v2.4s, #90
+; CHECK-NEXT:    fcmla v0.4s, v2.4s, v3.4s, #90
 ; CHECK-NEXT:    fmla v16.2s, v1.2s, v6.2s
 ; CHECK-NEXT:    st2 { v16.2s, v17.2s }, [x1]
 ; CHECK-NEXT:    ret
@@ -179,8 +179,8 @@ define <4 x float> @multiple_muls_shuffle_external_with_loads(ptr %ptr_a, ptr %p
 ; CHECK-NEXT:    movi v0.2d, #0000000000000000
 ; CHECK-NEXT:    st2 { v2.2s, v3.2s }, [x5]
 ; CHECK-NEXT:    ldr q1, [x3]
-; CHECK-NEXT:    fcmla v0.4s, v1.4s, v5.4s, #0
-; CHECK-NEXT:    fcmla v0.4s, v1.4s, v5.4s, #90
+; CHECK-NEXT:    fcmla v0.4s, v5.4s, v1.4s, #0
+; CHECK-NEXT:    fcmla v0.4s, v5.4s, v1.4s, #90
 ; CHECK-NEXT:    ret
 entry:
   %a = load <4 x float>, ptr %ptr_a
@@ -300,31 +300,31 @@ define void @mul_add_common_mul_add_mul(<4 x double> %a, <4 x double> %b, <4 x d
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v16.2d, #0000000000000000
 ; CHECK-NEXT:    movi v17.2d, #0000000000000000
+; CHECK-NEXT:    ldr q19, [sp, #112]
+; CHECK-NEXT:    ldp q18, q20, [sp, #80]
+; CHECK-NEXT:    ldr q21, [sp, #64]
 ; CHECK-NEXT:    movi v22.2d, #0000000000000000
-; CHECK-NEXT:    ldp q21, q18, [sp, #96]
-; CHECK-NEXT:    ldp q20, q19, [sp, #64]
-; CHECK-NEXT:    fcmla v22.2d, v3.2d, v1.2d, #0
 ; CHECK-NEXT:    fcmla v16.2d, v18.2d, v19.2d, #0
 ; CHECK-NEXT:    fcmla v17.2d, v21.2d, v20.2d, #0
-; CHECK-NEXT:    fcmla v22.2d, v3.2d, v1.2d, #90
-; CHECK-NEXT:    ldr q1, [sp, #48]
-; CHECK-NEXT:    ldr q3, [sp]
+; CHECK-NEXT:    fcmla v22.2d, v1.2d, v3.2d, #0
 ; CHECK-NEXT:    fcmla v16.2d, v18.2d, v19.2d, #90
 ; CHECK-NEXT:    movi v18.2d, #0000000000000000
 ; CHECK-NEXT:    fcmla v17.2d, v21.2d, v20.2d, #90
-; CHECK-NEXT:    fcmla v16.2d, v7.2d, v5.2d, #0
-; CHECK-NEXT:    fcmla v18.2d, v2.2d, v0.2d, #0
-; CHECK-NEXT:    fcmla v17.2d, v6.2d, v4.2d, #0
-; CHECK-NEXT:    fcmla v16.2d, v7.2d, v5.2d, #90
-; CHECK-NEXT:    fcmla v18.2d, v2.2d, v0.2d, #90
-; CHECK-NEXT:    fcmla v17.2d, v6.2d, v4.2d, #90
-; CHECK-NEXT:    ldp q0, q2, [sp, #16]
+; CHECK-NEXT:    fcmla v22.2d, v1.2d, v3.2d, #90
+; CHECK-NEXT:    fcmla v16.2d, v5.2d, v7.2d, #0
+; CHECK-NEXT:    fcmla v18.2d, v0.2d, v2.2d, #0
+; CHECK-NEXT:    fcmla v17.2d, v4.2d, v6.2d, #0
+; CHECK-NEXT:    fcmla v16.2d, v5.2d, v7.2d, #90
+; CHECK-NEXT:    fcmla v18.2d, v0.2d, v2.2d, #90
+; CHECK-NEXT:    fcmla v17.2d, v4.2d, v6.2d, #90
+; CHECK-NEXT:    ldp q3, q0, [sp, #32]
+; CHECK-NEXT:    ldp q2, q1, [sp]
 ; CHECK-NEXT:    fsub v4.2d, v22.2d, v16.2d
-; CHECK-NEXT:    fcmla v16.2d, v0.2d, v1.2d, #0
 ; CHECK-NEXT:    fsub v5.2d, v18.2d, v17.2d
+; CHECK-NEXT:    fcmla v16.2d, v0.2d, v1.2d, #0
 ; CHECK-NEXT:    fcmla v17.2d, v3.2d, v2.2d, #0
-; CHECK-NEXT:    fcmla v16.2d, v0.2d, v1.2d, #90
 ; CHECK-NEXT:    stp q5, q4, [x0]
+; CHECK-NEXT:    fcmla v16.2d, v0.2d, v1.2d, #90
 ; CHECK-NEXT:    fcmla v17.2d, v3.2d, v2.2d, #90
 ; CHECK-NEXT:    stp q17, q16, [x1]
 ; CHECK-NEXT:    ret
diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-reductions.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-reductions.ll
index d245c0a0e4823d0..40fd7a392c83b96 100644
--- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-reductions.ll
+++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-reductions.ll
@@ -25,10 +25,10 @@ define dso_local %"struct.std::complex" @complex_mul_v2f64(ptr %a, ptr %b) {
 ; CHECK-NEXT:    ldp q3, q2, [x9]
 ; CHECK-NEXT:    cmp x8, #1600
 ; CHECK-NEXT:    ldp q5, q4, [x10]
-; CHECK-NEXT:    fcmla v0.2d, v3.2d, v5.2d, #0
-; CHECK-NEXT:    fcmla v1.2d, v2.2d, v4.2d, #0
-; CHECK-NEXT:    fcmla v0.2d, v3.2d, v5.2d, #90
-; CHECK-NEXT:    fcmla v1.2d, v2.2d, v4.2d, #90
+; CHECK-NEXT:    fcmla v0.2d, v5.2d, v3.2d, #0
+; CHECK-NEXT:    fcmla v1.2d, v4.2d, v2.2d, #0
+; CHECK-NEXT:    fcmla v0.2d, v5.2d, v3.2d, #90
+; CHECK-NEXT:    fcmla v1.2d, v4.2d, v2.2d, #90
 ; CHECK-NEXT:    b.ne .LBB0_1
 ; CHECK-NEXT:  // %bb.2: // %middle.block
 ; CHECK-NEXT:    zip2 v2.2d, v0.2d, v1.2d
@@ -92,10 +92,10 @@ define %"struct.std::complex" @complex_mul_nonzero_init_v2f64(ptr %a, ptr %b) {
 ; CHECK-NEXT:    ldp q3, q2, [x9]
 ; CHECK-NEXT:    cmp x8, #1600
 ; CHECK-NEXT:    ldp q5, q4, [x10]
-; CHECK-NEXT:    fcmla v1.2d, v3.2d, v5.2d, #0
-; CHECK-NEXT:    fcmla v0.2d, v2.2d, v4.2d, #0
-; CHECK-NEXT:    fcmla v1.2d, v3.2d, v5.2d, #90
-; CHECK-NEXT:    fcmla v0.2d, v2.2d, v4.2d, #90
+; CHECK-NEXT:    fcmla v1.2d, v5.2d, v3.2d, #0
+; CHECK-NEXT:    fcmla v0.2d, v4.2d, v2.2d, #0
+; CHECK-NEXT:    fcmla v1.2d, v5.2d, v3.2d, #90
+; CHECK-NEXT:    fcmla v0.2d, v4.2d, v2.2d, #90
 ; CHECK-NEXT:    b.ne .LBB1_1
 ; CHECK-NEXT:  // %bb.2: // %middle.block
 ; CHECK-NEXT:    zip2 v2.2d, v1.2d, v0.2d
@@ -159,14 +159,14 @@ define %"struct.std::complex" @complex_mul_v2f64_unrolled(ptr %a, ptr %b) {
 ; CHECK-NEXT:    ldp q7, q6, [x10]
 ; CHECK-NEXT:    ldp q17, q16, [x9, #32]
 ; CHECK-NEXT:    ldp q19, q18, [x10, #32]
-; CHECK-NEXT:    fcmla v1.2d, v5.2d, v7.2d, #0
-; CHECK-NEXT:    fcmla v0.2d, v4.2d, v6.2d, #0
-; CHECK-NEXT:    fcmla v2.2d, v17.2d, v19.2d, #0
-; CHECK-NEXT:    fcmla v3.2d, v16.2d, v18.2d, #0
-; CHECK-NEXT:    fcmla v1.2d, v5.2d, v7.2d, #90
-; CHECK-NEXT:    fcmla v0.2d, v4.2d, v6.2d, #90
-; CHECK-NEXT:    fcmla v2.2d, v17.2d, v19.2d, #90
-; CHECK-NEXT:    fcmla v3.2d, v16.2d, v18.2d, #90
+; CHECK-NEXT:    fcmla v1.2d, v7.2d, v5.2d, #0
+; CHECK-NEXT:    fcmla v0.2d, v6.2d, v4.2d, #0
+; CHECK-NEXT:    fcmla v2.2d, v19.2d, v17.2d, #0
+; CHECK-NEXT:    fcmla v3.2d, v18.2d, v16.2d, #0
+; CHECK-NEXT:    fcmla v1.2d, v7.2d, v5.2d, #90
+; CHECK-NEXT:    fcmla v0.2d, v6.2d, v4.2d, #90
+; CHECK-NEXT:    fcmla v2.2d, v19.2d, v17.2d, #90
+; CHECK-NEXT:    fcmla v3.2d, v18.2d, v16.2d, #90
 ; CHECK-NEXT:    b.ne .LBB2_1
 ; CHECK-NEXT:  // %bb.2: // %middle.block
 ; CHECK-NEXT:    zip2 v4.2d, v2.2d, v3.2d
diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-splat.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-splat.ll
index 0dbc2ecc8b008d7..8de2ac5a140c681 100644
--- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-splat.ll
+++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-splat.ll
@@ -13,16 +13,16 @@ define <4 x double> @complex_mul_const(<4 x double> %a, <4 x double> %b) {
 ; CHECK-NEXT:    movi v5.2d, #0000000000000000
 ; CHECK-NEXT:    adrp x8, .LCPI0_0
 ; CHECK-NEXT:    movi v4.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v6.2d, v3.2d, v1.2d, #0
-; CHECK-NEXT:    fcmla v5.2d, v2.2d, v0.2d, #0
-; CHECK-NEXT:    fcmla v6.2d, v3.2d, v1.2d, #90
+; CHECK-NEXT:    fcmla v6.2d, v1.2d, v3.2d, #0
+; CHECK-NEXT:    fcmla v5.2d, v0.2d, v2.2d, #0
+; CHECK-NEXT:    fcmla v6.2d, v1.2d, v3.2d, #90
 ; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI0_0]
-; CHECK-NEXT:    fcmla v5.2d, v2.2d, v0.2d, #90
+; CHECK-NEXT:    fcmla v5.2d, v0.2d, v2.2d, #90
 ; CHECK-NEXT:    movi v0.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v4.2d, v1.2d, v6.2d, #0
-; CHECK-NEXT:    fcmla v0.2d, v1.2d, v5.2d, #0
-; CHECK-NEXT:    fcmla v4.2d, v1.2d, v6.2d, #90
-; CHECK-NEXT:    fcmla v0.2d, v1.2d, v5.2d, #90
+; CHECK-NEXT:    fcmla v4.2d, v6.2d, v1.2d, #0
+; CHECK-NEXT:    fcmla v0.2d, v5.2d, v1.2d, #0
+; CHECK-NEXT:    fcmla v4.2d, v6.2d, v1.2d, #90
+; CHECK-NEXT:    fcmla v0.2d, v5.2d, v1.2d, #90
 ; CHECK-NEXT:    mov v1.16b, v4.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -58,15 +58,15 @@ define <4 x double> @complex_mul_non_const(<4 x double> %a, <4 x double> %b, [2
 ; CHECK-NEXT:    // kill: def $d4 killed $d4 def $q4
 ; CHECK-NEXT:    mov v4.d[1], v5.d[0]
 ; CHECK-NEXT:    movi v5.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v7.2d, v3.2d, v1.2d, #0
-; CHECK-NEXT:    fcmla v6.2d, v2.2d, v0.2d, #0
-; CHECK-NEXT:    fcmla v7.2d, v3.2d, v1.2d, #90
-; CHECK-NEXT:    fcmla v6.2d, v2.2d, v0.2d, #90
+; CHECK-NEXT:    fcmla v7.2d, v1.2d, v3.2d, #0
+; CHECK-NEXT:    fcmla v6.2d, v0.2d, v2.2d, #0
+; CHECK-NEXT:    fcmla v7.2d, v1.2d, v3.2d, #90
+; CHECK-NEXT:    fcmla v6.2d, v0.2d, v2.2d, #90
 ; CHECK-NEXT:    movi v0.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v5.2d, v4.2d, v7.2d, #0
-; CHECK-NEXT:    fcmla v0.2d, v4.2d, v6.2d, #0
-; CHECK-NEXT:    fcmla v5.2d, v4.2d, v7.2d, #90
-; CHECK-NEXT:    fcmla v0.2d, v4.2d, v6.2d, #90
+; CHECK-NEXT:    fcmla v5.2d, v7.2d, v4.2d, #0
+; CHECK-NEXT:    fcmla v0.2d, v6.2d, v4.2d, #0
+; CHECK-NEXT:    fcmla v5.2d, v7.2d, v4.2d, #90
+; CHECK-NEXT:    fcmla v0.2d, v6.2d, v4.2d, #90
 ; CHECK-NEXT:    mov v1.16b, v5.16b
 ; CHECK-NEXT:    ret
 entry:
diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-uniform-cases.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-uniform-cases.ll
index 81a8631a1691b56..2cbc8ed3192de48 100644
--- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-uniform-cases.ll
+++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-uniform-cases.ll
@@ -8,8 +8,8 @@ define <4 x float> @simple_mul(<4 x float> %a, <4 x float> %b) {
 ; CHECK-LABEL: simple_mul:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v2.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v2.4s, v0.4s, v1.4s, #0
-; CHECK-NEXT:    fcmla v2.4s, v0.4s, v1.4s, #90
+; CHECK-NEXT:    fcmla v2.4s, v1.4s, v0.4s, #0
+; CHECK-NEXT:    fcmla v2.4s, v1.4s, v0.4s, #90
 ; CHECK-NEXT:    mov v0.16b, v2.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -65,10 +65,10 @@ define <4 x float> @three_way_mul(<4 x float> %a, <4 x float> %b, <4 x float> %c
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v4.2d, #0000000000000000
 ; CHECK-NEXT:    movi v3.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v4.4s, v1.4s, v0.4s, #0
-; CHECK-NEXT:    fcmla v4.4s, v1.4s, v0.4s, #90
-; CHECK-NEXT:    fcmla v3.4s, v2.4s, v4.4s, #0
-; CHECK-NEXT:    fcmla v3.4s, v2.4s, v4.4s, #90
+; CHECK-NEXT:    fcmla v4.4s, v0.4s, v1.4s, #0
+; CHECK-NEXT:    fcmla v4.4s, v0.4s, v1.4s, #90
+; CHECK-NEXT:    fcmla v3.4s, v4.4s, v2.4s, #0
+; CHECK-NEXT:    fcmla v3.4s, v4.4s, v2.4s, #90
 ; CHECK-NEXT:    mov v0.16b, v3.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -177,8 +177,8 @@ define <4 x float> @mul_mul_with_fneg(<4 x float> %a, <4 x float> %b) {
 ; CHECK-LABEL: mul_mul_with_fneg:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    movi v2.2d, #0000000000000000
-; CHECK-NEXT:    fcmla v2.4s, v1.4s, v0.4s, #270
-; CHECK-NEXT:    fcmla v2.4s, v1.4s, v0.4s, #180
+; CHECK-NEXT:    fcmla v2.4s, v0.4s, v1.4s, #270
+; CHECK-NEXT:    fcmla v2.4s, v0.4s, v1.4s, #180
 ; CHECK-NEXT:    mov v0.16b, v2.16b
 ; CHECK-NEXT:    ret
 entry:

>From 072b9a7c235af934904c3a78535b374ea47184e3 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Wed, 13 Sep 2023 21:24:30 -0700
Subject: [PATCH 18/86] [lldb] Improve comments in Editline.h (NFC)

Fix typos, add missing periods and reflow comments in the Editline
header.
---
 lldb/include/lldb/Host/Editline.h | 67 +++++++++++++------------------
 1 file changed, 29 insertions(+), 38 deletions(-)

diff --git a/lldb/include/lldb/Host/Editline.h b/lldb/include/lldb/Host/Editline.h
index ba289688aa7a95e..3698588fbea516b 100644
--- a/lldb/include/lldb/Host/Editline.h
+++ b/lldb/include/lldb/Host/Editline.h
@@ -103,36 +103,36 @@ using SuggestionCallbackType =
 using CompleteCallbackType = llvm::unique_function<void(CompletionRequest &)>;
 
 /// Status used to decide when and how to start editing another line in
-/// multi-line sessions
+/// multi-line sessions.
 enum class EditorStatus {
 
-  /// The default state proceeds to edit the current line
+  /// The default state proceeds to edit the current line.
   Editing,
 
-  /// Editing complete, returns the complete set of edited lines
+  /// Editing complete, returns the complete set of edited lines.
   Complete,
 
-  /// End of input reported
+  /// End of input reported.
   EndOfInput,
 
-  /// Editing interrupted
+  /// Editing interrupted.
   Interrupted
 };
 
-/// Established locations that can be easily moved among with MoveCursor
+/// Established locations that can be easily moved among with MoveCursor.
 enum class CursorLocation {
-  /// The start of the first line in a multi-line edit session
+  /// The start of the first line in a multi-line edit session.
   BlockStart,
 
-  /// The start of the current line in a multi-line edit session
+  /// The start of the current line in a multi-line edit session.
   EditingPrompt,
 
   /// The location of the cursor on the current line in a multi-line edit
-  /// session
+  /// session.
   EditingCursor,
 
   /// The location immediately after the last character in a multi-line edit
-  /// session
+  /// session.
   BlockEnd
 };
 
@@ -149,8 +149,7 @@ enum class HistoryOperation {
 using namespace line_editor;
 
 /// Instances of Editline provide an abstraction over libedit's EditLine
-/// facility.  Both
-/// single- and multi-line editing are supported.
+/// facility.  Both single- and multi-line editing are supported.
 class Editline {
 public:
   Editline(const char *editor_name, FILE *input_file, FILE *output_file,
@@ -168,23 +167,22 @@ class Editline {
   void SetPrompt(const char *prompt);
 
   /// Sets an alternate string to be used as a prompt for the second line and
-  /// beyond in multi-line
-  /// editing scenarios.
+  /// beyond in multi-line editing scenarios.
   void SetContinuationPrompt(const char *continuation_prompt);
 
-  /// Call when the terminal size changes
+  /// Call when the terminal size changes.
   void TerminalSizeChanged();
 
-  /// Returns the prompt established by SetPrompt()
+  /// Returns the prompt established by SetPrompt.
   const char *GetPrompt();
 
-  /// Returns the index of the line currently being edited
+  /// Returns the index of the line currently being edited.
   uint32_t GetCurrentLine();
 
-  /// Interrupt the current edit as if ^C was pressed
+  /// Interrupt the current edit as if ^C was pressed.
   bool Interrupt();
 
-  /// Cancel this edit and oblitarate all trace of it
+  /// Cancel this edit and obliterate all trace of it.
   bool Cancel();
 
   /// Register a callback for autosuggestion.
@@ -240,19 +238,16 @@ class Editline {
 
 private:
   /// Sets the lowest line number for multi-line editing sessions.  A value of
-  /// zero suppresses
-  /// line number printing in the prompt.
+  /// zero suppresses line number printing in the prompt.
   void SetBaseLineNumber(int line_number);
 
   /// Returns the complete prompt by combining the prompt or continuation prompt
-  /// with line numbers
-  /// as appropriate.  The line index is a zero-based index into the current
-  /// multi-line session.
+  /// with line numbers as appropriate.  The line index is a zero-based index
+  /// into the current multi-line session.
   std::string PromptForIndex(int line_index);
 
   /// Sets the current line index between line edits to allow free movement
-  /// between lines.  Updates
-  /// the prompt to match.
+  /// between lines.  Updates the prompt to match.
   void SetCurrentLine(int line_index);
 
   /// Determines the width of the prompt in characters.  The width is guaranteed
@@ -260,8 +255,7 @@ class Editline {
   size_t GetPromptWidth();
 
   /// Returns true if the underlying EditLine session's keybindings are
-  /// Emacs-based, or false if
-  /// they are VI-based.
+  /// Emacs-based, or false if they are VI-based.
   bool IsEmacs();
 
   /// Returns true if the current EditLine buffer contains nothing but spaces,
@@ -272,24 +266,21 @@ class Editline {
   int GetLineIndexForLocation(CursorLocation location, int cursor_row);
 
   /// Move the cursor from one well-established location to another using
-  /// relative line positioning
-  /// and absolute column positioning.
+  /// relative line positioning and absolute column positioning.
   void MoveCursor(CursorLocation from, CursorLocation to);
 
   /// Clear from cursor position to bottom of screen and print input lines
-  /// including prompts, optionally
-  /// starting from a specific line.  Lines are drawn with an extra space at the
-  /// end to reserve room for
-  /// the rightmost cursor position.
+  /// including prompts, optionally starting from a specific line.  Lines are
+  /// drawn with an extra space at the end to reserve room for the rightmost
+  /// cursor position.
   void DisplayInput(int firstIndex = 0);
 
   /// Counts the number of rows a given line of content will end up occupying,
-  /// taking into account both
-  /// the preceding prompt and a single trailing space occupied by a cursor when
-  /// at the end of the line.
+  /// taking into account both the preceding prompt and a single trailing space
+  /// occupied by a cursor when at the end of the line.
   int CountRowsForLine(const EditLineStringType &content);
 
-  /// Save the line currently being edited
+  /// Save the line currently being edited.
   void SaveEditedLine();
 
   /// Replaces the current multi-line session with the next entry from history.

>From fa0b541552540a049428afd606f7c9560477bdfb Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Wed, 13 Sep 2023 21:40:57 -0700
Subject: [PATCH 19/86] Fix PR description HTML escaping, the surrounding
 `<pre>` tag shouldn't be escaped (#66322)

---
 llvm/utils/git/github-automation.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/utils/git/github-automation.py b/llvm/utils/git/github-automation.py
index 0517cac286a30f0..eac5816b5499f6a 100755
--- a/llvm/utils/git/github-automation.py
+++ b/llvm/utils/git/github-automation.py
@@ -132,14 +132,14 @@ def run(self) -> bool:
             patch = html.escape(requests.get(self.pr.diff_url).text)
         except:
             patch = ""
-        diff_stats += "\n<pre>\n" + patch
+        diff_stats += "\n<pre>\n" + html.escape(patch)
 
         # GitHub limits comments to 65,536 characters, let's limit the diff to 20kB.
         DIFF_LIMIT = 20 * 1024
         patch_link = f"Full diff: {self.pr.diff_url}\n"
         if len(patch) > DIFF_LIMIT:
             patch_link = f"\nPatch is {human_readable_size(len(patch))}, truncated to {human_readable_size(DIFF_LIMIT)} below, full version: {self.pr.diff_url}\n"
-            diff_stats = html.escape(diff_stats[0:DIFF_LIMIT]) + "...\n<truncated>\n"
+            diff_stats = diff_stats[0:DIFF_LIMIT] + "...\n<truncated>\n"
         diff_stats += "</pre>"
         team_mention = "@llvm/{}".format(team.slug)
 

>From 4afd7c566bfa560c93d2c3678ad6ba4f7e9376f6 Mon Sep 17 00:00:00 2001
From: Siva Chandra <sivachandra at gmail.com>
Date: Wed, 13 Sep 2023 22:17:00 -0700
Subject: [PATCH 20/86] [libc] Remove common_libc_tuners.cmake and move options
 into config.json. (#66226)

The name has been changed to adhere to the config option naming format.
The necessary build changes to use the new option have also been made.
---
 libc/CMakeLists.txt                          |  2 --
 libc/cmake/modules/LLVMLibCObjectRules.cmake |  2 ++
 libc/common_libc_tuners.cmake                | 14 --------------
 libc/config/config.json                      |  6 ++++++
 libc/docs/configure.rst                      |  2 ++
 libc/src/string/CMakeLists.txt               |  8 ++++++++
 libc/src/string/string_utils.h               |  4 ++--
 7 files changed, 20 insertions(+), 18 deletions(-)
 delete mode 100644 libc/common_libc_tuners.cmake

diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index 752b048cd397a23..f81fe01b3918741 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -64,8 +64,6 @@ add_compile_definitions(LIBC_NAMESPACE=${LIBC_NAMESPACE})
 # Flags to pass down to the compiler while building the libc functions.
 set(LIBC_COMPILE_OPTIONS_DEFAULT "" CACHE STRING "Architecture to tell clang to optimize for (e.g. -march=... or -mcpu=...)")
 
-include(common_libc_tuners.cmake)
-
 list(APPEND LIBC_COMPILE_OPTIONS_DEFAULT ${LIBC_COMMON_TUNE_OPTIONS})
 
 # Check --print-resource-dir to find the compiler resource dir if this flag
diff --git a/libc/cmake/modules/LLVMLibCObjectRules.cmake b/libc/cmake/modules/LLVMLibCObjectRules.cmake
index 4d5835cc6b4d809..891c298855e6131 100644
--- a/libc/cmake/modules/LLVMLibCObjectRules.cmake
+++ b/libc/cmake/modules/LLVMLibCObjectRules.cmake
@@ -672,6 +672,7 @@ function(create_entrypoint_object fq_target_name)
     target_compile_options(${internal_target_name} BEFORE PRIVATE ${common_compile_options})
     target_include_directories(${internal_target_name} PRIVATE ${include_dirs})
     add_dependencies(${internal_target_name} ${full_deps_list})
+    target_link_libraries(${internal_target_name} ${full_deps_list})
 
     add_library(
       ${fq_target_name}
@@ -685,6 +686,7 @@ function(create_entrypoint_object fq_target_name)
     target_compile_options(${fq_target_name} BEFORE PRIVATE ${common_compile_options} -DLIBC_COPT_PUBLIC_PACKAGING)
     target_include_directories(${fq_target_name} PRIVATE ${include_dirs})
     add_dependencies(${fq_target_name} ${full_deps_list})
+    target_link_libraries(${fq_target_name} ${full_deps_list})
   endif()
 
   set_target_properties(
diff --git a/libc/common_libc_tuners.cmake b/libc/common_libc_tuners.cmake
deleted file mode 100644
index 20aee4899623490..000000000000000
--- a/libc/common_libc_tuners.cmake
+++ /dev/null
@@ -1,14 +0,0 @@
-# ------------------------------------------------------------------------------
-# Common tuning option definitions.
-# ------------------------------------------------------------------------------
-
-set(LIBC_COMMON_TUNE_OPTIONS "")
-
-option(LIBC_UNSAFE_STRING_WIDE_READ "Functions searching for the first character in a string such as strlen will read the string as int sized blocks instead of bytes. This relies on undefined behavior and may fail on some systems, but improves performance on long strings." OFF)
-if(LIBC_UNSAFE_STRING_WIDE_READ)
-  if(LLVM_USE_SANITIZER)
-    message(FATAL_ERROR "LIBC_UNSAFE_STRING_WIDE_READ is set at the same time as a sanitizer. LIBC_UNSAFE_STRING_WIDE_READ causes strlen and memchr to read beyond the end of their target strings, which is undefined behavior caught by sanitizers.")
-  else()
-    list(APPEND LIBC_COMMON_TUNE_OPTIONS "-DLIBC_COPT_UNSAFE_STRING_WIDE_READ")
-    endif()
-endif()
diff --git a/libc/config/config.json b/libc/config/config.json
index 134cf06a73b3ab5..3c74e0ed1eddf47 100644
--- a/libc/config/config.json
+++ b/libc/config/config.json
@@ -16,5 +16,11 @@
       "value": true,
       "doc": "Use large table for better printf long double performance."
     }
+  },
+  "string": {
+    "LIBC_CONF_STRING_UNSAFE_WIDE_READ": {
+      "value": false,
+      "doc": "Read more than a byte at a time to perform byte-string operations like strlen."
+    }
   }
 }
diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst
index a667316bd399156..0a1b3ea87a2133b 100644
--- a/libc/docs/configure.rst
+++ b/libc/docs/configure.rst
@@ -30,3 +30,5 @@ to learn about the defaults for your platform and target.
     - ``LIBC_CONF_PRINTF_DISABLE_INDEX_MODE``: Disable index mode in the printf format string.
     - ``LIBC_CONF_PRINTF_DISABLE_WRITE_INT``: Disable handling of %n in printf format string.
     - ``LIBC_CONF_PRINTF_FLOAT_TO_STR_USE_MEGA_LONG_DOUBLE_TABLE``: Use large table for better printf long double performance.
+* **"string" options**
+    - ``LIBC_CONF_STRING_UNSAFE_WIDE_READ``: Read more than a byte at a time to perform byte-string operations like strlen.
diff --git a/libc/src/string/CMakeLists.txt b/libc/src/string/CMakeLists.txt
index b073a62f957a734..f2e5654d03ccece 100644
--- a/libc/src/string/CMakeLists.txt
+++ b/libc/src/string/CMakeLists.txt
@@ -1,5 +1,12 @@
 add_subdirectory(memory_utils)
 
+if(LIBC_CONF_STRING_UNSAFE_WIDE_READ)
+  list(APPEND string_config_options "-DLIBC_COPT_STRING_UNSAFE_WIDE_READ")
+endif()
+if(string_config_options)
+  list(PREPEND string_config_options "COMPILE_OPTIONS")
+endif()
+
 add_header_library(
   string_utils
   HDRS
@@ -10,6 +17,7 @@ add_header_library(
     libc.include.stdlib
     libc.src.__support.common
     libc.src.__support.CPP.bitset
+  ${string_config_options}
 )
 
 add_header_library(
diff --git a/libc/src/string/string_utils.h b/libc/src/string/string_utils.h
index e2e7722e392a7fd..87dc4c6cd2b4c58 100644
--- a/libc/src/string/string_utils.h
+++ b/libc/src/string/string_utils.h
@@ -88,7 +88,7 @@ LIBC_INLINE size_t string_length_byte_read(const char *src) {
 // Returns the length of a string, denoted by the first occurrence
 // of a null terminator.
 LIBC_INLINE size_t string_length(const char *src) {
-#ifdef LIBC_COPT_UNSAFE_STRING_WIDE_READ
+#ifdef LIBC_COPT_STRING_UNSAFE_WIDE_READ
   // Unsigned int is the default size for most processors, and on x86-64 it
   // performs better than larger sizes when the src pointer can't be assumed to
   // be aligned to a word boundary, so it's the size we use for reading the
@@ -143,7 +143,7 @@ LIBC_INLINE void *find_first_character_byte_read(const unsigned char *src,
 // 'src'. If 'ch' is not found, returns nullptr.
 LIBC_INLINE void *find_first_character(const unsigned char *src,
                                        unsigned char ch, size_t max_strlen) {
-#ifdef LIBC_COPT_UNSAFE_STRING_WIDE_READ
+#ifdef LIBC_COPT_STRING_UNSAFE_WIDE_READ
   // If the maximum size of the string is small, the overhead of aligning to a
   // word boundary and generating a bitmask of the appropriate size may be
   // greater than the gains from reading larger chunks. Based on some testing,

>From 837a0057898848b979c8a294ae7879f603e963e7 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Wed, 13 Sep 2023 21:54:42 -0700
Subject: [PATCH 21/86] [lldb] Simplify color logic in (IOHandler)Editline
 (NFC)

This patch simplifies the color handling logic in Editline and
IOHandlerEditline:

 - Remove the m_color_prompts property from Editline and use the prompt
   ANSI prefix and suffix as the single source of truth. This avoids
   having to redraw the prompt unnecessarily, for example when colors
   are enabled but the prompt prefix and suffix are empty.

 - Rename m_color_prompts to just m_color in IOHandlerEditline and use
   it to ensure consistency between colored prompts and colored
   auto-suggestions. Some IOHandler explicitly turn off colors (such as
   IOHandlerConfirm) and it doesn't really make sense to have one or the
   other.
---
 lldb/include/lldb/Core/IOHandler.h       |  6 ++---
 lldb/include/lldb/Host/Editline.h        |  4 +---
 lldb/source/Core/IOHandler.cpp           | 28 +++++++++++++-----------
 lldb/source/Host/common/Editline.cpp     | 18 ++++++---------
 lldb/unittests/Editline/EditlineTest.cpp |  2 +-
 5 files changed, 27 insertions(+), 31 deletions(-)

diff --git a/lldb/include/lldb/Core/IOHandler.h b/lldb/include/lldb/Core/IOHandler.h
index bb0fb58175a6bce..f10d63198aefad8 100644
--- a/lldb/include/lldb/Core/IOHandler.h
+++ b/lldb/include/lldb/Core/IOHandler.h
@@ -328,7 +328,7 @@ class IOHandlerEditline : public IOHandler {
   IOHandlerEditline(Debugger &debugger, IOHandler::Type type,
                     const char *editline_name, // Used for saving history files
                     llvm::StringRef prompt, llvm::StringRef continuation_prompt,
-                    bool multi_line, bool color_prompts,
+                    bool multi_line, bool color,
                     uint32_t line_number_start, // If non-zero show line numbers
                                                 // starting at
                                                 // 'line_number_start'
@@ -340,7 +340,7 @@ class IOHandlerEditline : public IOHandler {
                     const lldb::StreamFileSP &error_sp, uint32_t flags,
                     const char *editline_name, // Used for saving history files
                     llvm::StringRef prompt, llvm::StringRef continuation_prompt,
-                    bool multi_line, bool color_prompts,
+                    bool multi_line, bool color,
                     uint32_t line_number_start, // If non-zero show line numbers
                                                 // starting at
                                                 // 'line_number_start'
@@ -432,7 +432,7 @@ class IOHandlerEditline : public IOHandler {
   uint32_t m_base_line_number; // If non-zero, then show line numbers in prompt
   uint32_t m_curr_line_idx;
   bool m_multi_line;
-  bool m_color_prompts;
+  bool m_color;
   bool m_interrupt_exits;
   std::string m_line_buffer;
 };
diff --git a/lldb/include/lldb/Host/Editline.h b/lldb/include/lldb/Host/Editline.h
index 3698588fbea516b..e1807aa5492680e 100644
--- a/lldb/include/lldb/Host/Editline.h
+++ b/lldb/include/lldb/Host/Editline.h
@@ -153,8 +153,7 @@ using namespace line_editor;
 class Editline {
 public:
   Editline(const char *editor_name, FILE *input_file, FILE *output_file,
-           FILE *error_file, std::recursive_mutex &output_mutex,
-           bool color_prompts);
+           FILE *error_file, std::recursive_mutex &output_mutex);
 
   ~Editline();
 
@@ -371,7 +370,6 @@ class Editline {
   bool m_multiline_enabled = false;
   std::vector<EditLineStringType> m_input_lines;
   EditorStatus m_editor_status;
-  bool m_color_prompts = true;
   int m_terminal_width = 0;
   int m_base_line_number = 0;
   unsigned m_current_line_index = 0;
diff --git a/lldb/source/Core/IOHandler.cpp b/lldb/source/Core/IOHandler.cpp
index 7272e5df43fe7e1..695c2481e353db7 100644
--- a/lldb/source/Core/IOHandler.cpp
+++ b/lldb/source/Core/IOHandler.cpp
@@ -226,7 +226,7 @@ IOHandlerEditline::IOHandlerEditline(
     Debugger &debugger, IOHandler::Type type,
     const char *editline_name, // Used for saving history files
     llvm::StringRef prompt, llvm::StringRef continuation_prompt,
-    bool multi_line, bool color_prompts, uint32_t line_number_start,
+    bool multi_line, bool color, uint32_t line_number_start,
     IOHandlerDelegate &delegate)
     : IOHandlerEditline(debugger, type,
                         FileSP(),       // Inherit input from top input reader
@@ -234,7 +234,7 @@ IOHandlerEditline::IOHandlerEditline(
                         StreamFileSP(), // Inherit error from top input reader
                         0,              // Flags
                         editline_name,  // Used for saving history files
-                        prompt, continuation_prompt, multi_line, color_prompts,
+                        prompt, continuation_prompt, multi_line, color,
                         line_number_start, delegate) {}
 
 IOHandlerEditline::IOHandlerEditline(
@@ -243,7 +243,7 @@ IOHandlerEditline::IOHandlerEditline(
     uint32_t flags,
     const char *editline_name, // Used for saving history files
     llvm::StringRef prompt, llvm::StringRef continuation_prompt,
-    bool multi_line, bool color_prompts, uint32_t line_number_start,
+    bool multi_line, bool color, uint32_t line_number_start,
     IOHandlerDelegate &delegate)
     : IOHandler(debugger, type, input_sp, output_sp, error_sp, flags),
 #if LLDB_ENABLE_LIBEDIT
@@ -251,8 +251,8 @@ IOHandlerEditline::IOHandlerEditline(
 #endif
       m_delegate(delegate), m_prompt(), m_continuation_prompt(),
       m_current_lines_ptr(nullptr), m_base_line_number(line_number_start),
-      m_curr_line_idx(UINT32_MAX), m_multi_line(multi_line),
-      m_color_prompts(color_prompts), m_interrupt_exits(true) {
+      m_curr_line_idx(UINT32_MAX), m_multi_line(multi_line), m_color(color),
+      m_interrupt_exits(true) {
   SetPrompt(prompt);
 
 #if LLDB_ENABLE_LIBEDIT
@@ -262,9 +262,9 @@ IOHandlerEditline::IOHandlerEditline(
                  m_input_sp && m_input_sp->GetIsRealTerminal();
 
   if (use_editline) {
-    m_editline_up = std::make_unique<Editline>(
-        editline_name, GetInputFILE(), GetOutputFILE(), GetErrorFILE(),
-        GetOutputMutex(), m_color_prompts);
+    m_editline_up = std::make_unique<Editline>(editline_name, GetInputFILE(),
+                                               GetOutputFILE(), GetErrorFILE(),
+                                               GetOutputMutex());
     m_editline_up->SetIsInputCompleteCallback(
         [this](Editline *editline, StringList &lines) {
           return this->IsInputCompleteCallback(editline, lines);
@@ -278,10 +278,12 @@ IOHandlerEditline::IOHandlerEditline(
       m_editline_up->SetSuggestionCallback([this](llvm::StringRef line) {
         return this->SuggestionCallback(line);
       });
-      m_editline_up->SetSuggestionAnsiPrefix(ansi::FormatAnsiTerminalCodes(
-          debugger.GetAutosuggestionAnsiPrefix()));
-      m_editline_up->SetSuggestionAnsiSuffix(ansi::FormatAnsiTerminalCodes(
-          debugger.GetAutosuggestionAnsiSuffix()));
+      if (m_color) {
+        m_editline_up->SetSuggestionAnsiPrefix(ansi::FormatAnsiTerminalCodes(
+            debugger.GetAutosuggestionAnsiPrefix()));
+        m_editline_up->SetSuggestionAnsiSuffix(ansi::FormatAnsiTerminalCodes(
+            debugger.GetAutosuggestionAnsiSuffix()));
+      }
     }
     // See if the delegate supports fixing indentation
     const char *indent_chars = delegate.IOHandlerGetFixIndentationCharacters();
@@ -476,7 +478,7 @@ bool IOHandlerEditline::SetPrompt(llvm::StringRef prompt) {
 #if LLDB_ENABLE_LIBEDIT
   if (m_editline_up) {
     m_editline_up->SetPrompt(m_prompt.empty() ? nullptr : m_prompt.c_str());
-    if (m_debugger.GetUseColor()) {
+    if (m_color) {
       m_editline_up->SetPromptAnsiPrefix(
           ansi::FormatAnsiTerminalCodes(m_debugger.GetPromptAnsiPrefix()));
       m_editline_up->SetPromptAnsiSuffix(
diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp
index 32dd4718c68d03a..edefbf4008129e4 100644
--- a/lldb/source/Host/common/Editline.cpp
+++ b/lldb/source/Host/common/Editline.cpp
@@ -622,7 +622,7 @@ int Editline::GetCharacter(EditLineGetCharType *c) {
 }
 
 const char *Editline::Prompt() {
-  if (m_color_prompts)
+  if (!m_prompt_ansi_prefix.empty() || !m_prompt_ansi_suffix.empty())
     m_needs_prompt_repaint = true;
   return m_current_prompt.c_str();
 }
@@ -1084,13 +1084,9 @@ unsigned char Editline::TypedCharacter(int ch) {
   llvm::StringRef line(line_info->buffer,
                        line_info->lastchar - line_info->buffer);
 
-  const char *ansi_prefix =
-      m_color_prompts ? m_suggestion_ansi_prefix.c_str() : "";
-  const char *ansi_suffix =
-      m_color_prompts ? m_suggestion_ansi_suffix.c_str() : "";
-
   if (std::optional<std::string> to_add = m_suggestion_callback(line)) {
-    std::string to_add_color = ansi_prefix + to_add.value() + ansi_suffix;
+    std::string to_add_color =
+        m_suggestion_ansi_prefix + to_add.value() + m_suggestion_ansi_suffix;
     fputs(typed.c_str(), m_output_file);
     fputs(to_add_color.c_str(), m_output_file);
     size_t new_autosuggestion_size = line.size() + to_add->length();
@@ -1381,10 +1377,10 @@ Editline *Editline::InstanceFor(EditLine *editline) {
 
 Editline::Editline(const char *editline_name, FILE *input_file,
                    FILE *output_file, FILE *error_file,
-                   std::recursive_mutex &output_mutex, bool color_prompts)
-    : m_editor_status(EditorStatus::Complete), m_color_prompts(color_prompts),
-      m_input_file(input_file), m_output_file(output_file),
-      m_error_file(error_file), m_input_connection(fileno(input_file), false),
+                   std::recursive_mutex &output_mutex)
+    : m_editor_status(EditorStatus::Complete), m_input_file(input_file),
+      m_output_file(output_file), m_error_file(error_file),
+      m_input_connection(fileno(input_file), false),
       m_output_mutex(output_mutex) {
   // Get a shared history instance
   m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name;
diff --git a/lldb/unittests/Editline/EditlineTest.cpp b/lldb/unittests/Editline/EditlineTest.cpp
index 92788374bc628b7..333ad77a0a16fd6 100644
--- a/lldb/unittests/Editline/EditlineTest.cpp
+++ b/lldb/unittests/Editline/EditlineTest.cpp
@@ -118,7 +118,7 @@ EditlineAdapter::EditlineAdapter()
   // Create an Editline instance.
   _editline_sp.reset(new lldb_private::Editline(
       "gtest editor", *_el_secondary_file, *_el_secondary_file,
-      *_el_secondary_file, output_mutex, false));
+      *_el_secondary_file, output_mutex));
   _editline_sp->SetPrompt("> ");
 
   // Hookup our input complete callback.

>From 75f5af10e6565f3f5c57d5cda54b983e39f28626 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?=
 =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?=
 =?UTF-8?q?=E3=83=B3=29?= <clementval at gmail.com>
Date: Wed, 13 Sep 2023 22:28:02 -0700
Subject: [PATCH 22/86] [flang][openacc] Use OpenACC terminator instead of
 fir.unreachable after Stop stmt (#66325)

This follow an update made on OpenMP https://reviews.llvm.org/D129969
and was not possible on OpenACC until the unstructured construct was
supported.
---
 flang/include/flang/Lower/OpenACC.h              | 3 +++
 flang/lib/Lower/OpenACC.cpp                      | 9 +++++++++
 flang/lib/Lower/Runtime.cpp                      | 5 +++++
 flang/test/Lower/OpenACC/acc-unstructured.f90    | 4 ++--
 flang/test/Lower/OpenACC/stop-stmt-in-region.f90 | 2 +-
 5 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/flang/include/flang/Lower/OpenACC.h b/flang/include/flang/Lower/OpenACC.h
index 429b548cc22bd47..b342e4a4704dab1 100644
--- a/flang/include/flang/Lower/OpenACC.h
+++ b/flang/include/flang/Lower/OpenACC.h
@@ -103,6 +103,9 @@ void attachDeclarePreDeallocAction(AbstractConverter &, fir::FirOpBuilder &,
 void attachDeclarePostDeallocAction(AbstractConverter &, fir::FirOpBuilder &,
                                     const Fortran::semantics::Symbol &);
 
+void genOpenACCTerminator(fir::FirOpBuilder &, mlir::Operation *,
+                          mlir::Location);
+
 } // namespace lower
 } // namespace Fortran
 
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 180c077d39c9ee2..04078d739ea78c4 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -3299,3 +3299,12 @@ void Fortran::lower::attachDeclarePostDeallocAction(
                  /*preAlloc=*/{}, /*postAlloc=*/{}, /*preDealloc=*/{},
                  /*postDealloc=*/builder.getSymbolRefAttr(fctName.str())));
 }
+
+void Fortran::lower::genOpenACCTerminator(fir::FirOpBuilder &builder,
+                                          mlir::Operation *op,
+                                          mlir::Location loc) {
+  if (mlir::isa<mlir::acc::ParallelOp, mlir::acc::LoopOp>(op))
+    builder.create<mlir::acc::YieldOp>(loc);
+  else
+    builder.create<mlir::acc::TerminatorOp>(loc);
+}
diff --git a/flang/lib/Lower/Runtime.cpp b/flang/lib/Lower/Runtime.cpp
index 11cb56c72d75932..2cf1e522d330d4c 100644
--- a/flang/lib/Lower/Runtime.cpp
+++ b/flang/lib/Lower/Runtime.cpp
@@ -8,6 +8,7 @@
 
 #include "flang/Lower/Runtime.h"
 #include "flang/Lower/Bridge.h"
+#include "flang/Lower/OpenACC.h"
 #include "flang/Lower/OpenMP.h"
 #include "flang/Lower/StatementContext.h"
 #include "flang/Optimizer/Builder/FIRBuilder.h"
@@ -21,6 +22,7 @@
 #include "flang/Runtime/stop.h"
 #include "flang/Runtime/time-intrinsic.h"
 #include "flang/Semantics/tools.h"
+#include "mlir/Dialect/OpenACC/OpenACC.h"
 #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
 #include "llvm/Support/Debug.h"
 #include <optional>
@@ -37,6 +39,9 @@ static void genUnreachable(fir::FirOpBuilder &builder, mlir::Location loc) {
   if (parentOp->getDialect()->getNamespace() ==
       mlir::omp::OpenMPDialect::getDialectNamespace())
     Fortran::lower::genOpenMPTerminator(builder, parentOp, loc);
+  else if (parentOp->getDialect()->getNamespace() ==
+           mlir::acc::OpenACCDialect::getDialectNamespace())
+    Fortran::lower::genOpenACCTerminator(builder, parentOp, loc);
   else
     builder.create<fir::UnreachableOp>(loc);
   mlir::Block *newBlock = curBlock->splitBlock(builder.getInsertionPoint());
diff --git a/flang/test/Lower/OpenACC/acc-unstructured.f90 b/flang/test/Lower/OpenACC/acc-unstructured.f90
index bd9f3284d9fc25c..4ce474241a4bec7 100644
--- a/flang/test/Lower/OpenACC/acc-unstructured.f90
+++ b/flang/test/Lower/OpenACC/acc-unstructured.f90
@@ -57,7 +57,7 @@ subroutine test_unstructured2(a, b, c)
 ! CHECK: acc.parallel
 ! CHECK: acc.loop
 ! CHECK: fir.call @_FortranAStopStatementText
-! CHECK: fir.unreachable
+! CHECK: acc.yield
 ! CHECK: acc.yield
 ! CHECK: acc.yield
 
@@ -80,7 +80,7 @@ subroutine test_unstructured3(a, b, c)
 ! CHECK-LABEL: func.func @_QPtest_unstructured3
 ! CHECK: acc.parallel
 ! CHECK: fir.call @_FortranAStopStatementText
-! CHECK: fir.unreachable
+! CHECK: acc.yield
 ! CHECK: acc.yield
 
 end subroutine
diff --git a/flang/test/Lower/OpenACC/stop-stmt-in-region.f90 b/flang/test/Lower/OpenACC/stop-stmt-in-region.f90
index bec9d53b54c0f1d..4b3e5632650f1cf 100644
--- a/flang/test/Lower/OpenACC/stop-stmt-in-region.f90
+++ b/flang/test/Lower/OpenACC/stop-stmt-in-region.f90
@@ -29,7 +29,7 @@ subroutine test_stop_in_region1()
 ! CHECK:           %[[VAL_2:.*]] = arith.constant false
 ! CHECK:           %[[VAL_3:.*]] = arith.constant false
 ! CHECK:           %[[VAL_4:.*]] = fir.call @_FortranAStopStatement(%[[VAL_1]], %[[VAL_2]], %[[VAL_3]]) {{.*}} : (i32, i1, i1) -> none
-! CHECK:           fir.unreachable
+! CHECK:           acc.yield
 ! CHECK:         }
 ! CHECK:         return
 ! CHECK:       }

>From b51c985e450a33ecbba6c19f44931ae2dee2ec3c Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 13 Sep 2023 22:51:14 -0700
Subject: [PATCH 23/86] Remove CODEOWNERS file and copy missing paths into
 new-prs-labeler.yml (#66145)

See https://discourse.llvm.org/t/changes-to-pull-request-subscription-system/73296/
---
 .github/CODEOWNERS          | 664 ------------------------------------
 .github/new-prs-labeler.yml |  39 ++-
 2 files changed, 38 insertions(+), 665 deletions(-)
 delete mode 100644 .github/CODEOWNERS

diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
deleted file mode 100644
index f62818c0ced9c6a..000000000000000
--- a/.github/CODEOWNERS
+++ /dev/null
@@ -1,664 +0,0 @@
-# llvm-lto
-/llvm/*/LTO/ @llvm/pr-subscribers-llvm-lto
-/llvm/*/Linker/ @llvm/pr-subscribers-llvm-lto
-/llvm/*/ThinLTO/ @llvm/pr-subscribers-llvm-lto
-/llvm/lib/Transforms/*/FunctionImport* @llvm/pr-subscribers-llvm-lto
-/llvm/tools/gold/ @llvm/pr-subscribers-llvm-lto
-
-# llvm-mc
-/llvm/*/MC/ @llvm/pr-subscribers-llvm-mc
-
-# clang-driver
-/clang/*/Driver/ @llvm/pr-subscribers-clang-driver
-
-# sanitizer
-/llvm/lib/Transforms/Instrumentation/*Sanitizer* @llvm/pr-subscribers-sanitizer
-/compiler-rt/lib/interception/ @llvm/pr-subscribers-sanitizer
-/compiler-rt/lib/*san* @llvm/pr-subscribers-sanitizer
-/compiler-rt/test/*san* @llvm/pr-subscribers-sanitizer
-/compiler-rt/lib/fuzzer/ @llvm/pr-subscribers-sanitizer
-/compiler-rt/test/fuzzer/ @llvm/pr-subscribers-sanitizer
-/compiler-rt/lib/scudo/ @llvm/pr-subscribers-sanitizer
-/compiler-rt/test/scudo/ @llvm/pr-subscribers-sanitizer
-
-# xray
-/llvm/tools/llvm-xray/ @llvm/pr-subscribers-xray
-/compiler-rt/*/xray/ @llvm/pr-subscribers-xray
-/clang/include/clang/Basic/XRay* @llvm/pr-subscribers-xray
-/clang/lib/Basic/XRay* @llvm/pr-subscribers-xray
-/compiler-rt/*/xray/ @llvm/pr-subscribers-xray
-/llvm/include/llvm/XRay/ @llvm/pr-subscribers-xray
-/llvm/lib/XRay/ @llvm/pr-subscribers-xray
-/llvm/tools/llvm-xray/ @llvm/pr-subscribers-xray
-/llvm/unittests/XRay/ @llvm/pr-subscribers-xray
-/compiler-rt/*/xray/ @llvm/pr-subscribers-xray
-
-# clang-codegen
-/clang/lib/CodeGen/** @llvm/pr-subscribers-clang-codegen
-/clang/include/clang/CodeGen/ @llvm/pr-subscribers-clang-codegen
-
-# mlir
-/mlir/ @llvm/pr-subscribers-mlir
-
-# mlir-core
-/mlir/**/AsmParser/ @llvm/pr-subscribers-mlir-core
-/mlir/**/Bytecode/ @llvm/pr-subscribers-mlir-core
-/mlir/**/Debug/ @llvm/pr-subscribers-mlir-core
-/mlir/**/IR/ @llvm/pr-subscribers-mlir-core
-/mlir/**/Parser/ @llvm/pr-subscribers-mlir-core
-/mlir/**/Pass/ @llvm/pr-subscribers-mlir-core
-/mlir/**/Reducer/ @llvm/pr-subscribers-mlir-core
-/mlir/**/Support/ @llvm/pr-subscribers-mlir-core
-/mlir/**/Transforms/ @llvm/pr-subscribers-mlir-core
-/mlir/**/tools/ @llvm/pr-subscribers-mlir-core
-/mlir/tools/ @llvm/pr-subscribers-mlir-core
-
-# mlir-ods
-/mlir/TableGen/ @llvm/pr-subscribers-mlir-ods
-/mlir/tblgen/ @llvm/pr-subscribers-mlir-ods
-/mlir/include/mlir/IR/*.td @llvm/pr-subscribers-mlir-ods
-
-# mlir-bindings
-/mlir/Bindings/ @llvm/pr-subscribers-mlir-bindings
-
-# mlir-gpu
-/mlir/**/*GPU @llvm/pr-subscribers-mlir-gpu
-
-# mlir-amdgpu
-/mlir/**/AMDGPU/ @llvm/pr-subscribers-mlir-amdgpu
-
-# mlir-amx
-/mlir/**/AMX/ @llvm/pr-subscribers-mlir-amx
-
-# mlir-affine
-/mlir/**/Affine/ @llvm/pr-subscribers-mlir-affine
-
-# mlir-arith
-/mlir/**/Arith/ @llvm/pr-subscribers-mlir-arith
-
-# mlir-neon
-/mlir/**/ArmNeon/ @llvm/pr-subscribers-mlir-neon
-
-# mlir-presburger
-/mlir/**/*Presburger @llvm/pr-subscribers-mlir-presburger
-
-# mlir-sme
-/mlir/**/ArmSME/ @llvm/pr-subscribers-mlir-sme
-
-# mlir-sve
-/mlir/**/ArmSVE/ @llvm/pr-subscribers-mlir-sve
-
-# mlir-async
-/mlir/**/Async/ @llvm/pr-subscribers-mlir-async
-
-# mlir-bufferization
-/mlir/**/Bufferization/ @llvm/pr-subscribers-mlir-bufferization
-
-# mlir-complex
-/mlir/**/Complex/ @llvm/pr-subscribers-mlir-complex
-
-# mlir-cf
-/mlir/**/ControlFlow/ @llvm/pr-subscribers-mlir-cf
-
-# mlir-dlti
-/mlir/**/DLTI/ @llvm/pr-subscribers-mlir-dlti
-
-# mlir-emitc
-/mlir/**/EmitC/ @llvm/pr-subscribers-mlir-emitc
-/mlir/lib/Target/Cpp @llvm/pr-subscribers-mlir-emitc
-
-# mlir-func
-/mlir/**/Func/ @llvm/pr-subscribers-mlir-func
-
-# mlir-async
-/mlir/**/Async/ @llvm/pr-subscribers-mlir-async
-
-# mlir-irdl
-/mlir/**/IRDL/ @llvm/pr-subscribers-mlir-irdl
-
-# mlir-index
-/mlir/**/Index/ @llvm/pr-subscribers-mlir-index
-
-# mlir-llvm
-/mlir/**/LLVM* @llvm/pr-subscribers-mlir-llvm
-
-# mlir-linalg
-/mlir/**/*Linalg @llvm/pr-subscribers-mlir-linalg
-/mlir/**/*linalg @llvm/pr-subscribers-mlir-linalg
-
-# mlir-mlprogram
-/mlir/**/MLProgram @llvm/pr-subscribers-mlir-mlprogram
-
-# mlir-math
-/mlir/**/Math/ @llvm/pr-subscribers-mlir-math
-
-# mlir-memref
-/mlir/**/MemRef/ @llvm/pr-subscribers-mlir-memref
-
-# mlir-nvgpu
-/mlir/**/NVGPU/ @llvm/pr-subscribers-mlir-nvgpu
-
-# mlir-openacc
-/mlir/**/*OpenACC @llvm/pr-subscribers-mlir-openacc
-
-# mlir-openmp
-/mlir/**/*OpenMP @llvm/pr-subscribers-mlir-openmp
-
-# mlir-pdl
-/mlir/**/PDL/ @llvm/pr-subscribers-mlir-pdl
-
-# mlir-quant
-/mlir/**/Quant/ @llvm/pr-subscribers-mlir-quant
-
-# mlir-scf
-/mlir/**/SCF/ @llvm/pr-subscribers-mlir-scf
-
-# mlir-spirv
-/mlir/**/SPIRV/ @llvm/pr-subscribers-mlir-spirv
-
-# mlir-shape
-/mlir/**/Shape/ @llvm/pr-subscribers-mlir-shape
-
-# mlir-sparse
-/mlir/**/SparseTensor/ @llvm/pr-subscribers-mlir-sparse
-
-# mlir-tensor
-/mlir/**/Tensor/ @llvm/pr-subscribers-mlir-tensor
-
-# mlir-tosa
-/mlir/**/Tosa/ @llvm/pr-subscribers-mlir-tosa
-
-# mlir-ub
-/mlir/**/UB/ @llvm/pr-subscribers-mlir-ub
-
-# mlir-vector
-/mlir/**/*Vector/ @llvm/pr-subscribers-mlir-vector
-
-# mlir-execution-engine
-/mlir/**/ExecutionEngine/ @llvm/pr-subscribers-mlir-execution-engine
-
-# coroutines
-/clang/docs/DebuggingCoroutines.rst @llvm/pr-subscribers-coroutines
-/clang/lib/Sema/SemaCoroutine.cpp @llvm/pr-subscribers-coroutines
-/clang/lib/CodeGen/CGCoroutine.cpp @llvm/pr-subscribers-coroutines
-/clang/test/CodeGenCoroutines/ @llvm/pr-subscribers-coroutines
-/llvm/docs/Coroutines.rst @llvm/pr-subscribers-coroutines
-/llvm/include/llvm/Transforms/Coroutines/ @llvm/pr-subscribers-coroutines
-/llvm/lib/Transforms/Coroutines/ @llvm/pr-subscribers-coroutines
-/llvm/test/Transforms/Coroutines/* @llvm/pr-subscribers-coroutines
-
-# modules
-/clang/docs/StandardCPlusPlusModules.rst @llvm/pr-subscribers-modules
-/clang/include/clang/AST/AbstractBasicReader.h @llvm/pr-subscribers-modules
-/clang/include/clang/AST/AbstractBasicWriter.h @llvm/pr-subscribers-modules
-/clang/include/clang/AST/AbstractTypeReader.h @llvm/pr-subscribers-modules
-/clang/include/clang/AST/AbstractTypeWriter.h @llvm/pr-subscribers-modules
-/clang/include/clang/AST/PropertiesBase.td @llvm/pr-subscribers-modules
-/clang/include/clang/AST/ODRHash.h @llvm/pr-subscribers-modules
-/clang/include/clang/AST/TypeProperties.td @llvm/pr-subscribers-modules
-/clang/include/clang/Basic/Module.h @llvm/pr-subscribers-modules
-/clang/include/clang/Frontend/PrecompiledPreamble.h @llvm/pr-subscribers-modules
-/clang/include/clang/Lex/ModuleLoader.h @llvm/pr-subscribers-modules
-/clang/include/clang/Lex/ModuleMap.h @llvm/pr-subscribers-modules
-/clang/include/clang/Serialization/ @llvm/pr-subscribers-modules
-/clang/lib/AST/ODRHash.cpp @llvm/pr-subscribers-modules
-/clang/lib/AST/StmtProfile.cpp @llvm/pr-subscribers-modules
-/clang/lib/Basic/Module.cpp @llvm/pr-subscribers-modules
-/clang/lib/Frontend/ModuleDependencyCollector.cpp @llvm/pr-subscribers-modules
-/clang/lib/Frontend/PrecompiledPreamble.cpp @llvm/pr-subscribers-modules
-/clang/lib/Lex/ModuleMap.cpp @llvm/pr-subscribers-modules
-/clang/lib/Sema/SemaModule.cpp @llvm/pr-subscribers-modules
-/clang/lib/Serialization/ @llvm/pr-subscribers-modules
-/clang/test/CXX/module/ @llvm/pr-subscribers-modules
-/clang/test/Modules/ @llvm/pr-subscribers-modules
-/clang/unittests/Serialization/* @llvm/pr-subscribers-modules
-
-# clang-tidy
-/clang-tools-extra/clang-tidy/ @llvm/pr-subscribers-clang-tidy
-/clang-tools-extra/docs/clang-tidy/ @llvm/pr-subscribers-clang-tidy
-/clang-tools-extra/test/clang-tidy/ @llvm/pr-subscribers-clang-tidy
-
-# llvm-mca
-/llvm/tools/llvm-mca/ @llvm/pr-subscribers-llvm-mca
-/llvm/include/llvm/MCA/ @llvm/pr-subscribers-llvm-mca
-/llvm/lib/MCA/ @llvm/pr-subscribers-llvm-mca
-
-# vectorizers
-/llvm/lib/Transforms/Vectorize/ @llvm/pr-subscribers-vectorizers
-/llvm/include/llvm/Transforms/Vectorize/ @llvm/pr-subscribers-vectorizers
-
-# clang
-/clang/ @llvm/pr-subscribers-clang
-
-# testing-tools
-/llvm/include/llvm/FileCheck/ @llvm/pr-subscribers-testing-tools
-/llvm/lib/FileCheck/ @llvm/pr-subscribers-testing-tools
-/llvm/test/FileCheck/ @llvm/pr-subscribers-testing-tools
-/llvm/unittests/FileCheck/ @llvm/pr-subscribers-testing-tools
-/llvm/utils/lit/ @llvm/pr-subscribers-testing-tools
-/llvm/utils/split-file/ @llvm/pr-subscribers-testing-tools
-/llvm/utils/not/ @llvm/pr-subscribers-testing-tools
-/llvm/utils/count/ @llvm/pr-subscribers-testing-tools
-/llvm/utils/FileCheck/ @llvm/pr-subscribers-testing-tools
-/llvm/docs/CommandGuide/FileCheck.rst @llvm/pr-subscribers-testing-tools
-/llvm/docs/CommandGuide/lit.rst @llvm/pr-subscribers-testing-tools
-/llvm/docs/TestingGuide.rst @llvm/pr-subscribers-testing-tools
-/llvm/test/Other/FileCheck-space.txt @llvm/pr-subscribers-testing-tools
-/llvm/utils/update*_test_checks.py @llvm/pr-subscribers-testing-tools
-/llvm/utils/UpdateTestChecks/ @llvm/pr-subscribers-testing-tools
-
-# llvm-binary-utilities
-/llvm/docs/CommandGuide/llvm-* @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/include/llvm/BinaryFormat/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/include/llvm/DebugInfo/Symbolize/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/include/llvm/ObjCopy/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/include/llvm/Object/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/lib/BinaryFormat/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/lib/DebugInfo/Symbolize/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/lib/ObjCopy/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/lib/Object/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/test/Object/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/test/tools/llvm-ar/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/test/tools/llvm-cxxfilt/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/test/tools/llvm-nm/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/test/tools/llvm-objcopy/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/test/tools/llvm-objdump/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/test/tools/llvm-readobj/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/test/tools/llvm-size/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/test/tools/llvm-strings/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/test/tools/llvm-symbolizer/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/tools/llvm-ar/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/tools/llvm-cxxfilt/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/tools/llvm-nm/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/tools/llvm-objcopy/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/tools/llvm-objdump/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/tools/llvm-readobj/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/tools/llvm-size/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/tools/llvm-strings/ @llvm/pr-subscribers-llvm-binary-utilities
-/llvm/tools/llvm-symbolizer/ @llvm/pr-subscribers-llvm-binary-utilities
-
-# debug-info
-/llvm/include/llvm/DebugInfo/ @llvm/pr-subscribers-debug-info
-/llvm/lib/DebugInfo/ @llvm/pr-subscribers-debug-info
-/llvm/tools/dsymutil/ @llvm/pr-subscribers-debug-info
-/llvm/tools/llvm-debuginfo-analyzer/ @llvm/pr-subscribers-debug-info
-/llvm/tools/llvm-dwarfdump/ @llvm/pr-subscribers-debug-info
-/llvm/tools/llvm-dwarfutil/ @llvm/pr-subscribers-debug-info
-/llvm/tools/llvm-dwp/ @llvm/pr-subscribers-debug-info
-/llvm/tools/llvm-gsymutil/ @llvm/pr-subscribers-debug-info
-/llvm/tools/llvm-pdbutil/ @llvm/pr-subscribers-debug-info
-/llvm/tools/llvm-debuginfod/ @llvm/pr-subscribers-debug-info
-/llvm/tools/llvm-debuginfod-find/ @llvm/pr-subscribers-debug-info
-/llvm/lib/CodeGen/AsmPrinter/ @llvm/pr-subscribers-debug-info
-/clang/lib/CodeGen/CGDebugInfo.cpp @llvm/pr-subscribers-debug-info
-/llvm/include/llvm/BinaryFormat/Dwarf.* @llvm/pr-subscribers-debug-info
-/llvm/test/DebugInfo/ @llvm/pr-subscribers-debug-info
-/llvm/test/tools/dsymutil/ @llvm/pr-subscribers-debug-info
-/llvm/test/tools/llvm-debuginfo-analyzer/ @llvm/pr-subscribers-debug-info
-/llvm/test/tools/llvm-debuginfod/ @llvm/pr-subscribers-debug-info
-/llvm/test/tools/llvm-debuginfod-find/ @llvm/pr-subscribers-debug-info
-/llvm/test/tools/llvm-dwarfdump/ @llvm/pr-subscribers-debug-info
-/llvm/test/tools/llvm-dwarfutil/ @llvm/pr-subscribers-debug-info
-/llvm/test/tools/llvm-dwp/ @llvm/pr-subscribers-debug-info
-/llvm/test/tools/llvm-gsymutil/ @llvm/pr-subscribers-debug-info
-/llvm/test/tools/llvm-pdbuti/ @llvm/pr-subscribers-debug-info
-/llvm/lib/IR/Debug*.cpp @llvm/pr-subscribers-debug-info
-/llvm/include/llvm/IR/Debug*.h @llvm/pr-subscribers-debug-info
-
-# github-workflow
-/.github/workflows/ @llvm/pr-subscribers-github-workflow
-
-# flang-driver
-/flang/tools/flang-driver/ @llvm/pr-subscribers-flang-driver
-/flang/unittests/Frontend/ @llvm/pr-subscribers-flang-driver
-/flang/lib/FrontendTool/ @llvm/pr-subscribers-flang-driver
-/flang/lib/Frontend/ @llvm/pr-subscribers-flang-driver
-/flang/include/flang/Frontend/ @llvm/pr-subscribers-flang-driver
-/flang/include/flang/FrontendTool/ @llvm/pr-subscribers-flang-driver
-/flang/test/Driver/ @llvm/pr-subscribers-flang-driver
-
-# m68k
-/llvm/lib/Target/M68k/ @llvm/pr-subscribers-m68k
-/llvm/test/CodeGen/M68k/ @llvm/pr-subscribers-m68k
-/llvm/test/MC/M68k/ @llvm/pr-subscribers-m68k
-/llvm/test/MC/Disassembler/M68k/ @llvm/pr-subscribers-m68k
-/clang/lib/Basic/Targets/M68k.* @llvm/pr-subscribers-m68k
-/clang/lib/CodeGen/Targets/M68k.cpp @llvm/pr-subscribers-m68k
-
-# libcxx
-/libcxx/ @llvm/pr-subscribers-libcxx
-/runtimes/ @llvm/pr-subscribers-libcxx
-
-# libcxxabi
-/libcxxabi/ @llvm/pr-subscribers-libcxxabi
-/runtimes/ @llvm/pr-subscribers-libcxxabi
-
-# libunwind
-/libunwind/ @llvm/pr-subscribers-libunwind
-/runtimes/ @llvm/pr-subscribers-libunwind
-
-# objectyaml
-/llvm/include/llvm/ObjectYAML/ @llvm/pr-subscribers-objectyaml
-/llvm/lib/ObjectYAML/ @llvm/pr-subscribers-objectyaml
-/llvm/test/tools/obj2yaml/ @llvm/pr-subscribers-objectyaml
-/llvm/test/tools/yaml2obj/ @llvm/pr-subscribers-objectyaml
-/llvm/tools/obj2yaml/ @llvm/pr-subscribers-objectyaml
-/llvm/tools/yaml2obj/ @llvm/pr-subscribers-objectyaml
-
-# clang-analysis
-/clang/include/clang/Analysis/ @llvm/pr-subscribers-clang-analysis
-/clang/lib/Analysis/ @llvm/pr-subscribers-clang-analysis
-
-# clang-static-analyzer
-/clang/include/clang/StaticAnalyzer/ @llvm/pr-subscribers-clang-static-analyzer
-/clang/lib/StaticAnalyzer/ @llvm/pr-subscribers-clang-static-analyzer
-/clang/tools/scan-build/ @llvm/pr-subscribers-clang-static-analyzer
-/clang/utils/analyzer/ @llvm/pr-subscribers-clang-static-analyzer
-/clang/docs/analyzer/ @llvm/pr-subscribers-clang-static-analyzer
-
-# pgo
-/llvm/lib/Transforms/Instrumentation/CGProfile.cpp @llvm/pr-subscribers-pgo
-/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp @llvm/pr-subscribers-pgo
-/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp @llvm/pr-subscribers-pgo
-/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @llvm/pr-subscribers-pgo
-/llvm/lib/Transforms/Instrumentation/PGO* @llvm/pr-subscribers-pgo
-/llvm/lib/Transforms/Instrumentation/ValueProfile* @llvm/pr-subscribers-pgo
-/llvm/test/Instrumentation/InstrProfiling/ @llvm/pr-subscribers-pgo
-/llvm/test/Transforms/PGOProfile/ @llvm/pr-subscribers-pgo
-/compiler-rt/lib/profile/ @llvm/pr-subscribers-pgo
-/compiler-rt/lib/memprof/ @llvm/pr-subscribers-pgo
-/compiler-rt/test/profile/ @llvm/pr-subscribers-pgo
-/compiler-rt/test/memprof/ @llvm/pr-subscribers-pgo
-/llvm/tools/llvm-profdata/ @llvm/pr-subscribers-pgo
-/llvm/tools/llvm-profgen/ @llvm/pr-subscribers-pgo
-/llvm/test/tools/llvm-profdata/ @llvm/pr-subscribers-pgo
-/llvm/test/tools/llvm-profgen/ @llvm/pr-subscribers-pgo
-/llvm/unittests/ProfileData/* @llvm/pr-subscribers-pgo
-
-# openacc
-/flang/**/OpenACC/ @llvm/pr-subscribers-openacc
-/flang/include/flang/Lower/OpenACC.h @llvm/pr-subscribers-openacc
-/flang/docs/OpenACC.md @llvm/pr-subscribers-openacc
-/flang/lib/Parser/openacc-parsers.cpp @llvm/pr-subscribers-openacc
-/flang/lib/Lower/OpenACC.cpp @llvm/pr-subscribers-openacc
-/llvm/**/Frontend/OpenACC/ @llvm/pr-subscribers-openacc
-/llvm/unittests/Frontend/OpenACCTest.cpp @llvm/pr-subscribers-openacc
-/mlir/test/Target/LLVMIR/openacc-llvm.mlir @llvm/pr-subscribers-openacc
-/mlir/**/*OpenACC/ @llvm/pr-subscribers-openacc
-
-# flang-runtime
-/flang/runtime/ @llvm/pr-subscribers-flang-runtime
-
-# flang-parser
-/flang/**/Parser/ @llvm/pr-subscribers-flang-parser
-
-# flang-semantics
-/flang/**/Evaluate/ @llvm/pr-subscribers-flang-semantics
-/flang/**/Semantics/ @llvm/pr-subscribers-flang-semantics
-
-# flang-fir-hlfir
-/flang/**/Lower/ @llvm/pr-subscribers-flang-fir-hlfir
-/flang/**/Optimizer/ @llvm/pr-subscribers-flang-fir-hlfir
-
-# flang-codegen
-flang/**/CodeGen/ @llvm/pr-subscribers-flang-codegen
-
-# hlsl
-/clang/test/ParserHLSL/ @llvm/pr-subscribers-hlsl
-/clang/test/SemaHLSL/ @llvm/pr-subscribers-hlsl
-/clang/test/AST/HLSL/ @llvm/pr-subscribers-hlsl
-/clang/test/CodeGenHLSL/ @llvm/pr-subscribers-hlsl
-/clang/cmake/caches/HLSL.cmake @llvm/pr-subscribers-hlsl
-/clang/include/clang/Basic/HLSL*.h @llvm/pr-subscribers-hlsl
-/clang/include/clang/Sema/HLSL*.h @llvm/pr-subscribers-hlsl
-/clang/docs/HLSL/ @llvm/pr-subscribers-hlsl
-/clang/lib/Driver/ToolChains/HLSL* @llvm/pr-subscribers-hlsl
-/clang/lib/Parse/ParseHLSL.cpp @llvm/pr-subscribers-hlsl
-/clang/lib/Sema/HLSLExternalSemaSource.cpp @llvm/pr-subscribers-hlsl
-/clang/lib/Sema/SemaHLSL.cpp @llvm/pr-subscribers-hlsl
-/clang/lib/CodeGen/CGHLSLRuntime.* @llvm/pr-subscribers-hlsl
-/llvm/include/llvm/Frontend/HLSL/ @llvm/pr-subscribers-hlsl
-/llvm/lib/Frontend/HLSL/ @llvm/pr-subscribers-hlsl
-
-# globalisel
-/llvm/**/GlobalISel/ @llvm/pr-subscribers-globalisel
-/llvm/utils/TableGen/GlobalISel* @llvm/pr-subscribers-globalisel
-
-# selection-dag
-/llvm/include/llvm/CodeGen/DAGCombine.h @llvm/pr-subscribers-selectiondag
-/llvm/include/llvm/CodeGen/ISDOpcodes.h @llvm/pr-subscribers-selectiondag
-/llvm/include/llvm/CodeGen/SelectionDAG*.h @llvm/pr-subscribers-selectiondag
-/llvm/include/llvm/CodeGen/SDNodeProperties.td @llvm/pr-subscribers-selectiondag
-/llvm/include/llvm/Target/TargetSelectionDAG.td @llvm/pr-subscribers-selectiondag
-/llvm/lib/CodeGen/SelectionDAG/ @llvm/pr-subscribers-selectiondag
-/llvm/utils/TableGen/CodeGenDAG* @llvm/pr-subscribers-selectiondag
-/llvm/utils/TableGen/DAGISel* @llvm/pr-subscribers-selectiondag
-
-# register allocation
-/llvm/**/*RegAlloc @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/Register* @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/LiveReg* @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/LiveInterval* @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/LiveVariables* @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/LiveRange* @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/SlotIndexes.h @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/VirtRegMap.h @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/PHIElimination* @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/SplitKit* @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/InlineSpiller* @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/ProcessImplicitDefs.cpp @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/RenameIndependentSubregs.cpp @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/InterferenceCache* @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/CalcSpillWeights* @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/RegUsage* @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/MachineCopyPropagation* @llvm/pr-subscribers-regalloc
-/llvm/**/CodeGen/SpillPlacement* @llvm/pr-subscribers-regalloc
-/llvm/include/PBQP/ @llvm/pr-subscribers-regalloc
-/llvm/include/PBQPRAConstraint.h @llvm/pr-subscribers-regalloc
-/llvm/include/llvm/CodeGen/Spiller.h @llvm/pr-subscribers-regalloc
-
-# function-specialization
-/llvm/include/llvm/Transforms/Utils/SCCPSolver.h @llvm/pr-subscribers-function-specialization
-/llvm/lib/Transforms/Utils/SCCPSolver.cpp @llvm/pr-subscribers-function-specialization
-/llvm/include/llvm/Transforms/IPO/FunctionSpecialization.h @llvm/pr-subscribers-function-specialization
-/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp @llvm/pr-subscribers-function-specialization
-/llvm/test/Transforms/FunctionSpecialization/* @llvm/pr-subscribers-function-specialization
-
-# libc
-libc/** @llvm/pr-subscribers-libc
-utils/bazel/llvm-project-overlay/libc/** @llvm/pr-subscribers-libc
-
-# clang-format
-/clang/**/Format/ @llvm/pr-subscribers-clang-format
-/clang/tools/clang-format/ @llvm/pr-subscribers-clang-format
-
-# flang-openmp
-/flang/test/**/OpenMP/ @llvm/pr-subscribers-flang-openmp
-/flang/lib/Lower/OpenMP.cpp @llvm/pr-subscribers-flang-openmp
-/flang/lib/Semantics/resolve-directives.cpp @llvm/pr-subscribers-flang-openmp
-/flang/lib/Semantics/check-omp-structure.cpp @llvm/pr-subscribers-flang-openmp
-/flang/lib/Optimizer/Transforms/OMP* @llvm/pr-subscribers-flang-openmp
-/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir @llvm/pr-subscribers-flang-openmp
-/flang/test/Lower/OpenMP/ @llvm/pr-subscribers-flang-openmp
-/flang/test/Transforms/omp* @llvm/pr-subscribers-flang-openmp
-/mlir/**/*OpenMP* @llvm/pr-subscribers-flang-openmp
-/mlir/test/Target/LLVMIR/openmp* @llvm/pr-subscribers-flang-openmp
-/llvm/lib/Frontend/OpenMP/ @llvm/pr-subscribers-flang-openmp
-/llvm/include/llvm/Frontend/OpenMP/ @llvm/pr-subscribers-flang-openmp
-/llvm/unittests/Frontend/OpenMP* @llvm/pr-subscribers-flang-openmp
-
-# llvm-ir
-/llvm/lib/IR/ @llvm/pr-subscribers-llvm-ir
-/llvm/include/llvm/IR/ @llvm/pr-subscribers-llvm-ir
-/llvm/docs/LangRef.rst @llvm/pr-subscribers-llvm-ir
-/llvm/unittests/IR/ @llvm/pr-subscribers-llvm-ir
-
-# llvm-analysis
-/llvm/lib/Analysis/ @llvm/pr-subscribers-llvm-analysis
-/llvm/include/llvm/Analysis/ @llvm/pr-subscribers-llvm-analysis
-/llvm/test/Analysis/ @llvm/pr-subscribers-llvm-analysis
-/llvm/unittests/Analysis/ @llvm/pr-subscribers-llvm-analysis
-
-# llvm-transforms
-/llvm/lib/Transforms/ @llvm/pr-subscribers-llvm-transforms
-/llvm/include/llvm/Transforms/ @llvm/pr-subscribers-llvm-transforms
-/llvm/test/Transforms/ @llvm/pr-subscribers-llvm-transforms
-/llvm/unittests/Transforms/ @llvm/pr-subscribers-llvm-transforms
-
-# clangd
-/clang-tools-extra/clangd/ @llvm/pr-subscribers-clangd
-
-# arm
-/llvm/include/llvm/IR/IntrinsicsARM.td @llvm/pr-subscribers-arm
-/llvm/lib/Target/ARM/ @llvm/pr-subscribers-arm
-/llvm/test/CodeGen/ARM/ @llvm/pr-subscribers-arm
-/llvm/test/MC/ARM/ @llvm/pr-subscribers-arm
-/llvm/test/MC/DisasemblerARM/ @llvm/pr-subscribers-arm
-/clang/lib/Basic/Targets/ARM* @llvm/pr-subscribers-arm
-/clang/lib/Driver/ToolChains/Arch/ARM.* @llvm/pr-subscribers-arm
-/clang/lib/CodeGen/Targets/ARM.cpp @llvm/pr-subscribers-arm
-/clang/include/clang/Basic/BuiltinsARM* @llvm/pr-subscribers-arm
-
-# AArch64
-/llvm/include/llvm/IR/IntrinsicsAArch64.td @llvm/pr-subscribers-AArch64
-/llvm/lib/Target/AArch64/ @llvm/pr-subscribers-AArch64
-/llvm/test/CodeGen/AArch64/ @llvm/pr-subscribers-AArch64
-/llvm/test/MC/AArch64/ @llvm/pr-subscribers-AArch64
-/llvm/test/MC/Disassembler/AArch64/ @llvm/pr-subscribers-AArch64
-/clang/lib/Basic/Targets/AArch64* @llvm/pr-subscribers-AArch64
-/clang/lib/Driver/ToolChains/Arch/AArch64.* @llvm/pr-subscribers-AArch64
-/clang/lib/CodeGen/Targets/AArch64.cpp @llvm/pr-subscribers-AArch64
-/clang/include/clang/Basic/BuiltinsAArch64* @llvm/pr-subscribers-AArch64
-
-# AMDGPU
-**/*AMDGPU* @llvm/pr-subscribers-amdgpu
-**/*amdgpu* @llvm/pr-subscribers-amdgpu
-
-# DirectX
-/llvm/include/llvm/IR/IntrinsicsDirectX.td @llvm/pr-subscribers-DirectX
-/llvm/lib/Target/DirectX/ @llvm/pr-subscribers-DirectX
-/llvm/test/CodeGen/DirectX/ @llvm/pr-subscribers-DirectX
-/llvm/tools/dxil-dis @llvm/pr-subscribers-DirectX
-/llvm/test/tools/dxil-dis @llvm/pr-subscribers-DirectX
-/clang/lib/Basic/Targets/DirectX* @llvm/pr-subscribers-DirectX
-
-# loongarch
-/llvm/include/llvm/IR/IntrinsicsLoongArch.td @llvm/pr-subscribers-loongarch
-/llvm/lib/Target/LoongArch/ @llvm/pr-subscribers-loongarch
-/llvm/test/CodeGen/LoongArch/ @llvm/pr-subscribers-loongarch
-/llvm/test/MC/LoongArch/ @llvm/pr-subscribers-loongarch
-/clang/lib/Basic/Targets/LoongArch* @llvm/pr-subscribers-loongarch
-/clang/lib/Driver/ToolChains/Arch/LoongArch.* @llvm/pr-subscribers-loongarch
-/clang/lib/CodeGen/Targets/LoongArch.cpp @llvm/pr-subscribers-loongarch
-/clang/include/clang/Basic/BuiltinsLoongArch* @llvm/pr-subscribers-loongarch
-
-# msp430
-/llvm/include/llvm/IR/IntrinsicsMSP430.td @llvm/pr-subscribers-msp430
-/llvm/lib/Target/MSP430/ @llvm/pr-subscribers-msp430
-/llvm/test/CodeGen/MSP430/ @llvm/pr-subscribers-msp430
-/llvm/test/MC/MSP430/ @llvm/pr-subscribers-msp430
-/llvm/test/MC/Disassembler/MSP430/ @llvm/pr-subscribers-msp430
-/clang/lib/Basic/Targets/MSP430* @llvm/pr-subscribers-msp430
-/clang/lib/Driver/ToolChains/Arch/MSP430.* @llvm/pr-subscribers-msp430
-/clang/lib/CodeGen/Targets/MSP430.cpp @llvm/pr-subscribers-msp430
-/clang/include/clang/Basic/BuiltinsMSP430* @llvm/pr-subscribers-msp430
-
-# riscv
-/llvm/**/*RISCV* @llvm/pr-subscribers-riscv
-/llvm/**/*riscv* @llvm/pr-subscribers-riscv
-/clang/**/*RISCV* @llvm/pr-subscribers-riscv
-/clang/**/*riscv* @llvm/pr-subscribers-riscv
-
-# sparc
-/llvm/include/llvm/IR/IntrinsicsSparc.td @llvm/pr-subscribers-sparc
-/llvm/lib/Target/Sparc/ @llvm/pr-subscribers-sparc
-/llvm/test/CodeGen/Sparc/ @llvm/pr-subscribers-sparc
-/llvm/test/MC/Sparc/ @llvm/pr-subscribers-sparc
-/llvm/test/MC/Disassembler/Sparc/ @llvm/pr-subscribers-sparc
-/clang/lib/Basic/Targets/Sparc* @llvm/pr-subscribers-sparc
-/clang/lib/Driver/ToolChains/Arch/Sparc.* @llvm/pr-subscribers-sparc
-/clang/lib/CodeGen/Targets/Sparc.cpp @llvm/pr-subscribers-sparc
-/clang/include/clang/Basic/BuiltinsSparc* @llvm/pr-subscribers-sparc
-
-# windows
-/lld/COFF/ @llvm/pr-subscribers-windows
-/clang/lib/Driver/MSVC.cpp @llvm/pr-subscribers-windows
-/clang/lib/Driver/MinGW.cpp @llvm/pr-subscribers-windows
-/llvm/lib/DebugInfo/CodeView/ @llvm/pr-subscribers-windows
-/llvm/lib/DebugInfo/PDB/ @llvm/pr-subscribers-windows
-/llvm/lib/WindowsDriver/ @llvm/pr-subscribers-windows
-/llvm/lib/Support/Windows/ @llvm/pr-subscribers-windows
-/llvm/lib/BinaryFormat/COFF.cpp @llvm/pr-subscribers-windows
-
-# x86
-/llvm/include/llvm/IR/IntrinsicsX86.td @llvm/pr-subscribers-x86
-/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h @llvm/pr-subscribers-x86
-/llvm/include/llvm/TargetParser/X86* @llvm/pr-subscribers-x86
-/llvm/lib/Target/X86/ @llvm/pr-subscribers-x86
-/llvm/lib/TargetParser/X86* @llvm/pr-subscribers-x86
-/llvm/test/CodeGen/X86/ @llvm/pr-subscribers-x86
-/llvm/test/MC/X86/ @llvm/pr-subscribers-x86
-/llvm/test/MC/Disassembler/X86/ @llvm/pr-subscribers-x86
-/llvm/test/Analysis/CostModel/X86/ @llvm/pr-subscribers-x86
-/llvm/test/tools/llvm-mca/X86/ @llvm/pr-subscribers-x86
-/llvm/utils/TableGen/X86* @llvm/pr-subscribers-x86
-/clang/lib/Basic/Targets/X86/ @llvm/pr-subscribers-x86
-/clang/lib/Driver/ToolChains/Arch/X86.* @llvm/pr-subscribers-x86
-/clang/lib/CodeGen/Targets/X86.* @llvm/pr-subscribers-x86
-/clang/lib/Headers/ @llvm/pr-subscribers-x86
-/clang/test/CodeGen/X86/ @llvm/pr-subscribers-x86
-/clang/include/clang/Basic/BuiltinsX86* @llvm/pr-subscribers-x86
-
-# MLGO
-/llvm/lib/Analysis/ML* @llvm/pr-subscribers-mlgo
-/llvm/include/llvm/Analysis/ML* @llvm/pr-subscribers-mlgo
-/llvm/lib/Analysis/*Runner.cpp @llvm/pr-subscribers-mlgo
-/llvm/include/llvm/Analysis/*Runner.h @llvm/pr-subscribers-mlgo
-/llvm/unittests/Analysis/ML* @llvm/pr-subscribers-mlgo
-/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp @llvm/pr-subscribers-mlgo
-/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h @llvm/pr-subscribers-mlgo
-/llvm/test/Analysis/FunctionPropertiesAnalysis/* @llvm/pr-subscribers-mlgo
-/llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp @llvm/pr-subscribers-mlgo
-/llvm/test/Transforms/inline/ML/ @llvm/pr-subscribers-mlgo
-/llvm/lib/CodeGen/ML* @llvm/pr-subscribers-mlgo
-/llvm/unittests/CodeGen/ML* @llvm/pr-subscribers-mlgo
-/llvm/test/CodeGen/MLRegAlloc/ @llvm/pr-subscribers-mlgo
-
-# llvm-exegesis
-/llvm/tools/llvm-exegesis/ @llvm/pr-subscribers-exegesis
-/llvm/test/tools/llvm-exegesis/ @llvm/pr-subscribers-exegesis
-/llvm/unittests/tools/llvm-exegesis/ @llvm/pr-subscribers-exegesis
-
-# WebAssembly
-/llvm/include/llvm/BinaryFormat/Wasm.h @llvm/pr-subscribers-webassembly
-/llvm/include/llvm/IR/IntinsicsWebAssembly.td @llvm/pr-subscribers-webassembly
-/llvm/include/llvm/Object/Wasm* @llvm/pr-subscribers-webassembly
-/llvm/lib/CodeGen/Wasm* @llvm/pr-subscribers-webassembly
-/llvm/lib/CodeGen/AsmPrinter/Wasm* @llvm/pr-subscribers-webassembly
-/llvm/lib/MC/MCParser/Wasm* @llvm/pr-subscribers-webassembly
-/llvm/lib/MC/Wasm* @llvm/pr-subscribers-webassembly
-/llvm/lib/ObjCopy/wasm/ @llvm/pr-subscribers-webassembly
-/llvm/lib/Object/Wasm* @llvm/pr-subscribers-webassembly
-/llvm/lib/Target/WebAssembly/ @llvm/pr-subscribers-webassembly
-/llvm/test/CodeGen/WebAssembly/ @llvm/pr-subscribers-webassembly
-/llvm/test/DebugInfo/WebAssembly/ @llvm/pr-subscribers-webassembly
-/llvm/test/MC/WebAssembly/ @llvm/pr-subscribers-webassembly
-/llvm/unittests/Target/WebAssembly/ @llvm/pr-subscribers-webassembly
-/clang/include/clang/Basic/BuiltinsWebAssembly.def @llvm/pr-subscribers-webassembly
-/clang/include/clang/Basic/WebAssemblyReferenceTypes.def @llvm/pr-subscribers-webassembly
-/clang/lib/Basic/Targets/WebAssembly* @llvm/pr-subscribers-webassembly
-/clang/lib/Driver/Toolchains/WebAssembly* @llvm/pr-subscribers-webassembly
-/clang/lib/CodeGen/Targets/WebAssembly* @llvm/pr-subscribers-webassembly
-/clang/lib/Headers/wasm_simd128.h @llvm/pr-subscribers-webassembly
-/clang/test/CodeGen/WebAssembly/ @llvm/pr-subscribers-webassembly
-/clang/test/Sema/*wasm* @llvm/pr-subscribers-webassembly
-/clang/test/SemaCXX/*wasm* @llvm/pr-subscribers-webassembly
-
-/lld/**/COFF/ @llvm/pr-subscribers-lld-coff
-/lld/**/ELF/ @llvm/pr-subscribers-lld-elf
-/lld/**/MachO/ @llvm/pr-subscribers-lld-macho
-/lld/**/wasm/ @llvm/pr-subscribers-lld-wasm
-/lld/Common/ @llvm/pr-subscribers-lld-coff @llvm/pr-subscribers-lld-elf @llvm/pr-subscribers-lld-macho @llvm/pr-subscribers-lld-wasm
-
-# lldb
-/lldb/** @llvm/pr-subscribers-lldb
diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml
index e77b17c166b8ce1..5513c5d49b6b3b0 100644
--- a/.github/new-prs-labeler.yml
+++ b/.github/new-prs-labeler.yml
@@ -172,6 +172,7 @@ mlir:dlti:
 
 mlir:emitc:
   - mlir/**/EmitC/**
+  - mlir/lib/Target/Cpp/**
 
 mlir:func:
   - mlir/**/Func/**
@@ -183,7 +184,8 @@ mlir:index:
   - mlir/**/Index/**
 
 mlir:llvm:
-  - mlir/**/LLVM/**
+  - mlir/**/LLVM*
+  - mlir/**/LLVM*/**
 
 mlir:linalg:
   - mlir/**/*linalg/**
@@ -493,14 +495,19 @@ llvm:ir:
   - llvm/lib/IR/**
   - llvm/include/llvm/IR/**
   - llvm/docs/LangRef.rst
+  - llvm/unittests/IR/**
 
 llvm:analysis:
   - llvm/lib/Analysis/**
   - llvm/include/llvm/Analysis/**
+  - llvm/test/Analysis/**
+  - llvm/unittests/Analysis/**
 
 llvm:transforms:
   - llvm/lib/Transforms/**
   - llvm/include/llvm/Transforms/**
+  - llvm/test/Transforms/**
+  - llvm/unittests/Transforms/**
 
 clangd:
   - clang-tools-extra/clangd/**
@@ -727,3 +734,33 @@ backend:X86:
 
 third-party:unittests:
   - third-party/unittests/**
+
+llvm:binary-utilities:
+  - llvm/docs/CommandGuide/llvm-*
+  - llvm/include/llvm/BinaryFormat/**
+  - llvm/include/llvm/DebugInfo/Symbolize/**
+  - llvm/include/llvm/ObjCopy/**
+  - llvm/include/llvm/Object/**
+  - llvm/lib/BinaryFormat/**
+  - llvm/lib/DebugInfo/Symbolize/**
+  - llvm/lib/ObjCopy/**
+  - llvm/lib/Object/**
+  - llvm/test/Object/**
+  - llvm/test/tools/llvm-ar/**
+  - llvm/test/tools/llvm-cxxfilt/**
+  - llvm/test/tools/llvm-nm/**
+  - llvm/test/tools/llvm-objcopy/**
+  - llvm/test/tools/llvm-objdump/**
+  - llvm/test/tools/llvm-readobj/**
+  - llvm/test/tools/llvm-size/**
+  - llvm/test/tools/llvm-strings/**
+  - llvm/test/tools/llvm-symbolizer/**
+  - llvm/tools/llvm-ar/**
+  - llvm/tools/llvm-cxxfilt/**
+  - llvm/tools/llvm-nm/**
+  - llvm/tools/llvm-objcopy/**
+  - llvm/tools/llvm-objdump/**
+  - llvm/tools/llvm-readobj/**
+  - llvm/tools/llvm-size/**
+  - llvm/tools/llvm-strings/**
+  - llvm/tools/llvm-symbolizer/**

>From 59b5ae806fddfbda5d916ec0fb2a7f15e0361b01 Mon Sep 17 00:00:00 2001
From: Siva Chandra <sivachandra at gmail.com>
Date: Wed, 13 Sep 2023 22:52:20 -0700
Subject: [PATCH 24/86] [libc][NFC] Make the dummy header target under overlay
 build a library. (#66329)

This fixes the broken overlay builders.
---
 libc/cmake/modules/LLVMLibCHeaderRules.cmake | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/cmake/modules/LLVMLibCHeaderRules.cmake b/libc/cmake/modules/LLVMLibCHeaderRules.cmake
index e259a512ea760f6..1027a55946d5f8b 100644
--- a/libc/cmake/modules/LLVMLibCHeaderRules.cmake
+++ b/libc/cmake/modules/LLVMLibCHeaderRules.cmake
@@ -86,7 +86,7 @@ function(add_gen_header target_name)
   get_fq_target_name(${target_name} fq_target_name)
   if(NOT LLVM_LIBC_FULL_BUILD)
     # We don't want to use generated headers if we are doing a non-full-build.
-    add_custom_target(${fq_target_name})
+    add_library(${fq_target_name} INTERFACE)
     return()
   endif()
   if(NOT ADD_GEN_HDR_DEF_FILE)

>From 76696ceec0c5a0cd76c3744b511f379440cc2a31 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 13 Sep 2023 23:46:23 -0700
Subject: [PATCH 25/86] workflows/pr-subscriber: Use our own custom concurrency
 implementation (#66263)

The builtin concurrency functionality for the workflows will cancel a
pending job if there is another job from the same workflow running. For
the pr-subscriber job, this means that if multiple labels are added at
the same time, then some of the pr-subscriber jobs will be cancelled and
the PR will not have all the necessary mentions.
---
 .github/workflows/pr-subscriber-wait.py | 27 ++++++++++++++++++++
 .github/workflows/pr-subscriber.yml     | 33 ++++++++++++++-----------
 llvm/utils/git/requirements.txt         | 12 ++++++---
 llvm/utils/git/requirements.txt.in      |  2 +-
 4 files changed, 55 insertions(+), 19 deletions(-)
 create mode 100644 .github/workflows/pr-subscriber-wait.py

diff --git a/.github/workflows/pr-subscriber-wait.py b/.github/workflows/pr-subscriber-wait.py
new file mode 100644
index 000000000000000..633f78c147707fc
--- /dev/null
+++ b/.github/workflows/pr-subscriber-wait.py
@@ -0,0 +1,27 @@
+import github
+import os
+import sys
+import time
+
+
+def needs_to_wait(repo):
+    workflow_name = os.environ.get("GITHUB_WORKFLOW")
+    run_number = os.environ.get("GITHUB_RUN_NUMBER")
+    print("Workflow Name:", workflow_name, "Run Number:", run_number)
+    for status in ["in_progress", "queued"]:
+        for workflow in repo.get_workflow_runs(status=status):
+            print("Looking at ", workflow.name, "#", workflow.run_number)
+            if workflow.name != workflow_name:
+                continue
+            if workflow.run_number < int(run_number):
+                print("Workflow {} still {} ".format(workflow.run_number, status))
+                return True
+    return False
+
+
+repo_name = os.environ.get("GITHUB_REPOSITORY")
+token = os.environ.get("GITHUB_TOKEN")
+gh = github.Github(token)
+repo = gh.get_repo(repo_name)
+while needs_to_wait(repo):
+    time.sleep(30)
diff --git a/.github/workflows/pr-subscriber.yml b/.github/workflows/pr-subscriber.yml
index e31b5c448ee1501..1fc3bfed3a66b19 100644
--- a/.github/workflows/pr-subscriber.yml
+++ b/.github/workflows/pr-subscriber.yml
@@ -7,16 +7,9 @@ on:
       - completed
 
 permissions:
+  actions: read
   contents: read
 
-concurrency:
-  # Ideally, we would use the PR number in the concurrency group, but we don't
-  # have access to it here.  We need to ensure only one job is running for
-  # each PR at a time, because there is a potential race condition when
-  # updating the issue comment.
-  group: "PR Subscriber"
-  cancel-in-progress: false
-
 jobs:
   auto-subscribe:
     runs-on: ubuntu-latest
@@ -25,6 +18,23 @@ jobs:
       github.event.workflow_run.event == 'pull_request' &&
       github.event.workflow_run.conclusion == 'success'
     steps:
+      - name: Setup Automation Script
+        run: |
+          curl -O -L https://raw.githubusercontent.com/"$GITHUB_REPOSITORY"/main/llvm/utils/git/github-automation.py
+          curl -O -L https://raw.githubusercontent.com/"$GITHUB_REPOSITORY"/main/llvm/utils/git/requirements.txt
+          curl -O -L https://raw.githubusercontent.com/"$GITHUB_REPOSITORY"/main/.github/workflows/pr-subscriber-wait.py
+          chmod a+x github-automation.py
+          pip install -r requirements.txt
+
+      - name: 'Wait for other actions'
+        # We can't use the concurrency tag for these jobs, because it will
+        # cancel pending jobs if another job is running.
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        run: |
+          python3 pr-subscriber-wait.py
+
+
       # From: https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
       # Updated version here: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow
       - name: 'Download artifact'
@@ -50,13 +60,6 @@ jobs:
 
       - run: unzip pr.zip
 
-      - name: Setup Automation Script
-        run: |
-          curl -O -L https://raw.githubusercontent.com/"$GITHUB_REPOSITORY"/main/llvm/utils/git/github-automation.py
-          curl -O -L https://raw.githubusercontent.com/"$GITHUB_REPOSITORY"/main/llvm/utils/git/requirements.txt
-          chmod a+x github-automation.py
-          pip install -r requirements.txt
-
       - name: Update watchers
         # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
         run: |
diff --git a/llvm/utils/git/requirements.txt b/llvm/utils/git/requirements.txt
index c83b2ae5df2a555..bed449e6bf9f092 100644
--- a/llvm/utils/git/requirements.txt
+++ b/llvm/utils/git/requirements.txt
@@ -9,9 +9,13 @@ certifi==2023.7.22
     #   -r requirements.txt.in
     #   requests
 cffi==1.15.1
-    # via pynacl
+    # via
+    #   cryptography
+    #   pynacl
 charset-normalizer==2.1.1
     # via requests
+cryptography==41.0.3
+    # via pyjwt
 deprecated==1.2.13
     # via pygithub
 gitdb==4.0.9
@@ -22,9 +26,9 @@ idna==3.4
     # via requests
 pycparser==2.21
     # via cffi
-pygithub==1.55
+pygithub==1.59.1
     # via -r requirements.txt.in
-pyjwt==2.5.0
+pyjwt[crypto]==2.5.0
     # via pygithub
 pynacl==1.5.0
     # via pygithub
@@ -32,6 +36,8 @@ requests==2.28.1
     # via pygithub
 smmap==5.0.0
     # via gitdb
+types-cryptography==3.3.23.2
+    # via pyjwt
 urllib3==1.26.12
     # via requests
 wrapt==1.14.1
diff --git a/llvm/utils/git/requirements.txt.in b/llvm/utils/git/requirements.txt.in
index ee45d2349ea1f30..a8bda5c8114058f 100644
--- a/llvm/utils/git/requirements.txt.in
+++ b/llvm/utils/git/requirements.txt.in
@@ -4,5 +4,5 @@
 # pip-compile -o requirements.txt  requirements.txt.in
 
 certifi>=2023.7.22  # https://security.snyk.io/vuln/SNYK-PYTHON-CERTIFI-5805047
-PyGithub
+PyGithub==1.59.1 # For WorkflowRun.name
 GitPython>=3.1.32  # https://security.snyk.io/vuln/SNYK-PYTHON-GITPYTHON-5840584

>From adf8ba063d389ab2930804c74ef14061382b2f47 Mon Sep 17 00:00:00 2001
From: Pierre van Houtryve <pierre.vanhoutryve at amd.com>
Date: Thu, 14 Sep 2023 08:47:10 +0200
Subject: [PATCH 26/86] [AMDGPU] Fix `HasFP32Denormals` check in FDIV32
 lowering (#66212)

Fixes SWDEV-403219
---
 .../lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp |    4 +-
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp     |    2 +-
 .../CodeGen/AMDGPU/GlobalISel/fdiv.f32.ll     | 2532 ++++++++++++++++-
 llvm/test/CodeGen/AMDGPU/fdiv.ll              |  352 +--
 4 files changed, 2643 insertions(+), 247 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
index 5bbd42295a1ce94..b5c746b81b91e32 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
@@ -4725,7 +4725,7 @@ bool AMDGPULegalizerInfo::legalizeFDIV32(MachineInstr &MI,
 
   // FIXME: Doesn't correctly model the FP mode switch, and the FP operations
   // aren't modeled as reading it.
-  if (Mode.FP32Denormals != DenormalMode::getIEEE())
+  if (Mode.FP32Denormals == DenormalMode::getPreserveSign())
     toggleSPDenormMode(true, B, ST, Mode);
 
   auto Fma0 = B.buildFMA(S32, NegDivScale0, ApproxRcp, One, Flags);
@@ -4737,7 +4737,7 @@ bool AMDGPULegalizerInfo::legalizeFDIV32(MachineInstr &MI,
 
   // FIXME: This mishandles dynamic denormal mode. We need to query the
   // current mode and restore the original.
-  if (Mode.FP32Denormals != DenormalMode::getIEEE())
+  if (Mode.FP32Denormals == DenormalMode::getPreserveSign())
     toggleSPDenormMode(false, B, ST, Mode);
 
   auto Fmas = B.buildIntrinsic(Intrinsic::amdgcn_div_fmas, {S32})
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 777fe76df1151cd..998904bf08820c0 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -9589,7 +9589,7 @@ SDValue SITargetLowering::LowerFDIV32(SDValue Op, SelectionDAG &DAG) const {
   const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
   const DenormalMode DenormMode = Info->getMode().FP32Denormals;
 
-  const bool HasFP32Denormals = DenormMode == DenormalMode::getIEEE();
+  const bool HasFP32Denormals = DenormMode != DenormalMode::getPreserveSign();
 
   if (!HasFP32Denormals) {
     // Note we can't use the STRICT_FMA/STRICT_FMUL for the non-strict FDIV
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/fdiv.f32.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/fdiv.f32.ll
index 25c7f5c8c531db2..55b8dd68920975f 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/fdiv.f32.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/fdiv.f32.ll
@@ -201,6 +201,144 @@ define float @v_fdiv_f32(float %a, float %b) {
   ret float %fdiv
 }
 
+
+define float @v_fdiv_f32_dynamic_denorm(float %a, float %b) #0 {
+; GFX6-IEEE-FASTFMA-LABEL: v_fdiv_f32_dynamic_denorm:
+; GFX6-IEEE-FASTFMA:       ; %bb.0:
+; GFX6-IEEE-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-IEEE-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
+; GFX6-IEEE-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-IEEE-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-FASTFMA-LABEL: v_fdiv_f32_dynamic_denorm:
+; GFX6-FLUSH-FASTFMA:       ; %bb.0:
+; GFX6-FLUSH-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
+; GFX6-FLUSH-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-SLOWFMA-LABEL: v_fdiv_f32_dynamic_denorm:
+; GFX6-IEEE-SLOWFMA:       ; %bb.0:
+; GFX6-IEEE-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-SLOWFMA-LABEL: v_fdiv_f32_dynamic_denorm:
+; GFX6-FLUSH-SLOWFMA:       ; %bb.0:
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-IEEE-LABEL: v_fdiv_f32_dynamic_denorm:
+; GFX89-IEEE:       ; %bb.0:
+; GFX89-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX89-IEEE-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX89-IEEE-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX89-IEEE-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX89-IEEE-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX89-IEEE-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX89-IEEE-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX89-IEEE-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX89-IEEE-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX89-IEEE-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX89-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-FLUSH-LABEL: v_fdiv_f32_dynamic_denorm:
+; GFX89-FLUSH:       ; %bb.0:
+; GFX89-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX89-FLUSH-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX89-FLUSH-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX89-FLUSH-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX89-FLUSH-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX89-FLUSH-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX89-FLUSH-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX89-FLUSH-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX89-FLUSH-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX89-FLUSH-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX89-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_f32_dynamic_denorm:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_div_scale_f32 v2, s4, v1, v1, v0
+; GFX10-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
+; GFX10-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX10-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX10-NEXT:    v_mul_f32_e32 v4, v5, v3
+; GFX10-NEXT:    v_fma_f32 v6, -v2, v4, v5
+; GFX10-NEXT:    v_fmac_f32_e32 v4, v6, v3
+; GFX10-NEXT:    v_fma_f32 v2, -v2, v4, v5
+; GFX10-NEXT:    v_div_fmas_f32 v2, v2, v3, v4
+; GFX10-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_f32_dynamic_denorm:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_div_scale_f32 v2, null, v1, v1, v0
+; GFX11-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_2) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_mul_f32_e32 v4, v5, v3
+; GFX11-NEXT:    v_fma_f32 v6, -v2, v4, v5
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_fmac_f32_e32 v4, v6, v3
+; GFX11-NEXT:    v_fma_f32 v2, -v2, v4, v5
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_div_fmas_f32 v2, v2, v3, v4
+; GFX11-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+  %fdiv = fdiv float %a, %b
+  ret float %fdiv
+}
+
 define float @v_fdiv_f32_afn(float %a, float %b) {
 ; GCN-LABEL: v_fdiv_f32_afn:
 ; GCN:       ; %bb.0:
@@ -316,6 +454,123 @@ define float @v_fdiv_f32_ulp25(float %a, float %b) {
   ret float %fdiv
 }
 
+define float @v_fdiv_f32_dynamic_25ulp(float %x, float %y) #0 {
+; GFX6-LABEL: v_fdiv_f32_dynamic_25ulp:
+; GFX6:       ; %bb.0:
+; GFX6-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX6-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-NEXT:    v_cndmask_b32_e32 v3, v0, v3, vcc
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_f32_dynamic_25ulp:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX7-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX7-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX7-NEXT:    v_frexp_exp_i32_f32_e32 v3, v0
+; GFX7-NEXT:    v_frexp_mant_f32_e32 v0, v0
+; GFX7-NEXT:    v_mul_f32_e32 v0, v0, v2
+; GFX7-NEXT:    v_sub_i32_e32 v1, vcc, v3, v1
+; GFX7-NEXT:    v_ldexp_f32_e32 v0, v0, v1
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_f32_dynamic_25ulp:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX8-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX8-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX8-NEXT:    v_frexp_exp_i32_f32_e32 v3, v0
+; GFX8-NEXT:    v_frexp_mant_f32_e32 v0, v0
+; GFX8-NEXT:    v_mul_f32_e32 v0, v0, v2
+; GFX8-NEXT:    v_sub_u32_e32 v1, vcc, v3, v1
+; GFX8-NEXT:    v_ldexp_f32 v0, v0, v1
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-LABEL: v_fdiv_f32_dynamic_25ulp:
+; GFX6-IEEE:       ; %bb.0:
+; GFX6-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-IEEE-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-IEEE-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-IEEE-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-IEEE-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-IEEE-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX6-IEEE-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-IEEE-NEXT:    v_cndmask_b32_e32 v3, v0, v3, vcc
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-IEEE-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-IEEE-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-IEEE-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-LABEL: v_fdiv_f32_dynamic_25ulp:
+; GFX6-FLUSH:       ; %bb.0:
+; GFX6-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-FLUSH-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-FLUSH-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-FLUSH-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-FLUSH-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-FLUSH-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX6-FLUSH-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-FLUSH-NEXT:    v_cndmask_b32_e32 v3, v0, v3, vcc
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-FLUSH-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-FLUSH-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-FLUSH-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_f32_dynamic_25ulp:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX10-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX10-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX10-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX10-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX10-NEXT:    v_sub_nc_u32_e32 v0, v0, v1
+; GFX10-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX10-NEXT:    v_ldexp_f32 v0, v2, v0
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_f32_dynamic_25ulp:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX11-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX11-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX11-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_4) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX11-NEXT:    v_sub_nc_u32_e32 v0, v0, v1
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1)
+; GFX11-NEXT:    v_ldexp_f32 v0, v2, v0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_f32_dynamic_25ulp:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %div = fdiv float %x, %y, !fpmath !0
+  ret float %div
+}
+
 define float @v_rcp_f32(float %x) {
 ; GFX6-IEEE-FASTFMA-LABEL: v_rcp_f32:
 ; GFX6-IEEE-FASTFMA:       ; %bb.0:
@@ -2220,7 +2475,2280 @@ define <2 x float> @v_fdiv_v2f32_arcp_afn_ulp25(<2 x float> %a, <2 x float> %b)
   ret <2 x float> %fdiv
 }
 
-!0 = !{float 2.500000e+00}
+
+define float @v_fdiv_f32_dynamic__nnan_ninf(float %x, float %y, float %z) #0 {
+; GFX6-FASTFMA-LABEL: v_fdiv_f32_dynamic__nnan_ninf:
+; GFX6-FASTFMA:       ; %bb.0:
+; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
+; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-SLOWFMA-LABEL: v_fdiv_f32_dynamic__nnan_ninf:
+; GFX6-SLOWFMA:       ; %bb.0:
+; GFX6-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_f32_dynamic__nnan_ninf:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX7-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX7-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX7-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX7-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
+; GFX7-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX7-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX7-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX7-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX7-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX7-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_f32_dynamic__nnan_ninf:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX8-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX8-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX8-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX8-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX8-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX8-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX8-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX8-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX8-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX8-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-FASTFMA-LABEL: v_fdiv_f32_dynamic__nnan_ninf:
+; GFX6-IEEE-FASTFMA:       ; %bb.0:
+; GFX6-IEEE-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-IEEE-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
+; GFX6-IEEE-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-IEEE-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-FASTFMA-LABEL: v_fdiv_f32_dynamic__nnan_ninf:
+; GFX6-FLUSH-FASTFMA:       ; %bb.0:
+; GFX6-FLUSH-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
+; GFX6-FLUSH-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-SLOWFMA-LABEL: v_fdiv_f32_dynamic__nnan_ninf:
+; GFX6-IEEE-SLOWFMA:       ; %bb.0:
+; GFX6-IEEE-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-SLOWFMA-LABEL: v_fdiv_f32_dynamic__nnan_ninf:
+; GFX6-FLUSH-SLOWFMA:       ; %bb.0:
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-IEEE-LABEL: v_fdiv_f32_dynamic__nnan_ninf:
+; GFX89-IEEE:       ; %bb.0:
+; GFX89-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX89-IEEE-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX89-IEEE-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX89-IEEE-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX89-IEEE-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX89-IEEE-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX89-IEEE-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX89-IEEE-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX89-IEEE-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX89-IEEE-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX89-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-FLUSH-LABEL: v_fdiv_f32_dynamic__nnan_ninf:
+; GFX89-FLUSH:       ; %bb.0:
+; GFX89-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX89-FLUSH-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX89-FLUSH-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX89-FLUSH-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX89-FLUSH-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX89-FLUSH-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX89-FLUSH-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX89-FLUSH-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX89-FLUSH-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX89-FLUSH-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX89-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_f32_dynamic__nnan_ninf:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_div_scale_f32 v2, s4, v1, v1, v0
+; GFX10-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
+; GFX10-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX10-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX10-NEXT:    v_mul_f32_e32 v4, v5, v3
+; GFX10-NEXT:    v_fma_f32 v6, -v2, v4, v5
+; GFX10-NEXT:    v_fmac_f32_e32 v4, v6, v3
+; GFX10-NEXT:    v_fma_f32 v2, -v2, v4, v5
+; GFX10-NEXT:    v_div_fmas_f32 v2, v2, v3, v4
+; GFX10-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_f32_dynamic__nnan_ninf:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_div_scale_f32 v2, null, v1, v1, v0
+; GFX11-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_2) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_mul_f32_e32 v4, v5, v3
+; GFX11-NEXT:    v_fma_f32 v6, -v2, v4, v5
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_fmac_f32_e32 v4, v6, v3
+; GFX11-NEXT:    v_fma_f32 v2, -v2, v4, v5
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_div_fmas_f32 v2, v2, v3, v4
+; GFX11-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_f32_dynamic__nnan_ninf:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %div = fdiv nnan ninf float %x, %y
+  ret float %div
+}
+
+define float @v_fdiv_f32_dynamic_25ulp__nnan_ninf(float %x, float %y, float %z) #0 {
+; GFX6-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf:
+; GFX6:       ; %bb.0:
+; GFX6-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX6-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-NEXT:    v_cndmask_b32_e32 v3, v0, v3, vcc
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX7-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX7-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX7-NEXT:    v_frexp_exp_i32_f32_e32 v3, v0
+; GFX7-NEXT:    v_frexp_mant_f32_e32 v0, v0
+; GFX7-NEXT:    v_mul_f32_e32 v0, v0, v2
+; GFX7-NEXT:    v_sub_i32_e32 v1, vcc, v3, v1
+; GFX7-NEXT:    v_ldexp_f32_e32 v0, v0, v1
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX8-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX8-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX8-NEXT:    v_frexp_exp_i32_f32_e32 v3, v0
+; GFX8-NEXT:    v_frexp_mant_f32_e32 v0, v0
+; GFX8-NEXT:    v_mul_f32_e32 v0, v0, v2
+; GFX8-NEXT:    v_sub_u32_e32 v1, vcc, v3, v1
+; GFX8-NEXT:    v_ldexp_f32 v0, v0, v1
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf:
+; GFX6-IEEE:       ; %bb.0:
+; GFX6-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-IEEE-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-IEEE-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-IEEE-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-IEEE-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-IEEE-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX6-IEEE-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-IEEE-NEXT:    v_cndmask_b32_e32 v3, v0, v3, vcc
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-IEEE-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-IEEE-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-IEEE-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf:
+; GFX6-FLUSH:       ; %bb.0:
+; GFX6-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-FLUSH-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-FLUSH-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-FLUSH-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-FLUSH-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-FLUSH-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX6-FLUSH-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-FLUSH-NEXT:    v_cndmask_b32_e32 v3, v0, v3, vcc
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-FLUSH-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-FLUSH-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-FLUSH-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX10-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX10-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX10-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX10-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX10-NEXT:    v_sub_nc_u32_e32 v0, v0, v1
+; GFX10-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX10-NEXT:    v_ldexp_f32 v0, v2, v0
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX11-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX11-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX11-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_4) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX11-NEXT:    v_sub_nc_u32_e32 v0, v0, v1
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1)
+; GFX11-NEXT:    v_ldexp_f32 v0, v2, v0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %div = fdiv nnan ninf float %x, %y, !fpmath !0
+  ret float %div
+}
+
+define float @v_fdiv_f32_dynamic_25ulp__nnan_ninf_contractable_user(float %x, float %y, float %z) #0 {
+; GFX6-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf_contractable_user:
+; GFX6:       ; %bb.0:
+; GFX6-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-NEXT:    v_frexp_mant_f32_e32 v3, v1
+; GFX6-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-NEXT:    v_cndmask_b32_e32 v3, v1, v3, vcc
+; GFX6-NEXT:    v_rcp_f32_e32 v3, v3
+; GFX6-NEXT:    v_frexp_mant_f32_e32 v4, v0
+; GFX6-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-NEXT:    v_cndmask_b32_e32 v4, v0, v4, vcc
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-NEXT:    v_mul_f32_e32 v3, v4, v3
+; GFX6-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-NEXT:    v_ldexp_f32_e32 v0, v3, v0
+; GFX6-NEXT:    v_add_f32_e32 v0, v0, v2
+; GFX6-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf_contractable_user:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    v_frexp_mant_f32_e32 v3, v1
+; GFX7-NEXT:    v_rcp_f32_e32 v3, v3
+; GFX7-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX7-NEXT:    v_frexp_exp_i32_f32_e32 v4, v0
+; GFX7-NEXT:    v_frexp_mant_f32_e32 v0, v0
+; GFX7-NEXT:    v_mul_f32_e32 v0, v0, v3
+; GFX7-NEXT:    v_sub_i32_e32 v1, vcc, v4, v1
+; GFX7-NEXT:    v_ldexp_f32_e32 v0, v0, v1
+; GFX7-NEXT:    v_add_f32_e32 v0, v0, v2
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf_contractable_user:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    v_frexp_mant_f32_e32 v3, v1
+; GFX8-NEXT:    v_rcp_f32_e32 v3, v3
+; GFX8-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX8-NEXT:    v_frexp_exp_i32_f32_e32 v4, v0
+; GFX8-NEXT:    v_frexp_mant_f32_e32 v0, v0
+; GFX8-NEXT:    v_mul_f32_e32 v0, v0, v3
+; GFX8-NEXT:    v_sub_u32_e32 v1, vcc, v4, v1
+; GFX8-NEXT:    v_ldexp_f32 v0, v0, v1
+; GFX8-NEXT:    v_add_f32_e32 v0, v0, v2
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf_contractable_user:
+; GFX6-IEEE:       ; %bb.0:
+; GFX6-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-IEEE-NEXT:    v_frexp_mant_f32_e32 v3, v1
+; GFX6-IEEE-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-IEEE-NEXT:    v_cndmask_b32_e32 v3, v1, v3, vcc
+; GFX6-IEEE-NEXT:    v_rcp_f32_e32 v3, v3
+; GFX6-IEEE-NEXT:    v_frexp_mant_f32_e32 v4, v0
+; GFX6-IEEE-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-IEEE-NEXT:    v_cndmask_b32_e32 v4, v0, v4, vcc
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-IEEE-NEXT:    v_mul_f32_e32 v3, v4, v3
+; GFX6-IEEE-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-IEEE-NEXT:    v_ldexp_f32_e32 v0, v3, v0
+; GFX6-IEEE-NEXT:    v_add_f32_e32 v0, v0, v2
+; GFX6-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf_contractable_user:
+; GFX6-FLUSH:       ; %bb.0:
+; GFX6-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-FLUSH-NEXT:    v_frexp_mant_f32_e32 v3, v1
+; GFX6-FLUSH-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-FLUSH-NEXT:    v_cndmask_b32_e32 v3, v1, v3, vcc
+; GFX6-FLUSH-NEXT:    v_rcp_f32_e32 v3, v3
+; GFX6-FLUSH-NEXT:    v_frexp_mant_f32_e32 v4, v0
+; GFX6-FLUSH-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-FLUSH-NEXT:    v_cndmask_b32_e32 v4, v0, v4, vcc
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-FLUSH-NEXT:    v_mul_f32_e32 v3, v4, v3
+; GFX6-FLUSH-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-FLUSH-NEXT:    v_ldexp_f32_e32 v0, v3, v0
+; GFX6-FLUSH-NEXT:    v_add_f32_e32 v0, v0, v2
+; GFX6-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf_contractable_user:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_frexp_mant_f32_e32 v3, v1
+; GFX10-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX10-NEXT:    v_frexp_mant_f32_e32 v4, v0
+; GFX10-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX10-NEXT:    v_rcp_f32_e32 v3, v3
+; GFX10-NEXT:    v_sub_nc_u32_e32 v0, v0, v1
+; GFX10-NEXT:    v_mul_f32_e32 v3, v4, v3
+; GFX10-NEXT:    v_ldexp_f32 v0, v3, v0
+; GFX10-NEXT:    v_add_f32_e32 v0, v0, v2
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf_contractable_user:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_frexp_mant_f32_e32 v3, v1
+; GFX11-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX11-NEXT:    v_frexp_mant_f32_e32 v4, v0
+; GFX11-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_4) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_rcp_f32_e32 v3, v3
+; GFX11-NEXT:    v_sub_nc_u32_e32 v0, v0, v1
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_mul_f32_e32 v3, v4, v3
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_ldexp_f32 v0, v3, v0
+; GFX11-NEXT:    v_add_f32_e32 v0, v0, v2
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_f32_dynamic_25ulp__nnan_ninf_contractable_user:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %div = fdiv nnan ninf contract float %x, %y, !fpmath !0
+  %add = fadd contract float %div, %z
+  ret float %add
+}
+
+
+define float @v_fdiv_neglhs_f32_dynamic(float %x, float %y) #0 {
+; GFX6-FASTFMA-LABEL: v_fdiv_neglhs_f32_dynamic:
+; GFX6-FASTFMA:       ; %bb.0:
+; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, -v0
+; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, -v0, v1, -v0
+; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
+; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-SLOWFMA-LABEL: v_fdiv_neglhs_f32_dynamic:
+; GFX6-SLOWFMA:       ; %bb.0:
+; GFX6-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, -v0
+; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, -v0, v1, -v0
+; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
+; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_neglhs_f32_dynamic:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, -v0
+; GFX7-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX7-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX7-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX7-NEXT:    v_div_scale_f32 v4, vcc, -v0, v1, -v0
+; GFX7-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX7-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX7-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX7-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX7-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX7-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_neglhs_f32_dynamic:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, -v0
+; GFX8-NEXT:    v_div_scale_f32 v3, vcc, -v0, v1, -v0
+; GFX8-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX8-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX8-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX8-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX8-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX8-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX8-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX8-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX8-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-FASTFMA-LABEL: v_fdiv_neglhs_f32_dynamic:
+; GFX6-IEEE-FASTFMA:       ; %bb.0:
+; GFX6-IEEE-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-FASTFMA-NEXT:    v_xor_b32_e32 v2, 0x80000000, v0
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v3, s[4:5], v1, v1, v2
+; GFX6-IEEE-FASTFMA-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v2, vcc, v2, v1, v2
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
+; GFX6-IEEE-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-FASTFMA-LABEL: v_fdiv_neglhs_f32_dynamic:
+; GFX6-FLUSH-FASTFMA:       ; %bb.0:
+; GFX6-FLUSH-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-FASTFMA-NEXT:    v_xor_b32_e32 v2, 0x80000000, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v3, s[4:5], v1, v1, v2
+; GFX6-FLUSH-FASTFMA-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v2, vcc, v2, v1, v2
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
+; GFX6-FLUSH-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-SLOWFMA-LABEL: v_fdiv_neglhs_f32_dynamic:
+; GFX6-IEEE-SLOWFMA:       ; %bb.0:
+; GFX6-IEEE-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-SLOWFMA-NEXT:    v_xor_b32_e32 v2, 0x80000000, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v3, s[4:5], v1, v1, v2
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v2, vcc, v2, v1, v2
+; GFX6-IEEE-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
+; GFX6-IEEE-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-SLOWFMA-LABEL: v_fdiv_neglhs_f32_dynamic:
+; GFX6-FLUSH-SLOWFMA:       ; %bb.0:
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_xor_b32_e32 v2, 0x80000000, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v3, s[4:5], v1, v1, v2
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v2, vcc, v2, v1, v2
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-IEEE-LABEL: v_fdiv_neglhs_f32_dynamic:
+; GFX89-IEEE:       ; %bb.0:
+; GFX89-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-IEEE-NEXT:    v_xor_b32_e32 v2, 0x80000000, v0
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v3, s[4:5], v1, v1, v2
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v2, vcc, v2, v1, v2
+; GFX89-IEEE-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX89-IEEE-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX89-IEEE-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX89-IEEE-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX89-IEEE-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX89-IEEE-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX89-IEEE-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX89-IEEE-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX89-IEEE-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
+; GFX89-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-FLUSH-LABEL: v_fdiv_neglhs_f32_dynamic:
+; GFX89-FLUSH:       ; %bb.0:
+; GFX89-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-FLUSH-NEXT:    v_xor_b32_e32 v2, 0x80000000, v0
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v3, s[4:5], v1, v1, v2
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v2, vcc, v2, v1, v2
+; GFX89-FLUSH-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX89-FLUSH-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX89-FLUSH-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX89-FLUSH-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX89-FLUSH-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX89-FLUSH-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX89-FLUSH-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX89-FLUSH-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX89-FLUSH-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
+; GFX89-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_neglhs_f32_dynamic:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_xor_b32_e32 v2, 0x80000000, v0
+; GFX10-NEXT:    v_div_scale_f32 v3, s4, v1, v1, v2
+; GFX10-NEXT:    v_div_scale_f32 v2, vcc_lo, v2, v1, v2
+; GFX10-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX10-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v4, v5, v4
+; GFX10-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX10-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX10-NEXT:    v_fmac_f32_e32 v5, v6, v4
+; GFX10-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX10-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX10-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_neglhs_f32_dynamic:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_xor_b32_e32 v2, 0x80000000, v0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
+; GFX11-NEXT:    v_div_scale_f32 v3, null, v1, v1, v2
+; GFX11-NEXT:    v_div_scale_f32 v2, vcc_lo, v2, v1, v2
+; GFX11-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_fmac_f32_e32 v4, v5, v4
+; GFX11-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX11-NEXT:    v_fmac_f32_e32 v5, v6, v4
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX11-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1)
+; GFX11-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_neglhs_f32_dynamic:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %neg.x = fneg float %x
+  %div = fdiv float %neg.x, %y
+  ret float %div
+}
+
+define float @v_fdiv_neglhs_f32_dynamic_25ulp(float %x, float %y) #0 {
+; GFX6-LABEL: v_fdiv_neglhs_f32_dynamic_25ulp:
+; GFX6:       ; %bb.0:
+; GFX6-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-NEXT:    v_frexp_mant_f32_e64 v3, -v0
+; GFX6-NEXT:    v_cmp_lt_f32_e64 s[4:5], |v0|, s4
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-NEXT:    v_cndmask_b32_e64 v3, -v0, v3, s[4:5]
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_neglhs_f32_dynamic_25ulp:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX7-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX7-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX7-NEXT:    v_frexp_exp_i32_f32_e32 v3, v0
+; GFX7-NEXT:    v_frexp_mant_f32_e64 v0, -v0
+; GFX7-NEXT:    v_mul_f32_e32 v0, v0, v2
+; GFX7-NEXT:    v_sub_i32_e32 v1, vcc, v3, v1
+; GFX7-NEXT:    v_ldexp_f32_e32 v0, v0, v1
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_neglhs_f32_dynamic_25ulp:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX8-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX8-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX8-NEXT:    v_frexp_exp_i32_f32_e32 v3, v0
+; GFX8-NEXT:    v_frexp_mant_f32_e64 v0, -v0
+; GFX8-NEXT:    v_mul_f32_e32 v0, v0, v2
+; GFX8-NEXT:    v_sub_u32_e32 v1, vcc, v3, v1
+; GFX8-NEXT:    v_ldexp_f32 v0, v0, v1
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-LABEL: v_fdiv_neglhs_f32_dynamic_25ulp:
+; GFX6-IEEE:       ; %bb.0:
+; GFX6-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-IEEE-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-IEEE-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-IEEE-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-IEEE-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-IEEE-NEXT:    v_frexp_mant_f32_e64 v3, -v0
+; GFX6-IEEE-NEXT:    v_cmp_lt_f32_e64 s[4:5], |v0|, s4
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-IEEE-NEXT:    v_cndmask_b32_e64 v3, -v0, v3, s[4:5]
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e64 v0, -v0
+; GFX6-IEEE-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-IEEE-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-IEEE-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-LABEL: v_fdiv_neglhs_f32_dynamic_25ulp:
+; GFX6-FLUSH:       ; %bb.0:
+; GFX6-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-FLUSH-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-FLUSH-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-FLUSH-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-FLUSH-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-FLUSH-NEXT:    v_frexp_mant_f32_e64 v3, -v0
+; GFX6-FLUSH-NEXT:    v_cmp_lt_f32_e64 s[4:5], |v0|, s4
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-FLUSH-NEXT:    v_cndmask_b32_e64 v3, -v0, v3, s[4:5]
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e64 v0, -v0
+; GFX6-FLUSH-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-FLUSH-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-FLUSH-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_neglhs_f32_dynamic_25ulp:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX10-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX10-NEXT:    v_frexp_mant_f32_e64 v3, -v0
+; GFX10-NEXT:    v_frexp_exp_i32_f32_e64 v0, -v0
+; GFX10-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX10-NEXT:    v_sub_nc_u32_e32 v0, v0, v1
+; GFX10-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX10-NEXT:    v_ldexp_f32 v0, v2, v0
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_neglhs_f32_dynamic_25ulp:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX11-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX11-NEXT:    v_frexp_mant_f32_e64 v3, -v0
+; GFX11-NEXT:    v_frexp_exp_i32_f32_e64 v0, -v0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_4) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX11-NEXT:    v_sub_nc_u32_e32 v0, v0, v1
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1)
+; GFX11-NEXT:    v_ldexp_f32 v0, v2, v0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_neglhs_f32_dynamic_25ulp:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %neg.x = fneg float %x
+  %div = fdiv float %neg.x, %y, !fpmath !0
+  ret float %div
+}
+
+
+define float @v_fdiv_negrhs_f32_dynamic(float %x, float %y) #0 {
+; GFX6-FASTFMA-LABEL: v_fdiv_negrhs_f32_dynamic:
+; GFX6-FASTFMA:       ; %bb.0:
+; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], -v1, -v1, v0
+; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, -v1, v0
+; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
+; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-SLOWFMA-LABEL: v_fdiv_negrhs_f32_dynamic:
+; GFX6-SLOWFMA:       ; %bb.0:
+; GFX6-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], -v1, -v1, v0
+; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, -v1, v0
+; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
+; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_negrhs_f32_dynamic:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    v_div_scale_f32 v2, s[4:5], -v1, -v1, v0
+; GFX7-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX7-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX7-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX7-NEXT:    v_div_scale_f32 v4, vcc, v0, -v1, v0
+; GFX7-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX7-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX7-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX7-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX7-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX7-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_negrhs_f32_dynamic:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    v_div_scale_f32 v2, s[4:5], -v1, -v1, v0
+; GFX8-NEXT:    v_div_scale_f32 v3, vcc, v0, -v1, v0
+; GFX8-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX8-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX8-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX8-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX8-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX8-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX8-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX8-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX8-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-FASTFMA-LABEL: v_fdiv_negrhs_f32_dynamic:
+; GFX6-IEEE-FASTFMA:       ; %bb.0:
+; GFX6-IEEE-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-FASTFMA-NEXT:    v_xor_b32_e32 v2, 0x80000000, v1
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v3, s[4:5], v2, v2, v0
+; GFX6-IEEE-FASTFMA-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v2, vcc, v0, v2, v0
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
+; GFX6-IEEE-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-FASTFMA-LABEL: v_fdiv_negrhs_f32_dynamic:
+; GFX6-FLUSH-FASTFMA:       ; %bb.0:
+; GFX6-FLUSH-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-FASTFMA-NEXT:    v_xor_b32_e32 v2, 0x80000000, v1
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v3, s[4:5], v2, v2, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v2, vcc, v0, v2, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-SLOWFMA-LABEL: v_fdiv_negrhs_f32_dynamic:
+; GFX6-IEEE-SLOWFMA:       ; %bb.0:
+; GFX6-IEEE-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-SLOWFMA-NEXT:    v_xor_b32_e32 v2, 0x80000000, v1
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v3, s[4:5], v2, v2, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v2, vcc, v0, v2, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-SLOWFMA-LABEL: v_fdiv_negrhs_f32_dynamic:
+; GFX6-FLUSH-SLOWFMA:       ; %bb.0:
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_xor_b32_e32 v2, 0x80000000, v1
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v3, s[4:5], v2, v2, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v2, vcc, v0, v2, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-IEEE-LABEL: v_fdiv_negrhs_f32_dynamic:
+; GFX89-IEEE:       ; %bb.0:
+; GFX89-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-IEEE-NEXT:    v_xor_b32_e32 v2, 0x80000000, v1
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v3, s[4:5], v2, v2, v0
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v2, vcc, v0, v2, v0
+; GFX89-IEEE-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX89-IEEE-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX89-IEEE-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX89-IEEE-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX89-IEEE-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX89-IEEE-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX89-IEEE-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX89-IEEE-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX89-IEEE-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
+; GFX89-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-FLUSH-LABEL: v_fdiv_negrhs_f32_dynamic:
+; GFX89-FLUSH:       ; %bb.0:
+; GFX89-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-FLUSH-NEXT:    v_xor_b32_e32 v2, 0x80000000, v1
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v3, s[4:5], v2, v2, v0
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v2, vcc, v0, v2, v0
+; GFX89-FLUSH-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX89-FLUSH-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX89-FLUSH-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX89-FLUSH-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX89-FLUSH-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX89-FLUSH-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX89-FLUSH-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX89-FLUSH-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX89-FLUSH-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
+; GFX89-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_negrhs_f32_dynamic:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_xor_b32_e32 v2, 0x80000000, v1
+; GFX10-NEXT:    v_div_scale_f32 v3, s4, v2, v2, v0
+; GFX10-NEXT:    v_div_scale_f32 v2, vcc_lo, v0, v2, v0
+; GFX10-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX10-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v4, v5, v4
+; GFX10-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX10-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX10-NEXT:    v_fmac_f32_e32 v5, v6, v4
+; GFX10-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX10-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX10-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_negrhs_f32_dynamic:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_xor_b32_e32 v2, 0x80000000, v1
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
+; GFX11-NEXT:    v_div_scale_f32 v3, null, v2, v2, v0
+; GFX11-NEXT:    v_div_scale_f32 v2, vcc_lo, v0, v2, v0
+; GFX11-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_fmac_f32_e32 v4, v5, v4
+; GFX11-NEXT:    v_mul_f32_e32 v5, v2, v4
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_fma_f32 v6, -v3, v5, v2
+; GFX11-NEXT:    v_fmac_f32_e32 v5, v6, v4
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_fma_f32 v2, -v3, v5, v2
+; GFX11-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1)
+; GFX11-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_negrhs_f32_dynamic:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %neg.y = fneg float %y
+  %div = fdiv float %x, %neg.y
+  ret float %div
+}
+
+
+define float @v_fdiv_f32_constrhs0_dynamic(float %x) #0 {
+; GFX6-FASTFMA-LABEL: v_fdiv_f32_constrhs0_dynamic:
+; GFX6-FASTFMA:       ; %bb.0:
+; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FASTFMA-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v1, s[4:5], s6, s6, v0
+; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, v3, v2, v2
+; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, s6, v0
+; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v4, v3, v2
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, -v1, v4, v3
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, v5, v2, v4
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v1, -v1, v4, v3
+; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
+; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v1, s6, v0
+; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-SLOWFMA-LABEL: v_fdiv_f32_constrhs0_dynamic:
+; GFX6-SLOWFMA:       ; %bb.0:
+; GFX6-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-SLOWFMA-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v1, s[4:5], s6, s6, v0
+; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, vcc, v0, s6, v0
+; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v3, v1
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v4, v2, v3
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v1, v4, v2
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v3, v4
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v1, -v1, v4, v2
+; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
+; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v1, s6, v0
+; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_f32_constrhs0_dynamic:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX7-NEXT:    v_div_scale_f32 v1, s[4:5], s6, s6, v0
+; GFX7-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX7-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX7-NEXT:    v_fma_f32 v2, v3, v2, v2
+; GFX7-NEXT:    v_div_scale_f32 v3, vcc, v0, s6, v0
+; GFX7-NEXT:    v_mul_f32_e32 v4, v3, v2
+; GFX7-NEXT:    v_fma_f32 v5, -v1, v4, v3
+; GFX7-NEXT:    v_fma_f32 v4, v5, v2, v4
+; GFX7-NEXT:    v_fma_f32 v1, -v1, v4, v3
+; GFX7-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
+; GFX7-NEXT:    v_div_fixup_f32 v0, v1, s6, v0
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_f32_constrhs0_dynamic:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX8-NEXT:    v_div_scale_f32 v1, s[4:5], s6, s6, v0
+; GFX8-NEXT:    v_div_scale_f32 v2, vcc, v0, s6, v0
+; GFX8-NEXT:    v_rcp_f32_e32 v3, v1
+; GFX8-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
+; GFX8-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX8-NEXT:    v_mul_f32_e32 v4, v2, v3
+; GFX8-NEXT:    v_fma_f32 v5, -v1, v4, v2
+; GFX8-NEXT:    v_fma_f32 v4, v5, v3, v4
+; GFX8-NEXT:    v_fma_f32 v1, -v1, v4, v2
+; GFX8-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
+; GFX8-NEXT:    v_div_fixup_f32 v0, v1, s6, v0
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-FASTFMA-LABEL: v_fdiv_f32_constrhs0_dynamic:
+; GFX6-IEEE-FASTFMA:       ; %bb.0:
+; GFX6-IEEE-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-FASTFMA-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v1, s[4:5], s6, s6, v0
+; GFX6-IEEE-FASTFMA-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, s6, v0
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v4, -v1, v2, 1.0
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v2, v4, v2, v2
+; GFX6-IEEE-FASTFMA-NEXT:    v_mul_f32_e32 v4, v3, v2
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v5, -v1, v4, v3
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v4, v5, v2, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v1, -v1, v4, v3
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fixup_f32 v0, v1, s6, v0
+; GFX6-IEEE-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-FASTFMA-LABEL: v_fdiv_f32_constrhs0_dynamic:
+; GFX6-FLUSH-FASTFMA:       ; %bb.0:
+; GFX6-FLUSH-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-FASTFMA-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v1, s[4:5], s6, s6, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, s6, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v4, -v1, v2, 1.0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v2, v4, v2, v2
+; GFX6-FLUSH-FASTFMA-NEXT:    v_mul_f32_e32 v4, v3, v2
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v5, -v1, v4, v3
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v4, v5, v2, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v1, -v1, v4, v3
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fixup_f32 v0, v1, s6, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-SLOWFMA-LABEL: v_fdiv_f32_constrhs0_dynamic:
+; GFX6-IEEE-SLOWFMA:       ; %bb.0:
+; GFX6-IEEE-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-SLOWFMA-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v1, s[4:5], s6, s6, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v2, vcc, v0, s6, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_rcp_f32_e32 v3, v1
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX6-IEEE-SLOWFMA-NEXT:    v_mul_f32_e32 v4, v2, v3
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v5, -v1, v4, v2
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v3, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v1, -v1, v4, v2
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v1, s6, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-SLOWFMA-LABEL: v_fdiv_f32_constrhs0_dynamic:
+; GFX6-FLUSH-SLOWFMA:       ; %bb.0:
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v1, s[4:5], s6, s6, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v2, vcc, v0, s6, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_rcp_f32_e32 v3, v1
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_mul_f32_e32 v4, v2, v3
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v5, -v1, v4, v2
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v3, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v1, -v1, v4, v2
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v1, s6, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-IEEE-LABEL: v_fdiv_f32_constrhs0_dynamic:
+; GFX89-IEEE:       ; %bb.0:
+; GFX89-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-IEEE-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v1, s[4:5], s6, s6, v0
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v2, vcc, v0, s6, v0
+; GFX89-IEEE-NEXT:    v_rcp_f32_e32 v3, v1
+; GFX89-IEEE-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
+; GFX89-IEEE-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX89-IEEE-NEXT:    v_mul_f32_e32 v4, v2, v3
+; GFX89-IEEE-NEXT:    v_fma_f32 v5, -v1, v4, v2
+; GFX89-IEEE-NEXT:    v_fma_f32 v4, v5, v3, v4
+; GFX89-IEEE-NEXT:    v_fma_f32 v1, -v1, v4, v2
+; GFX89-IEEE-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
+; GFX89-IEEE-NEXT:    v_div_fixup_f32 v0, v1, s6, v0
+; GFX89-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-FLUSH-LABEL: v_fdiv_f32_constrhs0_dynamic:
+; GFX89-FLUSH:       ; %bb.0:
+; GFX89-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-FLUSH-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v1, s[4:5], s6, s6, v0
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v2, vcc, v0, s6, v0
+; GFX89-FLUSH-NEXT:    v_rcp_f32_e32 v3, v1
+; GFX89-FLUSH-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
+; GFX89-FLUSH-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX89-FLUSH-NEXT:    v_mul_f32_e32 v4, v2, v3
+; GFX89-FLUSH-NEXT:    v_fma_f32 v5, -v1, v4, v2
+; GFX89-FLUSH-NEXT:    v_fma_f32 v4, v5, v3, v4
+; GFX89-FLUSH-NEXT:    v_fma_f32 v1, -v1, v4, v2
+; GFX89-FLUSH-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
+; GFX89-FLUSH-NEXT:    v_div_fixup_f32 v0, v1, s6, v0
+; GFX89-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_f32_constrhs0_dynamic:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_div_scale_f32 v1, s4, 0x4640e400, 0x4640e400, v0
+; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, 0x4640e400, v0
+; GFX10-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX10-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v2, v3, v2
+; GFX10-NEXT:    v_mul_f32_e32 v3, v4, v2
+; GFX10-NEXT:    v_fma_f32 v5, -v1, v3, v4
+; GFX10-NEXT:    v_fmac_f32_e32 v3, v5, v2
+; GFX10-NEXT:    v_fma_f32 v1, -v1, v3, v4
+; GFX10-NEXT:    v_div_fmas_f32 v1, v1, v2, v3
+; GFX10-NEXT:    v_div_fixup_f32 v0, v1, 0x4640e400, v0
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_f32_constrhs0_dynamic:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_div_scale_f32 v1, null, 0x4640e400, 0x4640e400, v0
+; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, 0x4640e400, v0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_2) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v2, v3, v2
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_mul_f32_e32 v3, v4, v2
+; GFX11-NEXT:    v_fma_f32 v5, -v1, v3, v4
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_fmac_f32_e32 v3, v5, v2
+; GFX11-NEXT:    v_fma_f32 v1, -v1, v3, v4
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_div_fmas_f32 v1, v1, v2, v3
+; GFX11-NEXT:    v_div_fixup_f32 v0, v1, 0x4640e400, v0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_f32_constrhs0_dynamic:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %div = fdiv float %x, 12345.0
+  ret float %div
+}
+
+define float @v_fdiv_f32_constrhs0_dynamic_25ulp(float %x) #0 {
+; GFX6-LABEL: v_fdiv_f32_constrhs0_dynamic_25ulp:
+; GFX6:       ; %bb.0:
+; GFX6-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-NEXT:    v_frexp_mant_f32_e32 v2, v0
+; GFX6-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v1, 0x4640e400
+; GFX6-NEXT:    v_cndmask_b32_e32 v2, v0, v2, vcc
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-NEXT:    v_mul_f32_e32 v2, 0x3fa9e0f0, v2
+; GFX6-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_f32_constrhs0_dynamic_25ulp:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    v_frexp_exp_i32_f32_e32 v1, v0
+; GFX7-NEXT:    v_frexp_mant_f32_e32 v0, v0
+; GFX7-NEXT:    v_mul_f32_e32 v0, 0x3fa9e0f0, v0
+; GFX7-NEXT:    v_add_i32_e32 v1, vcc, -14, v1
+; GFX7-NEXT:    v_ldexp_f32_e32 v0, v0, v1
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_f32_constrhs0_dynamic_25ulp:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    v_frexp_exp_i32_f32_e32 v1, v0
+; GFX8-NEXT:    v_frexp_mant_f32_e32 v0, v0
+; GFX8-NEXT:    v_mul_f32_e32 v0, 0x3fa9e0f0, v0
+; GFX8-NEXT:    v_add_u32_e32 v1, vcc, -14, v1
+; GFX8-NEXT:    v_ldexp_f32 v0, v0, v1
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-LABEL: v_fdiv_f32_constrhs0_dynamic_25ulp:
+; GFX6-IEEE:       ; %bb.0:
+; GFX6-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-NEXT:    v_rcp_f32_e32 v2, 0x3f40e400
+; GFX6-IEEE-NEXT:    v_mov_b32_e32 v4, 0x7f800000
+; GFX6-IEEE-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX6-IEEE-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, v4
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v1, 0x4640e400
+; GFX6-IEEE-NEXT:    v_cndmask_b32_e32 v3, v0, v3, vcc
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-IEEE-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-IEEE-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-IEEE-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-LABEL: v_fdiv_f32_constrhs0_dynamic_25ulp:
+; GFX6-FLUSH:       ; %bb.0:
+; GFX6-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-NEXT:    v_rcp_f32_e32 v2, 0x3f40e400
+; GFX6-FLUSH-NEXT:    v_mov_b32_e32 v4, 0x7f800000
+; GFX6-FLUSH-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX6-FLUSH-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, v4
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v1, 0x4640e400
+; GFX6-FLUSH-NEXT:    v_cndmask_b32_e32 v3, v0, v3, vcc
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-FLUSH-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-FLUSH-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-FLUSH-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_f32_constrhs0_dynamic_25ulp:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_rcp_f32_e32 v1, 0x3f40e400
+; GFX10-NEXT:    v_frexp_mant_f32_e32 v2, v0
+; GFX10-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX10-NEXT:    v_subrev_nc_u32_e32 v0, 14, v0
+; GFX10-NEXT:    v_mul_f32_e32 v1, v2, v1
+; GFX10-NEXT:    v_ldexp_f32 v0, v1, v0
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_f32_constrhs0_dynamic_25ulp:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_rcp_f32_e32 v1, 0x3f40e400
+; GFX11-NEXT:    v_frexp_mant_f32_e32 v2, v0
+; GFX11-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_2) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_subrev_nc_u32_e32 v0, 14, v0
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_mul_f32_e32 v1, v2, v1
+; GFX11-NEXT:    v_ldexp_f32 v0, v1, v0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_f32_constrhs0_dynamic_25ulp:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %div = fdiv float %x, 12345.0, !fpmath !0
+  ret float %div
+}
+
+
+define float @v_fdiv_f32_constlhs0_dynamic(float %x) #0 {
+; GFX6-FASTFMA-LABEL: v_fdiv_f32_constlhs0_dynamic:
+; GFX6-FASTFMA:       ; %bb.0:
+; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FASTFMA-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v1, s[4:5], v0, v0, s6
+; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, v3, v2, v2
+; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v3, vcc, s6, v0, s6
+; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v4, v3, v2
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, -v1, v4, v3
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, v5, v2, v4
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v1, -v1, v4, v3
+; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
+; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v1, v0, s6
+; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-SLOWFMA-LABEL: v_fdiv_f32_constlhs0_dynamic:
+; GFX6-SLOWFMA:       ; %bb.0:
+; GFX6-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-SLOWFMA-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v1, s[4:5], v0, v0, s6
+; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, vcc, s6, v0, s6
+; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v3, v1
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v4, v2, v3
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v1, v4, v2
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v3, v4
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v1, -v1, v4, v2
+; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
+; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v1, v0, s6
+; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_f32_constlhs0_dynamic:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX7-NEXT:    v_div_scale_f32 v1, s[4:5], v0, v0, s6
+; GFX7-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX7-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX7-NEXT:    v_fma_f32 v2, v3, v2, v2
+; GFX7-NEXT:    v_div_scale_f32 v3, vcc, s6, v0, s6
+; GFX7-NEXT:    v_mul_f32_e32 v4, v3, v2
+; GFX7-NEXT:    v_fma_f32 v5, -v1, v4, v3
+; GFX7-NEXT:    v_fma_f32 v4, v5, v2, v4
+; GFX7-NEXT:    v_fma_f32 v1, -v1, v4, v3
+; GFX7-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
+; GFX7-NEXT:    v_div_fixup_f32 v0, v1, v0, s6
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_f32_constlhs0_dynamic:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX8-NEXT:    v_div_scale_f32 v1, s[4:5], v0, v0, s6
+; GFX8-NEXT:    v_div_scale_f32 v2, vcc, s6, v0, s6
+; GFX8-NEXT:    v_rcp_f32_e32 v3, v1
+; GFX8-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
+; GFX8-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX8-NEXT:    v_mul_f32_e32 v4, v2, v3
+; GFX8-NEXT:    v_fma_f32 v5, -v1, v4, v2
+; GFX8-NEXT:    v_fma_f32 v4, v5, v3, v4
+; GFX8-NEXT:    v_fma_f32 v1, -v1, v4, v2
+; GFX8-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
+; GFX8-NEXT:    v_div_fixup_f32 v0, v1, v0, s6
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-FASTFMA-LABEL: v_fdiv_f32_constlhs0_dynamic:
+; GFX6-IEEE-FASTFMA:       ; %bb.0:
+; GFX6-IEEE-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-FASTFMA-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v1, s[4:5], v0, v0, s6
+; GFX6-IEEE-FASTFMA-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v3, vcc, s6, v0, s6
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v4, -v1, v2, 1.0
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v2, v4, v2, v2
+; GFX6-IEEE-FASTFMA-NEXT:    v_mul_f32_e32 v4, v3, v2
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v5, -v1, v4, v3
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v4, v5, v2, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v1, -v1, v4, v3
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fixup_f32 v0, v1, v0, s6
+; GFX6-IEEE-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-FASTFMA-LABEL: v_fdiv_f32_constlhs0_dynamic:
+; GFX6-FLUSH-FASTFMA:       ; %bb.0:
+; GFX6-FLUSH-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-FASTFMA-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v1, s[4:5], v0, v0, s6
+; GFX6-FLUSH-FASTFMA-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v3, vcc, s6, v0, s6
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v4, -v1, v2, 1.0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v2, v4, v2, v2
+; GFX6-FLUSH-FASTFMA-NEXT:    v_mul_f32_e32 v4, v3, v2
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v5, -v1, v4, v3
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v4, v5, v2, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v1, -v1, v4, v3
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fixup_f32 v0, v1, v0, s6
+; GFX6-FLUSH-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-SLOWFMA-LABEL: v_fdiv_f32_constlhs0_dynamic:
+; GFX6-IEEE-SLOWFMA:       ; %bb.0:
+; GFX6-IEEE-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-SLOWFMA-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v1, s[4:5], v0, v0, s6
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v2, vcc, s6, v0, s6
+; GFX6-IEEE-SLOWFMA-NEXT:    v_rcp_f32_e32 v3, v1
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX6-IEEE-SLOWFMA-NEXT:    v_mul_f32_e32 v4, v2, v3
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v5, -v1, v4, v2
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v3, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v1, -v1, v4, v2
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v1, v0, s6
+; GFX6-IEEE-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-SLOWFMA-LABEL: v_fdiv_f32_constlhs0_dynamic:
+; GFX6-FLUSH-SLOWFMA:       ; %bb.0:
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v1, s[4:5], v0, v0, s6
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v2, vcc, s6, v0, s6
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_rcp_f32_e32 v3, v1
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_mul_f32_e32 v4, v2, v3
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v5, -v1, v4, v2
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v3, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v1, -v1, v4, v2
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v1, v0, s6
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-IEEE-LABEL: v_fdiv_f32_constlhs0_dynamic:
+; GFX89-IEEE:       ; %bb.0:
+; GFX89-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-IEEE-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v1, s[4:5], v0, v0, s6
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v2, vcc, s6, v0, s6
+; GFX89-IEEE-NEXT:    v_rcp_f32_e32 v3, v1
+; GFX89-IEEE-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
+; GFX89-IEEE-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX89-IEEE-NEXT:    v_mul_f32_e32 v4, v2, v3
+; GFX89-IEEE-NEXT:    v_fma_f32 v5, -v1, v4, v2
+; GFX89-IEEE-NEXT:    v_fma_f32 v4, v5, v3, v4
+; GFX89-IEEE-NEXT:    v_fma_f32 v1, -v1, v4, v2
+; GFX89-IEEE-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
+; GFX89-IEEE-NEXT:    v_div_fixup_f32 v0, v1, v0, s6
+; GFX89-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-FLUSH-LABEL: v_fdiv_f32_constlhs0_dynamic:
+; GFX89-FLUSH:       ; %bb.0:
+; GFX89-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-FLUSH-NEXT:    s_mov_b32 s6, 0x4640e400
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v1, s[4:5], v0, v0, s6
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v2, vcc, s6, v0, s6
+; GFX89-FLUSH-NEXT:    v_rcp_f32_e32 v3, v1
+; GFX89-FLUSH-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
+; GFX89-FLUSH-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX89-FLUSH-NEXT:    v_mul_f32_e32 v4, v2, v3
+; GFX89-FLUSH-NEXT:    v_fma_f32 v5, -v1, v4, v2
+; GFX89-FLUSH-NEXT:    v_fma_f32 v4, v5, v3, v4
+; GFX89-FLUSH-NEXT:    v_fma_f32 v1, -v1, v4, v2
+; GFX89-FLUSH-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
+; GFX89-FLUSH-NEXT:    v_div_fixup_f32 v0, v1, v0, s6
+; GFX89-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_f32_constlhs0_dynamic:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_div_scale_f32 v1, s4, v0, v0, 0x4640e400
+; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, 0x4640e400, v0, 0x4640e400
+; GFX10-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX10-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v2, v3, v2
+; GFX10-NEXT:    v_mul_f32_e32 v3, v4, v2
+; GFX10-NEXT:    v_fma_f32 v5, -v1, v3, v4
+; GFX10-NEXT:    v_fmac_f32_e32 v3, v5, v2
+; GFX10-NEXT:    v_fma_f32 v1, -v1, v3, v4
+; GFX10-NEXT:    v_div_fmas_f32 v1, v1, v2, v3
+; GFX10-NEXT:    v_div_fixup_f32 v0, v1, v0, 0x4640e400
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_f32_constlhs0_dynamic:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_div_scale_f32 v1, null, v0, v0, 0x4640e400
+; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, 0x4640e400, v0, 0x4640e400
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_2) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v2, v3, v2
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_mul_f32_e32 v3, v4, v2
+; GFX11-NEXT:    v_fma_f32 v5, -v1, v3, v4
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_fmac_f32_e32 v3, v5, v2
+; GFX11-NEXT:    v_fma_f32 v1, -v1, v3, v4
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_div_fmas_f32 v1, v1, v2, v3
+; GFX11-NEXT:    v_div_fixup_f32 v0, v1, v0, 0x4640e400
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_f32_constlhs0_dynamic:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %div = fdiv float 12345.0, %x
+  ret float %div
+}
+
+define float @v_fdiv_f32_constlhs0_dynamic_25ulp(float %x) #0 {
+; GFX6-LABEL: v_fdiv_f32_constlhs0_dynamic_25ulp:
+; GFX6:       ; %bb.0:
+; GFX6-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-NEXT:    v_frexp_mant_f32_e32 v1, v0
+; GFX6-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-NEXT:    v_cndmask_b32_e32 v1, v0, v1, vcc
+; GFX6-NEXT:    v_rcp_f32_e32 v1, v1
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v2, 0x4640e400
+; GFX6-NEXT:    v_sub_i32_e32 v0, vcc, v2, v0
+; GFX6-NEXT:    v_mul_f32_e32 v1, 0x3f40e400, v1
+; GFX6-NEXT:    v_ldexp_f32_e32 v0, v1, v0
+; GFX6-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_f32_constlhs0_dynamic_25ulp:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    v_frexp_mant_f32_e32 v1, v0
+; GFX7-NEXT:    v_rcp_f32_e32 v1, v1
+; GFX7-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, 14, v0
+; GFX7-NEXT:    v_mul_f32_e32 v1, 0x3f40e400, v1
+; GFX7-NEXT:    v_ldexp_f32_e32 v0, v1, v0
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_f32_constlhs0_dynamic_25ulp:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    v_frexp_mant_f32_e32 v1, v0
+; GFX8-NEXT:    v_rcp_f32_e32 v1, v1
+; GFX8-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, 14, v0
+; GFX8-NEXT:    v_mul_f32_e32 v1, 0x3f40e400, v1
+; GFX8-NEXT:    v_ldexp_f32 v0, v1, v0
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-LABEL: v_fdiv_f32_constlhs0_dynamic_25ulp:
+; GFX6-IEEE:       ; %bb.0:
+; GFX6-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-NEXT:    v_mov_b32_e32 v2, 0x7f800000
+; GFX6-IEEE-NEXT:    v_frexp_mant_f32_e32 v1, v0
+; GFX6-IEEE-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, v2
+; GFX6-IEEE-NEXT:    v_cndmask_b32_e32 v1, v0, v1, vcc
+; GFX6-IEEE-NEXT:    v_rcp_f32_e32 v1, v1
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v2, 0x4640e400
+; GFX6-IEEE-NEXT:    v_sub_i32_e32 v0, vcc, v2, v0
+; GFX6-IEEE-NEXT:    v_mul_f32_e32 v1, 0x3f40e400, v1
+; GFX6-IEEE-NEXT:    v_ldexp_f32_e32 v0, v1, v0
+; GFX6-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-LABEL: v_fdiv_f32_constlhs0_dynamic_25ulp:
+; GFX6-FLUSH:       ; %bb.0:
+; GFX6-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-NEXT:    v_mov_b32_e32 v2, 0x7f800000
+; GFX6-FLUSH-NEXT:    v_frexp_mant_f32_e32 v1, v0
+; GFX6-FLUSH-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, v2
+; GFX6-FLUSH-NEXT:    v_cndmask_b32_e32 v1, v0, v1, vcc
+; GFX6-FLUSH-NEXT:    v_rcp_f32_e32 v1, v1
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v2, 0x4640e400
+; GFX6-FLUSH-NEXT:    v_sub_i32_e32 v0, vcc, v2, v0
+; GFX6-FLUSH-NEXT:    v_mul_f32_e32 v1, 0x3f40e400, v1
+; GFX6-FLUSH-NEXT:    v_ldexp_f32_e32 v0, v1, v0
+; GFX6-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_f32_constlhs0_dynamic_25ulp:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_frexp_mant_f32_e32 v1, v0
+; GFX10-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX10-NEXT:    v_rcp_f32_e32 v1, v1
+; GFX10-NEXT:    v_sub_nc_u32_e32 v0, 14, v0
+; GFX10-NEXT:    v_mul_f32_e32 v1, 0x3f40e400, v1
+; GFX10-NEXT:    v_ldexp_f32 v0, v1, v0
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_f32_constlhs0_dynamic_25ulp:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_frexp_mant_f32_e32 v1, v0
+; GFX11-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_rcp_f32_e32 v1, v1
+; GFX11-NEXT:    v_sub_nc_u32_e32 v0, 14, v0
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_mul_f32_e32 v1, 0x3f40e400, v1
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1)
+; GFX11-NEXT:    v_ldexp_f32 v0, v1, v0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_f32_constlhs0_dynamic_25ulp:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %div = fdiv float 12345.0, %x, !fpmath !0
+  ret float %div
+}
+
+
+define float @v_fdiv_f32_dynamic_nodenorm_x(float nofpclass(sub) %x, float %y) #0 {
+; GFX6-FASTFMA-LABEL: v_fdiv_f32_dynamic_nodenorm_x:
+; GFX6-FASTFMA:       ; %bb.0:
+; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
+; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-SLOWFMA-LABEL: v_fdiv_f32_dynamic_nodenorm_x:
+; GFX6-SLOWFMA:       ; %bb.0:
+; GFX6-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_f32_dynamic_nodenorm_x:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX7-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX7-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX7-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX7-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
+; GFX7-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX7-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX7-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX7-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX7-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX7-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_f32_dynamic_nodenorm_x:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX8-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX8-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX8-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX8-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX8-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX8-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX8-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX8-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX8-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX8-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-FASTFMA-LABEL: v_fdiv_f32_dynamic_nodenorm_x:
+; GFX6-IEEE-FASTFMA:       ; %bb.0:
+; GFX6-IEEE-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-IEEE-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
+; GFX6-IEEE-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-IEEE-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-FASTFMA-LABEL: v_fdiv_f32_dynamic_nodenorm_x:
+; GFX6-FLUSH-FASTFMA:       ; %bb.0:
+; GFX6-FLUSH-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
+; GFX6-FLUSH-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-SLOWFMA-LABEL: v_fdiv_f32_dynamic_nodenorm_x:
+; GFX6-IEEE-SLOWFMA:       ; %bb.0:
+; GFX6-IEEE-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-SLOWFMA-LABEL: v_fdiv_f32_dynamic_nodenorm_x:
+; GFX6-FLUSH-SLOWFMA:       ; %bb.0:
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-IEEE-LABEL: v_fdiv_f32_dynamic_nodenorm_x:
+; GFX89-IEEE:       ; %bb.0:
+; GFX89-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX89-IEEE-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX89-IEEE-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX89-IEEE-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX89-IEEE-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX89-IEEE-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX89-IEEE-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX89-IEEE-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX89-IEEE-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX89-IEEE-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX89-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-FLUSH-LABEL: v_fdiv_f32_dynamic_nodenorm_x:
+; GFX89-FLUSH:       ; %bb.0:
+; GFX89-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX89-FLUSH-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX89-FLUSH-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX89-FLUSH-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX89-FLUSH-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX89-FLUSH-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX89-FLUSH-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX89-FLUSH-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX89-FLUSH-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX89-FLUSH-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX89-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_f32_dynamic_nodenorm_x:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_div_scale_f32 v2, s4, v1, v1, v0
+; GFX10-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
+; GFX10-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX10-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX10-NEXT:    v_mul_f32_e32 v4, v5, v3
+; GFX10-NEXT:    v_fma_f32 v6, -v2, v4, v5
+; GFX10-NEXT:    v_fmac_f32_e32 v4, v6, v3
+; GFX10-NEXT:    v_fma_f32 v2, -v2, v4, v5
+; GFX10-NEXT:    v_div_fmas_f32 v2, v2, v3, v4
+; GFX10-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_f32_dynamic_nodenorm_x:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_div_scale_f32 v2, null, v1, v1, v0
+; GFX11-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_2) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_mul_f32_e32 v4, v5, v3
+; GFX11-NEXT:    v_fma_f32 v6, -v2, v4, v5
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_fmac_f32_e32 v4, v6, v3
+; GFX11-NEXT:    v_fma_f32 v2, -v2, v4, v5
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_div_fmas_f32 v2, v2, v3, v4
+; GFX11-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_f32_dynamic_nodenorm_x:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %div = fdiv float %x, %y
+  ret float %div
+}
+
+define float @v_fdiv_f32_dynamic_25ulp_nodenorm_x(float nofpclass(sub) %x, float %y) #0 {
+; GFX6-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_x:
+; GFX6:       ; %bb.0:
+; GFX6-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX6-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-NEXT:    v_cndmask_b32_e32 v3, v0, v3, vcc
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_x:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX7-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX7-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX7-NEXT:    v_frexp_exp_i32_f32_e32 v3, v0
+; GFX7-NEXT:    v_frexp_mant_f32_e32 v0, v0
+; GFX7-NEXT:    v_mul_f32_e32 v0, v0, v2
+; GFX7-NEXT:    v_sub_i32_e32 v1, vcc, v3, v1
+; GFX7-NEXT:    v_ldexp_f32_e32 v0, v0, v1
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_x:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX8-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX8-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX8-NEXT:    v_frexp_exp_i32_f32_e32 v3, v0
+; GFX8-NEXT:    v_frexp_mant_f32_e32 v0, v0
+; GFX8-NEXT:    v_mul_f32_e32 v0, v0, v2
+; GFX8-NEXT:    v_sub_u32_e32 v1, vcc, v3, v1
+; GFX8-NEXT:    v_ldexp_f32 v0, v0, v1
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_x:
+; GFX6-IEEE:       ; %bb.0:
+; GFX6-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-IEEE-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-IEEE-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-IEEE-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-IEEE-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-IEEE-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX6-IEEE-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-IEEE-NEXT:    v_cndmask_b32_e32 v3, v0, v3, vcc
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-IEEE-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-IEEE-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-IEEE-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_x:
+; GFX6-FLUSH:       ; %bb.0:
+; GFX6-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-FLUSH-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-FLUSH-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-FLUSH-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-FLUSH-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-FLUSH-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX6-FLUSH-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-FLUSH-NEXT:    v_cndmask_b32_e32 v3, v0, v3, vcc
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-FLUSH-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-FLUSH-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-FLUSH-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_x:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX10-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX10-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX10-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX10-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX10-NEXT:    v_sub_nc_u32_e32 v0, v0, v1
+; GFX10-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX10-NEXT:    v_ldexp_f32 v0, v2, v0
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_x:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX11-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX11-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX11-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_4) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX11-NEXT:    v_sub_nc_u32_e32 v0, v0, v1
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1)
+; GFX11-NEXT:    v_ldexp_f32 v0, v2, v0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_x:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %div = fdiv float %x, %y, !fpmath !0
+  ret float %div
+}
+
+define float @v_fdiv_f32_dynamic_nodenorm_y(float %x, float nofpclass(sub) %y) #0 {
+; GFX6-FASTFMA-LABEL: v_fdiv_f32_dynamic_nodenorm_y:
+; GFX6-FASTFMA:       ; %bb.0:
+; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
+; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-SLOWFMA-LABEL: v_fdiv_f32_dynamic_nodenorm_y:
+; GFX6-SLOWFMA:       ; %bb.0:
+; GFX6-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_f32_dynamic_nodenorm_y:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX7-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX7-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX7-NEXT:    v_fma_f32 v3, v4, v3, v3
+; GFX7-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
+; GFX7-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX7-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX7-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX7-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX7-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX7-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_f32_dynamic_nodenorm_y:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX8-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX8-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX8-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX8-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX8-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX8-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX8-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX8-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX8-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX8-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-FASTFMA-LABEL: v_fdiv_f32_dynamic_nodenorm_y:
+; GFX6-IEEE-FASTFMA:       ; %bb.0:
+; GFX6-IEEE-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-IEEE-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
+; GFX6-IEEE-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX6-IEEE-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX6-IEEE-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-IEEE-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-FASTFMA-LABEL: v_fdiv_f32_dynamic_nodenorm_y:
+; GFX6-FLUSH-FASTFMA:       ; %bb.0:
+; GFX6-FLUSH-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
+; GFX6-FLUSH-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
+; GFX6-FLUSH-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
+; GFX6-FLUSH-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-FLUSH-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-SLOWFMA-LABEL: v_fdiv_f32_dynamic_nodenorm_y:
+; GFX6-IEEE-SLOWFMA:       ; %bb.0:
+; GFX6-IEEE-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-IEEE-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-IEEE-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-IEEE-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-SLOWFMA-LABEL: v_fdiv_f32_dynamic_nodenorm_y:
+; GFX6-FLUSH-SLOWFMA:       ; %bb.0:
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX6-FLUSH-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX6-FLUSH-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-IEEE-LABEL: v_fdiv_f32_dynamic_nodenorm_y:
+; GFX89-IEEE:       ; %bb.0:
+; GFX89-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX89-IEEE-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX89-IEEE-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX89-IEEE-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX89-IEEE-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX89-IEEE-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX89-IEEE-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX89-IEEE-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX89-IEEE-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX89-IEEE-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX89-IEEE-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX89-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX89-FLUSH-LABEL: v_fdiv_f32_dynamic_nodenorm_y:
+; GFX89-FLUSH:       ; %bb.0:
+; GFX89-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
+; GFX89-FLUSH-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
+; GFX89-FLUSH-NEXT:    v_rcp_f32_e32 v4, v2
+; GFX89-FLUSH-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
+; GFX89-FLUSH-NEXT:    v_fma_f32 v4, v5, v4, v4
+; GFX89-FLUSH-NEXT:    v_mul_f32_e32 v5, v3, v4
+; GFX89-FLUSH-NEXT:    v_fma_f32 v6, -v2, v5, v3
+; GFX89-FLUSH-NEXT:    v_fma_f32 v5, v6, v4, v5
+; GFX89-FLUSH-NEXT:    v_fma_f32 v2, -v2, v5, v3
+; GFX89-FLUSH-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
+; GFX89-FLUSH-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX89-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_f32_dynamic_nodenorm_y:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_div_scale_f32 v2, s4, v1, v1, v0
+; GFX10-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
+; GFX10-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX10-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX10-NEXT:    v_mul_f32_e32 v4, v5, v3
+; GFX10-NEXT:    v_fma_f32 v6, -v2, v4, v5
+; GFX10-NEXT:    v_fmac_f32_e32 v4, v6, v3
+; GFX10-NEXT:    v_fma_f32 v2, -v2, v4, v5
+; GFX10-NEXT:    v_div_fmas_f32 v2, v2, v3, v4
+; GFX10-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_f32_dynamic_nodenorm_y:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_div_scale_f32 v2, null, v1, v1, v0
+; GFX11-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_2) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_mul_f32_e32 v4, v5, v3
+; GFX11-NEXT:    v_fma_f32 v6, -v2, v4, v5
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_fmac_f32_e32 v4, v6, v3
+; GFX11-NEXT:    v_fma_f32 v2, -v2, v4, v5
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_div_fmas_f32 v2, v2, v3, v4
+; GFX11-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_f32_dynamic_nodenorm_y:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %div = fdiv float %x, %y
+  ret float %div
+}
+
+define float @v_fdiv_f32_dynamic_25ulp_nodenorm_y(float %x, float nofpclass(sub) %y) #0 {
+; GFX6-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_y:
+; GFX6:       ; %bb.0:
+; GFX6-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX6-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-NEXT:    v_cndmask_b32_e32 v3, v0, v3, vcc
+; GFX6-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX7-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_y:
+; GFX7:       ; %bb.0:
+; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX7-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX7-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX7-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX7-NEXT:    v_frexp_exp_i32_f32_e32 v3, v0
+; GFX7-NEXT:    v_frexp_mant_f32_e32 v0, v0
+; GFX7-NEXT:    v_mul_f32_e32 v0, v0, v2
+; GFX7-NEXT:    v_sub_i32_e32 v1, vcc, v3, v1
+; GFX7-NEXT:    v_ldexp_f32_e32 v0, v0, v1
+; GFX7-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX8-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_y:
+; GFX8:       ; %bb.0:
+; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX8-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX8-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX8-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX8-NEXT:    v_frexp_exp_i32_f32_e32 v3, v0
+; GFX8-NEXT:    v_frexp_mant_f32_e32 v0, v0
+; GFX8-NEXT:    v_mul_f32_e32 v0, v0, v2
+; GFX8-NEXT:    v_sub_u32_e32 v1, vcc, v3, v1
+; GFX8-NEXT:    v_ldexp_f32 v0, v0, v1
+; GFX8-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-IEEE-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_y:
+; GFX6-IEEE:       ; %bb.0:
+; GFX6-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-IEEE-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-IEEE-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-IEEE-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-IEEE-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-IEEE-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-IEEE-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX6-IEEE-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-IEEE-NEXT:    v_cndmask_b32_e32 v3, v0, v3, vcc
+; GFX6-IEEE-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-IEEE-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-IEEE-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-IEEE-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX6-FLUSH-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_y:
+; GFX6-FLUSH:       ; %bb.0:
+; GFX6-FLUSH-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX6-FLUSH-NEXT:    s_mov_b32 s4, 0x7f800000
+; GFX6-FLUSH-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX6-FLUSH-NEXT:    v_cmp_lt_f32_e64 vcc, |v1|, s4
+; GFX6-FLUSH-NEXT:    v_cndmask_b32_e32 v2, v1, v2, vcc
+; GFX6-FLUSH-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX6-FLUSH-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX6-FLUSH-NEXT:    v_cmp_lt_f32_e64 vcc, |v0|, s4
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX6-FLUSH-NEXT:    v_cndmask_b32_e32 v3, v0, v3, vcc
+; GFX6-FLUSH-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX6-FLUSH-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX6-FLUSH-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
+; GFX6-FLUSH-NEXT:    v_ldexp_f32_e32 v0, v2, v0
+; GFX6-FLUSH-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX10-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_y:
+; GFX10:       ; %bb.0:
+; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX10-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX10-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX10-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX10-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX10-NEXT:    v_sub_nc_u32_e32 v0, v0, v1
+; GFX10-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX10-NEXT:    v_ldexp_f32 v0, v2, v0
+; GFX10-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX11-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_y:
+; GFX11:       ; %bb.0:
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    v_frexp_mant_f32_e32 v2, v1
+; GFX11-NEXT:    v_frexp_exp_i32_f32_e32 v1, v1
+; GFX11-NEXT:    v_frexp_mant_f32_e32 v3, v0
+; GFX11-NEXT:    v_frexp_exp_i32_f32_e32 v0, v0
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_4) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT:    v_rcp_f32_e32 v2, v2
+; GFX11-NEXT:    v_sub_nc_u32_e32 v0, v0, v1
+; GFX11-NEXT:    s_waitcnt_depctr 0xfff
+; GFX11-NEXT:    v_mul_f32_e32 v2, v3, v2
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1)
+; GFX11-NEXT:    v_ldexp_f32 v0, v2, v0
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+; EG-LABEL: v_fdiv_f32_dynamic_25ulp_nodenorm_y:
+; EG:       ; %bb.0:
+; EG-NEXT:    CF_END
+; EG-NEXT:    PAD
+  %div = fdiv float %x, %y, !fpmath !0
+  ret float %div
+}
+
+!0 = !{float 2.500000e+00}
+
+attributes #0 = { "denormal-fp-math-f32"="dynamic,dynamic" }
+
 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
 ; GCN-IEEE: {{.*}}
-; GFX6-FLUSH: {{.*}}
diff --git a/llvm/test/CodeGen/AMDGPU/fdiv.ll b/llvm/test/CodeGen/AMDGPU/fdiv.ll
index 617ca447ec87efc..415f9087a372dc1 100644
--- a/llvm/test/CodeGen/AMDGPU/fdiv.ll
+++ b/llvm/test/CodeGen/AMDGPU/fdiv.ll
@@ -2416,15 +2416,13 @@ define float @v_fdiv_f32_dynamic_denorm(float %a, float %b) #2 {
 ; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
 ; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -2435,14 +2433,12 @@ define float @v_fdiv_f32_dynamic_denorm(float %a, float %b) #2 {
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -2452,15 +2448,13 @@ define float @v_fdiv_f32_dynamic_denorm(float %a, float %b) #2 {
 ; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX7-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX7-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX7-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX7-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX7-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX7-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX7-NEXT:    v_fma_f32 v3, v5, v3, v3
 ; GFX7-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX7-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX7-NEXT:    v_fma_f32 v5, v6, v3, v5
 ; GFX7-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX7-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX7-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX7-NEXT:    s_setpc_b64 s[30:31]
@@ -2471,14 +2465,12 @@ define float @v_fdiv_f32_dynamic_denorm(float %a, float %b) #2 {
 ; GFX8-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX8-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
 ; GFX8-NEXT:    v_rcp_f32_e32 v4, v2
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX8-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
 ; GFX8-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX8-NEXT:    v_mul_f32_e32 v5, v3, v4
 ; GFX8-NEXT:    v_fma_f32 v6, -v2, v5, v3
 ; GFX8-NEXT:    v_fma_f32 v5, v6, v4, v5
 ; GFX8-NEXT:    v_fma_f32 v2, -v2, v5, v3
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX8-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
 ; GFX8-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
@@ -2487,16 +2479,14 @@ define float @v_fdiv_f32_dynamic_denorm(float %a, float %b) #2 {
 ; GFX10:       ; %bb.0:
 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX10-NEXT:    v_div_scale_f32 v2, s4, v1, v1, v0
-; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX10-NEXT:    v_rcp_f32_e32 v3, v2
-; GFX10-NEXT:    s_denorm_mode 15
-; GFX10-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX10-NEXT:    v_fmac_f32_e32 v3, v5, v3
+; GFX10-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX10-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX10-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX10-NEXT:    v_fmac_f32_e32 v5, v6, v3
 ; GFX10-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX10-NEXT:    s_denorm_mode 12
 ; GFX10-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX10-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
@@ -2505,17 +2495,15 @@ define float @v_fdiv_f32_dynamic_denorm(float %a, float %b) #2 {
 ; GFX11:       ; %bb.0:
 ; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX11-NEXT:    v_div_scale_f32 v2, null, v1, v1, v0
-; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX11-NEXT:    v_rcp_f32_e32 v3, v2
-; GFX11-NEXT:    s_denorm_mode 15
 ; GFX11-NEXT:    s_waitcnt_depctr 0xfff
-; GFX11-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX11-NEXT:    v_fmac_f32_e32 v3, v5, v3
+; GFX11-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX11-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX11-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX11-NEXT:    v_fmac_f32_e32 v5, v6, v3
 ; GFX11-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX11-NEXT:    s_denorm_mode 12
 ; GFX11-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX11-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX11-NEXT:    s_setpc_b64 s[30:31]
@@ -2720,15 +2708,13 @@ define float @v_fdiv_f32_dynamic(float %x, float %y) #2 {
 ; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
 ; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -2739,14 +2725,12 @@ define float @v_fdiv_f32_dynamic(float %x, float %y) #2 {
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -2756,15 +2740,13 @@ define float @v_fdiv_f32_dynamic(float %x, float %y) #2 {
 ; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX7-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX7-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX7-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX7-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX7-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX7-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX7-NEXT:    v_fma_f32 v3, v5, v3, v3
 ; GFX7-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX7-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX7-NEXT:    v_fma_f32 v5, v6, v3, v5
 ; GFX7-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX7-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX7-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX7-NEXT:    s_setpc_b64 s[30:31]
@@ -2775,14 +2757,12 @@ define float @v_fdiv_f32_dynamic(float %x, float %y) #2 {
 ; GFX8-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX8-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
 ; GFX8-NEXT:    v_rcp_f32_e32 v4, v2
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX8-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
 ; GFX8-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX8-NEXT:    v_mul_f32_e32 v5, v3, v4
 ; GFX8-NEXT:    v_fma_f32 v6, -v2, v5, v3
 ; GFX8-NEXT:    v_fma_f32 v5, v6, v4, v5
 ; GFX8-NEXT:    v_fma_f32 v2, -v2, v5, v3
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX8-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
 ; GFX8-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
@@ -2791,16 +2771,14 @@ define float @v_fdiv_f32_dynamic(float %x, float %y) #2 {
 ; GFX10:       ; %bb.0:
 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX10-NEXT:    v_div_scale_f32 v2, s4, v1, v1, v0
-; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX10-NEXT:    v_rcp_f32_e32 v3, v2
-; GFX10-NEXT:    s_denorm_mode 15
-; GFX10-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX10-NEXT:    v_fmac_f32_e32 v3, v5, v3
+; GFX10-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX10-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX10-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX10-NEXT:    v_fmac_f32_e32 v5, v6, v3
 ; GFX10-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX10-NEXT:    s_denorm_mode 12
 ; GFX10-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX10-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
@@ -2809,17 +2787,15 @@ define float @v_fdiv_f32_dynamic(float %x, float %y) #2 {
 ; GFX11:       ; %bb.0:
 ; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX11-NEXT:    v_div_scale_f32 v2, null, v1, v1, v0
-; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX11-NEXT:    v_rcp_f32_e32 v3, v2
-; GFX11-NEXT:    s_denorm_mode 15
 ; GFX11-NEXT:    s_waitcnt_depctr 0xfff
-; GFX11-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX11-NEXT:    v_fmac_f32_e32 v3, v5, v3
+; GFX11-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX11-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX11-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX11-NEXT:    v_fmac_f32_e32 v5, v6, v3
 ; GFX11-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX11-NEXT:    s_denorm_mode 12
 ; GFX11-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX11-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX11-NEXT:    s_setpc_b64 s[30:31]
@@ -3281,15 +3257,13 @@ define float @v_fdiv_f32_dynamic_contractable_user(float %x, float %y, float %z)
 ; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v3, s[4:5], v1, v1, v0
 ; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v5, vcc, v0, v1, v0
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, -v3, v4, 1.0
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, v6, v4, v4
 ; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v6, v5, v4
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v7, -v3, v6, v5
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, v7, v4, v6
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, -v3, v6, v5
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v3, v3, v4, v6
 ; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v3, v1, v0
 ; GFX6-FASTFMA-NEXT:    v_add_f32_e32 v0, v0, v2
@@ -3301,14 +3275,12 @@ define float @v_fdiv_f32_dynamic_contractable_user(float %x, float %y, float %z)
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v3, s[4:5], v1, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v5, v3
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, -v3, v5, 1.0
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v5, v5
 ; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v6, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v7, -v3, v6, v4
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, v7, v5, v6
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v3, -v3, v6, v4
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v3, v3, v5, v6
 ; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v3, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_add_f32_e32 v0, v0, v2
@@ -3319,15 +3291,13 @@ define float @v_fdiv_f32_dynamic_contractable_user(float %x, float %y, float %z)
 ; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX7-NEXT:    v_div_scale_f32 v3, s[4:5], v1, v1, v0
 ; GFX7-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX7-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX7-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX7-NEXT:    v_div_scale_f32 v5, vcc, v0, v1, v0
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX7-NEXT:    v_fma_f32 v6, -v3, v4, 1.0
-; GFX7-NEXT:    v_fma_f32 v4, v6, v4, v4
 ; GFX7-NEXT:    v_mul_f32_e32 v6, v5, v4
 ; GFX7-NEXT:    v_fma_f32 v7, -v3, v6, v5
 ; GFX7-NEXT:    v_fma_f32 v6, v7, v4, v6
 ; GFX7-NEXT:    v_fma_f32 v3, -v3, v6, v5
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX7-NEXT:    v_div_fmas_f32 v3, v3, v4, v6
 ; GFX7-NEXT:    v_div_fixup_f32 v0, v3, v1, v0
 ; GFX7-NEXT:    v_add_f32_e32 v0, v0, v2
@@ -3339,14 +3309,12 @@ define float @v_fdiv_f32_dynamic_contractable_user(float %x, float %y, float %z)
 ; GFX8-NEXT:    v_div_scale_f32 v3, s[4:5], v1, v1, v0
 ; GFX8-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
 ; GFX8-NEXT:    v_rcp_f32_e32 v5, v3
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX8-NEXT:    v_fma_f32 v6, -v3, v5, 1.0
 ; GFX8-NEXT:    v_fma_f32 v5, v6, v5, v5
 ; GFX8-NEXT:    v_mul_f32_e32 v6, v4, v5
 ; GFX8-NEXT:    v_fma_f32 v7, -v3, v6, v4
 ; GFX8-NEXT:    v_fma_f32 v6, v7, v5, v6
 ; GFX8-NEXT:    v_fma_f32 v3, -v3, v6, v4
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX8-NEXT:    v_div_fmas_f32 v3, v3, v5, v6
 ; GFX8-NEXT:    v_div_fixup_f32 v0, v3, v1, v0
 ; GFX8-NEXT:    v_add_f32_e32 v0, v0, v2
@@ -3356,16 +3324,14 @@ define float @v_fdiv_f32_dynamic_contractable_user(float %x, float %y, float %z)
 ; GFX10:       ; %bb.0:
 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX10-NEXT:    v_div_scale_f32 v3, s4, v1, v1, v0
-; GFX10-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
 ; GFX10-NEXT:    v_rcp_f32_e32 v4, v3
-; GFX10-NEXT:    s_denorm_mode 15
-; GFX10-NEXT:    v_fma_f32 v6, -v3, v4, 1.0
-; GFX10-NEXT:    v_fmac_f32_e32 v4, v6, v4
+; GFX10-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v4, v5, v4
+; GFX10-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
 ; GFX10-NEXT:    v_mul_f32_e32 v6, v5, v4
 ; GFX10-NEXT:    v_fma_f32 v7, -v3, v6, v5
 ; GFX10-NEXT:    v_fmac_f32_e32 v6, v7, v4
 ; GFX10-NEXT:    v_fma_f32 v3, -v3, v6, v5
-; GFX10-NEXT:    s_denorm_mode 12
 ; GFX10-NEXT:    v_div_fmas_f32 v3, v3, v4, v6
 ; GFX10-NEXT:    v_div_fixup_f32 v0, v3, v1, v0
 ; GFX10-NEXT:    v_add_f32_e32 v0, v0, v2
@@ -3375,17 +3341,15 @@ define float @v_fdiv_f32_dynamic_contractable_user(float %x, float %y, float %z)
 ; GFX11:       ; %bb.0:
 ; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX11-NEXT:    v_div_scale_f32 v3, null, v1, v1, v0
-; GFX11-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
 ; GFX11-NEXT:    v_rcp_f32_e32 v4, v3
-; GFX11-NEXT:    s_denorm_mode 15
 ; GFX11-NEXT:    s_waitcnt_depctr 0xfff
-; GFX11-NEXT:    v_fma_f32 v6, -v3, v4, 1.0
-; GFX11-NEXT:    v_fmac_f32_e32 v4, v6, v4
+; GFX11-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v4, v5, v4
+; GFX11-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
 ; GFX11-NEXT:    v_mul_f32_e32 v6, v5, v4
 ; GFX11-NEXT:    v_fma_f32 v7, -v3, v6, v5
 ; GFX11-NEXT:    v_fmac_f32_e32 v6, v7, v4
 ; GFX11-NEXT:    v_fma_f32 v3, -v3, v6, v5
-; GFX11-NEXT:    s_denorm_mode 12
 ; GFX11-NEXT:    v_div_fmas_f32 v3, v3, v4, v6
 ; GFX11-NEXT:    v_div_fixup_f32 v0, v3, v1, v0
 ; GFX11-NEXT:    v_add_f32_e32 v0, v0, v2
@@ -3849,15 +3813,13 @@ define float @v_fdiv_f32_dynamic__nnan_ninf(float %x, float %y, float %z) #2 {
 ; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
 ; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -3868,14 +3830,12 @@ define float @v_fdiv_f32_dynamic__nnan_ninf(float %x, float %y, float %z) #2 {
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -3885,15 +3845,13 @@ define float @v_fdiv_f32_dynamic__nnan_ninf(float %x, float %y, float %z) #2 {
 ; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX7-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX7-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX7-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX7-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX7-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX7-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX7-NEXT:    v_fma_f32 v3, v5, v3, v3
 ; GFX7-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX7-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX7-NEXT:    v_fma_f32 v5, v6, v3, v5
 ; GFX7-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX7-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX7-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX7-NEXT:    s_setpc_b64 s[30:31]
@@ -3904,14 +3862,12 @@ define float @v_fdiv_f32_dynamic__nnan_ninf(float %x, float %y, float %z) #2 {
 ; GFX8-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX8-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
 ; GFX8-NEXT:    v_rcp_f32_e32 v4, v2
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX8-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
 ; GFX8-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX8-NEXT:    v_mul_f32_e32 v5, v3, v4
 ; GFX8-NEXT:    v_fma_f32 v6, -v2, v5, v3
 ; GFX8-NEXT:    v_fma_f32 v5, v6, v4, v5
 ; GFX8-NEXT:    v_fma_f32 v2, -v2, v5, v3
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX8-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
 ; GFX8-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
@@ -3920,16 +3876,14 @@ define float @v_fdiv_f32_dynamic__nnan_ninf(float %x, float %y, float %z) #2 {
 ; GFX10:       ; %bb.0:
 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX10-NEXT:    v_div_scale_f32 v2, s4, v1, v1, v0
-; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX10-NEXT:    v_rcp_f32_e32 v3, v2
-; GFX10-NEXT:    s_denorm_mode 15
-; GFX10-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX10-NEXT:    v_fmac_f32_e32 v3, v5, v3
+; GFX10-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX10-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX10-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX10-NEXT:    v_fmac_f32_e32 v5, v6, v3
 ; GFX10-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX10-NEXT:    s_denorm_mode 12
 ; GFX10-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX10-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
@@ -3938,17 +3892,15 @@ define float @v_fdiv_f32_dynamic__nnan_ninf(float %x, float %y, float %z) #2 {
 ; GFX11:       ; %bb.0:
 ; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX11-NEXT:    v_div_scale_f32 v2, null, v1, v1, v0
-; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX11-NEXT:    v_rcp_f32_e32 v3, v2
-; GFX11-NEXT:    s_denorm_mode 15
 ; GFX11-NEXT:    s_waitcnt_depctr 0xfff
-; GFX11-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX11-NEXT:    v_fmac_f32_e32 v3, v5, v3
+; GFX11-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX11-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX11-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX11-NEXT:    v_fmac_f32_e32 v5, v6, v3
 ; GFX11-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX11-NEXT:    s_denorm_mode 12
 ; GFX11-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX11-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX11-NEXT:    s_setpc_b64 s[30:31]
@@ -4409,15 +4361,13 @@ define float @v_fdiv_f32_dynamic__nnan_ninf_contractable_user(float %x, float %y
 ; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v3, s[4:5], v1, v1, v0
 ; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v5, vcc, v0, v1, v0
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, -v3, v4, 1.0
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, v6, v4, v4
 ; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v6, v5, v4
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v7, -v3, v6, v5
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, v7, v4, v6
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, -v3, v6, v5
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v3, v3, v4, v6
 ; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v3, v1, v0
 ; GFX6-FASTFMA-NEXT:    v_add_f32_e32 v0, v0, v2
@@ -4429,14 +4379,12 @@ define float @v_fdiv_f32_dynamic__nnan_ninf_contractable_user(float %x, float %y
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v3, s[4:5], v1, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v5, v3
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, -v3, v5, 1.0
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v5, v5
 ; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v6, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v7, -v3, v6, v4
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, v7, v5, v6
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v3, -v3, v6, v4
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v3, v3, v5, v6
 ; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v3, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_add_f32_e32 v0, v0, v2
@@ -4447,15 +4395,13 @@ define float @v_fdiv_f32_dynamic__nnan_ninf_contractable_user(float %x, float %y
 ; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX7-NEXT:    v_div_scale_f32 v3, s[4:5], v1, v1, v0
 ; GFX7-NEXT:    v_rcp_f32_e32 v4, v3
+; GFX7-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX7-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX7-NEXT:    v_div_scale_f32 v5, vcc, v0, v1, v0
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX7-NEXT:    v_fma_f32 v6, -v3, v4, 1.0
-; GFX7-NEXT:    v_fma_f32 v4, v6, v4, v4
 ; GFX7-NEXT:    v_mul_f32_e32 v6, v5, v4
 ; GFX7-NEXT:    v_fma_f32 v7, -v3, v6, v5
 ; GFX7-NEXT:    v_fma_f32 v6, v7, v4, v6
 ; GFX7-NEXT:    v_fma_f32 v3, -v3, v6, v5
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX7-NEXT:    v_div_fmas_f32 v3, v3, v4, v6
 ; GFX7-NEXT:    v_div_fixup_f32 v0, v3, v1, v0
 ; GFX7-NEXT:    v_add_f32_e32 v0, v0, v2
@@ -4467,14 +4413,12 @@ define float @v_fdiv_f32_dynamic__nnan_ninf_contractable_user(float %x, float %y
 ; GFX8-NEXT:    v_div_scale_f32 v3, s[4:5], v1, v1, v0
 ; GFX8-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
 ; GFX8-NEXT:    v_rcp_f32_e32 v5, v3
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX8-NEXT:    v_fma_f32 v6, -v3, v5, 1.0
 ; GFX8-NEXT:    v_fma_f32 v5, v6, v5, v5
 ; GFX8-NEXT:    v_mul_f32_e32 v6, v4, v5
 ; GFX8-NEXT:    v_fma_f32 v7, -v3, v6, v4
 ; GFX8-NEXT:    v_fma_f32 v6, v7, v5, v6
 ; GFX8-NEXT:    v_fma_f32 v3, -v3, v6, v4
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX8-NEXT:    v_div_fmas_f32 v3, v3, v5, v6
 ; GFX8-NEXT:    v_div_fixup_f32 v0, v3, v1, v0
 ; GFX8-NEXT:    v_add_f32_e32 v0, v0, v2
@@ -4484,16 +4428,14 @@ define float @v_fdiv_f32_dynamic__nnan_ninf_contractable_user(float %x, float %y
 ; GFX10:       ; %bb.0:
 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX10-NEXT:    v_div_scale_f32 v3, s4, v1, v1, v0
-; GFX10-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
 ; GFX10-NEXT:    v_rcp_f32_e32 v4, v3
-; GFX10-NEXT:    s_denorm_mode 15
-; GFX10-NEXT:    v_fma_f32 v6, -v3, v4, 1.0
-; GFX10-NEXT:    v_fmac_f32_e32 v4, v6, v4
+; GFX10-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v4, v5, v4
+; GFX10-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
 ; GFX10-NEXT:    v_mul_f32_e32 v6, v5, v4
 ; GFX10-NEXT:    v_fma_f32 v7, -v3, v6, v5
 ; GFX10-NEXT:    v_fmac_f32_e32 v6, v7, v4
 ; GFX10-NEXT:    v_fma_f32 v3, -v3, v6, v5
-; GFX10-NEXT:    s_denorm_mode 12
 ; GFX10-NEXT:    v_div_fmas_f32 v3, v3, v4, v6
 ; GFX10-NEXT:    v_div_fixup_f32 v0, v3, v1, v0
 ; GFX10-NEXT:    v_add_f32_e32 v0, v0, v2
@@ -4503,17 +4445,15 @@ define float @v_fdiv_f32_dynamic__nnan_ninf_contractable_user(float %x, float %y
 ; GFX11:       ; %bb.0:
 ; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX11-NEXT:    v_div_scale_f32 v3, null, v1, v1, v0
-; GFX11-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
 ; GFX11-NEXT:    v_rcp_f32_e32 v4, v3
-; GFX11-NEXT:    s_denorm_mode 15
 ; GFX11-NEXT:    s_waitcnt_depctr 0xfff
-; GFX11-NEXT:    v_fma_f32 v6, -v3, v4, 1.0
-; GFX11-NEXT:    v_fmac_f32_e32 v4, v6, v4
+; GFX11-NEXT:    v_fma_f32 v5, -v3, v4, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v4, v5, v4
+; GFX11-NEXT:    v_div_scale_f32 v5, vcc_lo, v0, v1, v0
 ; GFX11-NEXT:    v_mul_f32_e32 v6, v5, v4
 ; GFX11-NEXT:    v_fma_f32 v7, -v3, v6, v5
 ; GFX11-NEXT:    v_fmac_f32_e32 v6, v7, v4
 ; GFX11-NEXT:    v_fma_f32 v3, -v3, v6, v5
-; GFX11-NEXT:    s_denorm_mode 12
 ; GFX11-NEXT:    v_div_fmas_f32 v3, v3, v4, v6
 ; GFX11-NEXT:    v_div_fixup_f32 v0, v3, v1, v0
 ; GFX11-NEXT:    v_add_f32_e32 v0, v0, v2
@@ -4979,15 +4919,13 @@ define float @v_fdiv_neglhs_f32_dynamic(float %x, float %y) #2 {
 ; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, -v0
 ; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, -v0, v1, -v0
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
 ; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
 ; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -4998,14 +4936,12 @@ define float @v_fdiv_neglhs_f32_dynamic(float %x, float %y) #2 {
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, -v0
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, -v0, v1, -v0
 ; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
 ; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -5015,15 +4951,13 @@ define float @v_fdiv_neglhs_f32_dynamic(float %x, float %y) #2 {
 ; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX7-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, -v0
 ; GFX7-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX7-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX7-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX7-NEXT:    v_div_scale_f32 v4, vcc, -v0, v1, -v0
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX7-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX7-NEXT:    v_fma_f32 v3, v5, v3, v3
 ; GFX7-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX7-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX7-NEXT:    v_fma_f32 v5, v6, v3, v5
 ; GFX7-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX7-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX7-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
 ; GFX7-NEXT:    s_setpc_b64 s[30:31]
@@ -5034,14 +4968,12 @@ define float @v_fdiv_neglhs_f32_dynamic(float %x, float %y) #2 {
 ; GFX8-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, -v0
 ; GFX8-NEXT:    v_div_scale_f32 v3, vcc, -v0, v1, -v0
 ; GFX8-NEXT:    v_rcp_f32_e32 v4, v2
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX8-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
 ; GFX8-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX8-NEXT:    v_mul_f32_e32 v5, v3, v4
 ; GFX8-NEXT:    v_fma_f32 v6, -v2, v5, v3
 ; GFX8-NEXT:    v_fma_f32 v5, v6, v4, v5
 ; GFX8-NEXT:    v_fma_f32 v2, -v2, v5, v3
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX8-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
 ; GFX8-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
@@ -5050,16 +4982,14 @@ define float @v_fdiv_neglhs_f32_dynamic(float %x, float %y) #2 {
 ; GFX10:       ; %bb.0:
 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX10-NEXT:    v_div_scale_f32 v2, s4, v1, v1, -v0
-; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, -v0, v1, -v0
 ; GFX10-NEXT:    v_rcp_f32_e32 v3, v2
-; GFX10-NEXT:    s_denorm_mode 15
-; GFX10-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX10-NEXT:    v_fmac_f32_e32 v3, v5, v3
+; GFX10-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, -v0, v1, -v0
 ; GFX10-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX10-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX10-NEXT:    v_fmac_f32_e32 v5, v6, v3
 ; GFX10-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX10-NEXT:    s_denorm_mode 12
 ; GFX10-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX10-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
@@ -5068,17 +4998,15 @@ define float @v_fdiv_neglhs_f32_dynamic(float %x, float %y) #2 {
 ; GFX11:       ; %bb.0:
 ; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX11-NEXT:    v_div_scale_f32 v2, null, v1, v1, -v0
-; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, -v0, v1, -v0
 ; GFX11-NEXT:    v_rcp_f32_e32 v3, v2
-; GFX11-NEXT:    s_denorm_mode 15
 ; GFX11-NEXT:    s_waitcnt_depctr 0xfff
-; GFX11-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX11-NEXT:    v_fmac_f32_e32 v3, v5, v3
+; GFX11-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, -v0, v1, -v0
 ; GFX11-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX11-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX11-NEXT:    v_fmac_f32_e32 v5, v6, v3
 ; GFX11-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX11-NEXT:    s_denorm_mode 12
 ; GFX11-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX11-NEXT:    v_div_fixup_f32 v0, v2, v1, -v0
 ; GFX11-NEXT:    s_setpc_b64 s[30:31]
@@ -5532,15 +5460,13 @@ define float @v_fdiv_negrhs_f32_dynamic(float %x, float %y) #2 {
 ; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], -v1, -v1, v0
 ; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, -v1, v0
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
 ; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
 ; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -5551,14 +5477,12 @@ define float @v_fdiv_negrhs_f32_dynamic(float %x, float %y) #2 {
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], -v1, -v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, -v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
 ; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -5568,15 +5492,13 @@ define float @v_fdiv_negrhs_f32_dynamic(float %x, float %y) #2 {
 ; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX7-NEXT:    v_div_scale_f32 v2, s[4:5], -v1, -v1, v0
 ; GFX7-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX7-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX7-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX7-NEXT:    v_div_scale_f32 v4, vcc, v0, -v1, v0
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX7-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX7-NEXT:    v_fma_f32 v3, v5, v3, v3
 ; GFX7-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX7-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX7-NEXT:    v_fma_f32 v5, v6, v3, v5
 ; GFX7-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX7-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX7-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
 ; GFX7-NEXT:    s_setpc_b64 s[30:31]
@@ -5587,14 +5509,12 @@ define float @v_fdiv_negrhs_f32_dynamic(float %x, float %y) #2 {
 ; GFX8-NEXT:    v_div_scale_f32 v2, s[4:5], -v1, -v1, v0
 ; GFX8-NEXT:    v_div_scale_f32 v3, vcc, v0, -v1, v0
 ; GFX8-NEXT:    v_rcp_f32_e32 v4, v2
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX8-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
 ; GFX8-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX8-NEXT:    v_mul_f32_e32 v5, v3, v4
 ; GFX8-NEXT:    v_fma_f32 v6, -v2, v5, v3
 ; GFX8-NEXT:    v_fma_f32 v5, v6, v4, v5
 ; GFX8-NEXT:    v_fma_f32 v2, -v2, v5, v3
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX8-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
 ; GFX8-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
@@ -5603,16 +5523,14 @@ define float @v_fdiv_negrhs_f32_dynamic(float %x, float %y) #2 {
 ; GFX10:       ; %bb.0:
 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX10-NEXT:    v_div_scale_f32 v2, s4, -v1, -v1, v0
-; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, -v1, v0
 ; GFX10-NEXT:    v_rcp_f32_e32 v3, v2
-; GFX10-NEXT:    s_denorm_mode 15
-; GFX10-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX10-NEXT:    v_fmac_f32_e32 v3, v5, v3
+; GFX10-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, -v1, v0
 ; GFX10-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX10-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX10-NEXT:    v_fmac_f32_e32 v5, v6, v3
 ; GFX10-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX10-NEXT:    s_denorm_mode 12
 ; GFX10-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX10-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
@@ -5621,17 +5539,15 @@ define float @v_fdiv_negrhs_f32_dynamic(float %x, float %y) #2 {
 ; GFX11:       ; %bb.0:
 ; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX11-NEXT:    v_div_scale_f32 v2, null, -v1, -v1, v0
-; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, -v1, v0
 ; GFX11-NEXT:    v_rcp_f32_e32 v3, v2
-; GFX11-NEXT:    s_denorm_mode 15
 ; GFX11-NEXT:    s_waitcnt_depctr 0xfff
-; GFX11-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX11-NEXT:    v_fmac_f32_e32 v3, v5, v3
+; GFX11-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, -v1, v0
 ; GFX11-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX11-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX11-NEXT:    v_fmac_f32_e32 v5, v6, v3
 ; GFX11-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX11-NEXT:    s_denorm_mode 12
 ; GFX11-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX11-NEXT:    v_div_fixup_f32 v0, v2, -v1, v0
 ; GFX11-NEXT:    s_setpc_b64 s[30:31]
@@ -6070,15 +5986,13 @@ define float @v_fdiv_f32_constrhs0_dynamic(float %x) #2 {
 ; GFX6-FASTFMA-NEXT:    s_mov_b32 s6, 0x4640e400
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v1, s[4:5], s6, s6, v0
 ; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, v3, v2, v2
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, s6, v0
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, -v1, v2, 1.0
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, v4, v2, v2
 ; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v4, v3, v2
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, -v1, v4, v3
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, v5, v2, v4
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v1, -v1, v4, v3
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
 ; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v1, s6, v0
 ; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -6090,14 +6004,12 @@ define float @v_fdiv_f32_constrhs0_dynamic(float %x) #2 {
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v1, s[4:5], s6, s6, v0
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, vcc, v0, s6, v0
 ; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v3, v1
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v4, v2, v3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v1, v4, v2
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v3, v4
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v1, -v1, v4, v2
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
 ; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v1, s6, v0
 ; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -6108,15 +6020,13 @@ define float @v_fdiv_f32_constrhs0_dynamic(float %x) #2 {
 ; GFX7-NEXT:    s_mov_b32 s6, 0x4640e400
 ; GFX7-NEXT:    v_div_scale_f32 v1, s[4:5], s6, s6, v0
 ; GFX7-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX7-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX7-NEXT:    v_fma_f32 v2, v3, v2, v2
 ; GFX7-NEXT:    v_div_scale_f32 v3, vcc, v0, s6, v0
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX7-NEXT:    v_fma_f32 v4, -v1, v2, 1.0
-; GFX7-NEXT:    v_fma_f32 v2, v4, v2, v2
 ; GFX7-NEXT:    v_mul_f32_e32 v4, v3, v2
 ; GFX7-NEXT:    v_fma_f32 v5, -v1, v4, v3
 ; GFX7-NEXT:    v_fma_f32 v4, v5, v2, v4
 ; GFX7-NEXT:    v_fma_f32 v1, -v1, v4, v3
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX7-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
 ; GFX7-NEXT:    v_div_fixup_f32 v0, v1, s6, v0
 ; GFX7-NEXT:    s_setpc_b64 s[30:31]
@@ -6128,14 +6038,12 @@ define float @v_fdiv_f32_constrhs0_dynamic(float %x) #2 {
 ; GFX8-NEXT:    v_div_scale_f32 v1, s[4:5], s6, s6, v0
 ; GFX8-NEXT:    v_div_scale_f32 v2, vcc, v0, s6, v0
 ; GFX8-NEXT:    v_rcp_f32_e32 v3, v1
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX8-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
 ; GFX8-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX8-NEXT:    v_mul_f32_e32 v4, v2, v3
 ; GFX8-NEXT:    v_fma_f32 v5, -v1, v4, v2
 ; GFX8-NEXT:    v_fma_f32 v4, v5, v3, v4
 ; GFX8-NEXT:    v_fma_f32 v1, -v1, v4, v2
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX8-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
 ; GFX8-NEXT:    v_div_fixup_f32 v0, v1, s6, v0
 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
@@ -6144,16 +6052,14 @@ define float @v_fdiv_f32_constrhs0_dynamic(float %x) #2 {
 ; GFX10:       ; %bb.0:
 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX10-NEXT:    v_div_scale_f32 v1, s4, 0x4640e400, 0x4640e400, v0
-; GFX10-NEXT:    v_div_scale_f32 v3, vcc_lo, v0, 0x4640e400, v0
 ; GFX10-NEXT:    v_rcp_f32_e32 v2, v1
-; GFX10-NEXT:    s_denorm_mode 15
-; GFX10-NEXT:    v_fma_f32 v4, -v1, v2, 1.0
-; GFX10-NEXT:    v_fmac_f32_e32 v2, v4, v2
+; GFX10-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v2, v3, v2
+; GFX10-NEXT:    v_div_scale_f32 v3, vcc_lo, v0, 0x4640e400, v0
 ; GFX10-NEXT:    v_mul_f32_e32 v4, v3, v2
 ; GFX10-NEXT:    v_fma_f32 v5, -v1, v4, v3
 ; GFX10-NEXT:    v_fmac_f32_e32 v4, v5, v2
 ; GFX10-NEXT:    v_fma_f32 v1, -v1, v4, v3
-; GFX10-NEXT:    s_denorm_mode 12
 ; GFX10-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
 ; GFX10-NEXT:    v_div_fixup_f32 v0, v1, 0x4640e400, v0
 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
@@ -6162,17 +6068,15 @@ define float @v_fdiv_f32_constrhs0_dynamic(float %x) #2 {
 ; GFX11:       ; %bb.0:
 ; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX11-NEXT:    v_div_scale_f32 v1, null, 0x4640e400, 0x4640e400, v0
-; GFX11-NEXT:    v_div_scale_f32 v3, vcc_lo, v0, 0x4640e400, v0
 ; GFX11-NEXT:    v_rcp_f32_e32 v2, v1
-; GFX11-NEXT:    s_denorm_mode 15
 ; GFX11-NEXT:    s_waitcnt_depctr 0xfff
-; GFX11-NEXT:    v_fma_f32 v4, -v1, v2, 1.0
-; GFX11-NEXT:    v_fmac_f32_e32 v2, v4, v2
+; GFX11-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v2, v3, v2
+; GFX11-NEXT:    v_div_scale_f32 v3, vcc_lo, v0, 0x4640e400, v0
 ; GFX11-NEXT:    v_mul_f32_e32 v4, v3, v2
 ; GFX11-NEXT:    v_fma_f32 v5, -v1, v4, v3
 ; GFX11-NEXT:    v_fmac_f32_e32 v4, v5, v2
 ; GFX11-NEXT:    v_fma_f32 v1, -v1, v4, v3
-; GFX11-NEXT:    s_denorm_mode 12
 ; GFX11-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
 ; GFX11-NEXT:    v_div_fixup_f32 v0, v1, 0x4640e400, v0
 ; GFX11-NEXT:    s_setpc_b64 s[30:31]
@@ -6570,15 +6474,13 @@ define float @v_fdiv_f32_constlhs0_dynamic(float %x) #2 {
 ; GFX6-FASTFMA-NEXT:    s_mov_b32 s6, 0x4640e400
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v1, s[4:5], v0, v0, s6
 ; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, v3, v2, v2
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v3, vcc, s6, v0, s6
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, -v1, v2, 1.0
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, v4, v2, v2
 ; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v4, v3, v2
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, -v1, v4, v3
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, v5, v2, v4
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v1, -v1, v4, v3
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
 ; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v1, v0, s6
 ; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -6590,14 +6492,12 @@ define float @v_fdiv_f32_constlhs0_dynamic(float %x) #2 {
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v1, s[4:5], v0, v0, s6
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, vcc, s6, v0, s6
 ; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v3, v1
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v4, v2, v3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v1, v4, v2
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v3, v4
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v1, -v1, v4, v2
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
 ; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v1, v0, s6
 ; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -6608,15 +6508,13 @@ define float @v_fdiv_f32_constlhs0_dynamic(float %x) #2 {
 ; GFX7-NEXT:    s_mov_b32 s6, 0x4640e400
 ; GFX7-NEXT:    v_div_scale_f32 v1, s[4:5], v0, v0, s6
 ; GFX7-NEXT:    v_rcp_f32_e32 v2, v1
+; GFX7-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX7-NEXT:    v_fma_f32 v2, v3, v2, v2
 ; GFX7-NEXT:    v_div_scale_f32 v3, vcc, s6, v0, s6
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX7-NEXT:    v_fma_f32 v4, -v1, v2, 1.0
-; GFX7-NEXT:    v_fma_f32 v2, v4, v2, v2
 ; GFX7-NEXT:    v_mul_f32_e32 v4, v3, v2
 ; GFX7-NEXT:    v_fma_f32 v5, -v1, v4, v3
 ; GFX7-NEXT:    v_fma_f32 v4, v5, v2, v4
 ; GFX7-NEXT:    v_fma_f32 v1, -v1, v4, v3
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX7-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
 ; GFX7-NEXT:    v_div_fixup_f32 v0, v1, v0, s6
 ; GFX7-NEXT:    s_setpc_b64 s[30:31]
@@ -6628,14 +6526,12 @@ define float @v_fdiv_f32_constlhs0_dynamic(float %x) #2 {
 ; GFX8-NEXT:    v_div_scale_f32 v1, s[4:5], v0, v0, s6
 ; GFX8-NEXT:    v_div_scale_f32 v2, vcc, s6, v0, s6
 ; GFX8-NEXT:    v_rcp_f32_e32 v3, v1
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX8-NEXT:    v_fma_f32 v4, -v1, v3, 1.0
 ; GFX8-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX8-NEXT:    v_mul_f32_e32 v4, v2, v3
 ; GFX8-NEXT:    v_fma_f32 v5, -v1, v4, v2
 ; GFX8-NEXT:    v_fma_f32 v4, v5, v3, v4
 ; GFX8-NEXT:    v_fma_f32 v1, -v1, v4, v2
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX8-NEXT:    v_div_fmas_f32 v1, v1, v3, v4
 ; GFX8-NEXT:    v_div_fixup_f32 v0, v1, v0, s6
 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
@@ -6644,16 +6540,14 @@ define float @v_fdiv_f32_constlhs0_dynamic(float %x) #2 {
 ; GFX10:       ; %bb.0:
 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX10-NEXT:    v_div_scale_f32 v1, s4, v0, v0, 0x4640e400
-; GFX10-NEXT:    v_div_scale_f32 v3, vcc_lo, 0x4640e400, v0, 0x4640e400
 ; GFX10-NEXT:    v_rcp_f32_e32 v2, v1
-; GFX10-NEXT:    s_denorm_mode 15
-; GFX10-NEXT:    v_fma_f32 v4, -v1, v2, 1.0
-; GFX10-NEXT:    v_fmac_f32_e32 v2, v4, v2
+; GFX10-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v2, v3, v2
+; GFX10-NEXT:    v_div_scale_f32 v3, vcc_lo, 0x4640e400, v0, 0x4640e400
 ; GFX10-NEXT:    v_mul_f32_e32 v4, v3, v2
 ; GFX10-NEXT:    v_fma_f32 v5, -v1, v4, v3
 ; GFX10-NEXT:    v_fmac_f32_e32 v4, v5, v2
 ; GFX10-NEXT:    v_fma_f32 v1, -v1, v4, v3
-; GFX10-NEXT:    s_denorm_mode 12
 ; GFX10-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
 ; GFX10-NEXT:    v_div_fixup_f32 v0, v1, v0, 0x4640e400
 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
@@ -6662,17 +6556,15 @@ define float @v_fdiv_f32_constlhs0_dynamic(float %x) #2 {
 ; GFX11:       ; %bb.0:
 ; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX11-NEXT:    v_div_scale_f32 v1, null, v0, v0, 0x4640e400
-; GFX11-NEXT:    v_div_scale_f32 v3, vcc_lo, 0x4640e400, v0, 0x4640e400
 ; GFX11-NEXT:    v_rcp_f32_e32 v2, v1
-; GFX11-NEXT:    s_denorm_mode 15
 ; GFX11-NEXT:    s_waitcnt_depctr 0xfff
-; GFX11-NEXT:    v_fma_f32 v4, -v1, v2, 1.0
-; GFX11-NEXT:    v_fmac_f32_e32 v2, v4, v2
+; GFX11-NEXT:    v_fma_f32 v3, -v1, v2, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v2, v3, v2
+; GFX11-NEXT:    v_div_scale_f32 v3, vcc_lo, 0x4640e400, v0, 0x4640e400
 ; GFX11-NEXT:    v_mul_f32_e32 v4, v3, v2
 ; GFX11-NEXT:    v_fma_f32 v5, -v1, v4, v3
 ; GFX11-NEXT:    v_fmac_f32_e32 v4, v5, v2
 ; GFX11-NEXT:    v_fma_f32 v1, -v1, v4, v3
-; GFX11-NEXT:    s_denorm_mode 12
 ; GFX11-NEXT:    v_div_fmas_f32 v1, v1, v2, v4
 ; GFX11-NEXT:    v_div_fixup_f32 v0, v1, v0, 0x4640e400
 ; GFX11-NEXT:    s_setpc_b64 s[30:31]
@@ -7113,15 +7005,13 @@ define float @v_fdiv_f32_dynamic_nodenorm_x(float nofpclass(sub) %x, float %y) #
 ; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
 ; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -7132,14 +7022,12 @@ define float @v_fdiv_f32_dynamic_nodenorm_x(float nofpclass(sub) %x, float %y) #
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -7149,15 +7037,13 @@ define float @v_fdiv_f32_dynamic_nodenorm_x(float nofpclass(sub) %x, float %y) #
 ; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX7-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX7-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX7-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX7-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX7-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX7-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX7-NEXT:    v_fma_f32 v3, v5, v3, v3
 ; GFX7-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX7-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX7-NEXT:    v_fma_f32 v5, v6, v3, v5
 ; GFX7-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX7-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX7-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX7-NEXT:    s_setpc_b64 s[30:31]
@@ -7168,14 +7054,12 @@ define float @v_fdiv_f32_dynamic_nodenorm_x(float nofpclass(sub) %x, float %y) #
 ; GFX8-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX8-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
 ; GFX8-NEXT:    v_rcp_f32_e32 v4, v2
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX8-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
 ; GFX8-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX8-NEXT:    v_mul_f32_e32 v5, v3, v4
 ; GFX8-NEXT:    v_fma_f32 v6, -v2, v5, v3
 ; GFX8-NEXT:    v_fma_f32 v5, v6, v4, v5
 ; GFX8-NEXT:    v_fma_f32 v2, -v2, v5, v3
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX8-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
 ; GFX8-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
@@ -7184,16 +7068,14 @@ define float @v_fdiv_f32_dynamic_nodenorm_x(float nofpclass(sub) %x, float %y) #
 ; GFX10:       ; %bb.0:
 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX10-NEXT:    v_div_scale_f32 v2, s4, v1, v1, v0
-; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX10-NEXT:    v_rcp_f32_e32 v3, v2
-; GFX10-NEXT:    s_denorm_mode 15
-; GFX10-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX10-NEXT:    v_fmac_f32_e32 v3, v5, v3
+; GFX10-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX10-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX10-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX10-NEXT:    v_fmac_f32_e32 v5, v6, v3
 ; GFX10-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX10-NEXT:    s_denorm_mode 12
 ; GFX10-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX10-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
@@ -7202,17 +7084,15 @@ define float @v_fdiv_f32_dynamic_nodenorm_x(float nofpclass(sub) %x, float %y) #
 ; GFX11:       ; %bb.0:
 ; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX11-NEXT:    v_div_scale_f32 v2, null, v1, v1, v0
-; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX11-NEXT:    v_rcp_f32_e32 v3, v2
-; GFX11-NEXT:    s_denorm_mode 15
 ; GFX11-NEXT:    s_waitcnt_depctr 0xfff
-; GFX11-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX11-NEXT:    v_fmac_f32_e32 v3, v5, v3
+; GFX11-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX11-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX11-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX11-NEXT:    v_fmac_f32_e32 v5, v6, v3
 ; GFX11-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX11-NEXT:    s_denorm_mode 12
 ; GFX11-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX11-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX11-NEXT:    s_setpc_b64 s[30:31]
@@ -7660,15 +7540,13 @@ define float @v_fdiv_f32_dynamic_nodenorm_y(float %x, float nofpclass(sub) %y) #
 ; GFX6-FASTFMA-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX6-FASTFMA-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX6-FASTFMA-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX6-FASTFMA-NEXT:    v_fma_f32 v3, v5, v3, v3
 ; GFX6-FASTFMA-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v5, v6, v3, v5
 ; GFX6-FASTFMA-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX6-FASTFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-FASTFMA-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX6-FASTFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX6-FASTFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -7679,14 +7557,12 @@ define float @v_fdiv_f32_dynamic_nodenorm_y(float %x, float nofpclass(sub) %y) #
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
 ; GFX6-SLOWFMA-NEXT:    v_rcp_f32_e32 v4, v2
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX6-SLOWFMA-NEXT:    v_mul_f32_e32 v5, v3, v4
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v6, -v2, v5, v3
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v5, v6, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_fma_f32 v2, -v2, v5, v3
-; GFX6-SLOWFMA-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX6-SLOWFMA-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
 ; GFX6-SLOWFMA-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX6-SLOWFMA-NEXT:    s_setpc_b64 s[30:31]
@@ -7696,15 +7572,13 @@ define float @v_fdiv_f32_dynamic_nodenorm_y(float %x, float nofpclass(sub) %y) #
 ; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX7-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX7-NEXT:    v_rcp_f32_e32 v3, v2
+; GFX7-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX7-NEXT:    v_fma_f32 v3, v4, v3, v3
 ; GFX7-NEXT:    v_div_scale_f32 v4, vcc, v0, v1, v0
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
-; GFX7-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX7-NEXT:    v_fma_f32 v3, v5, v3, v3
 ; GFX7-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX7-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX7-NEXT:    v_fma_f32 v5, v6, v3, v5
 ; GFX7-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX7-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX7-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX7-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX7-NEXT:    s_setpc_b64 s[30:31]
@@ -7715,14 +7589,12 @@ define float @v_fdiv_f32_dynamic_nodenorm_y(float %x, float nofpclass(sub) %y) #
 ; GFX8-NEXT:    v_div_scale_f32 v2, s[4:5], v1, v1, v0
 ; GFX8-NEXT:    v_div_scale_f32 v3, vcc, v0, v1, v0
 ; GFX8-NEXT:    v_rcp_f32_e32 v4, v2
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
 ; GFX8-NEXT:    v_fma_f32 v5, -v2, v4, 1.0
 ; GFX8-NEXT:    v_fma_f32 v4, v5, v4, v4
 ; GFX8-NEXT:    v_mul_f32_e32 v5, v3, v4
 ; GFX8-NEXT:    v_fma_f32 v6, -v2, v5, v3
 ; GFX8-NEXT:    v_fma_f32 v5, v6, v4, v5
 ; GFX8-NEXT:    v_fma_f32 v2, -v2, v5, v3
-; GFX8-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
 ; GFX8-NEXT:    v_div_fmas_f32 v2, v2, v4, v5
 ; GFX8-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX8-NEXT:    s_setpc_b64 s[30:31]
@@ -7731,16 +7603,14 @@ define float @v_fdiv_f32_dynamic_nodenorm_y(float %x, float nofpclass(sub) %y) #
 ; GFX10:       ; %bb.0:
 ; GFX10-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX10-NEXT:    v_div_scale_f32 v2, s4, v1, v1, v0
-; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX10-NEXT:    v_rcp_f32_e32 v3, v2
-; GFX10-NEXT:    s_denorm_mode 15
-; GFX10-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX10-NEXT:    v_fmac_f32_e32 v3, v5, v3
+; GFX10-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX10-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX10-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX10-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX10-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX10-NEXT:    v_fmac_f32_e32 v5, v6, v3
 ; GFX10-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX10-NEXT:    s_denorm_mode 12
 ; GFX10-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX10-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX10-NEXT:    s_setpc_b64 s[30:31]
@@ -7749,17 +7619,15 @@ define float @v_fdiv_f32_dynamic_nodenorm_y(float %x, float nofpclass(sub) %y) #
 ; GFX11:       ; %bb.0:
 ; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; GFX11-NEXT:    v_div_scale_f32 v2, null, v1, v1, v0
-; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX11-NEXT:    v_rcp_f32_e32 v3, v2
-; GFX11-NEXT:    s_denorm_mode 15
 ; GFX11-NEXT:    s_waitcnt_depctr 0xfff
-; GFX11-NEXT:    v_fma_f32 v5, -v2, v3, 1.0
-; GFX11-NEXT:    v_fmac_f32_e32 v3, v5, v3
+; GFX11-NEXT:    v_fma_f32 v4, -v2, v3, 1.0
+; GFX11-NEXT:    v_fmac_f32_e32 v3, v4, v3
+; GFX11-NEXT:    v_div_scale_f32 v4, vcc_lo, v0, v1, v0
 ; GFX11-NEXT:    v_mul_f32_e32 v5, v4, v3
 ; GFX11-NEXT:    v_fma_f32 v6, -v2, v5, v4
 ; GFX11-NEXT:    v_fmac_f32_e32 v5, v6, v3
 ; GFX11-NEXT:    v_fma_f32 v2, -v2, v5, v4
-; GFX11-NEXT:    s_denorm_mode 12
 ; GFX11-NEXT:    v_div_fmas_f32 v2, v2, v3, v5
 ; GFX11-NEXT:    v_div_fixup_f32 v0, v2, v1, v0
 ; GFX11-NEXT:    s_setpc_b64 s[30:31]

>From e21861899d05659d465fccb63b5933a169c47182 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Wed, 13 Sep 2023 18:44:19 +0200
Subject: [PATCH 27/86] [clang] Bail out when handling union access with
 virtual inheritance

An assertion issue that arose when handling union member access with
virtual base class has been addressed. As pointed out by @zygoloid,
there is no need for further derived-to-base analysis in this instance,
so we can bail out upon encountering a virtual base class. Minor
refinement on the function name as we might not be handling a union.

Reported-By: ormris

Fixes: https://github.com/llvm/llvm-project/issues/65982
---
 clang/lib/AST/ExprConstant.cpp                 | 17 ++++++++++++-----
 clang/test/SemaCXX/cxx2a-virtual-base-used.cpp | 11 +++++++++++
 2 files changed, 23 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2a-virtual-base-used.cpp

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index dfa48e9c030b6a3..fea06b97259fe31 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6062,8 +6062,9 @@ const AccessKinds StartLifetimeOfUnionMemberHandler::AccessKind;
 /// operator whose left-hand side might involve a union member access. If it
 /// does, implicitly start the lifetime of any accessed union elements per
 /// C++20 [class.union]5.
-static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
-                                          const LValue &LHS) {
+static bool MaybeHandleUnionActiveMemberChange(EvalInfo &Info,
+                                               const Expr *LHSExpr,
+                                               const LValue &LHS) {
   if (LHS.InvalidBase || LHS.Designator.Invalid)
     return false;
 
@@ -6118,8 +6119,14 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
         break;
       // Walk path backwards as we walk up from the base to the derived class.
       for (const CXXBaseSpecifier *Elt : llvm::reverse(ICE->path())) {
+        if (Elt->isVirtual()) {
+          // A class with virtual base classes never has a trivial default
+          // constructor, so S(E) is empty in this case.
+          E = nullptr;
+          break;
+        }
+
         --PathLength;
-        (void)Elt;
         assert(declaresSameEntity(Elt->getType()->getAsCXXRecordDecl(),
                                   LHS.Designator.Entries[PathLength]
                                       .getAsBaseOrMember().getPointer()));
@@ -7806,7 +7813,7 @@ class ExprEvaluatorBase
         // per C++20 [class.union]5.
         if (Info.getLangOpts().CPlusPlus20 && OCE &&
             OCE->getOperator() == OO_Equal && MD->isTrivial() &&
-            !HandleUnionActiveMemberChange(Info, Args[0], ThisVal))
+            !MaybeHandleUnionActiveMemberChange(Info, Args[0], ThisVal))
           return false;
 
         Args = Args.slice(1);
@@ -8679,7 +8686,7 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) {
     return false;
 
   if (Info.getLangOpts().CPlusPlus20 &&
-      !HandleUnionActiveMemberChange(Info, E->getLHS(), Result))
+      !MaybeHandleUnionActiveMemberChange(Info, E->getLHS(), Result))
     return false;
 
   return handleAssignment(this->Info, E, Result, E->getLHS()->getType(),
diff --git a/clang/test/SemaCXX/cxx2a-virtual-base-used.cpp b/clang/test/SemaCXX/cxx2a-virtual-base-used.cpp
new file mode 100644
index 000000000000000..196a3ab05564b96
--- /dev/null
+++ b/clang/test/SemaCXX/cxx2a-virtual-base-used.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -std=c++20 -verify=cxx20 -triple=x86_64-linux-gnu %s
+// Fixes assertion triggered by https://github.com/llvm/llvm-project/issues/65982
+
+struct A { int y; };
+struct B : virtual public A {};
+struct X : public B {};
+
+void member_with_virtual_inheritance() {
+  X x;
+  x.B::y = 1;
+}

>From 65414fa5ee547ccbc463c2084e643ec25d2db4aa Mon Sep 17 00:00:00 2001
From: Owen Pan <owenpiano at gmail.com>
Date: Wed, 13 Sep 2023 23:57:34 -0700
Subject: [PATCH 28/86] [clang-format] Fix a bug in annotating `&&` followed by
 `*` or `&` (#65933)

Fixes #65877.
---
 clang/lib/Format/TokenAnnotator.cpp           | 7 +++++--
 clang/unittests/Format/TokenAnnotatorTest.cpp | 6 ++++++
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index e925bee44cd0c6a..142168e074bbc27 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -2598,9 +2598,12 @@ class AnnotatingParser {
     if (InTemplateArgument && NextToken->Tok.isAnyIdentifier())
       return TT_BinaryOperator;
 
-    // "&&(" is quite unlikely to be two successive unary "&".
-    if (Tok.is(tok::ampamp) && NextToken->is(tok::l_paren))
+    // "&&" followed by "(", "*", or "&" is quite unlikely to be two successive
+    // unary "&".
+    if (Tok.is(tok::ampamp) &&
+        NextToken->isOneOf(tok::l_paren, tok::star, tok::amp)) {
       return TT_BinaryOperator;
+    }
 
     // This catches some cases where evaluation order is used as control flow:
     //   aaa && aaa->f();
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 9ab1eae85f29c4d..22698f6faf3cb1e 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -280,6 +280,12 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) {
   EXPECT_TOKEN(Tokens[12], tok::ampamp, TT_BinaryOperator);
   EXPECT_TOKEN(Tokens[27], tok::ampamp, TT_BinaryOperator);
 
+  Tokens = annotate("foo = *i < *j && *j > *k;");
+  EXPECT_EQ(Tokens.size(), 15u) << Tokens;
+  EXPECT_TOKEN(Tokens[4], tok::less, TT_BinaryOperator);
+  EXPECT_TOKEN(Tokens[7], tok::ampamp, TT_BinaryOperator);
+  EXPECT_TOKEN(Tokens[10], tok::greater, TT_BinaryOperator);
+
   FormatStyle Style = getLLVMStyle();
   Style.TypeNames.push_back("MYI");
   Tokens = annotate("if (MYI *p{nullptr})", Style);

>From 36c8e0fe0de9e91d7842dcdfa1d2d8996e94cb6d Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Mon, 21 Aug 2023 17:00:03 +0200
Subject: [PATCH 29/86] [InstCombine] Propagate nsw flag when negating

When pushing a sub nsw 0, %x negation into an expression, try to
preserve the nsw flag for the cases where this is possible. Do this
by passing the flag through recursive Negator::negate() calls.

Proofs: https://alive2.llvm.org/ce/z/oRPNcY

Differential Revision: https://reviews.llvm.org/D158510
---
 .../InstCombine/InstCombineAddSub.cpp         |  4 +-
 .../InstCombine/InstCombineInternal.h         |  8 +--
 .../InstCombine/InstCombineMulDivRem.cpp      | 11 +++-
 .../InstCombine/InstCombineNegator.cpp        | 55 ++++++++++---------
 .../Transforms/InstCombine/abs-intrinsic.ll   | 10 ++--
 llvm/test/Transforms/InstCombine/mul.ll       |  8 ++-
 llvm/test/Transforms/InstCombine/nsw.ll       | 32 +++++------
 7 files changed, 71 insertions(+), 57 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index aff8c333495c585..e08d41de87d40a2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2145,7 +2145,9 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
                      m_Select(m_Value(), m_Specific(Op1), m_Specific(&I))) ||
                match(UI, m_Select(m_Value(), m_Specific(&I), m_Specific(Op1)));
       })) {
-    if (Value *NegOp1 = Negator::Negate(IsNegation, Op1, *this))
+    if (Value *NegOp1 = Negator::Negate(IsNegation, /* IsNSW */ IsNegation &&
+                                                        I.hasNoSignedWrap(),
+                                        Op1, *this))
       return BinaryOperator::CreateAdd(NegOp1, Op0);
   }
   if (IsNegation)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index e8d85134cf77c1f..40c24d87bfec508 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -738,13 +738,13 @@ class Negator final {
 
   std::array<Value *, 2> getSortedOperandsOfBinOp(Instruction *I);
 
-  [[nodiscard]] Value *visitImpl(Value *V, unsigned Depth);
+  [[nodiscard]] Value *visitImpl(Value *V, bool IsNSW, unsigned Depth);
 
-  [[nodiscard]] Value *negate(Value *V, unsigned Depth);
+  [[nodiscard]] Value *negate(Value *V, bool IsNSW, unsigned Depth);
 
   /// Recurse depth-first and attempt to sink the negation.
   /// FIXME: use worklist?
-  [[nodiscard]] std::optional<Result> run(Value *Root);
+  [[nodiscard]] std::optional<Result> run(Value *Root, bool IsNSW);
 
   Negator(const Negator &) = delete;
   Negator(Negator &&) = delete;
@@ -754,7 +754,7 @@ class Negator final {
 public:
   /// Attempt to negate \p Root. Retuns nullptr if negation can't be performed,
   /// otherwise returns negated value.
-  [[nodiscard]] static Value *Negate(bool LHSIsZero, Value *Root,
+  [[nodiscard]] static Value *Negate(bool LHSIsZero, bool IsNSW, Value *Root,
                                      InstCombinerImpl &IC);
 };
 
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 86cacf979839126..dc091ec7c60e8dd 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -258,9 +258,14 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
   if (Op0->hasOneUse() && match(Op1, m_NegatedPower2())) {
     // Interpret  X * (-1<<C)  as  (-X) * (1<<C)  and try to sink the negation.
     // The "* (1<<C)" thus becomes a potential shifting opportunity.
-    if (Value *NegOp0 = Negator::Negate(/*IsNegation*/ true, Op0, *this))
-      return BinaryOperator::CreateMul(
-          NegOp0, ConstantExpr::getNeg(cast<Constant>(Op1)), I.getName());
+    if (Value *NegOp0 =
+            Negator::Negate(/*IsNegation*/ true, HasNSW, Op0, *this)) {
+      auto *Op1C = cast<Constant>(Op1);
+      return replaceInstUsesWith(
+          I, Builder.CreateMul(NegOp0, ConstantExpr::getNeg(Op1C), "",
+                               /* HasNUW */ false,
+                               HasNSW && Op1C->isNotMinSignedValue()));
+    }
 
     // Try to convert multiply of extended operand to narrow negate and shift
     // for better analysis.
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
index e24abc48424d4a7..b0f0295a7b90d3a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
@@ -128,7 +128,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
 
 // FIXME: can this be reworked into a worklist-based algorithm while preserving
 // the depth-first, early bailout traversal?
-[[nodiscard]] Value *Negator::visitImpl(Value *V, unsigned Depth) {
+[[nodiscard]] Value *Negator::visitImpl(Value *V, bool IsNSW, unsigned Depth) {
   // -(undef) -> undef.
   if (match(V, m_Undef()))
     return V;
@@ -237,7 +237,8 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
     // However, only do this either if the old `sub` doesn't stick around, or
     // it was subtracting from a constant. Otherwise, this isn't profitable.
     return Builder.CreateSub(I->getOperand(1), I->getOperand(0),
-                             I->getName() + ".neg");
+                             I->getName() + ".neg", /* HasNUW */ false,
+                             IsNSW && I->hasNoSignedWrap());
   }
 
   // Some other cases, while still don't require recursion,
@@ -302,7 +303,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
   switch (I->getOpcode()) {
   case Instruction::Freeze: {
     // `freeze` is negatible if its operand is negatible.
-    Value *NegOp = negate(I->getOperand(0), Depth + 1);
+    Value *NegOp = negate(I->getOperand(0), IsNSW, Depth + 1);
     if (!NegOp) // Early return.
       return nullptr;
     return Builder.CreateFreeze(NegOp, I->getName() + ".neg");
@@ -313,7 +314,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
     SmallVector<Value *, 4> NegatedIncomingValues(PHI->getNumOperands());
     for (auto I : zip(PHI->incoming_values(), NegatedIncomingValues)) {
       if (!(std::get<1>(I) =
-                negate(std::get<0>(I), Depth + 1))) // Early return.
+                negate(std::get<0>(I), IsNSW, Depth + 1))) // Early return.
         return nullptr;
     }
     // All incoming values are indeed negatible. Create negated PHI node.
@@ -336,10 +337,10 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
       return NewSelect;
     }
     // `select` is negatible if both hands of `select` are negatible.
-    Value *NegOp1 = negate(I->getOperand(1), Depth + 1);
+    Value *NegOp1 = negate(I->getOperand(1), IsNSW, Depth + 1);
     if (!NegOp1) // Early return.
       return nullptr;
-    Value *NegOp2 = negate(I->getOperand(2), Depth + 1);
+    Value *NegOp2 = negate(I->getOperand(2), IsNSW, Depth + 1);
     if (!NegOp2)
       return nullptr;
     // Do preserve the metadata!
@@ -349,10 +350,10 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
   case Instruction::ShuffleVector: {
     // `shufflevector` is negatible if both operands are negatible.
     auto *Shuf = cast<ShuffleVectorInst>(I);
-    Value *NegOp0 = negate(I->getOperand(0), Depth + 1);
+    Value *NegOp0 = negate(I->getOperand(0), IsNSW, Depth + 1);
     if (!NegOp0) // Early return.
       return nullptr;
-    Value *NegOp1 = negate(I->getOperand(1), Depth + 1);
+    Value *NegOp1 = negate(I->getOperand(1), IsNSW, Depth + 1);
     if (!NegOp1)
       return nullptr;
     return Builder.CreateShuffleVector(NegOp0, NegOp1, Shuf->getShuffleMask(),
@@ -361,7 +362,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
   case Instruction::ExtractElement: {
     // `extractelement` is negatible if source operand is negatible.
     auto *EEI = cast<ExtractElementInst>(I);
-    Value *NegVector = negate(EEI->getVectorOperand(), Depth + 1);
+    Value *NegVector = negate(EEI->getVectorOperand(), IsNSW, Depth + 1);
     if (!NegVector) // Early return.
       return nullptr;
     return Builder.CreateExtractElement(NegVector, EEI->getIndexOperand(),
@@ -371,10 +372,10 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
     // `insertelement` is negatible if both the source vector and
     // element-to-be-inserted are negatible.
     auto *IEI = cast<InsertElementInst>(I);
-    Value *NegVector = negate(IEI->getOperand(0), Depth + 1);
+    Value *NegVector = negate(IEI->getOperand(0), IsNSW, Depth + 1);
     if (!NegVector) // Early return.
       return nullptr;
-    Value *NegNewElt = negate(IEI->getOperand(1), Depth + 1);
+    Value *NegNewElt = negate(IEI->getOperand(1), IsNSW, Depth + 1);
     if (!NegNewElt) // Early return.
       return nullptr;
     return Builder.CreateInsertElement(NegVector, NegNewElt, IEI->getOperand(2),
@@ -382,15 +383,17 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
   }
   case Instruction::Trunc: {
     // `trunc` is negatible if its operand is negatible.
-    Value *NegOp = negate(I->getOperand(0), Depth + 1);
+    Value *NegOp = negate(I->getOperand(0), /* IsNSW */ false, Depth + 1);
     if (!NegOp) // Early return.
       return nullptr;
     return Builder.CreateTrunc(NegOp, I->getType(), I->getName() + ".neg");
   }
   case Instruction::Shl: {
     // `shl` is negatible if the first operand is negatible.
-    if (Value *NegOp0 = negate(I->getOperand(0), Depth + 1))
-      return Builder.CreateShl(NegOp0, I->getOperand(1), I->getName() + ".neg");
+    IsNSW &= I->hasNoSignedWrap();
+    if (Value *NegOp0 = negate(I->getOperand(0), IsNSW, Depth + 1))
+      return Builder.CreateShl(NegOp0, I->getOperand(1), I->getName() + ".neg",
+                               /* HasNUW */ false, IsNSW);
     // Otherwise, `shl %x, C` can be interpreted as `mul %x, 1<<C`.
     auto *Op1C = dyn_cast<Constant>(I->getOperand(1));
     if (!Op1C || !IsTrulyNegation)
@@ -398,7 +401,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
     return Builder.CreateMul(
         I->getOperand(0),
         ConstantExpr::getShl(Constant::getAllOnesValue(Op1C->getType()), Op1C),
-        I->getName() + ".neg");
+        I->getName() + ".neg", /* HasNUW */ false, IsNSW);
   }
   case Instruction::Or: {
     if (!haveNoCommonBitsSet(I->getOperand(0), I->getOperand(1), DL, &AC, I,
@@ -417,7 +420,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
     SmallVector<Value *, 2> NegatedOps, NonNegatedOps;
     for (Value *Op : I->operands()) {
       // Can we sink the negation into this operand?
-      if (Value *NegOp = negate(Op, Depth + 1)) {
+      if (Value *NegOp = negate(Op, /* IsNSW */ false, Depth + 1)) {
         NegatedOps.emplace_back(NegOp); // Successfully negated operand!
         continue;
       }
@@ -458,16 +461,17 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
     Value *NegatedOp, *OtherOp;
     // First try the second operand, in case it's a constant it will be best to
     // just invert it instead of sinking the `neg` deeper.
-    if (Value *NegOp1 = negate(Ops[1], Depth + 1)) {
+    if (Value *NegOp1 = negate(Ops[1], /* IsNSW */ false, Depth + 1)) {
       NegatedOp = NegOp1;
       OtherOp = Ops[0];
-    } else if (Value *NegOp0 = negate(Ops[0], Depth + 1)) {
+    } else if (Value *NegOp0 = negate(Ops[0], /* IsNSW */ false, Depth + 1)) {
       NegatedOp = NegOp0;
       OtherOp = Ops[1];
     } else
       // Can't negate either of them.
       return nullptr;
-    return Builder.CreateMul(NegatedOp, OtherOp, I->getName() + ".neg");
+    return Builder.CreateMul(NegatedOp, OtherOp, I->getName() + ".neg",
+                             /* HasNUW */ false, IsNSW && I->hasNoSignedWrap());
   }
   default:
     return nullptr; // Don't know, likely not negatible for free.
@@ -476,7 +480,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
   llvm_unreachable("Can't get here. We always return from switch.");
 }
 
-[[nodiscard]] Value *Negator::negate(Value *V, unsigned Depth) {
+[[nodiscard]] Value *Negator::negate(Value *V, bool IsNSW, unsigned Depth) {
   NegatorMaxDepthVisited.updateMax(Depth);
   ++NegatorNumValuesVisited;
 
@@ -506,15 +510,16 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
 #endif
 
   // No luck. Try negating it for real.
-  Value *NegatedV = visitImpl(V, Depth);
+  Value *NegatedV = visitImpl(V, IsNSW, Depth);
   // And cache the (real) result for the future.
   NegationsCache[V] = NegatedV;
 
   return NegatedV;
 }
 
-[[nodiscard]] std::optional<Negator::Result> Negator::run(Value *Root) {
-  Value *Negated = negate(Root, /*Depth=*/0);
+[[nodiscard]] std::optional<Negator::Result> Negator::run(Value *Root,
+                                                          bool IsNSW) {
+  Value *Negated = negate(Root, IsNSW, /*Depth=*/0);
   if (!Negated) {
     // We must cleanup newly-inserted instructions, to avoid any potential
     // endless combine looping.
@@ -525,7 +530,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
   return std::make_pair(ArrayRef<Instruction *>(NewInstructions), Negated);
 }
 
-[[nodiscard]] Value *Negator::Negate(bool LHSIsZero, Value *Root,
+[[nodiscard]] Value *Negator::Negate(bool LHSIsZero, bool IsNSW, Value *Root,
                                      InstCombinerImpl &IC) {
   ++NegatorTotalNegationsAttempted;
   LLVM_DEBUG(dbgs() << "Negator: attempting to sink negation into " << *Root
@@ -536,7 +541,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
 
   Negator N(Root->getContext(), IC.getDataLayout(), IC.getAssumptionCache(),
             IC.getDominatorTree(), LHSIsZero);
-  std::optional<Result> Res = N.run(Root);
+  std::optional<Result> Res = N.run(Root, IsNSW);
   if (!Res) { // Negation failed.
     LLVM_DEBUG(dbgs() << "Negator: failed to sink negation into " << *Root
                       << "\n");
diff --git a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
index 50bdd643528d96f..7fe34d923764857 100644
--- a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
+++ b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
@@ -486,7 +486,7 @@ define i32 @sub_abs_sgeT_swap(i32 %x, i32 %y) {
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp slt i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]]
 ; CHECK:       cond.true:
-; CHECK-NEXT:    [[SUB_NEG:%.*]] = sub i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[SUB_NEG:%.*]] = sub nsw i32 [[Y]], [[X]]
 ; CHECK-NEXT:    br label [[COND_END]]
 ; CHECK:       cond.end:
 ; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[SUB_NEG]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
@@ -513,7 +513,7 @@ define i32 @sub_abs_sgeT_false(i32 %x, i32 %y) {
 ; CHECK-NEXT:    [[CMP_NOT_NOT:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    br i1 [[CMP_NOT_NOT]], label [[COND_FALSE:%.*]], label [[COND_END:%.*]]
 ; CHECK:       cond.false:
-; CHECK-NEXT:    [[SUB_NEG:%.*]] = sub i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[SUB_NEG:%.*]] = sub nsw i32 [[Y]], [[X]]
 ; CHECK-NEXT:    br label [[COND_END]]
 ; CHECK:       cond.end:
 ; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[SUB_NEG]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
@@ -539,7 +539,7 @@ define i32 @sub_abs_lt(i32 %x, i32 %y) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
 ; CHECK:       cond.true:
-; CHECK-NEXT:    [[SUB_NEG:%.*]] = sub i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[SUB_NEG:%.*]] = sub nsw i32 [[Y]], [[X]]
 ; CHECK-NEXT:    br label [[COND_END]]
 ; CHECK:       cond.end:
 ; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[SUB_NEG]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
@@ -566,7 +566,7 @@ define i32 @sub_abs_sle(i32 %x, i32 %y) {
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]]
 ; CHECK:       cond.true:
-; CHECK-NEXT:    [[SUB_NEG:%.*]] = sub i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[SUB_NEG:%.*]] = sub nsw i32 [[Y]], [[X]]
 ; CHECK-NEXT:    br label [[COND_END]]
 ; CHECK:       cond.end:
 ; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[SUB_NEG]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
@@ -619,7 +619,7 @@ define i8 @sub_abs_sleT(i8 %x, i8 %y) {
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[COND_END:%.*]], label [[COND_TRUE:%.*]]
 ; CHECK:       cond.true:
-; CHECK-NEXT:    [[SUB_NEG:%.*]] = sub i8 [[Y]], [[X]]
+; CHECK-NEXT:    [[SUB_NEG:%.*]] = sub nsw i8 [[Y]], [[X]]
 ; CHECK-NEXT:    br label [[COND_END]]
 ; CHECK:       cond.end:
 ; CHECK-NEXT:    [[R:%.*]] = phi i8 [ [[SUB_NEG]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
diff --git a/llvm/test/Transforms/InstCombine/mul.ll b/llvm/test/Transforms/InstCombine/mul.ll
index 7e41b073d738f68..45a837a2a594aab 100644
--- a/llvm/test/Transforms/InstCombine/mul.ll
+++ b/llvm/test/Transforms/InstCombine/mul.ll
@@ -1545,8 +1545,8 @@ define <2 x i32> @mulsub2_vec_nonuniform_undef(<2 x i32> %a0) {
 
 define i8 @mulsub_nsw(i8 %a1, i8 %a2) {
 ; CHECK-LABEL: @mulsub_nsw(
-; CHECK-NEXT:    [[A_NEG:%.*]] = sub i8 [[A2:%.*]], [[A1:%.*]]
-; CHECK-NEXT:    [[MUL:%.*]] = shl i8 [[A_NEG]], 1
+; CHECK-NEXT:    [[A_NEG:%.*]] = sub nsw i8 [[A2:%.*]], [[A1:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = shl nsw i8 [[A_NEG]], 1
 ; CHECK-NEXT:    ret i8 [[MUL]]
 ;
   %a = sub nsw i8 %a1, %a2
@@ -1554,9 +1554,11 @@ define i8 @mulsub_nsw(i8 %a1, i8 %a2) {
   ret i8 %mul
 }
 
+; It would be safe to keep the nsw on the shl here, but only because the mul
+; to shl transform happens to replace undef with 0.
 define <2 x i8> @mulsub_nsw_undef(<2 x i8> %a1, <2 x i8> %a2) {
 ; CHECK-LABEL: @mulsub_nsw_undef(
-; CHECK-NEXT:    [[A_NEG:%.*]] = sub <2 x i8> [[A2:%.*]], [[A1:%.*]]
+; CHECK-NEXT:    [[A_NEG:%.*]] = sub nsw <2 x i8> [[A2:%.*]], [[A1:%.*]]
 ; CHECK-NEXT:    [[MUL:%.*]] = shl <2 x i8> [[A_NEG]], <i8 1, i8 0>
 ; CHECK-NEXT:    ret <2 x i8> [[MUL]]
 ;
diff --git a/llvm/test/Transforms/InstCombine/nsw.ll b/llvm/test/Transforms/InstCombine/nsw.ll
index d9dfa8fb3876831..2d68236d93346a5 100644
--- a/llvm/test/Transforms/InstCombine/nsw.ll
+++ b/llvm/test/Transforms/InstCombine/nsw.ll
@@ -145,7 +145,7 @@ define <vscale x 2 x i64> @mul_nuw_nsw_shuffle_constant_expr(<vscale x 2 x i8> %
 
 define i32 @neg_sub0_sub_nsw_nsw(i32 %a, i32 %b) {
 ; CHECK-LABEL: @neg_sub0_sub_nsw_nsw(
-; CHECK-NEXT:    [[C_NEG:%.*]] = sub i32 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT:    [[C_NEG:%.*]] = sub nsw i32 [[B:%.*]], [[A:%.*]]
 ; CHECK-NEXT:    ret i32 [[C_NEG]]
 ;
   %c = sub nsw i32 %a, %b
@@ -181,7 +181,7 @@ define i32 @neg_sub_sub_nsw1(i32 %a, i32 %b) {
 
 define i32 @neg_mul_sub_nsw_nsw(i32 %a, i32 %b) {
 ; CHECK-LABEL: @neg_mul_sub_nsw_nsw(
-; CHECK-NEXT:    [[C_NEG:%.*]] = sub i32 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT:    [[C_NEG:%.*]] = sub nsw i32 [[B:%.*]], [[A:%.*]]
 ; CHECK-NEXT:    ret i32 [[C_NEG]]
 ;
   %c = sub nsw i32 %a, %b
@@ -255,7 +255,7 @@ define i32 @sub_sub1_nsw_nsw(i32 %a, i32 %b, i32 %c) {
 
 define i8 @neg_nsw_freeze(i8 %a1, i8 %a2) {
 ; CHECK-LABEL: @neg_nsw_freeze(
-; CHECK-NEXT:    [[A_NEG:%.*]] = sub i8 [[A2:%.*]], [[A1:%.*]]
+; CHECK-NEXT:    [[A_NEG:%.*]] = sub nsw i8 [[A2:%.*]], [[A1:%.*]]
 ; CHECK-NEXT:    [[FR_NEG:%.*]] = freeze i8 [[A_NEG]]
 ; CHECK-NEXT:    ret i8 [[FR_NEG]]
 ;
@@ -269,10 +269,10 @@ define i8 @neg_nsw_phi(i1 %c, i8 %a1, i8 %a2, i8 %b1, i8 %b2) {
 ; CHECK-LABEL: @neg_nsw_phi(
 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
 ; CHECK:       if:
-; CHECK-NEXT:    [[A_NEG:%.*]] = sub i8 [[A2:%.*]], [[A1:%.*]]
+; CHECK-NEXT:    [[A_NEG:%.*]] = sub nsw i8 [[A2:%.*]], [[A1:%.*]]
 ; CHECK-NEXT:    br label [[JOIN:%.*]]
 ; CHECK:       else:
-; CHECK-NEXT:    [[B_NEG:%.*]] = sub i8 [[B2:%.*]], [[B1:%.*]]
+; CHECK-NEXT:    [[B_NEG:%.*]] = sub nsw i8 [[B2:%.*]], [[B1:%.*]]
 ; CHECK-NEXT:    br label [[JOIN]]
 ; CHECK:       join:
 ; CHECK-NEXT:    [[PHI_NEG:%.*]] = phi i8 [ [[A_NEG]], [[IF]] ], [ [[B_NEG]], [[ELSE]] ]
@@ -296,8 +296,8 @@ join:
 
 define i8 @neg_nsw_select(i1 %c, i8 %a1, i8 %a2, i8 %b1, i8 %b2) {
 ; CHECK-LABEL: @neg_nsw_select(
-; CHECK-NEXT:    [[A_NEG:%.*]] = sub i8 [[A2:%.*]], [[A1:%.*]]
-; CHECK-NEXT:    [[B_NEG:%.*]] = sub i8 [[B2:%.*]], [[B1:%.*]]
+; CHECK-NEXT:    [[A_NEG:%.*]] = sub nsw i8 [[A2:%.*]], [[A1:%.*]]
+; CHECK-NEXT:    [[B_NEG:%.*]] = sub nsw i8 [[B2:%.*]], [[B1:%.*]]
 ; CHECK-NEXT:    [[SEL_NEG:%.*]] = select i1 [[C:%.*]], i8 [[A_NEG]], i8 [[B_NEG]]
 ; CHECK-NEXT:    ret i8 [[SEL_NEG]]
 ;
@@ -310,8 +310,8 @@ define i8 @neg_nsw_select(i1 %c, i8 %a1, i8 %a2, i8 %b1, i8 %b2) {
 
 define <4 x i8> @neg_nsw_shufflevector(<2 x i8> %a1, <2 x i8> %a2, <2 x i8> %b1, <2 x i8> %b2) {
 ; CHECK-LABEL: @neg_nsw_shufflevector(
-; CHECK-NEXT:    [[A_NEG:%.*]] = sub <2 x i8> [[A2:%.*]], [[A1:%.*]]
-; CHECK-NEXT:    [[B_NEG:%.*]] = sub <2 x i8> [[B2:%.*]], [[B1:%.*]]
+; CHECK-NEXT:    [[A_NEG:%.*]] = sub nsw <2 x i8> [[A2:%.*]], [[A1:%.*]]
+; CHECK-NEXT:    [[B_NEG:%.*]] = sub nsw <2 x i8> [[B2:%.*]], [[B1:%.*]]
 ; CHECK-NEXT:    [[SHUF_NEG:%.*]] = shufflevector <2 x i8> [[A_NEG]], <2 x i8> [[B_NEG]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
 ; CHECK-NEXT:    ret <4 x i8> [[SHUF_NEG]]
 ;
@@ -324,7 +324,7 @@ define <4 x i8> @neg_nsw_shufflevector(<2 x i8> %a1, <2 x i8> %a2, <2 x i8> %b1,
 
 define i8 @neg_nsw_extractelement(<2 x i8> %a1, <2 x i8> %a2) {
 ; CHECK-LABEL: @neg_nsw_extractelement(
-; CHECK-NEXT:    [[A_NEG:%.*]] = sub <2 x i8> [[A2:%.*]], [[A1:%.*]]
+; CHECK-NEXT:    [[A_NEG:%.*]] = sub nsw <2 x i8> [[A2:%.*]], [[A1:%.*]]
 ; CHECK-NEXT:    [[EXTR_NEG:%.*]] = extractelement <2 x i8> [[A_NEG]], i64 0
 ; CHECK-NEXT:    ret i8 [[EXTR_NEG]]
 ;
@@ -336,8 +336,8 @@ define i8 @neg_nsw_extractelement(<2 x i8> %a1, <2 x i8> %a2) {
 
 define <2 x i8> @neg_nsw_insertelement(<2 x i8> %a1, <2 x i8> %a2, i8 %b1, i8 %b2) {
 ; CHECK-LABEL: @neg_nsw_insertelement(
-; CHECK-NEXT:    [[A_NEG:%.*]] = sub <2 x i8> [[A2:%.*]], [[A1:%.*]]
-; CHECK-NEXT:    [[B_NEG:%.*]] = sub i8 [[B2:%.*]], [[B1:%.*]]
+; CHECK-NEXT:    [[A_NEG:%.*]] = sub nsw <2 x i8> [[A2:%.*]], [[A1:%.*]]
+; CHECK-NEXT:    [[B_NEG:%.*]] = sub nsw i8 [[B2:%.*]], [[B1:%.*]]
 ; CHECK-NEXT:    [[INSERT_NEG:%.*]] = insertelement <2 x i8> [[A_NEG]], i8 [[B_NEG]], i64 0
 ; CHECK-NEXT:    ret <2 x i8> [[INSERT_NEG]]
 ;
@@ -350,8 +350,8 @@ define <2 x i8> @neg_nsw_insertelement(<2 x i8> %a1, <2 x i8> %a2, i8 %b1, i8 %b
 
 define i8 @neg_nsw_shl(i8 %a1, i8 %a2, i8 %b) {
 ; CHECK-LABEL: @neg_nsw_shl(
-; CHECK-NEXT:    [[A_NEG:%.*]] = sub i8 [[A2:%.*]], [[A1:%.*]]
-; CHECK-NEXT:    [[SHL_NEG:%.*]] = shl i8 [[A_NEG]], [[B:%.*]]
+; CHECK-NEXT:    [[A_NEG:%.*]] = sub nsw i8 [[A2:%.*]], [[A1:%.*]]
+; CHECK-NEXT:    [[SHL_NEG:%.*]] = shl nsw i8 [[A_NEG]], [[B:%.*]]
 ; CHECK-NEXT:    ret i8 [[SHL_NEG]]
 ;
   %a = sub nsw i8 %a1, %a2
@@ -374,7 +374,7 @@ define i8 @neg_nsw_shl_missing_nsw_on_shl(i8 %a1, i8 %a2, i8 %b) {
 
 define i8 @neg_nsw_shl_to_mul(i8 %a, i8 %b) {
 ; CHECK-LABEL: @neg_nsw_shl_to_mul(
-; CHECK-NEXT:    [[SHL_NEG:%.*]] = mul i8 [[A:%.*]], -2
+; CHECK-NEXT:    [[SHL_NEG:%.*]] = mul nsw i8 [[A:%.*]], -2
 ; CHECK-NEXT:    ret i8 [[SHL_NEG]]
 ;
   %shl = shl nsw i8 %a, 1
@@ -395,7 +395,7 @@ define i8 @neg_nsw_shl_to_mul_missing_nsw_on_shl(i8 %a, i8 %b) {
 define i8 @neg_nsw_mul(i8 %a1, i8 %a2, i8 %b) {
 ; CHECK-LABEL: @neg_nsw_mul(
 ; CHECK-NEXT:    [[A_NEG:%.*]] = sub i8 [[A2:%.*]], [[A1:%.*]]
-; CHECK-NEXT:    [[SHL_NEG:%.*]] = mul i8 [[A_NEG]], [[B:%.*]]
+; CHECK-NEXT:    [[SHL_NEG:%.*]] = mul nsw i8 [[A_NEG]], [[B:%.*]]
 ; CHECK-NEXT:    ret i8 [[SHL_NEG]]
 ;
   %a = sub nsw i8 %a1, %a2

>From 922c7d720e2e6306c5ff9ad2679e45d42f27bb03 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Thu, 14 Sep 2023 09:16:01 +0200
Subject: [PATCH 30/86] [clang] Include `expected-no-diagnostics` in
 newly-added test (NFC)

---
 clang/test/SemaCXX/cxx2a-virtual-base-used.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/clang/test/SemaCXX/cxx2a-virtual-base-used.cpp b/clang/test/SemaCXX/cxx2a-virtual-base-used.cpp
index 196a3ab05564b96..871c671f1d43772 100644
--- a/clang/test/SemaCXX/cxx2a-virtual-base-used.cpp
+++ b/clang/test/SemaCXX/cxx2a-virtual-base-used.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -std=c++20 -verify=cxx20 -triple=x86_64-linux-gnu %s
+// RUN: %clang_cc1 -std=c++2a -verify -triple=x86_64-linux-gnu %s
+// expected-no-diagnostics
+
 // Fixes assertion triggered by https://github.com/llvm/llvm-project/issues/65982
 
 struct A { int y; };

>From fc768d379b563bb056168d4afd06f0c79e297b04 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Tue, 22 Aug 2023 12:25:56 +0200
Subject: [PATCH 31/86] [clang][Interp] Actually consider ConstantExpr result

Since we have visitAPValue now, we might as well use it here.

Differential Revision: https://reviews.llvm.org/D158502
---
 clang/lib/AST/Interp/ByteCodeExprGen.cpp | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 2db71f945fb7909..0ce55f115a1a066 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -634,8 +634,14 @@ bool ByteCodeExprGen<Emitter>::VisitSubstNonTypeTemplateParmExpr(
 
 template <class Emitter>
 bool ByteCodeExprGen<Emitter>::VisitConstantExpr(const ConstantExpr *E) {
-  // TODO: Check if the ConstantExpr already has a value set and if so,
-  //   use that instead of evaluating it again.
+  // Try to emit the APValue directly, without visiting the subexpr.
+  // This will only fail if we can't emit the APValue, so won't emit any
+  // diagnostics or any double values.
+  std::optional<PrimType> T = classify(E->getType());
+  if (T && E->hasAPValueResult() &&
+      this->visitAPValue(E->getAPValueResult(), *T, E))
+    return true;
+
   return this->delegate(E->getSubExpr());
 }
 

>From a2e12e8d857b7b631e4a0828a6fff0d9e0799c4f Mon Sep 17 00:00:00 2001
From: Cullen Rhodes <cullen.rhodes at arm.com>
Date: Thu, 14 Sep 2023 08:31:52 +0100
Subject: [PATCH 32/86] [mlir][ArmSME] Lower vector.outerproduct to
 FMOPA/BFMOPA (#65621)

This patch adds support for lowering vector.outerproduct to the ArmSME
MOPA intrinsic for the following types:

  vector<[8]xf16>,  vector<[8]xf16>  -> vector<[8]x[8]xf16>
  vector<[8]xbf16>, vector<[8]xbf16> -> vector<[8]x[8]xbf16>
  vector<[4]xf32>,  vector<[4]xf32>  -> vector<[4]x[4]xf32>
  vector<[2]xf64>,  vector<[2]xf64>  -> vector<[2]x[2]xf64>

The FP variants are lowered to FMOPA (non-widening) [1] and BFloat to
BFMOPA
(non-widening) [2].

Note at the ISA level these variants are implemented by different
architecture features, these are listed below:

  FMOPA (non-widening)
    * half-precision   - +sme2p1,+sme-f16f16
    * single-precision - +sme
    * double-precision - +sme-f64f64
  BFMOPA (non-widening)
    * half-precision   - +sme2p1,+b16b16

There's currently no way to target different features when lowering to
ArmSME. Integration tests are added for F32 and F64. We use QEMU to run
the integration tests but SME2 support isn't available yet, it's
targeted for 9.0, so integration tests for these variants excluded.

Masking is currently unsupported.

Depends on #65450.

[1] https://developer.arm.com/documentation/ddi0602/2023-06/SME-Instructions/FMOPA--non-widening---Floating-point-outer-product-and-accumulate-
[2] https://developer.arm.com/documentation/ddi0602/2023-06/SME-Instructions/BFMOPA--non-widening---BFloat16-floating-point-outer-product-and-accumulate-
---
 .../include/mlir/Dialect/ArmSME/Utils/Utils.h |   2 +
 .../Transforms/LegalizeForLLVMExport.cpp      | 117 +++++++++++++++++-
 mlir/lib/Dialect/ArmSME/Utils/Utils.cpp       |   2 -
 .../Vector/Transforms/LowerVectorContract.cpp |   5 +-
 .../Dialect/ArmSME/vector-ops-to-llvm.mlir    | 107 +++++++++++++++-
 .../CPU/ArmSME/test-outerproduct-f32.mlir     | 116 +++++++++++++++++
 .../CPU/ArmSME/test-outerproduct-f64.mlir     |  77 ++++++++++++
 7 files changed, 418 insertions(+), 8 deletions(-)
 create mode 100644 mlir/test/Integration/Dialect/Vector/CPU/ArmSME/test-outerproduct-f32.mlir
 create mode 100644 mlir/test/Integration/Dialect/Vector/CPU/ArmSME/test-outerproduct-f64.mlir

diff --git a/mlir/include/mlir/Dialect/ArmSME/Utils/Utils.h b/mlir/include/mlir/Dialect/ArmSME/Utils/Utils.h
index 554b9f119230667..9e8ad48b3c2db94 100644
--- a/mlir/include/mlir/Dialect/ArmSME/Utils/Utils.h
+++ b/mlir/include/mlir/Dialect/ArmSME/Utils/Utils.h
@@ -20,6 +20,8 @@
 namespace mlir {
 namespace arm_sme {
 
+constexpr unsigned MinStreamingVectorLengthInBits = 128;
+
 /// Return minimum number of elements for the given element `type` in
 /// a vector of SVL bits.
 unsigned getSMETileSliceMinNumElts(Type type);
diff --git a/mlir/lib/Dialect/ArmSME/Transforms/LegalizeForLLVMExport.cpp b/mlir/lib/Dialect/ArmSME/Transforms/LegalizeForLLVMExport.cpp
index 685f8d57f76f52c..6c8843fbb4546e6 100644
--- a/mlir/lib/Dialect/ArmSME/Transforms/LegalizeForLLVMExport.cpp
+++ b/mlir/lib/Dialect/ArmSME/Transforms/LegalizeForLLVMExport.cpp
@@ -361,6 +361,112 @@ struct MoveVectorToTileSliceToArmSMELowering
   }
 };
 
+/// Lower `vector.outerproduct` to SME MOPA intrinsics.
+///
+/// Example:
+///
+///   %0 = vector.outerproduct %lhs, %rhs, %acc {kind = #vector.kind<add>}
+///     : vector<[4]xf32>, vector<[4]xf32>
+///
+/// is converted to:
+///
+///   "arm_sme.intr.mopa"(%tile_id, %ptrue_s, %ptrue_s, %lhs, %rhs)
+///     : (i32, vector<[4]xi1>, vector<[4]xi1>, vector<[4]xf32>,
+///        vector<[4]xf32>) -> ()
+///
+/// Currently only supports FMOPA and BFMOPA (non-widening).
+struct VectorOuterProductToArmSMELowering
+    : public ConvertOpToLLVMPattern<vector::OuterProductOp> {
+  using ConvertOpToLLVMPattern<vector::OuterProductOp>::ConvertOpToLLVMPattern;
+
+  LogicalResult
+  matchAndRewrite(vector::OuterProductOp outerProductOp,
+                  vector::OuterProductOp::Adaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    auto isSupportedType = [](VectorType vectorType) {
+      // TODO: the FP outer product instruction variants are predicated on
+      // different features [1]:
+      //
+      // * FMOPA (non-widening)
+      //   * half-precision   - +sme2p1,+sme-f16f16
+      //   * single-precision - +sme
+      //   * double-precision - +sme-f64f64
+      // * BFMOPA
+      //   * half-precision   - +sme2p1,+b16b16
+      //
+      // It should be possible to control lowering based on target features.
+      // [1] https://developer.arm.com/downloads/-/exploration-tools/feature-names-for-a-profile
+      if ((vectorType.getRank() != 2) || !vectorType.allDimsScalable())
+        return false;
+
+      auto elementType = vectorType.getElementType();
+
+      if (!elementType.isF16() && !elementType.isBF16() &&
+          !elementType.isF32() && !elementType.isF64())
+        return false;
+
+      unsigned minNumElts = arm_sme::MinStreamingVectorLengthInBits /
+                            vectorType.getElementTypeBitWidth();
+      if (vectorType.getShape() != ArrayRef<int64_t>({minNumElts, minNumElts}))
+        return false;
+
+      return true;
+    };
+
+    auto resultVectorType = outerProductOp.getResultVectorType();
+    if (!isSupportedType(resultVectorType))
+      return outerProductOp.emitError("unsupported type");
+
+    vector::CombiningKind kind = outerProductOp.getKind();
+    if (kind != vector::CombiningKind::ADD)
+      // TODO: support subtract.
+      return outerProductOp.emitError("unsupported kind");
+
+    auto maskableOp =
+        cast<vector::MaskableOpInterface>(outerProductOp.getOperation());
+    if (maskableOp.isMasked())
+      // TODO: support masking.
+      return outerProductOp.emitError("masking is currently unsupported");
+
+    if (!isa<VectorType>(outerProductOp.getOperandTypeRHS()))
+      // AXPY operation not suited for SME.
+      return failure();
+
+    auto loc = outerProductOp.getLoc();
+
+    Value acc = outerProductOp.getAcc();
+    if (!acc)
+      // Initalize accumulator with zero.
+      acc = rewriter.create<arm_sme::ZeroOp>(loc, resultVectorType);
+
+    unsigned elementWidth = resultVectorType.getElementTypeBitWidth();
+    auto tileId = rewriter.create<arm_sme::CastVectorToTile>(
+        loc, rewriter.getIntegerType(elementWidth), acc);
+
+    // Create all active predicate mask.
+    auto one = rewriter.create<arith::ConstantOp>(
+        loc, rewriter.getI1Type(),
+        rewriter.getIntegerAttr(rewriter.getI1Type(), 1));
+    auto predTy =
+        VectorType::get(resultVectorType.getShape()[0], rewriter.getI1Type(),
+                        /*scalableDims=*/{true});
+    auto allActiveMask = rewriter.create<vector::SplatOp>(loc, predTy, one);
+
+    auto tileI32 = castTileIDToI32(tileId, loc, rewriter);
+
+    // Create 'arm_sme.intr.mopa' outer product intrinsic.
+    rewriter.create<arm_sme::aarch64_sme_mopa>(
+        loc, tileI32, allActiveMask, allActiveMask, outerProductOp.getLhs(),
+        outerProductOp.getRhs());
+
+    // Create `CastTileToVectorOp` to use as the output.
+    rewriter.replaceOpWithNewOp<arm_sme::CastTileToVector>(
+        outerProductOp, resultVectorType, tileId);
+
+    return success();
+  }
+};
+
 } // namespace
 
 void mlir::configureArmSMELegalizeForExportTarget(
@@ -374,8 +480,10 @@ void mlir::configureArmSMELegalizeForExportTarget(
       arm_sme::aarch64_sme_st1b_horiz, arm_sme::aarch64_sme_st1h_horiz,
       arm_sme::aarch64_sme_st1w_horiz, arm_sme::aarch64_sme_st1d_horiz,
       arm_sme::aarch64_sme_st1q_horiz, arm_sme::aarch64_sme_write_horiz,
-      arm_sme::aarch64_sme_za_enable, arm_sme::aarch64_sme_za_disable>();
+      arm_sme::aarch64_sme_mopa, arm_sme::aarch64_sme_za_enable,
+      arm_sme::aarch64_sme_za_disable>();
   target.addLegalOp<GetTileID>();
+  target.addIllegalOp<vector::OuterProductOp>();
 
   // Mark 'func.func' ops as legal if either:
   //   1. no 'arm_za' function attribute is present.
@@ -405,7 +513,8 @@ void mlir::configureArmSMELegalizeForExportTarget(
 void mlir::populateArmSMELegalizeForLLVMExportPatterns(
     LLVMTypeConverter &converter, RewritePatternSet &patterns) {
   patterns.add<EnableZAPattern, DisableZAPattern>(patterns.getContext());
-  patterns.add<ZeroOpConversion, StoreTileSliceToArmSMELowering,
-               LoadTileSliceToArmSMELowering,
-               MoveVectorToTileSliceToArmSMELowering>(converter);
+  patterns
+      .add<ZeroOpConversion, StoreTileSliceToArmSMELowering,
+           LoadTileSliceToArmSMELowering, MoveVectorToTileSliceToArmSMELowering,
+           VectorOuterProductToArmSMELowering>(converter);
 }
diff --git a/mlir/lib/Dialect/ArmSME/Utils/Utils.cpp b/mlir/lib/Dialect/ArmSME/Utils/Utils.cpp
index 8b2be7bc1901b9a..b8a47951cc7bbba 100644
--- a/mlir/lib/Dialect/ArmSME/Utils/Utils.cpp
+++ b/mlir/lib/Dialect/ArmSME/Utils/Utils.cpp
@@ -17,8 +17,6 @@
 using namespace mlir;
 using namespace mlir::arm_sme;
 
-static constexpr unsigned MinStreamingVectorLengthInBits = 128;
-
 unsigned mlir::arm_sme::getSMETileSliceMinNumElts(Type type) {
   assert(isValidSMETileElementType(type) && "invalid tile type!");
   return MinStreamingVectorLengthInBits / type.getIntOrFloatBitWidth();
diff --git a/mlir/lib/Dialect/Vector/Transforms/LowerVectorContract.cpp b/mlir/lib/Dialect/Vector/Transforms/LowerVectorContract.cpp
index 3ab3c6ad8a3e29e..64ab0abda26e640 100644
--- a/mlir/lib/Dialect/Vector/Transforms/LowerVectorContract.cpp
+++ b/mlir/lib/Dialect/Vector/Transforms/LowerVectorContract.cpp
@@ -1122,11 +1122,14 @@ class OuterProductOpLowering : public OpRewritePattern<vector::OuterProductOp> {
 
   LogicalResult matchAndRewrite(vector::OuterProductOp op,
                                 PatternRewriter &rewriter) const override {
+    VectorType resType = op.getResultVectorType();
+    if ((resType.getShape().size() >= 2) && resType.allDimsScalable())
+      return failure();
+
     auto loc = op.getLoc();
 
     VectorType lhsType = op.getOperandVectorTypeLHS();
     VectorType rhsType = dyn_cast<VectorType>(op.getOperandTypeRHS());
-    VectorType resType = op.getResultVectorType();
     Type eltType = resType.getElementType();
     bool isInt = isa<IntegerType, IndexType>(eltType);
     Value acc = op.getAcc();
diff --git a/mlir/test/Dialect/ArmSME/vector-ops-to-llvm.mlir b/mlir/test/Dialect/ArmSME/vector-ops-to-llvm.mlir
index af528295ef6ee23..687ef79385334cf 100644
--- a/mlir/test/Dialect/ArmSME/vector-ops-to-llvm.mlir
+++ b/mlir/test/Dialect/ArmSME/vector-ops-to-llvm.mlir
@@ -1,4 +1,8 @@
-// RUN: mlir-opt %s -convert-vector-to-arm-sme -convert-arm-sme-to-scf -convert-vector-to-llvm="enable-arm-sme" -cse -canonicalize -split-input-file | FileCheck %s
+// RUN: mlir-opt %s -convert-vector-to-arm-sme -convert-arm-sme-to-scf -convert-vector-to-llvm="enable-arm-sme" -cse -canonicalize -split-input-file -allow-unregistered-dialect -verify-diagnostics | FileCheck %s
+
+//===----------------------------------------------------------------------===//
+// vector.transfer_write
+//===----------------------------------------------------------------------===//
 
 // CHECK-LABEL: @transfer_write_2d_zero_i8(
 // CHECK-SAME:                             %[[ARG0:.*]]: memref<?x?xi8>)
@@ -33,6 +37,10 @@ func.func @transfer_write_2d_zero_i8(%arg0 : memref<?x?xi8>) {
   return
 }
 
+//===----------------------------------------------------------------------===//
+// vector.load
+//===----------------------------------------------------------------------===//
+
 // -----
 
 // Load an 8-bit tile from a rank 2 memref with a non-zero offset for the first
@@ -232,6 +240,10 @@ func.func @vector_load_i128(%arg0 : memref<?x?xi128>) -> vector<[1]x[1]xi128> {
   return %tile : vector<[1]x[1]xi128>
 }
 
+//===----------------------------------------------------------------------===//
+// vector.store
+//===----------------------------------------------------------------------===//
+
 // -----
 
 // CHECK-LABEL: @vector_store_i8(
@@ -391,3 +403,96 @@ func.func @vector_store_i128(%tile : vector<[1]x[1]xi128>, %arg0 : memref<?x?xi1
   vector.store %tile, %arg0[%c0, %c0] : memref<?x?xi128>, vector<[1]x[1]xi128>
   return
 }
+
+//===----------------------------------------------------------------------===//
+// vector.outerproduct
+//===----------------------------------------------------------------------===//
+
+// -----
+
+// CHECK-LABEL: @vector_outerproduct_add_f16
+// CHECK-SAME: (%[[LHS:.*]]: vector<[8]xf16>, %[[RHS:.*]]: vector<[8]xf16>, %[[ACC:.*]]: vector<[8]x[8]xf16>)
+func.func @vector_outerproduct_add_f16(%lhs : vector<[8]xf16>, %rhs : vector<[8]xf16>, %acc : vector<[8]x[8]xf16>) {
+  // CHECK: %[[PTRUE_ALL:.*]] = arith.constant dense<true> : vector<[8]xi1>
+  // CHECK: %[[CAST_VECTOR_TO_TILE:.*]] = arm_sme.cast_vector_to_tile %[[ACC]] : vector<[8]x[8]xf16> to i16
+  // CHECK: %[[CAST_VECTOR_TO_TILE_I32:.*]] = arith.extui %[[CAST_VECTOR_TO_TILE]] : i16 to i32
+  // CHECK: "arm_sme.intr.mopa"(%[[CAST_VECTOR_TO_TILE_I32]], %[[PTRUE_ALL]], %[[PTRUE_ALL]], %[[LHS]], %[[RHS]]) : (i32, vector<[8]xi1>, vector<[8]xi1>, vector<[8]xf16>, vector<[8]xf16>)
+  %0 = vector.outerproduct %lhs, %rhs, %acc {kind = #vector.kind<add>} : vector<[8]xf16>, vector<[8]xf16>
+  "prevent.dce"(%0) : (vector<[8]x[8]xf16>) -> ()
+}
+
+// -----
+
+// CHECK-LABEL: @vector_outerproduct_add_bf16
+func.func @vector_outerproduct_add_bf16(%lhs : vector<[8]xbf16>, %rhs : vector<[8]xbf16>, %acc : vector<[8]x[8]xbf16>) {
+  // CHECK: "arm_sme.intr.mopa"({{.*}}, {{.*}}, {{.*}}) : (i32, vector<[8]xi1>, vector<[8]xi1>, vector<[8]xbf16>, vector<[8]xbf16>)
+  %0 = vector.outerproduct %lhs, %rhs, %acc {kind = #vector.kind<add>} : vector<[8]xbf16>, vector<[8]xbf16>
+  "prevent.dce"(%0) : (vector<[8]x[8]xbf16>) -> ()
+}
+
+// -----
+
+// CHECK-LABEL: @vector_outerproduct_add_f32
+func.func @vector_outerproduct_add_f32(%lhs : vector<[4]xf32>, %rhs : vector<[4]xf32>, %acc : vector<[4]x[4]xf32>) {
+  // CHECK-NOT: arith.extui
+  // CHECK-NOT: arith.trunci
+  // CHECK: "arm_sme.intr.mopa"({{.*}}, {{.*}}, {{.*}}) : (i32, vector<[4]xi1>, vector<[4]xi1>, vector<[4]xf32>, vector<[4]xf32>)
+  %0 = vector.outerproduct %lhs, %rhs, %acc {kind = #vector.kind<add>} : vector<[4]xf32>, vector<[4]xf32>
+  "prevent.dce"(%0) : (vector<[4]x[4]xf32>) -> ()
+}
+
+// -----
+
+// CHECK-LABEL: @vector_outerproduct_add_f64
+func.func @vector_outerproduct_add_f64(%lhs : vector<[2]xf64>, %rhs : vector<[2]xf64>, %acc : vector<[2]x[2]xf64>) {
+  // CHECK: arith.trunci {{.*}} : i64 to i32
+  // CHECK: "arm_sme.intr.mopa"({{.*}}, {{.*}}, {{.*}}) : (i32, vector<[2]xi1>, vector<[2]xi1>, vector<[2]xf64>, vector<[2]xf64>)
+  %0 = vector.outerproduct %lhs, %rhs, %acc {kind = #vector.kind<add>} : vector<[2]xf64>, vector<[2]xf64>
+  "prevent.dce"(%0) : (vector<[2]x[2]xf64>) -> ()
+}
+
+// -----
+
+// CHECK-LABEL: @vector_outerproduct_no_accumulator
+func.func @vector_outerproduct_no_accumulator(%lhs : vector<[2]xf64>, %rhs : vector<[2]xf64>) {
+  // CHECK: "arm_sme.intr.zero"({{.*}}) : (i32) -> ()
+  // CHECK: "arm_sme.intr.mopa"({{.*}}, {{.*}}, {{.*}}) : (i32, vector<[2]xi1>, vector<[2]xi1>, vector<[2]xf64>, vector<[2]xf64>)
+  %0 = vector.outerproduct %lhs, %rhs {kind = #vector.kind<add>} : vector<[2]xf64>, vector<[2]xf64>
+  "prevent.dce"(%0) : (vector<[2]x[2]xf64>) -> ()
+}
+
+// -----
+
+// CHECK-LABEL: @vector_outerproduct_unsupported_axpy
+func.func @vector_outerproduct_unsupported_axpy(%lhs : vector<[2]xf64>, %rhs : f64, %acc : vector<[2]xf64>) -> vector<[2]xf64> {
+  // CHECK-NOT: arm_sme
+  %0 = vector.outerproduct %lhs, %rhs, %acc {kind = #vector.kind<mul>} : vector<[2]xf64>, f64
+  return %0 : vector<[2]xf64>
+}
+
+// -----
+
+func.func @vector_outerproduct_unsupported_type(%lhs : vector<[16]xi8>, %rhs : vector<[16]xi8>, %acc : vector<[16]x[16]xi8>) {
+  // expected-error at +2 {{failed to legalize operation 'vector.outerproduct'}}
+  // expected-error at +1 {{unsupported type}}
+  %0 = vector.outerproduct %lhs, %rhs, %acc {kind = #vector.kind<add>} : vector<[16]xi8>, vector<[16]xi8>
+  "prevent.dce"(%0) : (vector<[16]x[16]xi8>) -> ()
+}
+
+// -----
+
+func.func @vector_outerproduct_unsupported_kind(%lhs : vector<[2]xf64>, %rhs : vector<[2]xf64>, %acc : vector<[2]x[2]xf64>) {
+  // expected-error at +2 {{failed to legalize operation 'vector.outerproduct'}}
+  // expected-error at +1 {{unsupported kind}}
+  %0 = vector.outerproduct %lhs, %rhs, %acc {kind = #vector.kind<mul>} : vector<[2]xf64>, vector<[2]xf64>
+  "prevent.dce"(%0) : (vector<[2]x[2]xf64>) -> ()
+}
+
+// -----
+
+func.func @vector_outerproduct_add_masked_f32(%lhs : vector<[4]xf32>, %rhs : vector<[4]xf32>, %acc : vector<[4]x[4]xf32>, %mask : vector<[4]x[4]xi1>) {
+  // expected-error at +2 {{failed to legalize operation 'vector.outerproduct'}}
+  // expected-error at +1 {{masking is currently unsupported}}
+  %0 = vector.mask %mask { vector.outerproduct %lhs, %rhs, %acc {kind = #vector.kind<add>} : vector<[4]xf32>, vector<[4]xf32> } : vector<[4]x[4]xi1> -> vector<[4]x[4]xf32>
+  "prevent.dce"(%0) : (vector<[4]x[4]xf32>) -> ()
+}
diff --git a/mlir/test/Integration/Dialect/Vector/CPU/ArmSME/test-outerproduct-f32.mlir b/mlir/test/Integration/Dialect/Vector/CPU/ArmSME/test-outerproduct-f32.mlir
new file mode 100644
index 000000000000000..00f1f6fd3fa8e19
--- /dev/null
+++ b/mlir/test/Integration/Dialect/Vector/CPU/ArmSME/test-outerproduct-f32.mlir
@@ -0,0 +1,116 @@
+// DEFINE: %{entry_point} = test_outerproduct_no_accumulator_4x4xf32
+// DEFINE: %{compile} = mlir-opt %s \
+// DEFINE:   -enable-arm-streaming="mode=locally enable-za" \
+// DEFINE:   -convert-vector-to-arm-sme -convert-arm-sme-to-scf \
+// DEFINE:   -convert-vector-to-llvm="enable-arm-sme" -cse -canonicalize \
+// DEFINE:   -allocate-arm-sme-tiles -test-lower-to-llvm
+// DEFINE: %{run} = %mcr_aarch64_cmd \
+// DEFINE:   -march=aarch64 -mattr=+sve,+sme \
+// DEFINE:   -e %{entry_point} -entry-point-result=void \
+// DEFINE:   -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils
+
+// RUN: %{compile} | %{run} | FileCheck %s --check-prefix=WITHOUT-ACC
+
+// REDEFINE: %{entry_point} = test_outerproduct_with_accumulator_4x4xf32
+// RUN: %{compile} | %{run} | FileCheck %s --check-prefix=WITH-ACC
+
+llvm.func @printCString(!llvm.ptr<i8>)
+
+func.func @printTileBegin() {
+  %0 = llvm.mlir.addressof @str_tile_begin : !llvm.ptr<array<11 x i8>>
+  %1 = llvm.mlir.constant(0 : index) : i64
+  %2 = llvm.getelementptr %0[%1, %1]
+    : (!llvm.ptr<array<11 x i8>>, i64, i64) -> !llvm.ptr<i8>
+  llvm.call @printCString(%2) : (!llvm.ptr<i8>) -> ()
+  return
+}
+
+func.func @printTileEnd() {
+  %0 = llvm.mlir.addressof @str_tile_end : !llvm.ptr<array<9 x i8>>
+  %1 = llvm.mlir.constant(0 : index) : i64
+  %2 = llvm.getelementptr %0[%1, %1]
+    : (!llvm.ptr<array<9 x i8>>, i64, i64) -> !llvm.ptr<i8>
+  llvm.call @printCString(%2) : (!llvm.ptr<i8>) -> ()
+  return
+}
+
+func.func @test_outerproduct_no_accumulator_4x4xf32() {
+  %c0 = arith.constant 0 : index
+
+  %vector_i32 = llvm.intr.experimental.stepvector : vector<[4]xi32>
+  %vector = arith.sitofp %vector_i32 : vector<[4]xi32> to vector<[4]xf32>
+  %tile = vector.outerproduct %vector, %vector : vector<[4]xf32>, vector<[4]xf32>
+
+  // Calculate the size of a 32-bit tile, e.g. ZA{n}.s.
+  %vscale = vector.vscale
+  %min_elts_s = arith.constant 4 : index
+  %svl_s = arith.muli %min_elts_s, %vscale : index
+  %za_s_size = arith.muli %svl_s, %svl_s : index
+
+  // Allocate memory.
+  %mem = memref.alloca(%za_s_size) : memref<?xf32>
+
+  // Store the tile to memory.
+  vector.store %tile, %mem[%c0] : memref<?xf32>, vector<[4]x[4]xf32>
+
+  // Reload and print. The smallest SVL is 128-bits so the tile will be at
+  // least 4x4xf32.
+  //
+  // WITHOUT-ACC:      TILE BEGIN
+  // WITHOUT-ACC-NEXT: ( 0, 0, 0, 0
+  // WITHOUT-ACC-NEXT: ( 0, 1, 2, 3
+  // WITHOUT-ACC-NEXT: ( 0, 2, 4, 6
+  // WITHOUT-ACC-NEXT: ( 0, 3, 6, 9
+  // WITHOUT-ACC:      TILE END
+  func.call @printTileBegin() : () -> ()
+  scf.for %i = %c0 to %za_s_size step %svl_s {
+    %tileslice = vector.load %mem[%i] : memref<?xf32>, vector<[4]xf32>
+    vector.print %tileslice : vector<[4]xf32>
+  }
+  func.call @printTileEnd() : () -> ()
+
+  return
+}
+
+func.func @test_outerproduct_with_accumulator_4x4xf32() {
+  %c0 = arith.constant 0 : index
+  %f10 = arith.constant 10.0 : f32
+
+  %acc = vector.broadcast %f10 : f32 to vector<[4]x[4]xf32>
+  %vector_i32 = llvm.intr.experimental.stepvector : vector<[4]xi32>
+  %vector = arith.sitofp %vector_i32 : vector<[4]xi32> to vector<[4]xf32>
+  %tile = vector.outerproduct %vector, %vector, %acc : vector<[4]xf32>, vector<[4]xf32>
+
+  // Calculate the size of a 32-bit tile, e.g. ZA{n}.s.
+  %vscale = vector.vscale
+  %min_elts_s = arith.constant 4 : index
+  %svl_s = arith.muli %min_elts_s, %vscale : index
+  %za_s_size = arith.muli %svl_s, %svl_s : index
+
+  // Allocate memory.
+  %mem = memref.alloca(%za_s_size) : memref<?xf32>
+
+  // Store the tile to memory.
+  vector.store %tile, %mem[%c0] : memref<?xf32>, vector<[4]x[4]xf32>
+
+  // Reload and print. The smallest SVL is 128-bits so the tile will be at
+  // least 4x4xf32.
+  //
+  // WITH-ACC:      TILE BEGIN
+  // WITH-ACC-NEXT: ( 10, 10, 10, 10
+  // WITH-ACC-NEXT: ( 10, 11, 12, 13
+  // WITH-ACC-NEXT: ( 10, 12, 14, 16
+  // WITH-ACC-NEXT: ( 10, 13, 16, 19
+  // WITH-ACC:      TILE END
+  func.call @printTileBegin() : () -> ()
+  scf.for %i = %c0 to %za_s_size step %svl_s {
+    %tileslice = vector.load %mem[%i] : memref<?xf32>, vector<[4]xf32>
+    vector.print %tileslice : vector<[4]xf32>
+  }
+  func.call @printTileEnd() : () -> ()
+
+  return
+}
+
+llvm.mlir.global internal constant @str_tile_begin("TILE BEGIN\0A")
+llvm.mlir.global internal constant @str_tile_end("TILE END\0A")
diff --git a/mlir/test/Integration/Dialect/Vector/CPU/ArmSME/test-outerproduct-f64.mlir b/mlir/test/Integration/Dialect/Vector/CPU/ArmSME/test-outerproduct-f64.mlir
new file mode 100644
index 000000000000000..2c2a06fa8db26e1
--- /dev/null
+++ b/mlir/test/Integration/Dialect/Vector/CPU/ArmSME/test-outerproduct-f64.mlir
@@ -0,0 +1,77 @@
+// DEFINE: %{entry_point} = test_outerproduct_with_accumulator_2x2xf64
+// DEFINE: %{compile} = mlir-opt %s \
+// DEFINE:   -enable-arm-streaming="mode=locally enable-za" \
+// DEFINE:   -convert-vector-to-arm-sme -convert-arm-sme-to-scf \
+// DEFINE:   -convert-vector-to-llvm="enable-arm-sme" -cse -canonicalize \
+// DEFINE:   -allocate-arm-sme-tiles -test-lower-to-llvm
+// DEFINE: %{run} = %mcr_aarch64_cmd \
+// DEFINE:   -march=aarch64 -mattr=+sve,+sme-f64f64 \
+// DEFINE:   -e %{entry_point} -entry-point-result=void \
+// DEFINE:   -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils
+
+// RUN: %{compile} | %{run} | FileCheck %s
+
+llvm.func @printCString(!llvm.ptr<i8>)
+
+func.func @printTileBegin() {
+  %0 = llvm.mlir.addressof @str_tile_begin : !llvm.ptr<array<11 x i8>>
+  %1 = llvm.mlir.constant(0 : index) : i64
+  %2 = llvm.getelementptr %0[%1, %1]
+    : (!llvm.ptr<array<11 x i8>>, i64, i64) -> !llvm.ptr<i8>
+  llvm.call @printCString(%2) : (!llvm.ptr<i8>) -> ()
+  return
+}
+
+func.func @printTileEnd() {
+  %0 = llvm.mlir.addressof @str_tile_end : !llvm.ptr<array<9 x i8>>
+  %1 = llvm.mlir.constant(0 : index) : i64
+  %2 = llvm.getelementptr %0[%1, %1]
+    : (!llvm.ptr<array<9 x i8>>, i64, i64) -> !llvm.ptr<i8>
+  llvm.call @printCString(%2) : (!llvm.ptr<i8>) -> ()
+  return
+}
+
+func.func @test_outerproduct_with_accumulator_2x2xf64() {
+  %c0 = arith.constant 0 : index
+  %f1 = arith.constant 1.0 : f64
+  %f2 = arith.constant 2.0 : f64
+  %f10 = arith.constant 10.0 : f64
+
+  %a = vector.splat %f1 : vector<[2]xf64>
+  %b = vector.splat %f2 : vector<[2]xf64>
+  // TODO: vector.splat doesn't support ArmSME.
+  %c = vector.broadcast %f10 : f64 to vector<[2]x[2]xf64>
+
+  %tile = vector.outerproduct %a, %b, %c : vector<[2]xf64>, vector<[2]xf64>
+
+  // Calculate the size of a 64-bit tile, e.g. ZA{n}.d.
+  %vscale = vector.vscale
+  %min_elts_d = arith.constant 2 : index
+  %svl_d = arith.muli %min_elts_d, %vscale : index
+  %za_d_size = arith.muli %svl_d, %svl_d : index
+
+  // Allocate memory.
+  %mem = memref.alloca(%za_d_size) : memref<?xf64>
+
+  // Store the tile to memory.
+  vector.store %tile, %mem[%c0] : memref<?xf64>, vector<[2]x[2]xf64>
+
+  // Reload and print. The smallest SVL is 128-bits so the tile will be at
+  // least 2x2xf64.
+  //
+  // CHECK:      TILE BEGIN
+  // CHECK-NEXT: ( 12, 12
+  // CHECK-NEXT: ( 12, 12
+  // CHECK:      TILE END
+  func.call @printTileBegin() : () -> ()
+  scf.for %i = %c0 to %za_d_size step %svl_d {
+    %tileslice = vector.load %mem[%i] : memref<?xf64>, vector<[2]xf64>
+    vector.print %tileslice : vector<[2]xf64>
+  }
+  func.call @printTileEnd() : () -> ()
+
+  return
+}
+
+llvm.mlir.global internal constant @str_tile_begin("TILE BEGIN\0A")
+llvm.mlir.global internal constant @str_tile_end("TILE END\0A")

>From 2b9dfd9ff2f00dd5a40923b2c20807503a20838e Mon Sep 17 00:00:00 2001
From: Jianjian Guan <jacquesguan at me.com>
Date: Thu, 14 Sep 2023 15:43:50 +0800
Subject: [PATCH 33/86] [RISCV] Update Zicntr and Zihpm to version 2p0 (#66323)

---
 clang/test/Preprocessor/riscv-target-features.c | 10 +++++++++-
 llvm/lib/Support/RISCVISAInfo.cpp               |  4 ++--
 llvm/test/CodeGen/RISCV/attributes.ll           |  8 ++++----
 llvm/unittests/Support/RISCVISAInfoTest.cpp     |  4 ++--
 4 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c
index 02b67dc7944ba88..8cdd23a927e3c80 100644
--- a/clang/test/Preprocessor/riscv-target-features.c
+++ b/clang/test/Preprocessor/riscv-target-features.c
@@ -643,7 +643,7 @@
 // RUN: %clang -target riscv64-unknown-linux-gnu \
 // RUN: -march=rv64izicntr -x c -E -dM %s \
 // RUN: -o - | FileCheck --check-prefix=CHECK-ZICNTR-EXT %s
-// CHECK-ZICNTR-EXT: __riscv_zicntr 1000000{{$}}
+// CHECK-ZICNTR-EXT: __riscv_zicntr 2000000{{$}}
 
 // RUN: %clang -target riscv32-unknown-linux-gnu \
 // RUN: -march=rv32izicsr2p0 -x c -E -dM %s \
@@ -677,6 +677,14 @@
 // RUN: -o - | FileCheck --check-prefix=CHECK-ZIHINTPAUSE-EXT %s
 // CHECK-ZIHINTPAUSE-EXT: __riscv_zihintpause 2000000{{$}}
 
+// RUN: %clang -target riscv32-unknown-linux-gnu \
+// RUN: -march=rv32izihpm -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-ZIHPM-EXT %s
+// RUN: %clang -target riscv64-unknown-linux-gnu \
+// RUN: -march=rv64izihpm -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-ZIHPM-EXT %s
+// CHECK-ZIHPM-EXT: __riscv_zihpm 2000000{{$}}
+
 // RUN: %clang -target riscv32-unknown-linux-gnu \
 // RUN: -march=rv32izk1p0 -x c -E -dM %s \
 // RUN: -o - | FileCheck --check-prefix=CHECK-ZK-EXT %s
diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp
index a02c9842e85839a..a3045657e63b724 100644
--- a/llvm/lib/Support/RISCVISAInfo.cpp
+++ b/llvm/lib/Support/RISCVISAInfo.cpp
@@ -116,12 +116,12 @@ static const RISCVSupportedExtension SupportedExtensions[] = {
     {"zicbom", RISCVExtensionVersion{1, 0}},
     {"zicbop", RISCVExtensionVersion{1, 0}},
     {"zicboz", RISCVExtensionVersion{1, 0}},
-    {"zicntr", RISCVExtensionVersion{1, 0}},
+    {"zicntr", RISCVExtensionVersion{2, 0}},
     {"zicsr", RISCVExtensionVersion{2, 0}},
     {"zifencei", RISCVExtensionVersion{2, 0}},
     {"zihintntl", RISCVExtensionVersion{1, 0}},
     {"zihintpause", RISCVExtensionVersion{2, 0}},
-    {"zihpm", RISCVExtensionVersion{1, 0}},
+    {"zihpm", RISCVExtensionVersion{2, 0}},
 
     {"zk", RISCVExtensionVersion{1, 0}},
     {"zkn", RISCVExtensionVersion{1, 0}},
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index 34209a2018e5070..29eaaee57868a83 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -241,8 +241,8 @@
 ; RV32ZCMT: .attribute 5, "rv32i2p1_zicsr2p0_zca1p0_zcmt1p0"
 ; RV32ZICSR: .attribute 5, "rv32i2p1_zicsr2p0"
 ; RV32ZIFENCEI: .attribute 5, "rv32i2p1_zifencei2p0"
-; RV32ZICNTR: .attribute 5, "rv32i2p1_zicntr1p0_zicsr2p0"
-; RV32ZIHPM: .attribute 5, "rv32i2p1_zicsr2p0_zihpm1p0"
+; RV32ZICNTR: .attribute 5, "rv32i2p1_zicntr2p0_zicsr2p0"
+; RV32ZIHPM: .attribute 5, "rv32i2p1_zicsr2p0_zihpm2p0"
 ; RV32ZFA: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zfa0p2"
 ; RV32ZVBB: .attribute 5, "rv32i2p1_zicsr2p0_zvbb1p0_zve32x1p0_zvkb1p0_zvl32b1p0"
 ; RV32ZVBC: .attribute 5, "rv32i2p1_zicsr2p0_zvbc1p0_zve32x1p0_zve64x1p0_zvl32b1p0_zvl64b1p0"
@@ -330,8 +330,8 @@
 ; RV64ZCMT: .attribute 5, "rv64i2p1_zicsr2p0_zca1p0_zcmt1p0"
 ; RV64ZICSR: .attribute 5, "rv64i2p1_zicsr2p0"
 ; RV64ZIFENCEI: .attribute 5, "rv64i2p1_zifencei2p0"
-; RV64ZICNTR: .attribute 5, "rv64i2p1_zicntr1p0_zicsr2p0"
-; RV64ZIHPM: .attribute 5, "rv64i2p1_zicsr2p0_zihpm1p0"
+; RV64ZICNTR: .attribute 5, "rv64i2p1_zicntr2p0_zicsr2p0"
+; RV64ZIHPM: .attribute 5, "rv64i2p1_zicsr2p0_zihpm2p0"
 ; RV64ZFA: .attribute 5, "rv64i2p1_f2p2_zicsr2p0_zfa0p2"
 ; RV64ZVBB: .attribute 5, "rv64i2p1_zicsr2p0_zvbb1p0_zve32x1p0_zvkb1p0_zvl32b1p0"
 ; RV64ZVBC: .attribute 5, "rv64i2p1_zicsr2p0_zvbc1p0_zve32x1p0_zve64x1p0_zvl32b1p0_zvl64b1p0"
diff --git a/llvm/unittests/Support/RISCVISAInfoTest.cpp b/llvm/unittests/Support/RISCVISAInfoTest.cpp
index f27557e41f973e2..a285baa57a2a6f5 100644
--- a/llvm/unittests/Support/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/Support/RISCVISAInfoTest.cpp
@@ -644,12 +644,12 @@ R"(All available -march extensions for RISC-V
 	zicbom              1.0
 	zicbop              1.0
 	zicboz              1.0
-	zicntr              1.0
+	zicntr              2.0
 	zicsr               2.0
 	zifencei            2.0
 	zihintntl           1.0
 	zihintpause         2.0
-	zihpm               1.0
+	zihpm               2.0
 	zmmul               1.0
 	zawrs               1.0
 	zfh                 1.0

>From 073bb8c19e0152b87e96f308ebd48c36b5cce3ae Mon Sep 17 00:00:00 2001
From: Weining Lu <luweining at loongson.cn>
Date: Thu, 14 Sep 2023 15:05:02 +0800
Subject: [PATCH 34/86] [LoongArch] Support llvm.is.fpclass for f32 and f64

is_fpclass (fj, mask)
->
sltu (r0, and (movfr2gr.[sd] (fclass.[sd] fj), (to_fclass_mask mask)))

[1]: https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_fclass_sd

Reviewed By: wangleiat

Differential Revision: https://reviews.llvm.org/D159183
---
 .../LoongArch/LoongArchFloat32InstrInfo.td    |    5 +-
 .../LoongArch/LoongArchFloat64InstrInfo.td    |   13 +-
 .../LoongArch/LoongArchISelLowering.cpp       |    2 +
 .../lib/Target/LoongArch/LoongArchInstrInfo.h |   15 +
 .../Target/LoongArch/LoongArchInstrInfo.td    |   26 +
 llvm/test/CodeGen/LoongArch/is_fpclass_f32.ll |  843 ++++++++++
 llvm/test/CodeGen/LoongArch/is_fpclass_f64.ll | 1371 +++++++++++++++++
 7 files changed, 2270 insertions(+), 5 deletions(-)
 create mode 100644 llvm/test/CodeGen/LoongArch/is_fpclass_f32.ll
 create mode 100644 llvm/test/CodeGen/LoongArch/is_fpclass_f64.ll

diff --git a/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
index eb49ae329ebe7e6..e01c721e9ee63b8 100644
--- a/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
@@ -153,10 +153,11 @@ def : PatFprFpr<fminnum_ieee, FMIN_S, FPR32>;
 def : PatFpr<fneg, FNEG_S, FPR32>;
 def : PatFpr<fabs, FABS_S, FPR32>;
 def : PatFpr<fsqrt, FSQRT_S, FPR32>;
-
 def : Pat<(fdiv fpimm1, (fsqrt FPR32:$fj)), (FRSQRT_S FPR32:$fj)>;
-
 def : Pat<(fcanonicalize FPR32:$fj), (FMAX_S $fj, $fj)>;
+def : Pat<(is_fpclass FPR32:$fj, (i32 timm:$mask)),
+          (SLTU R0, (AND (MOVFR2GR_S (FCLASS_S FPR32:$fj)),
+                         (to_fclass_mask timm:$mask)))>;
 
 /// Setcc
 
diff --git a/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
index 5118474725b6c8f..693e06cd4fd8b57 100644
--- a/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
@@ -142,15 +142,22 @@ def : PatFprFpr<fminnum_ieee, FMIN_D, FPR64>;
 def : PatFpr<fneg, FNEG_D, FPR64>;
 def : PatFpr<fabs, FABS_D, FPR64>;
 def : PatFpr<fsqrt, FSQRT_D, FPR64>;
-
 def : Pat<(fdiv fpimm1, (fsqrt FPR64:$fj)), (FRSQRT_D FPR64:$fj)>;
-
 def : Pat<(fcopysign FPR64:$fj, FPR32:$fk),
           (FCOPYSIGN_D FPR64:$fj, (FCVT_D_S FPR32:$fk))>;
 def : Pat<(fcopysign FPR32:$fj, FPR64:$fk),
           (FCOPYSIGN_S FPR32:$fj, (FCVT_S_D FPR64:$fk))>;
-
 def : Pat<(fcanonicalize FPR64:$fj), (FMAX_D $fj, $fj)>;
+let Predicates = [IsLA32] in {
+def : Pat<(is_fpclass FPR64:$fj, (i32 timm:$mask)),
+          (SLTU R0, (AND (MOVFR2GR_S_64 (FCLASS_D FPR64:$fj)),
+                         (to_fclass_mask timm:$mask)))>;
+} // Predicates = [IsLA32]
+let Predicates = [IsLA64] in {
+def : Pat<(is_fpclass FPR64:$fj, (i32 timm:$mask)),
+          (SLTU R0, (AND (MOVFR2GR_D (FCLASS_D FPR64:$fj)),
+                         (to_fclass_mask timm:$mask)))>;
+} // Predicates = [IsLA64]
 
 /// Setcc
 
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index c74093b3f14e242..a4fa79cb0aade6f 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -170,6 +170,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::FMAXNUM_IEEE, MVT::f32, Legal);
     setOperationAction(ISD::STRICT_FSETCCS, MVT::f32, Legal);
     setOperationAction(ISD::STRICT_FSETCC, MVT::f32, Legal);
+    setOperationAction(ISD::IS_FPCLASS, MVT::f32, Legal);
     setOperationAction(ISD::FSIN, MVT::f32, Expand);
     setOperationAction(ISD::FCOS, MVT::f32, Expand);
     setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
@@ -202,6 +203,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::FMA, MVT::f64, Legal);
     setOperationAction(ISD::FMINNUM_IEEE, MVT::f64, Legal);
     setOperationAction(ISD::FMAXNUM_IEEE, MVT::f64, Legal);
+    setOperationAction(ISD::IS_FPCLASS, MVT::f64, Legal);
     setOperationAction(ISD::FSIN, MVT::f64, Expand);
     setOperationAction(ISD::FCOS, MVT::f64, Expand);
     setOperationAction(ISD::FSINCOS, MVT::f64, Expand);
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
index cf83abf27a1e337..4b145d0baa4171e 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
@@ -88,5 +88,20 @@ class LoongArchInstrInfo : public LoongArchGenInstrInfo {
   const LoongArchSubtarget &STI;
 };
 
+namespace LoongArch {
+
+// Mask assignments for floating-point.
+static constexpr unsigned FClassMaskSignalingNaN = 0x001;
+static constexpr unsigned FClassMaskQuietNaN = 0x002;
+static constexpr unsigned FClassMaskNegativeInfinity = 0x004;
+static constexpr unsigned FClassMaskNegativeNormal = 0x008;
+static constexpr unsigned FClassMaskNegativeSubnormal = 0x010;
+static constexpr unsigned FClassMaskNegativeZero = 0x020;
+static constexpr unsigned FClassMaskPositiveInfinity = 0x040;
+static constexpr unsigned FClassMaskPositiveNormal = 0x080;
+static constexpr unsigned FClassMaskPositiveSubnormal = 0x100;
+static constexpr unsigned FClassMaskPositiveZero = 0x200;
+} // namespace LoongArch
+
 } // end namespace llvm
 #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHINSTRINFO_H
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 586f57a20c669d5..5d4ed46025d0578 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -143,6 +143,32 @@ def loongarch_iocsrwr_d : SDNode<"LoongArchISD::IOCSRWR_D",
 def loongarch_cpucfg : SDNode<"LoongArchISD::CPUCFG", SDTUnaryOp,
                                [SDNPHasChain]>;
 
+def to_fclass_mask: SDNodeXForm<timm, [{
+  uint64_t Check = N->getZExtValue();
+  unsigned Mask = 0;
+  if (Check & fcSNan)
+    Mask |= LoongArch::FClassMaskSignalingNaN;
+  if (Check & fcQNan)
+    Mask |= LoongArch::FClassMaskQuietNaN;
+  if (Check & fcPosInf)
+    Mask |= LoongArch::FClassMaskPositiveInfinity;
+  if (Check & fcNegInf)
+    Mask |= LoongArch::FClassMaskNegativeInfinity;
+  if (Check & fcPosNormal)
+    Mask |= LoongArch::FClassMaskPositiveNormal;
+  if (Check & fcNegNormal)
+    Mask |= LoongArch::FClassMaskNegativeNormal;
+  if (Check & fcPosSubnormal)
+    Mask |= LoongArch::FClassMaskPositiveSubnormal;
+  if (Check & fcNegSubnormal)
+    Mask |= LoongArch::FClassMaskNegativeSubnormal;
+  if (Check & fcPosZero)
+    Mask |= LoongArch::FClassMaskPositiveZero;
+  if (Check & fcNegZero)
+    Mask |= LoongArch::FClassMaskNegativeZero;
+  return CurDAG->getTargetConstant(Mask, SDLoc(N), Subtarget->getGRLenVT());
+}]>;
+
 //===----------------------------------------------------------------------===//
 // Operand and SDNode transformation definitions.
 //===----------------------------------------------------------------------===//
diff --git a/llvm/test/CodeGen/LoongArch/is_fpclass_f32.ll b/llvm/test/CodeGen/LoongArch/is_fpclass_f32.ll
new file mode 100644
index 000000000000000..095d6560e867127
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/is_fpclass_f32.ll
@@ -0,0 +1,843 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
+; RUN: llc --mtriple=loongarch32 --mattr=+f < %s | FileCheck %s
+; RUN: llc --mtriple=loongarch64 --mattr=+f < %s | FileCheck %s
+
+define i1 @isnan_f(float %x) {
+; CHECK-LABEL: isnan_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 3
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 3)  ; "nan"
+  ret i1 %0
+}
+
+define i1 @isnot_nan_f(float %x) {
+; CHECK-LABEL: isnot_nan_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 1020
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1020)  ; 0x3fc = "zero|subnormal|normal|inf"
+  ret i1 %0
+}
+
+define i1 @issignaling_f(float %x) {
+; CHECK-LABEL: issignaling_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 1
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1)  ; "snan"
+  ret i1 %0
+}
+
+define i1 @not_issignaling_f(float %x) {
+; CHECK-LABEL: not_issignaling_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 1022
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1022)  ; ~"snan"
+  ret i1 %0
+}
+
+define i1 @isquiet_f(float %x) {
+; CHECK-LABEL: isquiet_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 2
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 2)  ; "qnan"
+  ret i1 %0
+}
+
+define i1 @not_isquiet_f(float %x) {
+; CHECK-LABEL: not_isquiet_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 1021
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1021)  ; ~"qnan"
+  ret i1 %0
+}
+
+define i1 @isinf_f(float %x) {
+; CHECK-LABEL: isinf_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 68
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 516)  ; 0x204 = "inf"
+  ret i1 %0
+}
+
+define i1 @not_isinf_f(float %x) {
+; CHECK-LABEL: not_isinf_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 955
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 507)  ; ~0x204 = "~inf"
+  ret i1 %0
+}
+
+define i1 @is_plus_inf_f(float %x) {
+; CHECK-LABEL: is_plus_inf_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 64
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 512)  ; 0x200 = "+inf"
+  ret i1 %0
+}
+
+define i1 @is_minus_inf_f(float %x) {
+; CHECK-LABEL: is_minus_inf_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 4
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 4)  ; "-inf"
+  ret i1 %0
+}
+
+define i1 @not_is_minus_inf_f(float %x) {
+; CHECK-LABEL: not_is_minus_inf_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 1019
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1019)  ; ~"-inf"
+  ret i1 %0
+}
+
+define i1 @isfinite_f(float %x) {
+; CHECK-LABEL: isfinite_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 952
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 504)  ; 0x1f8 = "finite"
+  ret i1 %0
+}
+
+define i1 @not_isfinite_f(float %x) {
+; CHECK-LABEL: not_isfinite_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 71
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 519)  ; ~0x1f8 = "~finite"
+  ret i1 %0
+}
+
+define i1 @is_plus_finite_f(float %x) {
+; CHECK-LABEL: is_plus_finite_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 896
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 448)  ; 0x1c0 = "+finite"
+  ret i1 %0
+}
+
+define i1 @not_is_plus_finite_f(float %x) {
+; CHECK-LABEL: not_is_plus_finite_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 127
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 575)  ; ~0x1c0 = ~"+finite"
+  ret i1 %0
+}
+
+define i1 @is_minus_finite_f(float %x) {
+; CHECK-LABEL: is_minus_finite_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 56
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 56)  ; 0x38 = "-finite"
+  ret i1 %0
+}
+
+define i1 @not_is_minus_finite_f(float %x) {
+; CHECK-LABEL: not_is_minus_finite_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 967
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 967)  ; ~0x38 = ~"-finite"
+  ret i1 %0
+}
+
+define i1 @isnormal_f(float %x) {
+; CHECK-LABEL: isnormal_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 136
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 264)  ; 0x108 = "normal"
+  ret i1 %0
+}
+
+define i1 @not_isnormal_f(float %x) {
+; CHECK-LABEL: not_isnormal_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 887
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 759)  ; ~0x108 = "~normal"
+  ret i1 %0
+}
+
+define i1 @is_plus_normal_f(float %x) {
+; CHECK-LABEL: is_plus_normal_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 128
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 256)  ; 0x100 = "+normal"
+  ret i1 %0
+}
+
+define i1 @issubnormal_f(float %x) {
+; CHECK-LABEL: issubnormal_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 272
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 144)  ; 0x90 = "subnormal"
+  ret i1 %0
+}
+
+define i1 @not_issubnormal_f(float %x) {
+; CHECK-LABEL: not_issubnormal_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 751
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 879)  ; ~0x90 = "~subnormal"
+  ret i1 %0
+}
+
+define i1 @is_plus_subnormal_f(float %x) {
+; CHECK-LABEL: is_plus_subnormal_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 256
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 128)  ; 0x80 = "+subnormal"
+  ret i1 %0
+}
+
+define i1 @not_is_plus_subnormal_f(float %x) {
+; CHECK-LABEL: not_is_plus_subnormal_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 767
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 895)  ; ~0x80 = ~"+subnormal"
+  ret i1 %0
+}
+
+define i1 @is_minus_subnormal_f(float %x) {
+; CHECK-LABEL: is_minus_subnormal_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 16
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 16)  ; 0x10 = "-subnormal"
+  ret i1 %0
+}
+
+define i1 @not_is_minus_subnormal_f(float %x) {
+; CHECK-LABEL: not_is_minus_subnormal_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 1007
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1007)  ; ~0x10 = ~"-subnormal"
+  ret i1 %0
+}
+
+define i1 @iszero_f(float %x) {
+; CHECK-LABEL: iszero_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 544
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 96)  ; 0x60 = "zero"
+  ret i1 %0
+}
+
+define i1 @not_iszero_f(float %x) {
+; CHECK-LABEL: not_iszero_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 479
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 927)  ; ~0x60 = "~zero"
+  ret i1 %0
+}
+
+define i1 @issubnormal_or_zero_f(float %x) {
+; CHECK-LABEL: issubnormal_or_zero_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 816
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 240)  ; 0xf0 = "subnormal|zero"
+  ret i1 %0
+}
+
+define i1 @not_issubnormal_or_zero_f(float %x) {
+; CHECK-LABEL: not_issubnormal_or_zero_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 207
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 783)  ; ~0xf0 = "~(subnormal|zero)"
+  ret i1 %0
+}
+
+define i1 @is_plus_zero_f(float %x) {
+; CHECK-LABEL: is_plus_zero_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 512
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 64)  ; 0x40 = "+zero"
+  ret i1 %0
+}
+
+define i1 @not_is_plus_zero_f(float %x) {
+; CHECK-LABEL: not_is_plus_zero_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 511
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 959)  ; ~0x40 = ~"+zero"
+  ret i1 %0
+}
+
+define i1 @is_minus_zero_f(float %x) {
+; CHECK-LABEL: is_minus_zero_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 32
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 32)  ; 0x20 = "-zero"
+  ret i1 %0
+}
+
+define i1 @not_is_minus_zero_f(float %x) {
+; CHECK-LABEL: not_is_minus_zero_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 991
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 991)  ; ~0x20 = ~"-zero"
+  ret i1 %0
+}
+
+define i1 @isnone_f(float %x) {
+; CHECK-LABEL: isnone_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 0
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 0)
+  ret i1 %0
+}
+
+define i1 @isany_f(float %x) {
+; CHECK-LABEL: isany_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 1023
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1023)
+  ret i1 %0
+}
+
+define i1 @iszero_or_nan_f(float %x) {
+; CHECK-LABEL: iszero_or_nan_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 547
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 99)  ; 0x60|0x3 = "zero|nan"
+  ret i1 %0
+}
+
+define i1 @not_iszero_or_nan_f(float %x) {
+; CHECK-LABEL: not_iszero_or_nan_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 476
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 924)  ; ~0x60 = "~(zero|nan)"
+  ret i1 %0
+}
+
+define i1 @iszero_or_qnan_f(float %x) {
+; CHECK-LABEL: iszero_or_qnan_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 546
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 98)  ; 0x60|0x2 = "zero|qnan"
+  ret i1 %0
+}
+
+define i1 @iszero_or_snan_f(float %x) {
+; CHECK-LABEL: iszero_or_snan_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 545
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 97)  ; 0x60|0x1 = "zero|snan"
+  ret i1 %0
+}
+
+define i1 @not_iszero_or_qnan_f(float %x) {
+; CHECK-LABEL: not_iszero_or_qnan_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 477
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 925)  ; ~(0x60|0x2) = "~(zero|qnan)"
+  ret i1 %0
+}
+
+define i1 @not_iszero_or_snan_f(float %x) {
+; CHECK-LABEL: not_iszero_or_snan_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 478
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 926)  ; ~(0x60|0x1) = "~(zero|snan)"
+  ret i1 %0
+}
+
+define i1 @isinf_or_nan_f(float %x) {
+; CHECK-LABEL: isinf_or_nan_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 71
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 519)  ; 0x204|0x3 = "inf|nan"
+  ret i1 %0
+}
+
+define i1 @not_isinf_or_nan_f(float %x) {
+; CHECK-LABEL: not_isinf_or_nan_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 952
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 504)  ; ~(0x204|0x3) = "~(inf|nan)"
+  ret i1 %0
+}
+
+define i1 @isfinite_or_nan_f(float %x) {
+; CHECK-LABEL: isfinite_or_nan_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 955
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 507)  ; 0x1f8|0x3 = "finite|nan"
+  ret i1 %0
+}
+
+define i1 @not_isfinite_or_nan_f(float %x) {
+; CHECK-LABEL: not_isfinite_or_nan_f:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 68
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 516)  ; ~(0x1f8|0x3) = "~(finite|nan)"
+  ret i1 %0
+}
+
+define i1 @is_plus_inf_or_nan_f(float %x) {
+; CHECK-LABEL: is_plus_inf_or_nan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 67
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 515)  ; 0x200|0x3 = "+inf|nan"
+  ret i1 %class
+}
+
+define i1 @is_minus_inf_or_nan_f(float %x) {
+; CHECK-LABEL: is_minus_inf_or_nan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 7
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 7)  ; "-inf|nan"
+  ret i1 %class
+}
+
+define i1 @not_is_plus_inf_or_nan_f(float %x) {
+; CHECK-LABEL: not_is_plus_inf_or_nan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 956
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 508)  ; ~(0x200|0x3) = "~(+inf|nan)"
+  ret i1 %class
+}
+
+define i1 @not_is_minus_inf_or_nan_f(float %x) {
+; CHECK-LABEL: not_is_minus_inf_or_nan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 1016
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1016)  ; "~(-inf|nan)"
+  ret i1 %class
+}
+
+define i1 @is_plus_inf_or_snan_f(float %x) {
+; CHECK-LABEL: is_plus_inf_or_snan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 65
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 513)  ; 0x200|0x1 = "+inf|snan"
+  ret i1 %class
+}
+
+define i1 @is_plus_inf_or_qnan_f(float %x) {
+; CHECK-LABEL: is_plus_inf_or_qnan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 66
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 514)  ; 0x200|0x1 = "+inf|qnan"
+  ret i1 %class
+}
+
+define i1 @not_is_plus_inf_or_snan_f(float %x) {
+; CHECK-LABEL: not_is_plus_inf_or_snan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 958
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 510) ; ~(+inf|snan)
+  ret i1 %class
+}
+
+define i1 @not_is_plus_inf_or_qnan_f(float %x) {
+; CHECK-LABEL: not_is_plus_inf_or_qnan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 957
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 509) ; ~(+inf|qnan)
+  ret i1 %class
+}
+
+define i1 @is_minus_inf_or_snan_f(float %x) {
+; CHECK-LABEL: is_minus_inf_or_snan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 5
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 5)  ; "-inf|snan"
+  ret i1 %class
+}
+
+define i1 @is_minus_inf_or_qnan_f(float %x) {
+; CHECK-LABEL: is_minus_inf_or_qnan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 6
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 6)  ; "-inf|qnan"
+  ret i1 %class
+}
+
+define i1 @not_is_minus_inf_or_snan_f(float %x) {
+; CHECK-LABEL: not_is_minus_inf_or_snan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 1018
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1018)  ; "~(-inf|snan)"
+  ret i1 %class
+}
+
+define i1 @not_is_minus_inf_or_qnan_f(float %x) {
+; CHECK-LABEL: not_is_minus_inf_or_qnan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 1017
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1017)  ; "-inf|qnan"
+  ret i1 %class
+}
+
+define i1 @issubnormal_or_nan_f(float %x) {
+; CHECK-LABEL: issubnormal_or_nan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 275
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 147)  ; 0x90|0x3 = "subnormal|nan"
+  ret i1 %class
+}
+
+define i1 @issubnormal_or_zero_or_nan_f(float %x) {
+; CHECK-LABEL: issubnormal_or_zero_or_nan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 819
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 243)  ; 0xf0|0x3 = "subnormal|zero|nan"
+  ret i1 %class
+}
+
+define i1 @issubnormal_or_zero_or_snan_f(float %x) {
+; CHECK-LABEL: issubnormal_or_zero_or_snan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 817
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 241)  ; 0x90|0x1 = "subnormal|snan"
+  ret i1 %class
+}
+
+define i1 @issubnormal_or_zero_or_qnan_f(float %x) {
+; CHECK-LABEL: issubnormal_or_zero_or_qnan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 818
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 242)  ; 0x90|0x2 = "subnormal|qnan"
+  ret i1 %class
+}
+
+define i1 @not_issubnormal_or_nan_f(float %x) {
+; CHECK-LABEL: not_issubnormal_or_nan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 748
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 876)  ; ~(0x90|0x3) = ~"subnormal|nan"
+  ret i1 %class
+}
+
+define i1 @not_issubnormal_or_zero_or_nan_f(float %x) {
+; CHECK-LABEL: not_issubnormal_or_zero_or_nan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 204
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 780)  ; ~(0xf0|0x3) = ~"subnormal|zero|nan"
+  ret i1 %class
+}
+
+define i1 @not_issubnormal_or_zero_or_snan_f(float %x) {
+; CHECK-LABEL: not_issubnormal_or_zero_or_snan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 206
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 782)  ; ~(0x90|0x1) = ~"subnormal|snan"
+  ret i1 %class
+}
+
+define i1 @not_issubnormal_or_zero_or_qnan_f(float %x) {
+; CHECK-LABEL: not_issubnormal_or_zero_or_qnan_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fclass.s $fa0, $fa0
+; CHECK-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK-NEXT:    and $a0, $a0, 205
+; CHECK-NEXT:    sltu $a0, $zero, $a0
+; CHECK-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 781)  ; ~(0x90|0x2) = ~"subnormal|qnan"
+  ret i1 %class
+}
+
+declare i1 @llvm.is.fpclass.f32(float, i32)
diff --git a/llvm/test/CodeGen/LoongArch/is_fpclass_f64.ll b/llvm/test/CodeGen/LoongArch/is_fpclass_f64.ll
new file mode 100644
index 000000000000000..590e1db84b14af4
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/is_fpclass_f64.ll
@@ -0,0 +1,1371 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
+; RUN: llc --mtriple=loongarch32 --mattr=+d < %s | FileCheck %s --check-prefix=CHECK32
+; RUN: llc --mtriple=loongarch64 --mattr=+d < %s | FileCheck %s --check-prefix=CHECK64
+
+define i1 @isnan_d(double %x) {
+; CHECK32-LABEL: isnan_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 3
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: isnan_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 3
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 3)  ; "nan"
+  ret i1 %0
+}
+
+define i1 @isnot_nan_d(double %x) {
+; CHECK32-LABEL: isnot_nan_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 1020
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: isnot_nan_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 1020
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 1020)  ; 0x3fc = "zero|subnormal|normal|inf"
+  ret i1 %0
+}
+
+define i1 @issignaling_d(double %x) {
+; CHECK32-LABEL: issignaling_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 1
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: issignaling_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 1
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 1)  ; "snan"
+  ret i1 %0
+}
+
+define i1 @not_issignaling_d(double %x) {
+; CHECK32-LABEL: not_issignaling_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 1022
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_issignaling_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 1022
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 1022)  ; ~"snan"
+  ret i1 %0
+}
+
+define i1 @isquiet_d(double %x) {
+; CHECK32-LABEL: isquiet_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 2
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: isquiet_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 2
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 2)  ; "qnan"
+  ret i1 %0
+}
+
+define i1 @not_isquiet_d(double %x) {
+; CHECK32-LABEL: not_isquiet_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 1021
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_isquiet_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 1021
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 1021)  ; ~"qnan"
+  ret i1 %0
+}
+
+define i1 @isinf_d(double %x) {
+; CHECK32-LABEL: isinf_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 68
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: isinf_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 68
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 516)  ; 0x204 = "inf"
+  ret i1 %0
+}
+
+define i1 @not_isinf_d(double %x) {
+; CHECK32-LABEL: not_isinf_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 955
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_isinf_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 955
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 507)  ; ~0x204 = "~inf"
+  ret i1 %0
+}
+
+define i1 @is_plus_inf_d(double %x) {
+; CHECK32-LABEL: is_plus_inf_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 64
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_plus_inf_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 64
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 512)  ; 0x200 = "+inf"
+  ret i1 %0
+}
+
+define i1 @is_minus_inf_d(double %x) {
+; CHECK32-LABEL: is_minus_inf_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 4
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_minus_inf_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 4
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 4)  ; "-inf"
+  ret i1 %0
+}
+
+define i1 @not_is_minus_inf_d(double %x) {
+; CHECK32-LABEL: not_is_minus_inf_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 1019
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_is_minus_inf_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 1019
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 1019)  ; ~"-inf"
+  ret i1 %0
+}
+
+define i1 @isfinite_d(double %x) {
+; CHECK32-LABEL: isfinite_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 952
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: isfinite_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 952
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 504)  ; 0x1f8 = "finite"
+  ret i1 %0
+}
+
+define i1 @not_isfinite_d(double %x) {
+; CHECK32-LABEL: not_isfinite_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 71
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_isfinite_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 71
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 519)  ; ~0x1f8 = "~finite"
+  ret i1 %0
+}
+
+define i1 @is_plus_finite_d(double %x) {
+; CHECK32-LABEL: is_plus_finite_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 896
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_plus_finite_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 896
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 448)  ; 0x1c0 = "+finite"
+  ret i1 %0
+}
+
+define i1 @not_is_plus_finite_d(double %x) {
+; CHECK32-LABEL: not_is_plus_finite_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 127
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_is_plus_finite_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 127
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 575)  ; ~0x1c0 = ~"+finite"
+  ret i1 %0
+}
+
+define i1 @is_minus_finite_d(double %x) {
+; CHECK32-LABEL: is_minus_finite_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 56
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_minus_finite_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 56
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 56)  ; 0x38 = "-finite"
+  ret i1 %0
+}
+
+define i1 @not_is_minus_finite_d(double %x) {
+; CHECK32-LABEL: not_is_minus_finite_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 967
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_is_minus_finite_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 967
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 967)  ; ~0x38 = ~"-finite"
+  ret i1 %0
+}
+
+define i1 @isnormal_d(double %x) {
+; CHECK32-LABEL: isnormal_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 136
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: isnormal_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 136
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 264)  ; 0x108 = "normal"
+  ret i1 %0
+}
+
+define i1 @not_isnormal_d(double %x) {
+; CHECK32-LABEL: not_isnormal_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 887
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_isnormal_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 887
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 759)  ; ~0x108 = "~normal"
+  ret i1 %0
+}
+
+define i1 @is_plus_normal_d(double %x) {
+; CHECK32-LABEL: is_plus_normal_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 128
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_plus_normal_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 128
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 256)  ; 0x100 = "+normal"
+  ret i1 %0
+}
+
+define i1 @issubnormal_d(double %x) {
+; CHECK32-LABEL: issubnormal_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 272
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: issubnormal_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 272
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 144)  ; 0x90 = "subnormal"
+  ret i1 %0
+}
+
+define i1 @not_issubnormal_d(double %x) {
+; CHECK32-LABEL: not_issubnormal_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 751
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_issubnormal_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 751
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 879)  ; ~0x90 = "~subnormal"
+  ret i1 %0
+}
+
+define i1 @is_plus_subnormal_d(double %x) {
+; CHECK32-LABEL: is_plus_subnormal_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 256
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_plus_subnormal_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 256
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 128)  ; 0x80 = "+subnormal"
+  ret i1 %0
+}
+
+define i1 @not_is_plus_subnormal_d(double %x) {
+; CHECK32-LABEL: not_is_plus_subnormal_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 767
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_is_plus_subnormal_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 767
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 895)  ; ~0x80 = ~"+subnormal"
+  ret i1 %0
+}
+
+define i1 @is_minus_subnormal_d(double %x) {
+; CHECK32-LABEL: is_minus_subnormal_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 16
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_minus_subnormal_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 16
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 16)  ; 0x10 = "-subnormal"
+  ret i1 %0
+}
+
+define i1 @not_is_minus_subnormal_d(double %x) {
+; CHECK32-LABEL: not_is_minus_subnormal_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 1007
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_is_minus_subnormal_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 1007
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 1007)  ; ~0x10 = ~"-subnormal"
+  ret i1 %0
+}
+
+define i1 @iszero_d(double %x) {
+; CHECK32-LABEL: iszero_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 544
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: iszero_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 544
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 96)  ; 0x60 = "zero"
+  ret i1 %0
+}
+
+define i1 @not_iszero_d(double %x) {
+; CHECK32-LABEL: not_iszero_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 479
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_iszero_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 479
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 927)  ; ~0x60 = "~zero"
+  ret i1 %0
+}
+
+define i1 @issubnormal_or_zero_d(double %x) {
+; CHECK32-LABEL: issubnormal_or_zero_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 816
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: issubnormal_or_zero_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 816
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 240)  ; 0xf0 = "subnormal|zero"
+  ret i1 %0
+}
+
+define i1 @not_issubnormal_or_zero_d(double %x) {
+; CHECK32-LABEL: not_issubnormal_or_zero_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 207
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_issubnormal_or_zero_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 207
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 783)  ; ~0xf0 = "~(subnormal|zero)"
+  ret i1 %0
+}
+
+define i1 @is_plus_zero_d(double %x) {
+; CHECK32-LABEL: is_plus_zero_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 512
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_plus_zero_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 512
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 64)  ; 0x40 = "+zero"
+  ret i1 %0
+}
+
+define i1 @not_is_plus_zero_d(double %x) {
+; CHECK32-LABEL: not_is_plus_zero_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 511
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_is_plus_zero_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 511
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 959)  ; ~0x40 = ~"+zero"
+  ret i1 %0
+}
+
+define i1 @is_minus_zero_d(double %x) {
+; CHECK32-LABEL: is_minus_zero_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 32
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_minus_zero_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 32
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 32)  ; 0x20 = "-zero"
+  ret i1 %0
+}
+
+define i1 @not_is_minus_zero_d(double %x) {
+; CHECK32-LABEL: not_is_minus_zero_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 991
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_is_minus_zero_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 991
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 991)  ; ~0x20 = ~"-zero"
+  ret i1 %0
+}
+
+define i1 @isnone_d(double %x) {
+; CHECK32-LABEL: isnone_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 0
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: isnone_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 0
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 0)
+  ret i1 %0
+}
+
+define i1 @isany_d(double %x) {
+; CHECK32-LABEL: isany_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 1023
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: isany_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 1023
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 1023)
+  ret i1 %0
+}
+
+define i1 @iszero_or_nan_d(double %x) {
+; CHECK32-LABEL: iszero_or_nan_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 547
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: iszero_or_nan_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 547
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 99)  ; 0x60|0x3 = "zero|nan"
+  ret i1 %0
+}
+
+define i1 @not_iszero_or_nan_d(double %x) {
+; CHECK32-LABEL: not_iszero_or_nan_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 476
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_iszero_or_nan_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 476
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 924)  ; ~0x60 = "~(zero|nan)"
+  ret i1 %0
+}
+
+define i1 @iszero_or_qnan_d(double %x) {
+; CHECK32-LABEL: iszero_or_qnan_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 546
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: iszero_or_qnan_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 546
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 98)  ; 0x60|0x2 = "zero|qnan"
+  ret i1 %0
+}
+
+define i1 @iszero_or_snan_d(double %x) {
+; CHECK32-LABEL: iszero_or_snan_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 545
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: iszero_or_snan_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 545
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 97)  ; 0x60|0x1 = "zero|snan"
+  ret i1 %0
+}
+
+define i1 @not_iszero_or_qnan_d(double %x) {
+; CHECK32-LABEL: not_iszero_or_qnan_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 477
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_iszero_or_qnan_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 477
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 925)  ; ~(0x60|0x2) = "~(zero|qnan)"
+  ret i1 %0
+}
+
+define i1 @not_iszero_or_snan_d(double %x) {
+; CHECK32-LABEL: not_iszero_or_snan_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 478
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_iszero_or_snan_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 478
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 926)  ; ~(0x60|0x1) = "~(zero|snan)"
+  ret i1 %0
+}
+
+define i1 @isinf_or_nan_d(double %x) {
+; CHECK32-LABEL: isinf_or_nan_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 71
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: isinf_or_nan_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 71
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 519)  ; 0x204|0x3 = "inf|nan"
+  ret i1 %0
+}
+
+define i1 @not_isinf_or_nan_d(double %x) {
+; CHECK32-LABEL: not_isinf_or_nan_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 952
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_isinf_or_nan_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 952
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 504)  ; ~(0x204|0x3) = "~(inf|nan)"
+  ret i1 %0
+}
+
+define i1 @isfinite_or_nan_d(double %x) {
+; CHECK32-LABEL: isfinite_or_nan_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 955
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: isfinite_or_nan_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 955
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 507)  ; 0x1f8|0x3 = "finite|nan"
+  ret i1 %0
+}
+
+define i1 @not_isfinite_or_nan_d(double %x) {
+; CHECK32-LABEL: not_isfinite_or_nan_d:
+; CHECK32:       # %bb.0: # %entry
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 68
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_isfinite_or_nan_d:
+; CHECK64:       # %bb.0: # %entry
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 68
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+entry:
+  %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 516)  ; ~(0x1f8|0x3) = "~(finite|nan)"
+  ret i1 %0
+}
+
+define i1 @is_plus_inf_or_nan_d(double %x) {
+; CHECK32-LABEL: is_plus_inf_or_nan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 67
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_plus_inf_or_nan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 67
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 515)  ; 0x200|0x3 = "+inf|nan"
+  ret i1 %class
+}
+
+define i1 @is_minus_inf_or_nan_d(double %x) {
+; CHECK32-LABEL: is_minus_inf_or_nan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 7
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_minus_inf_or_nan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 7
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 7)  ; "-inf|nan"
+  ret i1 %class
+}
+
+define i1 @not_is_plus_inf_or_nan_d(double %x) {
+; CHECK32-LABEL: not_is_plus_inf_or_nan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 956
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_is_plus_inf_or_nan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 956
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 508)  ; ~(0x200|0x3) = "~(+inf|nan)"
+  ret i1 %class
+}
+
+define i1 @not_is_minus_inf_or_nan_d(double %x) {
+; CHECK32-LABEL: not_is_minus_inf_or_nan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 1016
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_is_minus_inf_or_nan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 1016
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 1016)  ; "~(-inf|nan)"
+  ret i1 %class
+}
+
+define i1 @is_plus_inf_or_snan_d(double %x) {
+; CHECK32-LABEL: is_plus_inf_or_snan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 65
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_plus_inf_or_snan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 65
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 513)  ; 0x200|0x1 = "+inf|snan"
+  ret i1 %class
+}
+
+define i1 @is_plus_inf_or_qnan_d(double %x) {
+; CHECK32-LABEL: is_plus_inf_or_qnan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 66
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_plus_inf_or_qnan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 66
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 514)  ; 0x200|0x1 = "+inf|qnan"
+  ret i1 %class
+}
+
+define i1 @not_is_plus_inf_or_snan_d(double %x) {
+; CHECK32-LABEL: not_is_plus_inf_or_snan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 958
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_is_plus_inf_or_snan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 958
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 510) ; ~(+inf|snan)
+  ret i1 %class
+}
+
+define i1 @not_is_plus_inf_or_qnan_d(double %x) {
+; CHECK32-LABEL: not_is_plus_inf_or_qnan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 957
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_is_plus_inf_or_qnan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 957
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 509) ; ~(+inf|qnan)
+  ret i1 %class
+}
+
+define i1 @is_minus_inf_or_snan_d(double %x) {
+; CHECK32-LABEL: is_minus_inf_or_snan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 5
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_minus_inf_or_snan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 5
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 5)  ; "-inf|snan"
+  ret i1 %class
+}
+
+define i1 @is_minus_inf_or_qnan_d(double %x) {
+; CHECK32-LABEL: is_minus_inf_or_qnan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 6
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: is_minus_inf_or_qnan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 6
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 6)  ; "-inf|qnan"
+  ret i1 %class
+}
+
+define i1 @not_is_minus_inf_or_snan_d(double %x) {
+; CHECK32-LABEL: not_is_minus_inf_or_snan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 1018
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_is_minus_inf_or_snan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 1018
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 1018)  ; "~(-inf|snan)"
+  ret i1 %class
+}
+
+define i1 @not_is_minus_inf_or_qnan_d(double %x) {
+; CHECK32-LABEL: not_is_minus_inf_or_qnan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 1017
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_is_minus_inf_or_qnan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 1017
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 1017)  ; "-inf|qnan"
+  ret i1 %class
+}
+
+define i1 @issubnormal_or_nan_d(double %x) {
+; CHECK32-LABEL: issubnormal_or_nan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 275
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: issubnormal_or_nan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 275
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 147)  ; 0x90|0x3 = "subnormal|nan"
+  ret i1 %class
+}
+
+define i1 @issubnormal_or_zero_or_nan_d(double %x) {
+; CHECK32-LABEL: issubnormal_or_zero_or_nan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 819
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: issubnormal_or_zero_or_nan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 819
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 243)  ; 0xf0|0x3 = "subnormal|zero|nan"
+  ret i1 %class
+}
+
+define i1 @issubnormal_or_zero_or_snan_d(double %x) {
+; CHECK32-LABEL: issubnormal_or_zero_or_snan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 817
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: issubnormal_or_zero_or_snan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 817
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 241)  ; 0x90|0x1 = "subnormal|snan"
+  ret i1 %class
+}
+
+define i1 @issubnormal_or_zero_or_qnan_d(double %x) {
+; CHECK32-LABEL: issubnormal_or_zero_or_qnan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 818
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: issubnormal_or_zero_or_qnan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 818
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 242)  ; 0x90|0x2 = "subnormal|qnan"
+  ret i1 %class
+}
+
+define i1 @not_issubnormal_or_nan_d(double %x) {
+; CHECK32-LABEL: not_issubnormal_or_nan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 748
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_issubnormal_or_nan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 748
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 876)  ; ~(0x90|0x3) = ~"subnormal|nan"
+  ret i1 %class
+}
+
+define i1 @not_issubnormal_or_zero_or_nan_d(double %x) {
+; CHECK32-LABEL: not_issubnormal_or_zero_or_nan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 204
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_issubnormal_or_zero_or_nan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 204
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 780)  ; ~(0xf0|0x3) = ~"subnormal|zero|nan"
+  ret i1 %class
+}
+
+define i1 @not_issubnormal_or_zero_or_snan_d(double %x) {
+; CHECK32-LABEL: not_issubnormal_or_zero_or_snan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 206
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_issubnormal_or_zero_or_snan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 206
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 782)  ; ~(0x90|0x1) = ~"subnormal|snan"
+  ret i1 %class
+}
+
+define i1 @not_issubnormal_or_zero_or_qnan_d(double %x) {
+; CHECK32-LABEL: not_issubnormal_or_zero_or_qnan_d:
+; CHECK32:       # %bb.0:
+; CHECK32-NEXT:    fclass.d $fa0, $fa0
+; CHECK32-NEXT:    movfr2gr.s $a0, $fa0
+; CHECK32-NEXT:    and $a0, $a0, 205
+; CHECK32-NEXT:    sltu $a0, $zero, $a0
+; CHECK32-NEXT:    ret
+;
+; CHECK64-LABEL: not_issubnormal_or_zero_or_qnan_d:
+; CHECK64:       # %bb.0:
+; CHECK64-NEXT:    fclass.d $fa0, $fa0
+; CHECK64-NEXT:    movfr2gr.d $a0, $fa0
+; CHECK64-NEXT:    and $a0, $a0, 205
+; CHECK64-NEXT:    sltu $a0, $zero, $a0
+; CHECK64-NEXT:    ret
+  %class = tail call i1 @llvm.is.fpclass.f64(double %x, i32 781)  ; ~(0x90|0x2) = ~"subnormal|qnan"
+  ret i1 %class
+}
+
+declare i1 @llvm.is.fpclass.f64(double, i32)

>From 57e04453862855bade087f4cdbe5f30525524cfc Mon Sep 17 00:00:00 2001
From: Matthias Springer <me at m-sp.org>
Date: Thu, 14 Sep 2023 09:45:22 +0200
Subject: [PATCH 35/86] [mlir][bufferization] Empty tensor elimination based on
 SubsetOpInterface (#65766)

This commit generalizes empty tensor elimination to operate on subset
ops. No new test cases are added because all current subset ops were
already supported previously. From this perspective, this change is NFC.

A new interface method (and a helper method) are added to
`SubsetInsertionOpInterface` to build the subset of the destination
tensor.
---
 .../IR/SubsetInsertionOpInterface.td          |  36 ++++
 .../TransformOps/BufferizationTransformOps.td |  20 +-
 .../Bufferization/Transforms/Passes.td        |  21 +-
 .../Bufferization/Transforms/Transforms.h     |  38 ++--
 .../BufferizationTransformOps.cpp             |   3 +-
 .../Transforms/EmptyTensorElimination.cpp     | 195 +++++-------------
 .../SubsetInsertionOpInterfaceImpl.cpp        |  49 +++++
 7 files changed, 180 insertions(+), 182 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/SubsetInsertionOpInterface.td b/mlir/include/mlir/Dialect/Bufferization/IR/SubsetInsertionOpInterface.td
index edf652537795771..aa09354bc753dba 100644
--- a/mlir/include/mlir/Dialect/Bufferization/IR/SubsetInsertionOpInterface.td
+++ b/mlir/include/mlir/Dialect/Bufferization/IR/SubsetInsertionOpInterface.td
@@ -99,6 +99,42 @@ def SubsetInsertionOpInterface : OpInterface<"SubsetInsertionOpInterface"> {
             "::mlir::Value":$candidate,
             "::llvm::function_ref<bool(Value, Value)>":$equivalenceFn)
       >,
+      InterfaceMethod<
+        /*desc=*/[{
+          Return the subset of the destination tensor that this operation
+          inserts into.
+
+          Example:
+          ```
+          // SubsetOpInterface op:
+          %0 = tensor.insert_slice %t0 into %t1[%pos][5][1]
+              : tensor<5xf32> into tensor<?xf32>
+          // Subset (built by this function):
+          %1 = tensor.extract_slice %t1[%pos][5][1]
+              : tensor<?xf32> to tensor<5xf32>
+          ```
+
+          Note: Implementations do not necessarily have to build new IR. They
+          may return existing SSA values.
+        }],
+        /*retType=*/"::mlir::Value",
+        /*methodName=*/"buildSubsetExtraction",
+        /*args=*/(ins "::mlir::OpBuilder &":$builder, "Location":$loc)
+      >,
+      InterfaceMethod<
+        /*desc=*/[{
+          Return all SSA values that are needed (i.e., must be in scope) at the
+          insertion of the builder when calling `buildSubsetExtraction`. Users
+          of `buildSubsetExtraction` can use this helper method to find a
+          suitable insertion point.
+
+          Example: The SSA values needed to build the subset in the example of
+          `buildSubsetExtraction` are %t1 and %pos.
+        }],
+        /*retType=*/"::llvm::SmallVector<::mlir::Value>",
+        /*methodName=*/"getValuesNeededToBuildSubsetExtraction",
+        /*args=*/(ins)
+      >,
   ];
 
   let extraClassDeclaration = [{
diff --git a/mlir/include/mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.td b/mlir/include/mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.td
index 46a95ad8db2a6db..84bd047e6d51eed 100644
--- a/mlir/include/mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.td
+++ b/mlir/include/mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.td
@@ -109,19 +109,17 @@ def EliminateEmptyTensorsOp
          DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
   let description = [{
     Try to eliminate all `tensor.empty` ops within the targeted op by replacing
-    them with a destination tensor.
+    them with another destination tensor.
 
-    `tensor.empty` ops cannot be bufferizes. They can either be converted to
-    `bufferization.alloc_tensor` or replaced with another tensor (via this
-    transform). `tensor.empty` does not specify the contents of the returned
+    "tensor.empty" ops cannot be bufferized. They can either be converted to
+    "bufferization.alloc_tensor" or replaced with another tensor (via this
+    transform). "tensor.empty" does not specify the contents of the returned
     tensor so their results can be replaced with arbitrary tensor values as long
     as the dimensions match.
 
-    This transform looks for `tensor.empty` ops where the SSA use-def chain of
-    the result ends in a supported "anchor op" (always following the aliasing
-    OpOperand/OpResult chain). Currently supported anchor ops are:
-    - `tensor.insert_slice`
-    - `bufferization.yield` (inside `bufferization.alloc_tensor`)
+    This transformation looks for subset ops that insert a tensor that
+    originates from a "tensor.empty" (as per the reverse use-def chain). Such
+    "tensor.empty" ops are replaced with the destination subset.
 
     Example:
 
@@ -138,6 +136,10 @@ def EliminateEmptyTensorsOp
     %2 = tensor.insert_slice %1 into %t[1][5][1]
     ```
 
+    In the above example, the subset op is "tensor.insert_slice". When tracing
+    back the reverse use-def chain of a the source, we end up at a
+    "tensor.empty" op.
+
     The above example can bufferize without an allocation (in the absence of
     other conflicts) because there is no longer a `tensor.empty` op.
 
diff --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
index df9bfcbfc548806..ff43cff817b64a8 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
@@ -402,11 +402,22 @@ def PromoteBuffersToStack : Pass<"promote-buffers-to-stack", "func::FuncOp"> {
 def EmptyTensorElimination : Pass<"eliminate-empty-tensors"> {
   let summary = "Try to eliminate all tensor.empty ops.";
   let description = [{
-    This pass tries to eliminate all insert_slice op-anchored tensor.empty ops.
-    I.e., when a value that is equivalent to an tensor.empty op is inserted into
-    another tensor, this pass tries to rewrite the IR in such a way that the
-    destination tensor of the insert_slice op is used directly instead of the
-    tensor.empty result.
+    Try to eliminate "tensor.empty" ops inside `op`. This transformation looks
+    for subset ops that insert a tensor that originates from a "tensor.empty"
+    (as per the reverse use-def chain). Such "tensor.empty" ops are replaced
+    with the destination subset.
+
+    E.g.:
+    ```
+    %0 = tensor.empty() : tensor<10xf32>
+    %1 = linalg.fill ... outs(%0 : tensor<10xf32>)
+    %2 = tensor.insert_slice %0 into %t ...
+    ```
+
+    In the above example, the subset op is "tensor.insert_slice". When tracing
+    back the reverse use-def chain of a the source, we end up at a
+    "tensor.empty" op. The "tensor.empty" op is replaced with a
+    "tensor.extract_slice" op.
   }];
   let constructor = "mlir::bufferization::createEmptyTensorEliminationPass()";
 }
diff --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Transforms.h b/mlir/include/mlir/Dialect/Bufferization/Transforms/Transforms.h
index a0cfc811a0b50a5..df866daf1ab1ff6 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Transforms.h
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Transforms.h
@@ -19,38 +19,26 @@ struct BufferizationStatistics;
 class OneShotAnalysisState;
 struct OneShotBufferizationOptions;
 
-/// A function that matches anchor OpOperands for tensor::EmptyOp elimination.
-/// If an OpOperand is matched, the function should populate the SmallVector
-/// with all values that are needed during `RewriteFn` to produce the
-/// replacement value.
-using AnchorMatchFn = std::function<bool(OpOperand &, SmallVector<Value> &)>;
-
-/// A function that rewrites matched anchors.
-using RewriteFn = std::function<Value(OpBuilder &, Location, OpOperand &)>;
-
-/// Try to eliminate tensor::EmptyOps inside `op`.
+/// Try to eliminate "tensor.empty" ops inside `op`. This transformation looks
+/// for subset ops that insert a tensor that originates from a "tensor.empty"
+/// (as per the reverse use-def chain). Such "tensor.empty" ops are replaced
+/// with the destination subset.
 ///
-/// * `rewriteFunc` generates the replacement for the tensor::EmptyOp.
-/// * Only tensor::EmptyOps that are anchored on a matching OpOperand as per
-///   `anchorMatchFunc` are considered. "Anchored" means that there is a path
-///   on the reverse SSA use-def chain, starting from the OpOperand and always
-///   following the aliasing  OpOperand, that eventually ends at a single
-///   tensor::EmptyOp.
+/// E.g.:
+/// %0 = tensor.empty() : tensor<10xf32>
+/// %1 = linalg.fill ... outs(%0 : tensor<10xf32>)
+/// %2 = tensor.insert_slice %0 into %t ...
+///
+/// In the above example, the subset op is "tensor.insert_slice". When tracing
+/// back the reverse use-def chain of a the source, we end up at a
+/// "tensor.empty" op.
 LogicalResult eliminateEmptyTensors(RewriterBase &rewriter, Operation *op,
-                                    OneShotAnalysisState &state,
-                                    AnchorMatchFn anchorMatchFunc,
-                                    RewriteFn rewriteFunc);
+                                    OneShotAnalysisState &state);
 
 /// Within the given operation, hoist buffers from loops where possible. See
 /// "BufferLoopHoistingPass" for more information.
 void hoistBuffersFromLoops(Operation *op);
 
-/// Try to eliminate tensor::EmptyOps inside `op` that are anchored on an
-/// InsertSliceOp, i.e., if it is eventually inserted into another tensor
-/// (and some other conditions are met).
-LogicalResult insertSliceAnchoredEmptyTensorEliminationStep(
-    RewriterBase &rewriter, Operation *op, OneShotAnalysisState &state);
-
 /// Resolve RaW and other conflicts by inserting bufferization.alloc_tensor ops.
 /// After applying this transform, the IR can be bufferized without inserting
 /// additional buffer allocations.
diff --git a/mlir/lib/Dialect/Bufferization/TransformOps/BufferizationTransformOps.cpp b/mlir/lib/Dialect/Bufferization/TransformOps/BufferizationTransformOps.cpp
index 097f75a7bc50f5b..b84cc452d0141cd 100644
--- a/mlir/lib/Dialect/Bufferization/TransformOps/BufferizationTransformOps.cpp
+++ b/mlir/lib/Dialect/Bufferization/TransformOps/BufferizationTransformOps.cpp
@@ -121,8 +121,7 @@ DiagnosedSilenceableFailure transform::EliminateEmptyTensorsOp::apply(
     if (failed(analyzeOp(target, state)))
       return mlir::emitSilenceableFailure(target->getLoc())
              << "failed to analyze op";
-    if (failed(bufferization::insertSliceAnchoredEmptyTensorEliminationStep(
-            rewriter, target, state)))
+    if (failed(bufferization::eliminateEmptyTensors(rewriter, target, state)))
       return mlir::emitSilenceableFailure(target->getLoc())
              << "failed to eliminate insert_slice anchored tensor.empty ops";
   }
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/EmptyTensorElimination.cpp b/mlir/lib/Dialect/Bufferization/Transforms/EmptyTensorElimination.cpp
index 4e0781dae0c2523..1662b52968d35b3 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/EmptyTensorElimination.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/EmptyTensorElimination.cpp
@@ -10,6 +10,7 @@
 
 #include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h"
 #include "mlir/Dialect/Bufferization/IR/Bufferization.h"
+#include "mlir/Dialect/Bufferization/IR/SubsetInsertionOpInterface.h"
 #include "mlir/Dialect/Bufferization/Transforms/OneShotAnalysis.h"
 #include "mlir/Dialect/Bufferization/Transforms/Transforms.h"
 #include "mlir/Dialect/Tensor/IR/Tensor.h"
@@ -99,154 +100,67 @@ findValidInsertionPoint(Operation *emptyTensorOp,
   return nullptr;
 }
 
-/// Try to eliminate tensor::EmptyOps inside `op`. A tensor::EmptyOp is replaced
-/// with the result of `rewriteFunc` if it is anchored on a matching
-/// OpOperand. "Anchored" means that there is a path on the reverse SSA use-def
-/// chain, starting from the OpOperand and always following the aliasing
-/// OpOperand, that eventually ends at the tensor::EmptyOp.
-///
-/// E.g.:
-/// %0 = tensor.empty() : tensor<10xf32>
-/// %1 = linalg.fill ... outs(%0 : tensor<10xf32>)
-/// %2 = tensor.insert_slice %0 into %t ...
-///
-/// In the above example, the anchor is the source operand of the insert_slice
-/// op. When tracing back the reverse use-def chain, we end up at a
-/// tensor.empty op.
 LogicalResult mlir::bufferization::eliminateEmptyTensors(
-    RewriterBase &rewriter, Operation *op, OneShotAnalysisState &state,
-    AnchorMatchFn anchorMatchFunc, RewriteFn rewriteFunc) {
+    RewriterBase &rewriter, Operation *op, OneShotAnalysisState &state) {
   OpBuilder::InsertionGuard g(rewriter);
 
-  op->walk([&](Operation *op) {
-    for (OpOperand &operand : op->getOpOperands()) {
-      // Skip operands that do not bufferize inplace.
-      if (!state.isInPlace(operand))
-        continue;
-      // All values that are needed to create the replacement op.
-      SmallVector<Value> neededValues;
-      // Is this an anchor?
-      if (!anchorMatchFunc(operand, neededValues))
+  op->walk([&](SubsetInsertionOpInterface op) {
+    OpOperand &source = op.getSourceOperand();
+    // Skip operands that do not bufferize inplace. "tensor.empty" could still
+    // be replaced, but the transformation may not be beneficial.
+    if (!state.isInPlace(source))
+      return WalkResult::skip();
+    // All values that are needed to create the replacement op.
+    SmallVector<Value> neededValues =
+        op.getValuesNeededToBuildSubsetExtraction();
+
+    // Find tensor.empty ops on the reverse SSA use-def chain. Only follow
+    // equivalent tensors. I.e., stop when there are ops such as extract_slice
+    // on the path.
+    TraversalConfig config;
+    config.followEquivalentOnly = true;
+    config.alwaysIncludeLeaves = false;
+    // Replace only if the types match or are static <-> dynamic casts. We do
+    // not support slices or reshapes.
+    // TODO: This could be extended to support IR such as:
+    // %0 = tensor.empty() : tensor<128xf32>
+    // %1 = "some_op"(%0) : (tensor<128xf32>) -> (tensor<128xf32>)
+    // %2 = tensor.expand_shape %1 ...
+    // %3 = tensor.insert_slice %2 into ...
+    config.followSameTypeOrCastsOnly = true;
+    SetVector<Value> emptyTensors = state.findValueInReverseUseDefChain(
+        source.get(), /*condition=*/
+        [&](Value val) { return val.getDefiningOp<tensor::EmptyOp>(); },
+        config);
+
+    for (Value v : emptyTensors) {
+      Operation *emptyTensorOp = v.getDefiningOp();
+
+      // Find a suitable insertion point. If no suitable insertion point for
+      // the replacement can be found, skip this replacement.
+      Operation *insertionPoint =
+          findValidInsertionPoint(emptyTensorOp, neededValues);
+      if (!insertionPoint)
         continue;
 
-      // Find tensor.empty ops on the reverse SSA use-def chain. Only follow
-      // equivalent tensors. I.e., stop when there are ops such as extract_slice
-      // on the path.
-      TraversalConfig config;
-      config.followEquivalentOnly = true;
-      config.alwaysIncludeLeaves = false;
-      // Replace only if the types match or are static <-> dynamic casts. We do
-      // not support slices or reshapes.
-      // TODO: This could be extended to support IR such as:
-      // %0 = tensor.empty() : tensor<128xf32>
-      // %1 = "some_op"(%0) : (tensor<128xf32>) -> (tensor<128xf32>)
-      // %2 = tensor.expand_shape %1 ...
-      // %3 = tensor.insert_slice %2 into ...
-      config.followSameTypeOrCastsOnly = true;
-      SetVector<Value> emptyTensors = state.findValueInReverseUseDefChain(
-          operand.get(), /*condition=*/
-          [&](Value val) { return val.getDefiningOp<tensor::EmptyOp>(); },
-          config);
-
-      for (Value v : emptyTensors) {
-        Operation *emptyTensorOp = v.getDefiningOp();
-
-        // Find a suitable insertion point. If no suitable insertion point for
-        // the replacement can be found, skip this replacement.
-        Operation *insertionPoint =
-            findValidInsertionPoint(emptyTensorOp, neededValues);
-        if (!insertionPoint)
-          continue;
-
-        rewriter.setInsertionPoint(insertionPoint);
-        Value replacement =
-            rewriteFunc(rewriter, emptyTensorOp->getLoc(), operand);
-        if (!replacement)
-          continue;
-        if (replacement.getType() != v.getType()) {
-          rewriter.setInsertionPointAfterValue(replacement);
-          replacement = rewriter.create<tensor::CastOp>(v.getLoc(), v.getType(),
-                                                        replacement);
-        }
-        // Replace the tensor::EmptyOp.
-        rewriter.replaceOp(emptyTensorOp, replacement);
-        state.resetCache();
+      rewriter.setInsertionPoint(insertionPoint);
+      Value replacement =
+          op.buildSubsetExtraction(rewriter, emptyTensorOp->getLoc());
+      if (!replacement)
+        continue;
+      if (replacement.getType() != v.getType()) {
+        rewriter.setInsertionPointAfterValue(replacement);
+        replacement = rewriter.create<tensor::CastOp>(v.getLoc(), v.getType(),
+                                                      replacement);
       }
+      // Replace the tensor::EmptyOp.
+      rewriter.replaceOp(emptyTensorOp, replacement);
+      state.resetCache();
     }
-  });
-
-  return success();
-}
-
-/// Try to eliminate tensor::EmptyOps inside `op`. An tensor::EmptyOp can be
-/// eliminated if it is eventually inserted into another tensor (and some other
-/// conditions are met).
-///
-/// E.g.:
-/// %0 = tensor.empty()
-/// %1 = linalg.fill(%cst, %0) {inplace = [true]}
-/// %2 = tensor.insert_slice %1 into %t[10][20][1]
-///
-/// tensor::EmptyOp elimination will try to fill %t inplace instead of filling a
-/// new allocation %0 and inserting it into %t. This is done by replacing the
-/// tensor::EmptyOp with:
-///
-/// %0 = tensor.extract_slice %t[10][20][1]
-///
-/// The analysis looks for matching ExtractSliceOp/InsertSliceOp pairs and lets
-/// those bufferize inplace in the absence of other conflicts.
-///
-/// Starting from an InsertSliceOp, an tensor::EmptyOp at the end of the insert
-/// source's reverse use-def chain is eliminated if:
-/// * On the reverse use-def chain path from the InsertSliceOp to the
-///   tensor::EmptyOp, all ops were decided to bufferize inplace and the buffer
-///   relation is "equivalent" (TODO: can be relaxed if needed).
-/// * The reverse use-def chain has exactly one end, which is the
-///   tensor::EmptyOp.
-template <typename OpTy>
-static LogicalResult insertSliceLikeAnchoredEmptyTensorEliminationStep(
-    RewriterBase &rewriter, Operation *op, OneShotAnalysisState &state) {
-  return eliminateEmptyTensors(
-      rewriter, op, state,
-      /*anchorMatchFunc=*/
-      [&](OpOperand &operand, SmallVector<Value> &neededValues) {
-        auto insertSliceOp = dyn_cast<OpTy>(operand.getOwner());
-        if (!insertSliceOp)
-          return false;
-        if (&operand != &insertSliceOp->getOpOperand(0) /*source*/)
-          return false;
 
-        // Collect all values that are needed to construct the replacement op.
-        neededValues.append(insertSliceOp.getOffsets().begin(),
-                            insertSliceOp.getOffsets().end());
-        neededValues.append(insertSliceOp.getSizes().begin(),
-                            insertSliceOp.getSizes().end());
-        neededValues.append(insertSliceOp.getStrides().begin(),
-                            insertSliceOp.getStrides().end());
-        neededValues.push_back(insertSliceOp.getDest());
-
-        return true;
-      },
-      /*rewriteFunc=*/
-      [](OpBuilder &b, Location loc, OpOperand &operand) {
-        auto insertOp = cast<OpTy>(operand.getOwner());
-        auto extractOp = b.create<tensor::ExtractSliceOp>(
-            loc, insertOp.getSourceType(), insertOp.getDest(),
-            insertOp.getMixedOffsets(), insertOp.getMixedSizes(),
-            insertOp.getMixedStrides());
-        return extractOp.getResult();
-      });
-}
+    return WalkResult::advance();
+  });
 
-LogicalResult
-mlir::bufferization::insertSliceAnchoredEmptyTensorEliminationStep(
-    RewriterBase &rewriter, Operation *op, OneShotAnalysisState &state) {
-  if (failed(insertSliceLikeAnchoredEmptyTensorEliminationStep<
-             tensor::InsertSliceOp>(rewriter, op, state)))
-    return failure();
-  if (failed(insertSliceLikeAnchoredEmptyTensorEliminationStep<
-             tensor::ParallelInsertSliceOp>(rewriter, op, state)))
-    return failure();
   return success();
 }
 
@@ -276,8 +190,7 @@ void EmptyTensorElimination::runOnOperation() {
   }
 
   IRRewriter rewriter(op->getContext());
-  if (failed(bufferization::insertSliceAnchoredEmptyTensorEliminationStep(
-          rewriter, op, state)))
+  if (failed(bufferization::eliminateEmptyTensors(rewriter, op, state)))
     signalPassFailure();
 }
 
diff --git a/mlir/lib/Dialect/Tensor/Transforms/SubsetInsertionOpInterfaceImpl.cpp b/mlir/lib/Dialect/Tensor/Transforms/SubsetInsertionOpInterfaceImpl.cpp
index 1156f2501a96ee1..dff9f64169d495d 100644
--- a/mlir/lib/Dialect/Tensor/Transforms/SubsetInsertionOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/Tensor/Transforms/SubsetInsertionOpInterfaceImpl.cpp
@@ -34,6 +34,31 @@ bool isSubsetEquivalentToInsertSliceLikeOp(
                                     isEqualConstantIntOrValue);
 }
 
+template <typename OpTy>
+Value buildSubsetExtractionOfInsertSliceLikeOp(OpBuilder &b, Location loc,
+                                               OpTy insertSliceOp) {
+  auto extractOp = b.create<tensor::ExtractSliceOp>(
+      loc, insertSliceOp.getSourceType(), insertSliceOp.getDest(),
+      insertSliceOp.getMixedOffsets(), insertSliceOp.getMixedSizes(),
+      insertSliceOp.getMixedStrides());
+  return extractOp.getResult();
+}
+
+template <typename OpTy>
+SmallVector<Value>
+getValuesNeededToBuildSubsetExtractionOfInsertSliceLikeOp(OpTy insertSliceOp) {
+  SmallVector<Value> neededValues;
+  // Collect all values that are needed to construct the replacement op.
+  neededValues.append(insertSliceOp.getOffsets().begin(),
+                      insertSliceOp.getOffsets().end());
+  neededValues.append(insertSliceOp.getSizes().begin(),
+                      insertSliceOp.getSizes().end());
+  neededValues.append(insertSliceOp.getStrides().begin(),
+                      insertSliceOp.getStrides().end());
+  neededValues.push_back(insertSliceOp.getDest());
+  return neededValues;
+}
+
 struct InsertSliceOpInterface
     : public SubsetInsertionOpInterface::ExternalModel<InsertSliceOpInterface,
                                                        tensor::InsertSliceOp> {
@@ -48,6 +73,18 @@ struct InsertSliceOpInterface
     return isSubsetEquivalentToInsertSliceLikeOp(insertSliceOp, candidate,
                                                  equivalenceFn);
   }
+
+  Value buildSubsetExtraction(Operation *op, OpBuilder &builder,
+                              Location loc) const {
+    return buildSubsetExtractionOfInsertSliceLikeOp(
+        builder, loc, cast<tensor::InsertSliceOp>(op));
+  }
+
+  SmallVector<Value>
+  getValuesNeededToBuildSubsetExtraction(Operation *op) const {
+    return getValuesNeededToBuildSubsetExtractionOfInsertSliceLikeOp(
+        cast<tensor::InsertSliceOp>(op));
+  }
 };
 
 struct ParallelInsertSliceOpInterface
@@ -68,6 +105,18 @@ struct ParallelInsertSliceOpInterface
     return isSubsetEquivalentToInsertSliceLikeOp(insertSliceOp, candidate,
                                                  equivalenceFn);
   }
+
+  Value buildSubsetExtraction(Operation *op, OpBuilder &builder,
+                              Location loc) const {
+    return buildSubsetExtractionOfInsertSliceLikeOp(
+        builder, loc, cast<tensor::ParallelInsertSliceOp>(op));
+  }
+
+  SmallVector<Value>
+  getValuesNeededToBuildSubsetExtraction(Operation *op) const {
+    return getValuesNeededToBuildSubsetExtractionOfInsertSliceLikeOp(
+        cast<tensor::ParallelInsertSliceOp>(op));
+  }
 };
 
 } // namespace

>From 9caf65c43813d6af8f44bcd33bae8bdf91003d45 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Thu, 14 Sep 2023 08:54:02 +0100
Subject: [PATCH 36/86] [lldb] Format Python files in scripts and utils
 (#66053)

Using:
black --exclude "third_party/" ./lldb/
---
 lldb/scripts/analyze-project-deps.py  |  66 +++--
 lldb/scripts/android/host_art_bt.py   | 229 ++++++++++------
 lldb/scripts/install_custom_python.py | 146 +++++-----
 lldb/scripts/reproducer-replay.py     |  98 +++----
 lldb/scripts/use_lldb_suite.py        |   4 +-
 lldb/scripts/verify_api.py            |  99 ++++---
 lldb/utils/lldb-repro/lldb-repro.py   |  30 ++-
 lldb/utils/lui/breakwin.py            |  14 +-
 lldb/utils/lui/commandwin.py          |  35 ++-
 lldb/utils/lui/cui.py                 |  55 ++--
 lldb/utils/lui/debuggerdriver.py      |  76 +++---
 lldb/utils/lui/eventwin.py            |   3 +-
 lldb/utils/lui/lldbutil.py            | 372 ++++++++++++++------------
 lldb/utils/lui/lui.py                 |  54 ++--
 lldb/utils/lui/sandbox.py             |  12 +-
 lldb/utils/lui/sourcewin.py           |  62 +++--
 lldb/utils/lui/statuswin.py           |  12 +-
 17 files changed, 754 insertions(+), 613 deletions(-)

diff --git a/lldb/scripts/analyze-project-deps.py b/lldb/scripts/analyze-project-deps.py
index 89da3dc9df7b3c6..4724367e2e722d0 100755
--- a/lldb/scripts/analyze-project-deps.py
+++ b/lldb/scripts/analyze-project-deps.py
@@ -10,12 +10,21 @@
 from use_lldb_suite import lldb_root
 
 parser = argparse.ArgumentParser(
-    description='Analyze LLDB project #include dependencies.')
-parser.add_argument('--show-counts', default=False, action='store_true', 
-    help='When true, show the number of dependencies from each subproject')
-parser.add_argument('--discover-cycles', default=False, action='store_true',
-    help='When true, find and display all project dependency cycles.  Note,'
-         'this option is very slow')
+    description="Analyze LLDB project #include dependencies."
+)
+parser.add_argument(
+    "--show-counts",
+    default=False,
+    action="store_true",
+    help="When true, show the number of dependencies from each subproject",
+)
+parser.add_argument(
+    "--discover-cycles",
+    default=False,
+    action="store_true",
+    help="When true, find and display all project dependency cycles.  Note,"
+    "this option is very slow",
+)
 
 args = parser.parse_args()
 
@@ -24,12 +33,14 @@
 
 src_map = {}
 
-include_regex = re.compile('#include \"((lldb|Plugins|clang)(.*/)+).*\"')
+include_regex = re.compile('#include "((lldb|Plugins|clang)(.*/)+).*"')
+
 
 def is_sublist(small, big):
     it = iter(big)
     return all(c in it for c in small)
 
+
 def normalize_host(str):
     if str.startswith("lldb/Host"):
         return "lldb/Host"
@@ -39,6 +50,7 @@ def normalize_host(str):
         return str.replace("lldb/../../source", "lldb")
     return str
 
+
 def scan_deps(this_dir, file):
     global src_map
     deps = {}
@@ -62,7 +74,8 @@ def scan_deps(this_dir, file):
     if this_dir not in src_map and len(deps) > 0:
         src_map[this_dir] = deps
 
-for (base, dirs, files) in os.walk(inc_dir):
+
+for base, dirs, files in os.walk(inc_dir):
     dir = os.path.basename(base)
     relative = os.path.relpath(base, inc_dir)
     inc_files = [x for x in files if os.path.splitext(x)[1] in [".h"]]
@@ -71,7 +84,7 @@ def scan_deps(this_dir, file):
         inc_path = os.path.join(base, inc)
         scan_deps(relative, inc_path)
 
-for (base, dirs, files) in os.walk(src_dir):
+for base, dirs, files in os.walk(src_dir):
     dir = os.path.basename(base)
     relative = os.path.relpath(base, src_dir)
     src_files = [x for x in files if os.path.splitext(x)[1] in [".cpp", ".h", ".mm"]]
@@ -82,6 +95,7 @@ def scan_deps(this_dir, file):
         scan_deps(norm_base_path, src_path)
     pass
 
+
 def is_existing_cycle(path, cycles):
     # If we have a cycle like # A -> B -> C (with an implicit -> A at the end)
     # then we don't just want to check for an occurrence of A -> B -> C in the
@@ -90,12 +104,13 @@ def is_existing_cycle(path, cycles):
     # at the end), then A -> B -> C is also a cycle.  This is an important
     # optimization which reduces the search space by multiple orders of
     # magnitude.
-    for i in range(0,len(path)):
+    for i in range(0, len(path)):
         if any(is_sublist(x, path) for x in cycles):
             return True
         path = [path[-1]] + path[0:-1]
     return False
 
+
 def expand(path_queue, path_lengths, cycles, src_map):
     # We do a breadth first search, to make sure we visit all paths in order
     # of ascending length.  This is an important optimization to make sure that
@@ -127,54 +142,57 @@ def expand(path_queue, path_lengths, cycles, src_map):
             path_queue.append(cur_path + [item])
     pass
 
+
 cycles = []
 
 path_queue = [[x] for x in iter(src_map)]
 path_lens = [1] * len(path_queue)
 
 items = list(src_map.items())
-items.sort(key = lambda A : A[0])
+items.sort(key=lambda A: A[0])
 
-for (path, deps) in items:
+for path, deps in items:
     print(path + ":")
     sorted_deps = list(deps.items())
     if args.show_counts:
-        sorted_deps.sort(key = lambda A: (A[1], A[0]))
+        sorted_deps.sort(key=lambda A: (A[1], A[0]))
         for dep in sorted_deps:
             print("\t{} [{}]".format(dep[0], dep[1]))
     else:
-        sorted_deps.sort(key = lambda A: A[0])
+        sorted_deps.sort(key=lambda A: A[0])
         for dep in sorted_deps:
             print("\t{}".format(dep[0]))
 
+
 def iter_cycles(cycles):
     global src_map
     for cycle in cycles:
         cycle.append(cycle[0])
         zipper = list(zip(cycle[0:-1], cycle[1:]))
-        result = [(x, src_map[x][y], y) for (x,y) in zipper]
+        result = [(x, src_map[x][y], y) for (x, y) in zipper]
         total = 0
         smallest = result[0][1]
-        for (first, value, last) in result:
+        for first, value, last in result:
             total += value
             smallest = min(smallest, value)
         yield (total, smallest, result)
 
+
 if args.discover_cycles:
     print("Analyzing cycles...")
 
     expand(path_queue, path_lens, cycles, src_map)
 
-    average = sum([len(x)+1 for x in cycles]) / len(cycles)
+    average = sum([len(x) + 1 for x in cycles]) / len(cycles)
 
     print("Found {} cycles.  Average cycle length = {}.".format(len(cycles), average))
     counted = list(iter_cycles(cycles))
     if args.show_counts:
-        counted.sort(key = lambda A: A[0])
-        for (total, smallest, cycle) in counted:
+        counted.sort(key=lambda A: A[0])
+        for total, smallest, cycle in counted:
             sys.stdout.write("{} deps to break: ".format(total))
             sys.stdout.write(cycle[0][0])
-            for (first, count, last) in cycle:
+            for first, count, last in cycle:
                 sys.stdout.write(" [{}->] {}".format(count, last))
             sys.stdout.write("\n")
     else:
@@ -186,8 +204,8 @@ def iter_cycles(cycles):
     islands = []
     outgoing_counts = defaultdict(int)
     incoming_counts = defaultdict(int)
-    for (total, smallest, cycle) in counted:
-        for (first, count, last) in cycle:
+    for total, smallest, cycle in counted:
+        for first, count, last in cycle:
             outgoing_counts[first] += count
             incoming_counts[last] += count
     for cycle in cycles:
@@ -201,8 +219,8 @@ def iter_cycles(cycles):
         sorted = []
         for node in island:
             sorted.append((node, incoming_counts[node], outgoing_counts[node]))
-        sorted.sort(key = lambda x: x[1]+x[2])
-        for (node, inc, outg) in sorted:
+        sorted.sort(key=lambda x: x[1] + x[2])
+        for node, inc, outg in sorted:
             print("  {} [{} in, {} out]".format(node, inc, outg))
     sys.stdout.flush()
 pass
diff --git a/lldb/scripts/android/host_art_bt.py b/lldb/scripts/android/host_art_bt.py
index 03797074aafdddd..d4c5af46d9e2f8e 100644
--- a/lldb/scripts/android/host_art_bt.py
+++ b/lldb/scripts/android/host_art_bt.py
@@ -20,45 +20,59 @@ def host_art_bt(debugger, command, result, internal_dict):
     thread = process.GetSelectedThread()
     while lldb_frame_index < thread.GetNumFrames():
         frame = thread.GetFrameAtIndex(lldb_frame_index)
-        if frame.GetModule() and re.match(r'JIT\(.*?\)',
-                                          frame.GetModule().GetFileSpec().GetFilename()):
+        if frame.GetModule() and re.match(
+            r"JIT\(.*?\)", frame.GetModule().GetFileSpec().GetFilename()
+        ):
             # Compiled Java frame
 
             # Get function/filename/lineno from symbol context
             symbol = frame.GetSymbol()
             if not symbol:
-                print('No symbol info for compiled Java frame: ', frame)
+                print("No symbol info for compiled Java frame: ", frame)
                 sys.exit(1)
             line_entry = frame.GetLineEntry()
-            prettified_frames.append({
-                'function': symbol.GetName(),
-                'file': str(line_entry.GetFileSpec()) if line_entry else None,
-                'line': line_entry.GetLine() if line_entry else -1
-            })
+            prettified_frames.append(
+                {
+                    "function": symbol.GetName(),
+                    "file": str(line_entry.GetFileSpec()) if line_entry else None,
+                    "line": line_entry.GetLine() if line_entry else -1,
+                }
+            )
 
             # Skip art frames
             while True:
                 art_stack_visitor = frame.EvaluateExpression(
-                    """struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor(""" +
-                    str(art_frame_index) +
-                    """); visitor.WalkStack(true); visitor""")
+                    """struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor("""
+                    + str(art_frame_index)
+                    + """); visitor.WalkStack(true); visitor"""
+                )
                 art_method = frame.EvaluateExpression(
-                    art_stack_visitor.GetName() + """.GetMethod()""")
+                    art_stack_visitor.GetName() + """.GetMethod()"""
+                )
                 if art_method.GetValueAsUnsigned() != 0:
                     art_method_name = frame.EvaluateExpression(
-                        """art::PrettyMethod(""" + art_method.GetName() + """, true)""")
+                        """art::PrettyMethod(""" + art_method.GetName() + """, true)"""
+                    )
                     art_method_name_data = frame.EvaluateExpression(
-                        art_method_name.GetName() + """.c_str()""").GetValueAsUnsigned()
+                        art_method_name.GetName() + """.c_str()"""
+                    ).GetValueAsUnsigned()
                     art_method_name_size = frame.EvaluateExpression(
-                        art_method_name.GetName() + """.length()""").GetValueAsUnsigned()
+                        art_method_name.GetName() + """.length()"""
+                    ).GetValueAsUnsigned()
                     error = lldb.SBError()
                     art_method_name = process.ReadCStringFromMemory(
-                        art_method_name_data, art_method_name_size + 1, error)
+                        art_method_name_data, art_method_name_size + 1, error
+                    )
                     if not error.Success:
-                        print('Failed to read method name')
+                        print("Failed to read method name")
                         sys.exit(1)
                     if art_method_name != symbol.GetName():
-                        print('Function names in native symbol and art runtime stack do not match: ', symbol.GetName(), ' != ', art_method_name)
+                        print(
+                            "Function names in native symbol and art runtime stack do not match: ",
+                            symbol.GetName(),
+                            " != ",
+                            art_method_name,
+                        )
                     art_frame_index = art_frame_index + 1
                     break
                 art_frame_index = art_frame_index + 1
@@ -68,53 +82,69 @@ def host_art_bt(debugger, command, result, internal_dict):
             if lldb_frame_index < thread.GetNumFrames():
                 frame = thread.GetFrameAtIndex(lldb_frame_index)
                 if frame.GetModule() and re.match(
-                        r'JIT\(.*?\)', frame.GetModule().GetFileSpec().GetFilename()):
+                    r"JIT\(.*?\)", frame.GetModule().GetFileSpec().GetFilename()
+                ):
                     # Another compile Java frame
                     # Don't skip; leave it to the next iteration
                     continue
-                elif frame.GetSymbol() and (frame.GetSymbol().GetName() == 'art_quick_invoke_stub' or frame.GetSymbol().GetName() == 'art_quick_invoke_static_stub'):
+                elif frame.GetSymbol() and (
+                    frame.GetSymbol().GetName() == "art_quick_invoke_stub"
+                    or frame.GetSymbol().GetName() == "art_quick_invoke_static_stub"
+                ):
                     # art_quick_invoke_stub / art_quick_invoke_static_stub
                     # Skip until we get past the next ArtMethod::Invoke()
                     while True:
                         lldb_frame_index = lldb_frame_index + 1
                         if lldb_frame_index >= thread.GetNumFrames():
-                            print('ArtMethod::Invoke not found below art_quick_invoke_stub/art_quick_invoke_static_stub')
+                            print(
+                                "ArtMethod::Invoke not found below art_quick_invoke_stub/art_quick_invoke_static_stub"
+                            )
                             sys.exit(1)
                         frame = thread.GetFrameAtIndex(lldb_frame_index)
-                        if frame.GetSymbol() and frame.GetSymbol().GetName(
-                        ) == 'art::mirror::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)':
+                        if (
+                            frame.GetSymbol()
+                            and frame.GetSymbol().GetName()
+                            == "art::mirror::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)"
+                        ):
                             lldb_frame_index = lldb_frame_index + 1
                             break
                 else:
-                    print('Invalid frame below compiled Java frame: ', frame)
-        elif frame.GetSymbol() and frame.GetSymbol().GetName() == 'art_quick_generic_jni_trampoline':
+                    print("Invalid frame below compiled Java frame: ", frame)
+        elif (
+            frame.GetSymbol()
+            and frame.GetSymbol().GetName() == "art_quick_generic_jni_trampoline"
+        ):
             # Interpreted JNI frame for x86_64
 
             # Skip art frames
             while True:
                 art_stack_visitor = frame.EvaluateExpression(
-                    """struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor(""" +
-                    str(art_frame_index) +
-                    """); visitor.WalkStack(true); visitor""")
+                    """struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor("""
+                    + str(art_frame_index)
+                    + """); visitor.WalkStack(true); visitor"""
+                )
                 art_method = frame.EvaluateExpression(
-                    art_stack_visitor.GetName() + """.GetMethod()""")
+                    art_stack_visitor.GetName() + """.GetMethod()"""
+                )
                 if art_method.GetValueAsUnsigned() != 0:
                     # Get function/filename/lineno from ART runtime
                     art_method_name = frame.EvaluateExpression(
-                        """art::PrettyMethod(""" + art_method.GetName() + """, true)""")
+                        """art::PrettyMethod(""" + art_method.GetName() + """, true)"""
+                    )
                     art_method_name_data = frame.EvaluateExpression(
-                        art_method_name.GetName() + """.c_str()""").GetValueAsUnsigned()
+                        art_method_name.GetName() + """.c_str()"""
+                    ).GetValueAsUnsigned()
                     art_method_name_size = frame.EvaluateExpression(
-                        art_method_name.GetName() + """.length()""").GetValueAsUnsigned()
+                        art_method_name.GetName() + """.length()"""
+                    ).GetValueAsUnsigned()
                     error = lldb.SBError()
                     function = process.ReadCStringFromMemory(
-                        art_method_name_data, art_method_name_size + 1, error)
+                        art_method_name_data, art_method_name_size + 1, error
+                    )
 
-                    prettified_frames.append({
-                        'function': function,
-                        'file': None,
-                        'line': -1
-                    })
+                    prettified_frames.append(
+                        {"function": function, "file": None, "line": -1}
+                    )
 
                     art_frame_index = art_frame_index + 1
                     break
@@ -124,78 +154,98 @@ def host_art_bt(debugger, command, result, internal_dict):
             lldb_frame_index = lldb_frame_index + 1
             if lldb_frame_index < thread.GetNumFrames():
                 frame = thread.GetFrameAtIndex(lldb_frame_index)
-                if frame.GetSymbol() and (frame.GetSymbol().GetName() ==
-                                          'art_quick_invoke_stub' or frame.GetSymbol().GetName() == 'art_quick_invoke_static_stub'):
+                if frame.GetSymbol() and (
+                    frame.GetSymbol().GetName() == "art_quick_invoke_stub"
+                    or frame.GetSymbol().GetName() == "art_quick_invoke_static_stub"
+                ):
                     # art_quick_invoke_stub / art_quick_invoke_static_stub
                     # Skip until we get past the next ArtMethod::Invoke()
                     while True:
                         lldb_frame_index = lldb_frame_index + 1
                         if lldb_frame_index >= thread.GetNumFrames():
-                            print('ArtMethod::Invoke not found below art_quick_invoke_stub/art_quick_invoke_static_stub')
+                            print(
+                                "ArtMethod::Invoke not found below art_quick_invoke_stub/art_quick_invoke_static_stub"
+                            )
                             sys.exit(1)
                         frame = thread.GetFrameAtIndex(lldb_frame_index)
-                        if frame.GetSymbol() and frame.GetSymbol().GetName(
-                        ) == 'art::mirror::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)':
+                        if (
+                            frame.GetSymbol()
+                            and frame.GetSymbol().GetName()
+                            == "art::mirror::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)"
+                        ):
                             lldb_frame_index = lldb_frame_index + 1
                             break
                 else:
-                    print('Invalid frame below compiled Java frame: ', frame)
-        elif frame.GetSymbol() and re.search(r'art::interpreter::', frame.GetSymbol().GetName()):
+                    print("Invalid frame below compiled Java frame: ", frame)
+        elif frame.GetSymbol() and re.search(
+            r"art::interpreter::", frame.GetSymbol().GetName()
+        ):
             # Interpreted Java frame
 
             while True:
                 lldb_frame_index = lldb_frame_index + 1
                 if lldb_frame_index >= thread.GetNumFrames():
-                    print('art::interpreter::Execute not found in interpreter frame')
+                    print("art::interpreter::Execute not found in interpreter frame")
                     sys.exit(1)
                 frame = thread.GetFrameAtIndex(lldb_frame_index)
-                if frame.GetSymbol() and frame.GetSymbol().GetName(
-                ) == 'art::interpreter::Execute(art::Thread*, art::MethodHelper&, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)':
+                if (
+                    frame.GetSymbol()
+                    and frame.GetSymbol().GetName()
+                    == "art::interpreter::Execute(art::Thread*, art::MethodHelper&, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)"
+                ):
                     break
 
             # Skip art frames
             while True:
                 art_stack_visitor = frame.EvaluateExpression(
-                    """struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor(""" +
-                    str(art_frame_index) +
-                    """); visitor.WalkStack(true); visitor""")
+                    """struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor("""
+                    + str(art_frame_index)
+                    + """); visitor.WalkStack(true); visitor"""
+                )
                 art_method = frame.EvaluateExpression(
-                    art_stack_visitor.GetName() + """.GetMethod()""")
+                    art_stack_visitor.GetName() + """.GetMethod()"""
+                )
                 if art_method.GetValueAsUnsigned() != 0:
                     # Get function/filename/lineno from ART runtime
                     art_method_name = frame.EvaluateExpression(
-                        """art::PrettyMethod(""" + art_method.GetName() + """, true)""")
+                        """art::PrettyMethod(""" + art_method.GetName() + """, true)"""
+                    )
                     art_method_name_data = frame.EvaluateExpression(
-                        art_method_name.GetName() + """.c_str()""").GetValueAsUnsigned()
+                        art_method_name.GetName() + """.c_str()"""
+                    ).GetValueAsUnsigned()
                     art_method_name_size = frame.EvaluateExpression(
-                        art_method_name.GetName() + """.length()""").GetValueAsUnsigned()
+                        art_method_name.GetName() + """.length()"""
+                    ).GetValueAsUnsigned()
                     error = lldb.SBError()
                     function = process.ReadCStringFromMemory(
-                        art_method_name_data, art_method_name_size + 1, error)
+                        art_method_name_data, art_method_name_size + 1, error
+                    )
 
                     line = frame.EvaluateExpression(
-                        art_stack_visitor.GetName() +
-                        """.GetMethod()->GetLineNumFromDexPC(""" +
-                        art_stack_visitor.GetName() +
-                        """.GetDexPc(true))""").GetValueAsUnsigned()
+                        art_stack_visitor.GetName()
+                        + """.GetMethod()->GetLineNumFromDexPC("""
+                        + art_stack_visitor.GetName()
+                        + """.GetDexPc(true))"""
+                    ).GetValueAsUnsigned()
 
                     file_name = frame.EvaluateExpression(
-                        art_method.GetName() + """->GetDeclaringClassSourceFile()""")
+                        art_method.GetName() + """->GetDeclaringClassSourceFile()"""
+                    )
                     file_name_data = file_name.GetValueAsUnsigned()
                     file_name_size = frame.EvaluateExpression(
-                        """(size_t)strlen(""" + file_name.GetName() + """)""").GetValueAsUnsigned()
+                        """(size_t)strlen(""" + file_name.GetName() + """)"""
+                    ).GetValueAsUnsigned()
                     error = lldb.SBError()
                     file_name = process.ReadCStringFromMemory(
-                        file_name_data, file_name_size + 1, error)
+                        file_name_data, file_name_size + 1, error
+                    )
                     if not error.Success():
-                        print('Failed to read source file name')
+                        print("Failed to read source file name")
                         sys.exit(1)
 
-                    prettified_frames.append({
-                        'function': function,
-                        'file': file_name,
-                        'line': line
-                    })
+                    prettified_frames.append(
+                        {"function": function, "file": file_name, "line": line}
+                    )
 
                     art_frame_index = art_frame_index + 1
                     break
@@ -205,11 +255,12 @@ def host_art_bt(debugger, command, result, internal_dict):
             while True:
                 lldb_frame_index = lldb_frame_index + 1
                 if lldb_frame_index >= thread.GetNumFrames():
-                    print('Can not get past interpreter native frames')
+                    print("Can not get past interpreter native frames")
                     sys.exit(1)
                 frame = thread.GetFrameAtIndex(lldb_frame_index)
                 if frame.GetSymbol() and not re.search(
-                        r'art::interpreter::', frame.GetSymbol().GetName()):
+                    r"art::interpreter::", frame.GetSymbol().GetName()
+                ):
                     break
         else:
             # Other frames. Add them as-is.
@@ -218,20 +269,32 @@ def host_art_bt(debugger, command, result, internal_dict):
             if frame.GetModule():
                 module_name = frame.GetModule().GetFileSpec().GetFilename()
                 if not module_name in [
-                    'libartd.so',
-                    'dalvikvm32',
-                    'dalvikvm64',
-                        'libc.so.6']:
-                    prettified_frames.append({
-                        'function': frame.GetSymbol().GetName() if frame.GetSymbol() else None,
-                        'file': str(frame.GetLineEntry().GetFileSpec()) if frame.GetLineEntry() else None,
-                        'line': frame.GetLineEntry().GetLine() if frame.GetLineEntry() else -1
-                    })
+                    "libartd.so",
+                    "dalvikvm32",
+                    "dalvikvm64",
+                    "libc.so.6",
+                ]:
+                    prettified_frames.append(
+                        {
+                            "function": frame.GetSymbol().GetName()
+                            if frame.GetSymbol()
+                            else None,
+                            "file": str(frame.GetLineEntry().GetFileSpec())
+                            if frame.GetLineEntry()
+                            else None,
+                            "line": frame.GetLineEntry().GetLine()
+                            if frame.GetLineEntry()
+                            else -1,
+                        }
+                    )
 
     for prettified_frame in prettified_frames:
-        print(prettified_frame['function'], prettified_frame['file'], prettified_frame['line'])
+        print(
+            prettified_frame["function"],
+            prettified_frame["file"],
+            prettified_frame["line"],
+        )
 
 
 def __lldb_init_module(debugger, internal_dict):
-    debugger.HandleCommand(
-        'command script add -f host_art_bt.host_art_bt host_art_bt')
+    debugger.HandleCommand("command script add -f host_art_bt.host_art_bt host_art_bt")
diff --git a/lldb/scripts/install_custom_python.py b/lldb/scripts/install_custom_python.py
index 6e263fa714e0079..04df6fbc3ceae03 100644
--- a/lldb/scripts/install_custom_python.py
+++ b/lldb/scripts/install_custom_python.py
@@ -30,122 +30,112 @@
 def copy_one_file(dest_dir, source_dir, filename):
     source_path = os.path.join(source_dir, filename)
     dest_path = os.path.join(dest_dir, filename)
-    print('Copying file %s ==> %s...' % (source_path, dest_path))
+    print("Copying file %s ==> %s..." % (source_path, dest_path))
     shutil.copyfile(source_path, dest_path)
 
 
-def copy_named_files(
-        dest_dir,
-        source_dir,
-        files,
-        extensions,
-        copy_debug_suffix_also):
-    for (file, ext) in itertools.product(files, extensions):
-        copy_one_file(dest_dir, source_dir, file + '.' + ext)
+def copy_named_files(dest_dir, source_dir, files, extensions, copy_debug_suffix_also):
+    for file, ext in itertools.product(files, extensions):
+        copy_one_file(dest_dir, source_dir, file + "." + ext)
         if copy_debug_suffix_also:
-            copy_one_file(dest_dir, source_dir, file + '_d.' + ext)
+            copy_one_file(dest_dir, source_dir, file + "_d." + ext)
 
 
 def copy_subdirectory(dest_dir, source_dir, subdir):
     dest_dir = os.path.join(dest_dir, subdir)
     source_dir = os.path.join(source_dir, subdir)
-    print('Copying directory %s ==> %s...' % (source_dir, dest_dir))
+    print("Copying directory %s ==> %s..." % (source_dir, dest_dir))
     shutil.copytree(source_dir, dest_dir)
 
 
 def copy_distro(dest_dir, dest_subdir, source_dir, source_prefix):
     dest_dir = os.path.join(dest_dir, dest_subdir)
 
-    print('Copying distribution %s ==> %s' % (source_dir, dest_dir))
+    print("Copying distribution %s ==> %s" % (source_dir, dest_dir))
 
     os.mkdir(dest_dir)
-    PCbuild_dir = os.path.join(source_dir, 'PCbuild')
+    PCbuild_dir = os.path.join(source_dir, "PCbuild")
     if source_prefix:
         PCbuild_dir = os.path.join(PCbuild_dir, source_prefix)
     # First copy the files that go into the root of the new distribution. This
     # includes the Python executables, python27(_d).dll, and relevant PDB
     # files.
-    print('Copying Python executables...')
+    print("Copying Python executables...")
+    copy_named_files(dest_dir, PCbuild_dir, ["w9xpopen"], ["exe", "pdb"], False)
+    copy_named_files(dest_dir, PCbuild_dir, ["python_d", "pythonw_d"], ["exe"], False)
     copy_named_files(
-        dest_dir, PCbuild_dir, ['w9xpopen'], [
-            'exe', 'pdb'], False)
-    copy_named_files(
-        dest_dir, PCbuild_dir, [
-            'python_d', 'pythonw_d'], ['exe'], False)
-    copy_named_files(
-        dest_dir, PCbuild_dir, [
-            'python', 'pythonw'], [
-            'exe', 'pdb'], False)
-    copy_named_files(dest_dir, PCbuild_dir, ['python27'], ['dll', 'pdb'], True)
+        dest_dir, PCbuild_dir, ["python", "pythonw"], ["exe", "pdb"], False
+    )
+    copy_named_files(dest_dir, PCbuild_dir, ["python27"], ["dll", "pdb"], True)
 
     # Next copy everything in the Include directory.
-    print('Copying Python include directory')
-    copy_subdirectory(dest_dir, source_dir, 'Include')
+    print("Copying Python include directory")
+    copy_subdirectory(dest_dir, source_dir, "Include")
 
     # Copy Lib folder (builtin Python modules)
-    print('Copying Python Lib directory')
-    copy_subdirectory(dest_dir, source_dir, 'Lib')
+    print("Copying Python Lib directory")
+    copy_subdirectory(dest_dir, source_dir, "Lib")
 
     # Copy tools folder.  These are probably not necessary, but we copy them anyway to
     # match an official distribution as closely as possible.  Note that we don't just copy
     # the subdirectory recursively.  The source distribution ships with many more tools
     # than what you get by installing python regularly.  We only copy the tools that appear
     # in an installed distribution.
-    tools_dest_dir = os.path.join(dest_dir, 'Tools')
-    tools_source_dir = os.path.join(source_dir, 'Tools')
+    tools_dest_dir = os.path.join(dest_dir, "Tools")
+    tools_source_dir = os.path.join(source_dir, "Tools")
     os.mkdir(tools_dest_dir)
-    copy_subdirectory(tools_dest_dir, tools_source_dir, 'i18n')
-    copy_subdirectory(tools_dest_dir, tools_source_dir, 'pynche')
-    copy_subdirectory(tools_dest_dir, tools_source_dir, 'scripts')
-    copy_subdirectory(tools_dest_dir, tools_source_dir, 'versioncheck')
-    copy_subdirectory(tools_dest_dir, tools_source_dir, 'webchecker')
+    copy_subdirectory(tools_dest_dir, tools_source_dir, "i18n")
+    copy_subdirectory(tools_dest_dir, tools_source_dir, "pynche")
+    copy_subdirectory(tools_dest_dir, tools_source_dir, "scripts")
+    copy_subdirectory(tools_dest_dir, tools_source_dir, "versioncheck")
+    copy_subdirectory(tools_dest_dir, tools_source_dir, "webchecker")
 
     pyd_names = [
-        '_ctypes',
-        '_ctypes_test',
-        '_elementtree',
-        '_multiprocessing',
-        '_socket',
-        '_testcapi',
-        'pyexpat',
-        'select',
-        'unicodedata',
-        'winsound']
+        "_ctypes",
+        "_ctypes_test",
+        "_elementtree",
+        "_multiprocessing",
+        "_socket",
+        "_testcapi",
+        "pyexpat",
+        "select",
+        "unicodedata",
+        "winsound",
+    ]
 
     # Copy builtin extension modules (pyd files)
-    dlls_dir = os.path.join(dest_dir, 'DLLs')
+    dlls_dir = os.path.join(dest_dir, "DLLs")
     os.mkdir(dlls_dir)
-    print('Copying DLLs directory')
-    copy_named_files(dlls_dir, PCbuild_dir, pyd_names, ['pyd', 'pdb'], True)
+    print("Copying DLLs directory")
+    copy_named_files(dlls_dir, PCbuild_dir, pyd_names, ["pyd", "pdb"], True)
 
     # Copy libs folder (implibs for the pyd files)
-    libs_dir = os.path.join(dest_dir, 'libs')
+    libs_dir = os.path.join(dest_dir, "libs")
     os.mkdir(libs_dir)
-    print('Copying libs directory')
-    copy_named_files(libs_dir, PCbuild_dir, pyd_names, ['lib'], False)
-    copy_named_files(libs_dir, PCbuild_dir, ['python27'], ['lib'], True)
+    print("Copying libs directory")
+    copy_named_files(libs_dir, PCbuild_dir, pyd_names, ["lib"], False)
+    copy_named_files(libs_dir, PCbuild_dir, ["python27"], ["lib"], True)
 
 
-parser = argparse.ArgumentParser(
-    description='Install a custom Python distribution')
+parser = argparse.ArgumentParser(description="Install a custom Python distribution")
 parser.add_argument(
-    '--source',
-    required=True,
-    help='The root of the source tree where Python is built.')
+    "--source", required=True, help="The root of the source tree where Python is built."
+)
 parser.add_argument(
-    '--dest',
-    required=True,
-    help='The location to install the Python distributions.')
+    "--dest", required=True, help="The location to install the Python distributions."
+)
 parser.add_argument(
-    '--overwrite',
+    "--overwrite",
     default=False,
-    action='store_true',
-    help='If the destination directory already exists, destroys its contents first.')
+    action="store_true",
+    help="If the destination directory already exists, destroys its contents first.",
+)
 parser.add_argument(
-    '--silent',
+    "--silent",
     default=False,
-    action='store_true',
-    help='If --overwite was specified, suppress confirmation before deleting a directory tree.')
+    action="store_true",
+    help="If --overwite was specified, suppress confirmation before deleting a directory tree.",
+)
 
 args = parser.parse_args()
 
@@ -153,23 +143,31 @@ def copy_distro(dest_dir, dest_subdir, source_dir, source_prefix):
 args.dest = os.path.normpath(args.dest)
 
 if not os.path.exists(args.source):
-    print('The source directory %s does not exist.  Exiting...')
+    print("The source directory %s does not exist.  Exiting...")
     sys.exit(1)
 
 if os.path.exists(args.dest):
     if not args.overwrite:
-        print('The destination directory \'%s\' already exists and --overwrite was not specified.  Exiting...' % args.dest)
+        print(
+            "The destination directory '%s' already exists and --overwrite was not specified.  Exiting..."
+            % args.dest
+        )
         sys.exit(1)
     while not args.silent:
-        print('Ok to recursively delete \'%s\' and all contents (Y/N)?  Choosing Y will permanently delete the contents.' % args.dest)
+        print(
+            "Ok to recursively delete '%s' and all contents (Y/N)?  Choosing Y will permanently delete the contents."
+            % args.dest
+        )
         result = str.upper(sys.stdin.read(1))
-        if result == 'N':
-            print('Unable to copy files to the destination.  The destination already exists.')
+        if result == "N":
+            print(
+                "Unable to copy files to the destination.  The destination already exists."
+            )
             sys.exit(1)
-        elif result == 'Y':
+        elif result == "Y":
             break
     shutil.rmtree(args.dest)
 
 os.mkdir(args.dest)
-copy_distro(args.dest, 'x86', args.source, None)
-copy_distro(args.dest, 'x64', args.source, 'amd64')
+copy_distro(args.dest, "x86", args.source, None)
+copy_distro(args.dest, "x64", args.source, "amd64")
diff --git a/lldb/scripts/reproducer-replay.py b/lldb/scripts/reproducer-replay.py
index 40d7cebca05d4e7..f44e3cf4935385d 100755
--- a/lldb/scripts/reproducer-replay.py
+++ b/lldb/scripts/reproducer-replay.py
@@ -10,39 +10,39 @@
 
 
 def run_reproducer(path):
-    proc = subprocess.Popen([LLDB, '--replay', path],
-                            stdout=subprocess.PIPE,
-                            stderr=subprocess.PIPE)
+    proc = subprocess.Popen(
+        [LLDB, "--replay", path], stdout=subprocess.PIPE, stderr=subprocess.PIPE
+    )
     reason = None
     try:
         outs, errs = proc.communicate(timeout=TIMEOUT)
         success = proc.returncode == 0
-        result = 'PASSED' if success else 'FAILED'
+        result = "PASSED" if success else "FAILED"
         if not success:
             outs = outs.decode()
             errs = errs.decode()
             # Do some pattern matching to find out the cause of the failure.
-            if 'Encountered unexpected packet during replay' in errs:
-                reason = 'Unexpected packet'
-            elif 'Assertion failed' in errs:
-                reason = 'Assertion failed'
-            elif 'UNREACHABLE' in errs:
-                reason = 'Unreachable executed'
-            elif 'Segmentation fault' in errs:
-                reason = 'Segmentation fault'
-            elif 'Illegal instruction' in errs:
-                reason = 'Illegal instruction'
+            if "Encountered unexpected packet during replay" in errs:
+                reason = "Unexpected packet"
+            elif "Assertion failed" in errs:
+                reason = "Assertion failed"
+            elif "UNREACHABLE" in errs:
+                reason = "Unreachable executed"
+            elif "Segmentation fault" in errs:
+                reason = "Segmentation fault"
+            elif "Illegal instruction" in errs:
+                reason = "Illegal instruction"
             else:
-                reason = f'Exit code {proc.returncode}'
+                reason = f"Exit code {proc.returncode}"
     except subprocess.TimeoutExpired:
         proc.kill()
         success = False
         outs, errs = proc.communicate()
-        result = 'TIMEOUT'
+        result = "TIMEOUT"
 
     if not FAILURE_ONLY or not success:
-        reason_str = f' ({reason})' if reason else ''
-        print(f'{result}: {path}{reason_str}')
+        reason_str = f" ({reason})" if reason else ""
+        print(f"{result}: {path}{reason_str}")
         if VERBOSE:
             if outs:
                 print(outs)
@@ -54,49 +54,51 @@ def find_reproducers(path):
     for root, dirs, files in os.walk(path):
         for dir in dirs:
             _, extension = os.path.splitext(dir)
-            if dir.startswith('Test') and extension == '.py':
+            if dir.startswith("Test") and extension == ".py":
                 yield os.path.join(root, dir)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     parser = argparse.ArgumentParser(
-        description='LLDB API Test Replay Driver. '
-        'Replay one or more reproducers in parallel using the specified LLDB driver. '
-        'The script will look for reproducers generated by the API lit test suite. '
-        'To generate the reproducers, pass --param \'lldb-run-with-repro=capture\' to lit.'
+        description="LLDB API Test Replay Driver. "
+        "Replay one or more reproducers in parallel using the specified LLDB driver. "
+        "The script will look for reproducers generated by the API lit test suite. "
+        "To generate the reproducers, pass --param 'lldb-run-with-repro=capture' to lit."
     )
     parser.add_argument(
-        '-j',
-        '--threads',
+        "-j",
+        "--threads",
         type=int,
         default=multiprocessing.cpu_count(),
-        help='Number of threads. The number of CPU threads if not specified.')
+        help="Number of threads. The number of CPU threads if not specified.",
+    )
     parser.add_argument(
-        '-t',
-        '--timeout',
+        "-t",
+        "--timeout",
         type=int,
         default=60,
-        help='Replay timeout in seconds. 60 seconds if not specified.')
+        help="Replay timeout in seconds. 60 seconds if not specified.",
+    )
     parser.add_argument(
-        '-p',
-        '--path',
+        "-p",
+        "--path",
         type=str,
         default=os.getcwd(),
-        help=
-        'Path to the directory containing the reproducers. The current working directory if not specified.'
+        help="Path to the directory containing the reproducers. The current working directory if not specified.",
+    )
+    parser.add_argument(
+        "-l",
+        "--lldb",
+        type=str,
+        required=True,
+        help="Path to the LLDB command line driver",
+    )
+    parser.add_argument(
+        "-v", "--verbose", help="Print replay output.", action="store_true"
+    )
+    parser.add_argument(
+        "--failure-only", help="Only log failures.", action="store_true"
     )
-    parser.add_argument('-l',
-                        '--lldb',
-                        type=str,
-                        required=True,
-                        help='Path to the LLDB command line driver')
-    parser.add_argument('-v',
-                        '--verbose',
-                        help='Print replay output.',
-                        action='store_true')
-    parser.add_argument('--failure-only',
-                        help='Only log failures.',
-                        action='store_true')
     args = parser.parse_args()
 
     global LLDB
@@ -109,11 +111,11 @@ def find_reproducers(path):
     FAILURE_ONLY = args.failure_only
 
     print(
-        f'Replaying reproducers in {args.path} with {args.threads} threads and a {args.timeout} seconds timeout'
+        f"Replaying reproducers in {args.path} with {args.threads} threads and a {args.timeout} seconds timeout"
     )
 
     try:
         pool = Pool(args.threads)
         pool.map(run_reproducer, find_reproducers(args.path))
     except KeyboardInterrupt:
-        print('Interrupted')
+        print("Interrupted")
diff --git a/lldb/scripts/use_lldb_suite.py b/lldb/scripts/use_lldb_suite.py
index 84380f6a5592d85..6388d87b181ce03 100644
--- a/lldb/scripts/use_lldb_suite.py
+++ b/lldb/scripts/use_lldb_suite.py
@@ -7,7 +7,7 @@ def find_lldb_root():
     lldb_root = os.path.dirname(inspect.getfile(inspect.currentframe()))
     while True:
         parent = os.path.dirname(lldb_root)
-        if parent == lldb_root: # dirname('/') == '/'
+        if parent == lldb_root:  # dirname('/') == '/'
             raise Exception("use_lldb_suite_root.py not found")
         lldb_root = parent
 
@@ -15,8 +15,10 @@ def find_lldb_root():
         if os.path.isfile(test_path):
             return lldb_root
 
+
 lldb_root = find_lldb_root()
 import imp
+
 fp, pathname, desc = imp.find_module("use_lldb_suite_root", [lldb_root])
 try:
     imp.load_module("use_lldb_suite_root", fp, pathname, desc)
diff --git a/lldb/scripts/verify_api.py b/lldb/scripts/verify_api.py
index f3f0748023bc207..9d14a58121bfbc8 100755
--- a/lldb/scripts/verify_api.py
+++ b/lldb/scripts/verify_api.py
@@ -10,58 +10,67 @@
 
 def extract_exe_symbol_names(arch, exe_path, match_str):
     command = 'dsymutil --arch %s -s "%s" | grep "%s" | colrm 1 69' % (
-        arch, exe_path, match_str)
+        arch,
+        exe_path,
+        match_str,
+    )
     (command_exit_status, command_output) = subprocess.getstatusoutput(command)
     if command_exit_status == 0:
         if command_output:
             return command_output[0:-1].split("'\n")
         else:
-            print('error: command returned no output')
+            print("error: command returned no output")
     else:
-        print('error: command failed with exit status %i\n    command: %s' % (command_exit_status, command))
+        print(
+            "error: command failed with exit status %i\n    command: %s"
+            % (command_exit_status, command)
+        )
     return list()
 
 
 def verify_api(all_args):
-    '''Verify the API in the specified library is valid given one or more binaries.'''
+    """Verify the API in the specified library is valid given one or more binaries."""
     usage = "usage: verify_api --library <path> [ --library <path> ...] executable1 [executable2 ...]"
-    description = '''Verify the API in the specified library is valid given one or more binaries.
+    description = """Verify the API in the specified library is valid given one or more binaries.
 
     Example:
 
         verify_api.py --library ~/Documents/src/lldb/build/Debug/LLDB.framework/LLDB --arch x86_64 /Applications/Xcode.app/Contents/PlugIns/DebuggerLLDB.ideplugin/Contents/MacOS/DebuggerLLDB --api-regex lldb
-    '''
+    """
     parser = optparse.OptionParser(
-        description=description,
-        prog='verify_api',
-        usage=usage)
+        description=description, prog="verify_api", usage=usage
+    )
     parser.add_option(
-        '-v',
-        '--verbose',
-        action='store_true',
-        dest='verbose',
-        help='display verbose debug info',
-        default=False)
+        "-v",
+        "--verbose",
+        action="store_true",
+        dest="verbose",
+        help="display verbose debug info",
+        default=False,
+    )
     parser.add_option(
-        '-a',
-        '--arch',
-        type='string',
-        action='append',
-        dest='archs',
-        help='architecture to use when checking the api')
+        "-a",
+        "--arch",
+        type="string",
+        action="append",
+        dest="archs",
+        help="architecture to use when checking the api",
+    )
     parser.add_option(
-        '-r',
-        '--api-regex',
-        type='string',
-        dest='api_regex_str',
-        help='Exclude any undefined symbols that do not match this regular expression when searching for missing APIs.')
+        "-r",
+        "--api-regex",
+        type="string",
+        dest="api_regex_str",
+        help="Exclude any undefined symbols that do not match this regular expression when searching for missing APIs.",
+    )
     parser.add_option(
-        '-l',
-        '--library',
-        type='string',
-        action='append',
-        dest='libraries',
-        help='Specify one or more libraries that will contain all needed APIs for the executables.')
+        "-l",
+        "--library",
+        type="string",
+        action="append",
+        dest="libraries",
+        help="Specify one or more libraries that will contain all needed APIs for the executables.",
+    )
     (options, args) = parser.parse_args(all_args)
 
     api_external_symbols = list()
@@ -69,18 +78,19 @@ def verify_api(all_args):
         for arch in options.archs:
             for library in options.libraries:
                 external_symbols = extract_exe_symbol_names(
-                    arch, library, "(     SECT EXT)")
+                    arch, library, "(     SECT EXT)"
+                )
                 if external_symbols:
                     for external_symbol in external_symbols:
                         api_external_symbols.append(external_symbol)
                 else:
                     sys.exit(1)
     else:
-        print('error: must specify one or more architectures with the --arch option')
+        print("error: must specify one or more architectures with the --arch option")
         sys.exit(4)
     if options.verbose:
         print("API symbols:")
-        for (i, external_symbol) in enumerate(api_external_symbols):
+        for i, external_symbol in enumerate(api_external_symbols):
             print("[%u] %s" % (i, external_symbol))
 
     api_regex = None
@@ -92,24 +102,29 @@ def verify_api(all_args):
             print('Verifying (%s) "%s"...' % (arch, exe_path))
             exe_errors = 0
             undefined_symbols = extract_exe_symbol_names(
-                arch, exe_path, "(     UNDF EXT)")
+                arch, exe_path, "(     UNDF EXT)"
+            )
             for undefined_symbol in undefined_symbols:
                 if api_regex:
                     match = api_regex.search(undefined_symbol)
                     if not match:
                         if options.verbose:
-                            print('ignoring symbol: %s' % (undefined_symbol))
+                            print("ignoring symbol: %s" % (undefined_symbol))
                         continue
                 if undefined_symbol in api_external_symbols:
                     if options.verbose:
-                        print('verified symbol: %s' % (undefined_symbol))
+                        print("verified symbol: %s" % (undefined_symbol))
                 else:
-                    print('missing symbol: %s' % (undefined_symbol))
+                    print("missing symbol: %s" % (undefined_symbol))
                     exe_errors += 1
             if exe_errors:
-                print('error: missing %u API symbols from %s' % (exe_errors, options.libraries))
+                print(
+                    "error: missing %u API symbols from %s"
+                    % (exe_errors, options.libraries)
+                )
             else:
-                print('success')
+                print("success")
 
-if __name__ == '__main__':
+
+if __name__ == "__main__":
     verify_api(sys.argv[1:])
diff --git a/lldb/utils/lldb-repro/lldb-repro.py b/lldb/utils/lldb-repro/lldb-repro.py
index 928e1008984b847..30788d6a815e1aa 100755
--- a/lldb/utils/lldb-repro/lldb-repro.py
+++ b/lldb/utils/lldb-repro/lldb-repro.py
@@ -34,23 +34,27 @@ def main():
     # Compute an MD5 hash based on the input arguments and the current working
     # directory.
     h = hashlib.md5()
-    h.update(' '.join(sys.argv[2:]).encode('utf-8'))
-    h.update(os.getcwd().encode('utf-8'))
+    h.update(" ".join(sys.argv[2:]).encode("utf-8"))
+    h.update(os.getcwd().encode("utf-8"))
     input_hash = h.hexdigest()
 
     # Use the hash to "uniquely" identify a reproducer path.
     reproducer_path = os.path.join(tempfile.gettempdir(), input_hash)
 
     # Create a new lldb invocation with capture or replay enabled.
-    lldb = os.path.join(os.path.dirname(sys.argv[0]), 'lldb')
+    lldb = os.path.join(os.path.dirname(sys.argv[0]), "lldb")
     new_args = [lldb]
     if sys.argv[1] == "replay":
-        new_args.extend(['--replay', reproducer_path])
+        new_args.extend(["--replay", reproducer_path])
     elif sys.argv[1] == "capture":
-        new_args.extend([
-            '--capture', '--capture-path', reproducer_path,
-            '--reproducer-generate-on-exit'
-        ])
+        new_args.extend(
+            [
+                "--capture",
+                "--capture-path",
+                reproducer_path,
+                "--reproducer-generate-on-exit",
+            ]
+        )
         new_args.extend(sys.argv[2:])
     else:
         help()
@@ -60,10 +64,10 @@ def main():
 
     # The driver always exists with a zero exit code during replay. Store the
     # exit code and return that for tests that expect a non-zero exit code.
-    exit_code_path = os.path.join(reproducer_path, 'exit_code.txt')
+    exit_code_path = os.path.join(reproducer_path, "exit_code.txt")
     if sys.argv[1] == "replay":
         replay_exit_code = exit_code
-        with open(exit_code_path, 'r') as f:
+        with open(exit_code_path, "r") as f:
             exit_code = int(f.read())
         if replay_exit_code != 0:
             print("error: replay failed with exit code {}".format(replay_exit_code))
@@ -72,11 +76,11 @@ def main():
             return 1 if (exit_code == 0) else 0
         shutil.rmtree(reproducer_path, True)
     elif sys.argv[1] == "capture":
-        with open(exit_code_path, 'w') as f:
-            f.write('%d' % exit_code)
+        with open(exit_code_path, "w") as f:
+            f.write("%d" % exit_code)
 
     return exit_code
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     exit(main())
diff --git a/lldb/utils/lui/breakwin.py b/lldb/utils/lui/breakwin.py
index a12b3a96fe413ee..038afa2b16ee3a7 100644
--- a/lldb/utils/lui/breakwin.py
+++ b/lldb/utils/lui/breakwin.py
@@ -14,7 +14,6 @@
 
 
 class BreakWin(cui.ListWin):
-
     def __init__(self, driver, x, y, w, h):
         super(BreakWin, self).__init__(x, y, w, h)
         self.driver = driver
@@ -26,7 +25,7 @@ def handleEvent(self, event):
             if lldb.SBBreakpoint.EventIsBreakpointEvent(event):
                 self.update()
         if isinstance(event, int):
-            if event == ord('d'):
+            if event == ord("d"):
                 self.deleteSelected()
             if event == curses.ascii.NL or event == curses.ascii.SP:
                 self.toggleSelected()
@@ -72,14 +71,14 @@ def update(self):
                 continue
             text = lldbutil.get_description(bp)
             # FIXME: Use an API for this, not parsing the description.
-            match = re.search('SBBreakpoint: id = ([^,]+), (.*)', text)
+            match = re.search("SBBreakpoint: id = ([^,]+), (.*)", text)
             try:
                 id = match.group(1)
                 desc = match.group(2).strip()
                 if bp.IsEnabled():
-                    text = '%s: %s' % (id, desc)
+                    text = "%s: %s" % (id, desc)
                 else:
-                    text = '%s: (disabled) %s' % (id, desc)
+                    text = "%s: (disabled) %s" % (id, desc)
             except ValueError as e:
                 # bp unparsable
                 pass
@@ -87,7 +86,8 @@ def update(self):
             if self.showDetails.setdefault(bp.id, False):
                 for location in bp:
                     desc = lldbutil.get_description(
-                        location, lldb.eDescriptionLevelFull)
-                    text += '\n  ' + desc
+                        location, lldb.eDescriptionLevelFull
+                    )
+                    text += "\n  " + desc
             self.addItem(text)
         self.setSelected(selected)
diff --git a/lldb/utils/lui/commandwin.py b/lldb/utils/lui/commandwin.py
index 7b2fdc1c09eaf91..8b0ecedc7d33ad9 100644
--- a/lldb/utils/lui/commandwin.py
+++ b/lldb/utils/lui/commandwin.py
@@ -13,21 +13,20 @@
 
 
 class History(object):
-
     def __init__(self):
         self.data = {}
         self.pos = 0
-        self.tempEntry = ''
+        self.tempEntry = ""
 
     def previous(self, curr):
         if self.pos == len(self.data):
             self.tempEntry = curr
 
         if self.pos < 0:
-            return ''
+            return ""
         if self.pos == 0:
             self.pos -= 1
-            return ''
+            return ""
         if self.pos > 0:
             self.pos -= 1
             return self.data[self.pos]
@@ -38,13 +37,13 @@ def next(self):
 
         if self.pos < len(self.data):
             return self.data[self.pos]
-        elif self.tempEntry != '':
+        elif self.tempEntry != "":
             return self.tempEntry
         else:
-            return ''
+            return ""
 
     def add(self, c):
-        self.tempEntry = ''
+        self.tempEntry = ""
         self.pos = len(self.data)
         if self.pos == 0 or self.data[self.pos - 1] != c:
             self.data[self.pos] = c
@@ -52,7 +51,6 @@ def add(self, c):
 
 
 class CommandWin(cui.TitledWin):
-
     def __init__(self, driver, x, y, w, h):
         super(CommandWin, self).__init__(x, y, w, h, "Commands")
         self.command = ""
@@ -72,7 +70,8 @@ def tabCompleteCallback(content):
             matches = lldb.SBStringList()
             commandinterpreter = self.getCommandInterpreter()
             commandinterpreter.HandleCompletion(
-                self.data, self.el.index, 0, -1, matches)
+                self.data, self.el.index, 0, -1, matches
+            )
             if matches.GetSize() == 2:
                 self.el.content += matches.GetStringAtIndex(0)
                 self.el.index = len(self.el.content)
@@ -90,19 +89,17 @@ def tabCompleteCallback(content):
         self.startline = self.win.getmaxyx()[0] - 2
 
         self.el = cui.CursesEditLine(
-            self.win,
-            self.history,
-            enterCallback,
-            tabCompleteCallback)
+            self.win, self.history, enterCallback, tabCompleteCallback
+        )
         self.el.prompt = self.driver.getPrompt()
         self.el.showPrompt(self.startline, 0)
 
     def handleCommand(self, cmd):
-       # enter!
+        # enter!
         self.win.scroll(1)  # TODO: scroll more for longer commands
-        if cmd == '':
-            cmd = self.history.previous('')
-        elif cmd in ('q', 'quit'):
+        if cmd == "":
+            cmd = self.history.previous("")
+        elif cmd in ("q", "quit"):
             self.driver.terminate()
             return
 
@@ -114,13 +111,13 @@ def handleCommand(self, cmd):
         else:
             out = ret.GetError()
             attr = curses.color_pair(3)  # red on black
-        self.win.addstr(self.startline, 0, out + '\n', attr)
+        self.win.addstr(self.startline, 0, out + "\n", attr)
         self.win.scroll(1)
         self.el.showPrompt(self.startline, 0)
 
     def handleEvent(self, event):
         if isinstance(event, int):
-            if event == curses.ascii.EOT and self.el.content == '':
+            if event == curses.ascii.EOT and self.el.content == "":
                 # When the command is empty, treat CTRL-D as EOF.
                 self.driver.terminate()
                 return
diff --git a/lldb/utils/lui/cui.py b/lldb/utils/lui/cui.py
index fffb812fbb9f630..06ffc4feadd4590 100755
--- a/lldb/utils/lui/cui.py
+++ b/lldb/utils/lui/cui.py
@@ -12,7 +12,6 @@
 
 
 class CursesWin(object):
-
     def __init__(self, x, y, w, h):
         self.win = curses.newwin(h, w, y, x)
         self.focus = False
@@ -34,11 +33,10 @@ def draw(self):
 
 
 class TextWin(CursesWin):
-
     def __init__(self, x, y, w):
         super(TextWin, self).__init__(x, y, w, 1)
         self.win.bkgd(curses.color_pair(1))
-        self.text = ''
+        self.text = ""
         self.reverse = False
 
     def canFocus(self):
@@ -48,8 +46,8 @@ def draw(self):
         w = self.win.getmaxyx()[1]
         text = self.text
         if len(text) > w:
-            #trunc_length = len(text) - w
-            text = text[-w + 1:]
+            # trunc_length = len(text) - w
+            text = text[-w + 1 :]
         if self.reverse:
             self.win.addstr(0, 0, text, curses.A_REVERSE)
         else:
@@ -64,7 +62,6 @@ def setText(self, text):
 
 
 class TitledWin(CursesWin):
-
     def __init__(self, x, y, w, h, title):
         super(TitledWin, self).__init__(x, y + 1, w, h - 1)
         self.title = title
@@ -82,7 +79,6 @@ def draw(self):
 
 
 class ListWin(CursesWin):
-
     def __init__(self, x, y, w, h):
         super(ListWin, self).__init__(x, y, w, h)
         self.items = []
@@ -101,10 +97,10 @@ def draw(self):
         firstSelected = -1
         lastSelected = -1
         for i, item in enumerate(self.items):
-            lines = self.items[i].split('\n')
-            lines = lines if lines[len(lines) - 1] != '' else lines[:-1]
+            lines = self.items[i].split("\n")
+            lines = lines if lines[len(lines) - 1] != "" else lines[:-1]
             if len(lines) == 0:
-                lines = ['']
+                lines = [""]
 
             if i == self.getSelected():
                 firstSelected = len(allLines)
@@ -127,7 +123,7 @@ def draw(self):
             attr = curses.A_NORMAL
             if i >= firstSelected and i <= lastSelected:
                 attr = curses.A_REVERSE
-                line = '{0:{width}}'.format(line, width=w - 1)
+                line = "{0:{width}}".format(line, width=w - 1)
 
             # Ignore the error we get from drawing over the bottom-right char.
             try:
@@ -170,7 +166,6 @@ def handleSelect(self, index):
 
 
 class InputHandler(threading.Thread):
-
     def __init__(self, screen, queue):
         super(InputHandler, self).__init__()
         self.screen = screen
@@ -183,7 +178,7 @@ def run(self):
 
 
 class CursesUI(object):
-    """ Responsible for updating the console UI with curses. """
+    """Responsible for updating the console UI with curses."""
 
     def __init__(self, screen, event_queue):
         self.screen = screen
@@ -220,7 +215,6 @@ def handleEvent(self, event):
                 self.focusNext()
 
     def eventLoop(self):
-
         self.input_handler.start()
         self.wins[self.focus].setFocus(True)
 
@@ -247,7 +241,7 @@ def eventLoop(self):
 
 
 class CursesEditLine(object):
-    """ Embed an 'editline'-compatible prompt inside a CursesWin. """
+    """Embed an 'editline'-compatible prompt inside a CursesWin."""
 
     def __init__(self, win, history, enterCallback, tabCompleteCallback):
         self.win = win
@@ -255,8 +249,8 @@ def __init__(self, win, history, enterCallback, tabCompleteCallback):
         self.enterCallback = enterCallback
         self.tabCompleteCallback = tabCompleteCallback
 
-        self.prompt = ''
-        self.content = ''
+        self.prompt = ""
+        self.content = ""
         self.index = 0
         self.startx = -1
         self.starty = -1
@@ -269,16 +263,16 @@ def draw(self, prompt=None):
             self.win.scroll(1)
             self.starty -= 1
             if self.starty < 0:
-                raise RuntimeError('Input too long; aborting')
+                raise RuntimeError("Input too long; aborting")
         (y, x) = (self.starty, self.startx)
 
         self.win.move(y, x)
         self.win.clrtobot()
         self.win.addstr(y, x, prompt)
         remain = self.content
-        self.win.addstr(remain[:w - len(prompt)])
-        remain = remain[w - len(prompt):]
-        while remain != '':
+        self.win.addstr(remain[: w - len(prompt)])
+        remain = remain[w - len(prompt) :]
+        while remain != "":
             y += 1
             self.win.addstr(y, 0, remain[:w])
             remain = remain[w:]
@@ -287,7 +281,7 @@ def draw(self, prompt=None):
         self.win.move(self.starty + length / w, length % w)
 
     def showPrompt(self, y, x, prompt=None):
-        self.content = ''
+        self.content = ""
         self.index = 0
         self.startx = x
         self.starty = y
@@ -299,26 +293,27 @@ def handleEvent(self, event):
         key = event
 
         if self.startx == -1:
-            raise RuntimeError('Trying to handle input without prompt')
+            raise RuntimeError("Trying to handle input without prompt")
 
         if key == curses.ascii.NL:
             self.enterCallback(self.content)
         elif key == curses.ascii.TAB:
             self.tabCompleteCallback(self.content)
         elif curses.ascii.isprint(key):
-            self.content = self.content[:self.index] + \
-                chr(key) + self.content[self.index:]
+            self.content = (
+                self.content[: self.index] + chr(key) + self.content[self.index :]
+            )
             self.index += 1
         elif key == curses.KEY_BACKSPACE or key == curses.ascii.BS:
             if self.index > 0:
                 self.index -= 1
-                self.content = self.content[
-                    :self.index] + self.content[self.index + 1:]
+                self.content = (
+                    self.content[: self.index] + self.content[self.index + 1 :]
+                )
         elif key == curses.KEY_DC or key == curses.ascii.DEL or key == curses.ascii.EOT:
-            self.content = self.content[
-                :self.index] + self.content[self.index + 1:]
+            self.content = self.content[: self.index] + self.content[self.index + 1 :]
         elif key == curses.ascii.VT:  # CTRL-K
-            self.content = self.content[:self.index]
+            self.content = self.content[: self.index]
         elif key == curses.KEY_LEFT or key == curses.ascii.STX:  # left or CTRL-B
             if self.index > 0:
                 self.index -= 1
diff --git a/lldb/utils/lui/debuggerdriver.py b/lldb/utils/lui/debuggerdriver.py
index f94ce5face7d4f3..c5d9da56170aaca 100644
--- a/lldb/utils/lui/debuggerdriver.py
+++ b/lldb/utils/lui/debuggerdriver.py
@@ -14,7 +14,7 @@
 
 
 class DebuggerDriver(Thread):
-    """ Drives the debugger and responds to events. """
+    """Drives the debugger and responds to events."""
 
     def __init__(self, debugger, event_queue):
         Thread.__init__(self)
@@ -31,41 +31,45 @@ def initialize(self, debugger):
         if not self.listener.IsValid():
             raise "Invalid listener"
 
-        self.listener.StartListeningForEventClass(self.debugger,
-                                                  lldb.SBTarget.GetBroadcasterClassName(),
-                                                  lldb.SBTarget.eBroadcastBitBreakpointChanged
-                                                  #| lldb.SBTarget.eBroadcastBitModuleLoaded
-                                                  #| lldb.SBTarget.eBroadcastBitModuleUnloaded
-                                                  | lldb.SBTarget.eBroadcastBitWatchpointChanged
-                                                  #| lldb.SBTarget.eBroadcastBitSymbolLoaded
-                                                  )
-
-        self.listener.StartListeningForEventClass(self.debugger,
-                                                  lldb.SBThread.GetBroadcasterClassName(),
-                                                  lldb.SBThread.eBroadcastBitStackChanged
-                                                  #  lldb.SBThread.eBroadcastBitBreakpointChanged
-                                                  | lldb.SBThread.eBroadcastBitThreadSuspended
-                                                  | lldb.SBThread.eBroadcastBitThreadResumed
-                                                  | lldb.SBThread.eBroadcastBitSelectedFrameChanged
-                                                  | lldb.SBThread.eBroadcastBitThreadSelected
-                                                  )
-
-        self.listener.StartListeningForEventClass(self.debugger,
-                                                  lldb.SBProcess.GetBroadcasterClassName(),
-                                                  lldb.SBProcess.eBroadcastBitStateChanged
-                                                  | lldb.SBProcess.eBroadcastBitInterrupt
-                                                  | lldb.SBProcess.eBroadcastBitSTDOUT
-                                                  | lldb.SBProcess.eBroadcastBitSTDERR
-                                                  | lldb.SBProcess.eBroadcastBitProfileData
-                                                  )
-        self.listener.StartListeningForEventClass(self.debugger,
-                                                  lldb.SBCommandInterpreter.GetBroadcasterClass(),
-                                                  lldb.SBCommandInterpreter.eBroadcastBitThreadShouldExit
-                                                  | lldb.SBCommandInterpreter.eBroadcastBitResetPrompt
-                                                  | lldb.SBCommandInterpreter.eBroadcastBitQuitCommandReceived
-                                                  | lldb.SBCommandInterpreter.eBroadcastBitAsynchronousOutputData
-                                                  | lldb.SBCommandInterpreter.eBroadcastBitAsynchronousErrorData
-                                                  )
+        self.listener.StartListeningForEventClass(
+            self.debugger,
+            lldb.SBTarget.GetBroadcasterClassName(),
+            lldb.SBTarget.eBroadcastBitBreakpointChanged
+            # | lldb.SBTarget.eBroadcastBitModuleLoaded
+            # | lldb.SBTarget.eBroadcastBitModuleUnloaded
+            | lldb.SBTarget.eBroadcastBitWatchpointChanged
+            # | lldb.SBTarget.eBroadcastBitSymbolLoaded
+        )
+
+        self.listener.StartListeningForEventClass(
+            self.debugger,
+            lldb.SBThread.GetBroadcasterClassName(),
+            lldb.SBThread.eBroadcastBitStackChanged
+            #  lldb.SBThread.eBroadcastBitBreakpointChanged
+            | lldb.SBThread.eBroadcastBitThreadSuspended
+            | lldb.SBThread.eBroadcastBitThreadResumed
+            | lldb.SBThread.eBroadcastBitSelectedFrameChanged
+            | lldb.SBThread.eBroadcastBitThreadSelected,
+        )
+
+        self.listener.StartListeningForEventClass(
+            self.debugger,
+            lldb.SBProcess.GetBroadcasterClassName(),
+            lldb.SBProcess.eBroadcastBitStateChanged
+            | lldb.SBProcess.eBroadcastBitInterrupt
+            | lldb.SBProcess.eBroadcastBitSTDOUT
+            | lldb.SBProcess.eBroadcastBitSTDERR
+            | lldb.SBProcess.eBroadcastBitProfileData,
+        )
+        self.listener.StartListeningForEventClass(
+            self.debugger,
+            lldb.SBCommandInterpreter.GetBroadcasterClass(),
+            lldb.SBCommandInterpreter.eBroadcastBitThreadShouldExit
+            | lldb.SBCommandInterpreter.eBroadcastBitResetPrompt
+            | lldb.SBCommandInterpreter.eBroadcastBitQuitCommandReceived
+            | lldb.SBCommandInterpreter.eBroadcastBitAsynchronousOutputData
+            | lldb.SBCommandInterpreter.eBroadcastBitAsynchronousErrorData,
+        )
 
     def createTarget(self, target_image, args=None):
         self.handleCommand("target create %s" % target_image)
diff --git a/lldb/utils/lui/eventwin.py b/lldb/utils/lui/eventwin.py
index c8d14d7aeb03fea..4ff8dd0b4eb7e2d 100644
--- a/lldb/utils/lui/eventwin.py
+++ b/lldb/utils/lui/eventwin.py
@@ -12,9 +12,8 @@
 
 
 class EventWin(cui.TitledWin):
-
     def __init__(self, x, y, w, h):
-        super(EventWin, self).__init__(x, y, w, h, 'LLDB Event Log')
+        super(EventWin, self).__init__(x, y, w, h, "LLDB Event Log")
         self.win.scrollok(1)
         super(EventWin, self).draw()
 
diff --git a/lldb/utils/lui/lldbutil.py b/lldb/utils/lui/lldbutil.py
index 2bf5e8ac0ef0540..6cbf4a302f65f35 100644
--- a/lldb/utils/lui/lldbutil.py
+++ b/lldb/utils/lui/lldbutil.py
@@ -40,6 +40,7 @@ def which(program):
                 return exe_file
     return None
 
+
 # ===================================================
 # Disassembly for an SBFunction or an SBSymbol object
 # ===================================================
@@ -56,6 +57,7 @@ def disassemble(target, function_or_symbol):
         print(i, file=buf)
     return buf.getvalue()
 
+
 # ==========================================================
 # Integer (byte size 1, 2, 4, and 8) to bytearray conversion
 # ==========================================================
@@ -75,11 +77,11 @@ def int_to_bytearray(val, bytesize):
     # Little endian followed by a format character.
     template = "<%c"
     if bytesize == 2:
-        fmt = template % 'h'
+        fmt = template % "h"
     elif bytesize == 4:
-        fmt = template % 'i'
+        fmt = template % "i"
     elif bytesize == 4:
-        fmt = template % 'q'
+        fmt = template % "q"
     else:
         return None
 
@@ -101,11 +103,11 @@ def bytearray_to_int(bytes, bytesize):
     # Little endian followed by a format character.
     template = "<%c"
     if bytesize == 2:
-        fmt = template % 'h'
+        fmt = template % "h"
     elif bytesize == 4:
-        fmt = template % 'i'
+        fmt = template % "i"
     elif bytesize == 4:
-        fmt = template % 'q'
+        fmt = template % "q"
     else:
         return None
 
@@ -126,7 +128,7 @@ def get_description(obj, option=None):
         o lldb.eDescriptionLevelFull
         o lldb.eDescriptionLevelVerbose
     """
-    method = getattr(obj, 'GetDescription')
+    method = getattr(obj, "GetDescription")
     if not method:
         return None
     tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint)
@@ -148,6 +150,7 @@ def get_description(obj, option=None):
 # Convert some enum value to its string counterpart
 # =================================================
 
+
 def state_type_to_str(enum):
     """Returns the stateType string given an enum."""
     if enum == lldb.eStateInvalid:
@@ -280,60 +283,70 @@ def value_type_to_str(enum):
 # Get stopped threads due to each stop reason.
 # ==================================================
 
-def sort_stopped_threads(process,
-                         breakpoint_threads=None,
-                         crashed_threads=None,
-                         watchpoint_threads=None,
-                         signal_threads=None,
-                         exiting_threads=None,
-                         other_threads=None):
-    """ Fills array *_threads with threads stopped for the corresponding stop
-        reason.
+
+def sort_stopped_threads(
+    process,
+    breakpoint_threads=None,
+    crashed_threads=None,
+    watchpoint_threads=None,
+    signal_threads=None,
+    exiting_threads=None,
+    other_threads=None,
+):
+    """Fills array *_threads with threads stopped for the corresponding stop
+    reason.
     """
-    for lst in [breakpoint_threads,
-                watchpoint_threads,
-                signal_threads,
-                exiting_threads,
-                other_threads]:
+    for lst in [
+        breakpoint_threads,
+        watchpoint_threads,
+        signal_threads,
+        exiting_threads,
+        other_threads,
+    ]:
         if lst is not None:
             lst[:] = []
 
     for thread in process:
         dispatched = False
-        for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads),
-                               (lldb.eStopReasonException, crashed_threads),
-                               (lldb.eStopReasonWatchpoint, watchpoint_threads),
-                               (lldb.eStopReasonSignal, signal_threads),
-                               (lldb.eStopReasonThreadExiting, exiting_threads),
-                               (None, other_threads)]:
+        for reason, list in [
+            (lldb.eStopReasonBreakpoint, breakpoint_threads),
+            (lldb.eStopReasonException, crashed_threads),
+            (lldb.eStopReasonWatchpoint, watchpoint_threads),
+            (lldb.eStopReasonSignal, signal_threads),
+            (lldb.eStopReasonThreadExiting, exiting_threads),
+            (None, other_threads),
+        ]:
             if not dispatched and list is not None:
                 if thread.GetStopReason() == reason or reason is None:
                     list.append(thread)
                     dispatched = True
 
+
 # ==================================================
 # Utility functions for setting breakpoints
 # ==================================================
 
 
 def run_break_set_by_file_and_line(
-        test,
-        file_name,
-        line_number,
-        extra_options=None,
-        num_expected_locations=1,
-        loc_exact=False,
-        module_name=None):
+    test,
+    file_name,
+    line_number,
+    extra_options=None,
+    num_expected_locations=1,
+    loc_exact=False,
+    module_name=None,
+):
     """Set a breakpoint by file and line, returning the breakpoint number.
 
     If extra_options is not None, then we append it to the breakpoint set command.
 
     If num_expected_locations is -1 we check that we got AT LEAST one location, otherwise we check that num_expected_locations equals the number of locations.
 
-    If loc_exact is true, we check that there is one location, and that location must be at the input file and line number."""
+    If loc_exact is true, we check that there is one location, and that location must be at the input file and line number.
+    """
 
     if file_name is None:
-        command = 'breakpoint set -l %d' % (line_number)
+        command = "breakpoint set -l %d" % (line_number)
     else:
         command = 'breakpoint set -f "%s" -l %d' % (file_name, line_number)
 
@@ -352,26 +365,28 @@ def run_break_set_by_file_and_line(
             num_locations=num_expected_locations,
             file_name=file_name,
             line_number=line_number,
-            module_name=module_name)
+            module_name=module_name,
+        )
     else:
         check_breakpoint_result(
-            test,
-            break_results,
-            num_locations=num_expected_locations)
+            test, break_results, num_locations=num_expected_locations
+        )
 
     return get_bpno_from_match(break_results)
 
 
 def run_break_set_by_symbol(
-        test,
-        symbol,
-        extra_options=None,
-        num_expected_locations=-1,
-        sym_exact=False,
-        module_name=None):
+    test,
+    symbol,
+    extra_options=None,
+    num_expected_locations=-1,
+    sym_exact=False,
+    module_name=None,
+):
     """Set a breakpoint by symbol name.  Common options are the same as run_break_set_by_file_and_line.
 
-    If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match."""
+    If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match.
+    """
     command = 'breakpoint set -n "%s"' % (symbol)
 
     if module_name:
@@ -388,22 +403,19 @@ def run_break_set_by_symbol(
             break_results,
             num_locations=num_expected_locations,
             symbol_name=symbol,
-            module_name=module_name)
+            module_name=module_name,
+        )
     else:
         check_breakpoint_result(
-            test,
-            break_results,
-            num_locations=num_expected_locations)
+            test, break_results, num_locations=num_expected_locations
+        )
 
     return get_bpno_from_match(break_results)
 
 
 def run_break_set_by_selector(
-        test,
-        selector,
-        extra_options=None,
-        num_expected_locations=-1,
-        module_name=None):
+    test, selector, extra_options=None, num_expected_locations=-1, module_name=None
+):
     """Set a breakpoint by selector.  Common options are the same as run_break_set_by_file_and_line."""
 
     command = 'breakpoint set -S "%s"' % (selector)
@@ -423,21 +435,19 @@ def run_break_set_by_selector(
             num_locations=num_expected_locations,
             symbol_name=selector,
             symbol_match_exact=False,
-            module_name=module_name)
+            module_name=module_name,
+        )
     else:
         check_breakpoint_result(
-            test,
-            break_results,
-            num_locations=num_expected_locations)
+            test, break_results, num_locations=num_expected_locations
+        )
 
     return get_bpno_from_match(break_results)
 
 
 def run_break_set_by_regexp(
-        test,
-        regexp,
-        extra_options=None,
-        num_expected_locations=-1):
+    test, regexp, extra_options=None, num_expected_locations=-1
+):
     """Set a breakpoint by regular expression match on symbol name.  Common options are the same as run_break_set_by_file_and_line."""
 
     command = 'breakpoint set -r "%s"' % (regexp)
@@ -446,19 +456,14 @@ def run_break_set_by_regexp(
 
     break_results = run_break_set_command(test, command)
 
-    check_breakpoint_result(
-        test,
-        break_results,
-        num_locations=num_expected_locations)
+    check_breakpoint_result(test, break_results, num_locations=num_expected_locations)
 
     return get_bpno_from_match(break_results)
 
 
 def run_break_set_by_source_regexp(
-        test,
-        regexp,
-        extra_options=None,
-        num_expected_locations=-1):
+    test, regexp, extra_options=None, num_expected_locations=-1
+):
     """Set a breakpoint by source regular expression.  Common options are the same as run_break_set_by_file_and_line."""
     command = 'breakpoint set -p "%s"' % (regexp)
     if extra_options:
@@ -466,10 +471,7 @@ def run_break_set_by_source_regexp(
 
     break_results = run_break_set_command(test, command)
 
-    check_breakpoint_result(
-        test,
-        break_results,
-        num_locations=num_expected_locations)
+    check_breakpoint_result(test, break_results, num_locations=num_expected_locations)
 
     return get_bpno_from_match(break_results)
 
@@ -496,120 +498,120 @@ def run_break_set_command(test, command):
         r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
         r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
         r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>[+\-]{0,1}[^+]+)( \+ (?P<offset>[0-9]+)){0,1}( \[inlined\] (?P<inline_symbol>.*)){0,1} at (?P<file>[^:]+):(?P<line_no>[0-9]+), address = (?P<address>0x[0-9a-fA-F]+)$",
-        r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>.*)( \+ (?P<offset>[0-9]+)){0,1}, address = (?P<address>0x[0-9a-fA-F]+)$"]
+        r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>.*)( \+ (?P<offset>[0-9]+)){0,1}, address = (?P<address>0x[0-9a-fA-F]+)$",
+    ]
     match_object = test.match(command, patterns)
     break_results = match_object.groupdict()
 
     # We always insert the breakpoint number, setting it to -1 if we couldn't find it
     # Also, make sure it gets stored as an integer.
-    if not 'bpno' in break_results:
-        break_results['bpno'] = -1
+    if not "bpno" in break_results:
+        break_results["bpno"] = -1
     else:
-        break_results['bpno'] = int(break_results['bpno'])
+        break_results["bpno"] = int(break_results["bpno"])
 
     # We always insert the number of locations
     # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
     # We also make sure it is an integer.
 
-    if not 'num_locations' in break_results:
+    if not "num_locations" in break_results:
         num_locations = 1
     else:
-        num_locations = break_results['num_locations']
-        if num_locations == 'no':
+        num_locations = break_results["num_locations"]
+        if num_locations == "no":
             num_locations = 0
         else:
-            num_locations = int(break_results['num_locations'])
+            num_locations = int(break_results["num_locations"])
 
-    break_results['num_locations'] = num_locations
+    break_results["num_locations"] = num_locations
 
-    if 'line_no' in break_results:
-        break_results['line_no'] = int(break_results['line_no'])
+    if "line_no" in break_results:
+        break_results["line_no"] = int(break_results["line_no"])
 
     return break_results
 
 
 def get_bpno_from_match(break_results):
-    return int(break_results['bpno'])
+    return int(break_results["bpno"])
 
 
 def check_breakpoint_result(
-        test,
-        break_results,
-        file_name=None,
-        line_number=-1,
-        symbol_name=None,
-        symbol_match_exact=True,
-        module_name=None,
-        offset=-1,
-        num_locations=-1):
-
-    out_num_locations = break_results['num_locations']
+    test,
+    break_results,
+    file_name=None,
+    line_number=-1,
+    symbol_name=None,
+    symbol_match_exact=True,
+    module_name=None,
+    offset=-1,
+    num_locations=-1,
+):
+    out_num_locations = break_results["num_locations"]
 
     if num_locations == -1:
-        test.assertTrue(out_num_locations > 0,
-                        "Expecting one or more locations, got none.")
+        test.assertTrue(
+            out_num_locations > 0, "Expecting one or more locations, got none."
+        )
     else:
         test.assertTrue(
             num_locations == out_num_locations,
-            "Expecting %d locations, got %d." %
-            (num_locations,
-             out_num_locations))
+            "Expecting %d locations, got %d." % (num_locations, out_num_locations),
+        )
 
     if file_name:
         out_file_name = ""
-        if 'file' in break_results:
-            out_file_name = break_results['file']
+        if "file" in break_results:
+            out_file_name = break_results["file"]
         test.assertTrue(
             file_name == out_file_name,
-            "Breakpoint file name '%s' doesn't match resultant name '%s'." %
-            (file_name,
-             out_file_name))
+            "Breakpoint file name '%s' doesn't match resultant name '%s'."
+            % (file_name, out_file_name),
+        )
 
     if line_number != -1:
         out_file_line = -1
-        if 'line_no' in break_results:
-            out_line_number = break_results['line_no']
+        if "line_no" in break_results:
+            out_line_number = break_results["line_no"]
 
         test.assertTrue(
             line_number == out_line_number,
-            "Breakpoint line number %s doesn't match resultant line %s." %
-            (line_number,
-             out_line_number))
+            "Breakpoint line number %s doesn't match resultant line %s."
+            % (line_number, out_line_number),
+        )
 
     if symbol_name:
         out_symbol_name = ""
         # Look first for the inlined symbol name, otherwise use the symbol
         # name:
-        if 'inline_symbol' in break_results and break_results['inline_symbol']:
-            out_symbol_name = break_results['inline_symbol']
-        elif 'symbol' in break_results:
-            out_symbol_name = break_results['symbol']
+        if "inline_symbol" in break_results and break_results["inline_symbol"]:
+            out_symbol_name = break_results["inline_symbol"]
+        elif "symbol" in break_results:
+            out_symbol_name = break_results["symbol"]
 
         if symbol_match_exact:
             test.assertTrue(
                 symbol_name == out_symbol_name,
-                "Symbol name '%s' doesn't match resultant symbol '%s'." %
-                (symbol_name,
-                 out_symbol_name))
+                "Symbol name '%s' doesn't match resultant symbol '%s'."
+                % (symbol_name, out_symbol_name),
+            )
         else:
             test.assertTrue(
-                out_symbol_name.find(symbol_name) != -
-                1,
-                "Symbol name '%s' isn't in resultant symbol '%s'." %
-                (symbol_name,
-                 out_symbol_name))
+                out_symbol_name.find(symbol_name) != -1,
+                "Symbol name '%s' isn't in resultant symbol '%s'."
+                % (symbol_name, out_symbol_name),
+            )
 
     if module_name:
         out_nodule_name = None
-        if 'module' in break_results:
-            out_module_name = break_results['module']
+        if "module" in break_results:
+            out_module_name = break_results["module"]
 
         test.assertTrue(
-            module_name.find(out_module_name) != -
-            1,
-            "Symbol module name '%s' isn't in expected module name '%s'." %
-            (out_module_name,
-             module_name))
+            module_name.find(out_module_name) != -1,
+            "Symbol module name '%s' isn't in expected module name '%s'."
+            % (out_module_name, module_name),
+        )
+
 
 # ==================================================
 # Utility functions related to Threads and Processes
@@ -658,7 +660,7 @@ def get_stopped_thread(process, reason):
 
 
 def get_threads_stopped_at_breakpoint(process, bkpt):
-    """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
+    """For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
     stopped_threads = []
     threads = []
 
@@ -677,7 +679,7 @@ def get_threads_stopped_at_breakpoint(process, bkpt):
 
 
 def continue_to_breakpoint(process, bkpt):
-    """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
+    """Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
     process.Continue()
     if process.GetState() != lldb.eStateStopped:
         return None
@@ -703,6 +705,7 @@ def get_function_names(thread):
     """
     Returns a sequence of function names from the stack frames of this thread.
     """
+
     def GetFuncName(i):
         return thread.GetFrameAtIndex(i).GetFunctionName()
 
@@ -713,6 +716,7 @@ def get_symbol_names(thread):
     """
     Returns a sequence of symbols for this thread.
     """
+
     def GetSymbol(i):
         return thread.GetFrameAtIndex(i).GetSymbol().GetName()
 
@@ -723,6 +727,7 @@ def get_pc_addresses(thread):
     """
     Returns a sequence of pc addresses for this thread.
     """
+
     def GetPCAddress(i):
         return thread.GetFrameAtIndex(i).GetPCAddress()
 
@@ -733,9 +738,9 @@ def get_filenames(thread):
     """
     Returns a sequence of file names from the stack frames of this thread.
     """
+
     def GetFilename(i):
-        return thread.GetFrameAtIndex(
-            i).GetLineEntry().GetFileSpec().GetFilename()
+        return thread.GetFrameAtIndex(i).GetLineEntry().GetFileSpec().GetFilename()
 
     return [GetFilename(i) for i in range(thread.GetNumFrames())]
 
@@ -744,6 +749,7 @@ def get_line_numbers(thread):
     """
     Returns a sequence of line numbers from the stack frames of this thread.
     """
+
     def GetLineNumber(i):
         return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
 
@@ -754,9 +760,9 @@ def get_module_names(thread):
     """
     Returns a sequence of module names from the stack frames of this thread.
     """
+
     def GetModuleName(i):
-        return thread.GetFrameAtIndex(
-            i).GetModule().GetFileSpec().GetFilename()
+        return thread.GetFrameAtIndex(i).GetModule().GetFileSpec().GetFilename()
 
     return [GetModuleName(i) for i in range(thread.GetNumFrames())]
 
@@ -765,6 +771,7 @@ def get_stack_frames(thread):
     """
     Returns a sequence of stack frames for this thread.
     """
+
     def GetStackFrame(i):
         return thread.GetFrameAtIndex(i)
 
@@ -790,8 +797,13 @@ def print_stacktrace(thread, string_buffer=False):
         desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason())
     else:
         desc = ""
-    print("Stack trace for thread id={0:#x} name={1} queue={2} ".format(
-        thread.GetThreadID(), thread.GetName(), thread.GetQueueName()) + desc, file=output)
+    print(
+        "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
+            thread.GetThreadID(), thread.GetName(), thread.GetQueueName()
+        )
+        + desc,
+        file=output,
+    )
 
     for i in range(depth):
         frame = thread.GetFrameAtIndex(i)
@@ -802,13 +814,31 @@ def print_stacktrace(thread, string_buffer=False):
             file_addr = addrs[i].GetFileAddress()
             start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress()
             symbol_offset = file_addr - start_addr
-            print("  frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
-                num=i, addr=load_addr, mod=mods[i], symbol=symbols[i], offset=symbol_offset), file=output)
+            print(
+                "  frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
+                    num=i,
+                    addr=load_addr,
+                    mod=mods[i],
+                    symbol=symbols[i],
+                    offset=symbol_offset,
+                ),
+                file=output,
+            )
         else:
-            print("  frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
-                num=i, addr=load_addr, mod=mods[i], func='%s [inlined]' %
-                funcs[i] if frame.IsInlined() else funcs[i], file=files[i], line=lines[i], args=get_args_as_string(
-                    frame, showFuncName=False) if not frame.IsInlined() else '()'), file=output)
+            print(
+                "  frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
+                    num=i,
+                    addr=load_addr,
+                    mod=mods[i],
+                    func="%s [inlined]" % funcs[i] if frame.IsInlined() else funcs[i],
+                    file=files[i],
+                    line=lines[i],
+                    args=get_args_as_string(frame, showFuncName=False)
+                    if not frame.IsInlined()
+                    else "()",
+                ),
+                file=output,
+            )
 
     if string_buffer:
         return output.getvalue()
@@ -827,6 +857,7 @@ def print_stacktraces(process, string_buffer=False):
     if string_buffer:
         return output.getvalue()
 
+
 # ===================================
 # Utility functions related to Frames
 # ===================================
@@ -859,9 +890,7 @@ def get_args_as_string(frame, showFuncName=True):
     vars = frame.GetVariables(True, False, False, True)  # type of SBValueList
     args = []  # list of strings
     for var in vars:
-        args.append("(%s)%s=%s" % (var.GetTypeName(),
-                                   var.GetName(),
-                                   var.GetValue()))
+        args.append("(%s)%s=%s" % (var.GetTypeName(), var.GetName(), var.GetValue()))
     if frame.GetFunction():
         name = frame.GetFunction().GetName()
     elif frame.GetSymbol():
@@ -882,15 +911,20 @@ def print_registers(frame, string_buffer=False):
     print("Register sets for " + str(frame), file=output)
 
     registerSet = frame.GetRegisters()  # Return type of SBValueList.
-    print("Frame registers (size of register set = %d):" % registerSet.GetSize(
-    ), file=output)
+    print(
+        "Frame registers (size of register set = %d):" % registerSet.GetSize(),
+        file=output,
+    )
     for value in registerSet:
-        #print >> output, value
-        print("%s (number of children = %d):" % (
-            value.GetName(), value.GetNumChildren()), file=output)
+        # print >> output, value
+        print(
+            "%s (number of children = %d):" % (value.GetName(), value.GetNumChildren()),
+            file=output,
+        )
         for child in value:
-            print("Name: %s, Value: %s" % (
-                child.GetName(), child.GetValue()), file=output)
+            print(
+                "Name: %s, Value: %s" % (child.GetName(), child.GetValue()), file=output
+            )
 
     if string_buffer:
         return output.getvalue()
@@ -950,6 +984,7 @@ def get_ESRs(frame):
     """
     return get_registers(frame, "exception state")
 
+
 # ======================================
 # Utility classes/functions for SBValues
 # ======================================
@@ -970,11 +1005,15 @@ def format(self, value, buffer=None, indent=0):
             val = value.GetValue()
         if val is None and value.GetNumChildren() > 0:
             val = "%s (location)" % value.GetLocation()
-        print("{indentation}({type}) {name} = {value}".format(
-            indentation=' ' * indent,
-            type=value.GetTypeName(),
-            name=value.GetName(),
-            value=val), file=output)
+        print(
+            "{indentation}({type}) {name} = {value}".format(
+                indentation=" " * indent,
+                type=value.GetTypeName(),
+                name=value.GetName(),
+                value=val,
+            ),
+            file=output,
+        )
         return output.getvalue()
 
 
@@ -996,8 +1035,7 @@ def format(self, value, buffer=None):
 
         BasicFormatter.format(self, value, buffer=output)
         for child in value:
-            BasicFormatter.format(
-                self, child, buffer=output, indent=self.cindent)
+            BasicFormatter.format(self, child, buffer=output, indent=self.cindent)
 
         return output.getvalue()
 
@@ -1025,14 +1063,12 @@ def format(self, value, buffer=None):
         new_indent = self.lindent + self.cindent
         for child in value:
             if child.GetSummary() is not None:
-                BasicFormatter.format(
-                    self, child, buffer=output, indent=new_indent)
+                BasicFormatter.format(self, child, buffer=output, indent=new_indent)
             else:
                 if child.GetNumChildren() > 0:
                     rdf = RecursiveDecentFormatter(indent_level=new_indent)
                     rdf.format(child, buffer=output)
                 else:
-                    BasicFormatter.format(
-                        self, child, buffer=output, indent=new_indent)
+                    BasicFormatter.format(self, child, buffer=output, indent=new_indent)
 
         return output.getvalue()
diff --git a/lldb/utils/lui/lui.py b/lldb/utils/lui/lui.py
index 98e1c63ce4141ae..42ea3c6787306b7 100755
--- a/lldb/utils/lui/lui.py
+++ b/lldb/utils/lui/lui.py
@@ -38,17 +38,11 @@
 def handle_args(driver, argv):
     parser = OptionParser()
     parser.add_option(
-        "-p",
-        "--attach",
-        dest="pid",
-        help="Attach to specified Process ID",
-        type="int")
+        "-p", "--attach", dest="pid", help="Attach to specified Process ID", type="int"
+    )
     parser.add_option(
-        "-c",
-        "--core",
-        dest="core",
-        help="Load specified core file",
-        type="string")
+        "-c", "--core", dest="core", help="Load specified core file", type="string"
+    )
 
     (options, args) = parser.parse_args(argv)
 
@@ -60,9 +54,7 @@ def handle_args(driver, argv):
             print("Error: expecting integer PID, got '%s'" % options.pid)
     elif options.core is not None:
         if not os.path.exists(options.core):
-            raise Exception(
-                "Specified core file '%s' does not exist." %
-                options.core)
+            raise Exception("Specified core file '%s' does not exist." % options.core)
         driver.loadCore(options.core)
     elif len(args) == 2:
         if not os.path.isfile(args[1]):
@@ -80,7 +72,6 @@ def sigint_handler(signal, frame):
 
 
 class LLDBUI(cui.CursesUI):
-
     def __init__(self, screen, event_queue, driver):
         super(LLDBUI, self).__init__(screen, event_queue)
 
@@ -94,19 +85,21 @@ def __init__(self, screen, event_queue, driver):
         self.status_win = statuswin.StatusWin(0, h - 1, w, 1)
         h -= 1
         self.command_win = commandwin.CommandWin(
-            driver, 0, h - command_win_height, w, command_win_height)
+            driver, 0, h - command_win_height, w, command_win_height
+        )
         h -= command_win_height
-        self.source_win = sourcewin.SourceWin(driver, 0, 0,
-                                              w - break_win_width - 1, h)
-        self.break_win = breakwin.BreakWin(driver, w - break_win_width, 0,
-                                           break_win_width, h)
-
-        self.wins = [self.status_win,
-                     # self.event_win,
-                     self.source_win,
-                     self.break_win,
-                     self.command_win,
-                     ]
+        self.source_win = sourcewin.SourceWin(driver, 0, 0, w - break_win_width - 1, h)
+        self.break_win = breakwin.BreakWin(
+            driver, w - break_win_width, 0, break_win_width, h
+        )
+
+        self.wins = [
+            self.status_win,
+            # self.event_win,
+            self.source_win,
+            self.break_win,
+            self.command_win,
+        ]
 
         self.focus = len(self.wins) - 1  # index of command window;
 
@@ -116,12 +109,14 @@ def handleEvent(self, event):
             if event == curses.KEY_F10:
                 self.driver.terminate()
             if event == 20:  # ctrl-T
+
                 def foo(cmd):
                     ret = lldb.SBCommandReturnObject()
                     self.driver.getCommandInterpreter().HandleCommand(cmd, ret)
-                foo('target create a.out')
-                foo('b main')
-                foo('run')
+
+                foo("target create a.out")
+                foo("b main")
+                foo("run")
         super(LLDBUI, self).handleEvent(event)
 
 
@@ -145,6 +140,7 @@ def main(screen):
     handle_args(driver, sys.argv)
     view.eventLoop()
 
+
 if __name__ == "__main__":
     try:
         curses.wrapper(main)
diff --git a/lldb/utils/lui/sandbox.py b/lldb/utils/lui/sandbox.py
index 8bb4e3595f805a8..3bcf3d5915d93c4 100755
--- a/lldb/utils/lui/sandbox.py
+++ b/lldb/utils/lui/sandbox.py
@@ -25,7 +25,6 @@
 
 
 class SandboxUI(cui.CursesUI):
-
     def __init__(self, screen, event_queue):
         super(SandboxUI, self).__init__(screen, event_queue)
 
@@ -34,10 +33,10 @@ def __init__(self, screen, event_queue):
         h2 = height / 2
 
         self.wins = []
-        #self.wins.append(cui.TitledWin(w2, h2, w2, h2, "Test Window 4"))
+        # self.wins.append(cui.TitledWin(w2, h2, w2, h2, "Test Window 4"))
         list_win = cui.ListWin(w2, h2, w2, h2)
         for i in range(0, 40):
-            list_win.addItem('Item %s' % i)
+            list_win.addItem("Item %s" % i)
         self.wins.append(list_win)
         self.wins.append(cui.TitledWin(0, 0, w2, h2, "Test Window 1"))
         self.wins.append(cui.TitledWin(w2, 0, w2, h2, "Test Window 2"))
@@ -52,12 +51,12 @@ def __init__(self, screen, event_queue):
         # self.wins[0].win.scrollok(1)
         # self.el = cui.CursesEditLine(self.wins[0].win, None,
         #  lambda c: callback('got', c), lambda c: callback('tab', c))
-        #self.el.prompt = '>>> '
-        #self.el.showPrompt(10, 0)
+        # self.el.prompt = '>>> '
+        # self.el.showPrompt(10, 0)
 
     def handleEvent(self, event):
         if isinstance(event, int):
-            if event == ord('q'):
+            if event == ord("q"):
                 sys.exit(0)
             # self.el.handleEvent(event)
         super(SandboxUI, self).handleEvent(event)
@@ -70,6 +69,7 @@ def main(screen):
     sandbox = SandboxUI(screen, event_queue)
     sandbox.eventLoop()
 
+
 if __name__ == "__main__":
     try:
         curses.wrapper(main)
diff --git a/lldb/utils/lui/sourcewin.py b/lldb/utils/lui/sourcewin.py
index c3add058f125eed..efe3c01f3ebd11c 100644
--- a/lldb/utils/lui/sourcewin.py
+++ b/lldb/utils/lui/sourcewin.py
@@ -15,7 +15,6 @@
 
 
 class SourceWin(cui.TitledWin):
-
     def __init__(self, driver, x, y, w, h):
         super(SourceWin, self).__init__(x, y, w, h, "Source")
         self.sourceman = driver.getSourceManager()
@@ -35,9 +34,10 @@ def __init__(self, driver, x, y, w, h):
 
         try:
             from pygments.formatters import TerminalFormatter
+
             self.formatter = TerminalFormatter()
         except ImportError:
-            #self.win.addstr("\nWarning: no 'pygments' library found. Syntax highlighting is disabled.")
+            # self.win.addstr("\nWarning: no 'pygments' library found. Syntax highlighting is disabled.")
             self.lexer = None
             self.formatter = None
             pass
@@ -55,8 +55,9 @@ def handleEvent(self, event):
             if lldb.SBBreakpoint.EventIsBreakpointEvent(event):
                 self.handleBPEvent(event)
 
-            if lldb.SBProcess.EventIsProcessEvent(event) and \
-                    not lldb.SBProcess.GetRestartedFromEvent(event):
+            if lldb.SBProcess.EventIsProcessEvent(
+                event
+            ) and not lldb.SBProcess.GetRestartedFromEvent(event):
                 process = lldb.SBProcess.GetProcessFromEvent(event)
                 if not process.IsValid():
                     return
@@ -71,8 +72,8 @@ def notifyExited(self, process):
         pid = process.GetProcessID()
         ec = process.GetExitStatus()
         self.win.addstr(
-            "\nProcess %s [%d] has exited with exit-code %d" %
-            (target, pid, ec))
+            "\nProcess %s [%d] has exited with exit-code %d" % (target, pid, ec)
+        )
 
     def pageUp(self):
         if self.viewline > 0:
@@ -100,8 +101,8 @@ def updateViewline(self):
 
         if self.viewline < 0:
             raise Exception(
-                "negative viewline: pc=%d viewline=%d" %
-                (self.pc_line, self.viewline))
+                "negative viewline: pc=%d viewline=%d" % (self.pc_line, self.viewline)
+            )
 
     def refreshSource(self, process=None):
         (self.height, self.width) = self.win.getmaxyx()
@@ -126,9 +127,14 @@ def refreshSource(self, process=None):
 
         if self.formatter is not None:
             from pygments.lexers import get_lexer_for_filename
+
             self.lexer = get_lexer_for_filename(self.filename)
 
-        bps = [] if not self.filename in self.breakpoints else self.breakpoints[self.filename]
+        bps = (
+            []
+            if not self.filename in self.breakpoints
+            else self.breakpoints[self.filename]
+        )
         self.win.erase()
         if self.content:
             self.formatContent(self.content, self.pc_line, bps)
@@ -159,7 +165,7 @@ def formatContent(self, content, pc_line, breakpoints):
                 marker = self.markerBP
             line = "%s%3d %s" % (marker, line_num, self.highlight(content[i]))
             if len(line) >= self.width:
-                line = line[0:self.width - 1] + "\n"
+                line = line[0 : self.width - 1] + "\n"
             self.win.addstr(line, attr)
             source += line
             count = count + 1
@@ -168,6 +174,7 @@ def formatContent(self, content, pc_line, breakpoints):
     def highlight(self, source):
         if self.lexer and self.formatter:
             from pygments import highlight
+
             return highlight(source, self.lexer, self.formatter)
         else:
             return source
@@ -202,9 +209,8 @@ def getLocations(event):
                 # hack! getting the LineEntry via SBBreakpointLocation.GetAddress.GetLineEntry does not work good for
                 # inlined frames, so we get the description (which does take
                 # into account inlined functions) and parse it.
-                desc = lldbutil.get_description(
-                    location, lldb.eDescriptionLevelFull)
-                match = re.search('at\ ([^:]+):([\d]+)', desc)
+                desc = lldbutil.get_description(location, lldb.eDescriptionLevelFull)
+                match = re.search("at\ ([^:]+):([\d]+)", desc)
                 try:
                     path = match.group(1)
                     line = int(match.group(2).strip())
@@ -219,20 +225,26 @@ def getLocations(event):
             return locs
 
         event_type = lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event)
-        if event_type == lldb.eBreakpointEventTypeEnabled \
-                or event_type == lldb.eBreakpointEventTypeAdded \
-                or event_type == lldb.eBreakpointEventTypeLocationsResolved \
-                or event_type == lldb.eBreakpointEventTypeLocationsAdded:
+        if (
+            event_type == lldb.eBreakpointEventTypeEnabled
+            or event_type == lldb.eBreakpointEventTypeAdded
+            or event_type == lldb.eBreakpointEventTypeLocationsResolved
+            or event_type == lldb.eBreakpointEventTypeLocationsAdded
+        ):
             self.addBPLocations(getLocations(event))
-        elif event_type == lldb.eBreakpointEventTypeRemoved \
-                or event_type == lldb.eBreakpointEventTypeLocationsRemoved \
-                or event_type == lldb.eBreakpointEventTypeDisabled:
+        elif (
+            event_type == lldb.eBreakpointEventTypeRemoved
+            or event_type == lldb.eBreakpointEventTypeLocationsRemoved
+            or event_type == lldb.eBreakpointEventTypeDisabled
+        ):
             self.removeBPLocations(getLocations(event))
-        elif event_type == lldb.eBreakpointEventTypeCommandChanged \
-                or event_type == lldb.eBreakpointEventTypeConditionChanged \
-                or event_type == lldb.eBreakpointEventTypeIgnoreChanged \
-                or event_type == lldb.eBreakpointEventTypeThreadChanged \
-                or event_type == lldb.eBreakpointEventTypeInvalidType:
+        elif (
+            event_type == lldb.eBreakpointEventTypeCommandChanged
+            or event_type == lldb.eBreakpointEventTypeConditionChanged
+            or event_type == lldb.eBreakpointEventTypeIgnoreChanged
+            or event_type == lldb.eBreakpointEventTypeThreadChanged
+            or event_type == lldb.eBreakpointEventTypeInvalidType
+        ):
             # no-op
             pass
         self.refreshSource()
diff --git a/lldb/utils/lui/statuswin.py b/lldb/utils/lui/statuswin.py
index 2d3cc217c0199d5..20f81181de43aaa 100644
--- a/lldb/utils/lui/statuswin.py
+++ b/lldb/utils/lui/statuswin.py
@@ -13,19 +13,19 @@
 
 
 class StatusWin(cui.TextWin):
-
     def __init__(self, x, y, w, h):
         super(StatusWin, self).__init__(x, y, w)
 
         self.keys = [  # ('F1', 'Help', curses.KEY_F1),
-            ('F3', 'Cycle-focus', curses.KEY_F3),
-            ('F10', 'Quit', curses.KEY_F10)]
+            ("F3", "Cycle-focus", curses.KEY_F3),
+            ("F10", "Quit", curses.KEY_F10),
+        ]
 
     def draw(self):
-        self.win.addstr(0, 0, '')
+        self.win.addstr(0, 0, "")
         for key in self.keys:
-            self.win.addstr('{0}'.format(key[0]), curses.A_REVERSE)
-            self.win.addstr(' {0} '.format(key[1]), curses.A_NORMAL)
+            self.win.addstr("{0}".format(key[0]), curses.A_REVERSE)
+            self.win.addstr(" {0} ".format(key[1]), curses.A_NORMAL)
         super(StatusWin, self).draw()
 
     def handleEvent(self, event):

>From 2ffc7471be9bb2cfd0b48a3ca6e64c1532861103 Mon Sep 17 00:00:00 2001
From: Hans <hans at hanshq.net>
Date: Thu, 14 Sep 2023 10:20:01 +0200
Subject: [PATCH 37/86] [clang] Don't inherit dllimport/dllexport to
 exclude_from_explicit_instantiation members during explicit instantiation
 (#65961)

This is a continuation of https://reviews.llvm.org/D155713

Fixes https://github.com/llvm/llvm-project/issues/40363
---
 clang/lib/Sema/SemaDeclCXX.cpp                |  7 +++
 ..._from_explicit_instantiation.dllimport.cpp | 48 +++++++++++++++++++
 ..._from_explicit_instantiation.dllimport.cpp | 27 +++++++++++
 3 files changed, 82 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp
 create mode 100644 clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 2b2b7391f88fd54..1f2bb1edd3b7be5 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -6602,6 +6602,13 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
     if (!VD && !MD)
       continue;
 
+    if ((TSK == TSK_ExplicitInstantiationDeclaration ||
+         TSK == TSK_ExplicitInstantiationDefinition) &&
+        Member->hasAttr<ExcludeFromExplicitInstantiationAttr>()) {
+      // Skip members excluded from instantiation.
+      continue;
+    }
+
     if (MD) {
       // Don't process deleted methods.
       if (MD->isDeleted())
diff --git a/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp b/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp
new file mode 100644
index 000000000000000..b3c804839be1ee4
--- /dev/null
+++ b/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-windows -fms-extensions -emit-llvm -O0 -o - %s | FileCheck %s
+
+// Test that dllimport and exclude_from_explicit_instantiation work properly
+// together. Specifically, we check that when exclude_from_explicit_instantiation
+// is used on a method, the compiler doesn't expect it to be provided externally
+// even if it is marked with dllimport.
+//
+// https://github.com/llvm/llvm-project/issues/40363
+
+#define DLLIMPORT __declspec(dllimport)
+#define DLLEXPORT __declspec(dllexport)
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))
+
+template <class T>
+struct DLLIMPORT Foo {
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void x() {}
+};
+
+template <class T>
+struct Bar {
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void x() {}
+};
+
+extern template struct Foo<int>;
+extern template struct DLLIMPORT Bar<int>;
+
+
+template <class T>
+struct Baz {
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void f() {}
+};
+
+template struct DLLEXPORT Baz<int>;
+
+
+void test(Foo<int>& foo, Bar<int>& bar, Baz<int>& baz) {
+  // Not imported.
+  // CHECK-DAG: define linkonce_odr dso_local void @"?x@?$Foo at H@@QEAAXXZ"
+  foo.x();
+
+  // Not imported.
+  // CHECK-DAG: define linkonce_odr dso_local void @"?x@?$Bar at H@@QEAAXXZ"
+  bar.x();
+
+  // Not exported.
+  // CHECK-DAG: define linkonce_odr dso_local void @"?f@?$Baz at H@@QEAAXXZ"
+  baz.f();
+}
diff --git a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp
new file mode 100644
index 000000000000000..bdca2d8895f516c
--- /dev/null
+++ b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-windows -fms-extensions -verify %s
+
+// Test that an entity marked as both dllimport and exclude_from_explicit_instantiation
+// isn't instantiated.
+
+#define DLLIMPORT __declspec(dllimport)
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))
+
+template <class T>
+struct DLLIMPORT Foo {
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void x();
+};
+
+template <class T>
+struct Bar {
+  DLLIMPORT EXCLUDE_FROM_EXPLICIT_INSTANTIATION inline void x();
+};
+
+template <class T>
+void Foo<T>::x() { using Fail = typename T::fail; }
+
+template <class T>
+DLLIMPORT inline void Bar<T>::x() { using Fail = typename T::fail; }
+
+// expected-no-diagnostics
+template struct Foo<int>;
+template struct Bar<int>;

>From 5d2821dde27175a42a5c4f2ff261422d746a1b2e Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Thu, 14 Sep 2023 10:28:43 +0200
Subject: [PATCH 38/86] [libc][utils] cpp::always_false to enable
 static_assert(false) (#66209)

---
 libc/src/__support/CPP/CMakeLists.txt         |  1 +
 .../__support/CPP/type_traits/always_false.h  | 29 +++++++++++++++++++
 libc/src/__support/CPP/utility/declval.h      |  8 ++---
 .../llvm-project-overlay/libc/BUILD.bazel     |  1 +
 4 files changed, 33 insertions(+), 6 deletions(-)
 create mode 100644 libc/src/__support/CPP/type_traits/always_false.h

diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt
index d24c023ec28ebc9..4e3e4a3edf381d2 100644
--- a/libc/src/__support/CPP/CMakeLists.txt
+++ b/libc/src/__support/CPP/CMakeLists.txt
@@ -95,6 +95,7 @@ add_header_library(
   type_traits
   HDRS
     type_traits.h
+    type_traits/always_false.h
     type_traits/add_lvalue_reference.h
     type_traits/add_pointer.h
     type_traits/add_rvalue_reference.h
diff --git a/libc/src/__support/CPP/type_traits/always_false.h b/libc/src/__support/CPP/type_traits/always_false.h
new file mode 100644
index 000000000000000..5e3a51479e3d259
--- /dev/null
+++ b/libc/src/__support/CPP/type_traits/always_false.h
@@ -0,0 +1,29 @@
+//===-- convenient static_assert(false) helper ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_ALWAYS_FALSE_H
+#define LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_ALWAYS_FALSE_H
+
+#include "src/__support/macros/attributes.h"
+
+namespace __llvm_libc::cpp {
+
+// This is technically not part of the standard but it come often enough that
+// it's convenient to have around.
+//
+// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2593r0.html#valid-workaround
+//
+// This will be fixed in C++23 according to [CWG
+// 2518](https://cplusplus.github.io/CWG/issues/2518.html).
+
+// Usage `static_assert(cpp::always_false<T>, "error message");`
+template <typename...> LIBC_INLINE_VAR constexpr bool always_false = false;
+
+} // namespace __llvm_libc::cpp
+
+#endif // LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_ALWAYS_FALSE_H
diff --git a/libc/src/__support/CPP/utility/declval.h b/libc/src/__support/CPP/utility/declval.h
index 9261ceb9332d518..21bb973de0dd048 100644
--- a/libc/src/__support/CPP/utility/declval.h
+++ b/libc/src/__support/CPP/utility/declval.h
@@ -9,17 +9,13 @@
 #define LLVM_LIBC_SRC_SUPPORT_CPP_UTILITY_DECLVAL_H
 
 #include "src/__support/CPP/type_traits/add_rvalue_reference.h"
-#include "src/__support/macros/attributes.h"
+#include "src/__support/CPP/type_traits/always_false.h"
 
 namespace __llvm_libc::cpp {
 
 // declval
-namespace detail {
-template <typename T> LIBC_INLINE_VAR constexpr bool always_false = false;
-}
-
 template <typename T> cpp::add_rvalue_reference_t<T> declval() {
-  static_assert(detail::always_false<T>,
+  static_assert(cpp::always_false<T>,
                 "declval not allowed in an evaluated context");
 }
 
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 17e4913749d51c6..160998049fcd2a8 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -289,6 +289,7 @@ libc_support_library(
         "src/__support/CPP/type_traits/add_lvalue_reference.h",
         "src/__support/CPP/type_traits/add_pointer.h",
         "src/__support/CPP/type_traits/add_rvalue_reference.h",
+        "src/__support/CPP/type_traits/always_false.h",
         "src/__support/CPP/type_traits/bool_constant.h",
         "src/__support/CPP/type_traits/conditional.h",
         "src/__support/CPP/type_traits/decay.h",

>From b9b08539487fb5803d70d4ad52993a8f10741082 Mon Sep 17 00:00:00 2001
From: vic <victor.perez at codeplay.com>
Date: Thu, 14 Sep 2023 10:30:40 +0200
Subject: [PATCH 39/86] [mlir] Allow loop-like operations in
 `AbstractDenseForwardDataFlowAnalysis` (#66179)

Remove assertion violated by loop-like operations.

Signed-off-by: Victor Perez <victor.perez at codeplay.com>
---
 mlir/lib/Analysis/DataFlow/DenseAnalysis.cpp  |   2 -
 .../Analysis/DataFlow/test-last-modified.mlir | 119 ++++++++++++++++++
 .../TestDenseForwardDataFlowAnalysis.cpp      |  24 ++--
 mlir/test/lib/Dialect/Test/TestDialect.cpp    |  10 ++
 mlir/test/lib/Dialect/Test/TestOps.td         |  12 ++
 5 files changed, 156 insertions(+), 11 deletions(-)

diff --git a/mlir/lib/Analysis/DataFlow/DenseAnalysis.cpp b/mlir/lib/Analysis/DataFlow/DenseAnalysis.cpp
index eab408cd5977c3a..5e75883e61468ec 100644
--- a/mlir/lib/Analysis/DataFlow/DenseAnalysis.cpp
+++ b/mlir/lib/Analysis/DataFlow/DenseAnalysis.cpp
@@ -199,8 +199,6 @@ void AbstractDenseForwardDataFlowAnalysis::visitRegionBranchOperation(
         op == branch ? std::optional<unsigned>()
                      : op->getBlock()->getParent()->getRegionNumber();
     if (auto *toBlock = point.dyn_cast<Block *>()) {
-      assert(op == branch ||
-             toBlock->getParent() != op->getBlock()->getParent());
       unsigned regionTo = toBlock->getParent()->getRegionNumber();
       visitRegionBranchControlFlowTransfer(branch, regionFrom, regionTo,
                                            *before, after);
diff --git a/mlir/test/Analysis/DataFlow/test-last-modified.mlir b/mlir/test/Analysis/DataFlow/test-last-modified.mlir
index 069cbbcc0cc1684..43326614d67933c 100644
--- a/mlir/test/Analysis/DataFlow/test-last-modified.mlir
+++ b/mlir/test/Analysis/DataFlow/test-last-modified.mlir
@@ -229,3 +229,122 @@ func.func @store_with_a_region_after_containing_a_store(%arg0: memref<f32>) -> m
   memref.store %1, %arg0[] {tag_name = "post"} : memref<f32>
   return {tag = "return"} %arg0 : memref<f32>
 }
+
+// CHECK-LABEL: test_tag: store_with_a_loop_region_before::before:
+// CHECK:  operand #0
+// CHECK:   - pre
+// CHECK: test_tag: inside_region:
+// CHECK:  operand #0
+// CHECK:   - region
+// CHECK: test_tag: after:
+// CHECK:  operand #0
+// CHECK:   - region
+// CHECK: test_tag: return:
+// CHECK:  operand #0
+// CHECK:   - post
+func.func @store_with_a_loop_region_before(%arg0: memref<f32>) -> memref<f32> {
+  %0 = arith.constant 0.0 : f32
+  %1 = arith.constant 1.0 : f32
+  memref.store %0, %arg0[] {tag_name = "pre"} : memref<f32>
+  memref.load %arg0[] {tag = "store_with_a_loop_region_before::before"} : memref<f32>
+  test.store_with_a_loop_region %arg0 attributes { tag_name = "region", store_before_region = true } {
+    memref.load %arg0[] {tag = "inside_region"} : memref<f32>
+    test.store_with_a_region_terminator
+  } : memref<f32>
+  memref.load %arg0[] {tag = "after"} : memref<f32>
+  memref.store %1, %arg0[] {tag_name = "post"} : memref<f32>
+  return {tag = "return"} %arg0 : memref<f32>
+}
+
+// CHECK-LABEL: test_tag: store_with_a_loop_region_after::before:
+// CHECK:  operand #0
+// CHECK:   - pre
+// CHECK: test_tag: inside_region:
+// CHECK:  operand #0
+// CHECK:   - pre
+// CHECK: test_tag: after:
+// CHECK:  operand #0
+// CHECK:   - region
+// CHECK: test_tag: return:
+// CHECK:  operand #0
+// CHECK:   - post
+func.func @store_with_a_loop_region_after(%arg0: memref<f32>) -> memref<f32> {
+  %0 = arith.constant 0.0 : f32
+  %1 = arith.constant 1.0 : f32
+  memref.store %0, %arg0[] {tag_name = "pre"} : memref<f32>
+  memref.load %arg0[] {tag = "store_with_a_loop_region_after::before"} : memref<f32>
+  test.store_with_a_loop_region %arg0 attributes { tag_name = "region", store_before_region = false } {
+    memref.load %arg0[] {tag = "inside_region"} : memref<f32>
+    test.store_with_a_region_terminator
+  } : memref<f32>
+  memref.load %arg0[] {tag = "after"} : memref<f32>
+  memref.store %1, %arg0[] {tag_name = "post"} : memref<f32>
+  return {tag = "return"} %arg0 : memref<f32>
+}
+
+// CHECK-LABEL:     test_tag: store_with_a_loop_region_before_containing_a_store::before:
+// CHECK:      operand #0
+// CHECK:       - pre
+// CHECK:     test_tag: enter_region:
+// CHECK:      operand #0
+// CHECK-DAG:   - region
+// CHECK-DAG:   - inner
+// CHECK:     test_tag: exit_region:
+// CHECK:      operand #0
+// CHECK:       - inner
+// CHECK:     test_tag: after:
+// CHECK:      operand #0
+// CHECK-DAG:   - region
+// CHECK-DAG:   - inner
+// CHECK:     test_tag: return:
+// CHECK:      operand #0
+// CHECK:       - post
+func.func @store_with_a_loop_region_before_containing_a_store(%arg0: memref<f32>) -> memref<f32> {
+  %0 = arith.constant 0.0 : f32
+  %1 = arith.constant 1.0 : f32
+  memref.store %0, %arg0[] {tag_name = "pre"} : memref<f32>
+  memref.load %arg0[] {tag = "store_with_a_loop_region_before_containing_a_store::before"} : memref<f32>
+  test.store_with_a_loop_region %arg0 attributes { tag_name = "region", store_before_region = true } {
+    memref.load %arg0[] {tag = "enter_region"} : memref<f32>
+    %2 = arith.constant 2.0 : f32
+    memref.store %2, %arg0[] {tag_name = "inner"} : memref<f32>
+    memref.load %arg0[] {tag = "exit_region"} : memref<f32>
+    test.store_with_a_region_terminator
+  } : memref<f32>
+  memref.load %arg0[] {tag = "after"} : memref<f32>
+  memref.store %1, %arg0[] {tag_name = "post"} : memref<f32>
+  return {tag = "return"} %arg0 : memref<f32>
+}
+
+// CHECK-LABEL:     test_tag: store_with_a_loop_region_after_containing_a_store::before:
+// CHECK:      operand #0
+// CHECK:       - pre
+// CHECK:     test_tag: enter_region:
+// CHECK:      operand #0
+// CHECK-DAG:   - pre
+// CHECK-DAG:   - inner
+// CHECK:     test_tag: exit_region:
+// CHECK:      operand #0
+// CHECK:       - inner
+// CHECK:     test_tag: after:
+// CHECK:      operand #0
+// CHECK:       - region
+// CHECK:     test_tag: return:
+// CHECK:      operand #0
+// CHECK:       - post
+func.func @store_with_a_loop_region_after_containing_a_store(%arg0: memref<f32>) -> memref<f32> {
+  %0 = arith.constant 0.0 : f32
+  %1 = arith.constant 1.0 : f32
+  memref.store %0, %arg0[] {tag_name = "pre"} : memref<f32>
+  memref.load %arg0[] {tag = "store_with_a_loop_region_after_containing_a_store::before"} : memref<f32>
+  test.store_with_a_loop_region %arg0 attributes { tag_name = "region", store_before_region = false } {
+    memref.load %arg0[] {tag = "enter_region"} : memref<f32>
+    %2 = arith.constant 2.0 : f32
+    memref.store %2, %arg0[] {tag_name = "inner"} : memref<f32>
+    memref.load %arg0[] {tag = "exit_region"} : memref<f32>
+    test.store_with_a_region_terminator
+  } : memref<f32>
+  memref.load %arg0[] {tag = "after"} : memref<f32>
+  memref.store %1, %arg0[] {tag_name = "post"} : memref<f32>
+  return {tag = "return"} %arg0 : memref<f32>
+}
diff --git a/mlir/test/lib/Analysis/DataFlow/TestDenseForwardDataFlowAnalysis.cpp b/mlir/test/lib/Analysis/DataFlow/TestDenseForwardDataFlowAnalysis.cpp
index 1a21719a44b994f..2520ed3d83b9efa 100644
--- a/mlir/test/lib/Analysis/DataFlow/TestDenseForwardDataFlowAnalysis.cpp
+++ b/mlir/test/lib/Analysis/DataFlow/TestDenseForwardDataFlowAnalysis.cpp
@@ -17,6 +17,8 @@
 #include "mlir/Analysis/DataFlow/DenseAnalysis.h"
 #include "mlir/Interfaces/SideEffectInterfaces.h"
 #include "mlir/Pass/Pass.h"
+#include "mlir/Support/LLVM.h"
+#include "llvm/ADT/TypeSwitch.h"
 #include <optional>
 
 using namespace mlir;
@@ -133,15 +135,19 @@ void LastModifiedAnalysis::visitRegionBranchControlFlowTransfer(
     RegionBranchOpInterface branch, std::optional<unsigned> regionFrom,
     std::optional<unsigned> regionTo, const LastModification &before,
     LastModification *after) {
-  auto testStoreWithARegion =
-      dyn_cast<::test::TestStoreWithARegion>(branch.getOperation());
-  if (testStoreWithARegion &&
-      ((!regionTo && !testStoreWithARegion.getStoreBeforeRegion()) ||
-       (!regionFrom && testStoreWithARegion.getStoreBeforeRegion()))) {
-    return visitOperation(branch, before, after);
-  }
-  AbstractDenseForwardDataFlowAnalysis::visitRegionBranchControlFlowTransfer(
-      branch, regionFrom, regionTo, before, after);
+  auto defaultHandling = [&]() {
+    AbstractDenseForwardDataFlowAnalysis::visitRegionBranchControlFlowTransfer(
+        branch, regionFrom, regionTo, before, after);
+  };
+  TypeSwitch<Operation *>(branch.getOperation())
+      .Case<::test::TestStoreWithARegion, ::test::TestStoreWithALoopRegion>(
+          [=](auto storeWithRegion) {
+            if ((!regionTo && !storeWithRegion.getStoreBeforeRegion()) ||
+                (!regionFrom && storeWithRegion.getStoreBeforeRegion()))
+              visitOperation(branch, before, after);
+            defaultHandling();
+          })
+      .Default([=](auto) { defaultHandling(); });
 }
 
 namespace {
diff --git a/mlir/test/lib/Dialect/Test/TestDialect.cpp b/mlir/test/lib/Dialect/Test/TestDialect.cpp
index e5fc97dafae9bb7..00c251936655d71 100644
--- a/mlir/test/lib/Dialect/Test/TestDialect.cpp
+++ b/mlir/test/lib/Dialect/Test/TestDialect.cpp
@@ -1315,6 +1315,16 @@ void TestStoreWithARegion::getSuccessorRegions(
     regions.emplace_back();
 }
 
+void TestStoreWithALoopRegion::getSuccessorRegions(
+    RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> &regions) {
+  // Both the operation itself and the region may be branching into the body or
+  // back into the operation itself. It is possible for the operation not to
+  // enter the body.
+  regions.emplace_back(
+      RegionSuccessor(&getBody(), getBody().front().getArguments()));
+  regions.emplace_back();
+}
+
 LogicalResult
 TestVersionedOpA::readProperties(::mlir::DialectBytecodeReader &reader,
                                  ::mlir::OperationState &state) {
diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td
index 9ceadab8fa4a086..0aa8ce4de9756fa 100644
--- a/mlir/test/lib/Dialect/Test/TestOps.td
+++ b/mlir/test/lib/Dialect/Test/TestOps.td
@@ -2953,6 +2953,18 @@ def TestStoreWithARegion : TEST_Op<"store_with_a_region",
     "$address attr-dict-with-keyword regions `:` type($address)";
 }
 
+def TestStoreWithALoopRegion : TEST_Op<"store_with_a_loop_region",
+    [DeclareOpInterfaceMethods<RegionBranchOpInterface>,
+     SingleBlock]> {
+  let arguments = (ins
+    Arg<AnyMemRef, "", [MemWrite]>:$address,
+    BoolAttr:$store_before_region
+  );
+  let regions = (region AnyRegion:$body);
+  let assemblyFormat =
+    "$address attr-dict-with-keyword regions `:` type($address)";
+}
+
 def TestStoreWithARegionTerminator : TEST_Op<"store_with_a_region_terminator",
     [ReturnLike, Terminator, NoMemoryEffect]> {
   let assemblyFormat = "attr-dict";

>From adf9b08acbbc9b08a7e91d6c1e7cb06c22cf4aab Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Thu, 14 Sep 2023 09:36:03 +0100
Subject: [PATCH 40/86] [AArch64] Add LRINT/LLRINT/LROUND/LLROUND FP16 lowering
 without fullfp16 (#66174)

We apparently somehow had lowering for the STRICT nodes without any handling
for the normal operations. This makes sure we support the LRINT and LROUND
intrinsics for fp16 when +fullfp16 is not present.
---
 .../Target/AArch64/AArch64ISelLowering.cpp    | 13 ++++-
 llvm/test/CodeGen/AArch64/llrint-conv-fp16.ll | 56 ++++++++++++++-----
 .../test/CodeGen/AArch64/llround-conv-fp16.ll | 47 ++++++++++++----
 llvm/test/CodeGen/AArch64/lrint-conv-fp16.ll  | 56 ++++++++++++++-----
 llvm/test/CodeGen/AArch64/lround-conv-fp16.ll | 47 ++++++++++++----
 5 files changed, 172 insertions(+), 47 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index fbadda1a8fd446d..b706f61ac75983e 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -707,7 +707,8 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
 
     // Round-to-integer need custom lowering for fp16, as Promote doesn't work
     // because the result type is integer.
-    for (auto Op : {ISD::STRICT_LROUND, ISD::STRICT_LLROUND, ISD::STRICT_LRINT,
+    for (auto Op : {ISD::LROUND, ISD::LLROUND, ISD::LRINT, ISD::LLRINT,
+                    ISD::STRICT_LROUND, ISD::STRICT_LLROUND, ISD::STRICT_LRINT,
                     ISD::STRICT_LLRINT})
       setOperationAction(Op, MVT::f16, Custom);
 
@@ -6185,6 +6186,16 @@ SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
     return LowerVECTOR_DEINTERLEAVE(Op, DAG);
   case ISD::VECTOR_INTERLEAVE:
     return LowerVECTOR_INTERLEAVE(Op, DAG);
+  case ISD::LROUND:
+  case ISD::LLROUND:
+  case ISD::LRINT:
+  case ISD::LLRINT: {
+    assert(Op.getOperand(0).getValueType() == MVT::f16 &&
+           "Expected custom lowering of rounding operations only for f16");
+    SDLoc DL(Op);
+    SDValue Ext = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Op.getOperand(0));
+    return DAG.getNode(Op.getOpcode(), DL, Op.getValueType(), Ext);
+  }
   case ISD::STRICT_LROUND:
   case ISD::STRICT_LLROUND:
   case ISD::STRICT_LRINT:
diff --git a/llvm/test/CodeGen/AArch64/llrint-conv-fp16.ll b/llvm/test/CodeGen/AArch64/llrint-conv-fp16.ll
index 366c337b59f6e32..1adbbab76abf52c 100644
--- a/llvm/test/CodeGen/AArch64/llrint-conv-fp16.ll
+++ b/llvm/test/CodeGen/AArch64/llrint-conv-fp16.ll
@@ -1,32 +1,62 @@
-; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK-NOFP16
+; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 | FileCheck %s --check-prefixes=CHECK-FP16
 
-; CHECK-LABEL: testmhhs:
-; CHECK:       frintx  h0, h0
-; CHECK-NEXT:  fcvtzs  x0, h0
-; CHECK:       ret
 define i16 @testmhhs(half %x) {
+; CHECK-NOFP16-LABEL: testmhhs:
+; CHECK-NOFP16:       // %bb.0: // %entry
+; CHECK-NOFP16-NEXT:    fcvt s0, h0
+; CHECK-NOFP16-NEXT:    frintx s0, s0
+; CHECK-NOFP16-NEXT:    fcvtzs x0, s0
+; CHECK-NOFP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-NOFP16-NEXT:    ret
+;
+; CHECK-FP16-LABEL: testmhhs:
+; CHECK-FP16:       // %bb.0: // %entry
+; CHECK-FP16-NEXT:    frintx h0, h0
+; CHECK-FP16-NEXT:    fcvtzs x0, h0
+; CHECK-FP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-FP16-NEXT:    ret
 entry:
   %0 = tail call i64 @llvm.llrint.i64.f16(half %x)
   %conv = trunc i64 %0 to i16
   ret i16 %conv
 }
 
-; CHECK-LABEL: testmhws:
-; CHECK:       frintx  h0, h0
-; CHECK-NEXT:  fcvtzs  x0, h0
-; CHECK:       ret
 define i32 @testmhws(half %x) {
+; CHECK-NOFP16-LABEL: testmhws:
+; CHECK-NOFP16:       // %bb.0: // %entry
+; CHECK-NOFP16-NEXT:    fcvt s0, h0
+; CHECK-NOFP16-NEXT:    frintx s0, s0
+; CHECK-NOFP16-NEXT:    fcvtzs x0, s0
+; CHECK-NOFP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-NOFP16-NEXT:    ret
+;
+; CHECK-FP16-LABEL: testmhws:
+; CHECK-FP16:       // %bb.0: // %entry
+; CHECK-FP16-NEXT:    frintx h0, h0
+; CHECK-FP16-NEXT:    fcvtzs x0, h0
+; CHECK-FP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-FP16-NEXT:    ret
 entry:
   %0 = tail call i64 @llvm.llrint.i64.f16(half %x)
   %conv = trunc i64 %0 to i32
   ret i32 %conv
 }
 
-; CHECK-LABEL: testmhxs:
-; CHECK:       frintx  h0, h0
-; CHECK-NEXT:  fcvtzs  x0, h0
-; CHECK:       ret
 define i64 @testmhxs(half %x) {
+; CHECK-NOFP16-LABEL: testmhxs:
+; CHECK-NOFP16:       // %bb.0: // %entry
+; CHECK-NOFP16-NEXT:    fcvt s0, h0
+; CHECK-NOFP16-NEXT:    frintx s0, s0
+; CHECK-NOFP16-NEXT:    fcvtzs x0, s0
+; CHECK-NOFP16-NEXT:    ret
+;
+; CHECK-FP16-LABEL: testmhxs:
+; CHECK-FP16:       // %bb.0: // %entry
+; CHECK-FP16-NEXT:    frintx h0, h0
+; CHECK-FP16-NEXT:    fcvtzs x0, h0
+; CHECK-FP16-NEXT:    ret
 entry:
   %0 = tail call i64 @llvm.llrint.i64.f16(half %x)
   ret i64 %0
diff --git a/llvm/test/CodeGen/AArch64/llround-conv-fp16.ll b/llvm/test/CodeGen/AArch64/llround-conv-fp16.ll
index 5c914c093610198..4bf65e7d6fd088c 100644
--- a/llvm/test/CodeGen/AArch64/llround-conv-fp16.ll
+++ b/llvm/test/CodeGen/AArch64/llround-conv-fp16.ll
@@ -1,29 +1,56 @@
-; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK-NOFP16
+; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 | FileCheck %s --check-prefixes=CHECK-FP16
 
-; CHECK-LABEL: testmhhs:
-; CHECK:       fcvtas  x0, h0
-; CHECK:       ret
 define i16 @testmhhs(half %x) {
+; CHECK-NOFP16-LABEL: testmhhs:
+; CHECK-NOFP16:       // %bb.0: // %entry
+; CHECK-NOFP16-NEXT:    fcvt s0, h0
+; CHECK-NOFP16-NEXT:    fcvtas x0, s0
+; CHECK-NOFP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-NOFP16-NEXT:    ret
+;
+; CHECK-FP16-LABEL: testmhhs:
+; CHECK-FP16:       // %bb.0: // %entry
+; CHECK-FP16-NEXT:    fcvtas x0, h0
+; CHECK-FP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-FP16-NEXT:    ret
 entry:
   %0 = tail call i64 @llvm.llround.i64.f16(half %x)
   %conv = trunc i64 %0 to i16
   ret i16 %conv
 }
 
-; CHECK-LABEL: testmhws:
-; CHECK:       fcvtas  x0, h0
-; CHECK:       ret
 define i32 @testmhws(half %x) {
+; CHECK-NOFP16-LABEL: testmhws:
+; CHECK-NOFP16:       // %bb.0: // %entry
+; CHECK-NOFP16-NEXT:    fcvt s0, h0
+; CHECK-NOFP16-NEXT:    fcvtas x0, s0
+; CHECK-NOFP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-NOFP16-NEXT:    ret
+;
+; CHECK-FP16-LABEL: testmhws:
+; CHECK-FP16:       // %bb.0: // %entry
+; CHECK-FP16-NEXT:    fcvtas x0, h0
+; CHECK-FP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-FP16-NEXT:    ret
 entry:
   %0 = tail call i64 @llvm.llround.i64.f16(half %x)
   %conv = trunc i64 %0 to i32
   ret i32 %conv
 }
 
-; CHECK-LABEL: testmhxs:
-; CHECK:       fcvtas  x0, h0
-; CHECK-NEXT:  ret
 define i64 @testmhxs(half %x) {
+; CHECK-NOFP16-LABEL: testmhxs:
+; CHECK-NOFP16:       // %bb.0: // %entry
+; CHECK-NOFP16-NEXT:    fcvt s0, h0
+; CHECK-NOFP16-NEXT:    fcvtas x0, s0
+; CHECK-NOFP16-NEXT:    ret
+;
+; CHECK-FP16-LABEL: testmhxs:
+; CHECK-FP16:       // %bb.0: // %entry
+; CHECK-FP16-NEXT:    fcvtas x0, h0
+; CHECK-FP16-NEXT:    ret
 entry:
   %0 = tail call i64 @llvm.llround.i64.f16(half %x)
   ret i64 %0
diff --git a/llvm/test/CodeGen/AArch64/lrint-conv-fp16.ll b/llvm/test/CodeGen/AArch64/lrint-conv-fp16.ll
index d812e2f585bce4f..7557ceac1212f78 100644
--- a/llvm/test/CodeGen/AArch64/lrint-conv-fp16.ll
+++ b/llvm/test/CodeGen/AArch64/lrint-conv-fp16.ll
@@ -1,32 +1,62 @@
-; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK-NOFP16
+; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 | FileCheck %s --check-prefixes=CHECK-FP16
 
-; CHECK-LABEL: testmhhs:
-; CHECK:       frintx  h0, h0
-; CHECK-NEXT:  fcvtzs  x0, h0
-; CHECK:       ret
 define i16 @testmhhs(half %x) {
+; CHECK-NOFP16-LABEL: testmhhs:
+; CHECK-NOFP16:       // %bb.0: // %entry
+; CHECK-NOFP16-NEXT:    fcvt s0, h0
+; CHECK-NOFP16-NEXT:    frintx s0, s0
+; CHECK-NOFP16-NEXT:    fcvtzs x0, s0
+; CHECK-NOFP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-NOFP16-NEXT:    ret
+;
+; CHECK-FP16-LABEL: testmhhs:
+; CHECK-FP16:       // %bb.0: // %entry
+; CHECK-FP16-NEXT:    frintx h0, h0
+; CHECK-FP16-NEXT:    fcvtzs x0, h0
+; CHECK-FP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-FP16-NEXT:    ret
 entry:
   %0 = tail call i64 @llvm.lrint.i64.f16(half %x)
   %conv = trunc i64 %0 to i16
   ret i16 %conv
 }
 
-; CHECK-LABEL: testmhws:
-; CHECK:       frintx  h0, h0
-; CHECK-NEXT:  fcvtzs  x0, h0
-; CHECK:       ret
 define i32 @testmhws(half %x) {
+; CHECK-NOFP16-LABEL: testmhws:
+; CHECK-NOFP16:       // %bb.0: // %entry
+; CHECK-NOFP16-NEXT:    fcvt s0, h0
+; CHECK-NOFP16-NEXT:    frintx s0, s0
+; CHECK-NOFP16-NEXT:    fcvtzs x0, s0
+; CHECK-NOFP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-NOFP16-NEXT:    ret
+;
+; CHECK-FP16-LABEL: testmhws:
+; CHECK-FP16:       // %bb.0: // %entry
+; CHECK-FP16-NEXT:    frintx h0, h0
+; CHECK-FP16-NEXT:    fcvtzs x0, h0
+; CHECK-FP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-FP16-NEXT:    ret
 entry:
   %0 = tail call i64 @llvm.lrint.i64.f16(half %x)
   %conv = trunc i64 %0 to i32
   ret i32 %conv
 }
 
-; CHECK-LABEL: testmhxs:
-; CHECK:       frintx  h0, h0
-; CHECK-NEXT:  fcvtzs  x0, h0
-; CHECK:       ret
 define i64 @testmhxs(half %x) {
+; CHECK-NOFP16-LABEL: testmhxs:
+; CHECK-NOFP16:       // %bb.0: // %entry
+; CHECK-NOFP16-NEXT:    fcvt s0, h0
+; CHECK-NOFP16-NEXT:    frintx s0, s0
+; CHECK-NOFP16-NEXT:    fcvtzs x0, s0
+; CHECK-NOFP16-NEXT:    ret
+;
+; CHECK-FP16-LABEL: testmhxs:
+; CHECK-FP16:       // %bb.0: // %entry
+; CHECK-FP16-NEXT:    frintx h0, h0
+; CHECK-FP16-NEXT:    fcvtzs x0, h0
+; CHECK-FP16-NEXT:    ret
 entry:
   %0 = tail call i64 @llvm.lrint.i64.f16(half %x)
   ret i64 %0
diff --git a/llvm/test/CodeGen/AArch64/lround-conv-fp16.ll b/llvm/test/CodeGen/AArch64/lround-conv-fp16.ll
index cf81047f65ec923..bf78fd456eac0ed 100644
--- a/llvm/test/CodeGen/AArch64/lround-conv-fp16.ll
+++ b/llvm/test/CodeGen/AArch64/lround-conv-fp16.ll
@@ -1,29 +1,56 @@
-; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK-NOFP16
+; RUN: llc < %s -mtriple=aarch64 -mattr=+fullfp16 | FileCheck %s --check-prefixes=CHECK-FP16
 
-; CHECK-LABEL: testmhhs:
-; CHECK:       fcvtas  x0, h0
-; CHECK:       ret
 define i16 @testmhhs(half %x) {
+; CHECK-NOFP16-LABEL: testmhhs:
+; CHECK-NOFP16:       // %bb.0: // %entry
+; CHECK-NOFP16-NEXT:    fcvt s0, h0
+; CHECK-NOFP16-NEXT:    fcvtas x0, s0
+; CHECK-NOFP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-NOFP16-NEXT:    ret
+;
+; CHECK-FP16-LABEL: testmhhs:
+; CHECK-FP16:       // %bb.0: // %entry
+; CHECK-FP16-NEXT:    fcvtas x0, h0
+; CHECK-FP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-FP16-NEXT:    ret
 entry:
   %0 = tail call i64 @llvm.lround.i64.f16(half %x)
   %conv = trunc i64 %0 to i16
   ret i16 %conv
 }
 
-; CHECK-LABEL: testmhws:
-; CHECK:       fcvtas  x0, h0
-; CHECK:       ret
 define i32 @testmhws(half %x) {
+; CHECK-NOFP16-LABEL: testmhws:
+; CHECK-NOFP16:       // %bb.0: // %entry
+; CHECK-NOFP16-NEXT:    fcvt s0, h0
+; CHECK-NOFP16-NEXT:    fcvtas x0, s0
+; CHECK-NOFP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-NOFP16-NEXT:    ret
+;
+; CHECK-FP16-LABEL: testmhws:
+; CHECK-FP16:       // %bb.0: // %entry
+; CHECK-FP16-NEXT:    fcvtas x0, h0
+; CHECK-FP16-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-FP16-NEXT:    ret
 entry:
   %0 = tail call i64 @llvm.lround.i64.f16(half %x)
   %conv = trunc i64 %0 to i32
   ret i32 %conv
 }
 
-; CHECK-LABEL: testmhxs:
-; CHECK:       fcvtas  x0, h0
-; CHECK-NEXT:  ret
 define i64 @testmhxs(half %x) {
+; CHECK-NOFP16-LABEL: testmhxs:
+; CHECK-NOFP16:       // %bb.0: // %entry
+; CHECK-NOFP16-NEXT:    fcvt s0, h0
+; CHECK-NOFP16-NEXT:    fcvtas x0, s0
+; CHECK-NOFP16-NEXT:    ret
+;
+; CHECK-FP16-LABEL: testmhxs:
+; CHECK-FP16:       // %bb.0: // %entry
+; CHECK-FP16-NEXT:    fcvtas x0, h0
+; CHECK-FP16-NEXT:    ret
 entry:
   %0 = tail call i64 @llvm.lround.i64.f16(half %x)
   ret i64 %0

>From e8e02e2064e1da404dc128b84cbd8fcb8dba0fdf Mon Sep 17 00:00:00 2001
From: Benjamin Kramer <benny.kra at googlemail.com>
Date: Thu, 14 Sep 2023 10:58:59 +0200
Subject: [PATCH 41/86] Add GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST to
 gwp_asan unittests

This keeps it working after the gtest update in a866ce789eb99da4d7a486eeb60a53be6c75f4fd
---
 compiler-rt/lib/gwp_asan/tests/harness.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/compiler-rt/lib/gwp_asan/tests/harness.cpp b/compiler-rt/lib/gwp_asan/tests/harness.cpp
index 4633d3ec6e9edf1..7ed408bedc2c3c3 100644
--- a/compiler-rt/lib/gwp_asan/tests/harness.cpp
+++ b/compiler-rt/lib/gwp_asan/tests/harness.cpp
@@ -55,7 +55,9 @@ INSTANTIATE_TEST_SUITE_P(RecoverableAndNonRecoverableTests,
 #else
 INSTANTIATE_TEST_SUITE_P(RecoverableTests, BacktraceGuardedPoolAllocator,
                          /* Recoverable */ testing::Values(true));
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BacktraceGuardedPoolAllocator);
 INSTANTIATE_TEST_SUITE_P(RecoverableAndNonRecoverableTests,
                          BacktraceGuardedPoolAllocatorDeathTest,
                          /* Recoverable */ testing::Bool());
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BacktraceGuardedPoolAllocatorDeathTest);
 #endif

>From b6ab4cd1fc4403fe9ef9cd7f24e27eb1a2feaad8 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Thu, 14 Sep 2023 10:24:26 +0100
Subject: [PATCH 42/86] [clang][bpf] Fix invalid RUN lines in stack protector
 warning test (#65251)

2 of them were missing the ":" on the end.

Adding them broke the test so I had to add a new prefix just for the
warning runs only.

I manually checked the first RUNs and there is no warning emitted, as
expected.
---
 clang/test/CodeGen/bpf-stack-protector.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/test/CodeGen/bpf-stack-protector.c b/clang/test/CodeGen/bpf-stack-protector.c
index c17af890eac239a..f79a49e6aa686df 100644
--- a/clang/test/CodeGen/bpf-stack-protector.c
+++ b/clang/test/CodeGen/bpf-stack-protector.c
@@ -1,16 +1,16 @@
 // REQUIRES: bpf-registered-target
 
-// RUN %clang -target bpf -S -emit-llvm -o - %s -fno-stack-protector 2>&1 \
-// RUN        | FileCheck -check-prefix=OFF -check-prefix=COMMON %s
+// RUN: %clang -target bpf -S -emit-llvm -o - %s -fno-stack-protector 2>&1 \
+// RUN:        | FileCheck -check-prefix=OFF -check-prefix=COMMON %s
 
 // RUN: %clang -target bpf -S -emit-llvm -o - %s -fstack-protector 2>&1 \
-// RUN:        | FileCheck -check-prefix=ON -check-prefix=COMMON %s
+// RUN:        | FileCheck -check-prefix=ON -check-prefix=COMMON -check-prefix=WARNING %s
 
 // RUN: %clang -target bpf -S -emit-llvm -o - %s -fstack-protector-all 2>&1 \
-// RUN:        | FileCheck -check-prefix=ALL -check-prefix=COMMON %s
+// RUN:        | FileCheck -check-prefix=ALL -check-prefix=COMMON -check-prefix=WARNING %s
 
 // RUN: %clang -target bpf -S -emit-llvm -o - %s -fstack-protector-strong 2>&1 \
-// RUN:        | FileCheck -check-prefix=STRONG -check-prefix=COMMON %s
+// RUN:        | FileCheck -check-prefix=STRONG -check-prefix=COMMON -check-prefix=WARNING %s
 
 typedef __SIZE_TYPE__ size_t;
 
@@ -22,7 +22,7 @@ char *strcpy(char *s1, const char *s2);
 //          ON: warning: ignoring '-fstack-protector'
 //         ALL: warning: ignoring '-fstack-protector-all'
 //      STRONG: warning: ignoring '-fstack-protector-strong'
-// COMMON-SAME: option as it is not currently supported for target 'bpf'
+// WARNING-SAME: option as it is not currently supported for target 'bpf'
 
 // COMMON: define {{.*}}void @test1(ptr noundef %{{[0-9a-z]+}}) #[[A:.*]] {
 void test1(const char *msg) {

>From 00c5945fea21163ce6141e916e8c9c807cabf901 Mon Sep 17 00:00:00 2001
From: Bill Wendling <5993918+bwendling at users.noreply.github.com>
Date: Thu, 14 Sep 2023 02:29:11 -0700
Subject: [PATCH 43/86] [NFC] Minimize header includes (#66339)

Minimize the headers included in header files to reduce the number of
files that need recompiled after a change.
---
 .../include/clang/Basic/AttrSubjectMatchRules.h  |  4 +++-
 clang/include/clang/Basic/AttributeCommonInfo.h  |  4 +++-
 clang/include/clang/Basic/Attributes.h           |  4 ++--
 clang/lib/Basic/Attributes.cpp                   | 16 +++++++++++++++-
 clang/lib/Basic/IdentifierTable.cpp              |  4 +---
 clang/lib/Parse/ParseStmt.cpp                    |  1 +
 6 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/Basic/AttrSubjectMatchRules.h b/clang/include/clang/Basic/AttrSubjectMatchRules.h
index e3dcb943e59d424..bec8122ea930a6a 100644
--- a/clang/include/clang/Basic/AttrSubjectMatchRules.h
+++ b/clang/include/clang/Basic/AttrSubjectMatchRules.h
@@ -9,10 +9,12 @@
 #ifndef LLVM_CLANG_BASIC_ATTRSUBJECTMATCHRULES_H
 #define LLVM_CLANG_BASIC_ATTRSUBJECTMATCHRULES_H
 
-#include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/DenseMap.h"
 
 namespace clang {
+
+class SourceRange;
+
 namespace attr {
 
 /// A list of all the recognized kinds of attributes.
diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h
index e57adc4bf5b99a2..7dc05418498d0ae 100644
--- a/clang/include/clang/Basic/AttributeCommonInfo.h
+++ b/clang/include/clang/Basic/AttributeCommonInfo.h
@@ -13,12 +13,14 @@
 
 #ifndef LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
 #define LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
+
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/TokenKinds.h"
 
 namespace clang {
-class IdentifierInfo;
+
 class ASTRecordWriter;
+class IdentifierInfo;
 
 class AttributeCommonInfo {
 public:
diff --git a/clang/include/clang/Basic/Attributes.h b/clang/include/clang/Basic/Attributes.h
index 3fc5fbacdb2cbd6..61666a6f4d9ac4a 100644
--- a/clang/include/clang/Basic/Attributes.h
+++ b/clang/include/clang/Basic/Attributes.h
@@ -10,12 +10,12 @@
 #define LLVM_CLANG_BASIC_ATTRIBUTES_H
 
 #include "clang/Basic/AttributeCommonInfo.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/TargetInfo.h"
 
 namespace clang {
 
 class IdentifierInfo;
+class LangOptions;
+class TargetInfo;
 
 /// Return the version number associated with the attribute if we
 /// recognize and implement the attribute specified by the given information.
diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp
index 1308e2d72f25f5b..bb495216ca93ca5 100644
--- a/clang/lib/Basic/Attributes.cpp
+++ b/clang/lib/Basic/Attributes.cpp
@@ -1,8 +1,22 @@
+//===--- Attributes.cpp ---------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the AttributeCommonInfo interface.
+//
+//===----------------------------------------------------------------------===//
+
 #include "clang/Basic/Attributes.h"
 #include "clang/Basic/AttrSubjectMatchRules.h"
-#include "clang/Basic/AttributeCommonInfo.h"
 #include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Basic/ParsedAttrInfo.h"
+#include "clang/Basic/TargetInfo.h"
+
 using namespace clang;
 
 static int hasAttributeImpl(AttributeCommonInfo::Syntax Syntax, StringRef Name,
diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp
index afb30268f2973ce..e5599d545541085 100644
--- a/clang/lib/Basic/IdentifierTable.cpp
+++ b/clang/lib/Basic/IdentifierTable.cpp
@@ -25,7 +25,6 @@
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Allocator.h"
-#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
 #include <cstdio>
@@ -52,8 +51,7 @@ namespace {
 
 /// A simple identifier lookup iterator that represents an
 /// empty sequence of identifiers.
-class EmptyLookupIterator : public IdentifierIterator
-{
+class EmptyLookupIterator : public IdentifierIterator {
 public:
   StringRef Next() override { return StringRef(); }
 };
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index fb883c08a745cfa..2531147c23196ae 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -14,6 +14,7 @@
 #include "clang/AST/PrettyDeclStackTrace.h"
 #include "clang/Basic/Attributes.h"
 #include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Parse/LoopHint.h"
 #include "clang/Parse/Parser.h"

>From 0d58774937e0401c6ca57f83bdcf643363f8bd11 Mon Sep 17 00:00:00 2001
From: martinboehme <mboehme at google.com>
Date: Thu, 14 Sep 2023 11:32:17 +0200
Subject: [PATCH 44/86] [clang][dataflow] In tests, error out if we didn't find
 any matching target functions. (#66197)

Before, we were silently letting the test pass, which masks test bugs;
for an
example, see https://github.com/llvm/llvm-project/pull/66195.
---
 .../Analysis/FlowSensitive/TestingSupport.h       | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
index 0cf66c218f43fdc..44d962d5da9a97b 100644
--- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
+++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
@@ -240,12 +240,15 @@ checkDataflow(AnalysisInputs<AnalysisT> AI,
     };
   }
 
-  for (const ast_matchers::BoundNodes &BN :
-       ast_matchers::match(ast_matchers::functionDecl(
-                               ast_matchers::hasBody(ast_matchers::stmt()),
-                               AI.TargetFuncMatcher)
-                               .bind("target"),
-                           Context)) {
+  SmallVector<ast_matchers::BoundNodes, 1> MatchResult = ast_matchers::match(
+      ast_matchers::functionDecl(ast_matchers::hasBody(ast_matchers::stmt()),
+                                 AI.TargetFuncMatcher)
+          .bind("target"),
+      Context);
+  if (MatchResult.empty())
+    return llvm::createStringError(llvm::inconvertibleErrorCode(),
+                                   "didn't find any matching target functions");
+  for (const ast_matchers::BoundNodes &BN : MatchResult) {
     // Get the AST node of the target function.
     const FunctionDecl *Target = BN.getNodeAs<FunctionDecl>("target");
     if (Target == nullptr)

>From 683069f6d5c89e168619b62ea9d11ae6a321892e Mon Sep 17 00:00:00 2001
From: Sergio Afonso <safonsof at amd.com>
Date: Thu, 30 Mar 2023 11:42:56 +0100
Subject: [PATCH 45/86] [OpenMP][OMPIRBuilder] OpenMPIRBuilder support for
 requires directive

This patch updates the `OpenMPIRBuilderConfig` structure to hold all
available 'requires' clauses, and it replicates part of the code
generation for the 'requires' registration function from clang in the
`OMPIRBuilder`, to be used with flang.

Porting the rest of features of the clang implementation to the IRBuilder
and sharing it between clang and flang remains for a future patch, due to the
complexity of the logic selecting the attributes of the generated
registration function.

Differential Revision: https://reviews.llvm.org/D147217
---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp         |  35 +----
 clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp      |   8 +-
 .../llvm/Frontend/OpenMP/OMPIRBuilder.h       |  53 ++++---
 llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp     | 137 ++++++++++++++++++
 .../Frontend/OpenMPIRBuilderTest.cpp          |  55 ++++++-
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp  |   7 +-
 6 files changed, 239 insertions(+), 56 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 380bab65c14f2e6..3b69305d050d769 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -480,27 +480,6 @@ enum OpenMPLocationFlags : unsigned {
   LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE)
 };
 
-namespace {
-LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
-/// Values for bit flags for marking which requires clauses have been used.
-enum OpenMPOffloadingRequiresDirFlags : int64_t {
-  /// flag undefined.
-  OMP_REQ_UNDEFINED               = 0x000,
-  /// no requires clause present.
-  OMP_REQ_NONE                    = 0x001,
-  /// reverse_offload clause.
-  OMP_REQ_REVERSE_OFFLOAD         = 0x002,
-  /// unified_address clause.
-  OMP_REQ_UNIFIED_ADDRESS         = 0x004,
-  /// unified_shared_memory clause.
-  OMP_REQ_UNIFIED_SHARED_MEMORY   = 0x008,
-  /// dynamic_allocators clause.
-  OMP_REQ_DYNAMIC_ALLOCATORS      = 0x010,
-  LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS)
-};
-
-} // anonymous namespace
-
 /// Describes ident structure that describes a source location.
 /// All descriptions are taken from
 /// https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h
@@ -1055,9 +1034,11 @@ static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
     : CGM(CGM), OMPBuilder(CGM.getModule()) {
   KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
-  llvm::OpenMPIRBuilderConfig Config(CGM.getLangOpts().OpenMPIsTargetDevice,
-                                     isGPU(), hasRequiresUnifiedSharedMemory(),
-                                     CGM.getLangOpts().OpenMPOffloadMandatory);
+  llvm::OpenMPIRBuilderConfig Config(
+      CGM.getLangOpts().OpenMPIsTargetDevice, isGPU(),
+      CGM.getLangOpts().OpenMPOffloadMandatory,
+      /*HasRequiresReverseOffload*/ false, /*HasRequiresUnifiedAddress*/ false,
+      hasRequiresUnifiedSharedMemory(), /*HasRequiresDynamicAllocators*/ false);
   OMPBuilder.initialize(CGM.getLangOpts().OpenMPIsTargetDevice
                             ? CGM.getLangOpts().OMPHostIRFile
                             : StringRef{});
@@ -10162,7 +10143,6 @@ llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
     std::string ReqName = getName({"omp_offloading", "requires_reg"});
     RequiresRegFn = CGM.CreateGlobalInitOrCleanUpFunction(FTy, ReqName, FI);
     CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
-    OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
     // TODO: check for other requires clauses.
     // The requires directive takes effect only when a target region is
     // present in the compilation unit. Otherwise it is ignored and not
@@ -10172,11 +10152,10 @@ llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
     assert((HasEmittedTargetRegion || HasEmittedDeclareTargetRegion ||
             !OMPBuilder.OffloadInfoManager.empty()) &&
            "Target or declare target region expected.");
-    if (HasRequiresUnifiedSharedMemory)
-      Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
     CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
                             CGM.getModule(), OMPRTL___tgt_register_requires),
-                        llvm::ConstantInt::get(CGM.Int64Ty, Flags));
+                        llvm::ConstantInt::get(
+                            CGM.Int64Ty, OMPBuilder.Config.getRequiresFlags()));
     CGF.FinishFunction();
   }
   return RequiresRegFn;
diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
index 1ec9bb3d5234714..93819ab815add08 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
@@ -853,9 +853,11 @@ void CGOpenMPRuntimeGPU::emitTargetOutlinedFunction(
 
 CGOpenMPRuntimeGPU::CGOpenMPRuntimeGPU(CodeGenModule &CGM)
     : CGOpenMPRuntime(CGM) {
-  llvm::OpenMPIRBuilderConfig Config(CGM.getLangOpts().OpenMPIsTargetDevice,
-                                     isGPU(), hasRequiresUnifiedSharedMemory(),
-                                     CGM.getLangOpts().OpenMPOffloadMandatory);
+  llvm::OpenMPIRBuilderConfig Config(
+      CGM.getLangOpts().OpenMPIsTargetDevice, isGPU(),
+      CGM.getLangOpts().OpenMPOffloadMandatory,
+      /*HasRequiresReverseOffload*/ false, /*HasRequiresUnifiedAddress*/ false,
+      hasRequiresUnifiedSharedMemory(), /*HasRequiresDynamicAllocators*/ false);
   OMPBuilder.setConfig(Config);
 
   if (!CGM.getLangOpts().OpenMPIsTargetDevice)
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index b6460267c08aaa1..a5977356da3e530 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -89,10 +89,6 @@ class OpenMPIRBuilderConfig {
   /// Flag for specifying if the compilation is done for an accelerator.
   std::optional<bool> IsGPU;
 
-  /// Flag for specifying weather a requires unified_shared_memory
-  /// directive is present or not.
-  std::optional<bool> HasRequiresUnifiedSharedMemory;
-
   // Flag for specifying if offloading is mandatory.
   std::optional<bool> OpenMPOffloadMandatory;
 
@@ -101,13 +97,13 @@ class OpenMPIRBuilderConfig {
   /// Separator used between all of the rest consecutive parts of s name
   std::optional<StringRef> Separator;
 
-  OpenMPIRBuilderConfig() {}
+  OpenMPIRBuilderConfig();
   OpenMPIRBuilderConfig(bool IsTargetDevice, bool IsGPU,
+                        bool OpenMPOffloadMandatory,
+                        bool HasRequiresReverseOffload,
+                        bool HasRequiresUnifiedAddress,
                         bool HasRequiresUnifiedSharedMemory,
-                        bool OpenMPOffloadMandatory)
-      : IsTargetDevice(IsTargetDevice), IsGPU(IsGPU),
-        HasRequiresUnifiedSharedMemory(HasRequiresUnifiedSharedMemory),
-        OpenMPOffloadMandatory(OpenMPOffloadMandatory) {}
+                        bool HasRequiresDynamicAllocators);
 
   // Getters functions that assert if the required values are not present.
   bool isTargetDevice() const {
@@ -120,17 +116,22 @@ class OpenMPIRBuilderConfig {
     return *IsGPU;
   }
 
-  bool hasRequiresUnifiedSharedMemory() const {
-    assert(HasRequiresUnifiedSharedMemory.has_value() &&
-           "HasUnifiedSharedMemory is not set");
-    return *HasRequiresUnifiedSharedMemory;
-  }
-
   bool openMPOffloadMandatory() const {
     assert(OpenMPOffloadMandatory.has_value() &&
            "OpenMPOffloadMandatory is not set");
     return *OpenMPOffloadMandatory;
   }
+
+  bool hasRequiresFlags() const { return RequiresFlags; }
+  bool hasRequiresReverseOffload() const;
+  bool hasRequiresUnifiedAddress() const;
+  bool hasRequiresUnifiedSharedMemory() const;
+  bool hasRequiresDynamicAllocators() const;
+
+  /// Returns requires directive clauses as flags compatible with those expected
+  /// by libomptarget.
+  int64_t getRequiresFlags() const;
+
   // Returns the FirstSeparator if set, otherwise use the default separator
   // depending on isGPU
   StringRef firstSeparator() const {
@@ -153,11 +154,17 @@ class OpenMPIRBuilderConfig {
 
   void setIsTargetDevice(bool Value) { IsTargetDevice = Value; }
   void setIsGPU(bool Value) { IsGPU = Value; }
-  void setHasRequiresUnifiedSharedMemory(bool Value) {
-    HasRequiresUnifiedSharedMemory = Value;
-  }
   void setFirstSeparator(StringRef FS) { FirstSeparator = FS; }
   void setSeparator(StringRef S) { Separator = S; }
+
+  void setHasRequiresReverseOffload(bool Value);
+  void setHasRequiresUnifiedAddress(bool Value);
+  void setHasRequiresUnifiedSharedMemory(bool Value);
+  void setHasRequiresDynamicAllocators(bool Value);
+
+private:
+  /// Flags for specifying which requires directive clauses are present.
+  int64_t RequiresFlags;
 };
 
 /// Data structure to contain the information needed to uniquely identify
@@ -2520,6 +2527,16 @@ class OpenMPIRBuilder {
   /// \param Name Name of the variable.
   GlobalVariable *getOrCreateInternalVariable(Type *Ty, const StringRef &Name,
                                               unsigned AddressSpace = 0);
+
+  /// Create a global function to register OpenMP requires flags into the
+  /// runtime, according to the `Config`.
+  ///
+  /// This function should be added to the list of constructors of the
+  /// compilation unit in order to be called before other OpenMP runtime
+  /// functions.
+  ///
+  /// \param Name  Name of the created function.
+  Function *createRegisterRequires(StringRef Name);
 };
 
 /// Class to represented the control flow structure of an OpenMP canonical loop.
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 6cab70df269c170..cc6054cb19d7806 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -25,12 +25,14 @@
 #include "llvm/Bitcode/BitcodeReader.h"
 #include "llvm/Frontend/OpenMP/OMPGridValues.h"
 #include "llvm/IR/Attributes.h"
+#include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/CFG.h"
 #include "llvm/IR/CallingConv.h"
 #include "llvm/IR/Constant.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
 #include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LLVMContext.h"
@@ -338,6 +340,104 @@ BasicBlock *llvm::splitBBWithSuffix(IRBuilderBase &Builder, bool CreateBranch,
   return splitBB(Builder, CreateBranch, Old->getName() + Suffix);
 }
 
+//===----------------------------------------------------------------------===//
+// OpenMPIRBuilderConfig
+//===----------------------------------------------------------------------===//
+
+namespace {
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+/// Values for bit flags for marking which requires clauses have been used.
+enum OpenMPOffloadingRequiresDirFlags {
+  /// flag undefined.
+  OMP_REQ_UNDEFINED = 0x000,
+  /// no requires directive present.
+  OMP_REQ_NONE = 0x001,
+  /// reverse_offload clause.
+  OMP_REQ_REVERSE_OFFLOAD = 0x002,
+  /// unified_address clause.
+  OMP_REQ_UNIFIED_ADDRESS = 0x004,
+  /// unified_shared_memory clause.
+  OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
+  /// dynamic_allocators clause.
+  OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
+  LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS)
+};
+
+} // anonymous namespace
+
+OpenMPIRBuilderConfig::OpenMPIRBuilderConfig()
+    : RequiresFlags(OMP_REQ_UNDEFINED) {}
+
+OpenMPIRBuilderConfig::OpenMPIRBuilderConfig(
+    bool IsTargetDevice, bool IsGPU, bool OpenMPOffloadMandatory,
+    bool HasRequiresReverseOffload, bool HasRequiresUnifiedAddress,
+    bool HasRequiresUnifiedSharedMemory, bool HasRequiresDynamicAllocators)
+    : IsTargetDevice(IsTargetDevice), IsGPU(IsGPU),
+      OpenMPOffloadMandatory(OpenMPOffloadMandatory),
+      RequiresFlags(OMP_REQ_UNDEFINED) {
+  if (HasRequiresReverseOffload)
+    RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
+  if (HasRequiresUnifiedAddress)
+    RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
+  if (HasRequiresUnifiedSharedMemory)
+    RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
+  if (HasRequiresDynamicAllocators)
+    RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
+}
+
+bool OpenMPIRBuilderConfig::hasRequiresReverseOffload() const {
+  return RequiresFlags & OMP_REQ_REVERSE_OFFLOAD;
+}
+
+bool OpenMPIRBuilderConfig::hasRequiresUnifiedAddress() const {
+  return RequiresFlags & OMP_REQ_UNIFIED_ADDRESS;
+}
+
+bool OpenMPIRBuilderConfig::hasRequiresUnifiedSharedMemory() const {
+  return RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY;
+}
+
+bool OpenMPIRBuilderConfig::hasRequiresDynamicAllocators() const {
+  return RequiresFlags & OMP_REQ_DYNAMIC_ALLOCATORS;
+}
+
+int64_t OpenMPIRBuilderConfig::getRequiresFlags() const {
+  return hasRequiresFlags() ? RequiresFlags
+                            : static_cast<int64_t>(OMP_REQ_NONE);
+}
+
+void OpenMPIRBuilderConfig::setHasRequiresReverseOffload(bool Value) {
+  if (Value)
+    RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
+  else
+    RequiresFlags &= ~OMP_REQ_REVERSE_OFFLOAD;
+}
+
+void OpenMPIRBuilderConfig::setHasRequiresUnifiedAddress(bool Value) {
+  if (Value)
+    RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
+  else
+    RequiresFlags &= ~OMP_REQ_UNIFIED_ADDRESS;
+}
+
+void OpenMPIRBuilderConfig::setHasRequiresUnifiedSharedMemory(bool Value) {
+  if (Value)
+    RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
+  else
+    RequiresFlags &= ~OMP_REQ_UNIFIED_SHARED_MEMORY;
+}
+
+void OpenMPIRBuilderConfig::setHasRequiresDynamicAllocators(bool Value) {
+  if (Value)
+    RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
+  else
+    RequiresFlags &= ~OMP_REQ_DYNAMIC_ALLOCATORS;
+}
+
+//===----------------------------------------------------------------------===//
+// OpenMPIRBuilder
+//===----------------------------------------------------------------------===//
+
 void OpenMPIRBuilder::getKernelArgsVector(TargetKernelArgs &KernelArgs,
                                           IRBuilderBase &Builder,
                                           SmallVector<Value *> &ArgsVector) {
@@ -6106,6 +6206,39 @@ void OpenMPIRBuilder::loadOffloadInfoMetadata(Module &M) {
   }
 }
 
+Function *OpenMPIRBuilder::createRegisterRequires(StringRef Name) {
+  // Skip the creation of the registration function if this is device codegen
+  if (Config.isTargetDevice())
+    return nullptr;
+
+  Builder.ClearInsertionPoint();
+
+  // Create registration function prototype
+  auto *RegFnTy = FunctionType::get(Builder.getVoidTy(), {});
+  auto *RegFn = Function::Create(
+      RegFnTy, GlobalVariable::LinkageTypes::InternalLinkage, Name, M);
+  RegFn->setSection(".text.startup");
+  RegFn->addFnAttr(Attribute::NoInline);
+  RegFn->addFnAttr(Attribute::NoUnwind);
+
+  // Create registration function body
+  auto *BB = BasicBlock::Create(M.getContext(), "entry", RegFn);
+  ConstantInt *FlagsVal =
+      ConstantInt::getSigned(Builder.getInt64Ty(), Config.getRequiresFlags());
+  Function *RTLRegFn = getOrCreateRuntimeFunctionPtr(
+      omp::RuntimeFunction::OMPRTL___tgt_register_requires);
+
+  Builder.SetInsertPoint(BB);
+  Builder.CreateCall(RTLRegFn, {FlagsVal});
+  Builder.CreateRetVoid();
+
+  return RegFn;
+}
+
+//===----------------------------------------------------------------------===//
+// OffloadEntriesInfoManager
+//===----------------------------------------------------------------------===//
+
 bool OffloadEntriesInfoManager::empty() const {
   return OffloadEntriesTargetRegion.empty() &&
          OffloadEntriesDeviceGlobalVar.empty();
@@ -6244,6 +6377,10 @@ void OffloadEntriesInfoManager::actOnDeviceGlobalVarEntriesInfo(
     Action(E.getKey(), E.getValue());
 }
 
+//===----------------------------------------------------------------------===//
+// CanonicalLoopInfo
+//===----------------------------------------------------------------------===//
+
 void CanonicalLoopInfo::collectControlBlocks(
     SmallVectorImpl<BasicBlock *> &BBs) {
   // We only count those BBs as control block for which we do not need to
diff --git a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
index 5870457956b5433..bc1687cae25f1d9 100644
--- a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
+++ b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
@@ -5128,7 +5128,7 @@ TEST_F(OpenMPIRBuilderTest, TargetRegion) {
   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
   OpenMPIRBuilder OMPBuilder(*M);
   OMPBuilder.initialize();
-  OpenMPIRBuilderConfig Config(false, false, false, false);
+  OpenMPIRBuilderConfig Config(false, false, false, false, false, false, false);
   OMPBuilder.setConfig(Config);
   F->setName("func");
   IRBuilder<> Builder(BB);
@@ -5206,7 +5206,8 @@ TEST_F(OpenMPIRBuilderTest, TargetRegion) {
 
 TEST_F(OpenMPIRBuilderTest, TargetRegionDevice) {
   OpenMPIRBuilder OMPBuilder(*M);
-  OMPBuilder.setConfig(OpenMPIRBuilderConfig(true, false, false, false));
+  OMPBuilder.setConfig(
+      OpenMPIRBuilderConfig(true, false, false, false, false, false, false));
   OMPBuilder.initialize();
 
   F->setName("func");
@@ -5896,7 +5897,8 @@ TEST_F(OpenMPIRBuilderTest, EmitOffloadingArraysArguments) {
 
 TEST_F(OpenMPIRBuilderTest, OffloadEntriesInfoManager) {
   OpenMPIRBuilder OMPBuilder(*M);
-  OMPBuilder.setConfig(OpenMPIRBuilderConfig(true, false, false, false));
+  OMPBuilder.setConfig(
+      OpenMPIRBuilderConfig(true, false, false, false, false, false, false));
   OffloadEntriesInfoManager &InfoManager = OMPBuilder.OffloadInfoManager;
   TargetRegionEntryInfo EntryInfo("parent", 1, 2, 4, 0);
   InfoManager.initializeTargetRegionEntryInfo(EntryInfo, 0);
@@ -5919,7 +5921,7 @@ TEST_F(OpenMPIRBuilderTest, OffloadEntriesInfoManager) {
 TEST_F(OpenMPIRBuilderTest, registerTargetGlobalVariable) {
   OpenMPIRBuilder OMPBuilder(*M);
   OMPBuilder.initialize();
-  OpenMPIRBuilderConfig Config(false, false, false, false);
+  OpenMPIRBuilderConfig Config(false, false, false, false, false, false, false);
   OMPBuilder.setConfig(Config);
 
   std::vector<llvm::Triple> TargetTriple;
@@ -5996,8 +5998,11 @@ TEST_F(OpenMPIRBuilderTest, createGPUOffloadEntry) {
   OMPBuilder.initialize();
   OpenMPIRBuilderConfig Config(/* IsTargetDevice = */ true,
                                /* IsGPU = */ true,
+                               /* OpenMPOffloadMandatory = */ false,
+                               /* HasRequiresReverseOffload = */ false,
+                               /* HasRequiresUnifiedAddress = */ false,
                                /* HasRequiresUnifiedSharedMemory = */ false,
-                               /* OpenMPOffloadMandatory = */ false);
+                               /* HasRequiresDynamicAllocators = */ false);
   OMPBuilder.setConfig(Config);
 
   FunctionCallee FnTypeAndCallee =
@@ -6033,4 +6038,44 @@ TEST_F(OpenMPIRBuilderTest, createGPUOffloadEntry) {
   EXPECT_TRUE(Fn->hasFnAttribute(Attribute::MustProgress));
 }
 
+TEST_F(OpenMPIRBuilderTest, CreateRegisterRequires) {
+  OpenMPIRBuilder OMPBuilder(*M);
+  OMPBuilder.initialize();
+
+  OpenMPIRBuilderConfig Config(/* IsTargetDevice = */ false,
+                               /* IsGPU = */ false,
+                               /* OpenMPOffloadMandatory = */ false,
+                               /* HasRequiresReverseOffload = */ true,
+                               /* HasRequiresUnifiedAddress = */ false,
+                               /* HasRequiresUnifiedSharedMemory = */ true,
+                               /* HasRequiresDynamicAllocators = */ false);
+  OMPBuilder.setConfig(Config);
+
+  auto FName =
+      OMPBuilder.createPlatformSpecificName({"omp_offloading", "requires_reg"});
+  EXPECT_EQ(FName, ".omp_offloading.requires_reg");
+
+  Function *Fn = OMPBuilder.createRegisterRequires(FName);
+  EXPECT_NE(Fn, nullptr);
+  EXPECT_EQ(FName, Fn->getName());
+
+  EXPECT_EQ(Fn->getSection(), ".text.startup");
+  EXPECT_TRUE(Fn->hasInternalLinkage());
+  EXPECT_TRUE(Fn->hasFnAttribute(Attribute::NoInline));
+  EXPECT_TRUE(Fn->hasFnAttribute(Attribute::NoUnwind));
+  EXPECT_EQ(Fn->size(), 1u);
+
+  BasicBlock *Entry = &Fn->getEntryBlock();
+  EXPECT_FALSE(Entry->empty());
+  EXPECT_EQ(Fn->getReturnType()->getTypeID(), Type::VoidTyID);
+
+  CallInst *Call = &cast<CallInst>(*Entry->begin());
+  EXPECT_EQ(Call->getCalledFunction()->getName(), "__tgt_register_requires");
+  EXPECT_EQ(Call->getNumOperands(), 2u);
+
+  Value *Flags = Call->getArgOperand(0);
+  EXPECT_EQ(cast<ConstantInt>(Flags)->getSExtValue(),
+            OMPBuilder.Config.getRequiresFlags());
+}
+
 } // namespace
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 24ddd47a794cee9..e3ece38b6b8ca9a 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1298,8 +1298,11 @@ llvm::OpenMPIRBuilder *ModuleTranslation::getOpenMPBuilder() {
     // TODO: set the flags when available
     llvm::OpenMPIRBuilderConfig config(
         isTargetDevice, isGPU,
-        /* HasRequiresUnifiedSharedMemory */ false,
-        /* OpenMPOffloadMandatory */ false);
+        /* OpenMPOffloadMandatory = */ false,
+        /* HasRequiresReverseOffload = */ false,
+        /* HasRequiresUnifiedAddress = */ false,
+        /* HasRequiresUnifiedSharedMemory = */ false,
+        /* HasRequiresDynamicAllocators = */ false);
     ompBuilder->setConfig(config);
   }
   return ompBuilder.get();

>From 0e3ba4e3e60986306a41839fad17500c8fcbf72d Mon Sep 17 00:00:00 2001
From: Sergio Afonso <safonsof at amd.com>
Date: Wed, 29 Mar 2023 18:13:48 +0100
Subject: [PATCH 46/86] [OpenMP][Flang][MLIR] Lowering of OpenMP requires
 directive from parse tree to MLIR

This patch implements the lowering of the OpenMP 'requires' directive
from Flang parse tree to MLIR attributes attached to the top-level
module.

Target-related 'requires' clauses are gathered and combined for each top-level
unit during semantics. Lastly, a single module-level `omp.requires` attribute
is attached to the MLIR module with that information at the end of the process.

The `atomic_default_mem_order` clause is not addressed by this patch, but
rather it will come as a separate patch and follow a different approach.

Depends on D147214, D150328, D150329 and D157983.

Differential Revision: https://reviews.llvm.org/D147218
---
 flang/include/flang/Lower/OpenMP.h            |  11 ++
 flang/lib/Lower/Bridge.cpp                    |  33 +++-
 flang/lib/Lower/OpenMP.cpp                    | 174 ++++++++++++++----
 .../OpenMP/Todo/requires-unnamed-common.f90   |  23 +++
 flang/test/Lower/OpenMP/requires-common.f90   |  19 ++
 flang/test/Lower/OpenMP/requires-notarget.f90 |  14 ++
 flang/test/Lower/OpenMP/requires.f90          |  14 ++
 7 files changed, 254 insertions(+), 34 deletions(-)
 create mode 100644 flang/test/Lower/OpenMP/Todo/requires-unnamed-common.f90
 create mode 100644 flang/test/Lower/OpenMP/requires-common.f90
 create mode 100644 flang/test/Lower/OpenMP/requires-notarget.f90
 create mode 100644 flang/test/Lower/OpenMP/requires.f90

diff --git a/flang/include/flang/Lower/OpenMP.h b/flang/include/flang/Lower/OpenMP.h
index 08863c79264c259..3563de7d091e894 100644
--- a/flang/include/flang/Lower/OpenMP.h
+++ b/flang/include/flang/Lower/OpenMP.h
@@ -34,6 +34,10 @@ struct OmpEndLoopDirective;
 struct OmpClauseList;
 } // namespace parser
 
+namespace semantics {
+class Symbol;
+} // namespace semantics
+
 namespace lower {
 
 class AbstractConverter;
@@ -62,6 +66,13 @@ fir::ConvertOp getConvertFromReductionOp(mlir::Operation *, mlir::Value);
 void updateReduction(mlir::Operation *, fir::FirOpBuilder &, mlir::Value,
                      mlir::Value, fir::ConvertOp * = nullptr);
 void removeStoreOp(mlir::Operation *, mlir::Value);
+
+bool isOpenMPTargetConstruct(const parser::OpenMPConstruct &);
+bool isOpenMPDeviceDeclareTarget(Fortran::lower::AbstractConverter &,
+                                 Fortran::lower::pft::Evaluation &,
+                                 const parser::OpenMPDeclarativeConstruct &);
+void genOpenMPRequires(mlir::Operation *, const Fortran::semantics::Symbol *);
+
 } // namespace lower
 } // namespace Fortran
 
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index cbe108194dd212f..b06497e3f8ee823 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -50,6 +50,7 @@
 #include "flang/Parser/parse-tree.h"
 #include "flang/Runtime/iostat.h"
 #include "flang/Semantics/runtime-type-info.h"
+#include "flang/Semantics/symbol.h"
 #include "flang/Semantics/tools.h"
 #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
 #include "mlir/IR/PatternMatch.h"
@@ -294,12 +295,15 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     //    that they are available before lowering any function that may use
     //    them.
     bool hasMainProgram = false;
+    const Fortran::semantics::Symbol *globalOmpRequiresSymbol = nullptr;
     for (Fortran::lower::pft::Program::Units &u : pft.getUnits()) {
       std::visit(Fortran::common::visitors{
                      [&](Fortran::lower::pft::FunctionLikeUnit &f) {
                        if (f.isMainProgram())
                          hasMainProgram = true;
                        declareFunction(f);
+                       if (!globalOmpRequiresSymbol)
+                         globalOmpRequiresSymbol = f.getScope().symbol();
                      },
                      [&](Fortran::lower::pft::ModuleLikeUnit &m) {
                        lowerModuleDeclScope(m);
@@ -307,7 +311,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
                             m.nestedFunctions)
                          declareFunction(f);
                      },
-                     [&](Fortran::lower::pft::BlockDataUnit &b) {},
+                     [&](Fortran::lower::pft::BlockDataUnit &b) {
+                       if (!globalOmpRequiresSymbol)
+                         globalOmpRequiresSymbol = b.symTab.symbol();
+                     },
                      [&](Fortran::lower::pft::CompilerDirectiveUnit &d) {},
                  },
                  u);
@@ -352,6 +359,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
       });
 
     finalizeOpenACCLowering();
+    finalizeOpenMPLowering(globalOmpRequiresSymbol);
   }
 
   /// Declare a function.
@@ -2347,10 +2355,19 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
     localSymbols.popScope();
     builder->restoreInsertionPoint(insertPt);
+
+    // Register if a target region was found
+    ompDeviceCodeFound =
+        ompDeviceCodeFound || Fortran::lower::isOpenMPTargetConstruct(omp);
   }
 
   void genFIR(const Fortran::parser::OpenMPDeclarativeConstruct &ompDecl) {
     mlir::OpBuilder::InsertPoint insertPt = builder->saveInsertionPoint();
+    // Register if a declare target construct intended for a target device was
+    // found
+    ompDeviceCodeFound =
+        ompDeviceCodeFound ||
+        Fortran::lower::isOpenMPDeviceDeclareTarget(*this, getEval(), ompDecl);
     genOpenMPDeclarativeConstruct(*this, getEval(), ompDecl);
     for (Fortran::lower::pft::Evaluation &e : getEval().getNestedEvaluations())
       genFIR(e);
@@ -4758,6 +4775,16 @@ class FirConverter : public Fortran::lower::AbstractConverter {
                                                      accRoutineInfos);
   }
 
+  /// Performing OpenMP lowering actions that were deferred to the end of
+  /// lowering.
+  void finalizeOpenMPLowering(
+      const Fortran::semantics::Symbol *globalOmpRequiresSymbol) {
+    // Set the module attribute related to OpenMP requires directives
+    if (ompDeviceCodeFound)
+      Fortran::lower::genOpenMPRequires(getModuleOp().getOperation(),
+                                        globalOmpRequiresSymbol);
+  }
+
   //===--------------------------------------------------------------------===//
 
   Fortran::lower::LoweringBridge &bridge;
@@ -4804,6 +4831,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
   /// Deferred OpenACC routine attachment.
   Fortran::lower::AccRoutineInfoMappingList accRoutineInfos;
+
+  /// Whether an OpenMP target region or declare target function/subroutine
+  /// intended for device offloading has been detected
+  bool ompDeviceCodeFound = false;
 };
 
 } // namespace
diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp
index be9c0dcdbdbf485..bc18898426aa85b 100644
--- a/flang/lib/Lower/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP.cpp
@@ -78,9 +78,7 @@ static void genObjectList(const Fortran::parser::OmpObjectList &objectList,
 static void gatherFuncAndVarSyms(
     const Fortran::parser::OmpObjectList &objList,
     mlir::omp::DeclareTargetCaptureClause clause,
-    llvm::SmallVectorImpl<std::pair<mlir::omp::DeclareTargetCaptureClause,
-                                    Fortran::semantics::Symbol>>
-        &symbolAndClause) {
+    llvm::SmallVectorImpl<DeclareTargetCapturePair> &symbolAndClause) {
   for (const Fortran::parser::OmpObject &ompObject : objList.v) {
     Fortran::common::visit(
         Fortran::common::visitors{
@@ -2453,6 +2451,71 @@ genTeamsOp(Fortran::lower::AbstractConverter &converter,
                                  reductionDeclSymbols));
 }
 
+/// Extract the list of function and variable symbols affected by the given
+/// 'declare target' directive and return the intended device type for them.
+static mlir::omp::DeclareTargetDeviceType getDeclareTargetInfo(
+    Fortran::lower::AbstractConverter &converter,
+    Fortran::lower::pft::Evaluation &eval,
+    const Fortran::parser::OpenMPDeclareTargetConstruct &declareTargetConstruct,
+    llvm::SmallVectorImpl<DeclareTargetCapturePair> &symbolAndClause) {
+
+  // The default capture type
+  mlir::omp::DeclareTargetDeviceType deviceType =
+      mlir::omp::DeclareTargetDeviceType::any;
+  const auto &spec = std::get<Fortran::parser::OmpDeclareTargetSpecifier>(
+      declareTargetConstruct.t);
+
+  if (const auto *objectList{
+          Fortran::parser::Unwrap<Fortran::parser::OmpObjectList>(spec.u)}) {
+    // Case: declare target(func, var1, var2)
+    gatherFuncAndVarSyms(*objectList, mlir::omp::DeclareTargetCaptureClause::to,
+                         symbolAndClause);
+  } else if (const auto *clauseList{
+                 Fortran::parser::Unwrap<Fortran::parser::OmpClauseList>(
+                     spec.u)}) {
+    if (clauseList->v.empty()) {
+      // Case: declare target, implicit capture of function
+      symbolAndClause.emplace_back(
+          mlir::omp::DeclareTargetCaptureClause::to,
+          eval.getOwningProcedure()->getSubprogramSymbol());
+    }
+
+    ClauseProcessor cp(converter, *clauseList);
+    cp.processTo(symbolAndClause);
+    cp.processLink(symbolAndClause);
+    cp.processDeviceType(deviceType);
+    cp.processTODO<Fortran::parser::OmpClause::Indirect>(
+        converter.getCurrentLocation(),
+        llvm::omp::Directive::OMPD_declare_target);
+  }
+
+  return deviceType;
+}
+
+static std::optional<mlir::omp::DeclareTargetDeviceType>
+getDeclareTargetFunctionDevice(
+    Fortran::lower::AbstractConverter &converter,
+    Fortran::lower::pft::Evaluation &eval,
+    const Fortran::parser::OpenMPDeclareTargetConstruct
+        &declareTargetConstruct) {
+  llvm::SmallVector<DeclareTargetCapturePair, 0> symbolAndClause;
+  mlir::omp::DeclareTargetDeviceType deviceType = getDeclareTargetInfo(
+      converter, eval, declareTargetConstruct, symbolAndClause);
+
+  // Return the device type only if at least one of the targets for the
+  // directive is a function or subroutine
+  mlir::ModuleOp mod = converter.getFirOpBuilder().getModule();
+  for (const DeclareTargetCapturePair &symClause : symbolAndClause) {
+    mlir::Operation *op = mod.lookupSymbol(
+        converter.mangleName(std::get<Fortran::semantics::Symbol>(symClause)));
+
+    if (mlir::isa<mlir::func::FuncOp>(op))
+      return deviceType;
+  }
+
+  return std::nullopt;
+}
+
 //===----------------------------------------------------------------------===//
 // genOMP() Code generation helper functions
 //===----------------------------------------------------------------------===//
@@ -2973,35 +3036,8 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
                        &declareTargetConstruct) {
   llvm::SmallVector<DeclareTargetCapturePair, 0> symbolAndClause;
   mlir::ModuleOp mod = converter.getFirOpBuilder().getModule();
-
-  // The default capture type
-  mlir::omp::DeclareTargetDeviceType deviceType =
-      mlir::omp::DeclareTargetDeviceType::any;
-  const auto &spec = std::get<Fortran::parser::OmpDeclareTargetSpecifier>(
-      declareTargetConstruct.t);
-  if (const auto *objectList{
-          Fortran::parser::Unwrap<Fortran::parser::OmpObjectList>(spec.u)}) {
-    // Case: declare target(func, var1, var2)
-    gatherFuncAndVarSyms(*objectList, mlir::omp::DeclareTargetCaptureClause::to,
-                         symbolAndClause);
-  } else if (const auto *clauseList{
-                 Fortran::parser::Unwrap<Fortran::parser::OmpClauseList>(
-                     spec.u)}) {
-    if (clauseList->v.empty()) {
-      // Case: declare target, implicit capture of function
-      symbolAndClause.emplace_back(
-          mlir::omp::DeclareTargetCaptureClause::to,
-          eval.getOwningProcedure()->getSubprogramSymbol());
-    }
-
-    ClauseProcessor cp(converter, *clauseList);
-    cp.processTo(symbolAndClause);
-    cp.processLink(symbolAndClause);
-    cp.processDeviceType(deviceType);
-    cp.processTODO<Fortran::parser::OmpClause::Indirect>(
-        converter.getCurrentLocation(),
-        llvm::omp::Directive::OMPD_declare_target);
-  }
+  mlir::omp::DeclareTargetDeviceType deviceType = getDeclareTargetInfo(
+      converter, eval, declareTargetConstruct, symbolAndClause);
 
   for (const DeclareTargetCapturePair &symClause : symbolAndClause) {
     mlir::Operation *op = mod.lookupSymbol(
@@ -3130,7 +3166,10 @@ void Fortran::lower::genOpenMPDeclarativeConstruct(
           },
           [&](const Fortran::parser::OpenMPRequiresConstruct
                   &requiresConstruct) {
-            TODO(converter.getCurrentLocation(), "OpenMPRequiresConstruct");
+            // Requires directives are gathered and processed in semantics and
+            // then combined in the lowering bridge before triggering codegen
+            // just once. Hence, there is no need to lower each individual
+            // occurrence here.
           },
           [&](const Fortran::parser::OpenMPThreadprivate &threadprivate) {
             // The directive is lowered when instantiating the variable to
@@ -3444,3 +3483,72 @@ void Fortran::lower::removeStoreOp(mlir::Operation *reductionOp,
     }
   }
 }
+
+bool Fortran::lower::isOpenMPTargetConstruct(
+    const Fortran::parser::OpenMPConstruct &omp) {
+  llvm::omp::Directive dir = llvm::omp::Directive::OMPD_unknown;
+  if (const auto *block =
+          std::get_if<Fortran::parser::OpenMPBlockConstruct>(&omp.u)) {
+    const auto &begin =
+        std::get<Fortran::parser::OmpBeginBlockDirective>(block->t);
+    dir = std::get<Fortran::parser::OmpBlockDirective>(begin.t).v;
+  } else if (const auto *loop =
+                 std::get_if<Fortran::parser::OpenMPLoopConstruct>(&omp.u)) {
+    const auto &begin =
+        std::get<Fortran::parser::OmpBeginLoopDirective>(loop->t);
+    dir = std::get<Fortran::parser::OmpLoopDirective>(begin.t).v;
+  }
+  return llvm::omp::allTargetSet.test(dir);
+}
+
+bool Fortran::lower::isOpenMPDeviceDeclareTarget(
+    Fortran::lower::AbstractConverter &converter,
+    Fortran::lower::pft::Evaluation &eval,
+    const Fortran::parser::OpenMPDeclarativeConstruct &ompDecl) {
+  return std::visit(
+      Fortran::common::visitors{
+          [&](const Fortran::parser::OpenMPDeclareTargetConstruct &ompReq) {
+            mlir::omp::DeclareTargetDeviceType targetType =
+                getDeclareTargetFunctionDevice(converter, eval, ompReq)
+                    .value_or(mlir::omp::DeclareTargetDeviceType::host);
+            return targetType != mlir::omp::DeclareTargetDeviceType::host;
+          },
+          [&](const auto &) { return false; },
+      },
+      ompDecl.u);
+}
+
+void Fortran::lower::genOpenMPRequires(
+    mlir::Operation *mod, const Fortran::semantics::Symbol *symbol) {
+  using MlirRequires = mlir::omp::ClauseRequires;
+  using SemaRequires = Fortran::semantics::WithOmpDeclarative::RequiresFlag;
+
+  if (auto offloadMod =
+          llvm::dyn_cast<mlir::omp::OffloadModuleInterface>(mod)) {
+    Fortran::semantics::WithOmpDeclarative::RequiresFlags semaFlags;
+    if (symbol) {
+      Fortran::common::visit(
+          [&](const auto &details) {
+            if constexpr (std::is_base_of_v<
+                              Fortran::semantics::WithOmpDeclarative,
+                              std::decay_t<decltype(details)>>) {
+              if (details.has_ompRequires())
+                semaFlags = *details.ompRequires();
+            }
+          },
+          symbol->details());
+    }
+
+    MlirRequires mlirFlags = MlirRequires::none;
+    if (semaFlags.test(SemaRequires::ReverseOffload))
+      mlirFlags = mlirFlags | MlirRequires::reverse_offload;
+    if (semaFlags.test(SemaRequires::UnifiedAddress))
+      mlirFlags = mlirFlags | MlirRequires::unified_address;
+    if (semaFlags.test(SemaRequires::UnifiedSharedMemory))
+      mlirFlags = mlirFlags | MlirRequires::unified_shared_memory;
+    if (semaFlags.test(SemaRequires::DynamicAllocators))
+      mlirFlags = mlirFlags | MlirRequires::dynamic_allocators;
+
+    offloadMod.setRequires(mlirFlags);
+  }
+}
diff --git a/flang/test/Lower/OpenMP/Todo/requires-unnamed-common.f90 b/flang/test/Lower/OpenMP/Todo/requires-unnamed-common.f90
new file mode 100644
index 000000000000000..578f71a55e43b68
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/requires-unnamed-common.f90
@@ -0,0 +1,23 @@
+! This test checks the lowering of REQUIRES inside of an unnamed BLOCK DATA.
+! The symbol of the `symTab` scope of the `BlockDataUnit` PFT node is null in
+! this case, resulting in the inability to store the REQUIRES flags gathered in
+! it.
+
+! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s
+! RUN: bbc -fopenmp -emit-fir %s -o - | FileCheck %s
+! RUN: bbc -fopenmp -fopenmp-is-target-device -emit-fir %s -o - | FileCheck %s
+! XFAIL: *
+
+!CHECK:         module attributes {
+!CHECK-SAME:    omp.requires = #omp<clause_requires unified_shared_memory>
+block data
+  !$omp requires unified_shared_memory
+  integer :: x
+  common /block/ x
+  data x / 10 /
+end
+
+subroutine f
+  !$omp declare target
+end subroutine f
diff --git a/flang/test/Lower/OpenMP/requires-common.f90 b/flang/test/Lower/OpenMP/requires-common.f90
new file mode 100644
index 000000000000000..2e112d72de3fdfc
--- /dev/null
+++ b/flang/test/Lower/OpenMP/requires-common.f90
@@ -0,0 +1,19 @@
+! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s
+! RUN: bbc -fopenmp -emit-fir %s -o - | FileCheck %s
+! RUN: bbc -fopenmp -fopenmp-is-target-device -emit-fir %s -o - | FileCheck %s
+
+! This test checks the lowering of requires into MLIR
+
+!CHECK:      module attributes {
+!CHECK-SAME: omp.requires = #omp<clause_requires unified_shared_memory>
+block data init
+  !$omp requires unified_shared_memory
+  integer :: x
+  common /block/ x
+  data x / 10 /
+end
+
+subroutine f
+  !$omp declare target
+end subroutine f
diff --git a/flang/test/Lower/OpenMP/requires-notarget.f90 b/flang/test/Lower/OpenMP/requires-notarget.f90
new file mode 100644
index 000000000000000..bfa509208428879
--- /dev/null
+++ b/flang/test/Lower/OpenMP/requires-notarget.f90
@@ -0,0 +1,14 @@
+! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s
+! RUN: bbc -fopenmp -emit-fir %s -o - | FileCheck %s
+! RUN: bbc -fopenmp -fopenmp-is-target-device -emit-fir %s -o - | FileCheck %s
+
+! This test checks that requires lowering into MLIR skips creating the
+! omp.requires attribute with target-related clauses if there are no device
+! functions in the compilation unit
+
+!CHECK:      module attributes {
+!CHECK-NOT:  omp.requires
+program requires
+  !$omp requires unified_shared_memory reverse_offload atomic_default_mem_order(seq_cst)
+end program requires
diff --git a/flang/test/Lower/OpenMP/requires.f90 b/flang/test/Lower/OpenMP/requires.f90
new file mode 100644
index 000000000000000..bc53931b9f240cf
--- /dev/null
+++ b/flang/test/Lower/OpenMP/requires.f90
@@ -0,0 +1,14 @@
+! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s
+! RUN: bbc -fopenmp -emit-fir %s -o - | FileCheck %s
+! RUN: bbc -fopenmp -fopenmp-is-target-device -emit-fir %s -o - | FileCheck %s
+
+! This test checks the lowering of requires into MLIR
+
+!CHECK:      module attributes {
+!CHECK-SAME: omp.requires = #omp<clause_requires reverse_offload|unified_shared_memory>
+program requires
+  !$omp requires unified_shared_memory reverse_offload atomic_default_mem_order(seq_cst)
+  !$omp target
+  !$omp end target
+end program requires

>From f5a5a785081d9087a928df1b7d1b58b2c6be17e1 Mon Sep 17 00:00:00 2001
From: Sergio Afonso <safonsof at amd.com>
Date: Thu, 30 Mar 2023 11:38:23 +0100
Subject: [PATCH 47/86] [OpenMP][Flang][MLIR] Lowering of requires directive
 from MLIR to LLVM IR

Default atomic ordering information is processed in the OpenMP dialect
to LLVM IR lowering stage at every spot where an operation can be
affected by it. The rest of clauses are stored globally in the
OpenMPIRBuilderConfig object before starting that lowering stage, so
that the OMPIRBuilder can conditionally modify code generation
depending on these. At the end of the process, the omp.requires
attribute is itself lowered into a global constructor that passes these
clauses as flags to the OpenMP runtime.

Depends on D147217, D147218 and D158278.

Differential Revision: https://reviews.llvm.org/D147219
---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp         |   7 +-
 .../llvm/Frontend/OpenMP/OMPIRBuilder.h       |  21 +--
 llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp     |  50 +++----
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp      | 129 +++++++++++++++---
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp  |  28 +---
 mlir/test/Target/LLVMIR/openmp-llvm.mlir      |   9 ++
 6 files changed, 165 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 3b69305d050d769..92b7c8d4aa546f0 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -1039,9 +1039,10 @@ CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
       CGM.getLangOpts().OpenMPOffloadMandatory,
       /*HasRequiresReverseOffload*/ false, /*HasRequiresUnifiedAddress*/ false,
       hasRequiresUnifiedSharedMemory(), /*HasRequiresDynamicAllocators*/ false);
-  OMPBuilder.initialize(CGM.getLangOpts().OpenMPIsTargetDevice
-                            ? CGM.getLangOpts().OMPHostIRFile
-                            : StringRef{});
+  OMPBuilder.initialize();
+  OMPBuilder.loadOffloadInfoMetadata(CGM.getLangOpts().OpenMPIsTargetDevice
+                                         ? CGM.getLangOpts().OMPHostIRFile
+                                         : StringRef{});
   OMPBuilder.setConfig(Config);
 }
 
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index a5977356da3e530..523a0718e1ffb53 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -154,6 +154,7 @@ class OpenMPIRBuilderConfig {
 
   void setIsTargetDevice(bool Value) { IsTargetDevice = Value; }
   void setIsGPU(bool Value) { IsGPU = Value; }
+  void setOpenMPOffloadMandatory(bool Value) { OpenMPOffloadMandatory = Value; }
   void setFirstSeparator(StringRef FS) { FirstSeparator = FS; }
   void setSeparator(StringRef S) { Separator = S; }
 
@@ -449,14 +450,9 @@ class OpenMPIRBuilder {
 
   /// Initialize the internal state, this will put structures types and
   /// potentially other helpers into the underlying module. Must be called
-  /// before any other method and only once! This internal state includes
-  /// Types used in the OpenMPIRBuilder generated from OMPKinds.def as well
-  /// as loading offload metadata for device from the OpenMP host IR file
-  /// passed in as the HostFilePath argument.
-  /// \param HostFilePath The path to the host IR file, used to load in
-  /// offload metadata for the device, allowing host and device to
-  /// maintain the same metadata mapping.
-  void initialize(StringRef HostFilePath = {});
+  /// before any other method and only once! This internal state includes types
+  /// used in the OpenMPIRBuilder generated from OMPKinds.def.
+  void initialize();
 
   void setConfig(OpenMPIRBuilderConfig C) { Config = C; }
 
@@ -2519,6 +2515,15 @@ class OpenMPIRBuilder {
   /// loaded from bitcode file, i.e, different from OpenMPIRBuilder::M module.
   void loadOffloadInfoMetadata(Module &M);
 
+  /// Loads all the offload entries information from the host IR
+  /// metadata read from the file passed in as the HostFilePath argument. This
+  /// function is only meant to be used with device code generation.
+  ///
+  /// \param HostFilePath The path to the host IR file,
+  /// used to load in offload metadata for the device, allowing host and device
+  /// to maintain the same metadata mapping.
+  void loadOffloadInfoMetadata(StringRef HostFilePath);
+
   /// Gets (if variable with the given name already exist) or creates
   /// internal global variable with the specified Name. The created variable has
   /// linkage CommonLinkage by default and is initialized by null value.
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index cc6054cb19d7806..9341c529c603e5d 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -582,31 +582,7 @@ Function *OpenMPIRBuilder::getOrCreateRuntimeFunctionPtr(RuntimeFunction FnID) {
   return Fn;
 }
 
-void OpenMPIRBuilder::initialize(StringRef HostFilePath) {
-  initializeTypes(M);
-
-  if (HostFilePath.empty())
-    return;
-
-  auto Buf = MemoryBuffer::getFile(HostFilePath);
-  if (std::error_code Err = Buf.getError()) {
-    report_fatal_error(("error opening host file from host file path inside of "
-                        "OpenMPIRBuilder: " +
-                        Err.message())
-                           .c_str());
-  }
-
-  LLVMContext Ctx;
-  auto M = expectedToErrorOrAndEmitErrors(
-      Ctx, parseBitcodeFile(Buf.get()->getMemBufferRef(), Ctx));
-  if (std::error_code Err = M.getError()) {
-    report_fatal_error(
-        ("error parsing host file inside of OpenMPIRBuilder: " + Err.message())
-            .c_str());
-  }
-
-  loadOffloadInfoMetadata(*M.get());
-}
+void OpenMPIRBuilder::initialize() { initializeTypes(M); }
 
 void OpenMPIRBuilder::finalize(Function *Fn) {
   SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
@@ -6206,6 +6182,30 @@ void OpenMPIRBuilder::loadOffloadInfoMetadata(Module &M) {
   }
 }
 
+void OpenMPIRBuilder::loadOffloadInfoMetadata(StringRef HostFilePath) {
+  if (HostFilePath.empty())
+    return;
+
+  auto Buf = MemoryBuffer::getFile(HostFilePath);
+  if (std::error_code Err = Buf.getError()) {
+    report_fatal_error(("error opening host file from host file path inside of "
+                        "OpenMPIRBuilder: " +
+                        Err.message())
+                           .c_str());
+  }
+
+  LLVMContext Ctx;
+  auto M = expectedToErrorOrAndEmitErrors(
+      Ctx, parseBitcodeFile(Buf.get()->getMemBufferRef(), Ctx));
+  if (std::error_code Err = M.getError()) {
+    report_fatal_error(
+        ("error parsing host file inside of OpenMPIRBuilder: " + Err.message())
+            .c_str());
+  }
+
+  loadOffloadInfoMetadata(*M.get());
+}
+
 Function *OpenMPIRBuilder::createRegisterRequires(StringRef Name) {
   // Skip the creation of the registration function if this is device codegen
   if (Config.isTargetDevice())
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 3181b5710c60708..dcc5e3823d663a8 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -17,6 +17,7 @@
 #include "mlir/IR/IRMapping.h"
 #include "mlir/IR/Operation.h"
 #include "mlir/Support/LLVM.h"
+#include "mlir/Support/LogicalResult.h"
 #include "mlir/Target/LLVMIR/Dialect/OpenMPCommon.h"
 #include "mlir/Target/LLVMIR/ModuleTranslation.h"
 #include "mlir/Transforms/RegionUtils.h"
@@ -28,6 +29,8 @@
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
+#include <optional>
 
 using namespace mlir;
 
@@ -1165,7 +1168,7 @@ convertOmpSimdLoop(Operation &opInst, llvm::IRBuilderBase &builder,
 }
 
 /// Convert an Atomic Ordering attribute to llvm::AtomicOrdering.
-llvm::AtomicOrdering
+static llvm::AtomicOrdering
 convertAtomicOrdering(std::optional<omp::ClauseMemoryOrderKind> ao) {
   if (!ao)
     return llvm::AtomicOrdering::Monotonic; // Default Memory Ordering
@@ -1932,6 +1935,27 @@ convertDeclareTargetAttr(Operation *op,
   return success();
 }
 
+/// Converts the module-level set of OpenMP requires clauses into LLVM IR using
+/// OpenMPIRBuilder.
+static LogicalResult
+convertRequiresAttr(Operation &op, omp::ClauseRequiresAttr requiresAttr,
+                    LLVM::ModuleTranslation &moduleTranslation) {
+  auto *ompBuilder = moduleTranslation.getOpenMPBuilder();
+
+  // No need to read requiresAttr here, because it has already been done in
+  // translateModuleToLLVMIR(). There, flags are stored in the
+  // OpenMPIRBuilderConfig object, available to the OpenMPIRBuilder.
+  auto *regFn =
+      ompBuilder->createRegisterRequires(ompBuilder->createPlatformSpecificName(
+          {"omp_offloading", "requires_reg"}));
+
+  // Add registration function as global constructor
+  if (regFn)
+    llvm::appendToGlobalCtors(ompBuilder->M, regFn, /* Priority = */ 0);
+
+  return success();
+}
+
 namespace {
 
 /// Implementation of the dialect interface that converts operations belonging
@@ -1947,6 +1971,8 @@ class OpenMPDialectLLVMIRTranslationInterface
   convertOperation(Operation *op, llvm::IRBuilderBase &builder,
                    LLVM::ModuleTranslation &moduleTranslation) const final;
 
+  /// Given an OpenMP MLIR attribute, create the corresponding LLVM-IR, runtime
+  /// calls, or operation amendments
   LogicalResult
   amendOperation(Operation *op, NamedAttribute attribute,
                  LLVM::ModuleTranslation &moduleTranslation) const final;
@@ -1954,31 +1980,90 @@ class OpenMPDialectLLVMIRTranslationInterface
 
 } // namespace
 
-/// Given an OpenMP MLIR attribute, create the corresponding LLVM-IR, runtime
-/// calls, or operation amendments
 LogicalResult OpenMPDialectLLVMIRTranslationInterface::amendOperation(
     Operation *op, NamedAttribute attribute,
     LLVM::ModuleTranslation &moduleTranslation) const {
-  return llvm::TypeSwitch<Attribute, LogicalResult>(attribute.getValue())
-      .Case([&](mlir::omp::FlagsAttr rtlAttr) {
-        return convertFlagsAttr(op, rtlAttr, moduleTranslation);
-      })
-      .Case([&](mlir::omp::VersionAttr versionAttr) {
-        llvm::OpenMPIRBuilder *ompBuilder =
-            moduleTranslation.getOpenMPBuilder();
-        ompBuilder->M.addModuleFlag(llvm::Module::Max, "openmp",
-                                    versionAttr.getVersion());
-        return success();
-      })
-      .Case([&](mlir::omp::DeclareTargetAttr declareTargetAttr) {
-        return convertDeclareTargetAttr(op, declareTargetAttr,
-                                        moduleTranslation);
-      })
-      .Default([&](Attribute attr) {
-        // fall through for omp attributes that do not require lowering and/or
-        // have no concrete definition and thus no type to define a case on
+  return llvm::StringSwitch<llvm::function_ref<LogicalResult(Attribute)>>(
+             attribute.getName())
+      .Case("omp.is_target_device",
+            [&](Attribute attr) {
+              if (auto deviceAttr = attr.dyn_cast<BoolAttr>()) {
+                llvm::OpenMPIRBuilderConfig &config =
+                    moduleTranslation.getOpenMPBuilder()->Config;
+                config.setIsTargetDevice(deviceAttr.getValue());
+                return success();
+              }
+              return failure();
+            })
+      .Case("omp.is_gpu",
+            [&](Attribute attr) {
+              if (auto gpuAttr = attr.dyn_cast<BoolAttr>()) {
+                llvm::OpenMPIRBuilderConfig &config =
+                    moduleTranslation.getOpenMPBuilder()->Config;
+                config.setIsGPU(gpuAttr.getValue());
+                return success();
+              }
+              return failure();
+            })
+      .Case("omp.host_ir_filepath",
+            [&](Attribute attr) {
+              if (auto filepathAttr = attr.dyn_cast<StringAttr>()) {
+                llvm::OpenMPIRBuilder *ompBuilder =
+                    moduleTranslation.getOpenMPBuilder();
+                ompBuilder->loadOffloadInfoMetadata(filepathAttr.getValue());
+                return success();
+              }
+              return failure();
+            })
+      .Case("omp.flags",
+            [&](Attribute attr) {
+              if (auto rtlAttr = attr.dyn_cast<omp::FlagsAttr>())
+                return convertFlagsAttr(op, rtlAttr, moduleTranslation);
+              return failure();
+            })
+      .Case("omp.version",
+            [&](Attribute attr) {
+              if (auto versionAttr = attr.dyn_cast<omp::VersionAttr>()) {
+                llvm::OpenMPIRBuilder *ompBuilder =
+                    moduleTranslation.getOpenMPBuilder();
+                ompBuilder->M.addModuleFlag(llvm::Module::Max, "openmp",
+                                            versionAttr.getVersion());
+                return success();
+              }
+              return failure();
+            })
+      .Case("omp.declare_target",
+            [&](Attribute attr) {
+              if (auto declareTargetAttr =
+                      attr.dyn_cast<omp::DeclareTargetAttr>())
+                return convertDeclareTargetAttr(op, declareTargetAttr,
+                                                moduleTranslation);
+              return failure();
+            })
+      .Case(
+          "omp.requires",
+          [&](Attribute attr) {
+            if (auto requiresAttr = attr.dyn_cast<omp::ClauseRequiresAttr>()) {
+              using Requires = omp::ClauseRequires;
+              Requires flags = requiresAttr.getValue();
+              llvm::OpenMPIRBuilderConfig &config =
+                  moduleTranslation.getOpenMPBuilder()->Config;
+              config.setHasRequiresReverseOffload(
+                  bitEnumContainsAll(flags, Requires::reverse_offload));
+              config.setHasRequiresUnifiedAddress(
+                  bitEnumContainsAll(flags, Requires::unified_address));
+              config.setHasRequiresUnifiedSharedMemory(
+                  bitEnumContainsAll(flags, Requires::unified_shared_memory));
+              config.setHasRequiresDynamicAllocators(
+                  bitEnumContainsAll(flags, Requires::dynamic_allocators));
+              return convertRequiresAttr(*op, requiresAttr, moduleTranslation);
+            }
+            return failure();
+          })
+      .Default([](Attribute) {
+        // Fall through for omp attributes that do not require lowering.
         return success();
-      });
+      })(attribute.getValue());
 
   return failure();
 }
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index e3ece38b6b8ca9a..0b0a0d1559144a6 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1278,32 +1278,18 @@ SmallVector<llvm::Value *> ModuleTranslation::lookupValues(ValueRange values) {
 llvm::OpenMPIRBuilder *ModuleTranslation::getOpenMPBuilder() {
   if (!ompBuilder) {
     ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
+    ompBuilder->initialize();
 
-    bool isTargetDevice = false, isGPU = false;
-    llvm::StringRef hostIRFilePath = "";
-
-    if (auto deviceAttr =
-            mlirModule->getAttrOfType<mlir::BoolAttr>("omp.is_target_device"))
-      isTargetDevice = deviceAttr.getValue();
-
-    if (auto gpuAttr = mlirModule->getAttrOfType<mlir::BoolAttr>("omp.is_gpu"))
-      isGPU = gpuAttr.getValue();
-
-    if (auto filepathAttr =
-            mlirModule->getAttrOfType<mlir::StringAttr>("omp.host_ir_filepath"))
-      hostIRFilePath = filepathAttr.getValue();
-
-    ompBuilder->initialize(hostIRFilePath);
-
-    // TODO: set the flags when available
-    llvm::OpenMPIRBuilderConfig config(
-        isTargetDevice, isGPU,
+    // Flags represented as top-level OpenMP dialect attributes are set in
+    // `OpenMPDialectLLVMIRTranslationInterface::amendOperation()`. Here we set
+    // the default configuration.
+    ompBuilder->setConfig(llvm::OpenMPIRBuilderConfig(
+        /* IsTargetDevice = */ false, /* IsGPU = */ false,
         /* OpenMPOffloadMandatory = */ false,
         /* HasRequiresReverseOffload = */ false,
         /* HasRequiresUnifiedAddress = */ false,
         /* HasRequiresUnifiedSharedMemory = */ false,
-        /* HasRequiresDynamicAllocators = */ false);
-    ompBuilder->setConfig(config);
+        /* HasRequiresDynamicAllocators = */ false));
   }
   return ompBuilder.get();
 }
diff --git a/mlir/test/Target/LLVMIR/openmp-llvm.mlir b/mlir/test/Target/LLVMIR/openmp-llvm.mlir
index 73b6b007e5a56b5..1dff33cdc22ce12 100644
--- a/mlir/test/Target/LLVMIR/openmp-llvm.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-llvm.mlir
@@ -2661,3 +2661,12 @@ llvm.func @omp_task_if(%boolexpr: i1) {
 // CHECK:         call void @foo_after()
 // CHECK:         ret void
 
+// -----
+
+// Check that OpenMP requires flags are registered by a global constructor.
+// CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }]
+// CHECK-SAME: [{ i32, ptr, ptr } { i32 0, ptr @[[REG_FN:.*]], ptr null }]
+// CHECK: define {{.*}} @[[REG_FN]]({{.*}})
+// CHECK-NOT: }
+// CHECK:   call void @__tgt_register_requires(i64 10)
+module attributes {omp.requires = #omp<clause_requires reverse_offload|unified_shared_memory>} {}

>From fc38b5ca080d42f7d58d37961d0e2c72b15f8199 Mon Sep 17 00:00:00 2001
From: Carlo Bramini <carlo_bramini at users.sourceforge.net>
Date: Thu, 14 Sep 2023 12:41:03 +0300
Subject: [PATCH 48/86] [flang/mlir] Fix "file too big" build error on CYGWIN.

Attached patch fixes issues #63582 and #57718 when building my port to CYGWIN of llvm-project.
https://github.com/llvm/llvm-project/issues/63582
https://github.com/llvm/llvm-project/issues/57718

Reviewed By: mstorsjo

Differential Revision: https://reviews.llvm.org/D159404
---
 llvm/cmake/modules/HandleLLVMOptions.cmake | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake
index 29b242d80051f0d..4e87c6d1c3eb868 100644
--- a/llvm/cmake/modules/HandleLLVMOptions.cmake
+++ b/llvm/cmake/modules/HandleLLVMOptions.cmake
@@ -458,7 +458,7 @@ if(MSVC)
   # value (1 MB) which is not enough for us in tasks such as parsing recursive
   # C++ templates in Clang.
   set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:10000000")
-elseif(MINGW) # FIXME: Also cygwin?
+elseif(MINGW OR CYGWIN)
   set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--stack,16777216")
 
   # Pass -mbig-obj to mingw gas to avoid COFF 2**16 section limit.

>From eaddf113976e05355e396f6ee76acb298a62a92b Mon Sep 17 00:00:00 2001
From: DonatNagyE <donat.nagy at ericsson.com>
Date: Thu, 14 Sep 2023 11:51:46 +0200
Subject: [PATCH 49/86] [analyzer] Fix StdLibraryFunctionsChecker crash on
 surprising sink node (#66109)

Recent changes in StdLibraryFunctionsChecker introduced a situation
where the checker sequentially performed two state transitions to add
two separate note tags.

In the unlikely case when the updated state (the variable `NewState`)
was posteriorly overconstrained, the engine marked the node after the
first state transition as a sink to stop the "natural" graph exploration
after that point.

However, in this particular case the checker tried to directly add a
second node, and this triggered an assertion in the `addPredecessor()`
method of `ExplodedNode`.

This commit introduces an explicit `isSink()` check to avoid this crash.
To avoid similar bugs in the future, perhaps it would be possible to
tweak `addTransition()` and ensure that it returns `nullptr` when it
would return a sink node (to unify the two possible error conditions).

This crash was observed in an analysis of the curl project (in a very
long and complex function), and there I validated that this is the root
cause, but I don't have a self-contained testcase that can trigger the
creation of a PosteriorlyOverconstrained node in this situation.
---
 .../Checkers/StdLibraryFunctionsChecker.cpp           | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index f5f6e3a91237686..13bb9cef5e490ed 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -1387,8 +1387,8 @@ void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call,
     if (!NewState)
       continue;
 
-    // It is possible that NewState == State is true.
-    // It can occur if another checker has applied the state before us.
+    // Here it's possible that NewState == State, e.g. when other checkers
+    // already applied the same constraints (or stricter ones).
     // Still add these note tags, the other checker should add only its
     // specialized note tags. These general note tags are handled always by
     // StdLibraryFunctionsChecker.
@@ -1427,7 +1427,12 @@ void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call,
             });
         Pred = C.addTransition(NewState, Pred, Tag);
       }
-      if (!Pred)
+
+      // Pred may be:
+      //  - a nullpointer, if we reach an already existing node (theoretically);
+      //  - a sink, when NewState is posteriorly overconstrained.
+      // In these situations we cannot add the errno note tag.
+      if (!Pred || Pred->isSink())
         continue;
     }
 

>From 68f9dc58e3494e614d92d39d8048dfa73639738f Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 14 Sep 2023 11:55:10 +0200
Subject: [PATCH 50/86] [analyzer] Fix stdin declaration in C++ tests (#66074)

The `stdin` declaration should be within `extern "C" {...}`, in C++
mode. In addition, it should be also marked `extern` in both C and
C++ modes.

I tightened the check to ensure we only accept `stdin` if both of these
match. However, from the Juliet test suite's perspective, this commit
should not matter.

https://github.com/llvm/llvm-project/pull/66074
---
 .../StaticAnalyzer/Checkers/GenericTaintChecker.cpp  |  3 +--
 clang/test/Analysis/taint-diagnostic-visitor.c       |  2 +-
 clang/test/Analysis/taint-generic.cpp                | 12 ++++++++++++
 3 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 3dcb45c0b110383..8138c8411fb2613 100644
--- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -104,8 +104,7 @@ bool isStdin(SVal Val, const ASTContext &ACtx) {
   // variable named stdin with the proper type.
   if (const auto *D = dyn_cast_or_null<VarDecl>(DeclReg->getDecl())) {
     D = D->getCanonicalDecl();
-    // FIXME: This should look for an exact match.
-    if (D->getName().contains("stdin") && D->isExternC()) {
+    if (D->getName() == "stdin" && D->hasExternalStorage() && D->isExternC()) {
       const QualType FILETy = ACtx.getFILEType().getCanonicalType();
       const QualType Ty = D->getType().getCanonicalType();
 
diff --git a/clang/test/Analysis/taint-diagnostic-visitor.c b/clang/test/Analysis/taint-diagnostic-visitor.c
index 663836836d3db67..f1b9ceebdd9a6b8 100644
--- a/clang/test/Analysis/taint-diagnostic-visitor.c
+++ b/clang/test/Analysis/taint-diagnostic-visitor.c
@@ -13,7 +13,7 @@ size_t strlen( const char* str );
 void *malloc(size_t size );
 void free( void *ptr );
 char *fgets(char *str, int n, FILE *stream);
-FILE *stdin;
+extern FILE *stdin;
 
 void taintDiagnostic(void)
 {
diff --git a/clang/test/Analysis/taint-generic.cpp b/clang/test/Analysis/taint-generic.cpp
index 09cd54471948e1a..c907c8f5eeb958b 100644
--- a/clang/test/Analysis/taint-generic.cpp
+++ b/clang/test/Analysis/taint-generic.cpp
@@ -7,6 +7,12 @@ int scanf(const char*, ...);
 int mySource1();
 int mySource3();
 
+typedef struct _FILE FILE;
+extern "C" {
+extern FILE *stdin;
+}
+int fscanf(FILE *stream, const char *format, ...);
+
 bool isOutOfRange2(const int*);
 
 void mySink2(int);
@@ -124,3 +130,9 @@ void testConfigurationMemberFunc() {
   foo.myMemberScanf("%d", &x);
   Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
 }
+
+void testReadingFromStdin(char **p) {
+  int n;
+  fscanf(stdin, "%d", &n);
+  Buffer[n] = 1; // expected-warning {{Out of bound memory access (index is tainted)}}
+}

>From db2360de11b3360e99a961907e984f772d0aaa15 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 14 Sep 2023 11:55:10 +0200
Subject: [PATCH 51/86] [analyzer] Make socket `accept()` propagate taint
 (#66074)

This allows to track taint on real code from `socket()`
to reading into a buffer using `recv()`.

https://github.com/llvm/llvm-project/pull/66074
---
 .../StaticAnalyzer/Checkers/GenericTaintChecker.cpp   |  1 +
 clang/test/Analysis/taint-generic.c                   | 11 +++++++++++
 2 files changed, 12 insertions(+)

diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 8138c8411fb2613..54c3f6dcdddaf59 100644
--- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -621,6 +621,7 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const {
       {{{"getlogin_r"}}, TR::Source({{0}})},
 
       // Props
+      {{{"accept"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
       {{{"atoi"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
       {{{"atol"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
       {{{"atoll"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
diff --git a/clang/test/Analysis/taint-generic.c b/clang/test/Analysis/taint-generic.c
index b7906d201e4fad3..e58b9c71a757821 100644
--- a/clang/test/Analysis/taint-generic.c
+++ b/clang/test/Analysis/taint-generic.c
@@ -544,6 +544,10 @@ void testFread(const char *fname, int *buffer, size_t size, size_t count) {
 }
 
 ssize_t recv(int sockfd, void *buf, size_t len, int flags);
+int accept(int fd, struct sockaddr *addr, socklen_t *addrlen);
+int bind(int fd, const struct sockaddr *addr, socklen_t addrlen);
+int listen(int fd, int backlog);
+
 void testRecv(int *buf, size_t len, int flags) {
   int fd;
   scanf("%d", &fd); // fake a tainted a file descriptor
@@ -1107,3 +1111,10 @@ void testProctitle2(char *real_argv[]) {
   setproctitle_init(1, argv, 0);         // expected-warning {{Untrusted data is passed to a user-defined sink}}
   setproctitle_init(1, real_argv, argv); // expected-warning {{Untrusted data is passed to a user-defined sink}}
 }
+
+void testAcceptPropagates() {
+  int listenSocket = socket(2, 1, 6);
+  clang_analyzer_isTainted_int(listenSocket); // expected-warning {{YES}}
+  int acceptSocket = accept(listenSocket, 0, 0);
+  clang_analyzer_isTainted_int(acceptSocket); // expected-warning {{YES}}
+}

>From e6bf958179acdafaffc9112d4a2e5a3645a7b366 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 14 Sep 2023 11:55:10 +0200
Subject: [PATCH 52/86] [analyzer] Propagate taint for wchar variants of some
 APIs (#66074)

Functions like `fgets`, `strlen`, `strcat` propagate taint.
However, their `wchar_t` variants don't. This patch fixes that.

Notice, that there could be many more APIs missing.
This patch intends to fix those that so far surfaced,
instead of exhaustively fixing this issue.

https://github.com/llvm/llvm-project/pull/66074
---
 .../Checkers/GenericTaintChecker.cpp          |  4 ++
 clang/test/Analysis/taint-generic.c           | 39 ++++++++++++++++---
 2 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 54c3f6dcdddaf59..5da0f34b3d0464f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -628,6 +628,7 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const {
       {{{"fgetc"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
       {{{"fgetln"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
       {{{"fgets"}}, TR::Prop({{2}}, {{0, ReturnValueIndex}})},
+      {{{"fgetws"}}, TR::Prop({{2}}, {{0, ReturnValueIndex}})},
       {{{"fscanf"}}, TR::Prop({{0}}, {{}, 2})},
       {{{"fscanf_s"}}, TR::Prop({{0}}, {{}, {2}})},
       {{{"sscanf"}}, TR::Prop({{0}}, {{}, 2})},
@@ -695,6 +696,7 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const {
       {{{"strndup"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
       {{{"strndupa"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
       {{{"strlen"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{{"wcslen"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
       {{{"strnlen"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
       {{{"strtol"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
       {{{"strtoll"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})},
@@ -731,6 +733,8 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const {
        TR::Prop({{1}}, {{0, ReturnValueIndex}})},
       {{CDF_MaybeBuiltin, {{"strcat"}}},
        TR::Prop({{1}}, {{0, ReturnValueIndex}})},
+      {{CDF_MaybeBuiltin, {{"wcsncat"}}},
+       TR::Prop({{1}}, {{0, ReturnValueIndex}})},
       {{CDF_MaybeBuiltin, {{"strdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
       {{CDF_MaybeBuiltin, {{"strdupa"}}},
        TR::Prop({{0}}, {{ReturnValueIndex}})},
diff --git a/clang/test/Analysis/taint-generic.c b/clang/test/Analysis/taint-generic.c
index e58b9c71a757821..f08186fc8c4c1e5 100644
--- a/clang/test/Analysis/taint-generic.c
+++ b/clang/test/Analysis/taint-generic.c
@@ -56,7 +56,10 @@
 // CHECK-INVALID-ARG-SAME:        rules greater or equal to -1
 
 typedef long long rsize_t;
+typedef typeof(sizeof(int)) size_t;
+typedef __WCHAR_TYPE__ wchar_t;
 void clang_analyzer_isTainted_char(char);
+void clang_analyzer_isTainted_wchar(wchar_t);
 void clang_analyzer_isTainted_charp(char*);
 void clang_analyzer_isTainted_int(int);
 
@@ -75,6 +78,17 @@ extern FILE *stdin;
 #define bool _Bool
 #define NULL (void*)0
 
+wchar_t *fgetws(wchar_t *ws, int n, FILE *stream);
+wchar_t *wmemset(wchar_t *wcs, wchar_t wc, unsigned long n);
+wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t n);
+wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t n);
+size_t wcslen(const wchar_t *s);
+wchar_t *wcscpy(wchar_t * dest, const wchar_t * src);
+wchar_t *wcsncpy(wchar_t *dest, const wchar_t *src, size_t n);
+wchar_t *wcscat(wchar_t *dest, const wchar_t *src);
+wchar_t *wcsncat(wchar_t *dest,const wchar_t *src, size_t n);
+int swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...);
+
 char *getenv(const char *name);
 
 FILE *fopen(const char *name, const char *mode);
@@ -430,6 +444,24 @@ int testSprintf_propagates_taint(char *buf, char *msg) {
   return 1 / x;                    // expected-warning {{Division by a tainted value, possibly zero}}
 }
 
+void test_wchar_apis_propagate(const char *path) {
+  FILE *f = fopen(path, "r");
+  clang_analyzer_isTainted_charp((char*)f);  // expected-warning {{YES}}
+  wchar_t wbuf[10];
+  fgetws(wbuf, sizeof(wbuf)/sizeof(*wbuf), f);
+  clang_analyzer_isTainted_wchar(*wbuf); // expected-warning {{YES}}
+  int n = wcslen(wbuf);
+  clang_analyzer_isTainted_int(n); // expected-warning {{YES}}
+
+  wchar_t dst[100] = L"ABC";
+  clang_analyzer_isTainted_wchar(*dst); // expected-warning {{NO}}
+  wcsncat(dst, wbuf, sizeof(wbuf)/sizeof(*wbuf));
+  clang_analyzer_isTainted_wchar(*dst); // expected-warning {{YES}}
+
+  int m = wcslen(dst);
+  clang_analyzer_isTainted_int(m); // expected-warning {{YES}}
+}
+
 int scanf_s(const char *format, ...);
 int testScanf_s_(int *out) {
   scanf_s("%d", out);
@@ -644,7 +676,6 @@ void testRawmemchr(int c) {
   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
 }
 
-typedef char wchar_t;
 int mbtowc(wchar_t *pwc, const char *s, size_t n);
 void testMbtowc(wchar_t *pwc, size_t n) {
   char buf[10];
@@ -657,8 +688,7 @@ void testMbtowc(wchar_t *pwc, size_t n) {
 
 int wctomb(char *s, wchar_t wc);
 void testWctomb(char *buf) {
-  wchar_t wc;
-  scanf("%c", &wc);
+  wchar_t wc = getchar();
 
   int result = wctomb(buf, wc);
   clang_analyzer_isTainted_char(*buf); // expected-warning {{YES}}
@@ -667,8 +697,7 @@ void testWctomb(char *buf) {
 
 int wcwidth(wchar_t c);
 void testWcwidth() {
-  wchar_t wc;
-  scanf("%c", &wc);
+  wchar_t wc = getchar();
 
   int width = wcwidth(wc);
   clang_analyzer_isTainted_int(width); // expected-warning {{YES}}

>From 235f91c93716600b13c8056d501de170bc31a439 Mon Sep 17 00:00:00 2001
From: M Iyengar <max.iyengar at arm.com>
Date: Thu, 14 Sep 2023 11:00:49 +0100
Subject: [PATCH 53/86] [AArch64][Clang] Implement ACLE rintn intrinsics
 (#66112)

This patch adds support for two missing ACLE intrinsics for floating
point round with ties to even:

- rintn
- rintnf

These are specified in ACLE section 8.6:
[https://arm-software.github.io/acle/main/acle.html#floating-point-data-processing-intrinsics]
---
 clang/lib/Headers/arm_acle.h  | 15 +++++++++++++++
 clang/test/CodeGen/arm_acle.c | 16 ++++++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/clang/lib/Headers/arm_acle.h b/clang/lib/Headers/arm_acle.h
index c208512bab59829..61d80258d166a1d 100644
--- a/clang/lib/Headers/arm_acle.h
+++ b/clang/lib/Headers/arm_acle.h
@@ -592,6 +592,21 @@ __smusdx(int16x2_t __a, int16x2_t __b) {
 }
 #endif
 
+/* 8.6 Floating-point data-processing intrinsics */
+#if (defined(__ARM_FEATURE_DIRECTED_ROUNDING)    &&                         \
+  (__ARM_FEATURE_DIRECTED_ROUNDING))             &&                         \
+  (defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE)
+static __inline__ double __attribute__((__always_inline__, __nodebug__))
+__rintn(double __a) {
+  return __builtin_roundeven(__a);
+}
+
+static __inline__ float __attribute__((__always_inline__, __nodebug__))
+__rintnf(float __a) {
+  return __builtin_roundevenf(__a);
+}
+#endif
+
 /* 9.7 CRC32 intrinsics */
 #if (defined(__ARM_FEATURE_CRC32) && __ARM_FEATURE_CRC32) ||                   \
     (defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE)
diff --git a/clang/test/CodeGen/arm_acle.c b/clang/test/CodeGen/arm_acle.c
index b1105a1d5aabb64..00afaf15fded392 100644
--- a/clang/test/CodeGen/arm_acle.c
+++ b/clang/test/CodeGen/arm_acle.c
@@ -1690,6 +1690,22 @@ int32_t test_jcvt(double v) {
 }
 #endif
 
+#if defined(__ARM_FEATURE_DIRECTED_ROUNDING) && defined(__ARM_64BIT_STATE)
+
+// AArch64-LABEL: @test_rintn(
+// AArch64-NEXT:  entry:
+// AArch64-NEXT:    call double @llvm.roundeven.f64(double [[TMP0:%.*]])
+double test_rintn(double a) {
+  return __rintn(a);
+}
+
+// AArch64-LABEL: @test_rintnf(
+// AArch64-NEXT: entry:
+// AArch64-NEXT:      call float @llvm.roundeven.f32(float [[TMP0:%.*]])
+float test_rintnf(float b) {
+  return __rintnf(b);
+}
+#endif
 
 #if defined(__ARM_64BIT_STATE) && defined(__ARM_FEATURE_RNG)
 

>From 2e41f2aa9b03e57e834b44de7e46057a08889ba1 Mon Sep 17 00:00:00 2001
From: Martin Erhart <merhart at google.com>
Date: Thu, 14 Sep 2023 12:13:37 +0200
Subject: [PATCH 54/86] [mlir][bufferization] Add an ownership based buffer
 deallocation pass (#66337)

Add a new Buffer Deallocation pass with the intend to replace the old
one. For now it is added as a separate pass alongside in order to allow
downstream users to migrate over gradually. This new pass has the goal
of inserting fewer clone operations and supporting additional use-cases.
Please refer to the Buffer Deallocation section in the updated
Bufferization.md file for more information on how this new pass works.
---
 mlir/docs/Bufferization.md                    |  604 +++++++
 .../Bufferization/Transforms/BufferUtils.h    |    8 +
 .../Dialect/Bufferization/Transforms/Passes.h |    9 +
 .../Bufferization/Transforms/Passes.td        |  144 ++
 .../Bufferization/Transforms/BufferUtils.cpp  |   59 +
 .../Bufferization/Transforms/CMakeLists.txt   |    2 +
 .../OwnershipBasedBufferDeallocation.cpp      | 1383 +++++++++++++++++
 .../dealloc-branchop-interface.mlir           |  589 +++++++
 .../dealloc-callop-interface.mlir             |  113 ++
 .../dealloc-existing-deallocs.mlir            |   43 +
 .../dealloc-function-boundaries.mlir          |  131 ++
 .../dealloc-memoryeffect-interface.mlir       |  124 ++
 .../dealloc-region-branchop-interface.mlir    |  695 +++++++++
 .../dealloc-subviews.mlir                     |   21 +
 .../invalid-buffer-deallocation.mlir          |   93 ++
 .../llvm-project-overlay/mlir/BUILD.bazel     |    1 +
 16 files changed, 4019 insertions(+)
 create mode 100644 mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp
 create mode 100644 mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-branchop-interface.mlir
 create mode 100644 mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-callop-interface.mlir
 create mode 100644 mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-existing-deallocs.mlir
 create mode 100644 mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-function-boundaries.mlir
 create mode 100644 mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-memoryeffect-interface.mlir
 create mode 100644 mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-region-branchop-interface.mlir
 create mode 100644 mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-subviews.mlir
 create mode 100644 mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/invalid-buffer-deallocation.mlir

diff --git a/mlir/docs/Bufferization.md b/mlir/docs/Bufferization.md
index f03d7bb877c9c74..09bec06743c7a65 100644
--- a/mlir/docs/Bufferization.md
+++ b/mlir/docs/Bufferization.md
@@ -224,6 +224,9 @@ dialect conversion-based bufferization.
 
 ## Buffer Deallocation
 
+**Important: this pass is deprecated, please use the ownership based buffer**
+**deallocation pass instead**
+
 One-Shot Bufferize deallocates all buffers that it allocates. This is in
 contrast to the dialect conversion-based bufferization that delegates this job
 to the
@@ -300,6 +303,607 @@ One-Shot Bufferize can be configured to leak all memory and not generate any
 buffer deallocations with `create-deallocs=0`. This can be useful for
 compatibility with legacy code that has its own method of deallocating buffers.
 
+## Ownership-based Buffer Deallocation
+
+Recommended compilation pipeline:
+```
+one-shot-bufferize
+       |          it's recommended to perform all bufferization here at latest,
+       |       <- any allocations inserted after this point have to be handled
+       V          manually
+expand-realloc
+       V
+ownership-based-buffer-deallocation
+       V
+  canonicalize <- mostly for scf.if simplifications
+       V
+buffer-deallocation-simplification
+       V       <- from this point onwards no tensor values are allowed
+lower-deallocations
+       V
+      CSE
+       V
+  canonicalize
+```
+
+One-Shot Bufferize does not deallocate any buffers that it allocates. This job
+is delegated to the
+[`-ownership-based-buffer-deallocation`](https://mlir.llvm.org/docs/Passes/#-ownership-based-buffer-deallocation)
+pass, i.e., after running One-Shot Bufferize, the result IR may have a number of
+`memref.alloc` ops, but no `memref.dealloc` ops. This pass processes operations
+implementing `FunctionOpInterface` one-by-one without analysing the call-graph.
+This means, that there have to be [some rules](#function-boundary-abi) on how
+MemRefs are handled when being passed from one function to another. The rest of
+the pass revolves heavily around the `bufferization.dealloc` operation which is
+inserted at the end of each basic block with appropriate operands and should be
+optimized using the Buffer Deallocation Simplification pass
+(`--buffer-deallocation-simplification`) and the regular canonicalizer
+(`--canonicalize`). Lowering the result of the
+`-ownership-based-buffer-deallocation` pass directly using
+`--convert-bufferization-to-memref` without beforehand optimization is not
+recommended as it will lead to very inefficient code (the runtime-cost of
+`bufferization.dealloc` is `O(|memrefs|^2+|memref|*|retained|)`).
+
+### Function boundary ABI
+
+The Buffer Deallocation pass operates on the level of operations implementing
+the `FunctionOpInterface`. Such operations can take MemRefs as arguments, but
+also return them. To ensure compatibility among all functions (including
+external ones), some rules have to be enforced:
+*   When a MemRef is passed as a function argument, ownership is never acquired.
+    It is always the caller's responsibility to deallocate such MemRefs.
+*   Returning a MemRef from a function always passes ownership to the caller,
+    i.e., it is also the caller's responsibility to deallocate memrefs returned
+    from a called function.
+*   A function must not return a MemRef with the same allocated base buffer as
+    one of its arguments (in this case a copy has to be created). Note that in
+    this context two subviews of the same buffer that don't overlap are also
+    considered to alias.
+
+For external functions (e.g., library functions written externally in C), the
+externally provided implementation has to adhere to these rules and they are
+just assumed by the buffer deallocation pass. Functions on which the
+deallocation pass is applied and the implementation is accessible are modified
+by the pass such that the ABI is respected (i.e., buffer copies are inserted as
+necessary).
+
+### Inserting `bufferization.dealloc` operations
+
+`bufferization.dealloc` operations are unconditionally inserted at the end of
+each basic block (just before the terminator). The majority of the pass is about
+finding the correct operands for this operation. There are three variadic
+operand lists to be populated, the first contains all MemRef values that may
+need to be deallocated, the second list contains their associated ownership
+values (of `i1` type), and the third list contains MemRef values that are still
+needed at a later point and should thus not be deallocated. This operation
+allows us to deal with any kind of aliasing behavior: it lowers to runtime
+aliasing checks when not enough information can be collected statically. When
+enough aliasing information is statically available, operands or the entire op
+may fold away.
+
+**Ownerships**
+
+To do so, we use a concept of ownership indicators of memrefs which materialize
+as an `i1` value for any SSA value of `memref` type, indicating whether the
+basic block in which it was materialized has ownership of this MemRef. Ideally,
+this is a constant `true` or `false`, but might also be a non-constant SSA
+value. To keep track of those ownership values without immediately materializing
+them (which might require insertion of `bufferization.clone` operations or
+operations checking for aliasing at runtime at positions where we don't actually
+need a materialized value), we use the `Ownership` class. This class represents
+the ownership in three states forming a lattice on a partial order:
+```
+forall X in SSA values. uninitialized < unique(X) < unknown
+forall X, Y in SSA values.
+  unique(X) == unique(Y) iff X and Y always evaluate to the same value
+  unique(X) != unique(Y) otherwise
+```
+Intuitively, the states have the following meaning:
+*   Uninitialized: the ownership is not initialized yet, this is the default
+    state; once an operation is finished processing the ownership of all
+    operation results with MemRef type should not be uninitialized anymore.
+*   Unique: there is a specific SSA value that can be queried to check ownership
+    without materializing any additional IR
+*   Unknown: no specific SSA value is available without materializing additional
+    IR, typically this is because two ownerships in 'Unique' state would have to
+    be merged manually (e.g., the result of an `arith.select` either has the
+    ownership of the then or else case depending on the condition value,
+    inserting another `arith.select` for the ownership values can perform the
+    merge and provide a 'Unique' ownership for the result), however, in the
+    general case this 'Unknown' state has to be assigned.
+
+Implied by the above partial order, the pass combines two ownerships in the
+following way:
+
+| Ownership 1   | Ownership 2   | Combined Ownership |
+|:--------------|:--------------|:-------------------|
+| uninitialized | uninitialized | uninitialized      |
+| unique(X)     | uninitialized | unique(X)          |
+| unique(X)     | unique(X)     | unique(X)          |
+| unique(X)     | unique(Y)     | unknown            |
+| unknown       | unique        | unknown            |
+| unknown       | uninitialized | unknown            |
+| <td colspan=3> + symmetric cases                   |
+
+**Collecting the list of MemRefs that potentially need to be deallocated**
+
+For a given block, the list of MemRefs that potentially need to be deallocated
+at the end of that block is computed by keeping track of all values for which
+the block potentially takes over ownership. This includes MemRefs provided as
+basic block arguments, interface handlers for operations like `memref.alloc` and
+`func.call`, but also liveness information in regions with multiple basic
+blocks.  More concretely, it is computed by taking the MemRefs in the 'in' set
+of the liveness analysis of the current basic block B, appended by the MemRef
+block arguments and by the set of MemRefs allocated in B itself (determined by
+the interface handlers), then subtracted (also determined by the interface
+handlers) by the set of MemRefs deallocated in B.
+
+Note that we don't have to take the intersection of the liveness 'in' set with
+the 'out' set of the predecessor block because a value that is in the 'in' set
+must be defined in an ancestor block that dominates all direct predecessors and
+thus the 'in' set of this block is a subset of the 'out' sets of each
+predecessor.
+
+```
+memrefs = filter((liveIn(block) U
+  allocated(block) U arguments(block)) \ deallocated(block), isMemRef)
+```
+
+The list of conditions for the second variadic operands list of
+`bufferization.dealloc` is computed by querying the stored ownership value for
+each of the MemRefs collected as described above. The ownership state is updated
+by the interface handlers while processing the basic block.
+
+**Collecting the list of MemRefs to retain**
+
+Given a basic block B, the list of MemRefs that have to be retained can be
+different for each successor block S.  For the two basic blocks B and S and the
+values passed via block arguments to the destination block S, we compute the
+list of MemRefs that have to be retained in B by taking the MemRefs in the
+successor operand list of the terminator and the MemRefs in the 'out' set of the
+liveness analysis for B intersected with the 'in' set of the destination block
+S.
+
+This list of retained values makes sure that we cannot run into use-after-free
+situations even if no aliasing information is present at compile-time.
+
+```
+toRetain = filter(successorOperands + (liveOut(fromBlock) insersect
+  liveIn(toBlock)), isMemRef)
+```
+
+### Supported interfaces
+
+The pass uses liveness analysis and a few interfaces:
+*   `FunctionOpInterface`
+*   `CallOpInterface`
+*   `MemoryEffectOpInterface`
+*   `RegionBranchOpInterface`
+*   `RegionBranchTerminatorOpInterface`
+
+Due to insufficient information provided by the interface, it also special-cases
+on the `cf.cond_br` operation and makes some assumptions about operations
+implementing the `RegionBranchOpInterface` at the moment, but improving the
+interfaces would allow us to remove those dependencies in the future.
+
+### Limitations
+
+The Buffer Deallocation pass has some requirements and limitations on the input
+IR. These are checked in the beginning of the pass and errors are emitted
+accordingly:
+*   The set of interfaces the pass operates on must be implemented (correctly).
+    E.g., if there is an operation present with a nested region, but does not
+    implement the `RegionBranchOpInterface`, an error is emitted because the
+    pass cannot know the semantics of the nested region (and does not make any
+    default assumptions on it).
+*   No explicit control-flow loops are present. Currently, only loops using
+    structural-control-flow are supported.  However, this limitation could be
+    lifted in the future.
+*   Deallocation operations should not be present already. The pass should
+    handle them correctly already (at least in most cases), but it's not
+    supported yet due to insufficient testing.
+*   Terminators must implement either `RegionBranchTerminatorOpInterface` or
+    `BranchOpInterface`, but not both. Terminators with more than one successor
+    are not supported (except `cf.cond_br`). This is not a fundamental
+    limitation, but there is no use-case justifying the more complex
+    implementation at the moment.
+
+### Example
+
+The following example contains a few interesting cases:
+*   Basic block arguments are modified to also pass along the ownership
+    indicator, but not for entry bocks of non-private functions (assuming the
+    `private-function-dynamic-ownership` pass option is disabled) where the
+    function boundary ABI is applied instead. "Private" in this context refers
+    to functions that cannot be called externally.
+*   The result of `arith.select` initially has 'Unknown' assigned as ownership,
+    but once the `bufferization.dealloc` operation is inserted it is put in the
+    'retained' list (since it has uses in a later basic block) and thus the
+    'Unknown' ownership can be replaced with a 'Unique' ownership using the
+    corresponding result of the dealloc operation.
+*   The `cf.cond_br` operation has more than one successor and thus has to
+    insert two `bufferization.dealloc` operations (one for each successor).
+    While they have the same list of MemRefs to deallocate (because they perform
+    the deallocations for the same block), it must be taken into account that
+    some MemRefs remain *live* for one branch but not the other (thus set
+    intersection is performed on the *live-out* of the current block and the
+    *live-in* of the target block). Also, `cf.cond_br` supports separate
+    forwarding operands for each successor. To make sure that no MemRef is
+    deallocated twice (because there are two `bufferization.dealloc` operations
+    with the same MemRefs to deallocate), the condition operands are adjusted to
+    take the branch condition into account. While a generic lowering for such
+    terminator operations could be implemented, a specialized implementation can
+    take all the semantics of this particular operation into account and thus
+    generate a more efficient lowering.
+
+```mlir
+func.func @example(%memref: memref<?xi8>, %select_cond: i1, %br_cond: i1) {
+  %alloc = memref.alloc() : memref<?xi8>
+  %alloca = memref.alloca() : memref<?xi8>
+  %select = arith.select %select_cond, %alloc, %alloca : memref<?xi8>
+  cf.cond_br %br_cond, ^bb1(%alloc : memref<?xi8>), ^bb1(%memref : memref<?xi8>)
+^bb1(%bbarg: memref<?xi8>):
+  test.copy(%bbarg, %select) : (memref<?xi8>, memref<?xi8>)
+  return
+}
+```
+
+After running `--ownership-based-buffer-deallocation`, it looks as follows:
+
+```mlir
+// Since this is not a private function, the signature will not be modified even
+// when private-function-dynamic-ownership is enabled. Instead the function
+// boundary ABI has to be applied which means that ownership of `%memref` will
+// never be acquired.
+func.func @example(%memref: memref<?xi8>, %select_cond: i1, %br_cond: i1) {
+  %false = arith.constant false
+  %true = arith.constant true
+
+  // The ownership of a MemRef defined by the `memref.alloc` operation is always
+  // assigned to be 'true'.
+  %alloc = memref.alloc() : memref<?xi8>
+
+  // The ownership of a MemRef defined by the `memref.alloca` operation is
+  // always assigned to be 'false'.
+  %alloca = memref.alloca() : memref<?xi8>
+
+  // The ownership of %select will be the join of the ownership of %alloc and
+  // the ownership of %alloca, i.e., of %true and %false. Because the pass does
+  // not know about the semantics of the `arith.select` operation (unless a
+  // custom handler is implemented), the ownership join will be 'Unknown'. If
+  // the materialized ownership indicator of %select is needed, either a clone
+  // has to be created for which %true is assigned as ownership or the result
+  // of a `bufferization.dealloc` where %select is in the retain list has to be
+  // used.
+  %select = arith.select %select_cond, %alloc, %alloca : memref<?xi8>
+
+  // We use `memref.extract_strided_metadata` to get the base memref since it is
+  // not allowed to pass arbitrary memrefs to `memref.dealloc`. This property is
+  // already enforced for `bufferization.dealloc`
+  %base_buffer_memref, ... = memref.extract_strided_metadata %memref
+    : memref<?xi8> -> memref<i8>, index, index, index
+  %base_buffer_alloc, ... = memref.extract_strided_metadata %alloc
+    : memref<?xi8> -> memref<i8>, index, index, index
+  %base_buffer_alloca, ... = memref.extract_strided_metadata %alloca
+    : memref<?xi8> -> memref<i8>, index, index, index
+
+  // The deallocation conditions need to be adjusted to incorporate the branch
+  // condition. In this example, this requires only a single negation, but might
+  // also require multiple arith.andi operations.
+  %not_br_cond = arith.xori %true, %br_cond : i1
+
+  // There are two dealloc operations inserted in this basic block, one per
+  // successor. Both have the same list of MemRefs to deallocate and the
+  // conditions only differ by the branch condition conjunct.
+  // Note, however, that the retained list differs. Here, both contain the
+  // %select value because it is used in both successors (since it's the same
+  // block), but the value passed via block argument differs (%memref vs.
+  // %alloc).
+  %10:2 = bufferization.dealloc
+           (%base_buffer_memref, %base_buffer_alloc, %base_buffer_alloca
+             : memref<i8>, memref<i8>, memref<i8>)
+        if (%false, %br_cond, %false)
+    retain (%alloc, %select : memref<?xi8>, memref<?xi8>)
+
+  %11:2 = bufferization.dealloc
+           (%base_buffer_memref, %base_buffer_alloc, %base_buffer_alloca
+             : memref<i8>, memref<i8>, memref<i8>)
+        if (%false, %not_br_cond, %false)
+    retain (%memref, %select : memref<?xi8>, memref<?xi8>)
+  
+  // Because %select is used in ^bb1 without passing it via block argument, we
+  // need to update it's ownership value here by merging the ownership values
+  // returned by the dealloc operations
+  %new_ownership = arith.select %br_cond, %10#1, %11#1 : i1
+
+  // The terminator is modified to pass along the ownership indicator values
+  // with each MemRef value.
+  cf.cond_br %br_cond, ^bb1(%alloc, %10#0 : memref<?xi8>, i1),
+                       ^bb1(%memref, %11#0 : memref<?xi8>, i1)
+
+// All non-entry basic blocks are modified to have an additional i1 argument for
+// each MemRef value in the argument list.
+^bb1(%13: memref<?xi8>, %14: i1):  // 2 preds: ^bb0, ^bb0
+  test.copy(%13, %select) : (memref<?xi8>, memref<?xi8>)
+
+  %base_buffer_13, ... = memref.extract_strided_metadata %13
+    : memref<?xi8> -> memref<i8>, index, index, index
+  %base_buffer_select, ... = memref.extract_strided_metadata %select
+    : memref<?xi8> -> memref<i8>, index, index, index
+
+  // Here, we don't have a retained list, because the block has no successors
+  // and the return has no operands.
+  bufferization.dealloc (%base_buffer_13, %base_buffer_select
+                          : memref<i8>, memref<i8>)
+                     if (%14, %new_ownership)
+  return
+}
+```
+
+## Buffer Deallocation Simplification Pass
+
+The [semantics of the `bufferization.dealloc` operation](https://mlir.llvm.org/docs/Dialects/BufferizationOps/#bufferizationdealloc-bufferizationdeallocop)
+provide a lot of opportunities for optimizations which can be conveniently split
+into patterns using the greedy pattern rewriter. Some of those patterns need
+access to additional analyses such as an analysis that can determine whether two
+MemRef values must, may, or never originate from the same buffer allocation.
+These patterns are collected in the Buffer Deallocation Simplification pass,
+while patterns that don't need additional analyses are registered as part of the
+regular canonicalizer pass. This pass is best run after
+`--ownership-based-buffer-deallocation` followed by `--canonicalize`.
+
+The pass applies patterns for the following simplifications:
+*   Remove MemRefs from retain list when guaranteed to not alias with any value
+    in the 'memref' operand list. This avoids an additional aliasing check with
+    the removed value.
+*   Split off values in the 'memref' list to new `bufferization.dealloc`
+    operations only containing this value in the 'memref' list when it is
+    guaranteed to not alias with any other value in the 'memref' list. This
+    avoids at least one aliasing check at runtime and enables using a more
+    efficient lowering for this new `bufferization.dealloc` operation.
+*   Remove values from the 'memref' operand list when it is guaranteed to alias
+    with at least one value in the 'retained' list and may not alias any other
+    value in the 'retain' list.
+
+## Lower Deallocations Pass
+
+The `-lower-deallocations` pass transforms all `bufferization.dealloc`
+operations to `memref.dealloc` operations and may also insert operations from
+the `scf`, `func`, and `arith` dialects to make deallocations conditional and
+check whether two MemRef values come from the same allocation at runtime (when
+the `buffer-deallocation-simplification` pass wasn't able to determine it
+statically).
+
+The same lowering of the `bufferization.dealloc` operation is also part of the
+`-convert-bufferization-to-memref` conversion pass which also lowers all the
+other operations of the bufferization dialect.
+
+We distinguish multiple cases in this lowering pass to provide an overall more
+efficient lowering. In the general case, a library function is created to avoid
+quadratic code size explosion (relative to the number of operands of the dealloc
+operation). The specialized lowerings aim to avoid this library function because
+it requires allocating auxiliary MemRefs of index values.
+
+### Generic Lowering
+
+A library function is generated to avoid code-size blow-up. On a high level, the
+base-memref of all operands is extracted as an index value and stored into
+specifically allocated MemRefs and passed to the library function which then
+determines whether they come from the same original allocation. This information
+is needed to avoid double-free situations and to correctly retain the MemRef
+values in the `retained` list.
+
+**Dealloc Operation Lowering**
+
+This lowering supports all features the dealloc operation has to offer. It
+computes the base pointer of each memref (as an index), stores it in a
+new memref helper structure and passes it to the helper function generated
+in `buildDeallocationLibraryFunction`. The results are stored in two lists
+(represented as MemRefs) of booleans passed as arguments. The first list
+stores whether the corresponding condition should be deallocated, the
+second list stores the ownership of the retained values which can be used
+to replace the result values of the `bufferization.dealloc` operation.
+
+Example:
+```
+%0:2 = bufferization.dealloc (%m0, %m1 : memref<2xf32>, memref<5xf32>)
+                          if (%cond0, %cond1)
+                      retain (%r0, %r1 : memref<1xf32>, memref<2xf32>)
+```
+lowers to (simplified):
+```
+%c0 = arith.constant 0 : index
+%c1 = arith.constant 1 : index
+%dealloc_base_pointer_list = memref.alloc() : memref<2xindex>
+%cond_list = memref.alloc() : memref<2xi1>
+%retain_base_pointer_list = memref.alloc() : memref<2xindex>
+%m0_base_pointer = memref.extract_aligned_pointer_as_index %m0
+memref.store %m0_base_pointer, %dealloc_base_pointer_list[%c0]
+%m1_base_pointer = memref.extract_aligned_pointer_as_index %m1
+memref.store %m1_base_pointer, %dealloc_base_pointer_list[%c1]
+memref.store %cond0, %cond_list[%c0]
+memref.store %cond1, %cond_list[%c1]
+%r0_base_pointer = memref.extract_aligned_pointer_as_index %r0
+memref.store %r0_base_pointer, %retain_base_pointer_list[%c0]
+%r1_base_pointer = memref.extract_aligned_pointer_as_index %r1
+memref.store %r1_base_pointer, %retain_base_pointer_list[%c1]
+%dyn_dealloc_base_pointer_list = memref.cast %dealloc_base_pointer_list :
+   memref<2xindex> to memref<?xindex>
+%dyn_cond_list = memref.cast %cond_list : memref<2xi1> to memref<?xi1>
+%dyn_retain_base_pointer_list = memref.cast %retain_base_pointer_list :
+   memref<2xindex> to memref<?xindex>
+%dealloc_cond_out = memref.alloc() : memref<2xi1>
+%ownership_out = memref.alloc() : memref<2xi1>
+%dyn_dealloc_cond_out = memref.cast %dealloc_cond_out :
+   memref<2xi1> to memref<?xi1>
+%dyn_ownership_out = memref.cast %ownership_out :
+   memref<2xi1> to memref<?xi1>
+call @dealloc_helper(%dyn_dealloc_base_pointer_list,
+                     %dyn_retain_base_pointer_list,
+                     %dyn_cond_list,
+                     %dyn_dealloc_cond_out,
+                     %dyn_ownership_out) : (...)
+%m0_dealloc_cond = memref.load %dyn_dealloc_cond_out[%c0] : memref<2xi1>
+scf.if %m0_dealloc_cond {
+  memref.dealloc %m0 : memref<2xf32>
+}
+%m1_dealloc_cond = memref.load %dyn_dealloc_cond_out[%c1] : memref<2xi1>
+scf.if %m1_dealloc_cond {
+  memref.dealloc %m1 : memref<5xf32>
+}
+%r0_ownership = memref.load %dyn_ownership_out[%c0] : memref<2xi1>
+%r1_ownership = memref.load %dyn_ownership_out[%c1] : memref<2xi1>
+memref.dealloc %dealloc_base_pointer_list : memref<2xindex>
+memref.dealloc %retain_base_pointer_list : memref<2xindex>
+memref.dealloc %cond_list : memref<2xi1>
+memref.dealloc %dealloc_cond_out : memref<2xi1>
+memref.dealloc %ownership_out : memref<2xi1>
+// replace %0#0 with %r0_ownership
+// replace %0#1 with %r1_ownership
+```
+
+**Library function**
+
+A library function is built per compilation unit that can be called at
+bufferization dealloc sites to determine whether two MemRefs come from the same
+allocation and their new ownerships.
+
+The generated function takes two MemRefs of indices and three MemRefs of
+booleans as arguments:
+  * The first argument A should contain the result of the
+  extract_aligned_pointer_as_index operation applied to the MemRefs to be
+  deallocated
+  * The second argument B should contain the result of the
+  extract_aligned_pointer_as_index operation applied to the MemRefs to be
+  retained
+  * The third argument C should contain the conditions as passed directly
+  to the deallocation operation.
+  * The fourth argument D is used to pass results to the caller. Those
+  represent the condition under which the MemRef at the corresponding
+  position in A should be deallocated.
+  * The fifth argument E is used to pass results to the caller. It
+  provides the ownership value corresponding the the MemRef at the same
+  position in B
+
+This helper function is supposed to be called once for each
+`bufferization.dealloc` operation to determine the deallocation need and
+new ownership indicator for the retained values, but does not perform the
+deallocation itself.
+
+Generated code:
+```
+func.func @dealloc_helper(
+    %dyn_dealloc_base_pointer_list: memref<?xindex>,
+    %dyn_retain_base_pointer_list: memref<?xindex>,
+    %dyn_cond_list: memref<?xi1>,
+    %dyn_dealloc_cond_out: memref<?xi1>,
+    %dyn_ownership_out: memref<?xi1>) {
+  %c0 = arith.constant 0 : index
+  %c1 = arith.constant 1 : index
+  %true = arith.constant true
+  %false = arith.constant false
+  %num_dealloc_memrefs = memref.dim %dyn_dealloc_base_pointer_list, %c0
+  %num_retain_memrefs = memref.dim %dyn_retain_base_pointer_list, %c0
+  // Zero initialize result buffer.
+  scf.for %i = %c0 to %num_retain_memrefs step %c1 {
+    memref.store %false, %dyn_ownership_out[%i] : memref<?xi1>
+  }
+  scf.for %i = %c0 to %num_dealloc_memrefs step %c1 {
+    %dealloc_bp = memref.load %dyn_dealloc_base_pointer_list[%i]
+    %cond = memref.load %dyn_cond_list[%i]
+    // Check for aliasing with retained memrefs.
+    %does_not_alias_retained = scf.for %j = %c0 to %num_retain_memrefs
+        step %c1 iter_args(%does_not_alias_aggregated = %true) -> (i1) {
+      %retain_bp = memref.load %dyn_retain_base_pointer_list[%j]
+      %does_alias = arith.cmpi eq, %retain_bp, %dealloc_bp : index
+      scf.if %does_alias {
+        %curr_ownership = memref.load %dyn_ownership_out[%j]
+        %updated_ownership = arith.ori %curr_ownership, %cond : i1
+        memref.store %updated_ownership, %dyn_ownership_out[%j]
+      }
+      %does_not_alias = arith.cmpi ne, %retain_bp, %dealloc_bp : index
+      %updated_aggregate = arith.andi %does_not_alias_aggregated,
+                                      %does_not_alias : i1
+      scf.yield %updated_aggregate : i1
+    }
+    // Check for aliasing with dealloc memrefs in the list before the
+    // current one, i.e.,
+    // `fix i, forall j < i: check_aliasing(%dyn_dealloc_base_pointer[j],
+    // %dyn_dealloc_base_pointer[i])`
+    %does_not_alias_any = scf.for %j = %c0 to %i step %c1
+       iter_args(%does_not_alias_agg = %does_not_alias_retained) -> (i1) {
+      %prev_dealloc_bp = memref.load %dyn_dealloc_base_pointer_list[%j]
+      %does_not_alias = arith.cmpi ne, %prev_dealloc_bp, %dealloc_bp
+      %updated_alias_agg = arith.andi %does_not_alias_agg, %does_not_alias
+      scf.yield %updated_alias_agg : i1
+    }
+    %dealloc_cond = arith.andi %does_not_alias_any, %cond : i1
+    memref.store %dealloc_cond, %dyn_dealloc_cond_out[%i] : memref<?xi1>
+  }
+  return
+}
+```
+
+### Specialized Lowerings
+
+Currently, there are two special lowerings for common cases to avoid the library
+function and thus unnecessary memory load and store operations and function
+calls:
+
+**One memref, no retained**
+
+Lower a simple case without any retained values and a single MemRef. Ideally,
+static analysis can provide enough information such that the
+`buffer-deallocation-simplification` pass is able to split the dealloc
+operations up into this simple case as much as possible before running this
+pass.
+
+Example:
+```mlir
+bufferization.dealloc (%arg0 : memref<2xf32>) if (%arg1)
+```
+is lowered to
+```mlir
+scf.if %arg1 {
+  memref.dealloc %arg0 : memref<2xf32>
+}
+```
+
+In most cases, the branch condition is either constant 'true' or 'false' and can
+thus be optimized away entirely by the canonicalizer pass.
+
+**One memref, arbitrarily many retained**
+
+A special case lowering for the deallocation operation with exactly one MemRef,
+but an arbitrary number of retained values. The size of the code produced by
+this lowering is linear to the number of retained values.
+
+Example:
+```mlir
+%0:2 = bufferization.dealloc (%m : memref<2xf32>) if (%cond)
+                      retain (%r0, %r1 : memref<1xf32>, memref<2xf32>)
+return %0#0, %0#1 : i1, i1
+```
+is lowered to
+```mlir
+%m_base_pointer = memref.extract_aligned_pointer_as_index %m
+%r0_base_pointer = memref.extract_aligned_pointer_as_index %r0
+%r0_does_not_alias = arith.cmpi ne, %m_base_pointer, %r0_base_pointer
+%r1_base_pointer = memref.extract_aligned_pointer_as_index %r1
+%r1_does_not_alias = arith.cmpi ne, %m_base_pointer, %r1_base_pointer
+%not_retained = arith.andi %r0_does_not_alias, %r1_does_not_alias : i1
+%should_dealloc = arith.andi %not_retained, %cond : i1
+scf.if %should_dealloc {
+  memref.dealloc %m : memref<2xf32>
+}
+%true = arith.constant true
+%r0_does_alias = arith.xori %r0_does_not_alias, %true : i1
+%r0_ownership = arith.andi %r0_does_alias, %cond : i1
+%r1_does_alias = arith.xori %r1_does_not_alias, %true : i1
+%r1_ownership = arith.andi %r1_does_alias, %cond : i1
+return %r0_ownership, %r1_ownership : i1, i1
+```
+
 ## Memory Layouts
 
 One-Shot Bufferize bufferizes ops from top to bottom. This works well when all
diff --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/BufferUtils.h b/mlir/include/mlir/Dialect/Bufferization/Transforms/BufferUtils.h
index 85e9c47ad5302cb..83e55fd70de6bb8 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/BufferUtils.h
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/BufferUtils.h
@@ -121,6 +121,14 @@ class BufferPlacementTransformationBase {
   Liveness liveness;
 };
 
+/// Compare two SSA values in a deterministic manner. Two block arguments are
+/// ordered by argument number, block arguments are always less than operation
+/// results, and operation results are ordered by the `isBeforeInBlock` order of
+/// their defining operation.
+struct ValueComparator {
+  bool operator()(const Value &lhs, const Value &rhs) const;
+};
+
 // Create a global op for the given tensor-valued constant in the program.
 // Globals are created lazily at the top of the enclosing ModuleOp with pretty
 // names. Duplicates are avoided.
diff --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
index b0b62acffe77a2a..23eed02a15d4801 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
@@ -4,6 +4,7 @@
 #include "mlir/Pass/Pass.h"
 
 namespace mlir {
+class FunctionOpInterface;
 class ModuleOp;
 class RewritePatternSet;
 class OpBuilder;
@@ -27,6 +28,10 @@ struct OneShotBufferizationOptions;
 /// buffers.
 std::unique_ptr<Pass> createBufferDeallocationPass();
 
+/// Creates an instance of the OwnershipBasedBufferDeallocation pass to free all
+/// allocated buffers.
+std::unique_ptr<Pass> createOwnershipBasedBufferDeallocationPass();
+
 /// Creates a pass that optimizes `bufferization.dealloc` operations. For
 /// example, it reduces the number of alias checks needed at runtime using
 /// static alias analysis.
@@ -127,6 +132,10 @@ func::FuncOp buildDeallocationLibraryFunction(OpBuilder &builder, Location loc,
 /// Run buffer deallocation.
 LogicalResult deallocateBuffers(Operation *op);
 
+/// Run ownership basedbuffer deallocation.
+LogicalResult deallocateBuffersOwnershipBased(FunctionOpInterface op,
+                                              bool privateFuncDynamicOwnership);
+
 /// Creates a pass that moves allocations upwards to reduce the number of
 /// required copies that are inserted during the BufferDeallocation pass.
 std::unique_ptr<Pass> createBufferHoistingPass();
diff --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
index ff43cff817b64a8..f3c2a29c0589f29 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
@@ -88,6 +88,150 @@ def BufferDeallocation : Pass<"buffer-deallocation", "func::FuncOp"> {
   let constructor = "mlir::bufferization::createBufferDeallocationPass()";
 }
 
+def OwnershipBasedBufferDeallocation : Pass<
+    "ownership-based-buffer-deallocation", "func::FuncOp"> {
+  let summary = "Adds all required dealloc operations for all allocations in "
+                "the input program";
+  let description = [{
+    This pass implements an algorithm to automatically introduce all required
+    deallocation operations for all buffers in the input program. This ensures
+    that the resulting program does not have any memory leaks.
+
+    The Buffer Deallocation pass operates on the level of operations
+    implementing the FunctionOpInterface. Such operations can take MemRefs as
+    arguments, but also return them. To ensure compatibility among all functions
+    (including external ones), some rules have to be enforced. They are just
+    assumed to hold for all external functions. Functions for which the
+    definition is available ideally also already adhere to the ABI.
+    Otherwise, all MemRef write operations in the input IR must dominate all
+    MemRef read operations in the input IR. Then, the pass may modify the input
+    IR by inserting `bufferization.clone` operations such that the output IR
+    adheres to the function boundary ABI:
+    * When a MemRef is passed as a function argument, ownership is never
+      acquired. It is always the caller's responsibility to deallocate such
+      MemRefs.
+    * Returning a MemRef from a function always passes ownership to the caller,
+      i.e., it is also the caller's responsibility to deallocate MemRefs
+      returned from a called function.
+    * A function must not return a MemRef with the same allocated base buffer as
+      one of its arguments (in this case a copy has to be created). Note that in
+      this context two subviews of the same buffer that don't overlap are also
+      considered an alias.
+
+    It is recommended to bufferize all operations first such that no tensor
+    values remain in the IR once this pass is applied. That way all allocated
+    MemRefs will be properly deallocated without any additional manual work.
+    Otherwise, the pass that bufferizes the remaining tensors is responsible to
+    add the corresponding deallocation operations. Note that this pass does not
+    consider any values of tensor type and assumes that MemRef values defined by
+    `bufferization.to_memref` do not return ownership and do not have to be
+    deallocated. `bufferization.to_tensor` operations are handled similarly to
+    `bufferization.clone` operations with the exception that the result value is
+    not handled because it's a tensor (not a MemRef).
+
+    Input
+
+    ```mlir
+    #map0 = affine_map<(d0) -> (d0)>
+    module {
+      func.func @condBranch(%arg0: i1,
+                            %arg1: memref<2xf32>,
+                            %arg2: memref<2xf32>) {
+        cf.cond_br %arg0, ^bb1, ^bb2
+      ^bb1:
+        cf.br ^bb3(%arg1 : memref<2xf32>)
+      ^bb2:
+        %0 = memref.alloc() : memref<2xf32>
+        linalg.generic {
+          args_in = 1 : i64,
+          args_out = 1 : i64,
+          indexing_maps = [#map0, #map0],
+          iterator_types = ["parallel"]}
+        outs(%arg1, %0 : memref<2xf32>, memref<2xf32>) {
+        ^bb0(%gen1_arg0: f32, %gen1_arg1: f32):
+          %tmp1 = exp %gen1_arg0 : f32
+          linalg.yield %tmp1 : f32
+        }
+        cf.br ^bb3(%0 : memref<2xf32>)
+      ^bb3(%1: memref<2xf32>):
+        "memref.copy"(%1, %arg2) : (memref<2xf32>, memref<2xf32>) -> ()
+        return
+      }
+    }
+    ```
+
+    Output
+
+    ```mlir
+    #map = affine_map<(d0) -> (d0)>
+    module {
+      func.func @condBranch(%arg0: i1,
+                            %arg1: memref<2xf32>,
+                            %arg2: memref<2xf32>) {
+        %false = arith.constant false
+        %true = arith.constant true
+        cf.cond_br %arg0, ^bb1, ^bb2
+      ^bb1:  // pred: ^bb0
+        cf.br ^bb3(%arg1, %false : memref<2xf32>, i1)
+      ^bb2:  // pred: ^bb0
+        %alloc = memref.alloc() : memref<2xf32>
+        linalg.generic {
+          indexing_maps = [#map, #map],
+          iterator_types = ["parallel"]}
+        outs(%arg1, %alloc : memref<2xf32>, memref<2xf32>)
+        attrs =  {args_in = 1 : i64, args_out = 1 : i64} {
+        ^bb0(%out: f32, %out_0: f32):
+          %2 = math.exp %out : f32
+          linalg.yield %2, %out_0 : f32, f32
+        }
+        cf.br ^bb3(%alloc, %true : memref<2xf32>, i1)
+      ^bb3(%0: memref<2xf32>, %1: i1):  // 2 preds: ^bb1, ^bb2
+        memref.copy %0, %arg2 : memref<2xf32> to memref<2xf32>
+        %base_buffer, %offset, %sizes, %strides =
+          memref.extract_strided_metadata %0 :
+          memref<2xf32> -> memref<f32>, index, index, index
+        bufferization.dealloc (%base_buffer : memref<f32>) if (%1)
+        return
+      }
+    }
+    ```
+
+    The `private-function-dynamic-ownership` pass option allows the pass to add
+    additional arguments to private functions to dynamically give ownership of
+    MemRefs to callees. This can enable earlier deallocations and allows the
+    pass to by-pass the function boundary ABI and thus potentially leading to
+    fewer MemRef clones being inserted. For example, the private function
+    ```mlir
+    func.func private @passthrough(%memref: memref<2xi32>) -> memref<2xi32> {
+      return %memref : memref<2xi32>
+    }
+    ```
+    would be converted to
+    ```mlir
+    func.func private @passthrough(%memref: memref<2xi32>,
+                                   %ownership: i1) -> (memref<2xi32>, i1) {
+      return %memref, %ownership : memref<2xi32>, i1
+    }
+    ```
+    and thus allows the returned MemRef to alias with the MemRef passed as
+    argument (which would otherwise be forbidden according to the function
+    boundary ABI).
+  }];
+  let options = [
+    Option<"privateFuncDynamicOwnership", "private-function-dynamic-ownership",
+           "bool", /*default=*/"false",
+           "Allows to add additional arguments to private functions to "
+           "dynamically pass ownership of memrefs to callees. This can enable "
+           "earlier deallocations.">,
+  ];
+  let constructor = "mlir::bufferization::createOwnershipBasedBufferDeallocationPass()";
+
+  let dependentDialects = [
+    "mlir::bufferization::BufferizationDialect", "mlir::arith::ArithDialect",
+    "mlir::memref::MemRefDialect", "mlir::scf::SCFDialect"
+  ];
+}
+
 def BufferDeallocationSimplification :
     Pass<"buffer-deallocation-simplification", "func::FuncOp"> {
   let summary = "Optimizes `bufferization.dealloc` operation for more "
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/BufferUtils.cpp b/mlir/lib/Dialect/Bufferization/Transforms/BufferUtils.cpp
index 119801f9cc92f32..b8fd99a5541242f 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/BufferUtils.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/BufferUtils.cpp
@@ -202,3 +202,62 @@ bufferization::getGlobalFor(arith::ConstantOp constantOp, uint64_t alignment,
   global->moveBefore(&moduleOp.front());
   return global;
 }
+
+//===----------------------------------------------------------------------===//
+// ValueComparator
+//===----------------------------------------------------------------------===//
+
+bool ValueComparator::operator()(const Value &lhs, const Value &rhs) const {
+  if (lhs == rhs)
+    return false;
+
+  // Block arguments are less than results.
+  bool lhsIsBBArg = lhs.isa<BlockArgument>();
+  if (lhsIsBBArg != rhs.isa<BlockArgument>()) {
+    return lhsIsBBArg;
+  }
+
+  Region *lhsRegion;
+  Region *rhsRegion;
+  if (lhsIsBBArg) {
+    auto lhsBBArg = llvm::cast<BlockArgument>(lhs);
+    auto rhsBBArg = llvm::cast<BlockArgument>(rhs);
+    if (lhsBBArg.getArgNumber() != rhsBBArg.getArgNumber()) {
+      return lhsBBArg.getArgNumber() < rhsBBArg.getArgNumber();
+    }
+    lhsRegion = lhsBBArg.getParentRegion();
+    rhsRegion = rhsBBArg.getParentRegion();
+    assert(lhsRegion != rhsRegion &&
+           "lhsRegion == rhsRegion implies lhs == rhs");
+  } else if (lhs.getDefiningOp() == rhs.getDefiningOp()) {
+    return llvm::cast<OpResult>(lhs).getResultNumber() <
+           llvm::cast<OpResult>(rhs).getResultNumber();
+  } else {
+    lhsRegion = lhs.getDefiningOp()->getParentRegion();
+    rhsRegion = rhs.getDefiningOp()->getParentRegion();
+    if (lhsRegion == rhsRegion) {
+      return lhs.getDefiningOp()->isBeforeInBlock(rhs.getDefiningOp());
+    }
+  }
+
+  // lhsRegion != rhsRegion, so if we look at their ancestor chain, they
+  // - have different heights
+  // - or there's a spot where their region numbers differ
+  // - or their parent regions are the same and their parent ops are
+  //   different.
+  while (lhsRegion && rhsRegion) {
+    if (lhsRegion->getRegionNumber() != rhsRegion->getRegionNumber()) {
+      return lhsRegion->getRegionNumber() < rhsRegion->getRegionNumber();
+    }
+    if (lhsRegion->getParentRegion() == rhsRegion->getParentRegion()) {
+      return lhsRegion->getParentOp()->isBeforeInBlock(
+          rhsRegion->getParentOp());
+    }
+    lhsRegion = lhsRegion->getParentRegion();
+    rhsRegion = rhsRegion->getParentRegion();
+  }
+  if (rhsRegion)
+    return true;
+  assert(lhsRegion && "this should only happen if lhs == rhs");
+  return false;
+}
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt b/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt
index 16659e0e3b20366..cbbfe7a81205857 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt
@@ -13,6 +13,7 @@ add_mlir_dialect_library(MLIRBufferizationTransforms
   LowerDeallocations.cpp
   OneShotAnalysis.cpp
   OneShotModuleBufferize.cpp
+  OwnershipBasedBufferDeallocation.cpp
   TensorCopyInsertion.cpp
 
   ADDITIONAL_HEADER_DIRS
@@ -34,6 +35,7 @@ add_mlir_dialect_library(MLIRBufferizationTransforms
   MLIRPass
   MLIRTensorDialect
   MLIRSCFDialect
+  MLIRControlFlowDialect
   MLIRSideEffectInterfaces
   MLIRTransforms
   MLIRViewLikeInterface
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp
new file mode 100644
index 000000000000000..eaced7202f4e606
--- /dev/null
+++ b/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp
@@ -0,0 +1,1383 @@
+//===- OwnershipBasedBufferDeallocation.cpp - impl. for buffer dealloc. ---===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements logic for computing correct `bufferization.dealloc`
+// positions. Furthermore, buffer deallocation also adds required new clone
+// operations to ensure that memrefs returned by functions never alias an
+// argument.
+//
+// TODO:
+// The current implementation does not support explicit-control-flow loops and
+// the resulting code will be invalid with respect to program semantics.
+// However, structured control-flow loops are fully supported.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/Bufferization/IR/Bufferization.h"
+#include "mlir/Dialect/Bufferization/Transforms/BufferUtils.h"
+#include "mlir/Dialect/Bufferization/Transforms/Passes.h"
+#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/Dialect/MemRef/IR/MemRef.h"
+#include "mlir/Dialect/SCF/IR/SCF.h"
+#include "mlir/IR/Iterators.h"
+#include "mlir/Interfaces/ControlFlowInterfaces.h"
+#include "llvm/ADT/SetOperations.h"
+
+namespace mlir {
+namespace bufferization {
+#define GEN_PASS_DEF_OWNERSHIPBASEDBUFFERDEALLOCATION
+#include "mlir/Dialect/Bufferization/Transforms/Passes.h.inc"
+} // namespace bufferization
+} // namespace mlir
+
+using namespace mlir;
+using namespace mlir::bufferization;
+
+//===----------------------------------------------------------------------===//
+// Helpers
+//===----------------------------------------------------------------------===//
+
+static Value buildBoolValue(OpBuilder &builder, Location loc, bool value) {
+  return builder.create<arith::ConstantOp>(loc, builder.getBoolAttr(value));
+}
+
+static bool isMemref(Value v) { return v.getType().isa<BaseMemRefType>(); }
+
+//===----------------------------------------------------------------------===//
+// Backedges analysis
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+/// A straight-forward program analysis which detects loop backedges induced by
+/// explicit control flow.
+class Backedges {
+public:
+  using BlockSetT = SmallPtrSet<Block *, 16>;
+  using BackedgeSetT = llvm::DenseSet<std::pair<Block *, Block *>>;
+
+public:
+  /// Constructs a new backedges analysis using the op provided.
+  Backedges(Operation *op) { recurse(op); }
+
+  /// Returns the number of backedges formed by explicit control flow.
+  size_t size() const { return edgeSet.size(); }
+
+  /// Returns the start iterator to loop over all backedges.
+  BackedgeSetT::const_iterator begin() const { return edgeSet.begin(); }
+
+  /// Returns the end iterator to loop over all backedges.
+  BackedgeSetT::const_iterator end() const { return edgeSet.end(); }
+
+private:
+  /// Enters the current block and inserts a backedge into the `edgeSet` if we
+  /// have already visited the current block. The inserted edge links the given
+  /// `predecessor` with the `current` block.
+  bool enter(Block &current, Block *predecessor) {
+    bool inserted = visited.insert(&current).second;
+    if (!inserted)
+      edgeSet.insert(std::make_pair(predecessor, &current));
+    return inserted;
+  }
+
+  /// Leaves the current block.
+  void exit(Block &current) { visited.erase(&current); }
+
+  /// Recurses into the given operation while taking all attached regions into
+  /// account.
+  void recurse(Operation *op) {
+    Block *current = op->getBlock();
+    // If the current op implements the `BranchOpInterface`, there can be
+    // cycles in the scope of all successor blocks.
+    if (isa<BranchOpInterface>(op)) {
+      for (Block *succ : current->getSuccessors())
+        recurse(*succ, current);
+    }
+    // Recurse into all distinct regions and check for explicit control-flow
+    // loops.
+    for (Region &region : op->getRegions()) {
+      if (!region.empty())
+        recurse(region.front(), current);
+    }
+  }
+
+  /// Recurses into explicit control-flow structures that are given by
+  /// the successor relation defined on the block level.
+  void recurse(Block &block, Block *predecessor) {
+    // Try to enter the current block. If this is not possible, we are
+    // currently processing this block and can safely return here.
+    if (!enter(block, predecessor))
+      return;
+
+    // Recurse into all operations and successor blocks.
+    for (Operation &op : block.getOperations())
+      recurse(&op);
+
+    // Leave the current block.
+    exit(block);
+  }
+
+  /// Stores all blocks that are currently visited and on the processing stack.
+  BlockSetT visited;
+
+  /// Stores all backedges in the format (source, target).
+  BackedgeSetT edgeSet;
+};
+
+} // namespace
+
+//===----------------------------------------------------------------------===//
+// BufferDeallocation
+//===----------------------------------------------------------------------===//
+
+namespace {
+/// This class is used to track the ownership of values. The ownership can
+/// either be not initialized yet ('Uninitialized' state), set to a unique SSA
+/// value which indicates the ownership at runtime (or statically if it is a
+/// constant value) ('Unique' state), or it cannot be represented in a single
+/// SSA value ('Unknown' state). An artificial example of a case where ownership
+/// cannot be represented in a single i1 SSA value could be the following:
+/// `%0 = test.non_deterministic_select %arg0, %arg1 : i32`
+/// Since the operation does not provide us a separate boolean indicator on
+/// which of the two operands was selected, we would need to either insert an
+/// alias check at runtime to determine if `%0` aliases with `%arg0` or `%arg1`,
+/// or insert a `bufferization.clone` operation to get a fresh buffer which we
+/// could assign ownership to.
+///
+/// The three states this class can represent form a lattice on a partial order:
+/// forall X in SSA values. uninitialized < unique(X) < unknown
+/// forall X, Y in SSA values.
+///   unique(X) == unique(Y) iff X and Y always evaluate to the same value
+///   unique(X) != unique(Y) otherwise
+class Ownership {
+public:
+  /// Constructor that creates an 'Uninitialized' ownership. This is needed for
+  /// default-construction when used in DenseMap.
+  Ownership() = default;
+
+  /// Constructor that creates an 'Unique' ownership. This is a non-explicit
+  /// constructor to allow implicit conversion from 'Value'.
+  Ownership(Value indicator) : indicator(indicator), state(State::Unique) {}
+
+  /// Get an ownership value in 'Unknown' state.
+  static Ownership getUnknown() {
+    Ownership unknown;
+    unknown.indicator = Value();
+    unknown.state = State::Unknown;
+    return unknown;
+  }
+  /// Get an ownership value in 'Unique' state with 'indicator' as parameter.
+  static Ownership getUnique(Value indicator) { return Ownership(indicator); }
+  /// Get an ownership value in 'Uninitialized' state.
+  static Ownership getUninitialized() { return Ownership(); }
+
+  /// Check if this ownership value is in the 'Uninitialized' state.
+  bool isUninitialized() const { return state == State::Uninitialized; }
+  /// Check if this ownership value is in the 'Unique' state.
+  bool isUnique() const { return state == State::Unique; }
+  /// Check if this ownership value is in the 'Unknown' state.
+  bool isUnknown() const { return state == State::Unknown; }
+
+  /// If this ownership value is in 'Unique' state, this function can be used to
+  /// get the indicator parameter. Using this function in any other state is UB.
+  Value getIndicator() const {
+    assert(isUnique() && "must have unique ownership to get the indicator");
+    return indicator;
+  }
+
+  /// Get the join of the two-element subset {this,other}. Does not modify
+  /// 'this'.
+  Ownership getCombined(Ownership other) const {
+    if (other.isUninitialized())
+      return *this;
+    if (isUninitialized())
+      return other;
+
+    if (!isUnique() || !other.isUnique())
+      return getUnknown();
+
+    // Since we create a new constant i1 value for (almost) each use-site, we
+    // should compare the actual value rather than just the SSA Value to avoid
+    // unnecessary invalidations.
+    if (isEqualConstantIntOrValue(indicator, other.indicator))
+      return *this;
+
+    // Return the join of the lattice if the indicator of both ownerships cannot
+    // be merged.
+    return getUnknown();
+  }
+
+  /// Modify 'this' ownership to be the join of the current 'this' and 'other'.
+  void combine(Ownership other) { *this = getCombined(other); }
+
+private:
+  enum class State {
+    Uninitialized,
+    Unique,
+    Unknown,
+  };
+
+  // The indicator value is only relevant in the 'Unique' state.
+  Value indicator;
+  State state = State::Uninitialized;
+};
+
+/// The buffer deallocation transformation which ensures that all allocs in the
+/// program have a corresponding de-allocation.
+class BufferDeallocation {
+public:
+  BufferDeallocation(Operation *op, bool privateFuncDynamicOwnership)
+      : liveness(op), privateFuncDynamicOwnership(privateFuncDynamicOwnership) {
+  }
+
+  /// Performs the actual placement/creation of all dealloc operations.
+  LogicalResult deallocate(FunctionOpInterface op);
+
+private:
+  /// The base case for the recursive template below.
+  template <typename... T>
+  typename std::enable_if<sizeof...(T) == 0, FailureOr<Operation *>>::type
+  handleOp(Operation *op) {
+    return op;
+  }
+
+  /// Applies all the handlers of the interfaces in the template list
+  /// implemented by 'op'. In particular, if an operation implements more than
+  /// one of the interfaces in the template list, all the associated handlers
+  /// will be applied to the operation in the same order as the template list
+  /// specifies. If a handler reports a failure or removes the operation without
+  /// replacement (indicated by returning 'nullptr'), no further handlers are
+  /// applied and the return value is propagated to the caller of 'handleOp'.
+  ///
+  /// The interface handlers job is to update the deallocation state, most
+  /// importantly the ownership map and list of memrefs to potentially be
+  /// deallocated per block, but also to insert `bufferization.dealloc`
+  /// operations where needed. Obviously, no MemRefs that may be used at a later
+  /// point in the control-flow may be deallocated and the ownership map has to
+  /// be updated to reflect potential ownership changes caused by the dealloc
+  /// operation (e.g., if two interfaces on the same op insert a dealloc
+  /// operation each, the second one should query the ownership map and use them
+  /// as deallocation condition such that MemRefs already deallocated in the
+  /// first dealloc operation are not deallocated a second time (double-free)).
+  /// Note that currently only the interfaces on terminators may insert dealloc
+  /// operations and it is verified as a precondition that a terminator op must
+  /// implement exactly one of the interfaces handling dealloc insertion.
+  ///
+  /// The return value of the 'handleInterface' functions should be a
+  /// FailureOr<Operation *> indicating whether there was a failure or otherwise
+  /// returning the operation itself or a replacement operation.
+  ///
+  /// Note: The difference compared to `TypeSwitch` is that all
+  /// matching cases are applied instead of just the first match.
+  template <typename InterfaceT, typename... InterfacesU>
+  FailureOr<Operation *> handleOp(Operation *op) {
+    Operation *next = op;
+    if (auto concreteOp = dyn_cast<InterfaceT>(op)) {
+      FailureOr<Operation *> result = handleInterface(concreteOp);
+      if (failed(result))
+        return failure();
+      next = *result;
+    }
+    if (!next)
+      return nullptr;
+    return handleOp<InterfacesU...>(next);
+  }
+
+  /// Apply all supported interface handlers to the given op.
+  FailureOr<Operation *> handleAllInterfaces(Operation *op) {
+    if (failed(verifyOperationPreconditions(op)))
+      return failure();
+
+    return handleOp<MemoryEffectOpInterface, RegionBranchOpInterface,
+                    CallOpInterface, BranchOpInterface, cf::CondBranchOp,
+                    RegionBranchTerminatorOpInterface>(op);
+  }
+
+  /// While CondBranchOp also implements the BranchOpInterface, we add a
+  /// special-case implementation here because the BranchOpInterface does not
+  /// offer all of the functionality we need to insert dealloc operations in an
+  /// efficient way. More precisely, there is no way to extract the branch
+  /// condition without casting to CondBranchOp specifically. It would still be
+  /// possible to implement deallocation for cases where we don't know to which
+  /// successor the terminator branches before the actual branch happens by
+  /// inserting auxiliary blocks and putting the dealloc op there, however, this
+  /// can lead to less efficient code.
+  /// This function inserts two dealloc operations (one for each successor) and
+  /// adjusts the dealloc conditions according to the branch condition, then the
+  /// ownerships of the retained MemRefs are updated by combining the result
+  /// values of the two dealloc operations.
+  ///
+  /// Example:
+  /// ```
+  /// ^bb1:
+  ///   <more ops...>
+  ///   cf.cond_br cond, ^bb2(<forward-to-bb2>), ^bb3(<forward-to-bb2>)
+  /// ```
+  /// becomes
+  /// ```
+  /// // let (m, c) = getMemrefsAndConditionsToDeallocate(bb1)
+  /// // let r0 = getMemrefsToRetain(bb1, bb2, <forward-to-bb2>)
+  /// // let r1 = getMemrefsToRetain(bb1, bb3, <forward-to-bb3>)
+  /// ^bb1:
+  ///   <more ops...>
+  ///   let thenCond = map(c, (c) -> arith.andi cond, c)
+  ///   let elseCond = map(c, (c) -> arith.andi (arith.xori cond, true), c)
+  ///   o0 = bufferization.dealloc m if thenCond retain r0
+  ///   o1 = bufferization.dealloc m if elseCond retain r1
+  ///   // replace ownership(r0) with o0 element-wise
+  ///   // replace ownership(r1) with o1 element-wise
+  ///   // let ownership0 := (r) -> o in o0 corresponding to r
+  ///   // let ownership1 := (r) -> o in o1 corresponding to r
+  ///   // let cmn := intersection(r0, r1)
+  ///   foreach (a, b) in zip(map(cmn, ownership0), map(cmn, ownership1)):
+  ///     forall r in r0: replace ownership0(r) with arith.select cond, a, b)
+  ///     forall r in r1: replace ownership1(r) with arith.select cond, a, b)
+  ///   cf.cond_br cond, ^bb2(<forward-to-bb2>, o0), ^bb3(<forward-to-bb3>, o1)
+  /// ```
+  FailureOr<Operation *> handleInterface(cf::CondBranchOp op);
+
+  /// Make sure that for each forwarded MemRef value, an ownership indicator
+  /// `i1` value is forwarded as well such that the successor block knows
+  /// whether the MemRef has to be deallocated.
+  ///
+  /// Example:
+  /// ```
+  /// ^bb1:
+  ///   <more ops...>
+  ///   cf.br ^bb2(<forward-to-bb2>)
+  /// ```
+  /// becomes
+  /// ```
+  /// // let (m, c) = getMemrefsAndConditionsToDeallocate(bb1)
+  /// // let r = getMemrefsToRetain(bb1, bb2, <forward-to-bb2>)
+  /// ^bb1:
+  ///   <more ops...>
+  ///   o = bufferization.dealloc m if c retain r
+  ///   // replace ownership(r) with o element-wise
+  ///   cf.br ^bb2(<forward-to-bb2>, o)
+  /// ```
+  FailureOr<Operation *> handleInterface(BranchOpInterface op);
+
+  /// Add an ownership indicator for every forwarding MemRef operand and result.
+  /// Nested regions never take ownership of MemRefs owned by a parent region
+  /// (neither via forwarding operand nor when captured implicitly when the
+  /// region is not isolated from above). Ownerships will only be passed to peer
+  /// regions (when an operation has multiple regions, such as scf.while), or to
+  /// parent regions.
+  /// Note that the block arguments in the nested region are currently handled
+  /// centrally in the 'dealloc' function, but better interface support could
+  /// allow us to do this here for the nested region specifically to reduce the
+  /// amount of assumptions we make on the structure of ops implementing this
+  /// interface.
+  ///
+  /// Example:
+  /// ```
+  /// %ret = scf.for %i = %c0 to %c10 step %c1 iter_args(%m = %memref) {
+  ///   <more ops...>
+  ///   scf.yield %m : memref<2xi32>, i1
+  /// }
+  /// ```
+  /// becomes
+  /// ```
+  /// %ret:2 = scf.for %i = %c0 to %c10 step %c1
+  ///     iter_args(%m = %memref, %own = %false) {
+  ///   <more ops...>
+  ///   // Note that the scf.yield is handled by the
+  ///   // RegionBranchTerminatorOpInterface (not this handler)
+  ///   // let o = getMemrefWithUniqueOwnership(%own)
+  ///   scf.yield %m, o : memref<2xi32>, i1
+  /// }
+  /// ```
+  FailureOr<Operation *> handleInterface(RegionBranchOpInterface op);
+
+  /// If the private-function-dynamic-ownership pass option is enabled and the
+  /// called function is private, additional arguments and results are added for
+  /// each MemRef argument/result to pass the dynamic ownership indicator along.
+  /// Otherwise, updates the ownership map and list of memrefs to be deallocated
+  /// according to the function boundary ABI, i.e., assume ownership of all
+  /// returned MemRefs.
+  ///
+  /// Example (assume `private-function-dynamic-ownership` is enabled):
+  /// ```
+  /// func.func @f(%arg0: memref<2xi32>) -> memref<2xi32> {...}
+  /// func.func private @g(%arg0: memref<2xi32>) -> memref<2xi32> {...}
+  ///
+  /// %ret_f = func.call @f(%memref) : (memref<2xi32>) -> memref<2xi32>
+  /// %ret_g = func.call @g(%memref) : (memref<2xi32>) -> memref<2xi32>
+  /// ```
+  /// becomes
+  /// ```
+  /// func.func @f(%arg0: memref<2xi32>) -> memref<2xi32> {...}
+  /// func.func private @g(%arg0: memref<2xi32>) -> memref<2xi32> {...}
+  ///
+  /// %ret_f = func.call @f(%memref) : (memref<2xi32>) -> memref<2xi32>
+  /// // set ownership(%ret_f) := true
+  /// // remember to deallocate %ret_f
+  ///
+  /// // (new_memref, own) = getmemrefWithUniqueOwnership(%memref)
+  /// %ret_g:2 = func.call @g(new_memref, own) :
+  ///   (memref<2xi32>, i1) -> (memref<2xi32>, i1)
+  /// // set ownership(%ret_g#0) := %ret_g#1
+  /// // remember to deallocate %ret_g
+  /// ```
+  FailureOr<Operation *> handleInterface(CallOpInterface op);
+
+  /// Takes care of allocation and free side-effects. It collects allocated
+  /// MemRefs that we have to add to manually deallocate, but also removes
+  /// values again that are already deallocated before the end of the block. It
+  /// also updates the ownership map accordingly.
+  ///
+  /// Example:
+  /// ```
+  /// %alloc = memref.alloc()
+  /// %alloca = memref.alloca()
+  /// ```
+  /// becomes
+  /// ```
+  /// %alloc = memref.alloc()
+  /// %alloca = memref.alloca()
+  /// // set ownership(alloc) := true
+  /// // set ownership(alloca) := false
+  /// // remember to deallocate %alloc
+  /// ```
+  FailureOr<Operation *> handleInterface(MemoryEffectOpInterface op);
+
+  /// Takes care that the function boundary ABI is adhered to if the parent
+  /// operation implements FunctionOpInterface, inserting a
+  /// `bufferization.clone` if necessary, and inserts the
+  /// `bufferization.dealloc` operation according to the ops operands.
+  ///
+  /// Example:
+  /// ```
+  /// ^bb1:
+  ///   <more ops...>
+  ///   func.return <return-vals>
+  /// ```
+  /// becomes
+  /// ```
+  /// // let (m, c) = getMemrefsAndConditionsToDeallocate(bb1)
+  /// // let r = getMemrefsToRetain(bb1, nullptr, <return-vals>)
+  /// ^bb1:
+  ///   <more ops...>
+  ///   o = bufferization.dealloc m if c retain r
+  ///   func.return <return-vals>
+  ///     (if !isFunctionWithoutDynamicOwnership: append o)
+  /// ```
+  FailureOr<Operation *> handleInterface(RegionBranchTerminatorOpInterface op);
+
+  /// Construct a new operation which is exactly the same as the passed 'op'
+  /// except that the OpResults list is appended by new results of the passed
+  /// 'types'.
+  /// TODO: ideally, this would be implemented using an OpInterface because it
+  /// is used to append function results, loop iter_args, etc. and thus makes
+  /// some assumptions that the variadic list of those is at the end of the
+  /// OpResults range.
+  Operation *appendOpResults(Operation *op, ArrayRef<Type> types);
+
+  /// A convenience template for the generic 'appendOpResults' function above to
+  /// avoid manual casting of the result.
+  template <typename OpTy>
+  OpTy appendOpResults(OpTy op, ArrayRef<Type> types) {
+    return cast<OpTy>(appendOpResults(op.getOperation(), types));
+  }
+
+  /// Performs deallocation of a single basic block. This is a private function
+  /// because some internal data structures have to be set up beforehand and
+  /// this function has to be called on blocks in a region in dominance order.
+  LogicalResult deallocate(Block *block);
+
+  /// Small helper function to update the ownership map by taking the current
+  /// ownership ('Uninitialized' state if not yet present), computing the join
+  /// with the passed ownership and storing this new value in the map. By
+  /// default, it will be performed for the block where 'owned' is defined. If
+  /// the ownership of the given value should be updated for another block, the
+  /// 'block' argument can be explicitly passed.
+  void joinOwnership(Value owned, Ownership ownership, Block *block = nullptr);
+
+  /// Removes ownerships associated with all values in the passed range for
+  /// 'block'.
+  void clearOwnershipOf(ValueRange values, Block *block);
+
+  /// After all relevant interfaces of an operation have been processed by the
+  /// 'handleInterface' functions, this function sets the ownership of operation
+  /// results that have not been set yet by the 'handleInterface' functions. It
+  /// generally assumes that each result can alias with every operand of the
+  /// operation, if there are MemRef typed results but no MemRef operands it
+  /// assigns 'false' as ownership. This happens, e.g., for the
+  /// memref.get_global operation. It would also be possible to query some alias
+  /// analysis to get more precise ownerships, however, the analysis would have
+  /// to be updated according to the IR modifications this pass performs (e.g.,
+  /// re-building operations to have more result values, inserting clone
+  /// operations, etc.).
+  void populateRemainingOwnerships(Operation *op);
+
+  /// Given two basic blocks and the values passed via block arguments to the
+  /// destination block, compute the list of MemRefs that have to be retained in
+  /// the 'fromBlock' to not run into a use-after-free situation.
+  /// This list consists of the MemRefs in the successor operand list of the
+  /// terminator and the MemRefs in the 'out' set of the liveness analysis
+  /// intersected with the 'in' set of the destination block.
+  ///
+  /// toRetain = filter(successorOperands + (liveOut(fromBlock) insersect
+  ///   liveIn(toBlock)), isMemRef)
+  void getMemrefsToRetain(Block *fromBlock, Block *toBlock,
+                          ValueRange destOperands,
+                          SmallVectorImpl<Value> &toRetain) const;
+
+  /// For a given block, computes the list of MemRefs that potentially need to
+  /// be deallocated at the end of that block. This list also contains values
+  /// that have to be retained (and are thus part of the list returned by
+  /// `getMemrefsToRetain`) and is computed by taking the MemRefs in the 'in'
+  /// set of the liveness analysis of 'block'  appended by the set of MemRefs
+  /// allocated in 'block' itself and subtracted by the set of MemRefs
+  /// deallocated in 'block'.
+  /// Note that we don't have to take the intersection of the liveness 'in' set
+  /// with the 'out' set of the predecessor block because a value that is in the
+  /// 'in' set must be defined in an ancestor block that dominates all direct
+  /// predecessors and thus the 'in' set of this block is a subset of the 'out'
+  /// sets of each predecessor.
+  ///
+  /// memrefs = filter((liveIn(block) U
+  ///   allocated(block) U arguments(block)) \ deallocated(block), isMemRef)
+  ///
+  /// The list of conditions is then populated by querying the internal
+  /// datastructures for the ownership value of that MemRef.
+  LogicalResult
+  getMemrefsAndConditionsToDeallocate(OpBuilder &builder, Location loc,
+                                      Block *block,
+                                      SmallVectorImpl<Value> &memrefs,
+                                      SmallVectorImpl<Value> &conditions) const;
+
+  /// Given an SSA value of MemRef type, this function queries the ownership and
+  /// if it is not already in the 'Unique' state, potentially inserts IR to get
+  /// a new SSA value, returned as the first element of the pair, which has
+  /// 'Unique' ownership and can be used instead of the passed Value with the
+  /// the ownership indicator returned as the second element of the pair.
+  std::pair<Value, Value> getMemrefWithUniqueOwnership(OpBuilder &builder,
+                                                       Value memref);
+
+  /// Given an SSA value of MemRef type, returns the same of a new SSA value
+  /// which has 'Unique' ownership where the ownership indicator is guaranteed
+  /// to be always 'true'.
+  Value getMemrefWithGuaranteedOwnership(OpBuilder &builder, Value memref);
+
+  /// Returns whether the given operation implements FunctionOpInterface, has
+  /// private visibility, and the private-function-dynamic-ownership pass option
+  /// is enabled.
+  bool isFunctionWithoutDynamicOwnership(Operation *op);
+
+  /// Checks all the preconditions for operations implementing the
+  /// FunctionOpInterface that have to hold for the deallocation to be
+  /// applicable:
+  /// (1) Checks that there are not explicit control flow loops.
+  static LogicalResult verifyFunctionPreconditions(FunctionOpInterface op);
+
+  /// Checks all the preconditions for operations inside the region of
+  /// operations implementing the FunctionOpInterface that have to hold for the
+  /// deallocation to be applicable:
+  /// (1) Checks if all operations that have at least one attached region
+  /// implement the RegionBranchOpInterface. This is not required in edge cases,
+  /// where we have a single attached region and the parent operation has no
+  /// results.
+  /// (2) Checks that no deallocations already exist. Especially deallocations
+  /// in nested regions are not properly supported yet since this requires
+  /// ownership of the memref to be transferred to the nested region, which does
+  /// not happen by default.  This constrained can be lifted in the future.
+  /// (3) Checks that terminators with more than one successor except
+  /// `cf.cond_br` are not present and that either BranchOpInterface or
+  /// RegionBranchTerminatorOpInterface is implemented.
+  static LogicalResult verifyOperationPreconditions(Operation *op);
+
+  /// When the 'private-function-dynamic-ownership' pass option is enabled,
+  /// additional `i1` arguments and return values are added for each MemRef
+  /// value in the function signature. This function takes care of updating the
+  /// `function_type` attribute of the function according to the actually
+  /// returned values from the terminators.
+  static LogicalResult updateFunctionSignature(FunctionOpInterface op);
+
+private:
+  // Mapping from each SSA value with MemRef type to the associated ownership in
+  // each block.
+  DenseMap<std::pair<Value, Block *>, Ownership> ownershipMap;
+
+  // Collects the list of MemRef values that potentially need to be deallocated
+  // per block. It is also fine (albeit not efficient) to add MemRef values that
+  // don't have to be deallocated, but only when the ownership is not 'Unknown'.
+  DenseMap<Block *, SmallVector<Value>> memrefsToDeallocatePerBlock;
+
+  // Symbol cache to lookup functions from call operations to check attributes
+  // on the function operation.
+  SymbolTableCollection symbolTable;
+
+  // The underlying liveness analysis to compute fine grained information about
+  // alloc and dealloc positions.
+  Liveness liveness;
+
+  // A pass option indicating whether private functions should be modified to
+  // pass the ownership of MemRef values instead of adhering to the function
+  // boundary ABI.
+  bool privateFuncDynamicOwnership;
+};
+
+} // namespace
+
+//===----------------------------------------------------------------------===//
+// BufferDeallocation Implementation
+//===----------------------------------------------------------------------===//
+
+void BufferDeallocation::joinOwnership(Value owned, Ownership ownership,
+                                       Block *block) {
+  // In most cases we care about the block where the value is defined.
+  if (block == nullptr)
+    block = owned.getParentBlock();
+
+  // Update ownership of current memref itself.
+  ownershipMap[{owned, block}].combine(ownership);
+}
+
+void BufferDeallocation::clearOwnershipOf(ValueRange values, Block *block) {
+  for (Value val : values) {
+    ownershipMap[{val, block}] = Ownership::getUninitialized();
+  }
+}
+
+static bool regionOperatesOnMemrefValues(Region &region) {
+  WalkResult result = region.walk([](Block *block) {
+    if (llvm::any_of(block->getArguments(), isMemref))
+      return WalkResult::interrupt();
+    for (Operation &op : *block) {
+      if (llvm::any_of(op.getOperands(), isMemref))
+        return WalkResult::interrupt();
+      if (llvm::any_of(op.getResults(), isMemref))
+        return WalkResult::interrupt();
+    }
+    return WalkResult::advance();
+  });
+  return result.wasInterrupted();
+}
+
+LogicalResult
+BufferDeallocation::verifyFunctionPreconditions(FunctionOpInterface op) {
+  // (1) Ensure that there are supported loops only (no explicit control flow
+  // loops).
+  Backedges backedges(op);
+  if (backedges.size()) {
+    op->emitError("Only structured control-flow loops are supported.");
+    return failure();
+  }
+
+  return success();
+}
+
+LogicalResult BufferDeallocation::verifyOperationPreconditions(Operation *op) {
+  // (1) Check that the control flow structures are supported.
+  auto regions = op->getRegions();
+  // Check that if the operation has at
+  // least one region it implements the RegionBranchOpInterface. If there
+  // is an operation that does not fulfill this condition, we cannot apply
+  // the deallocation steps. Furthermore, we accept cases, where we have a
+  // region that returns no results, since, in that case, the intra-region
+  // control flow does not affect the transformation.
+  size_t size = regions.size();
+  if (((size == 1 && !op->getResults().empty()) || size > 1) &&
+      !dyn_cast<RegionBranchOpInterface>(op)) {
+    if (llvm::any_of(regions, regionOperatesOnMemrefValues))
+      return op->emitError("All operations with attached regions need to "
+                           "implement the RegionBranchOpInterface.");
+  }
+
+  // (2) The pass does not work properly when deallocations are already present.
+  // Alternatively, we could also remove all deallocations as a pre-pass.
+  if (isa<DeallocOp>(op))
+    return op->emitError(
+        "No deallocation operations must be present when running this pass!");
+
+  // (3) Check that terminators with more than one successor except `cf.cond_br`
+  // are not present and that either BranchOpInterface or
+  // RegionBranchTerminatorOpInterface is implemented.
+  if (op->hasTrait<OpTrait::NoTerminator>())
+    return op->emitError("NoTerminator trait is not supported");
+
+  if (op->hasTrait<OpTrait::IsTerminator>()) {
+    // Either one of those interfaces has to be implemented on terminators, but
+    // not both.
+    if (!isa<BranchOpInterface, RegionBranchTerminatorOpInterface>(op) ||
+        (isa<BranchOpInterface>(op) &&
+         isa<RegionBranchTerminatorOpInterface>(op)))
+
+      return op->emitError(
+          "Terminators must implement either BranchOpInterface or "
+          "RegionBranchTerminatorOpInterface (but not both)!");
+
+    // We only support terminators with 0 or 1 successors for now and
+    // special-case the conditional branch op.
+    if (op->getSuccessors().size() > 1 && !isa<cf::CondBranchOp>(op))
+
+      return op->emitError("Terminators with more than one successor "
+                           "are not supported (except cf.cond_br)!");
+  }
+
+  return success();
+}
+
+LogicalResult
+BufferDeallocation::updateFunctionSignature(FunctionOpInterface op) {
+  SmallVector<TypeRange> returnOperandTypes(llvm::map_range(
+      op.getFunctionBody().getOps<RegionBranchTerminatorOpInterface>(),
+      [](RegionBranchTerminatorOpInterface op) {
+        return op.getSuccessorOperands(RegionBranchPoint::parent()).getTypes();
+      }));
+  if (!llvm::all_equal(returnOperandTypes))
+    return op->emitError(
+        "there are multiple return operations with different operand types");
+
+  TypeRange resultTypes = op.getResultTypes();
+  // Check if we found a return operation because that doesn't necessarily
+  // always have to be the case, e.g., consider a function with one block that
+  // has a cf.br at the end branching to itself again (i.e., an infinite loop).
+  // In that case we don't want to crash but just not update the return types.
+  if (!returnOperandTypes.empty())
+    resultTypes = returnOperandTypes[0];
+
+  // TODO: it would be nice if the FunctionOpInterface had a method to not only
+  // get the function type but also set it.
+  op->setAttr(
+      "function_type",
+      TypeAttr::get(FunctionType::get(
+          op->getContext(), op.getFunctionBody().front().getArgumentTypes(),
+          resultTypes)));
+
+  return success();
+}
+
+LogicalResult BufferDeallocation::deallocate(FunctionOpInterface op) {
+  // Stop and emit a proper error message if we don't support the input IR.
+  if (failed(verifyFunctionPreconditions(op)))
+    return failure();
+
+  // Process the function block by block.
+  auto result = op->walk<WalkOrder::PostOrder, ForwardDominanceIterator<>>(
+      [&](Block *block) {
+        if (failed(deallocate(block)))
+          return WalkResult::interrupt();
+        return WalkResult::advance();
+      });
+  if (result.wasInterrupted())
+    return failure();
+
+  // Update the function signature if the function is private, dynamic ownership
+  // is enabled, and the function has memrefs as arguments or results.
+  return updateFunctionSignature(op);
+}
+
+void BufferDeallocation::getMemrefsToRetain(
+    Block *fromBlock, Block *toBlock, ValueRange destOperands,
+    SmallVectorImpl<Value> &toRetain) const {
+  for (Value operand : destOperands) {
+    if (!isMemref(operand))
+      continue;
+    toRetain.push_back(operand);
+  }
+
+  SmallPtrSet<Value, 16> liveOut;
+  for (auto val : liveness.getLiveOut(fromBlock))
+    if (isMemref(val))
+      liveOut.insert(val);
+
+  if (toBlock)
+    llvm::set_intersect(liveOut, liveness.getLiveIn(toBlock));
+
+  // liveOut has non-deterministic order because it was constructed by iterating
+  // over a hash-set.
+  SmallVector<Value> retainedByLiveness(liveOut.begin(), liveOut.end());
+  std::sort(retainedByLiveness.begin(), retainedByLiveness.end(),
+            ValueComparator());
+  toRetain.append(retainedByLiveness);
+}
+
+LogicalResult BufferDeallocation::getMemrefsAndConditionsToDeallocate(
+    OpBuilder &builder, Location loc, Block *block,
+    SmallVectorImpl<Value> &memrefs, SmallVectorImpl<Value> &conditions) const {
+
+  for (auto [i, memref] :
+       llvm::enumerate(memrefsToDeallocatePerBlock.lookup(block))) {
+    Ownership ownership = ownershipMap.lookup({memref, block});
+    assert(ownership.isUnique() && "MemRef value must have valid ownership");
+
+    // Simply cast unranked MemRefs to ranked memrefs with 0 dimensions such
+    // that we can call extract_strided_metadata on it.
+    if (auto unrankedMemRefTy = dyn_cast<UnrankedMemRefType>(memref.getType()))
+      memref = builder.create<memref::ReinterpretCastOp>(
+          loc, MemRefType::get({}, unrankedMemRefTy.getElementType()), memref,
+          0, SmallVector<int64_t>{}, SmallVector<int64_t>{});
+
+    // Use the `memref.extract_strided_metadata` operation to get the base
+    // memref. This is needed because the same MemRef that was produced by the
+    // alloc operation has to be passed to the dealloc operation. Passing
+    // subviews, etc. to a dealloc operation is not allowed.
+    memrefs.push_back(
+        builder.create<memref::ExtractStridedMetadataOp>(loc, memref)
+            .getResult(0));
+    conditions.push_back(ownership.getIndicator());
+  }
+
+  return success();
+}
+
+LogicalResult BufferDeallocation::deallocate(Block *block) {
+  OpBuilder builder = OpBuilder::atBlockBegin(block);
+
+  // Compute liveness transfers of ownership to this block.
+  for (auto li : liveness.getLiveIn(block)) {
+    if (!isMemref(li))
+      continue;
+
+    // Ownership of implicitly captured memrefs from other regions is never
+    // taken, but ownership of memrefs in the same region (but different block)
+    // is taken.
+    if (li.getParentRegion() == block->getParent()) {
+      joinOwnership(li, ownershipMap[{li, li.getParentBlock()}], block);
+      memrefsToDeallocatePerBlock[block].push_back(li);
+      continue;
+    }
+
+    if (li.getParentRegion()->isProperAncestor(block->getParent())) {
+      Value falseVal = buildBoolValue(builder, li.getLoc(), false);
+      joinOwnership(li, falseVal, block);
+    }
+  }
+
+  for (unsigned i = 0, e = block->getNumArguments(); i < e; ++i) {
+    BlockArgument arg = block->getArgument(i);
+    if (!isMemref(arg))
+      continue;
+
+    // Adhere to function boundary ABI: no ownership of function argument
+    // MemRefs is taken.
+    if (isFunctionWithoutDynamicOwnership(block->getParentOp()) &&
+        block->isEntryBlock()) {
+      Value newArg = buildBoolValue(builder, arg.getLoc(), false);
+      joinOwnership(arg, newArg);
+      continue;
+    }
+
+    // Pass MemRef ownerships along via `i1` values.
+    Value newArg = block->addArgument(builder.getI1Type(), arg.getLoc());
+    joinOwnership(arg, newArg);
+    memrefsToDeallocatePerBlock[block].push_back(arg);
+  }
+
+  // For each operation in the block, handle the interfaces that affect aliasing
+  // and ownership of memrefs.
+  for (Operation &op : llvm::make_early_inc_range(*block)) {
+    FailureOr<Operation *> result = handleAllInterfaces(&op);
+    if (failed(result))
+      return failure();
+
+    populateRemainingOwnerships(*result);
+  }
+
+  // TODO: if block has no terminator, handle dealloc insertion here.
+  return success();
+}
+
+Operation *BufferDeallocation::appendOpResults(Operation *op,
+                                               ArrayRef<Type> types) {
+  SmallVector<Type> newTypes(op->getResultTypes());
+  newTypes.append(types.begin(), types.end());
+  auto *newOp = Operation::create(op->getLoc(), op->getName(), newTypes,
+                                  op->getOperands(), op->getAttrDictionary(),
+                                  op->getPropertiesStorage(),
+                                  op->getSuccessors(), op->getNumRegions());
+  for (auto [oldRegion, newRegion] :
+       llvm::zip(op->getRegions(), newOp->getRegions()))
+    newRegion.takeBody(oldRegion);
+
+  OpBuilder(op).insert(newOp);
+  op->replaceAllUsesWith(newOp->getResults().take_front(op->getNumResults()));
+  op->erase();
+
+  return newOp;
+}
+
+FailureOr<Operation *>
+BufferDeallocation::handleInterface(cf::CondBranchOp op) {
+  OpBuilder builder(op);
+
+  // The list of memrefs to pass to the `bufferization.dealloc` op as "memrefs
+  // to deallocate" in this block is independent of which branch is taken.
+  SmallVector<Value> memrefs, ownerships;
+  if (failed(getMemrefsAndConditionsToDeallocate(
+          builder, op.getLoc(), op->getBlock(), memrefs, ownerships)))
+    return failure();
+
+  // Helper lambda to factor out common logic for inserting the dealloc
+  // operations for each successor.
+  auto insertDeallocForBranch =
+      [&](Block *target, MutableOperandRange destOperands,
+          ArrayRef<Value> conditions,
+          DenseMap<Value, Value> &ownershipMapping) -> DeallocOp {
+    SmallVector<Value> toRetain;
+    getMemrefsToRetain(op->getBlock(), target, OperandRange(destOperands),
+                       toRetain);
+    auto deallocOp = builder.create<bufferization::DeallocOp>(
+        op.getLoc(), memrefs, conditions, toRetain);
+    clearOwnershipOf(deallocOp.getRetained(), op->getBlock());
+    for (auto [retained, ownership] :
+         llvm::zip(deallocOp.getRetained(), deallocOp.getUpdatedConditions())) {
+      joinOwnership(retained, ownership, op->getBlock());
+      ownershipMapping[retained] = ownership;
+    }
+    SmallVector<Value> replacements, ownerships;
+    for (Value operand : destOperands) {
+      replacements.push_back(operand);
+      if (isMemref(operand)) {
+        assert(ownershipMapping.contains(operand) &&
+               "Should be contained at this point");
+        ownerships.push_back(ownershipMapping[operand]);
+      }
+    }
+    replacements.append(ownerships);
+    destOperands.assign(replacements);
+    return deallocOp;
+  };
+
+  // Call the helper lambda and make sure the dealloc conditions are properly
+  // modified to reflect the branch condition as well.
+  DenseMap<Value, Value> thenOwnershipMap, elseOwnershipMap;
+
+  // Retain `trueDestOperands` if "true" branch is taken.
+  SmallVector<Value> thenOwnerships(
+      llvm::map_range(ownerships, [&](Value cond) {
+        return builder.create<arith::AndIOp>(op.getLoc(), cond,
+                                             op.getCondition());
+      }));
+  DeallocOp thenTakenDeallocOp =
+      insertDeallocForBranch(op.getTrueDest(), op.getTrueDestOperandsMutable(),
+                             thenOwnerships, thenOwnershipMap);
+
+  // Retain `elseDestOperands` if "false" branch is taken.
+  SmallVector<Value> elseOwnerships(
+      llvm::map_range(ownerships, [&](Value cond) {
+        Value trueVal = builder.create<arith::ConstantOp>(
+            op.getLoc(), builder.getBoolAttr(true));
+        Value negation = builder.create<arith::XOrIOp>(op.getLoc(), trueVal,
+                                                       op.getCondition());
+        return builder.create<arith::AndIOp>(op.getLoc(), cond, negation);
+      }));
+  DeallocOp elseTakenDeallocOp = insertDeallocForBranch(
+      op.getFalseDest(), op.getFalseDestOperandsMutable(), elseOwnerships,
+      elseOwnershipMap);
+
+  // We specifically need to update the ownerships of values that are retained
+  // in both dealloc operations again to get a combined 'Unique' ownership
+  // instead of an 'Unknown' ownership.
+  SmallPtrSet<Value, 16> thenValues(thenTakenDeallocOp.getRetained().begin(),
+                                    thenTakenDeallocOp.getRetained().end());
+  SetVector<Value> commonValues;
+  for (Value val : elseTakenDeallocOp.getRetained()) {
+    if (thenValues.contains(val))
+      commonValues.insert(val);
+  }
+
+  for (Value retained : commonValues) {
+    clearOwnershipOf(retained, op->getBlock());
+    Value combinedOwnership = builder.create<arith::SelectOp>(
+        op.getLoc(), op.getCondition(), thenOwnershipMap[retained],
+        elseOwnershipMap[retained]);
+    joinOwnership(retained, combinedOwnership, op->getBlock());
+  }
+
+  return op.getOperation();
+}
+
+FailureOr<Operation *>
+BufferDeallocation::handleInterface(RegionBranchOpInterface op) {
+  OpBuilder builder = OpBuilder::atBlockBegin(op->getBlock());
+
+  // TODO: the RegionBranchOpInterface does not provide all the necessary
+  // methods to perform this transformation without additional assumptions on
+  // the structure. In particular, that
+  // * additional values to be passed to the next region can be added to the end
+  //   of the operand list, the end of the block argument list, and the end of
+  //   the result value list. However, it seems to be the general guideline for
+  //   operations implementing this interface to follow this structure.
+  // * and that the block arguments and result values match the forwarded
+  //   operands one-to-one (i.e., that there are no other values appended to the
+  //   front).
+  // These assumptions are satisfied by the `scf.if`, `scf.for`, and `scf.while`
+  // operations.
+
+  SmallVector<RegionSuccessor> regions;
+  op.getSuccessorRegions(RegionBranchPoint::parent(), regions);
+  assert(!regions.empty() && "Must have at least one successor region");
+  SmallVector<Value> entryOperands(
+      op.getEntrySuccessorOperands(regions.front()));
+  unsigned numMemrefOperands = llvm::count_if(entryOperands, isMemref);
+
+  // No ownership is acquired for any MemRefs that are passed to the region from
+  // the outside.
+  Value falseVal = buildBoolValue(builder, op.getLoc(), false);
+  op->insertOperands(op->getNumOperands(),
+                     SmallVector<Value>(numMemrefOperands, falseVal));
+
+  int counter = op->getNumResults();
+  unsigned numMemrefResults = llvm::count_if(op->getResults(), isMemref);
+  SmallVector<Type> ownershipResults(numMemrefResults, builder.getI1Type());
+  RegionBranchOpInterface newOp = appendOpResults(op, ownershipResults);
+
+  for (auto result : llvm::make_filter_range(newOp->getResults(), isMemref)) {
+    joinOwnership(result, newOp->getResult(counter++));
+    memrefsToDeallocatePerBlock[newOp->getBlock()].push_back(result);
+  }
+
+  return newOp.getOperation();
+}
+
+std::pair<Value, Value>
+BufferDeallocation::getMemrefWithUniqueOwnership(OpBuilder &builder,
+                                                 Value memref) {
+  auto iter = ownershipMap.find({memref, memref.getParentBlock()});
+  assert(iter != ownershipMap.end() &&
+         "Value must already have been registered in the ownership map");
+
+  Ownership ownership = iter->second;
+  if (ownership.isUnique())
+    return {memref, ownership.getIndicator()};
+
+  // Instead of inserting a clone operation we could also insert a dealloc
+  // operation earlier in the block and use the updated ownerships returned by
+  // the op for the retained values. Alternatively, we could insert code to
+  // check aliasing at runtime and use this information to combine two unique
+  // ownerships more intelligently to not end up with an 'Unknown' ownership in
+  // the first place.
+  auto cloneOp =
+      builder.create<bufferization::CloneOp>(memref.getLoc(), memref);
+  Value condition = buildBoolValue(builder, memref.getLoc(), true);
+  Value newMemref = cloneOp.getResult();
+  joinOwnership(newMemref, condition);
+  memrefsToDeallocatePerBlock[newMemref.getParentBlock()].push_back(newMemref);
+  return {newMemref, condition};
+}
+
+Value BufferDeallocation::getMemrefWithGuaranteedOwnership(OpBuilder &builder,
+                                                           Value memref) {
+  // First, make sure we at least have 'Unique' ownership already.
+  std::pair<Value, Value> newMemrefAndOnwership =
+      getMemrefWithUniqueOwnership(builder, memref);
+  Value newMemref = newMemrefAndOnwership.first;
+  Value condition = newMemrefAndOnwership.second;
+
+  // Avoid inserting additional IR if ownership is already guaranteed. In
+  // particular, this is already the case when we had 'Unknown' ownership
+  // initially and a clone was inserted to get to 'Unique' ownership.
+  if (matchPattern(condition, m_One()))
+    return newMemref;
+
+  // Insert a runtime check and only clone if we still don't have ownership at
+  // runtime.
+  Value maybeClone =
+      builder
+          .create<scf::IfOp>(
+              memref.getLoc(), condition,
+              [&](OpBuilder &builder, Location loc) {
+                builder.create<scf::YieldOp>(loc, newMemref);
+              },
+              [&](OpBuilder &builder, Location loc) {
+                Value clone =
+                    builder.create<bufferization::CloneOp>(loc, newMemref);
+                builder.create<scf::YieldOp>(loc, clone);
+              })
+          .getResult(0);
+  Value trueVal = buildBoolValue(builder, memref.getLoc(), true);
+  joinOwnership(maybeClone, trueVal);
+  memrefsToDeallocatePerBlock[maybeClone.getParentBlock()].push_back(
+      maybeClone);
+  return maybeClone;
+}
+
+FailureOr<Operation *>
+BufferDeallocation::handleInterface(BranchOpInterface op) {
+  // Skip conditional branches since we special case them for now.
+  if (isa<cf::CondBranchOp>(op.getOperation()))
+    return op.getOperation();
+
+  if (op->getNumSuccessors() != 1)
+    return emitError(op.getLoc(),
+                     "only BranchOpInterface operations with exactly "
+                     "one successor are supported yet");
+
+  if (op.getSuccessorOperands(0).getProducedOperandCount() > 0)
+    return op.emitError("produced operands are not supported");
+
+  // Collect the values to deallocate and retain and use them to create the
+  // dealloc operation.
+  Block *block = op->getBlock();
+  OpBuilder builder(op);
+  SmallVector<Value> memrefs, conditions, toRetain;
+  if (failed(getMemrefsAndConditionsToDeallocate(builder, op.getLoc(), block,
+                                                 memrefs, conditions)))
+    return failure();
+
+  OperandRange forwardedOperands =
+      op.getSuccessorOperands(0).getForwardedOperands();
+  getMemrefsToRetain(block, op->getSuccessor(0), forwardedOperands, toRetain);
+
+  auto deallocOp = builder.create<bufferization::DeallocOp>(
+      op.getLoc(), memrefs, conditions, toRetain);
+
+  // We want to replace the current ownership of the retained values with the
+  // result values of the dealloc operation as they are always unique.
+  clearOwnershipOf(deallocOp.getRetained(), block);
+  for (auto [retained, ownership] :
+       llvm::zip(deallocOp.getRetained(), deallocOp.getUpdatedConditions())) {
+    joinOwnership(retained, ownership, block);
+  }
+
+  unsigned numAdditionalReturns = llvm::count_if(forwardedOperands, isMemref);
+  SmallVector<Value> newOperands(forwardedOperands);
+  auto additionalConditions =
+      deallocOp.getUpdatedConditions().take_front(numAdditionalReturns);
+  newOperands.append(additionalConditions.begin(), additionalConditions.end());
+  op.getSuccessorOperands(0).getMutableForwardedOperands().assign(newOperands);
+
+  return op.getOperation();
+}
+
+FailureOr<Operation *> BufferDeallocation::handleInterface(CallOpInterface op) {
+  OpBuilder builder(op);
+
+  // Lookup the function operation and check if it has private visibility. If
+  // the function is referenced by SSA value instead of a Symbol, it's assumed
+  // to be always private.
+  Operation *funcOp = op.resolveCallable(&symbolTable);
+  bool isPrivate = true;
+  if (auto symbol = dyn_cast<SymbolOpInterface>(funcOp))
+    isPrivate &= (symbol.getVisibility() == SymbolTable::Visibility::Private);
+
+  // If the private-function-dynamic-ownership option is enabled and we are
+  // calling a private function, we need to add an additional `i1`
+  // argument/result for each MemRef argument/result to dynamically pass the
+  // current ownership indicator rather than adhering to the function boundary
+  // ABI.
+  if (privateFuncDynamicOwnership && isPrivate) {
+    SmallVector<Value> newOperands, ownershipIndicatorsToAdd;
+    for (Value operand : op.getArgOperands()) {
+      if (!isMemref(operand)) {
+        newOperands.push_back(operand);
+        continue;
+      }
+      auto [memref, condition] = getMemrefWithUniqueOwnership(builder, operand);
+      newOperands.push_back(memref);
+      ownershipIndicatorsToAdd.push_back(condition);
+    }
+    newOperands.append(ownershipIndicatorsToAdd.begin(),
+                       ownershipIndicatorsToAdd.end());
+    op.getArgOperandsMutable().assign(newOperands);
+
+    unsigned numMemrefs = llvm::count_if(op->getResults(), isMemref);
+    SmallVector<Type> ownershipTypesToAppend(numMemrefs, builder.getI1Type());
+    unsigned ownershipCounter = op->getNumResults();
+    op = appendOpResults(op, ownershipTypesToAppend);
+
+    for (auto result : llvm::make_filter_range(op->getResults(), isMemref)) {
+      joinOwnership(result, op->getResult(ownershipCounter++));
+      memrefsToDeallocatePerBlock[result.getParentBlock()].push_back(result);
+    }
+
+    return op.getOperation();
+  }
+
+  // According to the function boundary ABI we are guaranteed to get ownership
+  // of all MemRefs returned by the function. Thus we set ownership to constant
+  // 'true' and remember to deallocate it.
+  Value trueVal = buildBoolValue(builder, op.getLoc(), true);
+  for (auto result : llvm::make_filter_range(op->getResults(), isMemref)) {
+    joinOwnership(result, trueVal);
+    memrefsToDeallocatePerBlock[result.getParentBlock()].push_back(result);
+  }
+
+  return op.getOperation();
+}
+
+FailureOr<Operation *>
+BufferDeallocation::handleInterface(MemoryEffectOpInterface op) {
+  auto *block = op->getBlock();
+
+  for (auto operand : llvm::make_filter_range(op->getOperands(), isMemref))
+    if (op.getEffectOnValue<MemoryEffects::Free>(operand).has_value())
+      return op->emitError(
+          "memory free side-effect on MemRef value not supported!");
+
+  OpBuilder builder = OpBuilder::atBlockBegin(block);
+  for (auto res : llvm::make_filter_range(op->getResults(), isMemref)) {
+    auto allocEffect = op.getEffectOnValue<MemoryEffects::Allocate>(res);
+    if (allocEffect.has_value()) {
+      if (isa<SideEffects::AutomaticAllocationScopeResource>(
+              allocEffect->getResource())) {
+        // Make sure that the ownership of auto-managed allocations is set to
+        // false. This is important for operations that have at least one memref
+        // typed operand. E.g., consider an operation like `bufferization.clone`
+        // that lowers to a `memref.alloca + memref.copy` instead of a
+        // `memref.alloc`. If we wouldn't set the ownership of the result here,
+        // the default ownership population in `populateRemainingOwnerships`
+        // would assume aliasing with the MemRef operand.
+        clearOwnershipOf(res, block);
+        joinOwnership(res, buildBoolValue(builder, op.getLoc(), false));
+        continue;
+      }
+
+      joinOwnership(res, buildBoolValue(builder, op.getLoc(), true));
+      memrefsToDeallocatePerBlock[block].push_back(res);
+    }
+  }
+
+  return op.getOperation();
+}
+
+FailureOr<Operation *>
+BufferDeallocation::handleInterface(RegionBranchTerminatorOpInterface op) {
+  OpBuilder builder(op);
+
+  // If this is a return operation of a function that is not private or the
+  // dynamic function boundary ownership is disabled, we need to return memref
+  // values for which we have guaranteed ownership to pass on to adhere to the
+  // function boundary ABI.
+  bool funcWithoutDynamicOwnership =
+      isFunctionWithoutDynamicOwnership(op->getParentOp());
+  if (funcWithoutDynamicOwnership) {
+    for (OpOperand &val : op->getOpOperands()) {
+      if (!isMemref(val.get()))
+        continue;
+
+      val.set(getMemrefWithGuaranteedOwnership(builder, val.get()));
+    }
+  }
+
+  // TODO: getSuccessorRegions is not implemented by all operations we care
+  // about, but we would need to check how many successors there are and under
+  // which condition they are taken, etc.
+
+  MutableOperandRange operands =
+      op.getMutableSuccessorOperands(RegionBranchPoint::parent());
+
+  // Collect the values to deallocate and retain and use them to create the
+  // dealloc operation.
+  Block *block = op->getBlock();
+  SmallVector<Value> memrefs, conditions, toRetain;
+  if (failed(getMemrefsAndConditionsToDeallocate(builder, op.getLoc(), block,
+                                                 memrefs, conditions)))
+    return failure();
+
+  getMemrefsToRetain(block, nullptr, OperandRange(operands), toRetain);
+  if (memrefs.empty() && toRetain.empty())
+    return op.getOperation();
+
+  auto deallocOp = builder.create<bufferization::DeallocOp>(
+      op.getLoc(), memrefs, conditions, toRetain);
+
+  // We want to replace the current ownership of the retained values with the
+  // result values of the dealloc operation as they are always unique.
+  clearOwnershipOf(deallocOp.getRetained(), block);
+  for (auto [retained, ownership] :
+       llvm::zip(deallocOp.getRetained(), deallocOp.getUpdatedConditions()))
+    joinOwnership(retained, ownership, block);
+
+  // Add an additional operand for every MemRef for the ownership indicator.
+  if (!funcWithoutDynamicOwnership) {
+    unsigned numMemRefs = llvm::count_if(operands, isMemref);
+    SmallVector<Value> newOperands{OperandRange(operands)};
+    auto ownershipValues =
+        deallocOp.getUpdatedConditions().take_front(numMemRefs);
+    newOperands.append(ownershipValues.begin(), ownershipValues.end());
+    operands.assign(newOperands);
+  }
+
+  return op.getOperation();
+}
+
+bool BufferDeallocation::isFunctionWithoutDynamicOwnership(Operation *op) {
+  auto funcOp = dyn_cast<FunctionOpInterface>(op);
+  return funcOp && (!privateFuncDynamicOwnership ||
+                    funcOp.getVisibility() != SymbolTable::Visibility::Private);
+}
+
+void BufferDeallocation::populateRemainingOwnerships(Operation *op) {
+  for (auto res : op->getResults()) {
+    if (!isMemref(res))
+      continue;
+    if (ownershipMap.count({res, op->getBlock()}))
+      continue;
+
+    // Don't take ownership of a returned memref if no allocate side-effect is
+    // present, relevant for memref.get_global, for example.
+    if (op->getNumOperands() == 0) {
+      OpBuilder builder(op);
+      joinOwnership(res, buildBoolValue(builder, op->getLoc(), false));
+      continue;
+    }
+
+    // Assume the result may alias with any operand and thus combine all their
+    // ownerships.
+    for (auto operand : op->getOperands()) {
+      if (!isMemref(operand))
+        continue;
+
+      ownershipMap[{res, op->getBlock()}].combine(
+          ownershipMap[{operand, operand.getParentBlock()}]);
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// OwnershipBasedBufferDeallocationPass
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+/// The actual buffer deallocation pass that inserts and moves dealloc nodes
+/// into the right positions. Furthermore, it inserts additional clones if
+/// necessary. It uses the algorithm described at the top of the file.
+struct OwnershipBasedBufferDeallocationPass
+    : public bufferization::impl::OwnershipBasedBufferDeallocationBase<
+          OwnershipBasedBufferDeallocationPass> {
+  void runOnOperation() override {
+    func::FuncOp func = getOperation();
+    if (func.isExternal())
+      return;
+
+    if (failed(
+            deallocateBuffersOwnershipBased(func, privateFuncDynamicOwnership)))
+      signalPassFailure();
+  }
+};
+
+} // namespace
+
+//===----------------------------------------------------------------------===//
+// Implement bufferization API
+//===----------------------------------------------------------------------===//
+
+LogicalResult bufferization::deallocateBuffersOwnershipBased(
+    FunctionOpInterface op, bool privateFuncDynamicOwnership) {
+  // Gather all required allocation nodes and prepare the deallocation phase.
+  BufferDeallocation deallocation(op, privateFuncDynamicOwnership);
+
+  // Place all required temporary clone and dealloc nodes.
+  return deallocation.deallocate(op);
+}
+
+//===----------------------------------------------------------------------===//
+// OwnershipBasedBufferDeallocationPass construction
+//===----------------------------------------------------------------------===//
+
+std::unique_ptr<Pass>
+mlir::bufferization::createOwnershipBasedBufferDeallocationPass() {
+  return std::make_unique<OwnershipBasedBufferDeallocationPass>();
+}
diff --git a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-branchop-interface.mlir b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-branchop-interface.mlir
new file mode 100644
index 000000000000000..23a628cc2b83d99
--- /dev/null
+++ b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-branchop-interface.mlir
@@ -0,0 +1,589 @@
+// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation \
+// RUN:  -buffer-deallocation-simplification -split-input-file %s | FileCheck %s
+// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation=private-function-dynamic-ownership=true -split-input-file %s > /dev/null
+
+// Test Case:
+//    bb0
+//   /   \
+//  bb1  bb2 <- Initial position of AllocOp
+//   \   /
+//    bb3
+// BufferDeallocation expected behavior: bb2 contains an AllocOp which is
+// passed to bb3. In the latter block, there should be a deallocation.
+// Since bb1 does not contain an adequate alloc, the deallocation has to be
+// made conditional on the branch taken in bb0.
+
+func.func @condBranch(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
+  cf.cond_br %arg0, ^bb2(%arg1 : memref<2xf32>), ^bb1
+^bb1:
+  %0 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
+  cf.br ^bb2(%0 : memref<2xf32>)
+^bb2(%1: memref<2xf32>):
+  test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+// CHECK-LABEL: func @condBranch
+//  CHECK-SAME: ([[ARG0:%.+]]: i1,
+//  CHECK-SAME: [[ARG1:%.+]]: memref<2xf32>,
+//  CHECK-SAME: [[ARG2:%.+]]: memref<2xf32>)
+//   CHECK-NOT: bufferization.dealloc
+//       CHECK: cf.cond_br{{.*}}, ^bb2([[ARG1]], %false{{[0-9_]*}} :{{.*}}), ^bb1
+//       CHECK: ^bb1:
+//       CHECK: %[[ALLOC1:.*]] = memref.alloc
+//  CHECK-NEXT: test.buffer_based
+//  CHECK-NEXT: cf.br ^bb2(%[[ALLOC1]], %true
+//  CHECK-NEXT: ^bb2([[ALLOC2:%.+]]: memref<2xf32>, [[COND1:%.+]]: i1):
+//       CHECK: test.copy
+//  CHECK-NEXT: [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[ALLOC2]]
+//  CHECK-NEXT: bufferization.dealloc ([[BASE]] : {{.*}}) if ([[COND1]])
+//  CHECK-NEXT: return
+
+// -----
+
+// Test Case:
+//    bb0
+//   /   \
+//  bb1  bb2 <- Initial position of AllocOp
+//   \   /
+//    bb3
+// BufferDeallocation expected behavior: The existing AllocOp has a dynamic
+// dependency to block argument %0 in bb2. Since the dynamic type is passed
+// to bb3 via the block argument %2, it is currently required to allocate a
+// temporary buffer for %2 that gets copies of %arg0 and %1 with their
+// appropriate shape dimensions. The copy buffer deallocation will be applied
+// to %2 in block bb3.
+
+func.func @condBranchDynamicType(
+  %arg0: i1,
+  %arg1: memref<?xf32>,
+  %arg2: memref<?xf32>,
+  %arg3: index) {
+  cf.cond_br %arg0, ^bb2(%arg1 : memref<?xf32>), ^bb1(%arg3: index)
+^bb1(%0: index):
+  %1 = memref.alloc(%0) : memref<?xf32>
+  test.buffer_based in(%arg1: memref<?xf32>) out(%1: memref<?xf32>)
+  cf.br ^bb2(%1 : memref<?xf32>)
+^bb2(%2: memref<?xf32>):
+  test.copy(%2, %arg2) : (memref<?xf32>, memref<?xf32>)
+  return
+}
+
+// CHECK-LABEL: func @condBranchDynamicType
+//  CHECK-SAME: ([[ARG0:%.+]]: i1, [[ARG1:%.+]]: memref<?xf32>, [[ARG2:%.+]]: memref<?xf32>, [[ARG3:%.+]]: index)
+//   CHECK-NOT: bufferization.dealloc
+//       CHECK: cf.cond_br{{.*}}^bb2(%arg1, %false{{[0-9_]*}} :{{.*}}), ^bb1
+//       CHECK: ^bb1([[IDX:%.*]]:{{.*}})
+//       CHECK: [[ALLOC1:%.*]] = memref.alloc([[IDX]])
+//  CHECK-NEXT: test.buffer_based
+//  CHECK-NEXT: cf.br ^bb2([[ALLOC1]], %true
+//  CHECK-NEXT: ^bb2([[ALLOC3:%.*]]:{{.*}}, [[COND:%.+]]:{{.*}})
+//       CHECK: test.copy([[ALLOC3]],
+//  CHECK-NEXT: [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[ALLOC3]]
+//  CHECK-NEXT: bufferization.dealloc ([[BASE]] : {{.*}}) if ([[COND]])
+//  CHECK-NEXT: return
+
+// -----
+
+// Test case: See above.
+
+func.func @condBranchUnrankedType(
+  %arg0: i1,
+  %arg1: memref<*xf32>,
+  %arg2: memref<*xf32>,
+  %arg3: index) {
+  cf.cond_br %arg0, ^bb2(%arg1 : memref<*xf32>), ^bb1(%arg3: index)
+^bb1(%0: index):
+  %1 = memref.alloc(%0) : memref<?xf32>
+  %2 = memref.cast %1 : memref<?xf32> to memref<*xf32>
+  test.buffer_based in(%arg1: memref<*xf32>) out(%2: memref<*xf32>)
+  cf.br ^bb2(%2 : memref<*xf32>)
+^bb2(%3: memref<*xf32>):
+  test.copy(%3, %arg2) : (memref<*xf32>, memref<*xf32>)
+  return
+}
+
+// CHECK-LABEL: func @condBranchUnrankedType
+//  CHECK-SAME: ([[ARG0:%.+]]: i1, [[ARG1:%.+]]: memref<*xf32>, [[ARG2:%.+]]: memref<*xf32>, [[ARG3:%.+]]: index)
+//   CHECK-NOT: bufferization.dealloc
+//       CHECK: cf.cond_br{{.*}}^bb2([[ARG1]], %false{{[0-9_]*}} :{{.*}}), ^bb1
+//       CHECK: ^bb1([[IDX:%.*]]:{{.*}})
+//       CHECK: [[ALLOC1:%.*]] = memref.alloc([[IDX]])
+//  CHECK-NEXT: [[CAST:%.+]] = memref.cast [[ALLOC1]]
+//  CHECK-NEXT: test.buffer_based
+//  CHECK-NEXT: cf.br ^bb2([[CAST]], %true
+//  CHECK-NEXT: ^bb2([[ALLOC3:%.*]]:{{.*}}, [[COND:%.+]]:{{.*}})
+//       CHECK: test.copy([[ALLOC3]],
+//  CHECK-NEXT: [[CAST:%.+]] = memref.reinterpret_cast [[ALLOC3]]
+//  CHECK-NEXT: [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[CAST]]
+//  CHECK-NEXT: bufferization.dealloc ([[BASE]] : {{.*}}) if ([[COND]])
+//  CHECK-NEXT: return
+
+// TODO: we can get rid of first dealloc by doing some must-alias analysis
+
+// -----
+
+// Test Case:
+//      bb0
+//     /    \
+//   bb1    bb2 <- Initial position of AllocOp
+//    |     /  \
+//    |   bb3  bb4
+//    |     \  /
+//    \     bb5
+//     \    /
+//       bb6
+//        |
+//       bb7
+// BufferDeallocation expected behavior: The existing AllocOp has a dynamic
+// dependency to block argument %0 in bb2.  Since the dynamic type is passed to
+// bb5 via the block argument %2 and to bb6 via block argument %3, it is
+// currently required to pass along the condition under which the newly
+// allocated buffer should be deallocated, since the path via bb1 does not
+// allocate a buffer.
+
+func.func @condBranchDynamicTypeNested(
+  %arg0: i1,
+  %arg1: memref<?xf32>,
+  %arg2: memref<?xf32>,
+  %arg3: index) {
+  cf.cond_br %arg0, ^bb1, ^bb2(%arg3: index)
+^bb1:
+  cf.br ^bb6(%arg1 : memref<?xf32>)
+^bb2(%0: index):
+  %1 = memref.alloc(%0) : memref<?xf32>
+  test.buffer_based in(%arg1: memref<?xf32>) out(%1: memref<?xf32>)
+  cf.cond_br %arg0, ^bb3, ^bb4
+^bb3:
+  cf.br ^bb5(%1 : memref<?xf32>)
+^bb4:
+  cf.br ^bb5(%1 : memref<?xf32>)
+^bb5(%2: memref<?xf32>):
+  cf.br ^bb6(%2 : memref<?xf32>)
+^bb6(%3: memref<?xf32>):
+  cf.br ^bb7(%3 : memref<?xf32>)
+^bb7(%4: memref<?xf32>):
+  test.copy(%4, %arg2) : (memref<?xf32>, memref<?xf32>)
+  return
+}
+
+// CHECK-LABEL: func @condBranchDynamicTypeNested
+//  CHECK-SAME: ([[ARG0:%.+]]: i1, [[ARG1:%.+]]: memref<?xf32>, [[ARG2:%.+]]: memref<?xf32>, [[ARG3:%.+]]: index)
+//   CHECK-NOT: bufferization.dealloc
+//   CHECK-NOT: bufferization.clone
+//       CHECK: cf.cond_br{{.*}}
+//  CHECK-NEXT: ^bb1
+//   CHECK-NOT: bufferization.dealloc
+//   CHECK-NOT: bufferization.clone
+//       CHECK: cf.br ^bb5([[ARG1]], %false{{[0-9_]*}} :
+//       CHECK: ^bb2([[IDX:%.*]]:{{.*}})
+//       CHECK: [[ALLOC1:%.*]] = memref.alloc([[IDX]])
+//  CHECK-NEXT: test.buffer_based
+//  CHECK-NEXT: [[NOT_ARG0:%.+]] = arith.xori [[ARG0]], %true
+//  CHECK-NEXT: [[OWN:%.+]] = arith.select [[ARG0]], [[ARG0]], [[NOT_ARG0]]
+//   CHECK-NOT: bufferization.dealloc
+//   CHECK-NOT: bufferization.clone
+//       CHECK: cf.cond_br{{.*}}, ^bb3, ^bb3
+//  CHECK-NEXT: ^bb3:
+//   CHECK-NOT: bufferization.dealloc
+//   CHECK-NOT: bufferization.clone
+//       CHECK: cf.br ^bb4([[ALLOC1]], [[OWN]]
+//  CHECK-NEXT: ^bb4([[ALLOC2:%.*]]:{{.*}}, [[COND1:%.+]]:{{.*}})
+//   CHECK-NOT: bufferization.dealloc
+//   CHECK-NOT: bufferization.clone
+//       CHECK: cf.br ^bb5([[ALLOC2]], [[COND1]]
+//  CHECK-NEXT: ^bb5([[ALLOC4:%.*]]:{{.*}}, [[COND2:%.+]]:{{.*}})
+//  CHECK-NEXT: [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[ALLOC4]]
+//  CHECK-NEXT: [[OWN:%.+]]:2 = bufferization.dealloc ([[BASE]] :{{.*}}) if ([[COND2]]) retain ([[ALLOC4]], [[ARG2]] :
+//       CHECK: cf.br ^bb6([[ALLOC4]], [[OWN]]#0
+//  CHECK-NEXT: ^bb6([[ALLOC5:%.*]]:{{.*}}, [[COND3:%.+]]:{{.*}})
+//       CHECK: test.copy
+//       CHECK: [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[ALLOC5]]
+//  CHECK-NEXT: bufferization.dealloc ([[BASE]] : {{.*}}) if ([[COND3]])
+//  CHECK-NEXT: return
+
+// TODO: the dealloc in bb5 can be optimized away by adding another
+// canonicalization pattern
+
+// -----
+
+// Test Case:
+//    bb0
+//   /   \
+//  |    bb1 <- Initial position of AllocOp
+//   \   /
+//    bb2
+// BufferDeallocation expected behavior: It should insert a DeallocOp at the
+// exit block after CopyOp since %1 is an alias for %0 and %arg1.
+
+func.func @criticalEdge(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
+  cf.cond_br %arg0, ^bb1, ^bb2(%arg1 : memref<2xf32>)
+^bb1:
+  %0 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
+  cf.br ^bb2(%0 : memref<2xf32>)
+^bb2(%1: memref<2xf32>):
+  test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+// CHECK-LABEL: func @criticalEdge
+//  CHECK-SAME: ([[ARG0:%.+]]: i1, [[ARG1:%.+]]: memref<2xf32>, [[ARG2:%.+]]: memref<2xf32>)
+//   CHECK-NOT: bufferization.dealloc
+//   CHECK-NOT: bufferization.clone
+//       CHECK: cf.cond_br{{.*}}, ^bb1, ^bb2([[ARG1]], %false
+//       CHECK: [[ALLOC1:%.*]] = memref.alloc()
+//  CHECK-NEXT: test.buffer_based
+//  CHECK-NEXT: cf.br ^bb2([[ALLOC1]], %true
+//  CHECK-NEXT: ^bb2([[ALLOC2:%.+]]:{{.*}}, [[COND:%.+]]: {{.*}})
+//       CHECK: test.copy
+//  CHECK-NEXT: [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[ALLOC2]]
+//  CHECK-NEXT: bufferization.dealloc ([[BASE]] : {{.*}}) if ([[COND]])
+//  CHECK-NEXT: return
+
+// -----
+
+// Test Case:
+//    bb0 <- Initial position of AllocOp
+//   /   \
+//  |    bb1
+//   \   /
+//    bb2
+// BufferDeallocation expected behavior: It only inserts a DeallocOp at the
+// exit block after CopyOp since %1 is an alias for %0 and %arg1.
+
+func.func @invCriticalEdge(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
+  %0 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
+  cf.cond_br %arg0, ^bb1, ^bb2(%arg1 : memref<2xf32>)
+^bb1:
+  cf.br ^bb2(%0 : memref<2xf32>)
+^bb2(%1: memref<2xf32>):
+  test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+// CHECK-LABEL: func @invCriticalEdge
+//  CHECK-SAME:  ([[ARG0:%.+]]: i1, [[ARG1:%.+]]: memref<2xf32>, [[ARG2:%.+]]: memref<2xf32>)
+//       CHECK:   [[ALLOC:%.+]] = memref.alloc()
+//  CHECK-NEXT:   test.buffer_based
+//  CHECK-NEXT:   [[NOT_ARG0:%.+]] = arith.xori [[ARG0]], %true
+//  CHECK-NEXT:   bufferization.dealloc ([[ALLOC]] : {{.*}}) if ([[NOT_ARG0]])
+//  CHECK-NEXT:   cf.cond_br{{.*}}^bb1, ^bb2([[ARG1]], %false
+//  CHECK-NEXT: ^bb1:
+//   CHECK-NOT:   bufferization.dealloc
+//   CHECK-NOT:   bufferization.clone
+//       CHECK:   cf.br ^bb2([[ALLOC]], [[ARG0]]
+//  CHECK-NEXT: ^bb2([[ALLOC1:%.+]]:{{.*}}, [[COND:%.+]]:{{.*}})
+//       CHECK:   test.copy
+//  CHECK-NEXT:   [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[ALLOC1]]
+//  CHECK-NEXT:   bufferization.dealloc ([[BASE]] : {{.*}}) if ([[COND]])
+//  CHECK-NEXT:   return
+
+// -----
+
+// Test Case:
+//    bb0 <- Initial position of the first AllocOp
+//   /   \
+//  bb1  bb2
+//   \   /
+//    bb3 <- Initial position of the second AllocOp
+// BufferDeallocation expected behavior: It only inserts two missing
+// DeallocOps in the exit block. %5 is an alias for %0. Therefore, the
+// DeallocOp for %0 should occur after the last BufferBasedOp. The Dealloc for
+// %7 should happen after CopyOp.
+
+func.func @ifElse(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
+  %0 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
+  cf.cond_br %arg0,
+    ^bb1(%arg1, %0 : memref<2xf32>, memref<2xf32>),
+    ^bb2(%0, %arg1 : memref<2xf32>, memref<2xf32>)
+^bb1(%1: memref<2xf32>, %2: memref<2xf32>):
+  cf.br ^bb3(%1, %2 : memref<2xf32>, memref<2xf32>)
+^bb2(%3: memref<2xf32>, %4: memref<2xf32>):
+  cf.br ^bb3(%3, %4 : memref<2xf32>, memref<2xf32>)
+^bb3(%5: memref<2xf32>, %6: memref<2xf32>):
+  %7 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%5: memref<2xf32>) out(%7: memref<2xf32>)
+  test.copy(%7, %arg2) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+// CHECK-LABEL: func @ifElse
+//  CHECK-SAME: ([[ARG0:%.+]]: i1, [[ARG1:%.+]]: memref<2xf32>, [[ARG2:%.+]]: memref<2xf32>)
+//       CHECK:   [[ALLOC0:%.+]] = memref.alloc()
+//  CHECK-NEXT:   test.buffer_based
+//   CHECK-NOT:   bufferization.dealloc
+//   CHECK-NOT:   bufferization.clone
+//  CHECK-NEXT:   [[NOT_ARG0:%.+]] = arith.xori [[ARG0]], %true
+//  CHECK-NEXT:   cf.cond_br {{.*}}^bb1([[ARG1]], [[ALLOC0]], %false{{[0-9_]*}}, [[ARG0]] : {{.*}}), ^bb2([[ALLOC0]], [[ARG1]], [[NOT_ARG0]], %false{{[0-9_]*}} : {{.*}})
+//       CHECK: ^bb3([[A0:%.+]]:{{.*}}, [[A1:%.+]]:{{.*}}, [[COND0:%.+]]: i1, [[COND1:%.+]]: i1):
+//       CHECK:   [[ALLOC1:%.+]] = memref.alloc()
+//  CHECK-NEXT:   test.buffer_based
+//  CHECK-NEXT:   test.copy
+//  CHECK-NEXT:   [[BASE0:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[A0]]
+//  CHECK-NEXT:   [[BASE1:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[A1]]
+//  CHECK-NEXT:   bufferization.dealloc ([[ALLOC1]] : {{.*}}) if (%true
+//   CHECK-NOT:   retain
+//  CHECK-NEXT:   bufferization.dealloc ([[BASE0]], [[BASE1]] : {{.*}}) if ([[COND0]], [[COND1]])
+//   CHECK-NOT:   retain
+//  CHECK-NEXT:   return
+
+// TODO: Instead of deallocating the bbarg memrefs, a slightly better analysis
+// could do an unconditional deallocation on ALLOC0 and move it before the
+// test.copy (dealloc of ALLOC1 would remain after the copy)
+
+// -----
+
+// Test Case: No users for buffer in if-else CFG
+//    bb0 <- Initial position of AllocOp
+//   /   \
+//  bb1  bb2
+//   \   /
+//    bb3
+// BufferDeallocation expected behavior: It only inserts a missing DeallocOp
+// in the exit block since %5 or %6 are the latest aliases of %0.
+
+func.func @ifElseNoUsers(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
+  %0 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
+  cf.cond_br %arg0,
+    ^bb1(%arg1, %0 : memref<2xf32>, memref<2xf32>),
+    ^bb2(%0, %arg1 : memref<2xf32>, memref<2xf32>)
+^bb1(%1: memref<2xf32>, %2: memref<2xf32>):
+  cf.br ^bb3(%1, %2 : memref<2xf32>, memref<2xf32>)
+^bb2(%3: memref<2xf32>, %4: memref<2xf32>):
+  cf.br ^bb3(%3, %4 : memref<2xf32>, memref<2xf32>)
+^bb3(%5: memref<2xf32>, %6: memref<2xf32>):
+  test.copy(%arg1, %arg2) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+// CHECK-LABEL: func @ifElseNoUsers
+//  CHECK-SAME: ([[ARG0:%.+]]: i1, [[ARG1:%.+]]: memref<2xf32>, [[ARG2:%.+]]: memref<2xf32>)
+//       CHECK:   [[ALLOC:%.+]] = memref.alloc()
+//  CHECK-NEXT:   test.buffer_based
+//  CHECK-NEXT:   [[NOT_ARG0:%.+]] = arith.xori [[ARG0]], %true
+//  CHECK-NEXT:   cf.cond_br {{.*}}^bb1([[ARG1]], [[ALLOC]], %false{{[0-9_]*}}, [[ARG0]] : {{.*}}), ^bb2([[ALLOC]], [[ARG1]], [[NOT_ARG0]], %false{{[0-9_]*}} : {{.*}})
+//       CHECK: ^bb3([[A0:%.+]]:{{.*}}, [[A1:%.+]]:{{.*}}, [[COND0:%.+]]: i1, [[COND1:%.+]]: i1):
+//       CHECK:   test.copy
+//  CHECK-NEXT:   [[BASE0:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[A0]]
+//  CHECK-NEXT:   [[BASE1:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[A1]]
+//  CHECK-NEXT:   bufferization.dealloc ([[BASE0]], [[BASE1]] : {{.*}}) if ([[COND0]], [[COND1]])
+//   CHECK-NOT:   retain
+//  CHECK-NEXT:   return
+
+// TODO: slightly better analysis could just insert an unconditional dealloc on %0
+
+// -----
+
+// Test Case:
+//      bb0 <- Initial position of the first AllocOp
+//     /    \
+//   bb1    bb2
+//    |     /  \
+//    |   bb3  bb4
+//    \     \  /
+//     \     /
+//       bb5 <- Initial position of the second AllocOp
+// BufferDeallocation expected behavior: Two missing DeallocOps should be
+// inserted in the exit block.
+
+func.func @ifElseNested(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
+  %0 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
+  cf.cond_br %arg0,
+    ^bb1(%arg1, %0 : memref<2xf32>, memref<2xf32>),
+    ^bb2(%0, %arg1 : memref<2xf32>, memref<2xf32>)
+^bb1(%1: memref<2xf32>, %2: memref<2xf32>):
+  cf.br ^bb5(%1, %2 : memref<2xf32>, memref<2xf32>)
+^bb2(%3: memref<2xf32>, %4: memref<2xf32>):
+  cf.cond_br %arg0, ^bb3(%3 : memref<2xf32>), ^bb4(%4 : memref<2xf32>)
+^bb3(%5: memref<2xf32>):
+  cf.br ^bb5(%5, %3 : memref<2xf32>, memref<2xf32>)
+^bb4(%6: memref<2xf32>):
+  cf.br ^bb5(%3, %6 : memref<2xf32>, memref<2xf32>)
+^bb5(%7: memref<2xf32>, %8: memref<2xf32>):
+  %9 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%7: memref<2xf32>) out(%9: memref<2xf32>)
+  test.copy(%9, %arg2) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+// CHECK-LABEL: func @ifElseNested
+//  CHECK-SAME: ([[ARG0:%.+]]: i1, [[ARG1:%.+]]: memref<2xf32>, [[ARG2:%.+]]: memref<2xf32>)
+//       CHECK:   [[ALLOC0:%.+]] = memref.alloc()
+//  CHECK-NEXT:   test.buffer_based
+//  CHECK-NEXT:   [[NOT_ARG0:%.+]] = arith.xori [[ARG0]], %true
+//  CHECK-NEXT:   cf.cond_br {{.*}}^bb1([[ARG1]], [[ALLOC0]], %false{{[0-9_]*}}, [[ARG0]] : {{.*}}), ^bb2([[ALLOC0]], [[ARG1]], [[NOT_ARG0]], %false{{[0-9_]*}} :
+//       CHECK: ^bb5([[A0:%.+]]: memref<2xf32>, [[A1:%.+]]: memref<2xf32>, [[COND0:%.+]]: i1, [[COND1:%.+]]: i1):
+//       CHECK:   [[ALLOC1:%.+]] = memref.alloc()
+//  CHECK-NEXT:   test.buffer_based
+//  CHECK-NEXT:   test.copy
+//  CHECK-NEXT:   [[BASE0:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[A0]]
+//  CHECK-NEXT:   [[BASE1:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[A1]]
+//  CHECK-NEXT:   bufferization.dealloc ([[ALLOC1]] : {{.*}}) if (%true
+//   CHECK-NOT:   retain
+//  CHECK-NEXT:   bufferization.dealloc ([[BASE0]], [[BASE1]] : {{.*}}) if ([[COND0]], [[COND1]])
+//   CHECK-NOT:   retain
+//  CHECK-NEXT:   return
+
+// TODO: Instead of deallocating the bbarg memrefs, a slightly better analysis
+// could do an unconditional deallocation on ALLOC0 and move it before the
+// test.copy (dealloc of ALLOC1 would remain after the copy)
+
+// -----
+
+// Test Case:
+//                                     bb0
+//                                    /   \
+// Initial pos of the 1st AllocOp -> bb1  bb2 <- Initial pos of the 2nd AllocOp
+//                                    \   /
+//                                     bb3
+// BufferDeallocation expected behavior: We need to introduce a copy for each
+// buffer since the buffers are passed to bb3. The both missing DeallocOps are
+// inserted in the respective block of the allocs. The copy is freed in the exit
+// block.
+
+func.func @moving_alloc_and_inserting_missing_dealloc(
+  %cond: i1,
+    %arg0: memref<2xf32>,
+    %arg1: memref<2xf32>) {
+  cf.cond_br %cond, ^bb1, ^bb2
+^bb1:
+  %0 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%arg0: memref<2xf32>) out(%0: memref<2xf32>)
+  cf.br ^exit(%0 : memref<2xf32>)
+^bb2:
+  %1 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%1: memref<2xf32>) out(%arg0: memref<2xf32>)
+  cf.br ^exit(%1 : memref<2xf32>)
+^exit(%arg2: memref<2xf32>):
+  test.copy(%arg2, %arg1) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+// CHECK-LABEL: func @moving_alloc_and_inserting_missing_dealloc
+//  CHECK-SAME: ([[ARG0:%.+]]: i1, [[ARG0:%.+]]: memref<2xf32>, [[ARG0:%.+]]: memref<2xf32>)
+//       CHECK: ^bb1:
+//       CHECK:   [[ALLOC0:%.+]] = memref.alloc()
+//  CHECK-NEXT:   test.buffer_based
+//  CHECK-NEXT:   cf.br ^bb3([[ALLOC0]], %true
+//       CHECK: ^bb2:
+//       CHECK:   [[ALLOC1:%.+]] = memref.alloc()
+//  CHECK-NEXT:   test.buffer_based
+//  CHECK-NEXT:   cf.br ^bb3([[ALLOC1]], %true
+//       CHECK: ^bb3([[A0:%.+]]: memref<2xf32>, [[COND0:%.+]]: i1):
+//       CHECK:   test.copy
+//  CHECK-NEXT:   [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[A0]]
+//  CHECK-NEXT:   bufferization.dealloc ([[BASE]] : {{.*}}) if ([[COND0]])
+//  CHECK-NEXT:   return
+
+// -----
+
+func.func @select_aliases(%arg0: index, %arg1: memref<?xi8>, %arg2: i1) {
+  %0 = memref.alloc(%arg0) : memref<?xi8>
+  %1 = memref.alloc(%arg0) : memref<?xi8>
+  %2 = arith.select %arg2, %0, %1 : memref<?xi8>
+  test.copy(%2, %arg1) : (memref<?xi8>, memref<?xi8>)
+  return
+}
+
+// CHECK-LABEL: func @select_aliases
+// CHECK: [[ALLOC0:%.+]] = memref.alloc(
+// CHECK: [[ALLOC1:%.+]] = memref.alloc(
+// CHECK: arith.select
+// CHECK: test.copy
+// CHECK: bufferization.dealloc ([[ALLOC0]] : {{.*}}) if (%true
+// CHECK-NOT: retain
+// CHECK: bufferization.dealloc ([[ALLOC1]] : {{.*}}) if (%true
+// CHECK-NOT: retain
+
+// -----
+
+func.func @select_aliases_not_same_ownership(%arg0: index, %arg1: memref<?xi8>, %arg2: i1) {
+  %0 = memref.alloc(%arg0) : memref<?xi8>
+  %1 = memref.alloca(%arg0) : memref<?xi8>
+  %2 = arith.select %arg2, %0, %1 : memref<?xi8>
+  cf.br ^bb1(%2 : memref<?xi8>)
+^bb1(%arg3: memref<?xi8>):
+  test.copy(%arg3, %arg1) : (memref<?xi8>, memref<?xi8>)
+  return
+}
+
+// CHECK-LABEL: func @select_aliases_not_same_ownership
+// CHECK: ([[ARG0:%.+]]: index, [[ARG1:%.+]]: memref<?xi8>, [[ARG2:%.+]]: i1)
+// CHECK: [[ALLOC0:%.+]] = memref.alloc(
+// CHECK: [[ALLOC1:%.+]] = memref.alloca(
+// CHECK: [[SELECT:%.+]] = arith.select
+// CHECK: [[OWN:%.+]] = bufferization.dealloc ([[ALLOC0]] :{{.*}}) if (%true{{[0-9_]*}}) retain ([[SELECT]] :
+// CHECK: cf.br ^bb1([[SELECT]], [[OWN]] :
+// CHECK: ^bb1([[A0:%.+]]: memref<?xi8>, [[COND:%.+]]: i1)
+// CHECK: test.copy
+// CHECK: [[BASE0:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[A0]]
+// CHECK: bufferization.dealloc ([[BASE0]] : {{.*}}) if ([[COND]])
+// CHECK-NOT: retain
+
+// -----
+
+func.func @select_captured_in_next_block(%arg0: index, %arg1: memref<?xi8>, %arg2: i1, %arg3: i1) {
+  %0 = memref.alloc(%arg0) : memref<?xi8>
+  %1 = memref.alloca(%arg0) : memref<?xi8>
+  %2 = arith.select %arg2, %0, %1 : memref<?xi8>
+  cf.cond_br %arg3, ^bb1(%0 : memref<?xi8>), ^bb1(%arg1 : memref<?xi8>)
+^bb1(%arg4: memref<?xi8>):
+  test.copy(%arg4, %2) : (memref<?xi8>, memref<?xi8>)
+  return
+}
+
+// CHECK-LABEL: func @select_captured_in_next_block
+// CHECK: ([[ARG0:%.+]]: index, [[ARG1:%.+]]: memref<?xi8>, [[ARG2:%.+]]: i1, [[ARG3:%.+]]: i1)
+// CHECK: [[ALLOC0:%.+]] = memref.alloc(
+// CHECK: [[ALLOC1:%.+]] = memref.alloca(
+// CHECK: [[SELECT:%.+]] = arith.select
+// CHECK: [[OWN0:%.+]]:2 = bufferization.dealloc ([[ALLOC0]] :{{.*}}) if ([[ARG3]]) retain ([[ALLOC0]], [[SELECT]] :
+// CHECK: [[NOT_ARG3:%.+]] = arith.xori [[ARG3]], %true
+// CHECK: [[OWN1:%.+]] = bufferization.dealloc ([[ALLOC0]] :{{.*}}) if ([[NOT_ARG3]]) retain ([[SELECT]] :
+// CHECK: [[MERGED_OWN:%.+]] = arith.select [[ARG3]], [[OWN0]]#1, [[OWN1]]
+// CHECK: cf.cond_br{{.*}}^bb1([[ALLOC0]], [[OWN0]]#0 :{{.*}}), ^bb1([[ARG1]], %false
+// CHECK: ^bb1([[A0:%.+]]: memref<?xi8>, [[COND:%.+]]: i1)
+// CHECK: test.copy
+// CHECK: [[BASE0:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[SELECT]]
+// CHECK: [[BASE1:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[A0]]
+// CHECK: bufferization.dealloc ([[BASE0]], [[BASE1]] : {{.*}}) if ([[MERGED_OWN]], [[COND]])
+
+// There are two interesting parts here:
+// * The dealloc condition of %0 in the second block should be the corresponding
+// result of the dealloc operation of the first block, because %0 has unknown
+// ownership status and thus would other wise require a clone in the first
+// block.
+// * The dealloc of the first block must make sure that the branch condition and
+// respective retained values are handled correctly, i.e., only the ones for the
+// actual branch taken have to be retained.
+
+// -----
+
+func.func @blocks_not_preordered_by_dominance() {
+  cf.br ^bb1
+^bb2:
+  "test.memref_user"(%alloc) : (memref<2xi32>) -> ()
+  return
+^bb1:
+  %alloc = memref.alloc() : memref<2xi32>
+  cf.br ^bb2
+}
+
+// CHECK-LABEL: func @blocks_not_preordered_by_dominance
+//  CHECK-NEXT:   [[TRUE:%.+]] = arith.constant true
+//  CHECK-NEXT:   cf.br [[BB1:\^.+]]
+//  CHECK-NEXT: [[BB2:\^[a-zA-Z0-9_]+]]:
+//  CHECK-NEXT:   "test.memref_user"([[ALLOC:%[a-zA-Z0-9_]+]])
+//  CHECK-NEXT:   bufferization.dealloc ([[ALLOC]] : {{.*}}) if ([[TRUE]])
+//   CHECK-NOT: retain
+//  CHECK-NEXT:   return
+//  CHECK-NEXT: [[BB1]]:
+//  CHECK-NEXT:   [[ALLOC]] = memref.alloc()
+//  CHECK-NEXT:   cf.br [[BB2]]
+//  CHECK-NEXT: }
diff --git a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-callop-interface.mlir b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-callop-interface.mlir
new file mode 100644
index 000000000000000..67128fee3dfe0ab
--- /dev/null
+++ b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-callop-interface.mlir
@@ -0,0 +1,113 @@
+// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation=private-function-dynamic-ownership=false \
+// RUN:   -buffer-deallocation-simplification -split-input-file %s | FileCheck %s
+// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation=private-function-dynamic-ownership=true \
+// RUN:   --buffer-deallocation-simplification -split-input-file %s | FileCheck %s --check-prefix=CHECK-DYNAMIC
+
+func.func private @f(%arg0: memref<f64>) -> memref<f64> {
+  return %arg0 : memref<f64>
+}
+
+func.func @function_call() {
+  %alloc = memref.alloc() : memref<f64>
+  %alloc2 = memref.alloc() : memref<f64>
+  %ret = call @f(%alloc) : (memref<f64>) -> memref<f64>
+  test.copy(%ret, %alloc2) : (memref<f64>, memref<f64>)
+  return
+}
+
+// CHECK-LABEL: func @function_call()
+//       CHECK: [[ALLOC0:%.+]] = memref.alloc(
+//  CHECK-NEXT: [[ALLOC1:%.+]] = memref.alloc(
+//  CHECK-NEXT: [[RET:%.+]] = call @f([[ALLOC0]]) : (memref<f64>) -> memref<f64>
+//  CHECK-NEXT: test.copy
+//  CHECK-NEXT: [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[RET]]
+// COM: the following dealloc operation should be split into three since we can
+// COM: be sure that the memrefs will never alias according to the buffer
+// COM: deallocation ABI, however, the local alias analysis is not powerful
+// COM: enough to detect this yet.
+//  CHECK-NEXT: bufferization.dealloc ([[ALLOC0]], [[ALLOC1]], [[BASE]] :{{.*}}) if (%true{{[0-9_]*}}, %true{{[0-9_]*}}, %true{{[0-9_]*}})
+
+// CHECK-DYNAMIC-LABEL: func @function_call()
+//       CHECK-DYNAMIC: [[ALLOC0:%.+]] = memref.alloc(
+//  CHECK-DYNAMIC-NEXT: [[ALLOC1:%.+]] = memref.alloc(
+//  CHECK-DYNAMIC-NEXT: [[RET:%.+]]:2 = call @f([[ALLOC0]], %true{{[0-9_]*}}) : (memref<f64>, i1) -> (memref<f64>, i1)
+//  CHECK-DYNAMIC-NEXT: test.copy
+//  CHECK-DYNAMIC-NEXT: [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[RET]]#0
+//  CHECK-DYNAMIC-NEXT: bufferization.dealloc ([[ALLOC0]], [[ALLOC1]], [[BASE]] :{{.*}}) if (%true{{[0-9_]*}}, %true{{[0-9_]*}}, [[RET]]#1)
+
+// -----
+
+func.func @f(%arg0: memref<f64>) -> memref<f64> {
+  return %arg0 : memref<f64>
+}
+
+func.func @function_call_non_private() {
+  %alloc = memref.alloc() : memref<f64>
+  %alloc2 = memref.alloc() : memref<f64>
+  %ret = call @f(%alloc) : (memref<f64>) -> memref<f64>
+  test.copy(%ret, %alloc2) : (memref<f64>, memref<f64>)
+  return
+}
+
+// CHECK-LABEL: func @function_call_non_private
+//       CHECK: [[ALLOC0:%.+]] = memref.alloc(
+//       CHECK: [[ALLOC1:%.+]] = memref.alloc(
+//       CHECK: [[RET:%.+]] = call @f([[ALLOC0]]) : (memref<f64>) -> memref<f64>
+//  CHECK-NEXT: test.copy
+//  CHECK-NEXT: [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[RET]]
+//  CHECK-NEXT: bufferization.dealloc ([[ALLOC0]], [[ALLOC1]], [[BASE]] :{{.*}}) if (%true{{[0-9_]*}}, %true{{[0-9_]*}}, %true{{[0-9_]*}})
+//  CHECK-NEXT: return
+
+// CHECK-DYNAMIC-LABEL: func @function_call_non_private
+//       CHECK-DYNAMIC: [[ALLOC0:%.+]] = memref.alloc(
+//       CHECK-DYNAMIC: [[ALLOC1:%.+]] = memref.alloc(
+//       CHECK-DYNAMIC: [[RET:%.+]] = call @f([[ALLOC0]]) : (memref<f64>) -> memref<f64>
+//  CHECK-DYNAMIC-NEXT: test.copy
+//  CHECK-DYNAMIC-NEXT: [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[RET]]
+//  CHECK-DYNAMIC-NEXT: bufferization.dealloc ([[ALLOC0]], [[ALLOC1]], [[BASE]] :{{.*}}) if (%true{{[0-9_]*}}, %true{{[0-9_]*}}, %true{{[0-9_]*}})
+//  CHECK-DYNAMIC-NEXT: return
+
+// -----
+
+func.func private @f(%arg0: memref<f64>) -> memref<f64> {
+  return %arg0 : memref<f64>
+}
+
+func.func @function_call_requries_merged_ownership_mid_block(%arg0: i1) {
+  %alloc = memref.alloc() : memref<f64>
+  %alloc2 = memref.alloca() : memref<f64>
+  %0 = arith.select %arg0, %alloc, %alloc2 : memref<f64>
+  %ret = call @f(%0) : (memref<f64>) -> memref<f64>
+  test.copy(%ret, %alloc) : (memref<f64>, memref<f64>)
+  return
+}
+
+// CHECK-LABEL: func @function_call_requries_merged_ownership_mid_block
+//       CHECK:   [[ALLOC0:%.+]] = memref.alloc(
+//  CHECK-NEXT:   [[ALLOC1:%.+]] = memref.alloca(
+//  CHECK-NEXT:   [[SELECT:%.+]] = arith.select{{.*}}[[ALLOC0]], [[ALLOC1]]
+//  CHECK-NEXT:   [[RET:%.+]] = call @f([[SELECT]])
+//  CHECK-NEXT:   test.copy
+//  CHECK-NEXT:   [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[RET]]
+//  CHECK-NEXT:   bufferization.dealloc ([[ALLOC0]], [[BASE]] :
+//  CHECK-SAME:     if (%true{{[0-9_]*}}, %true{{[0-9_]*}})
+//   CHECK-NOT:     retain
+//  CHECK-NEXT:   return
+
+// CHECK-DYNAMIC-LABEL: func @function_call_requries_merged_ownership_mid_block
+//       CHECK-DYNAMIC:   [[ALLOC0:%.+]] = memref.alloc(
+//  CHECK-DYNAMIC-NEXT:   [[ALLOC1:%.+]] = memref.alloca(
+//  CHECK-DYNAMIC-NEXT:   [[SELECT:%.+]] = arith.select{{.*}}[[ALLOC0]], [[ALLOC1]]
+//  CHECK-DYNAMIC-NEXT:   [[CLONE:%.+]] = bufferization.clone [[SELECT]]
+//  CHECK-DYNAMIC-NEXT:   [[RET:%.+]]:2 = call @f([[CLONE]], %true{{[0-9_]*}})
+//  CHECK-DYNAMIC-NEXT:   test.copy
+//  CHECK-DYNAMIC-NEXT:   [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[RET]]#0
+//  CHECK-DYNAMIC-NEXT:   bufferization.dealloc ([[ALLOC0]], [[CLONE]], [[BASE]] :
+//  CHECK-DYNAMIC-SAME:     if (%true{{[0-9_]*}}, %true{{[0-9_]*}}, [[RET]]#1)
+//   CHECK-DYNAMIC-NOT:     retain
+//  CHECK-DYNAMIC-NEXT:   return
+
+// TODO: the inserted clone is not necessary, we just have to know which of the
+// two allocations was selected, either by checking aliasing of the result at
+// runtime or by extracting the select condition using an OpInterface or by
+// hardcoding the select op
diff --git a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-existing-deallocs.mlir b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-existing-deallocs.mlir
new file mode 100644
index 000000000000000..bf4eabd31a81241
--- /dev/null
+++ b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-existing-deallocs.mlir
@@ -0,0 +1,43 @@
+// RUN: mlir-opt -verify-diagnostics -expand-realloc=emit-deallocs=false -ownership-based-buffer-deallocation \
+// RUN:  --buffer-deallocation-simplification -split-input-file %s | FileCheck %s
+
+func.func @auto_dealloc() {
+  %c10 = arith.constant 10 : index
+  %c100 = arith.constant 100 : index
+  %alloc = memref.alloc(%c10) : memref<?xi32>
+  %realloc = memref.realloc %alloc(%c100) : memref<?xi32> to memref<?xi32>
+  "test.memref_user"(%realloc) : (memref<?xi32>) -> ()
+  return
+}
+
+// CHECK-LABEL: func @auto_dealloc
+//       CHECK:  [[ALLOC:%.*]] = memref.alloc(
+//   CHECK-NOT:  bufferization.dealloc
+//       CHECK:  [[V0:%.+]]:2 = scf.if
+//   CHECK-NOT:  bufferization.dealloc
+//       CHECK:  test.memref_user
+//  CHECK-NEXT:  [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//  CHECK-NEXT:  bufferization.dealloc ([[ALLOC]], [[BASE]] :{{.*}}) if (%true{{[0-9_]*}}, [[V0]]#1)
+//  CHECK-NEXT:  return
+
+// -----
+
+func.func @auto_dealloc_inside_nested_region(%arg0: memref<?xi32>, %arg1: i1) {
+  %c100 = arith.constant 100 : index
+  %0 = scf.if %arg1 -> memref<?xi32> {
+    %realloc = memref.realloc %arg0(%c100) : memref<?xi32> to memref<?xi32>
+    scf.yield %realloc : memref<?xi32>
+  } else {
+    scf.yield %arg0 : memref<?xi32>
+  }
+  "test.memref_user"(%0) : (memref<?xi32>) -> ()
+  return
+}
+
+// CHECK-LABEL: func @auto_dealloc_inside_nested_region
+//  CHECK-SAME: (%arg0: memref<?xi32>, %arg1: i1)
+//   CHECK-NOT: dealloc
+//       CHECK: "test.memref_user"([[V0:%.+]]#0)
+//  CHECK-NEXT: [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//  CHECK-NEXT: bufferization.dealloc ([[BASE]] : memref<i32>) if ([[V0]]#1)
+//  CHECK-NEXT: return
diff --git a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-function-boundaries.mlir b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-function-boundaries.mlir
new file mode 100644
index 000000000000000..44f3e20c5009309
--- /dev/null
+++ b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-function-boundaries.mlir
@@ -0,0 +1,131 @@
+// RUN: mlir-opt --allow-unregistered-dialect -verify-diagnostics -ownership-based-buffer-deallocation=private-function-dynamic-ownership=false \
+// RUN:  --buffer-deallocation-simplification -split-input-file %s | FileCheck %s
+// RUN: mlir-opt --allow-unregistered-dialect -verify-diagnostics -ownership-based-buffer-deallocation=private-function-dynamic-ownership=true \
+// RUN:  --buffer-deallocation-simplification -split-input-file %s | FileCheck %s --check-prefix=CHECK-DYNAMIC
+
+// Test Case: Existing AllocOp with no users.
+// BufferDeallocation expected behavior: It should insert a DeallocOp right
+// before ReturnOp.
+
+func.func private @emptyUsesValue(%arg0: memref<4xf32>) {
+  %0 = memref.alloc() : memref<4xf32>
+  "test.memref_user"(%0) : (memref<4xf32>) -> ()
+  return
+}
+
+// CHECK-LABEL: func private @emptyUsesValue(
+//       CHECK: [[ALLOC:%.*]] = memref.alloc()
+//       CHECK: bufferization.dealloc ([[ALLOC]] :
+//  CHECK-SAME:   if (%true{{[0-9_]*}}) 
+//   CHECK-NOT:   retain
+//  CHECK-NEXT: return
+
+// CHECK-DYNAMIC-LABEL: func private @emptyUsesValue(
+//  CHECK-DYNAMIC-SAME: [[ARG0:%.+]]: memref<4xf32>, [[ARG1:%.+]]: i1)
+//       CHECK-DYNAMIC: [[ALLOC:%.*]] = memref.alloc()
+//      CHECK-DYNAMIC: [[BASE:%[a-zA-Z0-9_]+]], {{.*}} = memref.extract_strided_metadata [[ARG0]]
+//  CHECK-DYNAMIC-NEXT: bufferization.dealloc ([[BASE]] :{{.*}}) if ([[ARG1]]) 
+//   CHECK-DYNAMIC-NOT:   retain
+//  CHECK-DYNAMIC-NEXT: bufferization.dealloc ([[ALLOC]] :{{.*}}) if (%true{{[0-9_]*}}) 
+//   CHECK-DYNAMIC-NOT:   retain
+//  CHECK-DYNAMIC-NEXT: return
+
+// -----
+
+func.func @emptyUsesValue(%arg0: memref<4xf32>) {
+  %0 = memref.alloc() : memref<4xf32>
+  "test.memref_user"(%0) : (memref<4xf32>) -> ()
+  return
+}
+
+// CHECK-LABEL: func @emptyUsesValue(
+
+// CHECK-DYNAMIC-LABEL: func @emptyUsesValue(
+//       CHECK-DYNAMIC: [[ALLOC:%.*]] = memref.alloc()
+//       CHECK-DYNAMIC: bufferization.dealloc ([[ALLOC]] :{{.*}}) if (%true{{[0-9_]*}}) 
+//   CHECK-DYNAMIC-NOT:   retain
+//  CHECK-DYNAMIC-NEXT: return
+
+// -----
+
+// Test Case: Dead operations in a single block.
+// BufferDeallocation expected behavior: It only inserts the two missing
+// DeallocOps after the last BufferBasedOp.
+
+func.func private @redundantOperations(%arg0: memref<2xf32>) {
+  %0 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%arg0: memref<2xf32>) out(%0: memref<2xf32>)
+  %1 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%0: memref<2xf32>) out(%1: memref<2xf32>)
+  return
+}
+
+// CHECK-LABEL: func private @redundantOperations
+//      CHECK: (%[[ARG0:.*]]: {{.*}})
+//      CHECK: %[[FIRST_ALLOC:.*]] = memref.alloc()
+// CHECK-NEXT: test.buffer_based
+//      CHECK: %[[SECOND_ALLOC:.*]] = memref.alloc()
+// CHECK-NEXT: test.buffer_based
+// CHECK-NEXT: bufferization.dealloc (%[[FIRST_ALLOC]] : {{.*}}) if (%true{{[0-9_]*}})
+// CHECK-NEXT: bufferization.dealloc (%[[SECOND_ALLOC]] : {{.*}}) if (%true{{[0-9_]*}})
+// CHECK-NEXT: return
+
+// CHECK-DYNAMIC-LABEL: func private @redundantOperations
+//      CHECK-DYNAMIC: (%[[ARG0:.*]]: memref{{.*}}, %[[ARG1:.*]]: i1)
+//      CHECK-DYNAMIC: %[[FIRST_ALLOC:.*]] = memref.alloc()
+// CHECK-DYNAMIC-NEXT: test.buffer_based
+//      CHECK-DYNAMIC: %[[SECOND_ALLOC:.*]] = memref.alloc()
+// CHECK-DYNAMIC-NEXT: test.buffer_based
+// CHECK-DYNAMIC-NEXT: %[[BASE:[a-zA-Z0-9_]+]], {{.*}} = memref.extract_strided_metadata %[[ARG0]]
+// CHECK-DYNAMIC-NEXT: bufferization.dealloc (%[[BASE]] : {{.*}}) if (%[[ARG1]])
+// CHECK-DYNAMIC-NEXT: bufferization.dealloc (%[[FIRST_ALLOC]] : {{.*}}) if (%true{{[0-9_]*}})
+// CHECK-DYNAMIC-NEXT: bufferization.dealloc (%[[SECOND_ALLOC]] : {{.*}}) if (%true{{[0-9_]*}})
+// CHECK-DYNAMIC-NEXT: return
+
+// -----
+
+// Test Case: buffer deallocation escaping
+// BufferDeallocation expected behavior: It must not dealloc %arg1 and %x
+// since they are operands of return operation and should escape from
+// deallocating. It should dealloc %y after CopyOp.
+
+func.func private @memref_in_function_results(
+  %arg0: memref<5xf32>,
+  %arg1: memref<10xf32>,
+  %arg2: memref<5xf32>) -> (memref<10xf32>, memref<15xf32>) {
+  %x = memref.alloc() : memref<15xf32>
+  %y = memref.alloc() : memref<5xf32>
+  test.buffer_based in(%arg0: memref<5xf32>) out(%y: memref<5xf32>)
+  test.copy(%y, %arg2) : (memref<5xf32>, memref<5xf32>)
+  return %arg1, %x : memref<10xf32>, memref<15xf32>
+}
+
+// CHECK-LABEL: func private @memref_in_function_results
+//       CHECK: (%[[ARG0:.*]]: memref<5xf32>, %[[ARG1:.*]]: memref<10xf32>,
+//  CHECK-SAME: %[[RESULT:.*]]: memref<5xf32>)
+//       CHECK: %[[X:.*]] = memref.alloc()
+//       CHECK: %[[Y:.*]] = memref.alloc()
+//       CHECK: test.copy
+//  CHECK-NEXT: %[[V0:.+]] = scf.if %false
+//  CHECK-NEXT:   scf.yield %[[ARG1]]
+//  CHECK-NEXT: } else {
+//  CHECK-NEXT:   %[[CLONE:.+]] = bufferization.clone %[[ARG1]]
+//  CHECK-NEXT:   scf.yield %[[CLONE]]
+//  CHECK-NEXT: }
+//       CHECK: bufferization.dealloc (%[[Y]] : {{.*}}) if (%true{{[0-9_]*}})
+//   CHECK-NOT: retain
+//       CHECK: return %[[V0]], %[[X]]
+
+// CHECK-DYNAMIC-LABEL: func private @memref_in_function_results
+//       CHECK-DYNAMIC: (%[[ARG0:.*]]: memref<5xf32>, %[[ARG1:.*]]: memref<10xf32>,
+//  CHECK-DYNAMIC-SAME: %[[RESULT:.*]]: memref<5xf32>, %[[ARG3:.*]]: i1, %[[ARG4:.*]]: i1, %[[ARG5:.*]]: i1)
+//       CHECK-DYNAMIC: %[[X:.*]] = memref.alloc()
+//       CHECK-DYNAMIC: %[[Y:.*]] = memref.alloc()
+//       CHECK-DYNAMIC: test.copy
+//       CHECK-DYNAMIC: %[[BASE0:[a-zA-Z0-9_]+]], {{.+}} = memref.extract_strided_metadata %[[ARG0]]
+//       CHECK-DYNAMIC: %[[BASE1:[a-zA-Z0-9_]+]], {{.+}} = memref.extract_strided_metadata %[[RESULT]]
+//       CHECK-DYNAMIC: bufferization.dealloc (%[[Y]] : {{.*}}) if (%true{{[0-9_]*}})
+//   CHECK-DYNAMIC-NOT: retain
+//       CHECK-DYNAMIC: [[OWN:%.+]] = bufferization.dealloc (%[[BASE0]], %[[BASE1]] : {{.*}}) if (%[[ARG3]], %[[ARG5]]) retain (%[[ARG1]] :
+//       CHECK-DYNAMIC: [[OR:%.+]] = arith.ori [[OWN]], %[[ARG4]]
+//       CHECK-DYNAMIC: return %[[ARG1]], %[[X]], [[OR]], %true
diff --git a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-memoryeffect-interface.mlir b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-memoryeffect-interface.mlir
new file mode 100644
index 000000000000000..460e37aa03059ff
--- /dev/null
+++ b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-memoryeffect-interface.mlir
@@ -0,0 +1,124 @@
+// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation \
+// RUN:   --buffer-deallocation-simplification -split-input-file %s | FileCheck %s
+// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation=private-function-dynamic-ownership=true -split-input-file %s > /dev/null
+
+// Test Case: Dead operations in a single block.
+// BufferDeallocation expected behavior: It only inserts the two missing
+// DeallocOps after the last BufferBasedOp.
+
+// CHECK-LABEL: func @redundantOperations
+func.func @redundantOperations(%arg0: memref<2xf32>) {
+  %0 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%arg0: memref<2xf32>) out(%0: memref<2xf32>)
+  %1 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%0: memref<2xf32>) out(%1: memref<2xf32>)
+  return
+}
+
+//      CHECK: (%[[ARG0:.*]]: {{.*}})
+//      CHECK: %[[FIRST_ALLOC:.*]] = memref.alloc()
+//  CHECK-NOT: bufferization.dealloc
+//      CHECK: test.buffer_based in(%[[ARG0]]{{.*}}out(%[[FIRST_ALLOC]]
+//  CHECK-NOT: bufferization.dealloc
+//      CHECK: %[[SECOND_ALLOC:.*]] = memref.alloc()
+//  CHECK-NOT: bufferization.dealloc
+//      CHECK: test.buffer_based in(%[[FIRST_ALLOC]]{{.*}}out(%[[SECOND_ALLOC]]
+//      CHECK: bufferization.dealloc (%[[FIRST_ALLOC]] :{{.*}}) if (%true{{[0-9_]*}})
+//      CHECK: bufferization.dealloc (%[[SECOND_ALLOC]] :{{.*}}) if (%true{{[0-9_]*}})
+// CHECK-NEXT: return
+
+// TODO: The dealloc could be split in two to avoid runtime aliasing checks
+// since we can be sure at compile time that they will never alias.
+
+// -----
+
+// CHECK-LABEL: func @allocaIsNotDeallocated
+func.func @allocaIsNotDeallocated(%arg0: memref<2xf32>) {
+  %0 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%arg0: memref<2xf32>) out(%0: memref<2xf32>)
+  %1 = memref.alloca() : memref<2xf32>
+  test.buffer_based in(%0: memref<2xf32>) out(%1: memref<2xf32>)
+  return
+}
+
+//      CHECK: (%[[ARG0:.*]]: {{.*}})
+//      CHECK: %[[FIRST_ALLOC:.*]] = memref.alloc()
+// CHECK-NEXT: test.buffer_based in(%[[ARG0]]{{.*}}out(%[[FIRST_ALLOC]]
+// CHECK-NEXT: %[[SECOND_ALLOC:.*]] = memref.alloca()
+// CHECK-NEXT: test.buffer_based in(%[[FIRST_ALLOC]]{{.*}}out(%[[SECOND_ALLOC]]
+//      CHECK: bufferization.dealloc (%[[FIRST_ALLOC]] :{{.*}}) if (%true{{[0-9_]*}})
+// CHECK-NEXT: return
+
+// -----
+
+// Test Case: Inserting missing DeallocOp in a single block.
+
+// CHECK-LABEL: func @inserting_missing_dealloc_simple
+func.func @inserting_missing_dealloc_simple(
+  %arg0 : memref<2xf32>,
+  %arg1: memref<2xf32>) {
+  %0 = memref.alloc() : memref<2xf32>
+  test.buffer_based in(%arg0: memref<2xf32>) out(%0: memref<2xf32>)
+  test.copy(%0, %arg1) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+//      CHECK: %[[ALLOC0:.*]] = memref.alloc()
+//      CHECK: test.copy
+//      CHECK: bufferization.dealloc (%[[ALLOC0]] :{{.*}}) if (%true{{[0-9_]*}})
+
+// -----
+
+// Test Case: The ownership indicator is set to false for alloca
+
+// CHECK-LABEL: func @alloca_ownership_indicator_is_false
+func.func @alloca_ownership_indicator_is_false() {
+  %0 = memref.alloca() : memref<2xf32>
+  cf.br ^bb1(%0: memref<2xf32>)
+^bb1(%arg0 : memref<2xf32>):
+  return
+}
+
+//      CHECK:  %[[ALLOC0:.*]] = memref.alloca()
+// CHECK-NEXT:   cf.br ^bb1(%[[ALLOC0]], %false :
+// CHECK-NEXT: ^bb1([[A0:%.+]]: memref<2xf32>, [[COND0:%.+]]: i1):
+//      CHECK:   [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[A0]]
+//      CHECK:   bufferization.dealloc ([[BASE]] : {{.*}}) if ([[COND0]])
+// CHECK-NEXT:   return
+
+// -----
+
+func.func @dealloc_existing_clones(%arg0: memref<?x?xf64>, %arg1: memref<?x?xf64>) -> memref<?x?xf64> {
+  %0 = bufferization.clone %arg0 : memref<?x?xf64> to memref<?x?xf64>
+  %1 = bufferization.clone %arg1 : memref<?x?xf64> to memref<?x?xf64>
+  return %0 : memref<?x?xf64>
+}
+
+// CHECK-LABEL: func @dealloc_existing_clones
+//       CHECK: (%[[ARG0:.*]]: memref<?x?xf64>, %[[ARG1:.*]]: memref<?x?xf64>)
+//       CHECK: %[[RES0:.*]] = bufferization.clone %[[ARG0]]
+//       CHECK: %[[RES1:.*]] = bufferization.clone %[[ARG1]]
+//  CHECK-NEXT: bufferization.dealloc (%[[RES1]] :{{.*}}) if (%true{{[0-9_]*}})
+//   CHECK-NOT: retain
+//  CHECK-NEXT: return %[[RES0]]
+
+// TODO: The retain operand could be dropped to avoid runtime aliasing checks
+// since We can guarantee at compile-time that it will never alias with the
+// dealloc operand
+
+// -----
+
+memref.global "private" constant @__constant_4xf32 : memref<4xf32> = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00]>
+
+func.func @op_without_aliasing_and_allocation() -> memref<4xf32> {
+  %0 = memref.get_global @__constant_4xf32 : memref<4xf32>
+  return %0 : memref<4xf32>
+}
+
+// CHECK-LABEL: func @op_without_aliasing_and_allocation
+//       CHECK:   [[GLOBAL:%.+]] = memref.get_global @__constant_4xf32
+//       CHECK:   [[RES:%.+]] = scf.if %false
+//       CHECK:     scf.yield [[GLOBAL]] :
+//       CHECK:     [[CLONE:%.+]] = bufferization.clone [[GLOBAL]]
+//       CHECK:     scf.yield [[CLONE]] :
+//       CHECK:   return [[RES]] :
diff --git a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-region-branchop-interface.mlir b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-region-branchop-interface.mlir
new file mode 100644
index 000000000000000..d8090591c70513f
--- /dev/null
+++ b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-region-branchop-interface.mlir
@@ -0,0 +1,695 @@
+// RUN: mlir-opt -allow-unregistered-dialect -verify-diagnostics -ownership-based-buffer-deallocation \
+// RUN:  --buffer-deallocation-simplification -split-input-file %s | FileCheck %s
+// RUN: mlir-opt -allow-unregistered-dialect -verify-diagnostics -ownership-based-buffer-deallocation=private-function-dynamic-ownership=true -split-input-file %s > /dev/null
+
+// Test Case: Nested regions - This test defines a BufferBasedOp inside the
+// region of a RegionBufferBasedOp.
+// BufferDeallocation expected behavior: The AllocOp for the BufferBasedOp
+// should remain inside the region of the RegionBufferBasedOp and it should insert
+// the missing DeallocOp in the same region. The missing DeallocOp should be
+// inserted after CopyOp.
+
+func.func @nested_regions_and_cond_branch(
+  %arg0: i1,
+  %arg1: memref<2xf32>,
+  %arg2: memref<2xf32>) {
+  cf.cond_br %arg0, ^bb1, ^bb2
+^bb1:
+  cf.br ^bb3(%arg1 : memref<2xf32>)
+^bb2:
+  %0 = memref.alloc() : memref<2xf32>
+  test.region_buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>) {
+  ^bb0(%gen1_arg0: f32, %gen1_arg1: f32):
+    %1 = memref.alloc() : memref<2xf32>
+    test.buffer_based in(%arg1: memref<2xf32>) out(%1: memref<2xf32>)
+    %tmp1 = math.exp %gen1_arg0 : f32
+    test.region_yield %tmp1 : f32
+  }
+  cf.br ^bb3(%0 : memref<2xf32>)
+^bb3(%1: memref<2xf32>):
+  test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+// CHECK-LABEL: func @nested_regions_and_cond_branch
+//  CHECK-SAME: ([[ARG0:%.+]]: i1, [[ARG1:%.+]]: memref<2xf32>, [[ARG2:%.+]]: memref<2xf32>)
+//       CHECK: ^bb1:
+//   CHECK-NOT:   bufferization.clone
+//   CHECK-NOT:   bufferization.dealloc
+//       CHECK:   cf.br ^bb3([[ARG1]], %false
+//       CHECK: ^bb2:
+//       CHECK:   [[ALLOC0:%.+]] = memref.alloc()
+//       CHECK:   test.region_buffer_based
+//       CHECK:     [[ALLOC1:%.+]] = memref.alloc()
+//       CHECK:     test.buffer_based
+//       CHECK:     bufferization.dealloc ([[ALLOC1]] : memref<2xf32>) if (%true
+//  CHECK-NEXT:     test.region_yield
+//   CHECK-NOT:   bufferization.clone
+//   CHECK-NOT:   bufferization.dealloc
+//       CHECK:   cf.br ^bb3([[ALLOC0]], %true
+//       CHECK: ^bb3([[A0:%.+]]: memref<2xf32>, [[COND0:%.+]]: i1):
+//       CHECK:   test.copy
+//  CHECK-NEXT:   [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[A0]]
+//  CHECK-NEXT:   bufferization.dealloc ([[BASE]] : {{.*}}) if ([[COND0]])
+//       CHECK:   return
+
+// -----
+
+// Test Case: nested region control flow
+// The alloc %1 flows through both if branches until it is finally returned.
+// Hence, it does not require a specific dealloc operation. However, %3
+// requires a dealloc.
+
+func.func @nested_region_control_flow(
+  %arg0 : index,
+  %arg1 : index) -> memref<?x?xf32> {
+  %0 = arith.cmpi eq, %arg0, %arg1 : index
+  %1 = memref.alloc(%arg0, %arg0) : memref<?x?xf32>
+  %2 = scf.if %0 -> (memref<?x?xf32>) {
+    scf.yield %1 : memref<?x?xf32>
+  } else {
+    %3 = memref.alloc(%arg0, %arg1) : memref<?x?xf32>
+    "test.memref_user"(%3) : (memref<?x?xf32>) -> ()
+    scf.yield %1 : memref<?x?xf32>
+  }
+  return %2 : memref<?x?xf32>
+}
+
+// CHECK-LABEL: func @nested_region_control_flow
+//       CHECK:   [[ALLOC:%.+]] = memref.alloc(
+//       CHECK:   [[V0:%.+]]:2 = scf.if
+//       CHECK:     scf.yield [[ALLOC]], %false
+//       CHECK:     [[ALLOC1:%.+]] = memref.alloc(
+//       CHECK:     bufferization.dealloc ([[ALLOC1]] :{{.*}}) if (%true{{[0-9_]*}})
+//   CHECK-NOT: retain
+//       CHECK:     scf.yield [[ALLOC]], %false
+//       CHECK:   [[V1:%.+]] = scf.if [[V0]]#1
+//       CHECK:     scf.yield [[V0]]#0
+//       CHECK:     [[CLONE:%.+]] = bufferization.clone [[V0]]#0
+//       CHECK:     scf.yield [[CLONE]]
+//       CHECK:   [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//       CHECK:   bufferization.dealloc ([[ALLOC]], [[BASE]] : {{.*}}) if (%true{{[0-9_]*}}, [[V0]]#1) retain ([[V1]] :
+//       CHECK:   return [[V1]]
+
+// -----
+
+// Test Case: nested region control flow with a nested buffer allocation in a
+// divergent branch.
+// Buffer deallocation places a copy for both  %1 and %3, since they are
+// returned in the end.
+
+func.func @nested_region_control_flow_div(
+  %arg0 : index,
+  %arg1 : index) -> memref<?x?xf32> {
+  %0 = arith.cmpi eq, %arg0, %arg1 : index
+  %1 = memref.alloc(%arg0, %arg0) : memref<?x?xf32>
+  %2 = scf.if %0 -> (memref<?x?xf32>) {
+    scf.yield %1 : memref<?x?xf32>
+  } else {
+    %3 = memref.alloc(%arg0, %arg1) : memref<?x?xf32>
+    scf.yield %3 : memref<?x?xf32>
+  }
+  return %2 : memref<?x?xf32>
+}
+
+// CHECK-LABEL: func @nested_region_control_flow_div
+//       CHECK:   [[ALLOC:%.+]] = memref.alloc(
+//       CHECK:   [[V0:%.+]]:2 = scf.if
+//       CHECK:     scf.yield [[ALLOC]], %false
+//       CHECK:     [[ALLOC1:%.+]] = memref.alloc(
+//       CHECK:     scf.yield [[ALLOC1]], %true
+//       CHECK:   [[V1:%.+]] = scf.if [[V0]]#1
+//       CHECK:     scf.yield [[V0]]#0
+//       CHECK:     [[CLONE:%.+]] = bufferization.clone [[V0]]#0
+//       CHECK:     scf.yield [[CLONE]]
+//       CHECK:   [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//       CHECK:   bufferization.dealloc ([[ALLOC]], [[BASE]] :{{.*}}) if (%true{{[0-9_]*}}, [[V0]]#1) retain ([[V1]] :
+//       CHECK:   return [[V1]]
+
+// -----
+
+// Test Case: nested region control flow within a region interface.
+// No copies are required in this case since the allocation finally escapes
+// the method.
+
+func.func @inner_region_control_flow(%arg0 : index) -> memref<?x?xf32> {
+  %0 = memref.alloc(%arg0, %arg0) : memref<?x?xf32>
+  %1 = test.region_if %0 : memref<?x?xf32> -> (memref<?x?xf32>) then {
+    ^bb0(%arg1 : memref<?x?xf32>):
+      test.region_if_yield %arg1 : memref<?x?xf32>
+  } else {
+    ^bb0(%arg1 : memref<?x?xf32>):
+      test.region_if_yield %arg1 : memref<?x?xf32>
+  } join {
+    ^bb0(%arg1 : memref<?x?xf32>):
+      test.region_if_yield %arg1 : memref<?x?xf32>
+  }
+  return %1 : memref<?x?xf32>
+}
+
+// CHECK-LABEL: func.func @inner_region_control_flow
+//       CHECK:   [[ALLOC:%.+]] = memref.alloc(
+//       CHECK:   [[V0:%.+]]:2 = test.region_if [[ALLOC]], %false
+//       CHECK:   ^bb0([[ARG1:%.+]]: memref<?x?xf32>, [[ARG2:%.+]]: i1):
+//       CHECK:     test.region_if_yield [[ARG1]], [[ARG2]]
+//       CHECK:   ^bb0([[ARG1:%.+]]: memref<?x?xf32>, [[ARG2:%.+]]: i1):
+//       CHECK:     test.region_if_yield [[ARG1]], [[ARG2]]
+//       CHECK:   ^bb0([[ARG1:%.+]]: memref<?x?xf32>, [[ARG2:%.+]]: i1):
+//       CHECK:     test.region_if_yield [[ARG1]], [[ARG2]]
+//       CHECK:   [[V1:%.+]] = scf.if [[V0]]#1
+//       CHECK:     scf.yield [[V0]]#0
+//       CHECK:     [[CLONE:%.+]] = bufferization.clone [[V0]]#0
+//       CHECK:     scf.yield [[CLONE]]
+//       CHECK:   [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//       CHECK:   bufferization.dealloc ([[ALLOC]], [[BASE]] :{{.*}}) if (%true{{[0-9_]*}}, [[V0]]#1) retain ([[V1]] :
+//       CHECK:   return [[V1]]
+
+// -----
+
+func.func @nestedRegionsAndCondBranchAlloca(
+  %arg0: i1,
+  %arg1: memref<2xf32>,
+  %arg2: memref<2xf32>) {
+  cf.cond_br %arg0, ^bb1, ^bb2
+^bb1:
+  cf.br ^bb3(%arg1 : memref<2xf32>)
+^bb2:
+  %0 = memref.alloc() : memref<2xf32>
+  test.region_buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>) {
+  ^bb0(%gen1_arg0: f32, %gen1_arg1: f32):
+    %1 = memref.alloca() : memref<2xf32>
+    test.buffer_based in(%arg1: memref<2xf32>) out(%1: memref<2xf32>)
+    %tmp1 = math.exp %gen1_arg0 : f32
+    test.region_yield %tmp1 : f32
+  }
+  cf.br ^bb3(%0 : memref<2xf32>)
+^bb3(%1: memref<2xf32>):
+  test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+// CHECK-LABEL: func @nestedRegionsAndCondBranchAlloca
+//  CHECK-SAME: ([[ARG0:%.+]]: i1, [[ARG1:%.+]]: memref<2xf32>, [[ARG2:%.+]]: memref<2xf32>)
+//       CHECK: ^bb1:
+//       CHECK:   cf.br ^bb3([[ARG1]], %false
+//       CHECK: ^bb2:
+//       CHECK:   [[ALLOC:%.+]] = memref.alloc()
+//       CHECK:   test.region_buffer_based
+//       CHECK:     memref.alloca()
+//       CHECK:     test.buffer_based
+//   CHECK-NOT:     bufferization.dealloc
+//   CHECK-NOT:     bufferization.clone
+//       CHECK:     test.region_yield
+//       CHECK:   }
+//       CHECK:   cf.br ^bb3([[ALLOC]], %true
+//       CHECK: ^bb3([[A0:%.+]]: memref<2xf32>, [[COND:%.+]]: i1):
+//       CHECK:   test.copy
+//       CHECK:   [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[A0]]
+//       CHECK:   bufferization.dealloc ([[BASE]] :{{.*}}) if ([[COND]])
+
+// -----
+
+func.func @nestedRegionControlFlowAlloca(
+  %arg0 : index, %arg1 : index, %arg2: f32) -> memref<?x?xf32> {
+  %0 = arith.cmpi eq, %arg0, %arg1 : index
+  %1 = memref.alloc(%arg0, %arg0) : memref<?x?xf32>
+  %2 = scf.if %0 -> (memref<?x?xf32>) {
+    scf.yield %1 : memref<?x?xf32>
+  } else {
+    %3 = memref.alloca(%arg0, %arg1) : memref<?x?xf32>
+    %c0 = arith.constant 0 : index
+    memref.store %arg2, %3[%c0, %c0] : memref<?x?xf32>
+    scf.yield %1 : memref<?x?xf32>
+  }
+  return %2 : memref<?x?xf32>
+}
+
+// CHECK-LABEL: func @nestedRegionControlFlowAlloca
+//       CHECK: [[ALLOC:%.+]] = memref.alloc(
+//       CHECK: [[V0:%.+]]:2 = scf.if
+//       CHECK:   scf.yield [[ALLOC]], %false
+//       CHECK:   memref.alloca(
+//       CHECK:   scf.yield [[ALLOC]], %false
+//       CHECK: [[V1:%.+]] = scf.if [[V0]]#1
+//       CHECK:   scf.yield [[V0]]#0
+//       CHECK:   [[CLONE:%.+]] = bufferization.clone [[V0]]#0
+//       CHECK:   scf.yield [[CLONE]]
+//       CHECK: [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//       CHECK: bufferization.dealloc ([[ALLOC]], [[BASE]] :{{.*}}) if (%true{{[0-9_]*}}, [[V0]]#1) retain ([[V1]] :
+//       CHECK: return [[V1]]
+
+// -----
+
+// Test Case: structured control-flow loop using a nested alloc.
+// The iteration argument %iterBuf has to be freed before yielding %3 to avoid
+// memory leaks.
+
+func.func @loop_alloc(
+  %lb: index,
+  %ub: index,
+  %step: index,
+  %buf: memref<2xf32>,
+  %res: memref<2xf32>) {
+  %0 = memref.alloc() : memref<2xf32>
+  "test.memref_user"(%0) : (memref<2xf32>) -> ()
+  %1 = scf.for %i = %lb to %ub step %step
+    iter_args(%iterBuf = %buf) -> memref<2xf32> {
+    %2 = arith.cmpi eq, %i, %ub : index
+    %3 = memref.alloc() : memref<2xf32>
+    scf.yield %3 : memref<2xf32>
+  }
+  test.copy(%1, %res) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+// CHECK-LABEL: func @loop_alloc
+//  CHECK-SAME: ([[ARG0:%.+]]: index, [[ARG1:%.+]]: index, [[ARG2:%.+]]: index, [[ARG3:%.+]]: memref<2xf32>, [[ARG4:%.+]]: memref<2xf32>)
+//       CHECK: [[ALLOC:%.+]] = memref.alloc()
+//       CHECK: [[V0:%.+]]:2 = scf.for {{.*}} iter_args([[ARG6:%.+]] = [[ARG3]], [[ARG7:%.+]] = %false
+//       CHECK:   [[ALLOC1:%.+]] = memref.alloc()
+//       CHECK:   [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[ARG6]]
+//       CHECK:   bufferization.dealloc ([[BASE]] :{{.*}}) if ([[ARG7]]) retain ([[ALLOC1]] :
+//       CHECK:   scf.yield [[ALLOC1]], %true
+//       CHECK: test.copy
+//       CHECK: [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//       CHECK: bufferization.dealloc ([[ALLOC]] :{{.*}}) if (%true
+//   CHECK-NOT: retain
+//       CHECK: bufferization.dealloc ([[BASE]] :{{.*}}) if ([[V0]]#1)
+//   CHECK-NOT: retain
+
+// -----
+
+// Test Case: structured control-flow loop with a nested if operation.
+// The loop yields buffers that have been defined outside of the loop and the
+// backedges only use the iteration arguments (or one of its aliases).
+// Therefore, we do not have to (and are not allowed to) free any buffers
+// that are passed via the backedges.
+
+func.func @loop_nested_if_no_alloc(
+  %lb: index,
+  %ub: index,
+  %step: index,
+  %buf: memref<2xf32>,
+  %res: memref<2xf32>) {
+  %0 = memref.alloc() : memref<2xf32>
+  %1 = scf.for %i = %lb to %ub step %step
+    iter_args(%iterBuf = %buf) -> memref<2xf32> {
+    %2 = arith.cmpi eq, %i, %ub : index
+    %3 = scf.if %2 -> (memref<2xf32>) {
+      scf.yield %0 : memref<2xf32>
+    } else {
+      scf.yield %iterBuf : memref<2xf32>
+    }
+    scf.yield %3 : memref<2xf32>
+  }
+  test.copy(%1, %res) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+// CHECK-LABEL: func @loop_nested_if_no_alloc
+//  CHECK-SAME: ({{.*}}, [[ARG3:%.+]]: memref<2xf32>, [[ARG4:%.+]]: memref<2xf32>)
+//       CHECK: [[ALLOC:%.+]] = memref.alloc()
+//       CHECK: [[V0:%.+]]:2 = scf.for {{.*}} iter_args([[ARG6:%.+]] = [[ARG3]], [[ARG7:%.+]] = %false
+//       CHECK:   [[V1:%.+]]:2 = scf.if
+//       CHECK:     scf.yield [[ALLOC]], %false
+//       CHECK:     scf.yield [[ARG6]], %false
+//       CHECK:   [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[ARG6]]
+//       CHECK:   [[OWN:%.+]] = bufferization.dealloc ([[BASE]] :{{.*}}) if ([[ARG7]]) retain ([[V1]]#0 :
+//       CHECK:   [[OWN_AGG:%.+]] = arith.ori [[OWN]], [[V1]]#1
+//       CHECK:   scf.yield [[V1]]#0, [[OWN_AGG]]
+//       CHECK: test.copy
+//       CHECK: [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//       CHECK: bufferization.dealloc ([[ALLOC]], [[BASE]] :{{.*}}) if (%true{{[0-9_]*}}, [[V0]]#1)
+
+// TODO: we know statically that the inner dealloc will never deallocate
+//       anything, i.e., we can optimize it away
+
+// -----
+
+// Test Case: structured control-flow loop with a nested if operation using
+// a deeply nested buffer allocation.
+
+func.func @loop_nested_if_alloc(
+  %lb: index,
+  %ub: index,
+  %step: index,
+  %buf: memref<2xf32>) -> memref<2xf32> {
+  %0 = memref.alloc() : memref<2xf32>
+  %1 = scf.for %i = %lb to %ub step %step
+    iter_args(%iterBuf = %buf) -> memref<2xf32> {
+    %2 = arith.cmpi eq, %i, %ub : index
+    %3 = scf.if %2 -> (memref<2xf32>) {
+      %4 = memref.alloc() : memref<2xf32>
+      scf.yield %4 : memref<2xf32>
+    } else {
+      scf.yield %0 : memref<2xf32>
+    }
+    scf.yield %3 : memref<2xf32>
+  }
+  return %1 : memref<2xf32>
+}
+
+// CHECK-LABEL: func @loop_nested_if_alloc
+//  CHECK-SAME: ({{.*}}, [[ARG3:%.+]]: memref<2xf32>)
+//       CHECK: [[ALLOC:%.+]] = memref.alloc()
+//       CHECK: [[V0:%.+]]:2 = scf.for {{.*}} iter_args([[ARG5:%.+]] = [[ARG3]], [[ARG6:%.+]] = %false
+//       CHECK:   [[V1:%.+]]:2 = scf.if
+//       CHECK:     [[ALLOC1:%.+]] = memref.alloc()
+//       CHECK:     scf.yield [[ALLOC1]], %true
+//       CHECK:     scf.yield [[ALLOC]], %false
+//       CHECK:   [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[ARG5]]
+//       CHECK:   [[OWN:%.+]] = bufferization.dealloc ([[BASE]] :{{.*}}) if ([[ARG6]]) retain ([[V1]]#0 :
+//       CHECK:   [[OWN_AGG:%.+]] = arith.ori [[OWN]], [[V1]]#1
+//       CHECK:   scf.yield [[V1]]#0, [[OWN_AGG]]
+//       CHECK: }
+//       CHECK: [[V2:%.+]] = scf.if [[V0]]#1
+//       CHECK:   scf.yield [[V0]]#0
+//       CHECK:   [[CLONE:%.+]] = bufferization.clone [[V0]]#0
+//       CHECK:   scf.yield [[CLONE]]
+//       CHECK: [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//       CHECK: bufferization.dealloc ([[ALLOC]], [[BASE]] :{{.*}}) if (%true{{[0-9_]*}}, [[V0]]#1) retain ([[V2]] :
+//       CHECK: return [[V2]]
+
+// -----
+
+// Test Case: several nested structured control-flow loops with a deeply nested
+// buffer allocation inside an if operation.
+
+func.func @loop_nested_alloc(
+  %lb: index,
+  %ub: index,
+  %step: index,
+  %buf: memref<2xf32>,
+  %res: memref<2xf32>) {
+  %0 = memref.alloc() : memref<2xf32>
+  "test.memref_user"(%0) : (memref<2xf32>) -> ()
+  %1 = scf.for %i = %lb to %ub step %step
+    iter_args(%iterBuf = %buf) -> memref<2xf32> {
+    %2 = scf.for %i2 = %lb to %ub step %step
+      iter_args(%iterBuf2 = %iterBuf) -> memref<2xf32> {
+      %3 = scf.for %i3 = %lb to %ub step %step
+        iter_args(%iterBuf3 = %iterBuf2) -> memref<2xf32> {
+        %4 = memref.alloc() : memref<2xf32>
+        "test.memref_user"(%4) : (memref<2xf32>) -> ()
+        %5 = arith.cmpi eq, %i, %ub : index
+        %6 = scf.if %5 -> (memref<2xf32>) {
+          %7 = memref.alloc() : memref<2xf32>
+          scf.yield %7 : memref<2xf32>
+        } else {
+          scf.yield %iterBuf3 : memref<2xf32>
+        }
+        scf.yield %6 : memref<2xf32>
+      }
+      scf.yield %3 : memref<2xf32>
+    }
+    scf.yield %2 : memref<2xf32>
+  }
+  test.copy(%1, %res) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+// CHECK-LABEL: func @loop_nested_alloc
+//       CHECK: ({{.*}}, [[ARG3:%.+]]: memref<2xf32>, {{.*}}: memref<2xf32>)
+//       CHECK: [[ALLOC:%.+]] = memref.alloc()
+//       CHECK: [[V0:%.+]]:2 = scf.for {{.*}} iter_args([[ARG6:%.+]] = [[ARG3]], [[ARG7:%.+]] = %false
+//       CHECK:   [[V1:%.+]]:2 = scf.for {{.*}} iter_args([[ARG9:%.+]] = [[ARG6]], [[ARG10:%.+]] = %false
+//       CHECK:     [[V2:%.+]]:2 = scf.for {{.*}} iter_args([[ARG12:%.+]] = [[ARG9]], [[ARG13:%.+]] = %false
+//       CHECK:       [[ALLOC1:%.+]] = memref.alloc()
+//       CHECK:       [[V3:%.+]]:2 = scf.if
+//       CHECK:         [[ALLOC2:%.+]] = memref.alloc()
+//       CHECK:         scf.yield [[ALLOC2]], %true
+//       CHECK:       } else {
+//       CHECK:         scf.yield [[ARG12]], %false
+//       CHECK:       }
+//       CHECK:       [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[ARG12]]
+//       CHECK:       [[OWN:%.+]] = bufferization.dealloc ([[BASE]] :{{.*}}) if ([[ARG13]]) retain ([[V3]]#0 :
+//       CHECK:       bufferization.dealloc ([[ALLOC1]] :{{.*}}) if (%true{{[0-9_]*}})
+//   CHECK-NOT: retain
+//       CHECK:       [[OWN_AGG:%.+]] = arith.ori [[OWN]], [[V3]]#1
+//       CHECK:       scf.yield [[V3]]#0, [[OWN_AGG]]
+//       CHECK:     }
+//       CHECK:     [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[ARG9]]
+//       CHECK:     [[OWN:%.+]] = bufferization.dealloc ([[BASE]] :{{.*}}) if ([[ARG10]]) retain ([[V2]]#0 :
+//       CHECK:     [[OWN_AGG:%.+]] = arith.ori [[OWN]], [[V2]]#1
+//       CHECK:     scf.yield [[V2]]#0, [[OWN_AGG]]
+//       CHECK:   }
+//       CHECK:   [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[ARG6]]
+//       CHECK:   [[OWN:%.+]] = bufferization.dealloc ([[BASE]] :{{.*}}) if ([[ARG7]]) retain ([[V1]]#0 :
+//       CHECK:   [[OWN_AGG:%.+]] = arith.ori [[OWN]], [[V1]]#1
+//       CHECK:   scf.yield [[V1]]#0, [[OWN_AGG]]
+//       CHECK: }
+//       CHECK: test.copy
+//       CHECK: [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//       CHECK: bufferization.dealloc ([[ALLOC]] :{{.*}}) if (%true
+//       CHECK: bufferization.dealloc ([[BASE]] :{{.*}}) if ([[V0]]#1)
+
+// TODO: all the retain operands could be removed by doing some more thorough analysis
+
+// -----
+
+func.func @affine_loop() -> f32 {
+  %buffer = memref.alloc() : memref<1024xf32>
+  %sum_init_0 = arith.constant 0.0 : f32
+  %res = affine.for %i = 0 to 10 step 2 iter_args(%sum_iter = %sum_init_0) -> f32 {
+    %t = affine.load %buffer[%i] : memref<1024xf32>
+    %sum_next = arith.addf %sum_iter, %t : f32
+    affine.yield %sum_next : f32
+  }
+  return %res : f32
+}
+
+// CHECK-LABEL: func @affine_loop
+//       CHECK: [[ALLOC:%.+]] = memref.alloc()
+//       CHECK: affine.for {{.*}} iter_args(%arg1 = %cst)
+//       CHECK:   affine.yield
+//       CHECK: bufferization.dealloc ([[ALLOC]] :{{.*}}) if (%true
+
+// -----
+
+func.func @assumingOp(
+  %arg0: !shape.witness,
+  %arg2: memref<2xf32>,
+  %arg3: memref<2xf32>) {
+  // Confirm the alloc will be dealloc'ed in the block.
+  %1 = shape.assuming %arg0 -> memref<2xf32> {
+    %0 = memref.alloc() : memref<2xf32>
+    "test.memref_user"(%0) : (memref<2xf32>) -> ()
+    shape.assuming_yield %arg2 : memref<2xf32>
+  }
+  // Confirm the alloc will be returned and dealloc'ed after its use.
+  %3 = shape.assuming %arg0 -> memref<2xf32> {
+    %2 = memref.alloc() : memref<2xf32>
+    shape.assuming_yield %2 : memref<2xf32>
+  }
+  test.copy(%3, %arg3) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+// CHECK-LABEL: func @assumingOp
+//       CHECK: ({{.*}}, [[ARG1:%.+]]: memref<2xf32>, {{.*}}: memref<2xf32>)
+//       CHECK: [[V0:%.+]]:2 = shape.assuming
+//       CHECK:   [[ALLOC:%.+]] = memref.alloc()
+//       CHECK:   bufferization.dealloc ([[ALLOC]] :{{.*}}) if (%true{{[0-9_]*}})
+//   CHECK-NOT: retain
+//       CHECK:   shape.assuming_yield [[ARG1]], %false
+//       CHECK: }
+//       CHECK: [[V1:%.+]]:2 = shape.assuming
+//       CHECK:   [[ALLOC:%.+]] = memref.alloc()
+//       CHECK:   shape.assuming_yield [[ALLOC]], %true
+//       CHECK: }
+//       CHECK: test.copy
+//       CHECK: [[BASE0:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//       CHECK: [[BASE1:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V1]]#0
+//       CHECK: bufferization.dealloc ([[BASE0]] :{{.*}}) if ([[V0]]#1)
+//   CHECK-NOT: retain
+//       CHECK: bufferization.dealloc ([[BASE1]] :{{.*}}) if ([[V1]]#1)
+//   CHECK-NOT: retain
+//       CHECK: return
+
+// -----
+
+// Test Case: The op "test.bar" does not implement the RegionBranchOpInterface.
+// This is only allowed in buffer deallocation because the operation's region
+// does not deal with any MemRef values.
+
+func.func @noRegionBranchOpInterface() {
+  %0 = "test.bar"() ({
+    %1 = "test.bar"() ({
+      "test.yield"() : () -> ()
+    }) : () -> (i32)
+    "test.yield"() : () -> ()
+  }) : () -> (i32)
+  "test.terminator"() : () -> ()
+}
+
+// -----
+
+// Test Case: The op "test.bar" does not implement the RegionBranchOpInterface.
+// This is not allowed in buffer deallocation.
+
+func.func @noRegionBranchOpInterface() {
+  // expected-error at +1 {{All operations with attached regions need to implement the RegionBranchOpInterface.}}
+  %0 = "test.bar"() ({
+    %1 = "test.bar"() ({
+      %2 = "test.get_memref"() : () -> memref<2xi32>
+      "test.yield"(%2) : (memref<2xi32>) -> ()
+    }) : () -> (memref<2xi32>)
+    "test.yield"() : () -> ()
+  }) : () -> (i32)
+  "test.terminator"() : () -> ()
+}
+
+// -----
+
+func.func @while_two_arg(%arg0: index) {
+  %a = memref.alloc(%arg0) : memref<?xf32>
+  scf.while (%arg1 = %a, %arg2 = %a) : (memref<?xf32>, memref<?xf32>) -> (memref<?xf32>, memref<?xf32>) {
+    %0 = "test.make_condition"() : () -> i1
+    scf.condition(%0) %arg1, %arg2 : memref<?xf32>, memref<?xf32>
+  } do {
+  ^bb0(%arg1: memref<?xf32>, %arg2: memref<?xf32>):
+    %b = memref.alloc(%arg0) : memref<?xf32>
+    scf.yield %arg1, %b : memref<?xf32>, memref<?xf32>
+  }
+  return
+}
+
+// CHECK-LABEL: func @while_two_arg
+//       CHECK: [[ALLOC:%.+]] = memref.alloc(
+//       CHECK: [[V0:%.+]]:4 = scf.while ({{.*}} = [[ALLOC]], {{.*}} = [[ALLOC]], {{.*}} = %false{{[0-9_]*}}, {{.*}} = %false{{[0-9_]*}})
+//       CHECK:   scf.condition
+//       CHECK: ^bb0([[ARG1:%.+]]: memref<?xf32>, [[ARG2:%.+]]: memref<?xf32>, [[ARG3:%.+]]: i1, [[ARG4:%.+]]: i1):
+//       CHECK:   [[ALLOC1:%.+]] = memref.alloc(
+//       CHECK:   [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[ARG2]]
+//       CHECK:   [[OWN:%.+]]:2 = bufferization.dealloc ([[BASE]] :{{.*}}) if ([[ARG4]]) retain ([[ARG1]], [[ALLOC1]] :
+//       CHECK:   [[OWN_AGG:%.+]] = arith.ori [[OWN]]#0, [[ARG3]]
+//       CHECK:   scf.yield [[ARG1]], [[ALLOC1]], [[OWN_AGG]], %true
+//       CHECK: [[BASE0:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//       CHECK: [[BASE1:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#1
+//       CHECK: bufferization.dealloc ([[ALLOC]], [[BASE0]], [[BASE1]] :{{.*}}) if (%true{{[0-9_]*}}, [[V0]]#2, [[V0]]#3)
+
+// -----
+
+func.func @while_three_arg(%arg0: index) {
+  %a = memref.alloc(%arg0) : memref<?xf32>
+  scf.while (%arg1 = %a, %arg2 = %a, %arg3 = %a) : (memref<?xf32>, memref<?xf32>, memref<?xf32>) -> (memref<?xf32>, memref<?xf32>, memref<?xf32>) {
+    %0 = "test.make_condition"() : () -> i1
+    scf.condition(%0) %arg1, %arg2, %arg3 : memref<?xf32>, memref<?xf32>, memref<?xf32>
+  } do {
+  ^bb0(%arg1: memref<?xf32>, %arg2: memref<?xf32>, %arg3: memref<?xf32>):
+    %b = memref.alloc(%arg0) : memref<?xf32>
+    %q = memref.alloc(%arg0) : memref<?xf32>
+    scf.yield %q, %b, %arg2: memref<?xf32>, memref<?xf32>, memref<?xf32>
+  }
+  return
+}
+
+// CHECK-LABEL: func @while_three_arg
+//       CHECK: [[ALLOC:%.+]] = memref.alloc(
+//       CHECK: [[V0:%.+]]:6 = scf.while ({{.*}} = [[ALLOC]], {{.*}} = [[ALLOC]], {{.*}} = [[ALLOC]], {{.*}} = %false{{[0-9_]*}}, {{.*}} = %false{{[0-9_]*}}, {{.*}} = %false
+//       CHECK:   scf.condition
+//       CHECK: ^bb0([[ARG1:%.+]]: memref<?xf32>, [[ARG2:%.+]]: memref<?xf32>, [[ARG3:%.+]]: memref<?xf32>, [[ARG4:%.+]]: i1, [[ARG5:%.+]]: i1, [[ARG6:%.+]]: i1):
+//       CHECK:   [[ALLOC1:%.+]] = memref.alloc(
+//       CHECK:   [[ALLOC2:%.+]] = memref.alloc(
+//       CHECK:   [[BASE0:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[ARG1]]
+//       CHECK:   [[BASE1:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[ARG2]]
+//       CHECK:   [[BASE2:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[ARG3]]
+//       CHECK:   [[OWN:%.+]]:3 = bufferization.dealloc ([[BASE0]], [[BASE1]], [[BASE2]], [[ALLOC1]] :{{.*}}) if ([[ARG4]], [[ARG5]], [[ARG6]], %true{{[0-9_]*}}) retain ([[ALLOC2]], [[ALLOC1]], [[ARG2]] :
+//       CHECK:   scf.yield [[ALLOC2]], [[ALLOC1]], [[ARG2]], %true{{[0-9_]*}}, %true{{[0-9_]*}}, [[OWN]]#2 :
+//       CHECK: }
+//       CHECK: [[BASE0:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//       CHECK: [[BASE1:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#1
+//       CHECK: [[BASE2:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#2
+//       CHECK: bufferization.dealloc ([[ALLOC]], [[BASE0]], [[BASE1]], [[BASE2]] :{{.*}}) if (%true{{[0-9_]*}}, [[V0]]#3, [[V0]]#4, [[V0]]#5)
+
+// TODO: better alias analysis could simplify the dealloc inside the body further
+
+// -----
+
+// Memref allocated in `then` region and passed back to the parent if op.
+#set = affine_set<() : (0 >= 0)>
+func.func @test_affine_if_1(%arg0: memref<10xf32>) -> memref<10xf32> {
+  %0 = affine.if #set() -> memref<10xf32> {
+    %alloc = memref.alloc() : memref<10xf32>
+    affine.yield %alloc : memref<10xf32>
+  } else {
+    affine.yield %arg0 : memref<10xf32>
+  }
+  return %0 : memref<10xf32>
+}
+
+// CHECK-LABEL: func @test_affine_if_1
+//  CHECK-SAME: ([[ARG0:%.*]]: memref<10xf32>)
+//       CHECK: [[V0:%.+]]:2 = affine.if
+//       CHECK:   [[ALLOC:%.+]] = memref.alloc()
+//       CHECK:   affine.yield [[ALLOC]], %true
+//       CHECK:   affine.yield [[ARG0]], %false
+//       CHECK: [[V1:%.+]] = scf.if [[V0]]#1
+//       CHECK:   scf.yield [[V0]]#0
+//       CHECK:   [[CLONE:%.+]] = bufferization.clone [[V0]]#0
+//       CHECK:   scf.yield [[CLONE]]
+//       CHECK: [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//       CHECK: bufferization.dealloc ([[BASE]] :{{.*}}) if ([[V0]]#1) retain ([[V1]] :
+//       CHECK: return [[V1]]
+
+// TODO: the dealloc could be optimized away since the memref to be deallocated
+//       either aliases with V1 or the condition is false
+
+// -----
+
+// Memref allocated before parent IfOp and used in `then` region.
+// Expected result: deallocation should happen after affine.if op.
+#set = affine_set<() : (0 >= 0)>
+func.func @test_affine_if_2() -> memref<10xf32> {
+  %alloc0 = memref.alloc() : memref<10xf32>
+  %0 = affine.if #set() -> memref<10xf32> {
+    affine.yield %alloc0 : memref<10xf32>
+  } else {
+    %alloc = memref.alloc() : memref<10xf32>
+    affine.yield %alloc : memref<10xf32>
+  }
+  return %0 : memref<10xf32>
+}
+// CHECK-LABEL: func @test_affine_if_2
+//       CHECK: [[ALLOC:%.+]] = memref.alloc()
+//       CHECK: [[V0:%.+]]:2 = affine.if
+//       CHECK:   affine.yield [[ALLOC]], %false
+//       CHECK:   [[ALLOC1:%.+]] = memref.alloc()
+//       CHECK:   affine.yield [[ALLOC1]], %true
+//       CHECK: [[V1:%.+]] = scf.if [[V0]]#1
+//       CHECK:   scf.yield [[V0]]#0
+//       CHECK:   [[CLONE:%.+]] = bufferization.clone [[V0]]#0
+//       CHECK:   scf.yield [[CLONE]]
+//       CHECK: [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//       CHECK: bufferization.dealloc ([[ALLOC]], [[BASE]] :{{.*}}) if (%true{{[0-9_]*}}, [[V0]]#1) retain ([[V1]] :
+//       CHECK: return [[V1]]
+
+// -----
+
+// Memref allocated before parent IfOp and used in `else` region.
+// Expected result: deallocation should happen after affine.if op.
+#set = affine_set<() : (0 >= 0)>
+func.func @test_affine_if_3() -> memref<10xf32> {
+  %alloc0 = memref.alloc() : memref<10xf32>
+  %0 = affine.if #set() -> memref<10xf32> {
+    %alloc = memref.alloc() : memref<10xf32>
+    affine.yield %alloc : memref<10xf32>
+  } else {
+    affine.yield %alloc0 : memref<10xf32>
+  }
+  return %0 : memref<10xf32>
+}
+
+// CHECK-LABEL: func @test_affine_if_3
+//       CHECK: [[ALLOC:%.+]] = memref.alloc()
+//       CHECK: [[V0:%.+]]:2 = affine.if
+//       CHECK:   [[ALLOC1:%.+]] = memref.alloc()
+//       CHECK:   affine.yield [[ALLOC1]], %true
+//       CHECK:   affine.yield [[ALLOC]], %false
+//       CHECK: [[V1:%.+]] = scf.if [[V0]]#1
+//       CHECK:   scf.yield [[V0]]#0
+//       CHECK:   [[CLONE:%.+]] = bufferization.clone [[V0]]#0
+//       CHECK:   scf.yield [[CLONE]]
+//       CHECK: [[BASE:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
+//       CHECK: bufferization.dealloc ([[ALLOC]], [[BASE]] :{{.*}}) if (%true{{[0-9_]*}}, [[V0]]#1) retain ([[V1]]
+//       CHECK: return [[V1]]
diff --git a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-subviews.mlir b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-subviews.mlir
new file mode 100644
index 000000000000000..666b3b08995e8ad
--- /dev/null
+++ b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-subviews.mlir
@@ -0,0 +1,21 @@
+// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation \
+// RUN:   --buffer-deallocation-simplification -split-input-file %s | FileCheck %s
+// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation=private-function-dynamic-ownership=true -split-input-file %s > /dev/null
+
+// CHECK-LABEL: func @subview
+func.func @subview(%arg0 : index, %arg1 : index, %arg2 : memref<?x?xf32>) {
+  %0 = memref.alloc() : memref<64x4xf32, strided<[4, 1], offset: 0>>
+  %1 = memref.subview %0[%arg0, %arg1][%arg0, %arg1][%arg0, %arg1] :
+    memref<64x4xf32, strided<[4, 1], offset: 0>>
+  to memref<?x?xf32, strided<[?, ?], offset: ?>>
+  test.copy(%1, %arg2) :
+    (memref<?x?xf32, strided<[?, ?], offset: ?>>, memref<?x?xf32>)
+  return
+}
+
+//      CHECK: %[[ALLOC:.*]] = memref.alloc()
+// CHECK-NEXT: memref.subview
+// CHECK-NEXT: test.copy
+// CHECK-NEXT: bufferization.dealloc (%[[ALLOC]] :
+// CHECK-SAME:   if (%true)
+// CHECK-NEXT: return
diff --git a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/invalid-buffer-deallocation.mlir b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/invalid-buffer-deallocation.mlir
new file mode 100644
index 000000000000000..c623891e48362fa
--- /dev/null
+++ b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/invalid-buffer-deallocation.mlir
@@ -0,0 +1,93 @@
+// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation -split-input-file %s
+
+
+// Test Case: explicit control-flow loop with a dynamically allocated buffer.
+// The BufferDeallocation transformation should fail on this explicit
+// control-flow loop since they are not supported.
+
+// expected-error at +1 {{Only structured control-flow loops are supported}}
+func.func @loop_dynalloc(
+  %arg0 : i32,
+  %arg1 : i32,
+  %arg2: memref<?xf32>,
+  %arg3: memref<?xf32>) {
+  %const0 = arith.constant 0 : i32
+  cf.br ^loopHeader(%const0, %arg2 : i32, memref<?xf32>)
+
+^loopHeader(%i : i32, %buff : memref<?xf32>):
+  %lessThan = arith.cmpi slt, %i, %arg1 : i32
+  cf.cond_br %lessThan,
+    ^loopBody(%i, %buff : i32, memref<?xf32>),
+    ^exit(%buff : memref<?xf32>)
+
+^loopBody(%val : i32, %buff2: memref<?xf32>):
+  %const1 = arith.constant 1 : i32
+  %inc = arith.addi %val, %const1 : i32
+  %size = arith.index_cast %inc : i32 to index
+  %alloc1 = memref.alloc(%size) : memref<?xf32>
+  cf.br ^loopHeader(%inc, %alloc1 : i32, memref<?xf32>)
+
+^exit(%buff3 : memref<?xf32>):
+  test.copy(%buff3, %arg3) : (memref<?xf32>, memref<?xf32>)
+  return
+}
+
+// -----
+
+// Test Case: explicit control-flow loop with a dynamically allocated buffer.
+// The BufferDeallocation transformation should fail on this explicit
+// control-flow loop since they are not supported.
+
+// expected-error at +1 {{Only structured control-flow loops are supported}}
+func.func @do_loop_alloc(
+  %arg0 : i32,
+  %arg1 : i32,
+  %arg2: memref<2xf32>,
+  %arg3: memref<2xf32>) {
+  %const0 = arith.constant 0 : i32
+  cf.br ^loopBody(%const0, %arg2 : i32, memref<2xf32>)
+
+^loopBody(%val : i32, %buff2: memref<2xf32>):
+  %const1 = arith.constant 1 : i32
+  %inc = arith.addi %val, %const1 : i32
+  %alloc1 = memref.alloc() : memref<2xf32>
+  cf.br ^loopHeader(%inc, %alloc1 : i32, memref<2xf32>)
+
+^loopHeader(%i : i32, %buff : memref<2xf32>):
+  %lessThan = arith.cmpi slt, %i, %arg1 : i32
+  cf.cond_br %lessThan,
+    ^loopBody(%i, %buff : i32, memref<2xf32>),
+    ^exit(%buff : memref<2xf32>)
+
+^exit(%buff3 : memref<2xf32>):
+  test.copy(%buff3, %arg3) : (memref<2xf32>, memref<2xf32>)
+  return
+}
+
+// -----
+
+func.func @free_effect() {
+  %alloc = memref.alloc() : memref<2xi32>
+  // expected-error @below {{memory free side-effect on MemRef value not supported!}}
+  %new_alloc = memref.realloc %alloc : memref<2xi32> to memref<4xi32>
+  return
+}
+
+// -----
+
+func.func @free_effect() {
+  %alloc = memref.alloc() : memref<2xi32>
+  // expected-error @below {{memory free side-effect on MemRef value not supported!}}
+  memref.dealloc %alloc : memref<2xi32>
+  return
+}
+
+// -----
+
+func.func @free_effect() {
+  %true = arith.constant true
+  %alloc = memref.alloc() : memref<2xi32>
+  // expected-error @below {{No deallocation operations must be present when running this pass!}}
+  bufferization.dealloc (%alloc : memref<2xi32>) if (%true)
+  return
+}
diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
index 2263414388b0811..d4390e7651be0f0 100644
--- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
@@ -12137,6 +12137,7 @@ cc_library(
         ":BufferizationDialect",
         ":BufferizationEnumsIncGen",
         ":BufferizationPassIncGen",
+        ":ControlFlowDialect",
         ":ControlFlowInterfaces",
         ":FuncDialect",
         ":IR",

>From 3cb5a26661521b00f59121677ed539cd366ceaf6 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Thu, 14 Sep 2023 11:14:00 +0100
Subject: [PATCH 55/86] [lldb][Docs] Link to testing page from debugging page

The testing page already has some page about debugging failures.

I'm not linking directly to that section because:
* The earlier sections about running single tests and such
  are just as useful for debugging in general.
* The new theme has a nice sidebar on the right that makes
  it really easy to find what you want once on the page.
* We'll probably add more content to the testing page later.
---
 lldb/docs/resources/debugging.rst | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lldb/docs/resources/debugging.rst b/lldb/docs/resources/debugging.rst
index c4f5594096f573b..0af1de1581c4bd0 100644
--- a/lldb/docs/resources/debugging.rst
+++ b/lldb/docs/resources/debugging.rst
@@ -580,3 +580,8 @@ reproduction steps.
 Finally, that "thing" is the ptrace calls you got from the ``lldb-server`` logs.
 Add those to the debugger function and you now have a reproducer that doesn't
 need any part of LLDB.
+
+Debugging Tests
+---------------
+
+See :doc:`/resources/test`.
\ No newline at end of file

>From a83290e7f4820f372043dd25e6f4578a052d2391 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 14 Sep 2023 12:22:11 +0200
Subject: [PATCH 56/86] Fixup "[analyzer] Propagate taint for wchar variants of
 some APIs"

Fix build bot: https://lab.llvm.org/buildbot/#/builders/139/builds/49699

clang/test/Analysis/taint-generic.c:
```
Line 100: redefinition of typedef 'size_t' is a C11 feature
Line 59: previous definition is here
```

This commit fixups 61924da630532c91f00351b7e84548eb42e2e1e0
Committed in this PR: https://github.com/llvm/llvm-project/pull/66074
---
 clang/test/Analysis/taint-generic.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/clang/test/Analysis/taint-generic.c b/clang/test/Analysis/taint-generic.c
index f08186fc8c4c1e5..c674a03cfaec6c8 100644
--- a/clang/test/Analysis/taint-generic.c
+++ b/clang/test/Analysis/taint-generic.c
@@ -56,7 +56,8 @@
 // CHECK-INVALID-ARG-SAME:        rules greater or equal to -1
 
 typedef long long rsize_t;
-typedef typeof(sizeof(int)) size_t;
+typedef __typeof(sizeof(int)) size_t;
+typedef signed long long ssize_t;
 typedef __WCHAR_TYPE__ wchar_t;
 void clang_analyzer_isTainted_char(char);
 void clang_analyzer_isTainted_wchar(wchar_t);
@@ -97,8 +98,6 @@ int fscanf(FILE *restrict stream, const char *restrict format, ...);
 int sprintf(char *str, const char *format, ...);
 void setproctitle(const char *fmt, ...);
 void setproctitle_init(int argc, char *argv[], char *envp[]);
-typedef __typeof(sizeof(int)) size_t;
-typedef signed long long ssize_t;
 
 // Define string functions. Use builtin for some of them. They all default to
 // the processing in the taint checker.

>From 221eb2b1fef0c8a16f0d7fcabd0656319bfd0ca2 Mon Sep 17 00:00:00 2001
From: khei4 <kk.asano.luxy at gmail.com>
Date: Mon, 11 Sep 2023 12:21:34 +0900
Subject: [PATCH 57/86] Reapply "Revert "[MemCpyOpt] implement multi BB
 stack-move optimization"

This reverts commit efe8aa2e618122e8050af10cc5d6ad83f24ef557.

Differential Revision: https://reviews.llvm.org/D155406
---
 .../llvm/Transforms/Scalar/MemCpyOptimizer.h  |   5 +-
 .../lib/Transforms/Scalar/MemCpyOptimizer.cpp | 117 +++++++++---------
 llvm/test/Other/new-pm-defaults.ll            |   3 +-
 llvm/test/Other/new-pm-lto-defaults.ll        |   2 +-
 .../Other/new-pm-thinlto-postlink-defaults.ll |   3 +-
 .../Other/new-pm-thinlto-prelink-defaults.ll  |   3 +-
 .../Transforms/MemCpyOpt/lifetime-missing.ll  |   2 -
 llvm/test/Transforms/MemCpyOpt/stack-move.ll  | 105 ++--------------
 8 files changed, 81 insertions(+), 159 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Scalar/MemCpyOptimizer.h b/llvm/include/llvm/Transforms/Scalar/MemCpyOptimizer.h
index d3e5e2591eea110..3e8a5bf6a5bd56e 100644
--- a/llvm/include/llvm/Transforms/Scalar/MemCpyOptimizer.h
+++ b/llvm/include/llvm/Transforms/Scalar/MemCpyOptimizer.h
@@ -34,6 +34,7 @@ class MemMoveInst;
 class MemorySSA;
 class MemorySSAUpdater;
 class MemSetInst;
+class PostDominatorTree;
 class StoreInst;
 class TargetLibraryInfo;
 class Value;
@@ -43,6 +44,7 @@ class MemCpyOptPass : public PassInfoMixin<MemCpyOptPass> {
   AAResults *AA = nullptr;
   AssumptionCache *AC = nullptr;
   DominatorTree *DT = nullptr;
+  PostDominatorTree *PDT = nullptr;
   MemorySSA *MSSA = nullptr;
   MemorySSAUpdater *MSSAU = nullptr;
 
@@ -53,7 +55,8 @@ class MemCpyOptPass : public PassInfoMixin<MemCpyOptPass> {
 
   // Glue for the old PM.
   bool runImpl(Function &F, TargetLibraryInfo *TLI, AAResults *AA,
-               AssumptionCache *AC, DominatorTree *DT, MemorySSA *MSSA);
+               AssumptionCache *AC, DominatorTree *DT, PostDominatorTree *PDT,
+               MemorySSA *MSSA);
 
 private:
   // Helper functions
diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 6015bdf88a62ead..12e74929b452710 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -19,12 +19,14 @@
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/CFG.h"
 #include "llvm/Analysis/CaptureTracking.h"
 #include "llvm/Analysis/GlobalsModRef.h"
 #include "llvm/Analysis/Loads.h"
 #include "llvm/Analysis/MemoryLocation.h"
 #include "llvm/Analysis/MemorySSA.h"
 #include "llvm/Analysis/MemorySSAUpdater.h"
+#include "llvm/Analysis/PostDominators.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/IR/BasicBlock.h"
@@ -1440,8 +1442,7 @@ bool MemCpyOptPass::performStackMoveOptzn(Instruction *Load, Instruction *Store,
     return false;
   }
 
-  // 1. Check that copy is full. Calculate the static size of the allocas to be
-  // merged, bail out if we can't.
+  // Check that copy is full with static size.
   const DataLayout &DL = DestAlloca->getModule()->getDataLayout();
   std::optional<TypeSize> SrcSize = SrcAlloca->getAllocationSize(DL);
   if (!SrcSize || SrcSize->isScalable() || Size != SrcSize->getFixedValue()) {
@@ -1455,19 +1456,15 @@ bool MemCpyOptPass::performStackMoveOptzn(Instruction *Load, Instruction *Store,
     return false;
   }
 
-  // 2-1. Check that src and dest are static allocas, which are not affected by
-  // stacksave/stackrestore.
-  if (!SrcAlloca->isStaticAlloca() || !DestAlloca->isStaticAlloca() ||
-      SrcAlloca->getParent() != Load->getParent() ||
-      SrcAlloca->getParent() != Store->getParent())
+  if (!SrcAlloca->isStaticAlloca() || !DestAlloca->isStaticAlloca())
     return false;
 
-  // 2-2. Check that src and dest are never captured, unescaped allocas. Also
-  // collect lifetime markers first/last users in order to shrink wrap the
-  // lifetimes, and instructions with noalias metadata to remove them.
+  // Check that src and dest are never captured, unescaped allocas. Also
+  // find the nearest common dominator and postdominator for all users in
+  // order to shrink wrap the lifetimes, and instructions with noalias metadata
+  // to remove them.
 
   SmallVector<Instruction *, 4> LifetimeMarkers;
-  Instruction *FirstUser = nullptr, *LastUser = nullptr;
   SmallSet<Instruction *, 4> NoAliasInstrs;
 
   // Recursively track the user and check whether modified alias exist.
@@ -1505,12 +1502,6 @@ bool MemCpyOptPass::performStackMoveOptzn(Instruction *Load, Instruction *Store,
           continue;
         case UseCaptureKind::NO_CAPTURE: {
           auto *UI = cast<Instruction>(U.getUser());
-          if (DestAlloca->getParent() != UI->getParent())
-            return false;
-          if (!FirstUser || UI->comesBefore(FirstUser))
-            FirstUser = UI;
-          if (!LastUser || LastUser->comesBefore(UI))
-            LastUser = UI;
           if (UI->isLifetimeStartOrEnd()) {
             // We note the locations of these intrinsic calls so that we can
             // delete them later if the optimization succeeds, this is safe
@@ -1534,37 +1525,64 @@ bool MemCpyOptPass::performStackMoveOptzn(Instruction *Load, Instruction *Store,
     return true;
   };
 
-  // 3. Check that dest has no Mod/Ref, except full size lifetime intrinsics,
-  // from the alloca to the Store.
+  // Check that dest has no Mod/Ref, from the alloca to the Store, except full
+  // size lifetime intrinsics. And collect modref inst for the reachability
+  // check.
   ModRefInfo DestModRef = ModRefInfo::NoModRef;
   MemoryLocation DestLoc(DestAlloca, LocationSize::precise(Size));
+  SmallVector<BasicBlock *, 8> ReachabilityWorklist;
   auto DestModRefCallback = [&](Instruction *UI) -> bool {
     // We don't care about the store itself.
     if (UI == Store)
       return true;
     ModRefInfo Res = BAA.getModRefInfo(UI, DestLoc);
-    // FIXME: For multi-BB cases, we need to see reachability from it to
-    // store.
-    // Bailout if Dest may have any ModRef before Store.
-    if (UI->comesBefore(Store) && isModOrRefSet(Res))
-      return false;
-    DestModRef |= BAA.getModRefInfo(UI, DestLoc);
+    DestModRef |= Res;
+    if (isModOrRefSet(Res)) {
+      // Instructions reachability checks.
+      // FIXME: adding the Instruction version isPotentiallyReachableFromMany on
+      // lib/Analysis/CFG.cpp (currently only for BasicBlocks) might be helpful.
+      if (UI->getParent() == Store->getParent()) {
+        // The same block case is special because it's the only time we're
+        // looking within a single block to see which instruction comes first.
+        // Once we start looking at multiple blocks, the first instruction of
+        // the block is reachable, so we only need to determine reachability
+        // between whole blocks.
+        BasicBlock *BB = UI->getParent();
+
+        // If A comes before B, then B is definitively reachable from A.
+        if (UI->comesBefore(Store))
+          return false;
+
+        // If the user's parent block is entry, no predecessor exists.
+        if (BB->isEntryBlock())
+          return true;
 
+        // Otherwise, continue doing the normal per-BB CFG walk.
+        ReachabilityWorklist.append(succ_begin(BB), succ_end(BB));
+      } else {
+        ReachabilityWorklist.push_back(UI->getParent());
+      }
+    }
     return true;
   };
 
   if (!CaptureTrackingWithModRef(DestAlloca, DestModRefCallback))
     return false;
+  // Bailout if Dest may have any ModRef before Store.
+  if (!ReachabilityWorklist.empty() &&
+      isPotentiallyReachableFromMany(ReachabilityWorklist, Store->getParent(),
+                                     nullptr, DT, nullptr))
+    return false;
 
-  // 3. Check that, from after the Load to the end of the BB,
-  // 3-1. if the dest has any Mod, src has no Ref, and
-  // 3-2. if the dest has any Ref, src has no Mod except full-sized lifetimes.
+  // Check that, from after the Load to the end of the BB,
+  //   - if the dest has any Mod, src has no Ref, and
+  //   - if the dest has any Ref, src has no Mod except full-sized lifetimes.
   MemoryLocation SrcLoc(SrcAlloca, LocationSize::precise(Size));
 
   auto SrcModRefCallback = [&](Instruction *UI) -> bool {
-    // Any ModRef before Load doesn't matter, also Load and Store can be
-    // ignored.
-    if (UI->comesBefore(Load) || UI == Load || UI == Store)
+    // Any ModRef post-dominated by Load doesn't matter, also Load and Store
+    // themselves can be ignored.
+    if (PDT->dominates(Load, UI) || UI == Load || UI == Store)
       return true;
     ModRefInfo Res = BAA.getModRefInfo(UI, SrcLoc);
     if ((isModSet(DestModRef) && isRefSet(Res)) ||
@@ -1588,34 +1606,10 @@ bool MemCpyOptPass::performStackMoveOptzn(Instruction *Load, Instruction *Store,
   // Drop metadata on the source alloca.
   SrcAlloca->dropUnknownNonDebugMetadata();
 
-  // Do "shrink wrap" the lifetimes, if the original lifetime intrinsics exists.
+  // TODO: Reconstruct merged lifetime markers.
+  // Remove all other lifetime markers. if the original lifetime intrinsics
+  // exists.
   if (!LifetimeMarkers.empty()) {
-    LLVMContext &C = SrcAlloca->getContext();
-    IRBuilder<> Builder(C);
-
-    ConstantInt *AllocaSize = ConstantInt::get(Type::getInt64Ty(C), Size);
-    // Create a new lifetime start marker before the first user of src or alloca
-    // users.
-    Builder.SetInsertPoint(FirstUser->getParent(), FirstUser->getIterator());
-    auto *Start = Builder.CreateLifetimeStart(SrcAlloca, AllocaSize);
-    auto *FirstMA = MSSA->getMemoryAccess(FirstUser);
-    auto *StartMA = MSSAU->createMemoryAccessBefore(Start, nullptr, FirstMA);
-    MSSAU->insertDef(cast<MemoryDef>(StartMA), /*RenameUses=*/true);
-
-    // Create a new lifetime end marker after the last user of src or alloca
-    // users.
-    // FIXME: If the last user is the terminator for the bb, we can insert
-    // lifetime.end marker to the immidiate post-dominator, but currently do
-    // nothing.
-    if (!LastUser->isTerminator()) {
-      Builder.SetInsertPoint(LastUser->getParent(), ++LastUser->getIterator());
-      auto *End = Builder.CreateLifetimeEnd(SrcAlloca, AllocaSize);
-      auto *LastMA = MSSA->getMemoryAccess(LastUser);
-      auto *EndMA = MSSAU->createMemoryAccessAfter(End, nullptr, LastMA);
-      MSSAU->insertDef(cast<MemoryDef>(EndMA), /*RenameUses=*/true);
-    }
-
-    // Remove all other lifetime markers.
     for (Instruction *I : LifetimeMarkers)
       eraseInstruction(I);
   }
@@ -1999,9 +1993,10 @@ PreservedAnalyses MemCpyOptPass::run(Function &F, FunctionAnalysisManager &AM) {
   auto *AA = &AM.getResult<AAManager>(F);
   auto *AC = &AM.getResult<AssumptionAnalysis>(F);
   auto *DT = &AM.getResult<DominatorTreeAnalysis>(F);
+  auto *PDT = &AM.getResult<PostDominatorTreeAnalysis>(F);
   auto *MSSA = &AM.getResult<MemorySSAAnalysis>(F);
 
-  bool MadeChange = runImpl(F, &TLI, AA, AC, DT, &MSSA->getMSSA());
+  bool MadeChange = runImpl(F, &TLI, AA, AC, DT, PDT, &MSSA->getMSSA());
   if (!MadeChange)
     return PreservedAnalyses::all();
 
@@ -2013,12 +2008,14 @@ PreservedAnalyses MemCpyOptPass::run(Function &F, FunctionAnalysisManager &AM) {
 
 bool MemCpyOptPass::runImpl(Function &F, TargetLibraryInfo *TLI_,
                             AliasAnalysis *AA_, AssumptionCache *AC_,
-                            DominatorTree *DT_, MemorySSA *MSSA_) {
+                            DominatorTree *DT_, PostDominatorTree *PDT_,
+                            MemorySSA *MSSA_) {
   bool MadeChange = false;
   TLI = TLI_;
   AA = AA_;
   AC = AC_;
   DT = DT_;
+  PDT = PDT_;
   MSSA = MSSA_;
   MemorySSAUpdater MSSAU_(MSSA_);
   MSSAU = &MSSAU_;
diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll
index 5cb9a7f331a680b..016dfad98c69f70 100644
--- a/llvm/test/Other/new-pm-defaults.ll
+++ b/llvm/test/Other/new-pm-defaults.ll
@@ -190,6 +190,7 @@
 ; CHECK-O23SZ-NEXT: Running pass: GVNPass
 ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis
 ; CHECK-O1-NEXT: Running pass: MemCpyOptPass
+; CHECK-O1-NEXT: Running analysis: PostDominatorTreeAnalysis
 ; CHECK-O-NEXT: Running pass: SCCPPass
 ; CHECK-O-NEXT: Running pass: BDCEPass
 ; CHECK-O-NEXT: Running analysis: DemandedBitsAnalysis
@@ -201,7 +202,7 @@
 ; CHECK-O23SZ-NEXT: Invalidating analysis: LazyValueAnalysis
 ; CHECK-O1-NEXT: Running pass: CoroElidePass
 ; CHECK-O-NEXT: Running pass: ADCEPass
-; CHECK-O-NEXT: Running analysis: PostDominatorTreeAnalysis
+; CHECK-O23SZ-NEXT: Running analysis: PostDominatorTreeAnalysis
 ; CHECK-O23SZ-NEXT: Running pass: MemCpyOptPass
 ; CHECK-O23SZ-NEXT: Running pass: DSEPass
 ; CHECK-O23SZ-NEXT: Running pass: MoveAutoInitPass on foo
diff --git a/llvm/test/Other/new-pm-lto-defaults.ll b/llvm/test/Other/new-pm-lto-defaults.ll
index 1b64760e42c1efb..c444197e0db7062 100644
--- a/llvm/test/Other/new-pm-lto-defaults.ll
+++ b/llvm/test/Other/new-pm-lto-defaults.ll
@@ -103,8 +103,8 @@
 ; CHECK-O23SZ-NEXT: Running pass: GVNPass on foo
 ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis on foo
 ; CHECK-O23SZ-NEXT: Running pass: MemCpyOptPass on foo
-; CHECK-O23SZ-NEXT: Running pass: DSEPass on foo
 ; CHECK-O23SZ-NEXT: Running analysis: PostDominatorTreeAnalysis on foo
+; CHECK-O23SZ-NEXT: Running pass: DSEPass on foo
 ; CHECK-O23SZ-NEXT: Running pass: MoveAutoInitPass on foo
 ; CHECK-O23SZ-NEXT: Running pass: MergedLoadStoreMotionPass on foo
 ; CHECK-O23SZ-NEXT: Running pass: LoopSimplifyPass on foo
diff --git a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
index aa3b8e85749d955..79010c3eb808044 100644
--- a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
@@ -125,6 +125,7 @@
 ; CHECK-O23SZ-NEXT: Running pass: GVNPass
 ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis
 ; CHECK-O1-NEXT: Running pass: MemCpyOptPass
+; CHECK-O1-NEXT: Running analysis: PostDominatorTreeAnalysis
 ; CHECK-O-NEXT: Running pass: SCCPPass
 ; CHECK-O-NEXT: Running pass: BDCEPass
 ; CHECK-O-NEXT: Running analysis: DemandedBitsAnalysis
@@ -135,7 +136,7 @@
 ; CHECK-O23SZ-NEXT: Invalidating analysis: LazyValueAnalysis
 ; CHECK-O1-NEXT: Running pass: CoroElidePass
 ; CHECK-O-NEXT: Running pass: ADCEPass
-; CHECK-O-NEXT: Running analysis: PostDominatorTreeAnalysis
+; CHECK-O23SZ-NEXT: Running analysis: PostDominatorTreeAnalysis
 ; CHECK-O23SZ-NEXT: Running pass: MemCpyOptPass
 ; CHECK-O23SZ-NEXT: Running pass: DSEPass
 ; CHECK-O23SZ-NEXT: Running pass: MoveAutoInitPass on foo
diff --git a/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll
index 7761ae84b3a125f..0697fb253b1fe0a 100644
--- a/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll
@@ -157,6 +157,7 @@
 ; CHECK-O23SZ-NEXT: Running pass: GVNPass
 ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis
 ; CHECK-O1-NEXT: Running pass: MemCpyOptPass
+; CHECK-O1-NEXT: Running analysis: PostDominatorTreeAnalysis
 ; CHECK-O-NEXT: Running pass: SCCPPass
 ; CHECK-O-NEXT: Running pass: BDCEPass
 ; CHECK-O-NEXT: Running analysis: DemandedBitsAnalysis
@@ -167,7 +168,7 @@
 ; CHECK-O23SZ-NEXT: Invalidating analysis: LazyValueAnalysis
 ; CHECK-O1-NEXT: Running pass: CoroElidePass
 ; CHECK-O-NEXT: Running pass: ADCEPass
-; CHECK-O-NEXT: Running analysis: PostDominatorTreeAnalysis
+; CHECK-O23SZ-NEXT: Running analysis: PostDominatorTreeAnalysis
 ; CHECK-O23SZ-NEXT: Running pass: MemCpyOptPass
 ; CHECK-O23SZ-NEXT: Running pass: DSEPass
 ; CHECK-O23SZ-NEXT: Running pass: MoveAutoInitPass
diff --git a/llvm/test/Transforms/MemCpyOpt/lifetime-missing.ll b/llvm/test/Transforms/MemCpyOpt/lifetime-missing.ll
index b3ad0f7cdd8c6c7..0626f09702f7e21 100644
--- a/llvm/test/Transforms/MemCpyOpt/lifetime-missing.ll
+++ b/llvm/test/Transforms/MemCpyOpt/lifetime-missing.ll
@@ -15,11 +15,9 @@ define void @test() {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[AGG_TMP_SROA_14:%.*]] = alloca [20 x i8], align 4
 ; CHECK-NEXT:    [[AGG_TMP_SROA_14_128_SROA_IDX:%.*]] = getelementptr i8, ptr [[AGG_TMP_SROA_14]], i64 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 20, ptr [[AGG_TMP_SROA_14]])
 ; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[AGG_TMP_SROA_14_128_SROA_IDX]], i8 0, i64 1, i1 false)
 ; CHECK-NEXT:    [[AGG_TMP3_SROA_35_128_SROA_IDX:%.*]] = getelementptr i8, ptr [[AGG_TMP_SROA_14]], i64 4
 ; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr inttoptr (i64 4 to ptr), i8 0, i64 1, i1 false)
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 20, ptr [[AGG_TMP_SROA_14]])
 ; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr null, i8 0, i64 1, i1 false)
 ; CHECK-NEXT:    ret void
 ;
diff --git a/llvm/test/Transforms/MemCpyOpt/stack-move.ll b/llvm/test/Transforms/MemCpyOpt/stack-move.ll
index f0f0df9f527a399..161a732fdc2a94b 100644
--- a/llvm/test/Transforms/MemCpyOpt/stack-move.ll
+++ b/llvm/test/Transforms/MemCpyOpt/stack-move.ll
@@ -24,11 +24,9 @@ declare i32 @use_writeonly(ptr noundef) memory(write)
 define void @basic_memcpy() {
 ; CHECK-LABEL: define void @basic_memcpy() {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4
@@ -50,11 +48,9 @@ define void @basic_memcpy() {
 define void @basic_memmove() {
 ; CHECK-LABEL: define void @basic_memmove() {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4
@@ -77,11 +73,9 @@ define void @basic_memmove() {
 define void @load_store() {
 ; CHECK-LABEL: define void @load_store() {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca i32, align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[SRC]])
 ; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca i32, align 4
@@ -104,11 +98,9 @@ define void @load_store() {
 define void @align_up() {
 ; CHECK-LABEL: define void @align_up() {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4
@@ -131,12 +123,10 @@ define void @align_up() {
 define void @remove_extra_lifetime_intrinsics() {
 ; CHECK-LABEL: define void @remove_extra_lifetime_intrinsics() {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
 ; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4
@@ -185,13 +175,11 @@ define void @no_lifetime() {
 define void @alias_no_mod() {
 ; CHECK-LABEL: define void @alias_no_mod() {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    [[DEST_ALIAS:%.*]] = getelementptr [[STRUCT_FOO]], ptr [[SRC]], i32 0, i32 0
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
 ; CHECK-NEXT:    [[SRC_ALIAS:%.*]] = getelementptr [[STRUCT_FOO]], ptr [[SRC]], i32 0, i32 0
 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4
@@ -224,11 +212,9 @@ define void @alias_no_mod() {
 define void @remove_scoped_noalias() {
 ; CHECK-LABEL: define void @remove_scoped_noalias() {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]]), !alias.scope !0
 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4
@@ -250,11 +236,9 @@ define void @remove_scoped_noalias() {
 define void @remove_alloca_metadata() {
 ; CHECK-LABEL: define void @remove_alloca_metadata() {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]]), !alias.scope !0
 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4, !annotation !3
@@ -277,11 +261,9 @@ define void @remove_alloca_metadata() {
 define void @noalias_on_lifetime() {
 ; CHECK-LABEL: define void @noalias_on_lifetime() {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]]), !alias.scope !0
 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4
@@ -303,11 +285,9 @@ define void @noalias_on_lifetime() {
 define void @src_ref_dest_ref_after_copy() {
 ; CHECK-LABEL: define void @src_ref_dest_ref_after_copy() {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_readonly(ptr nocapture [[SRC]])
 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_readonly(ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4
@@ -329,11 +309,9 @@ define void @src_ref_dest_ref_after_copy() {
 define void @src_mod_dest_mod_after_copy() {
 ; CHECK-LABEL: define void @src_mod_dest_mod_after_copy() {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_writeonly(ptr nocapture [[SRC]])
 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_writeonly(ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4
@@ -354,10 +332,8 @@ define void @src_mod_dest_mod_after_copy() {
 define void @avoid_memory_use_last_user_crash() {
 ; CHECK-LABEL: define void @avoid_memory_use_last_user_crash() {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[SRC]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4
@@ -375,7 +351,6 @@ define void @avoid_memory_use_last_user_crash() {
 define void @terminator_lastuse() personality i32 0 {
 ; CHECK-LABEL: define void @terminator_lastuse() personality i32 0 {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr [[SRC]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
 ; CHECK-NEXT:    [[RV:%.*]] = invoke i32 @use_nocapture(ptr [[SRC]])
@@ -406,24 +381,17 @@ suc:
   ret void
 }
 
-; TODO: merge allocas for bb-separated, but logically straight
 define void @multi_bb_memcpy(i1 %b) {
 ; CHECK-LABEL: define void @multi_bb_memcpy
 ; CHECK-SAME: (i1 [[B:%.*]]) {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca i32, align 4
-; CHECK-NEXT:    [[DEST:%.*]] = alloca i32, align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr nocapture [[DEST]])
 ; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
 ; CHECK-NEXT:    br label [[BB0:%.*]]
 ; CHECK:       bb0:
-; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 4, i1 false)
 ; CHECK-NEXT:    br label [[BB1:%.*]]
 ; CHECK:       bb1:
-; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[DEST]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr nocapture [[DEST]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca i32, align 4
@@ -445,23 +413,15 @@ bb1:
   ret void
 }
 
-; TODO: Merge alloca
 define void @multi_bb_load_store(i1 %b) {
 ; CHECK-LABEL: define void @multi_bb_load_store
 ; CHECK-SAME: (i1 [[B:%.*]]) {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca i32, align 4
-; CHECK-NEXT:    [[DEST:%.*]] = alloca i32, align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr nocapture [[DEST]])
 ; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
-; CHECK-NEXT:    [[SRC_VAL:%.*]] = load i32, ptr [[SRC]], align 4
-; CHECK-NEXT:    store i32 [[SRC_VAL]], ptr [[DEST]], align 4
 ; CHECK-NEXT:    br label [[BB0:%.*]]
 ; CHECK:       bb0:
-; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[DEST]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr nocapture [[DEST]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca i32, align 4
@@ -525,28 +485,20 @@ bb1:
   ret void
 }
 
-; TODO: merge allocas for multi basicblocks, s.t. all copy-dominated
-; uses are satisfy the condition.
 define void @multi_bb_simple_br(i1 %b) {
 ; CHECK-LABEL: define void @multi_bb_simple_br
 ; CHECK-SAME: (i1 [[B:%.*]]) {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[DEST]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
-; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
 ; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]
 ; CHECK:       bb0:
-; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    br label [[BB2:%.*]]
 ; CHECK:       bb1:
-; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
+; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    br label [[BB2]]
 ; CHECK:       bb2:
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4
@@ -577,7 +529,6 @@ define void @multi_bb_dom_test0(i1 %b) {
 ; CHECK-LABEL: define void @multi_bb_dom_test0
 ; CHECK-SAME: (i1 [[B:%.*]]) {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
 ; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]
 ; CHECK:       bb0:
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
@@ -586,9 +537,7 @@ define void @multi_bb_dom_test0(i1 %b) {
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 40, i32 50, i32 60 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    br label [[BB2]]
 ; CHECK:       bb2:
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[DEST]])
-; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
-; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4
@@ -663,20 +612,16 @@ define void @multi_bb_pdom_test0(i1 %b) {
 ; CHECK-LABEL: define void @multi_bb_pdom_test0
 ; CHECK-SAME: (i1 [[B:%.*]]) {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[DEST]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
-; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
 ; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]
 ; CHECK:       bb0:
-; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    br label [[BB2:%.*]]
 ; CHECK:       bb1:
-; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    br label [[BB2]]
 ; CHECK:       bb2:
-; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
+; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4
@@ -707,16 +652,13 @@ define void @multi_bb_pdom_test1(i1 %b) {
 ; CHECK-LABEL: define void @multi_bb_pdom_test1
 ; CHECK-SAME: (i1 [[B:%.*]]) {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[DEST]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
-; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
 ; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]
 ; CHECK:       bb0:
-; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    br label [[BB2:%.*]]
 ; CHECK:       bb1:
-; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    br label [[BB2]]
 ; CHECK:       bb2:
 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 42, [[BB0]] ], [ 41, [[BB1]] ]
@@ -748,17 +690,14 @@ define void @multi_bb_pdom_test2(i1 %b) {
 ; CHECK-LABEL: define void @multi_bb_pdom_test2
 ; CHECK-SAME: (i1 [[B:%.*]]) {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[DEST]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
-; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
-; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       unr1:
-; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    br label [[UNR2:%.*]]
 ; CHECK:       unr2:
-; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
+; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    br label [[UNR1:%.*]]
 ;
   %src = alloca %struct.Foo, align 4
@@ -786,14 +725,10 @@ define void @multi_bb_loop(i32 %n) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[NLT1:%.*]] = icmp slt i32 [[N]], 1
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8
-; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 8
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[DEST]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 0, i32 1, i32 42 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    br i1 [[NLT1]], label [[LOOP_EXIT:%.*]], label [[LOOP_BODY:%.*]]
 ; CHECK:       loop_body:
 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[NEW_I:%.*]], [[LOOP_BODY]] ], [ 1, [[ENTRY:%.*]] ]
-; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DEST]], ptr align 8 [[SRC]], i64 12, i1 false)
 ; CHECK-NEXT:    [[NEW_I]] = add i32 [[I]], 1
 ; CHECK-NEXT:    store i32 [[NEW_I]], ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[IGTN:%.*]] = icmp sgt i32 [[NEW_I]], [[N]]
@@ -822,14 +757,10 @@ loop_exit:
   ret void
 }
 
-; TODO: merge allocas for multi basicblocks, s.t. some modref which is unreachable from copy exists.
 define void @multi_bb_unreachable_modref(i1 %b0) {
 ; CHECK-LABEL: define void @multi_bb_unreachable_modref
 ; CHECK-SAME: (i1 [[B0:%.*]]) {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[DEST]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    br i1 [[B0]], label [[BB0:%.*]], label [[EXIT:%.*]]
@@ -837,9 +768,6 @@ define void @multi_bb_unreachable_modref(i1 %b0) {
 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       bb0:
-; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4
@@ -861,26 +789,19 @@ bb0:
   ret void
 }
 
-; TODO: merge allocas for multi basicblocks, s.t. memcpy doesn't dominate the uses.
 define void @multi_bb_non_dominated(i1 %b0, i1 %b1) {
 ; CHECK-LABEL: define void @multi_bb_non_dominated
 ; CHECK-SAME: (i1 [[B0:%.*]], i1 [[B1:%.*]]) {
 ; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
-; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[DEST]])
 ; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    br i1 [[B0]], label [[BB0:%.*]], label [[BB1:%.*]]
 ; CHECK:       bb0:
-; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
 ; CHECK-NEXT:    br label [[BB2:%.*]]
 ; CHECK:       bb1:
 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
 ; CHECK-NEXT:    br label [[BB2]]
 ; CHECK:       bb2:
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
 ; CHECK-NEXT:    ret void
 ;
   %src = alloca %struct.Foo, align 4

>From 9d39dc126d6714b83251f79bf3452ef902024356 Mon Sep 17 00:00:00 2001
From: Felix Schneider <fx.schn at gmail.com>
Date: Thu, 14 Sep 2023 13:12:24 +0200
Subject: [PATCH 58/86] [mlir][memref] Fix MemrefToLLVM lowering pattern for
 memref.transpose

The lowering pattern to LLVM for memref.transpose has a bug where
instead of transposing from (source) -> (dest) it actually transposes
(dest) -> (source). This patch fixes the bug and updates the test.

Fix https://github.com/llvm/llvm-project/issues/65145

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D159290
---
 mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp  |  9 ++++++---
 .../Conversion/MemRefToLLVM/memref-to-llvm.mlir    | 14 ++++++++++----
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp b/mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp
index 97faefe2cd4d631..159fa1da935700e 100644
--- a/mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp
+++ b/mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp
@@ -1428,11 +1428,14 @@ class TransposeOpLowering : public ConvertOpToLLVMPattern<memref::TransposeOp> {
     // Copy the offset pointer from the old descriptor to the new one.
     targetMemRef.setOffset(rewriter, loc, viewMemRef.offset(rewriter, loc));
 
-    // Iterate over the dimensions and apply size/stride permutation.
+    // Iterate over the dimensions and apply size/stride permutation:
+    // When enumerating the results of the permutation map, the enumeration index
+    // is the index into the target dimensions and the DimExpr points to the
+    // dimension of the source memref.
     for (const auto &en :
          llvm::enumerate(transposeOp.getPermutation().getResults())) {
-      int sourcePos = en.index();
-      int targetPos = en.value().cast<AffineDimExpr>().getPosition();
+      int targetPos = en.index();
+      int sourcePos = en.value().cast<AffineDimExpr>().getPosition();
       targetMemRef.setSize(rewriter, loc, targetPos,
                            viewMemRef.size(rewriter, loc, sourcePos));
       targetMemRef.setStride(rewriter, loc, targetPos,
diff --git a/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir b/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir
index f28f400db7f3c2d..2ece4acc05f5d92 100644
--- a/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir
+++ b/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir
@@ -230,12 +230,18 @@ func.func @address_space(%arg0 : memref<32xf32, affine_map<(d0) -> (d0)>, 7>) {
 //       CHECK:   llvm.insertvalue {{.*}}[0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
 //       CHECK:    llvm.insertvalue {{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
 //       CHECK:    llvm.insertvalue {{.*}}[2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
-//       CHECK:   llvm.extractvalue {{.*}}[3, 0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
-//       CHECK:    llvm.insertvalue {{.*}}[3, 2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
-//       CHECK:   llvm.extractvalue {{.*}}[3, 1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
-//       CHECK:    llvm.insertvalue {{.*}}[3, 0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
 //       CHECK:   llvm.extractvalue {{.*}}[3, 2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
+//       CHECK:    llvm.insertvalue {{.*}}[3, 0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
+//       CHECK:   llvm.extractvalue {{.*}}[4, 2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
+//       CHECK:    llvm.insertvalue {{.*}}[4, 0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
+//       CHECK:   llvm.extractvalue {{.*}}[3, 0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
 //       CHECK:    llvm.insertvalue {{.*}}[3, 1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
+//       CHECK:   llvm.extractvalue {{.*}}[4, 0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
+//       CHECK:    llvm.insertvalue {{.*}}[4, 1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
+//       CHECK:   llvm.extractvalue {{.*}}[3, 1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
+//       CHECK:    llvm.insertvalue {{.*}}[3, 2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
+//       CHECK:   llvm.extractvalue {{.*}}[4, 1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
+//       CHECK:    llvm.insertvalue {{.*}}[4, 2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
 func.func @transpose(%arg0: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>) {
   %0 = memref.transpose %arg0 (i, j, k) -> (k, i, j) : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>> to memref<?x?x?xf32, strided<[1, ?, ?], offset: ?>>
   return

>From f7df98abd0a62adf46c51923e77dc61e69638574 Mon Sep 17 00:00:00 2001
From: Felix Schneider <fx.schn at gmail.com>
Date: Thu, 14 Sep 2023 13:13:29 +0200
Subject: [PATCH 59/86] [mlir][CRunnerUtils] Fix iterators accessing MemRefs
 with non-zero offset

MemRef descriptors contain - among others - a field called `alignedPtr` or `data` and a field called `offset`. The actual buffer of the MemRef starts at `offset` elements after `alignedPtr`. In the CRunnerUtils, there exist helper classes to iterate over MemRefs' elements but the `offset` is not handled consistently so that accessing a MemRef with an `offset` != 0 via an iterator will lead to incorrect results.

The problem is that "offset" can be understood in two ways, firstly as the offset of the beginning of the MemRef with respect to the `alignedPtr`, ie what the `offset` field means in the MemRef descriptor, and secondly as the offset of some element within the MemRef relative to the first element of the MemRef, which could more accurately be called something like `linearIndex`.

The `offset` field within `StridedMemRefIterator` and `DynamicMemRefIterator` are interpreted the first way, therefore the offsets passed to the constructors of these classes need to account for the already existing offset in the descriptor on top of any potential "shift" within the MemRef.
This patch takes care of that and adds some basic tests that catch problems with indexing MemRefs with an `offset`.

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D157008
---
 .../mlir/ExecutionEngine/CRunnerUtils.h       | 10 ++---
 mlir/unittests/ExecutionEngine/CMakeLists.txt |  1 +
 .../ExecutionEngine/DynamicMemRef.cpp         | 27 +++++++++++-
 .../ExecutionEngine/StridedMemRef.cpp         | 41 +++++++++++++++++++
 4 files changed, 73 insertions(+), 6 deletions(-)
 create mode 100644 mlir/unittests/ExecutionEngine/StridedMemRef.cpp

diff --git a/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h b/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h
index e7798b2136af07e..e8f429463cb0b9b 100644
--- a/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h
+++ b/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h
@@ -149,7 +149,7 @@ struct StridedMemRefType {
     return data[curOffset];
   }
 
-  StridedMemrefIterator<T, N> begin() { return {*this}; }
+  StridedMemrefIterator<T, N> begin() { return {*this, offset}; }
   StridedMemrefIterator<T, N> end() { return {*this, -1}; }
 
   // This operator[] is extremely slow and only for sugaring purposes.
@@ -181,7 +181,7 @@ struct StridedMemRefType<T, 1> {
     return (*this)[*indices.begin()];
   }
 
-  StridedMemrefIterator<T, 1> begin() { return {*this}; }
+  StridedMemrefIterator<T, 1> begin() { return {*this, offset}; }
   StridedMemrefIterator<T, 1> end() { return {*this, -1}; }
 
   T &operator[](int64_t idx) { return *(data + offset + idx * strides[0]); }
@@ -202,8 +202,8 @@ struct StridedMemRefType<T, 0> {
     return data[offset];
   }
 
-  StridedMemrefIterator<T, 0> begin() { return {*this}; }
-  StridedMemrefIterator<T, 0> end() { return {*this, 1}; }
+  StridedMemrefIterator<T, 0> begin() { return {*this, offset}; }
+  StridedMemrefIterator<T, 0> end() { return {*this, offset + 1}; }
 };
 
 /// Iterate over all elements in a strided memref.
@@ -364,7 +364,7 @@ class DynamicMemRefType {
     return data[curOffset];
   }
 
-  DynamicMemRefIterator<T> begin() { return {*this}; }
+  DynamicMemRefIterator<T> begin() { return {*this, offset}; }
   DynamicMemRefIterator<T> end() { return {*this, -1}; }
 
   // This operator[] is extremely slow and only for sugaring purposes.
diff --git a/mlir/unittests/ExecutionEngine/CMakeLists.txt b/mlir/unittests/ExecutionEngine/CMakeLists.txt
index 2676cb63cd2407c..383e172aa3f6670 100644
--- a/mlir/unittests/ExecutionEngine/CMakeLists.txt
+++ b/mlir/unittests/ExecutionEngine/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_mlir_unittest(MLIRExecutionEngineTests
   DynamicMemRef.cpp
+  StridedMemRef.cpp
   Invoke.cpp
 )
 get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
diff --git a/mlir/unittests/ExecutionEngine/DynamicMemRef.cpp b/mlir/unittests/ExecutionEngine/DynamicMemRef.cpp
index 5f4f01270246821..78a2440b59cbaab 100644
--- a/mlir/unittests/ExecutionEngine/DynamicMemRef.cpp
+++ b/mlir/unittests/ExecutionEngine/DynamicMemRef.cpp
@@ -96,4 +96,29 @@ TEST(DynamicMemRef, rankThree) {
 
   llvm::SmallVector<int, 24> values(dynamicMemRef.begin(), dynamicMemRef.end());
   EXPECT_THAT(values, ElementsAreArray(data));
-}
\ No newline at end of file
+}
+
+TEST(DynamicMemRef, rankOneWithOffset) {
+  constexpr int offset = 4;
+  std::array<int, 3 + offset> buffer;
+
+  for (size_t i = 0; i < buffer.size(); ++i) {
+    buffer[i] = i;
+  }
+
+  StridedMemRefType<int, 1> memRef;
+  memRef.basePtr = buffer.data();
+  memRef.data = buffer.data();
+  memRef.offset = offset;
+  memRef.sizes[0] = 3;
+  memRef.strides[0] = 1;
+
+  DynamicMemRefType<int> dynamicMemRef(memRef);
+
+  llvm::SmallVector<int, 3> values(dynamicMemRef.begin(), dynamicMemRef.end());
+
+  for (int64_t i = 0; i < 3; ++i) {
+    EXPECT_EQ(values[i], buffer[offset + i]);
+    EXPECT_EQ(*dynamicMemRef[i], buffer[offset + i]);
+  }
+}
diff --git a/mlir/unittests/ExecutionEngine/StridedMemRef.cpp b/mlir/unittests/ExecutionEngine/StridedMemRef.cpp
new file mode 100644
index 000000000000000..f5ffcc8fc911f10
--- /dev/null
+++ b/mlir/unittests/ExecutionEngine/StridedMemRef.cpp
@@ -0,0 +1,41 @@
+//===- StridedMemRef.cpp ----------------------------------------*- C++ -*-===//
+//
+// This file is licensed 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 "mlir/ExecutionEngine/CRunnerUtils.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include "gmock/gmock.h"
+
+using namespace ::mlir;
+using namespace ::testing;
+
+TEST(StridedMemRef, rankOneWithOffset) {
+  std::array<int, 15> data;
+
+  for (size_t i = 0; i < data.size(); ++i) {
+    data[i] = i;
+  }
+
+  StridedMemRefType<int, 1> memRefA;
+  memRefA.basePtr = data.data();
+  memRefA.data = data.data();
+  memRefA.offset = 0;
+  memRefA.sizes[0] = 10;
+  memRefA.strides[0] = 1;
+
+  StridedMemRefType<int, 1> memRefB = memRefA;
+  memRefB.offset = 5;
+
+  llvm::SmallVector<int, 10> valuesA(memRefA.begin(), memRefA.end());
+  llvm::SmallVector<int, 10> valuesB(memRefB.begin(), memRefB.end());
+
+  for (int64_t i = 0; i < 10; ++i) {
+    EXPECT_EQ(valuesA[i], i);
+    EXPECT_EQ(valuesA[i] + 5, valuesB[i]);
+  }
+}

>From 94e7c3a0598c5729b6ed6046f852d31d96b0c3b8 Mon Sep 17 00:00:00 2001
From: Benjamin Kramer <benny.kra at googlemail.com>
Date: Thu, 14 Sep 2023 13:16:09 +0200
Subject: [PATCH 60/86] Turn off memory leaks in unit test

---
 clang/unittests/Serialization/ForceCheckFileInputTest.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
index c1f6d40767751e4..ed0daa43436eb6d 100644
--- a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
+++ b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
@@ -75,6 +75,7 @@ export int aa = 43;
     std::shared_ptr<CompilerInvocation> Invocation =
         createInvocation(Args, CIOpts);
     EXPECT_TRUE(Invocation);
+    Invocation->getFrontendOpts().DisableFree = false;
 
     auto Buf = CIOpts.VFS->getBufferForFile("a.cppm");
     EXPECT_TRUE(Buf);
@@ -113,6 +114,7 @@ export int aa = 43;
     std::shared_ptr<CompilerInvocation> Invocation =
         createInvocation(Args, CIOpts);
     EXPECT_TRUE(Invocation);
+    Invocation->getFrontendOpts().DisableFree = false;
 
     CompilerInstance Clang;
 

>From 4eeee1568dd3d3e80d208f9aba567d0fefae629c Mon Sep 17 00:00:00 2001
From: Felix Schneider <fx.schn at gmail.com>
Date: Thu, 14 Sep 2023 13:17:49 +0200
Subject: [PATCH 61/86] [mlir] [memref] Fix alignment bug in memref.copy
 lowering

memref.copy gets lowered to a function call sometimes, this function
is passed the element size of the memref in bytes as an argument.
The element size passed to the copyMemRef() function call can be
miscalculated if the LLVM IR uses aligned access to the memory.

This can be fixed by using llvm.getelementptr to calculate the element
size natively. This is also done in the other lowering path that lowers
to an intrinsic.

Fix https://github.com/llvm/llvm-project/issues/64072

Reviewed By: ftynse

Differential Revision: https://reviews.llvm.org/D156126
---
 mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp     | 7 +++----
 mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir | 3 ++-
 mlir/test/Conversion/MemRefToLLVM/typed-pointers.mlir | 3 ++-
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp b/mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp
index 159fa1da935700e..61bd23f12601c79 100644
--- a/mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp
+++ b/mlir/lib/Conversion/MemRefToLLVM/MemRefToLLVM.cpp
@@ -879,10 +879,9 @@ struct MemRefCopyOpLowering : public ConvertOpToLLVMPattern<memref::CopyOp> {
     auto sourcePtr = promote(unrankedSource);
     auto targetPtr = promote(unrankedTarget);
 
-    unsigned typeSize =
-        mlir::DataLayout::closest(op).getTypeSize(srcType.getElementType());
-    auto elemSize = rewriter.create<LLVM::ConstantOp>(
-        loc, getIndexType(), rewriter.getIndexAttr(typeSize));
+    // Derive size from llvm.getelementptr which will account for any
+    // potential alignment
+    auto elemSize = getSizeInBytes(loc, srcType.getElementType(), rewriter);
     auto copyFn = LLVM::lookupOrCreateMemRefCopyFn(
         op->getParentOfType<ModuleOp>(), getIndexType(), sourcePtr.getType());
     rewriter.create<LLVM::CallOp>(loc, copyFn,
diff --git a/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir b/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir
index 2ece4acc05f5d92..9e44029ad93bd9c 100644
--- a/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir
+++ b/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir
@@ -558,7 +558,8 @@ func.func @memref_copy_unranked() {
   // CHECK: llvm.store {{%.*}}, [[ALLOCA2]] : !llvm.struct<(i64, ptr)>, !llvm.ptr
   // CHECK: [[ALLOCA3:%.*]] = llvm.alloca [[RANK2]] x !llvm.struct<(i64, ptr)> : (i64) -> !llvm.ptr
   // CHECK: llvm.store [[INSERT2]], [[ALLOCA3]] : !llvm.struct<(i64, ptr)>, !llvm.ptr
-  // CHECK: [[SIZE:%.*]] = llvm.mlir.constant(1 : index) : i64
+  // CHECK: [[SIZEPTR:%.*]] = llvm.getelementptr {{%.*}}[1] : (!llvm.ptr) -> !llvm.ptr, i1
+  // CHECK: [[SIZE:%.*]] = llvm.ptrtoint [[SIZEPTR]] : !llvm.ptr to i64
   // CHECK: llvm.call @memrefCopy([[SIZE]], [[ALLOCA2]], [[ALLOCA3]]) : (i64, !llvm.ptr, !llvm.ptr) -> ()
   // CHECK: llvm.intr.stackrestore [[STACKSAVE]]
   return
diff --git a/mlir/test/Conversion/MemRefToLLVM/typed-pointers.mlir b/mlir/test/Conversion/MemRefToLLVM/typed-pointers.mlir
index 4b077b8e650dcdd..893c359b7b0718e 100644
--- a/mlir/test/Conversion/MemRefToLLVM/typed-pointers.mlir
+++ b/mlir/test/Conversion/MemRefToLLVM/typed-pointers.mlir
@@ -82,7 +82,8 @@ func.func @memref_copy_unranked() {
   // CHECK: llvm.store {{%.*}}, [[ALLOCA2]] : !llvm.ptr<struct<(i64, ptr<i8>)>>
   // CHECK: [[ALLOCA3:%.*]] = llvm.alloca [[RANK2]] x !llvm.struct<(i64, ptr<i8>)> : (i64) -> !llvm.ptr<struct<(i64, ptr<i8>)>>
   // CHECK: llvm.store [[INSERT2]], [[ALLOCA3]] : !llvm.ptr<struct<(i64, ptr<i8>)>>
-  // CHECK: [[SIZE:%.*]] = llvm.mlir.constant(1 : index) : i64
+  // CHECK: [[SIZEPTR:%.*]] = llvm.getelementptr {{%.*}}[1] : (!llvm.ptr<i1>) -> !llvm.ptr<i1>
+  // CHECK: [[SIZE:%.*]] = llvm.ptrtoint [[SIZEPTR]] : !llvm.ptr<i1> to i64
   // CHECK: llvm.call @memrefCopy([[SIZE]], [[ALLOCA2]], [[ALLOCA3]]) : (i64, !llvm.ptr<struct<(i64, ptr<i8>)>>, !llvm.ptr<struct<(i64, ptr<i8>)>>) -> ()
   // CHECK: llvm.intr.stackrestore [[STACKSAVE]]
   return

>From 03f0e03a739c31bfe8016c21373cca25ed83f00c Mon Sep 17 00:00:00 2001
From: Oleg Shyshkov <shyshkov at google.com>
Date: Thu, 14 Sep 2023 13:28:25 +0200
Subject: [PATCH 62/86] [llvm][mlir][bazel] Fix build.

---
 utils/bazel/llvm-project-overlay/mlir/BUILD.bazel                | 1 +
 .../bazel/llvm-project-overlay/third-party/unittest/BUILD.bazel  | 1 +
 2 files changed, 2 insertions(+)

diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
index d4390e7651be0f0..9e37b37b9af089e 100644
--- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
@@ -8000,6 +8000,7 @@ cc_library(
         "//llvm:Core",
         "//llvm:FrontendOpenMP",
         "//llvm:Support",
+        "//llvm:TransformUtils",
     ],
 )
 
diff --git a/utils/bazel/llvm-project-overlay/third-party/unittest/BUILD.bazel b/utils/bazel/llvm-project-overlay/third-party/unittest/BUILD.bazel
index 2a6b81052068e96..86d502ad326ca1a 100644
--- a/utils/bazel/llvm-project-overlay/third-party/unittest/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/third-party/unittest/BUILD.bazel
@@ -52,6 +52,7 @@ cc_library(
     ) + [
     ],
     hdrs = [
+        "googletest/include/gtest/internal/gtest-port.h",
         "googletest/include/gtest/gtest.h",
         "googletest/include/gtest/gtest-spi.h",
     ],

>From 90261279b4392d7aa78ffb4f21264a1e0aa55031 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Thu, 14 Sep 2023 11:08:51 +0200
Subject: [PATCH 63/86] [clang][Interp][NFC] Call delegate() for the RHS of a
 comma op

---
 clang/lib/AST/Interp/ByteCodeExprGen.cpp | 16 +++++++---------
 clang/test/AST/Interp/literals.cpp       |  1 +
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 0ce55f115a1a066..4fa12a66bbf767f 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -243,12 +243,6 @@ bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
   std::optional<PrimType> RT = classify(RHS->getType());
   std::optional<PrimType> T = classify(BO->getType());
 
-  auto Discard = [this, T, BO](bool Result) {
-    if (!Result)
-      return false;
-    return DiscardResult ? this->emitPop(*T, BO) : true;
-  };
-
   // Deal with operations which have composite or void types.
   if (BO->isCommaOp()) {
     if (!this->discard(LHS))
@@ -256,9 +250,7 @@ bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
     if (RHS->getType()->isVoidType())
       return this->discard(RHS);
 
-    // Otherwise, visit RHS and optionally discard its value.
-    return Discard(Initializing ? this->visitInitializer(RHS)
-                                : this->visit(RHS));
+    return this->delegate(RHS);
   }
 
   if (!LT || !RT || !T)
@@ -285,6 +277,12 @@ bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
     return true;
   };
 
+  auto Discard = [this, T, BO](bool Result) {
+    if (!Result)
+      return false;
+    return DiscardResult ? this->emitPop(*T, BO) : true;
+  };
+
   switch (BO->getOpcode()) {
   case BO_EQ:
     return MaybeCastToBool(this->emitEQ(*LT, BO));
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index 69a3edc87b6ec65..dae1d5af6f7ae38 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -929,6 +929,7 @@ namespace DiscardExprs {
     (bool)1;
     __null;
     __builtin_offsetof(A, a);
+    1,2;
 
     return 0;
   }

>From bb54c7cac4aaebe30c548d7f66c896d5d91c67de Mon Sep 17 00:00:00 2001
From: Martin Erhart <merhart at google.com>
Date: Thu, 14 Sep 2023 13:58:30 +0200
Subject: [PATCH 64/86] [mlir][bufferization][NFC] Introduce
 BufferDeallocationOpInterface (#66349)

This new interface allows operations to implement custom handling of ownership values and insertion of dealloc operations which is useful when an op cannot implement the interfaces supported by default by the buffer deallocation pass (e.g., because they are not exactly compatible or because there are some additional semantics to it that would render the default implementations in buffer deallocation invalid, or because no interfaces exist for this
kind of behavior and it's not worth introducing one plus a default implementation in buffer deallocation). Additionally, it can also be used to provide more efficient handling for a specific op than the interface based default
implementations can.
---
 .../IR/BufferDeallocationOpInterface.h        | 217 ++++++++
 .../IR/BufferDeallocationOpInterface.td       |  46 ++
 .../Dialect/Bufferization/IR/CMakeLists.txt   |   1 +
 .../Bufferization/Transforms/BufferUtils.h    |   8 -
 .../BufferDeallocationOpInterfaceImpl.h       |  22 +
 mlir/include/mlir/InitAllDialects.h           |   2 +
 .../IR/BufferDeallocationOpInterface.cpp      | 274 ++++++++++
 .../Dialect/Bufferization/IR/CMakeLists.txt   |   1 +
 .../Bufferization/Transforms/BufferUtils.cpp  |  59 --
 .../Bufferization/Transforms/CMakeLists.txt   |   1 -
 .../OwnershipBasedBufferDeallocation.cpp      | 515 +++---------------
 .../BufferDeallocationOpInterfaceImpl.cpp     | 163 ++++++
 .../ControlFlow/Transforms/CMakeLists.txt     |   3 +-
 .../dealloc-region-branchop-interface.mlir    |   4 +-
 .../llvm-project-overlay/mlir/BUILD.bazel     |   4 +
 15 files changed, 798 insertions(+), 522 deletions(-)
 create mode 100644 mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h
 create mode 100644 mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.td
 create mode 100644 mlir/include/mlir/Dialect/ControlFlow/Transforms/BufferDeallocationOpInterfaceImpl.h
 create mode 100644 mlir/lib/Dialect/Bufferization/IR/BufferDeallocationOpInterface.cpp
 create mode 100644 mlir/lib/Dialect/ControlFlow/Transforms/BufferDeallocationOpInterfaceImpl.cpp

diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h b/mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h
new file mode 100644
index 000000000000000..b88270f1c150a27
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h
@@ -0,0 +1,217 @@
+//===- BufferDeallocationOpInterface.h --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_BUFFERIZATION_IR_BUFFERDEALLOCATIONOPINTERFACE_H_
+#define MLIR_DIALECT_BUFFERIZATION_IR_BUFFERDEALLOCATIONOPINTERFACE_H_
+
+#include "mlir/Analysis/Liveness.h"
+#include "mlir/IR/Operation.h"
+#include "mlir/IR/SymbolTable.h"
+#include "mlir/Support/LLVM.h"
+
+namespace mlir {
+namespace bufferization {
+
+/// Compare two SSA values in a deterministic manner. Two block arguments are
+/// ordered by argument number, block arguments are always less than operation
+/// results, and operation results are ordered by the `isBeforeInBlock` order of
+/// their defining operation.
+struct ValueComparator {
+  bool operator()(const Value &lhs, const Value &rhs) const;
+};
+
+/// This class is used to track the ownership of values. The ownership can
+/// either be not initialized yet ('Uninitialized' state), set to a unique SSA
+/// value which indicates the ownership at runtime (or statically if it is a
+/// constant value) ('Unique' state), or it cannot be represented in a single
+/// SSA value ('Unknown' state). An artificial example of a case where ownership
+/// cannot be represented in a single i1 SSA value could be the following:
+/// `%0 = test.non_deterministic_select %arg0, %arg1 : i32`
+/// Since the operation does not provide us a separate boolean indicator on
+/// which of the two operands was selected, we would need to either insert an
+/// alias check at runtime to determine if `%0` aliases with `%arg0` or `%arg1`,
+/// or insert a `bufferization.clone` operation to get a fresh buffer which we
+/// could assign ownership to.
+///
+/// The three states this class can represent form a lattice on a partial order:
+/// forall X in SSA values. uninitialized < unique(X) < unknown
+/// forall X, Y in SSA values.
+///   unique(X) == unique(Y) iff X and Y always evaluate to the same value
+///   unique(X) != unique(Y) otherwise
+class Ownership {
+public:
+  /// Constructor that creates an 'Uninitialized' ownership. This is needed for
+  /// default-construction when used in DenseMap.
+  Ownership() = default;
+
+  /// Constructor that creates an 'Unique' ownership. This is a non-explicit
+  /// constructor to allow implicit conversion from 'Value'.
+  Ownership(Value indicator);
+
+  /// Get an ownership value in 'Unknown' state.
+  static Ownership getUnknown();
+  /// Get an ownership value in 'Unique' state with 'indicator' as parameter.
+  static Ownership getUnique(Value indicator);
+  /// Get an ownership value in 'Uninitialized' state.
+  static Ownership getUninitialized();
+
+  /// Check if this ownership value is in the 'Uninitialized' state.
+  bool isUninitialized() const;
+  /// Check if this ownership value is in the 'Unique' state.
+  bool isUnique() const;
+  /// Check if this ownership value is in the 'Unknown' state.
+  bool isUnknown() const;
+
+  /// If this ownership value is in 'Unique' state, this function can be used to
+  /// get the indicator parameter. Using this function in any other state is UB.
+  Value getIndicator() const;
+
+  /// Get the join of the two-element subset {this,other}. Does not modify
+  /// 'this'.
+  Ownership getCombined(Ownership other) const;
+
+  /// Modify 'this' ownership to be the join of the current 'this' and 'other'.
+  void combine(Ownership other);
+
+private:
+  enum class State {
+    Uninitialized,
+    Unique,
+    Unknown,
+  };
+
+  // The indicator value is only relevant in the 'Unique' state.
+  Value indicator;
+  State state = State::Uninitialized;
+};
+
+/// Options for BufferDeallocationOpInterface-based buffer deallocation.
+struct DeallocationOptions {
+  // A pass option indicating whether private functions should be modified to
+  // pass the ownership of MemRef values instead of adhering to the function
+  // boundary ABI.
+  bool privateFuncDynamicOwnership = false;
+};
+
+/// This class collects all the state that we need to perform the buffer
+/// deallocation pass with associated helper functions such that we have easy
+/// access to it in the BufferDeallocationOpInterface implementations and the
+/// BufferDeallocation pass.
+class DeallocationState {
+public:
+  DeallocationState(Operation *op);
+
+  // The state should always be passed by reference.
+  DeallocationState(const DeallocationState &) = delete;
+
+  /// Small helper function to update the ownership map by taking the current
+  /// ownership ('Uninitialized' state if not yet present), computing the join
+  /// with the passed ownership and storing this new value in the map. By
+  /// default, it will be performed for the block where 'owned' is defined. If
+  /// the ownership of the given value should be updated for another block, the
+  /// 'block' argument can be explicitly passed.
+  void updateOwnership(Value memref, Ownership ownership,
+                       Block *block = nullptr);
+
+  /// Removes ownerships associated with all values in the passed range for
+  /// 'block'.
+  void resetOwnerships(ValueRange memrefs, Block *block);
+
+  /// Returns the ownership of 'memref' for the given basic block.
+  Ownership getOwnership(Value memref, Block *block) const;
+
+  /// Remember the given 'memref' to deallocate it at the end of the 'block'.
+  void addMemrefToDeallocate(Value memref, Block *block);
+
+  /// Forget about a MemRef that we originally wanted to deallocate at the end
+  /// of 'block', possibly because it already gets deallocated before the end of
+  /// the block.
+  void dropMemrefToDeallocate(Value memref, Block *block);
+
+  /// Return a sorted list of MemRef values which are live at the start of the
+  /// given block.
+  void getLiveMemrefsIn(Block *block, SmallVectorImpl<Value> &memrefs);
+
+  /// Given an SSA value of MemRef type, this function queries the ownership and
+  /// if it is not already in the 'Unique' state, potentially inserts IR to get
+  /// a new SSA value, returned as the first element of the pair, which has
+  /// 'Unique' ownership and can be used instead of the passed Value with the
+  /// the ownership indicator returned as the second element of the pair.
+  std::pair<Value, Value> getMemrefWithUniqueOwnership(OpBuilder &builder,
+                                                       Value memref);
+
+  /// Given two basic blocks and the values passed via block arguments to the
+  /// destination block, compute the list of MemRefs that have to be retained in
+  /// the 'fromBlock' to not run into a use-after-free situation.
+  /// This list consists of the MemRefs in the successor operand list of the
+  /// terminator and the MemRefs in the 'out' set of the liveness analysis
+  /// intersected with the 'in' set of the destination block.
+  ///
+  /// toRetain = filter(successorOperands + (liveOut(fromBlock) insersect
+  ///   liveIn(toBlock)), isMemRef)
+  void getMemrefsToRetain(Block *fromBlock, Block *toBlock,
+                          ValueRange destOperands,
+                          SmallVectorImpl<Value> &toRetain) const;
+
+  /// For a given block, computes the list of MemRefs that potentially need to
+  /// be deallocated at the end of that block. This list also contains values
+  /// that have to be retained (and are thus part of the list returned by
+  /// `getMemrefsToRetain`) and is computed by taking the MemRefs in the 'in'
+  /// set of the liveness analysis of 'block'  appended by the set of MemRefs
+  /// allocated in 'block' itself and subtracted by the set of MemRefs
+  /// deallocated in 'block'.
+  /// Note that we don't have to take the intersection of the liveness 'in' set
+  /// with the 'out' set of the predecessor block because a value that is in the
+  /// 'in' set must be defined in an ancestor block that dominates all direct
+  /// predecessors and thus the 'in' set of this block is a subset of the 'out'
+  /// sets of each predecessor.
+  ///
+  /// memrefs = filter((liveIn(block) U
+  ///   allocated(block) U arguments(block)) \ deallocated(block), isMemRef)
+  ///
+  /// The list of conditions is then populated by querying the internal
+  /// datastructures for the ownership value of that MemRef.
+  LogicalResult
+  getMemrefsAndConditionsToDeallocate(OpBuilder &builder, Location loc,
+                                      Block *block,
+                                      SmallVectorImpl<Value> &memrefs,
+                                      SmallVectorImpl<Value> &conditions) const;
+
+  /// Returns the symbol cache to lookup functions from call operations to check
+  /// attributes on the function operation.
+  SymbolTableCollection *getSymbolTable() { return &symbolTable; }
+
+private:
+  // Symbol cache to lookup functions from call operations to check attributes
+  // on the function operation.
+  SymbolTableCollection symbolTable;
+
+  // Mapping from each SSA value with MemRef type to the associated ownership in
+  // each block.
+  DenseMap<std::pair<Value, Block *>, Ownership> ownershipMap;
+
+  // Collects the list of MemRef values that potentially need to be deallocated
+  // per block. It is also fine (albeit not efficient) to add MemRef values that
+  // don't have to be deallocated, but only when the ownership is not 'Unknown'.
+  DenseMap<Block *, SmallVector<Value>> memrefsToDeallocatePerBlock;
+
+  // The underlying liveness analysis to compute fine grained information about
+  // alloc and dealloc positions.
+  Liveness liveness;
+};
+
+} // namespace bufferization
+} // namespace mlir
+
+//===----------------------------------------------------------------------===//
+// Buffer Deallocation Interface
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h.inc"
+
+#endif // MLIR_DIALECT_BUFFERIZATION_IR_BUFFERDEALLOCATIONOPINTERFACE_H_
diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.td b/mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.td
new file mode 100644
index 000000000000000..c35fe417184ffd4
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.td
@@ -0,0 +1,46 @@
+//===-- BufferDeallocationOpInterface.td -------------------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef BUFFER_DEALLOCATION_OP_INTERFACE
+#define BUFFER_DEALLOCATION_OP_INTERFACE
+
+include "mlir/IR/OpBase.td"
+
+def BufferDeallocationOpInterface :
+    OpInterface<"BufferDeallocationOpInterface"> {
+  let description = [{
+    An op interface for Buffer Deallocation. Ops that implement this interface
+    can provide custom logic for computing the ownership of OpResults, modify
+    the operation to properly pass the ownership values around, and insert
+    `bufferization.dealloc` operations when necessary.
+  }];
+  let cppNamespace = "::mlir::bufferization";
+  let methods = [
+      InterfaceMethod<
+        /*desc=*/[{
+          This method takes the current deallocation state and transformation
+          options and updates the deallocation state as necessary for the
+          operation implementing this interface. It may also insert
+          `bufferization.dealloc` operations and rebuild itself with different
+          result types. For operations implementing this interface all other
+          interface handlers (e.g., default handlers for interfaces like
+          RegionBranchOpInterface, CallOpInterface, etc.) are skipped by the
+          deallocation pass. On success, either the current operation or one of
+          the newly inserted operations is returned from which on the driver
+          should continue the processing. On failure, the deallocation pass
+          will terminate. It is recommended to emit a useful error message in
+          that case.
+        }],
+        /*retType=*/"FailureOr<Operation *>",
+        /*methodName=*/"process",
+        /*args=*/(ins "DeallocationState &":$state,
+                      "const DeallocationOptions &":$options)>
+  ];
+}
+
+#endif  // BUFFER_DEALLOCATION_OP_INTERFACE
diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/Bufferization/IR/CMakeLists.txt
index 440125031b1acc5..38057d4910d2958 100644
--- a/mlir/include/mlir/Dialect/Bufferization/IR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/Bufferization/IR/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_mlir_dialect(BufferizationOps bufferization)
 add_mlir_doc(BufferizationOps BufferizationOps Dialects/ -gen-dialect-doc)
 add_mlir_interface(AllocationOpInterface)
+add_mlir_interface(BufferDeallocationOpInterface)
 add_mlir_interface(BufferizableOpInterface)
 add_mlir_interface(SubsetInsertionOpInterface)
 
diff --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/BufferUtils.h b/mlir/include/mlir/Dialect/Bufferization/Transforms/BufferUtils.h
index 83e55fd70de6bb8..85e9c47ad5302cb 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/BufferUtils.h
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/BufferUtils.h
@@ -121,14 +121,6 @@ class BufferPlacementTransformationBase {
   Liveness liveness;
 };
 
-/// Compare two SSA values in a deterministic manner. Two block arguments are
-/// ordered by argument number, block arguments are always less than operation
-/// results, and operation results are ordered by the `isBeforeInBlock` order of
-/// their defining operation.
-struct ValueComparator {
-  bool operator()(const Value &lhs, const Value &rhs) const;
-};
-
 // Create a global op for the given tensor-valued constant in the program.
 // Globals are created lazily at the top of the enclosing ModuleOp with pretty
 // names. Duplicates are avoided.
diff --git a/mlir/include/mlir/Dialect/ControlFlow/Transforms/BufferDeallocationOpInterfaceImpl.h b/mlir/include/mlir/Dialect/ControlFlow/Transforms/BufferDeallocationOpInterfaceImpl.h
new file mode 100644
index 000000000000000..c34ebd0494fec89
--- /dev/null
+++ b/mlir/include/mlir/Dialect/ControlFlow/Transforms/BufferDeallocationOpInterfaceImpl.h
@@ -0,0 +1,22 @@
+//===- BufferDeallocationOpInterfaceImpl.h ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_CONTROLFLOW_TRANSFORMS_BUFFERDEALLOCATIONOPINTERFACEIMPL_H
+#define MLIR_DIALECT_CONTROLFLOW_TRANSFORMS_BUFFERDEALLOCATIONOPINTERFACEIMPL_H
+
+namespace mlir {
+
+class DialectRegistry;
+
+namespace cf {
+void registerBufferDeallocationOpInterfaceExternalModels(
+    DialectRegistry &registry);
+} // namespace cf
+} // namespace mlir
+
+#endif // MLIR_DIALECT_CONTROLFLOW_TRANSFORMS_BUFFERDEALLOCATIONOPINTERFACEIMPL_H
diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h
index 6eaa0cc0d46aadb..ee91bfa57d12a39 100644
--- a/mlir/include/mlir/InitAllDialects.h
+++ b/mlir/include/mlir/InitAllDialects.h
@@ -29,6 +29,7 @@
 #include "mlir/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.h"
 #include "mlir/Dialect/Complex/IR/Complex.h"
 #include "mlir/Dialect/ControlFlow/IR/ControlFlow.h"
+#include "mlir/Dialect/ControlFlow/Transforms/BufferDeallocationOpInterfaceImpl.h"
 #include "mlir/Dialect/ControlFlow/Transforms/BufferizableOpInterfaceImpl.h"
 #include "mlir/Dialect/DLTI/DLTI.h"
 #include "mlir/Dialect/EmitC/IR/EmitC.h"
@@ -138,6 +139,7 @@ inline void registerAllDialects(DialectRegistry &registry) {
       registry);
   builtin::registerCastOpInterfaceExternalModels(registry);
   cf::registerBufferizableOpInterfaceExternalModels(registry);
+  cf::registerBufferDeallocationOpInterfaceExternalModels(registry);
   linalg::registerBufferizableOpInterfaceExternalModels(registry);
   linalg::registerTilingInterfaceExternalModels(registry);
   linalg::registerValueBoundsOpInterfaceExternalModels(registry);
diff --git a/mlir/lib/Dialect/Bufferization/IR/BufferDeallocationOpInterface.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferDeallocationOpInterface.cpp
new file mode 100644
index 000000000000000..2314cee2ff2c158
--- /dev/null
+++ b/mlir/lib/Dialect/Bufferization/IR/BufferDeallocationOpInterface.cpp
@@ -0,0 +1,274 @@
+//===- BufferDeallocationOpInterface.cpp ----------------------------------===//
+//
+// 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 "mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h"
+#include "mlir/Dialect/Bufferization/IR/Bufferization.h"
+#include "mlir/Dialect/MemRef/IR/MemRef.h"
+#include "mlir/IR/AsmState.h"
+#include "mlir/IR/Matchers.h"
+#include "mlir/IR/Operation.h"
+#include "mlir/IR/TypeUtilities.h"
+#include "mlir/IR/Value.h"
+#include "llvm/ADT/SetOperations.h"
+
+//===----------------------------------------------------------------------===//
+// BufferDeallocationOpInterface
+//===----------------------------------------------------------------------===//
+
+namespace mlir {
+namespace bufferization {
+
+#include "mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.cpp.inc"
+
+} // namespace bufferization
+} // namespace mlir
+
+using namespace mlir;
+using namespace bufferization;
+
+//===----------------------------------------------------------------------===//
+// Helpers
+//===----------------------------------------------------------------------===//
+
+static Value buildBoolValue(OpBuilder &builder, Location loc, bool value) {
+  return builder.create<arith::ConstantOp>(loc, builder.getBoolAttr(value));
+}
+
+static bool isMemref(Value v) { return v.getType().isa<BaseMemRefType>(); }
+
+//===----------------------------------------------------------------------===//
+// Ownership
+//===----------------------------------------------------------------------===//
+
+Ownership::Ownership(Value indicator)
+    : indicator(indicator), state(State::Unique) {}
+
+Ownership Ownership::getUnknown() {
+  Ownership unknown;
+  unknown.indicator = Value();
+  unknown.state = State::Unknown;
+  return unknown;
+}
+Ownership Ownership::getUnique(Value indicator) { return Ownership(indicator); }
+Ownership Ownership::getUninitialized() { return Ownership(); }
+
+bool Ownership::isUninitialized() const {
+  return state == State::Uninitialized;
+}
+bool Ownership::isUnique() const { return state == State::Unique; }
+bool Ownership::isUnknown() const { return state == State::Unknown; }
+
+Value Ownership::getIndicator() const {
+  assert(isUnique() && "must have unique ownership to get the indicator");
+  return indicator;
+}
+
+Ownership Ownership::getCombined(Ownership other) const {
+  if (other.isUninitialized())
+    return *this;
+  if (isUninitialized())
+    return other;
+
+  if (!isUnique() || !other.isUnique())
+    return getUnknown();
+
+  // Since we create a new constant i1 value for (almost) each use-site, we
+  // should compare the actual value rather than just the SSA Value to avoid
+  // unnecessary invalidations.
+  if (isEqualConstantIntOrValue(indicator, other.indicator))
+    return *this;
+
+  // Return the join of the lattice if the indicator of both ownerships cannot
+  // be merged.
+  return getUnknown();
+}
+
+void Ownership::combine(Ownership other) { *this = getCombined(other); }
+
+//===----------------------------------------------------------------------===//
+// DeallocationState
+//===----------------------------------------------------------------------===//
+
+DeallocationState::DeallocationState(Operation *op) : liveness(op) {}
+
+void DeallocationState::updateOwnership(Value memref, Ownership ownership,
+                                        Block *block) {
+  // In most cases we care about the block where the value is defined.
+  if (block == nullptr)
+    block = memref.getParentBlock();
+
+  // Update ownership of current memref itself.
+  ownershipMap[{memref, block}].combine(ownership);
+}
+
+void DeallocationState::resetOwnerships(ValueRange memrefs, Block *block) {
+  for (Value val : memrefs)
+    ownershipMap[{val, block}] = Ownership::getUninitialized();
+}
+
+Ownership DeallocationState::getOwnership(Value memref, Block *block) const {
+  return ownershipMap.lookup({memref, block});
+}
+
+void DeallocationState::addMemrefToDeallocate(Value memref, Block *block) {
+  memrefsToDeallocatePerBlock[block].push_back(memref);
+}
+
+void DeallocationState::dropMemrefToDeallocate(Value memref, Block *block) {
+  llvm::erase_if(memrefsToDeallocatePerBlock[block],
+                 [&](const auto &mr) { return mr == memref; });
+}
+
+void DeallocationState::getLiveMemrefsIn(Block *block,
+                                         SmallVectorImpl<Value> &memrefs) {
+  SmallVector<Value> liveMemrefs(
+      llvm::make_filter_range(liveness.getLiveIn(block), isMemref));
+  llvm::sort(liveMemrefs, ValueComparator());
+  memrefs.append(liveMemrefs);
+}
+
+std::pair<Value, Value>
+DeallocationState::getMemrefWithUniqueOwnership(OpBuilder &builder,
+                                                Value memref) {
+  auto iter = ownershipMap.find({memref, memref.getParentBlock()});
+  assert(iter != ownershipMap.end() &&
+         "Value must already have been registered in the ownership map");
+
+  Ownership ownership = iter->second;
+  if (ownership.isUnique())
+    return {memref, ownership.getIndicator()};
+
+  // Instead of inserting a clone operation we could also insert a dealloc
+  // operation earlier in the block and use the updated ownerships returned by
+  // the op for the retained values. Alternatively, we could insert code to
+  // check aliasing at runtime and use this information to combine two unique
+  // ownerships more intelligently to not end up with an 'Unknown' ownership in
+  // the first place.
+  auto cloneOp =
+      builder.create<bufferization::CloneOp>(memref.getLoc(), memref);
+  Value condition = buildBoolValue(builder, memref.getLoc(), true);
+  Value newMemref = cloneOp.getResult();
+  updateOwnership(newMemref, condition);
+  memrefsToDeallocatePerBlock[newMemref.getParentBlock()].push_back(newMemref);
+  return {newMemref, condition};
+}
+
+void DeallocationState::getMemrefsToRetain(
+    Block *fromBlock, Block *toBlock, ValueRange destOperands,
+    SmallVectorImpl<Value> &toRetain) const {
+  for (Value operand : destOperands) {
+    if (!isMemref(operand))
+      continue;
+    toRetain.push_back(operand);
+  }
+
+  SmallPtrSet<Value, 16> liveOut;
+  for (auto val : liveness.getLiveOut(fromBlock))
+    if (isMemref(val))
+      liveOut.insert(val);
+
+  if (toBlock)
+    llvm::set_intersect(liveOut, liveness.getLiveIn(toBlock));
+
+  // liveOut has non-deterministic order because it was constructed by iterating
+  // over a hash-set.
+  SmallVector<Value> retainedByLiveness(liveOut.begin(), liveOut.end());
+  std::sort(retainedByLiveness.begin(), retainedByLiveness.end(),
+            ValueComparator());
+  toRetain.append(retainedByLiveness);
+}
+
+LogicalResult DeallocationState::getMemrefsAndConditionsToDeallocate(
+    OpBuilder &builder, Location loc, Block *block,
+    SmallVectorImpl<Value> &memrefs, SmallVectorImpl<Value> &conditions) const {
+
+  for (auto [i, memref] :
+       llvm::enumerate(memrefsToDeallocatePerBlock.lookup(block))) {
+    Ownership ownership = ownershipMap.lookup({memref, block});
+    if (!ownership.isUnique())
+      return emitError(memref.getLoc(),
+                       "MemRef value does not have valid ownership");
+
+    // Simply cast unranked MemRefs to ranked memrefs with 0 dimensions such
+    // that we can call extract_strided_metadata on it.
+    if (auto unrankedMemRefTy = dyn_cast<UnrankedMemRefType>(memref.getType()))
+      memref = builder.create<memref::ReinterpretCastOp>(
+          loc, MemRefType::get({}, unrankedMemRefTy.getElementType()), memref,
+          0, SmallVector<int64_t>{}, SmallVector<int64_t>{});
+
+    // Use the `memref.extract_strided_metadata` operation to get the base
+    // memref. This is needed because the same MemRef that was produced by the
+    // alloc operation has to be passed to the dealloc operation. Passing
+    // subviews, etc. to a dealloc operation is not allowed.
+    memrefs.push_back(
+        builder.create<memref::ExtractStridedMetadataOp>(loc, memref)
+            .getResult(0));
+    conditions.push_back(ownership.getIndicator());
+  }
+
+  return success();
+}
+
+//===----------------------------------------------------------------------===//
+// ValueComparator
+//===----------------------------------------------------------------------===//
+
+bool ValueComparator::operator()(const Value &lhs, const Value &rhs) const {
+  if (lhs == rhs)
+    return false;
+
+  // Block arguments are less than results.
+  bool lhsIsBBArg = lhs.isa<BlockArgument>();
+  if (lhsIsBBArg != rhs.isa<BlockArgument>()) {
+    return lhsIsBBArg;
+  }
+
+  Region *lhsRegion;
+  Region *rhsRegion;
+  if (lhsIsBBArg) {
+    auto lhsBBArg = llvm::cast<BlockArgument>(lhs);
+    auto rhsBBArg = llvm::cast<BlockArgument>(rhs);
+    if (lhsBBArg.getArgNumber() != rhsBBArg.getArgNumber()) {
+      return lhsBBArg.getArgNumber() < rhsBBArg.getArgNumber();
+    }
+    lhsRegion = lhsBBArg.getParentRegion();
+    rhsRegion = rhsBBArg.getParentRegion();
+    assert(lhsRegion != rhsRegion &&
+           "lhsRegion == rhsRegion implies lhs == rhs");
+  } else if (lhs.getDefiningOp() == rhs.getDefiningOp()) {
+    return llvm::cast<OpResult>(lhs).getResultNumber() <
+           llvm::cast<OpResult>(rhs).getResultNumber();
+  } else {
+    lhsRegion = lhs.getDefiningOp()->getParentRegion();
+    rhsRegion = rhs.getDefiningOp()->getParentRegion();
+    if (lhsRegion == rhsRegion) {
+      return lhs.getDefiningOp()->isBeforeInBlock(rhs.getDefiningOp());
+    }
+  }
+
+  // lhsRegion != rhsRegion, so if we look at their ancestor chain, they
+  // - have different heights
+  // - or there's a spot where their region numbers differ
+  // - or their parent regions are the same and their parent ops are
+  //   different.
+  while (lhsRegion && rhsRegion) {
+    if (lhsRegion->getRegionNumber() != rhsRegion->getRegionNumber()) {
+      return lhsRegion->getRegionNumber() < rhsRegion->getRegionNumber();
+    }
+    if (lhsRegion->getParentRegion() == rhsRegion->getParentRegion()) {
+      return lhsRegion->getParentOp()->isBeforeInBlock(
+          rhsRegion->getParentOp());
+    }
+    lhsRegion = lhsRegion->getParentRegion();
+    rhsRegion = rhsRegion->getParentRegion();
+  }
+  if (rhsRegion)
+    return true;
+  assert(lhsRegion && "this should only happen if lhs == rhs");
+  return false;
+}
diff --git a/mlir/lib/Dialect/Bufferization/IR/CMakeLists.txt b/mlir/lib/Dialect/Bufferization/IR/CMakeLists.txt
index 3fd9221624d0f88..b1940e40ba34114 100644
--- a/mlir/lib/Dialect/Bufferization/IR/CMakeLists.txt
+++ b/mlir/lib/Dialect/Bufferization/IR/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_mlir_dialect_library(MLIRBufferizationDialect
   AllocationOpInterface.cpp
   BufferizableOpInterface.cpp
+  BufferDeallocationOpInterface.cpp
   BufferizationOps.cpp
   BufferizationDialect.cpp
   SubsetInsertionOpInterface.cpp
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/BufferUtils.cpp b/mlir/lib/Dialect/Bufferization/Transforms/BufferUtils.cpp
index b8fd99a5541242f..119801f9cc92f32 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/BufferUtils.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/BufferUtils.cpp
@@ -202,62 +202,3 @@ bufferization::getGlobalFor(arith::ConstantOp constantOp, uint64_t alignment,
   global->moveBefore(&moduleOp.front());
   return global;
 }
-
-//===----------------------------------------------------------------------===//
-// ValueComparator
-//===----------------------------------------------------------------------===//
-
-bool ValueComparator::operator()(const Value &lhs, const Value &rhs) const {
-  if (lhs == rhs)
-    return false;
-
-  // Block arguments are less than results.
-  bool lhsIsBBArg = lhs.isa<BlockArgument>();
-  if (lhsIsBBArg != rhs.isa<BlockArgument>()) {
-    return lhsIsBBArg;
-  }
-
-  Region *lhsRegion;
-  Region *rhsRegion;
-  if (lhsIsBBArg) {
-    auto lhsBBArg = llvm::cast<BlockArgument>(lhs);
-    auto rhsBBArg = llvm::cast<BlockArgument>(rhs);
-    if (lhsBBArg.getArgNumber() != rhsBBArg.getArgNumber()) {
-      return lhsBBArg.getArgNumber() < rhsBBArg.getArgNumber();
-    }
-    lhsRegion = lhsBBArg.getParentRegion();
-    rhsRegion = rhsBBArg.getParentRegion();
-    assert(lhsRegion != rhsRegion &&
-           "lhsRegion == rhsRegion implies lhs == rhs");
-  } else if (lhs.getDefiningOp() == rhs.getDefiningOp()) {
-    return llvm::cast<OpResult>(lhs).getResultNumber() <
-           llvm::cast<OpResult>(rhs).getResultNumber();
-  } else {
-    lhsRegion = lhs.getDefiningOp()->getParentRegion();
-    rhsRegion = rhs.getDefiningOp()->getParentRegion();
-    if (lhsRegion == rhsRegion) {
-      return lhs.getDefiningOp()->isBeforeInBlock(rhs.getDefiningOp());
-    }
-  }
-
-  // lhsRegion != rhsRegion, so if we look at their ancestor chain, they
-  // - have different heights
-  // - or there's a spot where their region numbers differ
-  // - or their parent regions are the same and their parent ops are
-  //   different.
-  while (lhsRegion && rhsRegion) {
-    if (lhsRegion->getRegionNumber() != rhsRegion->getRegionNumber()) {
-      return lhsRegion->getRegionNumber() < rhsRegion->getRegionNumber();
-    }
-    if (lhsRegion->getParentRegion() == rhsRegion->getParentRegion()) {
-      return lhsRegion->getParentOp()->isBeforeInBlock(
-          rhsRegion->getParentOp());
-    }
-    lhsRegion = lhsRegion->getParentRegion();
-    rhsRegion = rhsRegion->getParentRegion();
-  }
-  if (rhsRegion)
-    return true;
-  assert(lhsRegion && "this should only happen if lhs == rhs");
-  return false;
-}
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt b/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt
index cbbfe7a81205857..ed8dbd57bf40ba1 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt
@@ -35,7 +35,6 @@ add_mlir_dialect_library(MLIRBufferizationTransforms
   MLIRPass
   MLIRTensorDialect
   MLIRSCFDialect
-  MLIRControlFlowDialect
   MLIRSideEffectInterfaces
   MLIRTransforms
   MLIRViewLikeInterface
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp
index eaced7202f4e606..d4b8e0dff67bae4 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp
@@ -18,16 +18,14 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h"
 #include "mlir/Dialect/Bufferization/IR/Bufferization.h"
-#include "mlir/Dialect/Bufferization/Transforms/BufferUtils.h"
 #include "mlir/Dialect/Bufferization/Transforms/Passes.h"
-#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
 #include "mlir/Dialect/Func/IR/FuncOps.h"
 #include "mlir/Dialect/MemRef/IR/MemRef.h"
 #include "mlir/Dialect/SCF/IR/SCF.h"
 #include "mlir/IR/Iterators.h"
 #include "mlir/Interfaces/ControlFlowInterfaces.h"
-#include "llvm/ADT/SetOperations.h"
 
 namespace mlir {
 namespace bufferization {
@@ -137,103 +135,13 @@ class Backedges {
 //===----------------------------------------------------------------------===//
 
 namespace {
-/// This class is used to track the ownership of values. The ownership can
-/// either be not initialized yet ('Uninitialized' state), set to a unique SSA
-/// value which indicates the ownership at runtime (or statically if it is a
-/// constant value) ('Unique' state), or it cannot be represented in a single
-/// SSA value ('Unknown' state). An artificial example of a case where ownership
-/// cannot be represented in a single i1 SSA value could be the following:
-/// `%0 = test.non_deterministic_select %arg0, %arg1 : i32`
-/// Since the operation does not provide us a separate boolean indicator on
-/// which of the two operands was selected, we would need to either insert an
-/// alias check at runtime to determine if `%0` aliases with `%arg0` or `%arg1`,
-/// or insert a `bufferization.clone` operation to get a fresh buffer which we
-/// could assign ownership to.
-///
-/// The three states this class can represent form a lattice on a partial order:
-/// forall X in SSA values. uninitialized < unique(X) < unknown
-/// forall X, Y in SSA values.
-///   unique(X) == unique(Y) iff X and Y always evaluate to the same value
-///   unique(X) != unique(Y) otherwise
-class Ownership {
-public:
-  /// Constructor that creates an 'Uninitialized' ownership. This is needed for
-  /// default-construction when used in DenseMap.
-  Ownership() = default;
-
-  /// Constructor that creates an 'Unique' ownership. This is a non-explicit
-  /// constructor to allow implicit conversion from 'Value'.
-  Ownership(Value indicator) : indicator(indicator), state(State::Unique) {}
-
-  /// Get an ownership value in 'Unknown' state.
-  static Ownership getUnknown() {
-    Ownership unknown;
-    unknown.indicator = Value();
-    unknown.state = State::Unknown;
-    return unknown;
-  }
-  /// Get an ownership value in 'Unique' state with 'indicator' as parameter.
-  static Ownership getUnique(Value indicator) { return Ownership(indicator); }
-  /// Get an ownership value in 'Uninitialized' state.
-  static Ownership getUninitialized() { return Ownership(); }
-
-  /// Check if this ownership value is in the 'Uninitialized' state.
-  bool isUninitialized() const { return state == State::Uninitialized; }
-  /// Check if this ownership value is in the 'Unique' state.
-  bool isUnique() const { return state == State::Unique; }
-  /// Check if this ownership value is in the 'Unknown' state.
-  bool isUnknown() const { return state == State::Unknown; }
-
-  /// If this ownership value is in 'Unique' state, this function can be used to
-  /// get the indicator parameter. Using this function in any other state is UB.
-  Value getIndicator() const {
-    assert(isUnique() && "must have unique ownership to get the indicator");
-    return indicator;
-  }
-
-  /// Get the join of the two-element subset {this,other}. Does not modify
-  /// 'this'.
-  Ownership getCombined(Ownership other) const {
-    if (other.isUninitialized())
-      return *this;
-    if (isUninitialized())
-      return other;
-
-    if (!isUnique() || !other.isUnique())
-      return getUnknown();
-
-    // Since we create a new constant i1 value for (almost) each use-site, we
-    // should compare the actual value rather than just the SSA Value to avoid
-    // unnecessary invalidations.
-    if (isEqualConstantIntOrValue(indicator, other.indicator))
-      return *this;
-
-    // Return the join of the lattice if the indicator of both ownerships cannot
-    // be merged.
-    return getUnknown();
-  }
-
-  /// Modify 'this' ownership to be the join of the current 'this' and 'other'.
-  void combine(Ownership other) { *this = getCombined(other); }
-
-private:
-  enum class State {
-    Uninitialized,
-    Unique,
-    Unknown,
-  };
-
-  // The indicator value is only relevant in the 'Unique' state.
-  Value indicator;
-  State state = State::Uninitialized;
-};
-
 /// The buffer deallocation transformation which ensures that all allocs in the
 /// program have a corresponding de-allocation.
 class BufferDeallocation {
 public:
   BufferDeallocation(Operation *op, bool privateFuncDynamicOwnership)
-      : liveness(op), privateFuncDynamicOwnership(privateFuncDynamicOwnership) {
+      : state(op) {
+    options.privateFuncDynamicOwnership = privateFuncDynamicOwnership;
   }
 
   /// Performs the actual placement/creation of all dealloc operations.
@@ -291,57 +199,17 @@ class BufferDeallocation {
 
   /// Apply all supported interface handlers to the given op.
   FailureOr<Operation *> handleAllInterfaces(Operation *op) {
+    if (auto deallocOpInterface = dyn_cast<BufferDeallocationOpInterface>(op))
+      return deallocOpInterface.process(state, options);
+
     if (failed(verifyOperationPreconditions(op)))
       return failure();
 
     return handleOp<MemoryEffectOpInterface, RegionBranchOpInterface,
-                    CallOpInterface, BranchOpInterface, cf::CondBranchOp,
+                    CallOpInterface, BranchOpInterface,
                     RegionBranchTerminatorOpInterface>(op);
   }
 
-  /// While CondBranchOp also implements the BranchOpInterface, we add a
-  /// special-case implementation here because the BranchOpInterface does not
-  /// offer all of the functionality we need to insert dealloc operations in an
-  /// efficient way. More precisely, there is no way to extract the branch
-  /// condition without casting to CondBranchOp specifically. It would still be
-  /// possible to implement deallocation for cases where we don't know to which
-  /// successor the terminator branches before the actual branch happens by
-  /// inserting auxiliary blocks and putting the dealloc op there, however, this
-  /// can lead to less efficient code.
-  /// This function inserts two dealloc operations (one for each successor) and
-  /// adjusts the dealloc conditions according to the branch condition, then the
-  /// ownerships of the retained MemRefs are updated by combining the result
-  /// values of the two dealloc operations.
-  ///
-  /// Example:
-  /// ```
-  /// ^bb1:
-  ///   <more ops...>
-  ///   cf.cond_br cond, ^bb2(<forward-to-bb2>), ^bb3(<forward-to-bb2>)
-  /// ```
-  /// becomes
-  /// ```
-  /// // let (m, c) = getMemrefsAndConditionsToDeallocate(bb1)
-  /// // let r0 = getMemrefsToRetain(bb1, bb2, <forward-to-bb2>)
-  /// // let r1 = getMemrefsToRetain(bb1, bb3, <forward-to-bb3>)
-  /// ^bb1:
-  ///   <more ops...>
-  ///   let thenCond = map(c, (c) -> arith.andi cond, c)
-  ///   let elseCond = map(c, (c) -> arith.andi (arith.xori cond, true), c)
-  ///   o0 = bufferization.dealloc m if thenCond retain r0
-  ///   o1 = bufferization.dealloc m if elseCond retain r1
-  ///   // replace ownership(r0) with o0 element-wise
-  ///   // replace ownership(r1) with o1 element-wise
-  ///   // let ownership0 := (r) -> o in o0 corresponding to r
-  ///   // let ownership1 := (r) -> o in o1 corresponding to r
-  ///   // let cmn := intersection(r0, r1)
-  ///   foreach (a, b) in zip(map(cmn, ownership0), map(cmn, ownership1)):
-  ///     forall r in r0: replace ownership0(r) with arith.select cond, a, b)
-  ///     forall r in r1: replace ownership1(r) with arith.select cond, a, b)
-  ///   cf.cond_br cond, ^bb2(<forward-to-bb2>, o0), ^bb3(<forward-to-bb3>, o1)
-  /// ```
-  FailureOr<Operation *> handleInterface(cf::CondBranchOp op);
-
   /// Make sure that for each forwarded MemRef value, an ownership indicator
   /// `i1` value is forwarded as well such that the successor block knows
   /// whether the MemRef has to be deallocated.
@@ -492,18 +360,6 @@ class BufferDeallocation {
   /// this function has to be called on blocks in a region in dominance order.
   LogicalResult deallocate(Block *block);
 
-  /// Small helper function to update the ownership map by taking the current
-  /// ownership ('Uninitialized' state if not yet present), computing the join
-  /// with the passed ownership and storing this new value in the map. By
-  /// default, it will be performed for the block where 'owned' is defined. If
-  /// the ownership of the given value should be updated for another block, the
-  /// 'block' argument can be explicitly passed.
-  void joinOwnership(Value owned, Ownership ownership, Block *block = nullptr);
-
-  /// Removes ownerships associated with all values in the passed range for
-  /// 'block'.
-  void clearOwnershipOf(ValueRange values, Block *block);
-
   /// After all relevant interfaces of an operation have been processed by the
   /// 'handleInterface' functions, this function sets the ownership of operation
   /// results that have not been set yet by the 'handleInterface' functions. It
@@ -517,51 +373,6 @@ class BufferDeallocation {
   /// operations, etc.).
   void populateRemainingOwnerships(Operation *op);
 
-  /// Given two basic blocks and the values passed via block arguments to the
-  /// destination block, compute the list of MemRefs that have to be retained in
-  /// the 'fromBlock' to not run into a use-after-free situation.
-  /// This list consists of the MemRefs in the successor operand list of the
-  /// terminator and the MemRefs in the 'out' set of the liveness analysis
-  /// intersected with the 'in' set of the destination block.
-  ///
-  /// toRetain = filter(successorOperands + (liveOut(fromBlock) insersect
-  ///   liveIn(toBlock)), isMemRef)
-  void getMemrefsToRetain(Block *fromBlock, Block *toBlock,
-                          ValueRange destOperands,
-                          SmallVectorImpl<Value> &toRetain) const;
-
-  /// For a given block, computes the list of MemRefs that potentially need to
-  /// be deallocated at the end of that block. This list also contains values
-  /// that have to be retained (and are thus part of the list returned by
-  /// `getMemrefsToRetain`) and is computed by taking the MemRefs in the 'in'
-  /// set of the liveness analysis of 'block'  appended by the set of MemRefs
-  /// allocated in 'block' itself and subtracted by the set of MemRefs
-  /// deallocated in 'block'.
-  /// Note that we don't have to take the intersection of the liveness 'in' set
-  /// with the 'out' set of the predecessor block because a value that is in the
-  /// 'in' set must be defined in an ancestor block that dominates all direct
-  /// predecessors and thus the 'in' set of this block is a subset of the 'out'
-  /// sets of each predecessor.
-  ///
-  /// memrefs = filter((liveIn(block) U
-  ///   allocated(block) U arguments(block)) \ deallocated(block), isMemRef)
-  ///
-  /// The list of conditions is then populated by querying the internal
-  /// datastructures for the ownership value of that MemRef.
-  LogicalResult
-  getMemrefsAndConditionsToDeallocate(OpBuilder &builder, Location loc,
-                                      Block *block,
-                                      SmallVectorImpl<Value> &memrefs,
-                                      SmallVectorImpl<Value> &conditions) const;
-
-  /// Given an SSA value of MemRef type, this function queries the ownership and
-  /// if it is not already in the 'Unique' state, potentially inserts IR to get
-  /// a new SSA value, returned as the first element of the pair, which has
-  /// 'Unique' ownership and can be used instead of the passed Value with the
-  /// the ownership indicator returned as the second element of the pair.
-  std::pair<Value, Value> getMemrefWithUniqueOwnership(OpBuilder &builder,
-                                                       Value memref);
-
   /// Given an SSA value of MemRef type, returns the same of a new SSA value
   /// which has 'Unique' ownership where the ownership indicator is guaranteed
   /// to be always 'true'.
@@ -602,27 +413,13 @@ class BufferDeallocation {
   static LogicalResult updateFunctionSignature(FunctionOpInterface op);
 
 private:
-  // Mapping from each SSA value with MemRef type to the associated ownership in
-  // each block.
-  DenseMap<std::pair<Value, Block *>, Ownership> ownershipMap;
-
-  // Collects the list of MemRef values that potentially need to be deallocated
-  // per block. It is also fine (albeit not efficient) to add MemRef values that
-  // don't have to be deallocated, but only when the ownership is not 'Unknown'.
-  DenseMap<Block *, SmallVector<Value>> memrefsToDeallocatePerBlock;
-
-  // Symbol cache to lookup functions from call operations to check attributes
-  // on the function operation.
-  SymbolTableCollection symbolTable;
-
-  // The underlying liveness analysis to compute fine grained information about
-  // alloc and dealloc positions.
-  Liveness liveness;
-
-  // A pass option indicating whether private functions should be modified to
-  // pass the ownership of MemRef values instead of adhering to the function
-  // boundary ABI.
-  bool privateFuncDynamicOwnership;
+  ///  Collects all analysis state and including liveness, caches, ownerships of
+  ///  already processed values and operations, and the MemRefs that have to be
+  ///  deallocated at the end of each block.
+  DeallocationState state;
+
+  /// Collects all pass options in a single place.
+  DeallocationOptions options;
 };
 
 } // namespace
@@ -631,22 +428,6 @@ class BufferDeallocation {
 // BufferDeallocation Implementation
 //===----------------------------------------------------------------------===//
 
-void BufferDeallocation::joinOwnership(Value owned, Ownership ownership,
-                                       Block *block) {
-  // In most cases we care about the block where the value is defined.
-  if (block == nullptr)
-    block = owned.getParentBlock();
-
-  // Update ownership of current memref itself.
-  ownershipMap[{owned, block}].combine(ownership);
-}
-
-void BufferDeallocation::clearOwnershipOf(ValueRange values, Block *block) {
-  for (Value val : values) {
-    ownershipMap[{val, block}] = Ownership::getUninitialized();
-  }
-}
-
 static bool regionOperatesOnMemrefValues(Region &region) {
   WalkResult result = region.walk([](Block *block) {
     if (llvm::any_of(block->getArguments(), isMemref))
@@ -717,10 +498,10 @@ LogicalResult BufferDeallocation::verifyOperationPreconditions(Operation *op) {
 
     // We only support terminators with 0 or 1 successors for now and
     // special-case the conditional branch op.
-    if (op->getSuccessors().size() > 1 && !isa<cf::CondBranchOp>(op))
+    if (op->getSuccessors().size() > 1)
 
       return op->emitError("Terminators with more than one successor "
-                           "are not supported (except cf.cond_br)!");
+                           "are not supported!");
   }
 
   return success();
@@ -776,80 +557,26 @@ LogicalResult BufferDeallocation::deallocate(FunctionOpInterface op) {
   return updateFunctionSignature(op);
 }
 
-void BufferDeallocation::getMemrefsToRetain(
-    Block *fromBlock, Block *toBlock, ValueRange destOperands,
-    SmallVectorImpl<Value> &toRetain) const {
-  for (Value operand : destOperands) {
-    if (!isMemref(operand))
-      continue;
-    toRetain.push_back(operand);
-  }
-
-  SmallPtrSet<Value, 16> liveOut;
-  for (auto val : liveness.getLiveOut(fromBlock))
-    if (isMemref(val))
-      liveOut.insert(val);
-
-  if (toBlock)
-    llvm::set_intersect(liveOut, liveness.getLiveIn(toBlock));
-
-  // liveOut has non-deterministic order because it was constructed by iterating
-  // over a hash-set.
-  SmallVector<Value> retainedByLiveness(liveOut.begin(), liveOut.end());
-  std::sort(retainedByLiveness.begin(), retainedByLiveness.end(),
-            ValueComparator());
-  toRetain.append(retainedByLiveness);
-}
-
-LogicalResult BufferDeallocation::getMemrefsAndConditionsToDeallocate(
-    OpBuilder &builder, Location loc, Block *block,
-    SmallVectorImpl<Value> &memrefs, SmallVectorImpl<Value> &conditions) const {
-
-  for (auto [i, memref] :
-       llvm::enumerate(memrefsToDeallocatePerBlock.lookup(block))) {
-    Ownership ownership = ownershipMap.lookup({memref, block});
-    assert(ownership.isUnique() && "MemRef value must have valid ownership");
-
-    // Simply cast unranked MemRefs to ranked memrefs with 0 dimensions such
-    // that we can call extract_strided_metadata on it.
-    if (auto unrankedMemRefTy = dyn_cast<UnrankedMemRefType>(memref.getType()))
-      memref = builder.create<memref::ReinterpretCastOp>(
-          loc, MemRefType::get({}, unrankedMemRefTy.getElementType()), memref,
-          0, SmallVector<int64_t>{}, SmallVector<int64_t>{});
-
-    // Use the `memref.extract_strided_metadata` operation to get the base
-    // memref. This is needed because the same MemRef that was produced by the
-    // alloc operation has to be passed to the dealloc operation. Passing
-    // subviews, etc. to a dealloc operation is not allowed.
-    memrefs.push_back(
-        builder.create<memref::ExtractStridedMetadataOp>(loc, memref)
-            .getResult(0));
-    conditions.push_back(ownership.getIndicator());
-  }
-
-  return success();
-}
-
 LogicalResult BufferDeallocation::deallocate(Block *block) {
   OpBuilder builder = OpBuilder::atBlockBegin(block);
 
   // Compute liveness transfers of ownership to this block.
-  for (auto li : liveness.getLiveIn(block)) {
-    if (!isMemref(li))
-      continue;
-
+  SmallVector<Value> liveMemrefs;
+  state.getLiveMemrefsIn(block, liveMemrefs);
+  for (auto li : liveMemrefs) {
     // Ownership of implicitly captured memrefs from other regions is never
     // taken, but ownership of memrefs in the same region (but different block)
     // is taken.
     if (li.getParentRegion() == block->getParent()) {
-      joinOwnership(li, ownershipMap[{li, li.getParentBlock()}], block);
-      memrefsToDeallocatePerBlock[block].push_back(li);
+      state.updateOwnership(li, state.getOwnership(li, li.getParentBlock()),
+                            block);
+      state.addMemrefToDeallocate(li, block);
       continue;
     }
 
     if (li.getParentRegion()->isProperAncestor(block->getParent())) {
       Value falseVal = buildBoolValue(builder, li.getLoc(), false);
-      joinOwnership(li, falseVal, block);
+      state.updateOwnership(li, falseVal, block);
     }
   }
 
@@ -863,14 +590,15 @@ LogicalResult BufferDeallocation::deallocate(Block *block) {
     if (isFunctionWithoutDynamicOwnership(block->getParentOp()) &&
         block->isEntryBlock()) {
       Value newArg = buildBoolValue(builder, arg.getLoc(), false);
-      joinOwnership(arg, newArg);
+      state.updateOwnership(arg, newArg);
+      state.addMemrefToDeallocate(arg, block);
       continue;
     }
 
     // Pass MemRef ownerships along via `i1` values.
     Value newArg = block->addArgument(builder.getI1Type(), arg.getLoc());
-    joinOwnership(arg, newArg);
-    memrefsToDeallocatePerBlock[block].push_back(arg);
+    state.updateOwnership(arg, newArg);
+    state.addMemrefToDeallocate(arg, block);
   }
 
   // For each operation in the block, handle the interfaces that affect aliasing
@@ -906,97 +634,6 @@ Operation *BufferDeallocation::appendOpResults(Operation *op,
   return newOp;
 }
 
-FailureOr<Operation *>
-BufferDeallocation::handleInterface(cf::CondBranchOp op) {
-  OpBuilder builder(op);
-
-  // The list of memrefs to pass to the `bufferization.dealloc` op as "memrefs
-  // to deallocate" in this block is independent of which branch is taken.
-  SmallVector<Value> memrefs, ownerships;
-  if (failed(getMemrefsAndConditionsToDeallocate(
-          builder, op.getLoc(), op->getBlock(), memrefs, ownerships)))
-    return failure();
-
-  // Helper lambda to factor out common logic for inserting the dealloc
-  // operations for each successor.
-  auto insertDeallocForBranch =
-      [&](Block *target, MutableOperandRange destOperands,
-          ArrayRef<Value> conditions,
-          DenseMap<Value, Value> &ownershipMapping) -> DeallocOp {
-    SmallVector<Value> toRetain;
-    getMemrefsToRetain(op->getBlock(), target, OperandRange(destOperands),
-                       toRetain);
-    auto deallocOp = builder.create<bufferization::DeallocOp>(
-        op.getLoc(), memrefs, conditions, toRetain);
-    clearOwnershipOf(deallocOp.getRetained(), op->getBlock());
-    for (auto [retained, ownership] :
-         llvm::zip(deallocOp.getRetained(), deallocOp.getUpdatedConditions())) {
-      joinOwnership(retained, ownership, op->getBlock());
-      ownershipMapping[retained] = ownership;
-    }
-    SmallVector<Value> replacements, ownerships;
-    for (Value operand : destOperands) {
-      replacements.push_back(operand);
-      if (isMemref(operand)) {
-        assert(ownershipMapping.contains(operand) &&
-               "Should be contained at this point");
-        ownerships.push_back(ownershipMapping[operand]);
-      }
-    }
-    replacements.append(ownerships);
-    destOperands.assign(replacements);
-    return deallocOp;
-  };
-
-  // Call the helper lambda and make sure the dealloc conditions are properly
-  // modified to reflect the branch condition as well.
-  DenseMap<Value, Value> thenOwnershipMap, elseOwnershipMap;
-
-  // Retain `trueDestOperands` if "true" branch is taken.
-  SmallVector<Value> thenOwnerships(
-      llvm::map_range(ownerships, [&](Value cond) {
-        return builder.create<arith::AndIOp>(op.getLoc(), cond,
-                                             op.getCondition());
-      }));
-  DeallocOp thenTakenDeallocOp =
-      insertDeallocForBranch(op.getTrueDest(), op.getTrueDestOperandsMutable(),
-                             thenOwnerships, thenOwnershipMap);
-
-  // Retain `elseDestOperands` if "false" branch is taken.
-  SmallVector<Value> elseOwnerships(
-      llvm::map_range(ownerships, [&](Value cond) {
-        Value trueVal = builder.create<arith::ConstantOp>(
-            op.getLoc(), builder.getBoolAttr(true));
-        Value negation = builder.create<arith::XOrIOp>(op.getLoc(), trueVal,
-                                                       op.getCondition());
-        return builder.create<arith::AndIOp>(op.getLoc(), cond, negation);
-      }));
-  DeallocOp elseTakenDeallocOp = insertDeallocForBranch(
-      op.getFalseDest(), op.getFalseDestOperandsMutable(), elseOwnerships,
-      elseOwnershipMap);
-
-  // We specifically need to update the ownerships of values that are retained
-  // in both dealloc operations again to get a combined 'Unique' ownership
-  // instead of an 'Unknown' ownership.
-  SmallPtrSet<Value, 16> thenValues(thenTakenDeallocOp.getRetained().begin(),
-                                    thenTakenDeallocOp.getRetained().end());
-  SetVector<Value> commonValues;
-  for (Value val : elseTakenDeallocOp.getRetained()) {
-    if (thenValues.contains(val))
-      commonValues.insert(val);
-  }
-
-  for (Value retained : commonValues) {
-    clearOwnershipOf(retained, op->getBlock());
-    Value combinedOwnership = builder.create<arith::SelectOp>(
-        op.getLoc(), op.getCondition(), thenOwnershipMap[retained],
-        elseOwnershipMap[retained]);
-    joinOwnership(retained, combinedOwnership, op->getBlock());
-  }
-
-  return op.getOperation();
-}
-
 FailureOr<Operation *>
 BufferDeallocation::handleInterface(RegionBranchOpInterface op) {
   OpBuilder builder = OpBuilder::atBlockBegin(op->getBlock());
@@ -1033,44 +670,18 @@ BufferDeallocation::handleInterface(RegionBranchOpInterface op) {
   RegionBranchOpInterface newOp = appendOpResults(op, ownershipResults);
 
   for (auto result : llvm::make_filter_range(newOp->getResults(), isMemref)) {
-    joinOwnership(result, newOp->getResult(counter++));
-    memrefsToDeallocatePerBlock[newOp->getBlock()].push_back(result);
+    state.updateOwnership(result, newOp->getResult(counter++));
+    state.addMemrefToDeallocate(result, newOp->getBlock());
   }
 
   return newOp.getOperation();
 }
 
-std::pair<Value, Value>
-BufferDeallocation::getMemrefWithUniqueOwnership(OpBuilder &builder,
-                                                 Value memref) {
-  auto iter = ownershipMap.find({memref, memref.getParentBlock()});
-  assert(iter != ownershipMap.end() &&
-         "Value must already have been registered in the ownership map");
-
-  Ownership ownership = iter->second;
-  if (ownership.isUnique())
-    return {memref, ownership.getIndicator()};
-
-  // Instead of inserting a clone operation we could also insert a dealloc
-  // operation earlier in the block and use the updated ownerships returned by
-  // the op for the retained values. Alternatively, we could insert code to
-  // check aliasing at runtime and use this information to combine two unique
-  // ownerships more intelligently to not end up with an 'Unknown' ownership in
-  // the first place.
-  auto cloneOp =
-      builder.create<bufferization::CloneOp>(memref.getLoc(), memref);
-  Value condition = buildBoolValue(builder, memref.getLoc(), true);
-  Value newMemref = cloneOp.getResult();
-  joinOwnership(newMemref, condition);
-  memrefsToDeallocatePerBlock[newMemref.getParentBlock()].push_back(newMemref);
-  return {newMemref, condition};
-}
-
 Value BufferDeallocation::getMemrefWithGuaranteedOwnership(OpBuilder &builder,
                                                            Value memref) {
   // First, make sure we at least have 'Unique' ownership already.
   std::pair<Value, Value> newMemrefAndOnwership =
-      getMemrefWithUniqueOwnership(builder, memref);
+      state.getMemrefWithUniqueOwnership(builder, memref);
   Value newMemref = newMemrefAndOnwership.first;
   Value condition = newMemrefAndOnwership.second;
 
@@ -1096,17 +707,16 @@ Value BufferDeallocation::getMemrefWithGuaranteedOwnership(OpBuilder &builder,
               })
           .getResult(0);
   Value trueVal = buildBoolValue(builder, memref.getLoc(), true);
-  joinOwnership(maybeClone, trueVal);
-  memrefsToDeallocatePerBlock[maybeClone.getParentBlock()].push_back(
-      maybeClone);
+  state.updateOwnership(maybeClone, trueVal);
+  state.addMemrefToDeallocate(maybeClone, maybeClone.getParentBlock());
   return maybeClone;
 }
 
 FailureOr<Operation *>
 BufferDeallocation::handleInterface(BranchOpInterface op) {
-  // Skip conditional branches since we special case them for now.
-  if (isa<cf::CondBranchOp>(op.getOperation()))
-    return op.getOperation();
+  if (op->getNumSuccessors() > 1)
+    return op->emitError("BranchOpInterface operations with multiple "
+                         "successors are not supported yet");
 
   if (op->getNumSuccessors() != 1)
     return emitError(op.getLoc(),
@@ -1121,23 +731,24 @@ BufferDeallocation::handleInterface(BranchOpInterface op) {
   Block *block = op->getBlock();
   OpBuilder builder(op);
   SmallVector<Value> memrefs, conditions, toRetain;
-  if (failed(getMemrefsAndConditionsToDeallocate(builder, op.getLoc(), block,
-                                                 memrefs, conditions)))
+  if (failed(state.getMemrefsAndConditionsToDeallocate(
+          builder, op.getLoc(), block, memrefs, conditions)))
     return failure();
 
   OperandRange forwardedOperands =
       op.getSuccessorOperands(0).getForwardedOperands();
-  getMemrefsToRetain(block, op->getSuccessor(0), forwardedOperands, toRetain);
+  state.getMemrefsToRetain(block, op->getSuccessor(0), forwardedOperands,
+                           toRetain);
 
   auto deallocOp = builder.create<bufferization::DeallocOp>(
       op.getLoc(), memrefs, conditions, toRetain);
 
   // We want to replace the current ownership of the retained values with the
   // result values of the dealloc operation as they are always unique.
-  clearOwnershipOf(deallocOp.getRetained(), block);
+  state.resetOwnerships(deallocOp.getRetained(), block);
   for (auto [retained, ownership] :
        llvm::zip(deallocOp.getRetained(), deallocOp.getUpdatedConditions())) {
-    joinOwnership(retained, ownership, block);
+    state.updateOwnership(retained, ownership, block);
   }
 
   unsigned numAdditionalReturns = llvm::count_if(forwardedOperands, isMemref);
@@ -1156,7 +767,7 @@ FailureOr<Operation *> BufferDeallocation::handleInterface(CallOpInterface op) {
   // Lookup the function operation and check if it has private visibility. If
   // the function is referenced by SSA value instead of a Symbol, it's assumed
   // to be always private.
-  Operation *funcOp = op.resolveCallable(&symbolTable);
+  Operation *funcOp = op.resolveCallable(state.getSymbolTable());
   bool isPrivate = true;
   if (auto symbol = dyn_cast<SymbolOpInterface>(funcOp))
     isPrivate &= (symbol.getVisibility() == SymbolTable::Visibility::Private);
@@ -1166,14 +777,15 @@ FailureOr<Operation *> BufferDeallocation::handleInterface(CallOpInterface op) {
   // argument/result for each MemRef argument/result to dynamically pass the
   // current ownership indicator rather than adhering to the function boundary
   // ABI.
-  if (privateFuncDynamicOwnership && isPrivate) {
+  if (options.privateFuncDynamicOwnership && isPrivate) {
     SmallVector<Value> newOperands, ownershipIndicatorsToAdd;
     for (Value operand : op.getArgOperands()) {
       if (!isMemref(operand)) {
         newOperands.push_back(operand);
         continue;
       }
-      auto [memref, condition] = getMemrefWithUniqueOwnership(builder, operand);
+      auto [memref, condition] =
+          state.getMemrefWithUniqueOwnership(builder, operand);
       newOperands.push_back(memref);
       ownershipIndicatorsToAdd.push_back(condition);
     }
@@ -1187,8 +799,8 @@ FailureOr<Operation *> BufferDeallocation::handleInterface(CallOpInterface op) {
     op = appendOpResults(op, ownershipTypesToAppend);
 
     for (auto result : llvm::make_filter_range(op->getResults(), isMemref)) {
-      joinOwnership(result, op->getResult(ownershipCounter++));
-      memrefsToDeallocatePerBlock[result.getParentBlock()].push_back(result);
+      state.updateOwnership(result, op->getResult(ownershipCounter++));
+      state.addMemrefToDeallocate(result, result.getParentBlock());
     }
 
     return op.getOperation();
@@ -1199,8 +811,8 @@ FailureOr<Operation *> BufferDeallocation::handleInterface(CallOpInterface op) {
   // 'true' and remember to deallocate it.
   Value trueVal = buildBoolValue(builder, op.getLoc(), true);
   for (auto result : llvm::make_filter_range(op->getResults(), isMemref)) {
-    joinOwnership(result, trueVal);
-    memrefsToDeallocatePerBlock[result.getParentBlock()].push_back(result);
+    state.updateOwnership(result, trueVal);
+    state.addMemrefToDeallocate(result, result.getParentBlock());
   }
 
   return op.getOperation();
@@ -1228,13 +840,13 @@ BufferDeallocation::handleInterface(MemoryEffectOpInterface op) {
         // `memref.alloc`. If we wouldn't set the ownership of the result here,
         // the default ownership population in `populateRemainingOwnerships`
         // would assume aliasing with the MemRef operand.
-        clearOwnershipOf(res, block);
-        joinOwnership(res, buildBoolValue(builder, op.getLoc(), false));
+        state.resetOwnerships(res, block);
+        state.updateOwnership(res, buildBoolValue(builder, op.getLoc(), false));
         continue;
       }
 
-      joinOwnership(res, buildBoolValue(builder, op.getLoc(), true));
-      memrefsToDeallocatePerBlock[block].push_back(res);
+      state.updateOwnership(res, buildBoolValue(builder, op.getLoc(), true));
+      state.addMemrefToDeallocate(res, block);
     }
   }
 
@@ -1271,11 +883,11 @@ BufferDeallocation::handleInterface(RegionBranchTerminatorOpInterface op) {
   // dealloc operation.
   Block *block = op->getBlock();
   SmallVector<Value> memrefs, conditions, toRetain;
-  if (failed(getMemrefsAndConditionsToDeallocate(builder, op.getLoc(), block,
-                                                 memrefs, conditions)))
+  if (failed(state.getMemrefsAndConditionsToDeallocate(
+          builder, op.getLoc(), block, memrefs, conditions)))
     return failure();
 
-  getMemrefsToRetain(block, nullptr, OperandRange(operands), toRetain);
+  state.getMemrefsToRetain(block, nullptr, OperandRange(operands), toRetain);
   if (memrefs.empty() && toRetain.empty())
     return op.getOperation();
 
@@ -1284,10 +896,10 @@ BufferDeallocation::handleInterface(RegionBranchTerminatorOpInterface op) {
 
   // We want to replace the current ownership of the retained values with the
   // result values of the dealloc operation as they are always unique.
-  clearOwnershipOf(deallocOp.getRetained(), block);
+  state.resetOwnerships(deallocOp.getRetained(), block);
   for (auto [retained, ownership] :
        llvm::zip(deallocOp.getRetained(), deallocOp.getUpdatedConditions()))
-    joinOwnership(retained, ownership, block);
+    state.updateOwnership(retained, ownership, block);
 
   // Add an additional operand for every MemRef for the ownership indicator.
   if (!funcWithoutDynamicOwnership) {
@@ -1304,7 +916,7 @@ BufferDeallocation::handleInterface(RegionBranchTerminatorOpInterface op) {
 
 bool BufferDeallocation::isFunctionWithoutDynamicOwnership(Operation *op) {
   auto funcOp = dyn_cast<FunctionOpInterface>(op);
-  return funcOp && (!privateFuncDynamicOwnership ||
+  return funcOp && (!options.privateFuncDynamicOwnership ||
                     funcOp.getVisibility() != SymbolTable::Visibility::Private);
 }
 
@@ -1312,14 +924,14 @@ void BufferDeallocation::populateRemainingOwnerships(Operation *op) {
   for (auto res : op->getResults()) {
     if (!isMemref(res))
       continue;
-    if (ownershipMap.count({res, op->getBlock()}))
+    if (!state.getOwnership(res, op->getBlock()).isUninitialized())
       continue;
 
     // Don't take ownership of a returned memref if no allocate side-effect is
     // present, relevant for memref.get_global, for example.
     if (op->getNumOperands() == 0) {
       OpBuilder builder(op);
-      joinOwnership(res, buildBoolValue(builder, op->getLoc(), false));
+      state.updateOwnership(res, buildBoolValue(builder, op->getLoc(), false));
       continue;
     }
 
@@ -1329,8 +941,9 @@ void BufferDeallocation::populateRemainingOwnerships(Operation *op) {
       if (!isMemref(operand))
         continue;
 
-      ownershipMap[{res, op->getBlock()}].combine(
-          ownershipMap[{operand, operand.getParentBlock()}]);
+      state.updateOwnership(
+          res, state.getOwnership(operand, operand.getParentBlock()),
+          op->getBlock());
     }
   }
 }
diff --git a/mlir/lib/Dialect/ControlFlow/Transforms/BufferDeallocationOpInterfaceImpl.cpp b/mlir/lib/Dialect/ControlFlow/Transforms/BufferDeallocationOpInterfaceImpl.cpp
new file mode 100644
index 000000000000000..e847e946eef1b5d
--- /dev/null
+++ b/mlir/lib/Dialect/ControlFlow/Transforms/BufferDeallocationOpInterfaceImpl.cpp
@@ -0,0 +1,163 @@
+//===- BufferDeallocationOpInterfaceImpl.cpp ------------------------------===//
+//
+// 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 "mlir/Dialect/ControlFlow/Transforms/BufferDeallocationOpInterfaceImpl.h"
+#include "mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h"
+#include "mlir/Dialect/Bufferization/IR/Bufferization.h"
+#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
+#include "mlir/Dialect/MemRef/IR/MemRef.h"
+#include "mlir/IR/Dialect.h"
+#include "mlir/IR/Operation.h"
+
+using namespace mlir;
+using namespace mlir::bufferization;
+
+static bool isMemref(Value v) { return v.getType().isa<BaseMemRefType>(); }
+
+namespace {
+/// While CondBranchOp also implement the BranchOpInterface, we add a
+/// special-case implementation here because the BranchOpInterface does not
+/// offer all of the functionallity we need to insert dealloc oeprations in an
+/// efficient way. More precisely, there is no way to extract the branch
+/// condition without casting to CondBranchOp specifically. It is still
+/// possible to implement deallocation for cases where we don't know to which
+/// successor the terminator branches before the actual branch happens by
+/// inserting auxiliary blocks and putting the dealloc op there, however, this
+/// can lead to less efficient code.
+/// This function inserts two dealloc operations (one for each successor) and
+/// adjusts the dealloc conditions according to the branch condition, then the
+/// ownerships of the retained MemRefs are updated by combining the result
+/// values of the two dealloc operations.
+///
+/// Example:
+/// ```
+/// ^bb1:
+///   <more ops...>
+///   cf.cond_br cond, ^bb2(<forward-to-bb2>), ^bb3(<forward-to-bb2>)
+/// ```
+/// becomes
+/// ```
+/// // let (m, c) = getMemrefsAndConditionsToDeallocate(bb1)
+/// // let r0 = getMemrefsToRetain(bb1, bb2, <forward-to-bb2>)
+/// // let r1 = getMemrefsToRetain(bb1, bb3, <forward-to-bb3>)
+/// ^bb1:
+///   <more ops...>
+///   let thenCond = map(c, (c) -> arith.andi cond, c)
+///   let elseCond = map(c, (c) -> arith.andi (arith.xori cond, true), c)
+///   o0 = bufferization.dealloc m if thenCond retain r0
+///   o1 = bufferization.dealloc m if elseCond retain r1
+///   // replace ownership(r0) with o0 element-wise
+///   // replace ownership(r1) with o1 element-wise
+///   // let ownership0 := (r) -> o in o0 corresponding to r
+///   // let ownership1 := (r) -> o in o1 corresponding to r
+///   // let cmn := intersection(r0, r1)
+///   foreach (a, b) in zip(map(cmn, ownership0), map(cmn, ownership1)):
+///     forall r in r0: replace ownership0(r) with arith.select cond, a, b)
+///     forall r in r1: replace ownership1(r) with arith.select cond, a, b)
+///   cf.cond_br cond, ^bb2(<forward-to-bb2>, o0), ^bb3(<forward-to-bb3>, o1)
+/// ```
+struct CondBranchOpInterface
+    : public BufferDeallocationOpInterface::ExternalModel<CondBranchOpInterface,
+                                                          cf::CondBranchOp> {
+  FailureOr<Operation *> process(Operation *op, DeallocationState &state,
+                                 const DeallocationOptions &options) const {
+    OpBuilder builder(op);
+    auto condBr = cast<cf::CondBranchOp>(op);
+
+    // The list of memrefs to deallocate in this block is independent of which
+    // branch is taken.
+    SmallVector<Value> memrefs, conditions;
+    if (failed(state.getMemrefsAndConditionsToDeallocate(
+            builder, condBr.getLoc(), condBr->getBlock(), memrefs, conditions)))
+      return failure();
+
+    // Helper lambda to factor out common logic for inserting the dealloc
+    // operations for each successor.
+    auto insertDeallocForBranch =
+        [&](Block *target, MutableOperandRange destOperands,
+            const std::function<Value(Value)> &conditionModifier,
+            DenseMap<Value, Value> &mapping) -> DeallocOp {
+      SmallVector<Value> toRetain;
+      state.getMemrefsToRetain(condBr->getBlock(), target,
+                               OperandRange(destOperands), toRetain);
+      SmallVector<Value> adaptedConditions(
+          llvm::map_range(conditions, conditionModifier));
+      auto deallocOp = builder.create<bufferization::DeallocOp>(
+          condBr.getLoc(), memrefs, adaptedConditions, toRetain);
+      state.resetOwnerships(deallocOp.getRetained(), condBr->getBlock());
+      for (auto [retained, ownership] : llvm::zip(
+               deallocOp.getRetained(), deallocOp.getUpdatedConditions())) {
+        state.updateOwnership(retained, ownership, condBr->getBlock());
+        mapping[retained] = ownership;
+      }
+      SmallVector<Value> replacements, ownerships;
+      for (Value operand : destOperands) {
+        replacements.push_back(operand);
+        if (isMemref(operand)) {
+          assert(mapping.contains(operand) &&
+                 "Should be contained at this point");
+          ownerships.push_back(mapping[operand]);
+        }
+      }
+      replacements.append(ownerships);
+      destOperands.assign(replacements);
+      return deallocOp;
+    };
+
+    // Call the helper lambda and make sure the dealloc conditions are properly
+    // modified to reflect the branch condition as well.
+    DenseMap<Value, Value> thenMapping, elseMapping;
+    DeallocOp thenTakenDeallocOp = insertDeallocForBranch(
+        condBr.getTrueDest(), condBr.getTrueDestOperandsMutable(),
+        [&](Value cond) {
+          return builder.create<arith::AndIOp>(condBr.getLoc(), cond,
+                                               condBr.getCondition());
+        },
+        thenMapping);
+    DeallocOp elseTakenDeallocOp = insertDeallocForBranch(
+        condBr.getFalseDest(), condBr.getFalseDestOperandsMutable(),
+        [&](Value cond) {
+          Value trueVal = builder.create<arith::ConstantOp>(
+              condBr.getLoc(), builder.getBoolAttr(true));
+          Value negation = builder.create<arith::XOrIOp>(
+              condBr.getLoc(), trueVal, condBr.getCondition());
+          return builder.create<arith::AndIOp>(condBr.getLoc(), cond, negation);
+        },
+        elseMapping);
+
+    // We specifically need to update the ownerships of values that are retained
+    // in both dealloc operations again to get a combined 'Unique' ownership
+    // instead of an 'Unknown' ownership.
+    SmallPtrSet<Value, 16> thenValues(thenTakenDeallocOp.getRetained().begin(),
+                                      thenTakenDeallocOp.getRetained().end());
+    SetVector<Value> commonValues;
+    for (Value val : elseTakenDeallocOp.getRetained()) {
+      if (thenValues.contains(val))
+        commonValues.insert(val);
+    }
+
+    for (Value retained : commonValues) {
+      state.resetOwnerships(retained, condBr->getBlock());
+      Value combinedOwnership = builder.create<arith::SelectOp>(
+          condBr.getLoc(), condBr.getCondition(), thenMapping[retained],
+          elseMapping[retained]);
+      state.updateOwnership(retained, combinedOwnership, condBr->getBlock());
+    }
+
+    return condBr.getOperation();
+  }
+};
+
+} // namespace
+
+void mlir::cf::registerBufferDeallocationOpInterfaceExternalModels(
+    DialectRegistry &registry) {
+  registry.addExtension(+[](MLIRContext *ctx, ControlFlowDialect *dialect) {
+    CondBranchOp::attachInterface<CondBranchOpInterface>(*ctx);
+  });
+}
diff --git a/mlir/lib/Dialect/ControlFlow/Transforms/CMakeLists.txt b/mlir/lib/Dialect/ControlFlow/Transforms/CMakeLists.txt
index b2ef59887515e74..37b4cfc893879b3 100644
--- a/mlir/lib/Dialect/ControlFlow/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/ControlFlow/Transforms/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_mlir_dialect_library(MLIRControlFlowTransforms
+  BufferDeallocationOpInterfaceImpl.cpp
   BufferizableOpInterfaceImpl.cpp
 
   ADDITIONAL_HEADER_DIRS
@@ -10,4 +11,4 @@ add_mlir_dialect_library(MLIRControlFlowTransforms
   MLIRControlFlowDialect
   MLIRMemRefDialect
   MLIRIR
-  )
+)
diff --git a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-region-branchop-interface.mlir b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-region-branchop-interface.mlir
index d8090591c70513f..66449aa2ffdb60e 100644
--- a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-region-branchop-interface.mlir
+++ b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-region-branchop-interface.mlir
@@ -500,10 +500,10 @@ func.func @assumingOp(
 //       CHECK: test.copy
 //       CHECK: [[BASE0:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V0]]#0
 //       CHECK: [[BASE1:%[a-zA-Z0-9_]+]],{{.*}} = memref.extract_strided_metadata [[V1]]#0
-//       CHECK: bufferization.dealloc ([[BASE0]] :{{.*}}) if ([[V0]]#1)
-//   CHECK-NOT: retain
 //       CHECK: bufferization.dealloc ([[BASE1]] :{{.*}}) if ([[V1]]#1)
 //   CHECK-NOT: retain
+//       CHECK: bufferization.dealloc ([[BASE0]] :{{.*}}) if ([[V0]]#1)
+//   CHECK-NOT: retain
 //       CHECK: return
 
 // -----
diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
index 9e37b37b9af089e..114216752d71907 100644
--- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
@@ -12067,6 +12067,7 @@ gentbl_cc_library(
 cc_library(
     name = "BufferizationDialect",
     srcs = [
+        "lib/Dialect/Bufferization/IR/BufferDeallocationOpInterface.cpp",
         "lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp",
         "lib/Dialect/Bufferization/IR/BufferizationDialect.cpp",
         "lib/Dialect/Bufferization/IR/BufferizationOps.cpp",
@@ -12074,6 +12075,7 @@ cc_library(
         "lib/Dialect/Bufferization/IR/UnstructuredControlFlow.cpp",
     ],
     hdrs = [
+        "include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h",
         "include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h",
         "include/mlir/Dialect/Bufferization/IR/Bufferization.h",
         "include/mlir/Dialect/Bufferization/IR/DstBufferizableOpInterfaceImpl.h",
@@ -12084,7 +12086,9 @@ cc_library(
     deps = [
         ":AffineDialect",
         ":AllocationOpInterface",
+        ":Analysis",
         ":ArithDialect",
+        ":BufferDeallocationOpInterfaceIncGen",
         ":BufferizableOpInterfaceIncGen",
         ":BufferizationBaseIncGen",
         ":BufferizationEnumsIncGen",

>From 6a41e67b34e01bd3e4f959a95f923f2f6f418ece Mon Sep 17 00:00:00 2001
From: paulwalker-arm <paul.walker at arm.com>
Date: Thu, 14 Sep 2023 12:58:58 +0100
Subject: [PATCH 65/86] [SVE] Ensure SVE call operands passed via memory are
 correctly initialised. (#66070)

The stores created when passing operands via memory don't typically
maintain the chain, because they can be done in any order. Instead,
a new chain is created based on all collated stores. SVE parameters
passed via memory don't follow this idiom and try to maintain the
chain, which unfortunately can result in them being incorrectly
deadcoded when the chain is recreated.

This patch brings the SVE side in line with the non-SVE side to
ensure no stores become lost whilst also allowing greater flexibility
when ordering the stores.
---
 .../Target/AArch64/AArch64ISelLowering.cpp    |  4 ++-
 llvm/test/CodeGen/AArch64/arm64ec-varargs.ll  | 30 +++++++++----------
 .../AArch64/sve-calling-convention-mixed.ll   | 24 ++++++++-------
 3 files changed, 32 insertions(+), 26 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index b706f61ac75983e..5da41ec6376dcb0 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -7510,7 +7510,9 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
       // Ensure we generate all stores for each tuple part, whilst updating the
       // pointer after each store correctly using vscale.
       while (NumParts) {
-        Chain = DAG.getStore(Chain, DL, OutVals[i], Ptr, MPI);
+        SDValue Store = DAG.getStore(Chain, DL, OutVals[i], Ptr, MPI);
+        MemOpChains.push_back(Store);
+
         NumParts--;
         if (NumParts > 0) {
           SDValue BytesIncrement;
diff --git a/llvm/test/CodeGen/AArch64/arm64ec-varargs.ll b/llvm/test/CodeGen/AArch64/arm64ec-varargs.ll
index 3950a3026769c89..957ed995ee3bfc0 100644
--- a/llvm/test/CodeGen/AArch64/arm64ec-varargs.ll
+++ b/llvm/test/CodeGen/AArch64/arm64ec-varargs.ll
@@ -35,15 +35,15 @@ define void @varargs_caller() nounwind {
 ; CHECK-NEXT:    sub sp, sp, #48
 ; CHECK-NEXT:    mov x4, sp
 ; CHECK-NEXT:    add x8, sp, #16
-; CHECK-NEXT:    mov x9, #4617315517961601024
-; CHECK-NEXT:    mov x0, #4607182418800017408
-; CHECK-NEXT:    mov w1, #2
-; CHECK-NEXT:    mov x2, #4613937818241073152
-; CHECK-NEXT:    mov w3, #4
-; CHECK-NEXT:    mov w5, #16
+; CHECK-NEXT:    mov x9, #4617315517961601024 // =0x4014000000000000
+; CHECK-NEXT:    mov x0, #4607182418800017408 // =0x3ff0000000000000
+; CHECK-NEXT:    mov w1, #2 // =0x2
+; CHECK-NEXT:    mov x2, #4613937818241073152 // =0x4008000000000000
+; CHECK-NEXT:    mov w3, #4 // =0x4
+; CHECK-NEXT:    mov w5, #16 // =0x10
 ; CHECK-NEXT:    stp xzr, x30, [sp, #24] // 8-byte Folded Spill
-; CHECK-NEXT:    stp x8, xzr, [sp, #8]
-; CHECK-NEXT:    str x9, [sp]
+; CHECK-NEXT:    stp x9, x8, [sp]
+; CHECK-NEXT:    str xzr, [sp, #16]
 ; CHECK-NEXT:    bl varargs_callee
 ; CHECK-NEXT:    ldr x30, [sp, #32] // 8-byte Folded Reload
 ; CHECK-NEXT:    add sp, sp, #48
@@ -70,17 +70,17 @@ define void @varargs_many_argscalleer() nounwind {
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    sub sp, sp, #64
 ; CHECK-NEXT:    movi v0.2d, #0000000000000000
-; CHECK-NEXT:    mov x4, sp
-; CHECK-NEXT:    mov x8, #4618441417868443648
+; CHECK-NEXT:    mov x8, #4618441417868443648 // =0x4018000000000000
 ; CHECK-NEXT:    add x9, sp, #16
 ; CHECK-NEXT:    add x3, sp, #32
-; CHECK-NEXT:    mov x0, #4607182418800017408
-; CHECK-NEXT:    mov x1, #4611686018427387904
-; CHECK-NEXT:    mov x2, #4613937818241073152
-; CHECK-NEXT:    mov w5, #16
+; CHECK-NEXT:    mov x0, #4607182418800017408 // =0x3ff0000000000000
+; CHECK-NEXT:    mov x1, #4611686018427387904 // =0x4000000000000000
+; CHECK-NEXT:    mov x2, #4613937818241073152 // =0x4008000000000000
+; CHECK-NEXT:    mov x4, sp
+; CHECK-NEXT:    mov w5, #16 // =0x10
 ; CHECK-NEXT:    str x30, [sp, #48] // 8-byte Folded Spill
-; CHECK-NEXT:    stp q0, q0, [sp, #16]
 ; CHECK-NEXT:    stp x9, x8, [sp]
+; CHECK-NEXT:    stp q0, q0, [sp, #16]
 ; CHECK-NEXT:    bl varargs_many_argscallee
 ; CHECK-NEXT:    ldr x30, [sp, #48] // 8-byte Folded Reload
 ; CHECK-NEXT:    add sp, sp, #64
diff --git a/llvm/test/CodeGen/AArch64/sve-calling-convention-mixed.ll b/llvm/test/CodeGen/AArch64/sve-calling-convention-mixed.ll
index c8748052a9f263e..b7505625cde9773 100644
--- a/llvm/test/CodeGen/AArch64/sve-calling-convention-mixed.ll
+++ b/llvm/test/CodeGen/AArch64/sve-calling-convention-mixed.ll
@@ -18,10 +18,10 @@ define float @foo1(ptr %x0, ptr %x1, ptr %x2) nounwind {
 ; CHECK-NEXT:    ld4d { z16.d - z19.d }, p0/z, [x1]
 ; CHECK-NEXT:    ld1d { z5.d }, p0/z, [x2]
 ; CHECK-NEXT:    ptrue p0.d
-; CHECK-NEXT:    st1d { z16.d }, p0, [sp]
-; CHECK-NEXT:    st1d { z17.d }, p0, [sp, #1, mul vl]
-; CHECK-NEXT:    st1d { z18.d }, p0, [sp, #2, mul vl]
 ; CHECK-NEXT:    st1d { z19.d }, p0, [sp, #3, mul vl]
+; CHECK-NEXT:    st1d { z18.d }, p0, [sp, #2, mul vl]
+; CHECK-NEXT:    st1d { z17.d }, p0, [sp, #1, mul vl]
+; CHECK-NEXT:    st1d { z16.d }, p0, [sp]
 ; CHECK-NEXT:    bl callee1
 ; CHECK-NEXT:    addvl sp, sp, #4
 ; CHECK-NEXT:    ldp x29, x30, [sp], #16 // 16-byte Folded Reload
@@ -73,10 +73,10 @@ define float @foo2(ptr %x0, ptr %x1) nounwind {
 ; CHECK-NEXT:    ld4d { z16.d - z19.d }, p0/z, [x1]
 ; CHECK-NEXT:    ptrue p0.d
 ; CHECK-NEXT:    mov w1, #1 // =0x1
-; CHECK-NEXT:    st1d { z16.d }, p0, [x8]
-; CHECK-NEXT:    st1d { z17.d }, p0, [x8, #1, mul vl]
+; CHECK-NEXT:    st1d { z19.d }, p0, [x8, #3, mul vl]
 ; CHECK-NEXT:    st1d { z18.d }, p0, [x8, #2, mul vl]
-; CHECK-NEXT:    st1d { z19.d }, p0, [x9, #3, mul vl]
+; CHECK-NEXT:    st1d { z17.d }, p0, [x8, #1, mul vl]
+; CHECK-NEXT:    st1d { z16.d }, p0, [x9]
 ; CHECK-NEXT:    str x8, [sp]
 ; CHECK-NEXT:    bl callee2
 ; CHECK-NEXT:    addvl sp, sp, #4
@@ -121,9 +121,9 @@ define float @foo3(ptr %x0, ptr %x1, ptr %x2) nounwind {
 ; CHECK-NEXT:    ld3d { z16.d - z18.d }, p0/z, [x1]
 ; CHECK-NEXT:    ld1d { z6.d }, p0/z, [x2]
 ; CHECK-NEXT:    ptrue p0.d
-; CHECK-NEXT:    st1d { z16.d }, p0, [sp]
-; CHECK-NEXT:    st1d { z17.d }, p0, [sp, #1, mul vl]
 ; CHECK-NEXT:    st1d { z18.d }, p0, [sp, #2, mul vl]
+; CHECK-NEXT:    st1d { z17.d }, p0, [sp, #1, mul vl]
+; CHECK-NEXT:    st1d { z16.d }, p0, [sp]
 ; CHECK-NEXT:    bl callee3
 ; CHECK-NEXT:    addvl sp, sp, #3
 ; CHECK-NEXT:    ldp x29, x30, [sp], #16 // 16-byte Folded Reload
@@ -704,17 +704,21 @@ define void @verify_all_operands_are_initialised() {
 ; CHECK-NEXT:    .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 32 + 8 * VG
 ; CHECK-NEXT:    .cfi_offset w30, -8
 ; CHECK-NEXT:    .cfi_offset w29, -16
+; CHECK-NEXT:    ptrue p0.s
 ; CHECK-NEXT:    movi d0, #0000000000000000
 ; CHECK-NEXT:    fmov s1, #1.00000000
+; CHECK-NEXT:    fmov z16.s, #9.00000000
 ; CHECK-NEXT:    mov w8, #1090519040 // =0x41000000
+; CHECK-NEXT:    add x0, sp, #16
 ; CHECK-NEXT:    fmov s2, #2.00000000
 ; CHECK-NEXT:    fmov s3, #3.00000000
-; CHECK-NEXT:    add x0, sp, #16
+; CHECK-NEXT:    add x9, sp, #16
 ; CHECK-NEXT:    fmov s4, #4.00000000
 ; CHECK-NEXT:    fmov s5, #5.00000000
-; CHECK-NEXT:    str w8, [sp]
 ; CHECK-NEXT:    fmov s6, #6.00000000
 ; CHECK-NEXT:    fmov s7, #7.00000000
+; CHECK-NEXT:    st1w { z16.s }, p0, [x9]
+; CHECK-NEXT:    str w8, [sp]
 ; CHECK-NEXT:    bl func_f8_and_v0_passed_via_memory
 ; CHECK-NEXT:    addvl sp, sp, #1
 ; CHECK-NEXT:    add sp, sp, #16

>From 2db0a8d79f021d35ae323f769193c69be9409faa Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 14 Sep 2023 08:06:36 -0400
Subject: [PATCH 66/86] [github] Label PRs touching CMake-related files with
 the 'cmake' tag (#66247)

---
 .github/new-prs-labeler.yml | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml
index 5513c5d49b6b3b0..c3d132db340a9f8 100644
--- a/.github/new-prs-labeler.yml
+++ b/.github/new-prs-labeler.yml
@@ -362,6 +362,11 @@ debuginfo:
 github:workflow:
   - .github/workflows/**
 
+cmake:
+  - cmake/**
+  - llvm/cmake/**
+  - runtimes/**
+
 flang:driver:
   - flang/tools/flang-driver/**
   - flang/unittests/Frontend/**
@@ -381,15 +386,12 @@ backend:m68k:
 
 libc++:
   - libcxx/**
-  - runtimes/**
 
 libc++abi:
   - libcxxabi/**
-  - runtimes/**
 
 libunwind:
   - libunwind/**
-  - runtimes/**
 
 objectyaml:
   - llvm/include/llvm/ObjectYAML/**

>From 3fe68127deb284a2392bd6df715f6f057e62f2a6 Mon Sep 17 00:00:00 2001
From: Kohei Asano <32860920+khei4 at users.noreply.github.com>
Date: Thu, 14 Sep 2023 21:26:11 +0900
Subject: [PATCH 67/86] [SimplifyCFG] handle monotonic wrapped case for D150943
 (#65882)

---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp     | 12 +++++---
 .../SimplifyCFG/X86/switch_to_lookup_table.ll | 29 +++++++++++++++++++
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 84e5906340278a5..14cabd275d5b111 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6068,8 +6068,9 @@ SwitchLookupTable::SwitchLookupTable(
     bool LinearMappingPossible = true;
     APInt PrevVal;
     APInt DistToPrev;
-    // When linear map is monotonic, we can attach nsw.
-    bool Wrapped = false;
+    // When linear map is monotonic and signed overflow doesn't happen on
+    // maximum index, we can attach nsw on Add and Mul.
+    bool NonMonotonic = false;
     assert(TableSize >= 2 && "Should be a SingleValue table.");
     // Check if there is the same distance between two consecutive values.
     for (uint64_t I = 0; I < TableSize; ++I) {
@@ -6089,7 +6090,7 @@ SwitchLookupTable::SwitchLookupTable(
           LinearMappingPossible = false;
           break;
         }
-        Wrapped |=
+        NonMonotonic |=
             Dist.isStrictlyPositive() ? Val.sle(PrevVal) : Val.sgt(PrevVal);
       }
       PrevVal = Val;
@@ -6097,7 +6098,10 @@ SwitchLookupTable::SwitchLookupTable(
     if (LinearMappingPossible) {
       LinearOffset = cast<ConstantInt>(TableContents[0]);
       LinearMultiplier = ConstantInt::get(M.getContext(), DistToPrev);
-      LinearMapValWrapped = Wrapped;
+      bool MayWrap = false;
+      APInt M = LinearMultiplier->getValue();
+      (void)M.smul_ov(APInt(M.getBitWidth(), TableSize - 1), MayWrap);
+      LinearMapValWrapped = NonMonotonic || MayWrap;
       Kind = LinearMapKind;
       ++NumLinearMaps;
       return;
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
index a00805077aae00e..3873f0c0ae0bbd5 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
@@ -2039,3 +2039,32 @@ return:
   %x = phi i8 [ 3, %sw.default ], [ 124, %sw.bb3 ], [ -99, %sw.bb2 ], [ -66, %sw.bb1 ], [ -33, %entry ]
   ret i8 %x
 }
+
+define i8 @linearmap_dec_wrapped_mon(i3 %0) {
+; CHECK-LABEL: @linearmap_dec_wrapped_mon(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SWITCH_TABLEIDX:%.*]] = sub i3 [[TMP0:%.*]], -2
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i3 [[SWITCH_TABLEIDX]], -4
+; CHECK-NEXT:    [[SWITCH_IDX_MULT:%.*]] = mul i3 [[SWITCH_TABLEIDX]], 2
+; CHECK-NEXT:    [[SWITCH_OFFSET:%.*]] = add i3 [[SWITCH_IDX_MULT]], -4
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[TMP1]], i3 [[SWITCH_OFFSET]], i3 2
+; CHECK-NEXT:    [[CONV:%.*]] = sext i3 [[COND]] to i8
+; CHECK-NEXT:    ret i8 [[CONV]]
+;
+entry:
+  switch i3 %0, label %cond.end [
+  i3 -1, label %cond.false
+  i3 -2, label %cond.false
+  i3 1, label %cond.false
+  i3 0, label %cond.false
+  ]
+
+cond.false:                                       ; preds = %entry, %entry, %entry, %entry
+  %mul = shl nsw i3 %0, 1
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.false
+  %cond = phi i3 [ %mul, %cond.false ], [ 2, %entry ]
+  %conv = sext i3 %cond to i8
+  ret i8 %conv
+}

>From 0aef07fd10d616eb4019aac10a7eba54b5204f13 Mon Sep 17 00:00:00 2001
From: Martin Erhart <merhart at google.com>
Date: Thu, 14 Sep 2023 14:34:04 +0200
Subject: [PATCH 68/86] [mlir][bufferization] BufferDeallocationOpInterface:
 support custom ownership update logic (#66350)

Add a method to the BufferDeallocationOpInterface that allows operations to implement the interface and provide custom logic to compute the ownership indicators of values it defines. As a demonstrating example, this new method is implemented by the `arith.select` operation.
---
 .../BufferDeallocationOpInterfaceImpl.h       | 22 +++++
 .../IR/BufferDeallocationOpInterface.h        |  4 +-
 .../IR/BufferDeallocationOpInterface.td       | 29 ++++++-
 mlir/include/mlir/InitAllDialects.h           |  2 +
 .../BufferDeallocationOpInterfaceImpl.cpp     | 85 +++++++++++++++++++
 .../Dialect/Arith/Transforms/CMakeLists.txt   |  1 +
 .../IR/BufferDeallocationOpInterface.cpp      |  4 +-
 .../OwnershipBasedBufferDeallocation.cpp      | 46 ++++++++--
 .../dealloc-callop-interface.mlir             | 10 +--
 9 files changed, 187 insertions(+), 16 deletions(-)
 create mode 100644 mlir/include/mlir/Dialect/Arith/Transforms/BufferDeallocationOpInterfaceImpl.h
 create mode 100644 mlir/lib/Dialect/Arith/Transforms/BufferDeallocationOpInterfaceImpl.cpp

diff --git a/mlir/include/mlir/Dialect/Arith/Transforms/BufferDeallocationOpInterfaceImpl.h b/mlir/include/mlir/Dialect/Arith/Transforms/BufferDeallocationOpInterfaceImpl.h
new file mode 100644
index 000000000000000..16cec1a82b5c86c
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Arith/Transforms/BufferDeallocationOpInterfaceImpl.h
@@ -0,0 +1,22 @@
+//===- BufferDeallocationOpInterfaceImpl.h ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_ARITH_TRANSFORMS_BUFFERDEALLOCATIONOPINTERFACEIMPL_H
+#define MLIR_DIALECT_ARITH_TRANSFORMS_BUFFERDEALLOCATIONOPINTERFACEIMPL_H
+
+namespace mlir {
+
+class DialectRegistry;
+
+namespace arith {
+void registerBufferDeallocationOpInterfaceExternalModels(
+    DialectRegistry &registry);
+} // namespace arith
+} // namespace mlir
+
+#endif // MLIR_DIALECT_ARITH_TRANSFORMS_BUFFERDEALLOCATIONOPINTERFACEIMPL_H
diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h b/mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h
index b88270f1c150a27..7ac4592de7875fb 100644
--- a/mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h
+++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h
@@ -142,8 +142,8 @@ class DeallocationState {
   /// a new SSA value, returned as the first element of the pair, which has
   /// 'Unique' ownership and can be used instead of the passed Value with the
   /// the ownership indicator returned as the second element of the pair.
-  std::pair<Value, Value> getMemrefWithUniqueOwnership(OpBuilder &builder,
-                                                       Value memref);
+  std::pair<Value, Value>
+  getMemrefWithUniqueOwnership(OpBuilder &builder, Value memref, Block *block);
 
   /// Given two basic blocks and the values passed via block arguments to the
   /// destination block, compute the list of MemRefs that have to be retained in
diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.td b/mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.td
index c35fe417184ffd4..3e11432c65c5f08 100644
--- a/mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.td
+++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.td
@@ -39,7 +39,34 @@ def BufferDeallocationOpInterface :
         /*retType=*/"FailureOr<Operation *>",
         /*methodName=*/"process",
         /*args=*/(ins "DeallocationState &":$state,
-                      "const DeallocationOptions &":$options)>
+                      "const DeallocationOptions &":$options)>,
+      InterfaceMethod<
+        /*desc=*/[{
+          This method allows the implementing operation to specify custom logic
+          to materialize an ownership indicator value for the given MemRef typed
+          value it defines (including block arguments of nested regions). Since
+          the operation itself has more information about its semantics the
+          materialized IR can be more efficient compared to the default
+          implementation and avoid cloning MemRefs and/or doing alias checking
+          at runtime.
+          Note that the same logic could also be implemented in the 'process'
+          method above, however, the IR is always materialized then. If
+          it's desirable to only materialize the IR to compute an updated
+          ownership indicator when needed, it should be implemented using this
+          method (which is especially important if operations are created that
+          cannot be easily canonicalized away anymore).
+        }],
+        /*retType=*/"std::pair<Value, Value>",
+        /*methodName=*/"materializeUniqueOwnershipForMemref",
+        /*args=*/(ins "DeallocationState &":$state,
+                      "const DeallocationOptions &":$options,
+                      "OpBuilder &":$builder,
+                      "Value":$memref),
+        /*methodBody=*/[{}],
+        /*defaultImplementation=*/[{
+          return state.getMemrefWithUniqueOwnership(
+            builder, memref, memref.getParentBlock());
+        }]>,
   ];
 }
 
diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h
index ee91bfa57d12a39..0182ab93929cb8c 100644
--- a/mlir/include/mlir/InitAllDialects.h
+++ b/mlir/include/mlir/InitAllDialects.h
@@ -20,6 +20,7 @@
 #include "mlir/Dialect/Affine/IR/ValueBoundsOpInterfaceImpl.h"
 #include "mlir/Dialect/Arith/IR/Arith.h"
 #include "mlir/Dialect/Arith/IR/ValueBoundsOpInterfaceImpl.h"
+#include "mlir/Dialect/Arith/Transforms/BufferDeallocationOpInterfaceImpl.h"
 #include "mlir/Dialect/Arith/Transforms/BufferizableOpInterfaceImpl.h"
 #include "mlir/Dialect/ArmNeon/ArmNeonDialect.h"
 #include "mlir/Dialect/ArmSME/IR/ArmSME.h"
@@ -133,6 +134,7 @@ inline void registerAllDialects(DialectRegistry &registry) {
 
   // Register all external models.
   affine::registerValueBoundsOpInterfaceExternalModels(registry);
+  arith::registerBufferDeallocationOpInterfaceExternalModels(registry);
   arith::registerBufferizableOpInterfaceExternalModels(registry);
   arith::registerValueBoundsOpInterfaceExternalModels(registry);
   bufferization::func_ext::registerBufferizableOpInterfaceExternalModels(
diff --git a/mlir/lib/Dialect/Arith/Transforms/BufferDeallocationOpInterfaceImpl.cpp b/mlir/lib/Dialect/Arith/Transforms/BufferDeallocationOpInterfaceImpl.cpp
new file mode 100644
index 000000000000000..f2e7732e8ea4aa3
--- /dev/null
+++ b/mlir/lib/Dialect/Arith/Transforms/BufferDeallocationOpInterfaceImpl.cpp
@@ -0,0 +1,85 @@
+//===- BufferDeallocationOpInterfaceImpl.cpp ------------------------------===//
+//
+// 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 "mlir/Dialect/Arith/Transforms/BufferDeallocationOpInterfaceImpl.h"
+#include "mlir/Dialect/Arith/IR/Arith.h"
+#include "mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h"
+#include "mlir/Dialect/MemRef/IR/MemRef.h"
+#include "mlir/IR/Dialect.h"
+#include "mlir/IR/Operation.h"
+
+using namespace mlir;
+using namespace mlir::bufferization;
+
+namespace {
+/// Provides custom logic to materialize ownership indicator values for the
+/// result value of 'arith.select'. Instead of cloning or runtime alias
+/// checking, this implementation inserts another `arith.select` to choose the
+/// ownership indicator of the operand in the same way the original
+/// `arith.select` chooses the MemRef operand. If at least one of the operand's
+/// ownerships is 'Unknown', fall back to the default implementation.
+///
+/// Example:
+/// ```mlir
+/// // let ownership(%m0) := %o0
+/// // let ownership(%m1) := %o1
+/// %res = arith.select %cond, %m0, %m1
+/// ```
+/// The default implementation would insert a clone and replace all uses of the
+/// result of `arith.select` with that clone:
+/// ```mlir
+/// %res = arith.select %cond, %m0, %m1
+/// %clone = bufferization.clone %res
+/// // let ownership(%res) := 'Unknown'
+/// // let ownership(%clone) := %true
+/// // replace all uses of %res with %clone
+/// ```
+/// This implementation, on the other hand, materializes the following:
+/// ```mlir
+/// %res = arith.select %cond, %m0, %m1
+/// %res_ownership = arith.select %cond, %o0, %o1
+/// // let ownership(%res) := %res_ownership
+/// ```
+struct SelectOpInterface
+    : public BufferDeallocationOpInterface::ExternalModel<SelectOpInterface,
+                                                          arith::SelectOp> {
+  FailureOr<Operation *> process(Operation *op, DeallocationState &state,
+                                 const DeallocationOptions &options) const {
+    return op; // nothing to do
+  }
+
+  std::pair<Value, Value>
+  materializeUniqueOwnershipForMemref(Operation *op, DeallocationState &state,
+                                      const DeallocationOptions &options,
+                                      OpBuilder &builder, Value value) const {
+    auto selectOp = cast<arith::SelectOp>(op);
+    assert(value == selectOp.getResult() &&
+           "Value not defined by this operation");
+
+    Block *block = value.getParentBlock();
+    if (!state.getOwnership(selectOp.getTrueValue(), block).isUnique() ||
+        !state.getOwnership(selectOp.getFalseValue(), block).isUnique())
+      return state.getMemrefWithUniqueOwnership(builder, value,
+                                                value.getParentBlock());
+
+    Value ownership = builder.create<arith::SelectOp>(
+        op->getLoc(), selectOp.getCondition(),
+        state.getOwnership(selectOp.getTrueValue(), block).getIndicator(),
+        state.getOwnership(selectOp.getFalseValue(), block).getIndicator());
+    return {selectOp.getResult(), ownership};
+  }
+};
+
+} // namespace
+
+void mlir::arith::registerBufferDeallocationOpInterfaceExternalModels(
+    DialectRegistry &registry) {
+  registry.addExtension(+[](MLIRContext *ctx, ArithDialect *dialect) {
+    SelectOp::attachInterface<SelectOpInterface>(*ctx);
+  });
+}
diff --git a/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt b/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt
index a9b86b4d99256c0..02240601bcd35a1 100644
--- a/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_mlir_dialect_library(MLIRArithTransforms
+  BufferDeallocationOpInterfaceImpl.cpp
   BufferizableOpInterfaceImpl.cpp
   Bufferize.cpp
   EmulateUnsupportedFloats.cpp
diff --git a/mlir/lib/Dialect/Bufferization/IR/BufferDeallocationOpInterface.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferDeallocationOpInterface.cpp
index 2314cee2ff2c158..407d75e2426e9f9 100644
--- a/mlir/lib/Dialect/Bufferization/IR/BufferDeallocationOpInterface.cpp
+++ b/mlir/lib/Dialect/Bufferization/IR/BufferDeallocationOpInterface.cpp
@@ -134,8 +134,8 @@ void DeallocationState::getLiveMemrefsIn(Block *block,
 
 std::pair<Value, Value>
 DeallocationState::getMemrefWithUniqueOwnership(OpBuilder &builder,
-                                                Value memref) {
-  auto iter = ownershipMap.find({memref, memref.getParentBlock()});
+                                                Value memref, Block *block) {
+  auto iter = ownershipMap.find({memref, block});
   assert(iter != ownershipMap.end() &&
          "Value must already have been registered in the ownership map");
 
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp
index d4b8e0dff67bae4..02fb4d3c42fa521 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp
@@ -376,13 +376,24 @@ class BufferDeallocation {
   /// Given an SSA value of MemRef type, returns the same of a new SSA value
   /// which has 'Unique' ownership where the ownership indicator is guaranteed
   /// to be always 'true'.
-  Value getMemrefWithGuaranteedOwnership(OpBuilder &builder, Value memref);
+  Value materializeMemrefWithGuaranteedOwnership(OpBuilder &builder,
+                                                 Value memref, Block *block);
 
   /// Returns whether the given operation implements FunctionOpInterface, has
   /// private visibility, and the private-function-dynamic-ownership pass option
   /// is enabled.
   bool isFunctionWithoutDynamicOwnership(Operation *op);
 
+  /// Given an SSA value of MemRef type, this function queries the
+  /// BufferDeallocationOpInterface of the defining operation of 'memref' for a
+  /// materialized ownership indicator for 'memref'.  If the op does not
+  /// implement the interface or if the block for which the materialized value
+  /// is requested does not match the block in which 'memref' is defined, the
+  /// default implementation in
+  /// `DeallocationState::getMemrefWithUniqueOwnership` is queried instead.
+  std::pair<Value, Value>
+  materializeUniqueOwnership(OpBuilder &builder, Value memref, Block *block);
+
   /// Checks all the preconditions for operations implementing the
   /// FunctionOpInterface that have to hold for the deallocation to be
   /// applicable:
@@ -428,6 +439,28 @@ class BufferDeallocation {
 // BufferDeallocation Implementation
 //===----------------------------------------------------------------------===//
 
+std::pair<Value, Value>
+BufferDeallocation::materializeUniqueOwnership(OpBuilder &builder, Value memref,
+                                               Block *block) {
+  // The interface can only materialize ownership indicators in the same block
+  // as the defining op.
+  if (memref.getParentBlock() != block)
+    return state.getMemrefWithUniqueOwnership(builder, memref, block);
+
+  Operation *owner = memref.getDefiningOp();
+  if (!owner)
+    owner = memref.getParentBlock()->getParentOp();
+
+  // If the op implements the interface, query it for a materialized ownership
+  // value.
+  if (auto deallocOpInterface = dyn_cast<BufferDeallocationOpInterface>(owner))
+    return deallocOpInterface.materializeUniqueOwnershipForMemref(
+        state, options, builder, memref);
+
+  // Otherwise use the default implementation.
+  return state.getMemrefWithUniqueOwnership(builder, memref, block);
+}
+
 static bool regionOperatesOnMemrefValues(Region &region) {
   WalkResult result = region.walk([](Block *block) {
     if (llvm::any_of(block->getArguments(), isMemref))
@@ -677,11 +710,11 @@ BufferDeallocation::handleInterface(RegionBranchOpInterface op) {
   return newOp.getOperation();
 }
 
-Value BufferDeallocation::getMemrefWithGuaranteedOwnership(OpBuilder &builder,
-                                                           Value memref) {
+Value BufferDeallocation::materializeMemrefWithGuaranteedOwnership(
+    OpBuilder &builder, Value memref, Block *block) {
   // First, make sure we at least have 'Unique' ownership already.
   std::pair<Value, Value> newMemrefAndOnwership =
-      state.getMemrefWithUniqueOwnership(builder, memref);
+      materializeUniqueOwnership(builder, memref, block);
   Value newMemref = newMemrefAndOnwership.first;
   Value condition = newMemrefAndOnwership.second;
 
@@ -785,7 +818,7 @@ FailureOr<Operation *> BufferDeallocation::handleInterface(CallOpInterface op) {
         continue;
       }
       auto [memref, condition] =
-          state.getMemrefWithUniqueOwnership(builder, operand);
+          materializeUniqueOwnership(builder, operand, op->getBlock());
       newOperands.push_back(memref);
       ownershipIndicatorsToAdd.push_back(condition);
     }
@@ -868,7 +901,8 @@ BufferDeallocation::handleInterface(RegionBranchTerminatorOpInterface op) {
       if (!isMemref(val.get()))
         continue;
 
-      val.set(getMemrefWithGuaranteedOwnership(builder, val.get()));
+      val.set(materializeMemrefWithGuaranteedOwnership(builder, val.get(),
+                                                       op->getBlock()));
     }
   }
 
diff --git a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-callop-interface.mlir b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-callop-interface.mlir
index 67128fee3dfe0ab..bff06d4499938df 100644
--- a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-callop-interface.mlir
+++ b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-callop-interface.mlir
@@ -95,15 +95,15 @@ func.func @function_call_requries_merged_ownership_mid_block(%arg0: i1) {
 //  CHECK-NEXT:   return
 
 // CHECK-DYNAMIC-LABEL: func @function_call_requries_merged_ownership_mid_block
+//  CHECK-DYNAMIC-SAME: ([[ARG0:%.+]]: i1)
 //       CHECK-DYNAMIC:   [[ALLOC0:%.+]] = memref.alloc(
 //  CHECK-DYNAMIC-NEXT:   [[ALLOC1:%.+]] = memref.alloca(
-//  CHECK-DYNAMIC-NEXT:   [[SELECT:%.+]] = arith.select{{.*}}[[ALLOC0]], [[ALLOC1]]
-//  CHECK-DYNAMIC-NEXT:   [[CLONE:%.+]] = bufferization.clone [[SELECT]]
-//  CHECK-DYNAMIC-NEXT:   [[RET:%.+]]:2 = call @f([[CLONE]], %true{{[0-9_]*}})
+//  CHECK-DYNAMIC-NEXT:   [[SELECT:%.+]] = arith.select [[ARG0]], [[ALLOC0]], [[ALLOC1]]
+//  CHECK-DYNAMIC-NEXT:   [[RET:%.+]]:2 = call @f([[SELECT]], [[ARG0]])
 //  CHECK-DYNAMIC-NEXT:   test.copy
 //  CHECK-DYNAMIC-NEXT:   [[BASE:%[a-zA-Z0-9_]+]]{{.*}} = memref.extract_strided_metadata [[RET]]#0
-//  CHECK-DYNAMIC-NEXT:   bufferization.dealloc ([[ALLOC0]], [[CLONE]], [[BASE]] :
-//  CHECK-DYNAMIC-SAME:     if (%true{{[0-9_]*}}, %true{{[0-9_]*}}, [[RET]]#1)
+//  CHECK-DYNAMIC-NEXT:   bufferization.dealloc ([[ALLOC0]], [[BASE]] :
+//  CHECK-DYNAMIC-SAME:     if (%true{{[0-9_]*}}, [[RET]]#1)
 //   CHECK-DYNAMIC-NOT:     retain
 //  CHECK-DYNAMIC-NEXT:   return
 

>From 3e175cc6bb5370655970b7e0281565f3aff5759d Mon Sep 17 00:00:00 2001
From: sstwcw <su3e8a96kzlver at posteo.net>
Date: Thu, 14 Sep 2023 03:26:10 +0000
Subject: [PATCH 69/86] [clang-format] More on unbreakable strings in
 TypeScript (#66321)

Now. string literals in lines beginning with `export type` will not be
broken.

The case was missed in 5db201fb75e6.  I don't know TypeScript.  And
merging GitHub pull requests seems to be a little too easy.  So it got
committed before the reviewers had a chance to find edge cases.
---
 clang/lib/Format/ContinuationIndenter.cpp | 6 ++++--
 clang/unittests/Format/FormatTestJS.cpp   | 3 +++
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 75ab08de42ea0e8..6673b5c703b835f 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -2242,8 +2242,10 @@ ContinuationIndenter::createBreakableToken(const FormatToken &Current,
       return nullptr;
 
     // Strings in TypeScript types and dictionary keys can not be broken.
-    if (Style.isJavaScript() && (Current.is(TT_SelectorName) ||
-                                 State.Line->startsWith(Keywords.kw_type))) {
+    if (Style.isJavaScript() &&
+        (Current.is(TT_SelectorName) ||
+         State.Line->startsWith(Keywords.kw_type) ||
+         State.Line->startsWith(tok::kw_export, Keywords.kw_type))) {
       return nullptr;
     }
 
diff --git a/clang/unittests/Format/FormatTestJS.cpp b/clang/unittests/Format/FormatTestJS.cpp
index 309326569143df6..51543d0a54d8561 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -1604,6 +1604,9 @@ TEST_F(FormatTestJS, StringLiteralConcatenation) {
   verifyFormat("/* type */ type x =\n"
                "    'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';",
                getGoogleJSStyleWithColumns(20));
+  verifyFormat("export type x =\n"
+               "    'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';",
+               getGoogleJSStyleWithColumns(20));
   // Dictionary keys can't be broken. Values can be broken.
   verifyFormat("var w = {\n"
                "  'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx':\n"

>From 92c4a6b2b1d004475e9b22b9d7de025bed9b518a Mon Sep 17 00:00:00 2001
From: Alex Brachet <abrachet at google.com>
Date: Thu, 14 Sep 2023 08:47:21 -0400
Subject: [PATCH 70/86] [libc] Fix some warnings (#66366)

Some compilers will warn about dangling else and missleading lack of
parentheses.
---
 libc/src/__support/CPP/limits.h      | 4 ++--
 libc/test/src/ctype/isprint_test.cpp | 5 +++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/CPP/limits.h b/libc/src/__support/CPP/limits.h
index e42414523a76df7..46a1172c285020c 100644
--- a/libc/src/__support/CPP/limits.h
+++ b/libc/src/__support/CPP/limits.h
@@ -17,8 +17,8 @@ namespace cpp {
 // Some older gcc distributions don't define these for 32 bit targets.
 #ifndef LLONG_MAX
 constexpr size_t LLONG_BIT_WIDTH = sizeof(long long) * 8;
-constexpr long long LLONG_MAX = ~0LL ^ (1LL << LLONG_BIT_WIDTH - 1);
-constexpr long long LLONG_MIN = 1LL << LLONG_BIT_WIDTH - 1;
+constexpr long long LLONG_MAX = ~0LL ^ (1LL << (LLONG_BIT_WIDTH - 1));
+constexpr long long LLONG_MIN = 1LL << (LLONG_BIT_WIDTH - 1);
 constexpr unsigned long long ULLONG_MAX = ~0ULL;
 #endif
 
diff --git a/libc/test/src/ctype/isprint_test.cpp b/libc/test/src/ctype/isprint_test.cpp
index d7278fadc10fd52..08963209c1d4cb0 100644
--- a/libc/test/src/ctype/isprint_test.cpp
+++ b/libc/test/src/ctype/isprint_test.cpp
@@ -11,9 +11,10 @@
 
 TEST(LlvmLibcIsPrint, DefaultLocale) {
   for (int ch = -255; ch < 255; ++ch) {
-    if (' ' <= ch && ch <= '~') // A-Z, a-z, 0-9, punctuation, space.
+    if (' ' <= ch && ch <= '~') { // A-Z, a-z, 0-9, punctuation, space.
       EXPECT_NE(__llvm_libc::isprint(ch), 0);
-    else
+    } else {
       EXPECT_EQ(__llvm_libc::isprint(ch), 0);
+    }
   }
 }

>From 56d1b8445aef12bb888e4e43c9d1f6a0bd14fe5c Mon Sep 17 00:00:00 2001
From: Martin Erhart <merhart at google.com>
Date: Thu, 14 Sep 2023 12:57:49 +0000
Subject: [PATCH 71/86] [mlir][bufferization] Fix BAZEL build

---
 .../llvm-project-overlay/mlir/BUILD.bazel     | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
index 114216752d71907..9cdbe29587fed62 100644
--- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
@@ -9770,6 +9770,36 @@ gentbl_cc_library(
     ],
 )
 
+td_library(
+    name = "BufferDeallocationOpInterfaceTdFiles",
+    srcs = [
+        "include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.td",
+    ],
+    includes = ["include"],
+    deps = [
+        ":OpBaseTdFiles",
+    ],
+)
+
+gentbl_cc_library(
+    name = "BufferDeallocationOpInterfaceIncGen",
+    tbl_outs = [
+        (
+            ["-gen-op-interface-decls"],
+            "include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h.inc",
+        ),
+        (
+            ["-gen-op-interface-defs"],
+            "include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.cpp.inc",
+        ),
+    ],
+    tblgen = ":mlir-tblgen",
+    td_file = "include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.td",
+    deps = [
+        ":BufferDeallocationOpInterfaceTdFiles",
+    ],
+)
+
 td_library(
     name = "SubsetInsertionOpInterfaceTdFiles",
     srcs = [

>From 40b1a4f0f77eaea84715c77e4bf33f7085e23f10 Mon Sep 17 00:00:00 2001
From: Matthias Springer <me at m-sp.org>
Date: Thu, 14 Sep 2023 14:59:36 +0200
Subject: [PATCH 72/86] [mlir][transform] Fix crash when op is erased during
 transform.foreach (#66357)

Fixes a crash when an op, that is mapped to handle that a
`transform.foreach` iterates over, was erased (through the
`TrackingRewriter`). Erasing an op removes it from all mappings and
invalidates iterators. This is already taken care of when an op is
iterating over payload ops in its `apply` method, but not when another
transform op is erasing a tracked payload op.
---
 .../Transform/IR/TransformInterfaces.h        |  5 +++++
 .../Transform/IR/TransformInterfaces.cpp      | 14 ++++++++++++
 .../lib/Dialect/Transform/IR/TransformOps.cpp | 18 +++++++++++++--
 .../Dialect/Transform/test-interpreter.mlir   | 22 +++++++++++++++++++
 .../TestTransformDialectExtension.cpp         |  2 +-
 5 files changed, 58 insertions(+), 3 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h b/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h
index 114d79555dcef50..efd8d573936c332 100644
--- a/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h
+++ b/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h
@@ -1156,6 +1156,11 @@ bool isHandleConsumed(Value handle, transform::TransformOpInterface transform);
 void modifiesPayload(SmallVectorImpl<MemoryEffects::EffectInstance> &effects);
 void onlyReadsPayload(SmallVectorImpl<MemoryEffects::EffectInstance> &effects);
 
+/// Checks whether the transform op modifies the payload.
+bool doesModifyPayload(transform::TransformOpInterface transform);
+/// Checks whether the transform op reads the payload.
+bool doesReadPayload(transform::TransformOpInterface transform);
+
 /// Populates `consumedArguments` with positions of `block` arguments that are
 /// consumed by the operations in the `block`.
 void getConsumedBlockArguments(
diff --git a/mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp b/mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp
index ed987ac4b51646c..00450a1ff8f36cf 100644
--- a/mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp
+++ b/mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp
@@ -1904,6 +1904,20 @@ void transform::onlyReadsPayload(
   effects.emplace_back(MemoryEffects::Read::get(), PayloadIRResource::get());
 }
 
+bool transform::doesModifyPayload(transform::TransformOpInterface transform) {
+  auto iface = cast<MemoryEffectOpInterface>(transform.getOperation());
+  SmallVector<MemoryEffects::EffectInstance> effects;
+  iface.getEffects(effects);
+  return ::hasEffect<MemoryEffects::Write, PayloadIRResource>(effects);
+}
+
+bool transform::doesReadPayload(transform::TransformOpInterface transform) {
+  auto iface = cast<MemoryEffectOpInterface>(transform.getOperation());
+  SmallVector<MemoryEffects::EffectInstance> effects;
+  iface.getEffects(effects);
+  return ::hasEffect<MemoryEffects::Read, PayloadIRResource>(effects);
+}
+
 void transform::getConsumedBlockArguments(
     Block &block, llvm::SmallDenseSet<unsigned int> &consumedArguments) {
   SmallVector<MemoryEffects::EffectInstance> effects;
diff --git a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp
index 7bbbbba4134b184..a56adcfd7fd8472 100644
--- a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp
+++ b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp
@@ -1121,8 +1121,11 @@ transform::ForeachOp::apply(transform::TransformRewriter &rewriter,
                             transform::TransformResults &results,
                             transform::TransformState &state) {
   SmallVector<SmallVector<Operation *>> resultOps(getNumResults(), {});
-
-  for (Operation *op : state.getPayloadOps(getTarget())) {
+  // Store payload ops in a vector because ops may be removed from the mapping
+  // by the TrackingRewriter while the iteration is in progress.
+  SmallVector<Operation *> targets =
+      llvm::to_vector(state.getPayloadOps(getTarget()));
+  for (Operation *op : targets) {
     auto scope = state.make_region_scope(getBody());
     if (failed(state.mapBlockArguments(getIterationVariable(), {op})))
       return DiagnosedSilenceableFailure::definiteFailure();
@@ -1152,6 +1155,7 @@ void transform::ForeachOp::getEffects(
     SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
   BlockArgument iterVar = getIterationVariable();
   if (any_of(getBody().front().without_terminator(), [&](Operation &op) {
+
         return isHandleConsumed(iterVar, cast<TransformOpInterface>(&op));
       })) {
     consumesHandle(getTarget(), effects);
@@ -1159,6 +1163,16 @@ void transform::ForeachOp::getEffects(
     onlyReadsHandle(getTarget(), effects);
   }
 
+  if (any_of(getBody().front().without_terminator(), [&](Operation &op) {
+        return doesModifyPayload(cast<TransformOpInterface>(&op));
+      })) {
+    modifiesPayload(effects);
+  } else if (any_of(getBody().front().without_terminator(), [&](Operation &op) {
+               return doesReadPayload(cast<TransformOpInterface>(&op));
+             })) {
+    onlyReadsPayload(effects);
+  }
+
   for (Value result : getResults())
     producesHandle(result, effects);
 }
diff --git a/mlir/test/Dialect/Transform/test-interpreter.mlir b/mlir/test/Dialect/Transform/test-interpreter.mlir
index db97d0a0887576f..68e3a4851539690 100644
--- a/mlir/test/Dialect/Transform/test-interpreter.mlir
+++ b/mlir/test/Dialect/Transform/test-interpreter.mlir
@@ -691,6 +691,28 @@ transform.with_pdl_patterns {
 
 // -----
 
+// CHECK-LABEL: func @consume_in_foreach()
+//  CHECK-NEXT:   return
+func.func @consume_in_foreach() {
+  %0 = arith.constant 0 : index
+  %1 = arith.constant 1 : index
+  %2 = arith.constant 2 : index
+  %3 = arith.constant 3 : index
+  return
+}
+
+transform.sequence failures(propagate) {
+^bb1(%arg1: !transform.any_op):
+  %f = transform.structured.match ops{["arith.constant"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+  transform.foreach %f : !transform.any_op {
+  ^bb2(%arg2: !transform.any_op):
+    // expected-remark @below {{erasing}}
+    transform.test_emit_remark_and_erase_operand %arg2, "erasing" : !transform.any_op
+  }
+}
+
+// -----
+
 func.func @bar() {
   scf.execute_region {
     // expected-remark @below {{transform applied}}
diff --git a/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.cpp b/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.cpp
index afd5011f17c6d2b..21f9ff5999a5ed5 100644
--- a/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.cpp
+++ b/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.cpp
@@ -390,7 +390,7 @@ DiagnosedSilenceableFailure mlir::test::TestEmitRemarkAndEraseOperandOp::apply(
     transform::TransformResults &results, transform::TransformState &state) {
   emitRemark() << getRemark();
   for (Operation *op : state.getPayloadOps(getTarget()))
-    op->erase();
+    rewriter.eraseOp(op);
 
   if (getFailAfterErase())
     return emitSilenceableError() << "silenceable error";

>From 1f8fa8a832f037850fc16d67dba9918c21b414ff Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Thu, 14 Sep 2023 10:02:35 -0300
Subject: [PATCH 73/86] [libc] Fix start up crash on 32 bit systems (#66210)

This patch changes the default types of argc/argv so it's no longer a
uint64_t in all systems, instead, it's now a uintptr_t, which fixes
crashes in 32-bit systems that expect 32-bit types. This patch also adds
two uintptr_t types (EnvironType and AuxEntryType) for the same reason.

The patch also adds a PgrHdrTableType type behind an ifdef that's
Elf64_Phdr in 64-bit systems and Elf32_Phdr in 32-bit systems.
---
 libc/config/linux/app.h              |  9 ++++++---
 libc/startup/linux/riscv64/start.cpp | 24 +++++++++++++++++-------
 2 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/libc/config/linux/app.h b/libc/config/linux/app.h
index ffd0e01f7b5a457..40a45078f6c8f35 100644
--- a/libc/config/linux/app.h
+++ b/libc/config/linux/app.h
@@ -42,11 +42,14 @@ struct TLSImage {
 // ABI specifies it as an 8 byte value. Likewise, in the ARM64 ABI, arguments
 // are usually passed in registers.  x0 is a doubleword register, so this is
 // 64 bit for aarch64 as well.
-typedef uint64_t ArgcType;
+typedef uintptr_t ArgcType;
 
 // At the language level, argv is a char** value. However, we use uint64_t as
 // ABIs specify the argv vector be an |argc| long array of 8-byte values.
-typedef uint64_t ArgVEntryType;
+typedef uintptr_t ArgVEntryType;
+
+typedef uintptr_t EnvironType;
+typedef uintptr_t AuxEntryType;
 #else
 #error "argc and argv types are not defined for the target platform."
 #endif
@@ -74,7 +77,7 @@ struct AppProperties {
   TLSImage tls;
 
   // Environment data.
-  uint64_t *envPtr;
+  EnvironType *envPtr;
 };
 
 extern AppProperties app;
diff --git a/libc/startup/linux/riscv64/start.cpp b/libc/startup/linux/riscv64/start.cpp
index d68cc9219ecce7e..1bf05b94ad5acfe 100644
--- a/libc/startup/linux/riscv64/start.cpp
+++ b/libc/startup/linux/riscv64/start.cpp
@@ -118,10 +118,20 @@ using __llvm_libc::app;
 
 // TODO: Would be nice to use the aux entry structure from elf.h when available.
 struct AuxEntry {
-  uint64_t type;
-  uint64_t value;
+  __llvm_libc::AuxEntryType type;
+  __llvm_libc::AuxEntryType value;
 };
 
+#if defined(LIBC_TARGET_ARCH_IS_X86_64) ||                                     \
+    defined(LIBC_TARGET_ARCH_IS_AARCH64) ||                                    \
+    defined(LIBC_TARGET_ARCH_IS_RISCV64)
+typedef Elf64_Phdr PgrHdrTableType;
+#elif defined(LIBC_TARGET_ARCH_IS_RISCV32)
+typedef Elf32_Phdr PgrHdrTableType;
+#else
+#error "Program header table type is not defined for the target platform."
+#endif
+
 __attribute__((noinline)) static void do_start() {
   LIBC_INLINE_ASM(".option push\n\t"
                   ".option norelax\n\t"
@@ -135,8 +145,8 @@ __attribute__((noinline)) static void do_start() {
   // After the argv array, is a 8-byte long NULL value before the array of env
   // values. The end of the env values is marked by another 8-byte long NULL
   // value. We step over it (the "+ 1" below) to get to the env values.
-  uint64_t *env_ptr = app.args->argv + app.args->argc + 1;
-  uint64_t *env_end_marker = env_ptr;
+  __llvm_libc::ArgVEntryType *env_ptr = app.args->argv + app.args->argc + 1;
+  __llvm_libc::ArgVEntryType *env_end_marker = env_ptr;
   app.envPtr = env_ptr;
   while (*env_end_marker)
     ++env_end_marker;
@@ -146,13 +156,13 @@ __attribute__((noinline)) static void do_start() {
 
   // After the env array, is the aux-vector. The end of the aux-vector is
   // denoted by an AT_NULL entry.
-  Elf64_Phdr *programHdrTable = nullptr;
+  PgrHdrTableType *programHdrTable = nullptr;
   uintptr_t programHdrCount;
   for (AuxEntry *aux_entry = reinterpret_cast<AuxEntry *>(env_end_marker + 1);
        aux_entry->type != AT_NULL; ++aux_entry) {
     switch (aux_entry->type) {
     case AT_PHDR:
-      programHdrTable = reinterpret_cast<Elf64_Phdr *>(aux_entry->value);
+      programHdrTable = reinterpret_cast<PgrHdrTableType *>(aux_entry->value);
       break;
     case AT_PHNUM:
       programHdrCount = aux_entry->value;
@@ -167,7 +177,7 @@ __attribute__((noinline)) static void do_start() {
 
   app.tls.size = 0;
   for (uintptr_t i = 0; i < programHdrCount; ++i) {
-    Elf64_Phdr *phdr = programHdrTable + i;
+    PgrHdrTableType *phdr = programHdrTable + i;
     if (phdr->p_type != PT_TLS)
       continue;
     // TODO: p_vaddr value has to be adjusted for static-pie executables.

>From 0c11f6957fb784ec8bf3664d9e6a42af36a44738 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 14 Sep 2023 09:02:51 -0400
Subject: [PATCH 74/86] [lit][NFC] Remove stray character in docstring

---
 llvm/utils/lit/lit/TestingConfig.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/utils/lit/lit/TestingConfig.py b/llvm/utils/lit/lit/TestingConfig.py
index 76fd665020097dd..541bd01ef8e8f95 100644
--- a/llvm/utils/lit/lit/TestingConfig.py
+++ b/llvm/utils/lit/lit/TestingConfig.py
@@ -3,7 +3,7 @@
 
 
 class TestingConfig(object):
-    """ "
+    """
     TestingConfig - Information on the tests inside a suite.
     """
 

>From b577cedfc0b62e1943ecac9402c700f1e993b4e2 Mon Sep 17 00:00:00 2001
From: Nicolas Vasilache <nicolasvasilache at users.noreply.github.com>
Date: Thu, 14 Sep 2023 15:32:35 +0200
Subject: [PATCH 75/86] [mlir][Linalg] NFC - Simplify transform script

---
 mlir/test/Dialect/LLVM/transform-e2e.mlir | 21 ---------------------
 1 file changed, 21 deletions(-)

diff --git a/mlir/test/Dialect/LLVM/transform-e2e.mlir b/mlir/test/Dialect/LLVM/transform-e2e.mlir
index 777de75b1a47acc..2cb753a3d7fb8f3 100644
--- a/mlir/test/Dialect/LLVM/transform-e2e.mlir
+++ b/mlir/test/Dialect/LLVM/transform-e2e.mlir
@@ -29,33 +29,12 @@ transform.sequence failures(propagate) {
   // lowering TD macros.
   transform.apply_patterns to %f {
     transform.apply_patterns.vector.lower_contraction lowering_strategy = "outerproduct"
-  } : !transform.any_op
-
-  transform.apply_patterns to %f {
     transform.apply_patterns.vector.transfer_permutation_patterns
-  } : !transform.any_op
-
-  transform.apply_patterns to %f {
     transform.apply_patterns.vector.lower_multi_reduction lowering_strategy = "innerparallel"
-  } : !transform.any_op
-
-  transform.apply_patterns to %f {
     transform.apply_patterns.vector.split_transfer_full_partial split_transfer_strategy = "linalg-copy"
-  } : !transform.any_op
-
-  transform.apply_patterns to %f {
     transform.apply_patterns.vector.transfer_to_scf max_transfer_rank = 1 full_unroll = true
-  } : !transform.any_op
-
-  transform.apply_patterns to %f {
     transform.apply_patterns.vector.lower_transfer max_transfer_rank = 1
-  } : !transform.any_op
-
-  transform.apply_patterns to %f {
     transform.apply_patterns.vector.lower_shape_cast
-  } : !transform.any_op
-
-  transform.apply_patterns to %f {
     transform.apply_patterns.vector.lower_transpose lowering_strategy = "shuffle_1d"
   } : !transform.any_op
 }

>From 4d03670dd7ef5e5bbb9ebfea2273f96ff65c596e Mon Sep 17 00:00:00 2001
From: Paul Walker <paul.walker at arm.com>
Date: Fri, 11 Aug 2023 14:39:17 +0100
Subject: [PATCH 76/86] [IR] Enable load/store/alloca for arrays of scalable
 vectors.

Differential Revision: https://reviews.llvm.org/D158517
---
 llvm/docs/LangRef.rst                         |  20 ++--
 llvm/include/llvm/IR/Type.h                   |   3 +-
 llvm/lib/Analysis/InstructionSimplify.cpp     |   2 +-
 llvm/lib/IR/Operator.cpp                      |   6 +-
 llvm/lib/IR/Type.cpp                          |   5 +-
 llvm/lib/IR/Verifier.cpp                      |  14 +--
 llvm/lib/Transforms/IPO/GlobalOpt.cpp         |   2 +-
 .../InstCombineLoadStoreAlloca.cpp            |  16 +--
 .../InstCombine/InstructionCombining.cpp      |   4 +-
 .../Scalar/SeparateConstOffsetFromGEP.cpp     |   4 +-
 .../alloca-load-store-scalable-array.ll       | 106 ++++++++++++++++++
 .../rvv/alloca-load-store-scalable-array.ll   |  40 +++++++
 llvm/test/Other/scalable-vector-array.ll      |   8 --
 llvm/test/Transforms/GVN/opaque-ptr.ll        |  12 ++
 .../2022-08-23-ScalableVectorArrayCrash.ll    |  15 +++
 ...-can-replace-gep-idx-with-zero-typesize.ll |   7 ++
 .../test/Transforms/InstCombine/opaque-ptr.ll |  11 ++
 .../InstCombine/scalable-vector-array.ll      |  28 +++++
 llvm/test/Transforms/InstSimplify/gep.ll      |   9 ++
 .../Transforms/SROA/scalable-vector-array.ll  |  20 ++++
 .../AArch64/scalable-vector-geps.ll           |  37 ++++++
 llvm/test/Verifier/scalable-global-vars.ll    |  11 +-
 22 files changed, 324 insertions(+), 56 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/alloca-load-store-scalable-array.ll
 create mode 100644 llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-array.ll
 delete mode 100644 llvm/test/Other/scalable-vector-array.ll
 create mode 100644 llvm/test/Transforms/GlobalOpt/2022-08-23-ScalableVectorArrayCrash.ll
 create mode 100644 llvm/test/Transforms/InstCombine/scalable-vector-array.ll
 create mode 100644 llvm/test/Transforms/SROA/scalable-vector-array.ll

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index dc5c84de420d76c..f542e70bcfee810 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -742,16 +742,16 @@ an optional list of attached :ref:`metadata <metadata>`.
 Variables and aliases can have a
 :ref:`Thread Local Storage Model <tls_model>`.
 
-:ref:`Scalable vectors <t_vector>` cannot be global variables or members of
-arrays because their size is unknown at compile time. They are allowed in
-structs to facilitate intrinsics returning multiple values. Generally, structs
-containing scalable vectors are not considered "sized" and cannot be used in
-loads, stores, allocas, or GEPs. The only exception to this rule is for structs
-that contain scalable vectors of the same type (e.g. ``{<vscale x 2 x i32>,
-<vscale x 2 x i32>}`` contains the same type while ``{<vscale x 2 x i32>,
-<vscale x 2 x i64>}`` doesn't). These kinds of structs (we may call them
-homogeneous scalable vector structs) are considered sized and can be used in
-loads, stores, allocas, but not GEPs.
+Globals cannot be or contain :ref:`Scalable vectors <t_vector>` because their
+size is unknown at compile time. They are allowed in structs to facilitate
+intrinsics returning multiple values. Generally, structs containing scalable
+vectors are not considered "sized" and cannot be used in loads, stores, allocas,
+or GEPs. The only exception to this rule is for structs that contain scalable
+vectors of the same type (e.g. ``{<vscale x 2 x i32>, <vscale x 2 x i32>}``
+contains the same type while ``{<vscale x 2 x i32>, <vscale x 2 x i64>}``
+doesn't). These kinds of structs (we may call them homogeneous scalable vector
+structs) are considered sized and can be used in loads, stores, allocas, but
+not GEPs.
 
 Syntax::
 
diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h
index 118f53b2ba16aba..c12e899d58fa834 100644
--- a/llvm/include/llvm/IR/Type.h
+++ b/llvm/include/llvm/IR/Type.h
@@ -209,8 +209,7 @@ class Type {
   /// Return true if this is a target extension type with a scalable layout.
   bool isScalableTargetExtTy() const;
 
-  /// Return true if this is a scalable vector type or a target extension type
-  /// with a scalable layout.
+  /// Return true if this is a type whose size is a known multiple of vscale.
   bool isScalableTy() const;
 
   /// Return true if this is a FP type or a vector of FP.
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 5fe0d53c313d40e..2a3011075e47ed7 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4934,7 +4934,7 @@ static Value *simplifyGEPInst(Type *SrcTy, Value *Ptr,
     return UndefValue::get(GEPTy);
 
   bool IsScalableVec =
-      isa<ScalableVectorType>(SrcTy) || any_of(Indices, [](const Value *V) {
+      SrcTy->isScalableTy() || any_of(Indices, [](const Value *V) {
         return isa<ScalableVectorType>(V->getType());
       });
 
diff --git a/llvm/lib/IR/Operator.cpp b/llvm/lib/IR/Operator.cpp
index b57f3e3b2967eb9..d2a1f2eb49dafed 100644
--- a/llvm/lib/IR/Operator.cpp
+++ b/llvm/lib/IR/Operator.cpp
@@ -127,9 +127,7 @@ bool GEPOperator::accumulateConstantOffset(
   auto end = generic_gep_type_iterator<decltype(Index.end())>::end(Index.end());
   for (auto GTI = begin, GTE = end; GTI != GTE; ++GTI) {
     // Scalable vectors are multiplied by a runtime constant.
-    bool ScalableType = false;
-    if (isa<ScalableVectorType>(GTI.getIndexedType()))
-      ScalableType = true;
+    bool ScalableType = GTI.getIndexedType()->isScalableTy();
 
     Value *V = GTI.getOperand();
     StructType *STy = GTI.getStructTypeOrNull();
@@ -189,7 +187,7 @@ bool GEPOperator::collectOffset(
   for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
        GTI != GTE; ++GTI) {
     // Scalable vectors are multiplied by a runtime constant.
-    bool ScalableType = isa<ScalableVectorType>(GTI.getIndexedType());
+    bool ScalableType = GTI.getIndexedType()->isScalableTy();
 
     Value *V = GTI.getOperand();
     StructType *STy = GTI.getStructTypeOrNull();
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index f88d3ace64c26f6..97febcd99b4114f 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -58,6 +58,8 @@ bool Type::isIntegerTy(unsigned Bitwidth) const {
 }
 
 bool Type::isScalableTy() const {
+  if (const auto *ATy = dyn_cast<ArrayType>(this))
+    return ATy->getElementType()->isScalableTy();
   if (const auto *STy = dyn_cast<StructType>(this)) {
     SmallPtrSet<Type *, 4> Visited;
     return STy->containsScalableVectorType(&Visited);
@@ -658,8 +660,7 @@ ArrayType *ArrayType::get(Type *ElementType, uint64_t NumElements) {
 bool ArrayType::isValidElementType(Type *ElemTy) {
   return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
          !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy() &&
-         !ElemTy->isTokenTy() && !ElemTy->isX86_AMXTy() &&
-         !isa<ScalableVectorType>(ElemTy);
+         !ElemTy->isTokenTy() && !ElemTy->isX86_AMXTy();
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index c0f30a62b8bccc3..10d176380ebed94 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -850,17 +850,9 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
   }
 
   // Scalable vectors cannot be global variables, since we don't know
-  // the runtime size. If the global is an array containing scalable vectors,
-  // that will be caught by the isValidElementType methods in StructType or
-  // ArrayType instead.
-  Check(!isa<ScalableVectorType>(GV.getValueType()),
-        "Globals cannot contain scalable vectors", &GV);
-
-  if (auto *STy = dyn_cast<StructType>(GV.getValueType())) {
-    SmallPtrSet<Type *, 4> Visited;
-    Check(!STy->containsScalableVectorType(&Visited),
-          "Globals cannot contain scalable vectors", &GV);
-  }
+  // the runtime size.
+  Check(!GV.getValueType()->isScalableTy(),
+        "Globals cannot contain scalable types", &GV);
 
   // Check if it's a target extension type that disallows being used as a
   // global.
diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
index 658db532835a504..56a52d13c20d0cc 100644
--- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
@@ -390,7 +390,7 @@ static bool collectSRATypes(DenseMap<uint64_t, GlobalPart> &Parts,
       }
 
       // Scalable types not currently supported.
-      if (isa<ScalableVectorType>(Ty))
+      if (Ty->isScalableTy())
         return false;
 
       auto IsStored = [](Value *V, Constant *Initializer) {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
index 6e491acc1403859..e176d1bea25a0ed 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
@@ -804,7 +804,7 @@ static Instruction *unpackLoadToAggregate(InstCombinerImpl &IC, LoadInst &LI) {
       return nullptr;
 
     const DataLayout &DL = IC.getDataLayout();
-    auto EltSize = DL.getTypeAllocSize(ET);
+    TypeSize EltSize = DL.getTypeAllocSize(ET);
     const auto Align = LI.getAlign();
 
     auto *Addr = LI.getPointerOperand();
@@ -812,7 +812,7 @@ static Instruction *unpackLoadToAggregate(InstCombinerImpl &IC, LoadInst &LI) {
     auto *Zero = ConstantInt::get(IdxType, 0);
 
     Value *V = PoisonValue::get(T);
-    uint64_t Offset = 0;
+    TypeSize Offset = TypeSize::get(0, ET->isScalableTy());
     for (uint64_t i = 0; i < NumElements; i++) {
       Value *Indices[2] = {
         Zero,
@@ -820,9 +820,9 @@ static Instruction *unpackLoadToAggregate(InstCombinerImpl &IC, LoadInst &LI) {
       };
       auto *Ptr = IC.Builder.CreateInBoundsGEP(AT, Addr, ArrayRef(Indices),
                                                Name + ".elt");
+      auto EltAlign = commonAlignment(Align, Offset.getKnownMinValue());
       auto *L = IC.Builder.CreateAlignedLoad(AT->getElementType(), Ptr,
-                                             commonAlignment(Align, Offset),
-                                             Name + ".unpack");
+                                             EltAlign, Name + ".unpack");
       L->setAAMetadata(LI.getAAMetadata());
       V = IC.Builder.CreateInsertValue(V, L, i);
       Offset += EltSize;
@@ -957,7 +957,7 @@ static bool canReplaceGEPIdxWithZero(InstCombinerImpl &IC,
   Type *SourceElementType = GEPI->getSourceElementType();
   // Size information about scalable vectors is not available, so we cannot
   // deduce whether indexing at n is undefined behaviour or not. Bail out.
-  if (isa<ScalableVectorType>(SourceElementType))
+  if (SourceElementType->isScalableTy())
     return false;
 
   Type *AllocTy = GetElementPtrInst::getIndexedType(SourceElementType, Ops);
@@ -1323,7 +1323,7 @@ static bool unpackStoreToAggregate(InstCombinerImpl &IC, StoreInst &SI) {
       return false;
 
     const DataLayout &DL = IC.getDataLayout();
-    auto EltSize = DL.getTypeAllocSize(AT->getElementType());
+    TypeSize EltSize = DL.getTypeAllocSize(AT->getElementType());
     const auto Align = SI.getAlign();
 
     SmallString<16> EltName = V->getName();
@@ -1335,7 +1335,7 @@ static bool unpackStoreToAggregate(InstCombinerImpl &IC, StoreInst &SI) {
     auto *IdxType = Type::getInt64Ty(T->getContext());
     auto *Zero = ConstantInt::get(IdxType, 0);
 
-    uint64_t Offset = 0;
+    TypeSize Offset = TypeSize::get(0, AT->getElementType()->isScalableTy());
     for (uint64_t i = 0; i < NumElements; i++) {
       Value *Indices[2] = {
         Zero,
@@ -1344,7 +1344,7 @@ static bool unpackStoreToAggregate(InstCombinerImpl &IC, StoreInst &SI) {
       auto *Ptr =
           IC.Builder.CreateInBoundsGEP(AT, Addr, ArrayRef(Indices), AddrName);
       auto *Val = IC.Builder.CreateExtractValue(V, i, EltName);
-      auto EltAlign = commonAlignment(Align, Offset);
+      auto EltAlign = commonAlignment(Align, Offset.getKnownMinValue());
       Instruction *NS = IC.Builder.CreateAlignedStore(Val, Ptr, EltAlign);
       NS->setAAMetadata(SI.getAAMetadata());
       Offset += EltSize;
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 1b9943f7025ea6d..145386946320c40 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2005,7 +2005,7 @@ Instruction *InstCombinerImpl::visitGEPOfGEP(GetElementPtrInst &GEP,
     APInt Offset(DL.getIndexTypeSizeInBits(PtrTy), 0);
     if (NumVarIndices != Src->getNumIndices()) {
       // FIXME: getIndexedOffsetInType() does not handled scalable vectors.
-      if (isa<ScalableVectorType>(BaseType))
+      if (BaseType->isScalableTy())
         return nullptr;
 
       SmallVector<Value *> ConstantIndices;
@@ -2118,7 +2118,7 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
   SmallVector<Value *, 8> Indices(GEP.indices());
   Type *GEPType = GEP.getType();
   Type *GEPEltType = GEP.getSourceElementType();
-  bool IsGEPSrcEleScalable = isa<ScalableVectorType>(GEPEltType);
+  bool IsGEPSrcEleScalable = GEPEltType->isScalableTy();
   if (Value *V = simplifyGEPInst(GEPEltType, PtrOp, Indices, GEP.isInBounds(),
                                  SQ.getWithInstruction(&GEP)))
     return replaceInstUsesWith(GEP, V);
diff --git a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp
index 89d0b7c33e0d934..afd72cdd7dc0012 100644
--- a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp
+++ b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp
@@ -830,7 +830,7 @@ SeparateConstOffsetFromGEP::accumulateByteOffset(GetElementPtrInst *GEP,
   for (unsigned I = 1, E = GEP->getNumOperands(); I != E; ++I, ++GTI) {
     if (GTI.isSequential()) {
       // Constant offsets of scalable types are not really constant.
-      if (isa<ScalableVectorType>(GTI.getIndexedType()))
+      if (GTI.getIndexedType()->isScalableTy())
         continue;
 
       // Tries to extract a constant offset from this GEP index.
@@ -1019,7 +1019,7 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
   for (unsigned I = 1, E = GEP->getNumOperands(); I != E; ++I, ++GTI) {
     if (GTI.isSequential()) {
       // Constant offsets of scalable types are not really constant.
-      if (isa<ScalableVectorType>(GTI.getIndexedType()))
+      if (GTI.getIndexedType()->isScalableTy())
         continue;
 
       // Splits this GEP index into a variadic part and a constant offset, and
diff --git a/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-array.ll b/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-array.ll
new file mode 100644
index 000000000000000..49bdaf0fcde9418
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-array.ll
@@ -0,0 +1,106 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s | FileCheck %s
+
+target triple = "aarch64-unknown-linux-gnu"
+
+%my_subtype = type <vscale x 2 x double>
+%my_type = type [3 x %my_subtype]
+
+define void @array_1D(ptr %addr) #0 {
+; CHECK-LABEL: array_1D:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    str x29, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT:    addvl sp, sp, #-3
+; CHECK-NEXT:    .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 24 * VG
+; CHECK-NEXT:    .cfi_offset w29, -16
+; CHECK-NEXT:    ptrue p0.d
+; CHECK-NEXT:    ld1d { z0.d }, p0/z, [x0, #1, mul vl]
+; CHECK-NEXT:    ld1d { z1.d }, p0/z, [x0, #2, mul vl]
+; CHECK-NEXT:    ld1d { z2.d }, p0/z, [x0]
+; CHECK-NEXT:    st1d { z2.d }, p0, [sp]
+; CHECK-NEXT:    st1d { z1.d }, p0, [sp, #2, mul vl]
+; CHECK-NEXT:    st1d { z0.d }, p0, [sp, #1, mul vl]
+; CHECK-NEXT:    addvl sp, sp, #3
+; CHECK-NEXT:    ldr x29, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+entry:
+  %ret = alloca %my_type, align 8
+  %val = load %my_type, ptr %addr
+  store %my_type %val, ptr %ret, align 8
+  ret void
+}
+
+define %my_subtype @array_1D_extract(ptr %addr) #0 {
+; CHECK-LABEL: array_1D_extract:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    str x29, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT:    addvl sp, sp, #-3
+; CHECK-NEXT:    .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 24 * VG
+; CHECK-NEXT:    .cfi_offset w29, -16
+; CHECK-NEXT:    ptrue p0.d
+; CHECK-NEXT:    ld1d { z0.d }, p0/z, [x0, #1, mul vl]
+; CHECK-NEXT:    addvl sp, sp, #3
+; CHECK-NEXT:    ldr x29, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+entry:
+  %ret = alloca %my_type, align 8
+  %val = load %my_type, ptr %addr
+  %elt = extractvalue %my_type %val, 1
+  ret %my_subtype %elt
+}
+
+define void @array_1D_insert(ptr %addr, %my_subtype %elt) #0 {
+; CHECK-LABEL: array_1D_insert:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    str x29, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT:    addvl sp, sp, #-3
+; CHECK-NEXT:    .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 24 * VG
+; CHECK-NEXT:    .cfi_offset w29, -16
+; CHECK-NEXT:    ptrue p0.d
+; CHECK-NEXT:    ld1d { z1.d }, p0/z, [x0]
+; CHECK-NEXT:    ld1d { z2.d }, p0/z, [x0, #2, mul vl]
+; CHECK-NEXT:    st1d { z2.d }, p0, [sp, #2, mul vl]
+; CHECK-NEXT:    st1d { z1.d }, p0, [sp]
+; CHECK-NEXT:    st1d { z0.d }, p0, [sp, #1, mul vl]
+; CHECK-NEXT:    addvl sp, sp, #3
+; CHECK-NEXT:    ldr x29, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+entry:
+  %ret = alloca %my_type, align 8
+  %val = load %my_type, ptr %addr
+  %ins = insertvalue %my_type %val, %my_subtype %elt, 1
+  store %my_type %ins, ptr %ret, align 8
+  ret void
+}
+
+define void @array_2D(ptr %addr) #0 {
+; CHECK-LABEL: array_2D:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    str x29, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT:    addvl sp, sp, #-6
+; CHECK-NEXT:    .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x30, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 48 * VG
+; CHECK-NEXT:    .cfi_offset w29, -16
+; CHECK-NEXT:    ptrue p0.d
+; CHECK-NEXT:    ld1d { z0.d }, p0/z, [x0, #1, mul vl]
+; CHECK-NEXT:    ld1d { z1.d }, p0/z, [x0, #2, mul vl]
+; CHECK-NEXT:    ld1d { z2.d }, p0/z, [x0, #3, mul vl]
+; CHECK-NEXT:    ld1d { z3.d }, p0/z, [x0, #4, mul vl]
+; CHECK-NEXT:    ld1d { z4.d }, p0/z, [x0, #5, mul vl]
+; CHECK-NEXT:    ld1d { z5.d }, p0/z, [x0]
+; CHECK-NEXT:    st1d { z5.d }, p0, [sp]
+; CHECK-NEXT:    st1d { z4.d }, p0, [sp, #5, mul vl]
+; CHECK-NEXT:    st1d { z3.d }, p0, [sp, #4, mul vl]
+; CHECK-NEXT:    st1d { z2.d }, p0, [sp, #3, mul vl]
+; CHECK-NEXT:    st1d { z1.d }, p0, [sp, #2, mul vl]
+; CHECK-NEXT:    st1d { z0.d }, p0, [sp, #1, mul vl]
+; CHECK-NEXT:    addvl sp, sp, #6
+; CHECK-NEXT:    ldr x29, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+entry:
+  %ret = alloca [2 x %my_type], align 8
+  %val = load [2 x %my_type], ptr %addr
+  store [2 x %my_type] %val, ptr %ret, align 8
+  ret void
+}
+
+attributes #0 = { "target-features"="+sve" }
diff --git a/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-array.ll b/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-array.ll
new file mode 100644
index 000000000000000..1fe91c721f4dd2b
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-array.ll
@@ -0,0 +1,40 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc -mtriple=riscv64 -mattr=+v -verify-machineinstrs --riscv-no-aliases < %s | FileCheck %s
+
+target triple = "riscv64-unknown-unknown-elf"
+
+%my_type = type [3 x <vscale x 1 x double>]
+
+define void @test(ptr %addr) {
+; CHECK-LABEL: test:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addi sp, sp, -16
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    csrrs a1, vlenb, zero
+; CHECK-NEXT:    slli a1, a1, 2
+; CHECK-NEXT:    sub sp, sp, a1
+; CHECK-NEXT:    .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x04, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 16 + 4 * vlenb
+; CHECK-NEXT:    csrrs a1, vlenb, zero
+; CHECK-NEXT:    add a2, a0, a1
+; CHECK-NEXT:    vl1re64.v v8, (a2)
+; CHECK-NEXT:    slli a2, a1, 1
+; CHECK-NEXT:    vl1re64.v v9, (a0)
+; CHECK-NEXT:    add a0, a0, a2
+; CHECK-NEXT:    vl1re64.v v10, (a0)
+; CHECK-NEXT:    addi a0, sp, 16
+; CHECK-NEXT:    vs1r.v v9, (a0)
+; CHECK-NEXT:    add a2, a0, a2
+; CHECK-NEXT:    vs1r.v v10, (a2)
+; CHECK-NEXT:    add a0, a0, a1
+; CHECK-NEXT:    vs1r.v v8, (a0)
+; CHECK-NEXT:    csrrs a0, vlenb, zero
+; CHECK-NEXT:    slli a0, a0, 2
+; CHECK-NEXT:    add sp, sp, a0
+; CHECK-NEXT:    addi sp, sp, 16
+; CHECK-NEXT:    jalr zero, 0(ra)
+entry:
+  %ret = alloca %my_type, align 8
+  %val = load %my_type, ptr %addr
+  store %my_type %val, ptr %ret, align 8
+  ret void
+}
diff --git a/llvm/test/Other/scalable-vector-array.ll b/llvm/test/Other/scalable-vector-array.ll
deleted file mode 100644
index 4119bb6953b421c..000000000000000
--- a/llvm/test/Other/scalable-vector-array.ll
+++ /dev/null
@@ -1,8 +0,0 @@
-; RUN: not opt -S -passes=verify < %s 2>&1 | FileCheck %s
-
-;; Arrays cannot contain scalable vectors; make sure we detect them even
-;; when nested inside other aggregates.
-
-%ty = type { i64, [4 x <vscale x 256 x i1>] }
-; CHECK: error: invalid array element type
-; CHECK: %ty = type { i64, [4 x <vscale x 256 x i1>] }
diff --git a/llvm/test/Transforms/GVN/opaque-ptr.ll b/llvm/test/Transforms/GVN/opaque-ptr.ll
index 911a7eba16794a6..4a0f9d319501c88 100644
--- a/llvm/test/Transforms/GVN/opaque-ptr.ll
+++ b/llvm/test/Transforms/GVN/opaque-ptr.ll
@@ -52,6 +52,12 @@ define void @gep_cse_offset_canonicalization(ptr %p, i64 %idx, i64 %idx2) {
 ; CHECK-NEXT:    call void @use(ptr [[GEP5]])
 ; CHECK-NEXT:    call void @use(ptr [[GEP5_SAME]])
 ; CHECK-NEXT:    call void @use(ptr [[GEP5_DIFFERENT]])
+; CHECK-NEXT:    [[GEP6:%.*]] = getelementptr [4 x <vscale x 4 x i32>], ptr [[P]], i64 [[IDX]], i64 1
+; CHECK-NEXT:    [[GEP6_SAME:%.*]] = getelementptr [4 x <vscale x 4 x float>], ptr [[P]], i64 [[IDX]], i64 1
+; CHECK-NEXT:    [[GEP6_DIFFERENT:%.*]] = getelementptr [4 x <vscale x 4 x float>], ptr [[P]], i64 [[IDX2]], i64 1
+; CHECK-NEXT:    call void @use(ptr [[GEP6]])
+; CHECK-NEXT:    call void @use(ptr [[GEP6_SAME]])
+; CHECK-NEXT:    call void @use(ptr [[GEP6_DIFFERENT]])
 ; CHECK-NEXT:    ret void
 ;
   %gep1 = getelementptr i64, ptr %p, i64 1
@@ -89,6 +95,12 @@ define void @gep_cse_offset_canonicalization(ptr %p, i64 %idx, i64 %idx2) {
   call void @use(ptr %gep5)
   call void @use(ptr %gep5.same)
   call void @use(ptr %gep5.different)
+  %gep6 = getelementptr [4 x <vscale x 4 x i32>], ptr %p, i64 %idx, i64 1
+  %gep6.same = getelementptr [4 x <vscale x 4 x float>], ptr %p, i64 %idx, i64 1
+  %gep6.different = getelementptr [4 x <vscale x 4 x float>], ptr %p, i64 %idx2, i64 1
+  call void @use(ptr %gep6)
+  call void @use(ptr %gep6.same)
+  call void @use(ptr %gep6.different)
   ret void
 }
 
diff --git a/llvm/test/Transforms/GlobalOpt/2022-08-23-ScalableVectorArrayCrash.ll b/llvm/test/Transforms/GlobalOpt/2022-08-23-ScalableVectorArrayCrash.ll
new file mode 100644
index 000000000000000..1f358ec850bc492
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/2022-08-23-ScalableVectorArrayCrash.ll
@@ -0,0 +1,15 @@
+; RUN: opt -passes=globalopt < %s
+
+; Ensure we don't ICE by trying to optimize a scalable vector load of a global
+; variable.
+
+%struct.xxx = type <{ [96 x i8] }>
+
+ at .bss = internal unnamed_addr global %struct.xxx zeroinitializer, align 32
+
+define dso_local void @foo() local_unnamed_addr align 16 {
+L.entry:
+  store [4 x <vscale x 2 x double>] zeroinitializer, ptr @.bss, align 1
+  %0 = load [4 x <vscale x 2 x double>], ptr @.bss, align 8
+  unreachable
+}
diff --git a/llvm/test/Transforms/InstCombine/gep-can-replace-gep-idx-with-zero-typesize.ll b/llvm/test/Transforms/InstCombine/gep-can-replace-gep-idx-with-zero-typesize.ll
index 6514158966ac590..5be2b90bf7a626a 100644
--- a/llvm/test/Transforms/InstCombine/gep-can-replace-gep-idx-with-zero-typesize.ll
+++ b/llvm/test/Transforms/InstCombine/gep-can-replace-gep-idx-with-zero-typesize.ll
@@ -18,3 +18,10 @@ define void @can_replace_gep_idx_with_zero_typesize(i64 %n, ptr %a, i64 %b) {
   call void @do_something(<vscale x 4 x i32> %tmp)
   ret void
 }
+
+define void @can_replace_gep_idx_with_zero_typesize_2(i64 %n, ptr %a, i64 %b) {
+  %idx = getelementptr [2 x <vscale x 4 x i32>], ptr %a, i64 %b, i64 0
+  %tmp = load <vscale x 4 x i32>, ptr %idx
+  call void @do_something(<vscale x 4 x i32> %tmp)
+  ret void
+}
diff --git a/llvm/test/Transforms/InstCombine/opaque-ptr.ll b/llvm/test/Transforms/InstCombine/opaque-ptr.ll
index 4f12fa45e9ecadd..900d3f142a6ff79 100644
--- a/llvm/test/Transforms/InstCombine/opaque-ptr.ll
+++ b/llvm/test/Transforms/InstCombine/opaque-ptr.ll
@@ -298,6 +298,17 @@ define ptr @geps_combinable_scalable(ptr %a, i64 %idx) {
   ret ptr %a3
 }
 
+define ptr @geps_combinable_scalable_vector_array(ptr %a, i64 %idx) {
+; CHECK-LABEL: @geps_combinable_scalable_vector_array(
+; CHECK-NEXT:    [[A2:%.*]] = getelementptr inbounds [4 x <vscale x 2 x i32>], ptr [[A:%.*]], i64 1
+; CHECK-NEXT:    [[A3:%.*]] = getelementptr inbounds i8, ptr [[A2]], i64 4
+; CHECK-NEXT:    ret ptr [[A3]]
+;
+  %a2 = getelementptr inbounds [4 x <vscale x 2 x i32>], ptr %a, i64 1
+  %a3 = getelementptr inbounds i8, ptr %a2, i32 4
+  ret ptr %a3
+}
+
 define i1 @compare_geps_same_indices(ptr %a, ptr %b, i64 %idx) {
 ; CHECK-LABEL: @compare_geps_same_indices(
 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[A:%.*]], [[B:%.*]]
diff --git a/llvm/test/Transforms/InstCombine/scalable-vector-array.ll b/llvm/test/Transforms/InstCombine/scalable-vector-array.ll
new file mode 100644
index 000000000000000..d03184766b4a682
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/scalable-vector-array.ll
@@ -0,0 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
+; RUN: opt -passes=instcombine -S < %s | FileCheck %s
+
+define <vscale x 4 x i32> @load(ptr %x) {
+; CHECK-LABEL: define <vscale x 4 x i32> @load
+; CHECK-SAME: (ptr [[X:%.*]]) {
+; CHECK-NEXT:    [[A_ELT1:%.*]] = getelementptr inbounds [2 x <vscale x 4 x i32>], ptr [[X]], i64 0, i64 1
+; CHECK-NEXT:    [[A_UNPACK2:%.*]] = load <vscale x 4 x i32>, ptr [[A_ELT1]], align 16
+; CHECK-NEXT:    ret <vscale x 4 x i32> [[A_UNPACK2]]
+;
+  %a = load [2 x <vscale x 4 x i32>], ptr %x
+  %b = extractvalue [2 x <vscale x 4 x i32>] %a, 1
+  ret <vscale x 4 x i32> %b
+}
+
+define void @store(ptr %x, <vscale x 4 x i32> %y, <vscale x 4 x i32> %z) {
+; CHECK-LABEL: define void @store
+; CHECK-SAME: (ptr [[X:%.*]], <vscale x 4 x i32> [[Y:%.*]], <vscale x 4 x i32> [[Z:%.*]]) {
+; CHECK-NEXT:    store <vscale x 4 x i32> [[Y]], ptr [[X]], align 16
+; CHECK-NEXT:    [[X_REPACK1:%.*]] = getelementptr inbounds [2 x <vscale x 4 x i32>], ptr [[X]], i64 0, i64 1
+; CHECK-NEXT:    store <vscale x 4 x i32> [[Z]], ptr [[X_REPACK1]], align 16
+; CHECK-NEXT:    ret void
+;
+  %a = insertvalue [2 x <vscale x 4 x i32>] poison, <vscale x 4 x i32> %y, 0
+  %b = insertvalue [2 x <vscale x 4 x i32>] %a, <vscale x 4 x i32> %z, 1
+  store [2 x <vscale x 4 x i32>] %b, ptr %x
+  ret void
+}
diff --git a/llvm/test/Transforms/InstSimplify/gep.ll b/llvm/test/Transforms/InstSimplify/gep.ll
index 5e70c2ca37c3a2e..281c286ef36ea2f 100644
--- a/llvm/test/Transforms/InstSimplify/gep.ll
+++ b/llvm/test/Transforms/InstSimplify/gep.ll
@@ -358,3 +358,12 @@ define <8 x ptr> @gep_vector_index_op3_poison_constant_index_afterwards(ptr %ptr
   %res = getelementptr inbounds %t.3, ptr %ptr, i64 0, i32 1, <8 x i64> poison, i32 1
   ret <8 x ptr> %res
 }
+
+define i64 @gep_array_of_scalable_vectors_ptrdiff(ptr %ptr) {
+  %c1 = getelementptr inbounds [8 x <vscale x 4 x i32>], ptr %ptr, i64 4
+  %c2 = getelementptr inbounds [8 x <vscale x 4 x i32>], ptr %ptr, i64 6
+  %c1.int = ptrtoint ptr %c1 to i64
+  %c2.int = ptrtoint ptr %c2 to i64
+  %diff = sub i64 %c2.int, %c1.int
+  ret i64 %diff
+}
diff --git a/llvm/test/Transforms/SROA/scalable-vector-array.ll b/llvm/test/Transforms/SROA/scalable-vector-array.ll
new file mode 100644
index 000000000000000..dbb6b4cbea47fb5
--- /dev/null
+++ b/llvm/test/Transforms/SROA/scalable-vector-array.ll
@@ -0,0 +1,20 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
+; RUN: opt < %s -passes='sroa<preserve-cfg>' -S | FileCheck %s
+; RUN: opt < %s -passes='sroa<modify-cfg>' -S | FileCheck %s
+
+; This test checks that SROA runs mem2reg on arrays of scalable vectors.
+
+define [ 2 x <vscale x 4 x i32> ] @alloca(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {
+; CHECK-LABEL: define [2 x <vscale x 4 x i32>] @alloca
+; CHECK-SAME: (<vscale x 4 x i32> [[X:%.*]], <vscale x 4 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:    [[AGG0:%.*]] = insertvalue [2 x <vscale x 4 x i32>] poison, <vscale x 4 x i32> [[X]], 0
+; CHECK-NEXT:    [[AGG1:%.*]] = insertvalue [2 x <vscale x 4 x i32>] [[AGG0]], <vscale x 4 x i32> [[Y]], 1
+; CHECK-NEXT:    ret [2 x <vscale x 4 x i32>] [[AGG1]]
+;
+  %addr = alloca [ 2 x <vscale x 4 x i32> ], align 4
+  %agg0 = insertvalue [ 2 x <vscale x 4 x i32> ] poison, <vscale x 4 x i32> %x, 0
+  %agg1 = insertvalue [ 2 x <vscale x 4 x i32> ] %agg0, <vscale x 4 x i32> %y, 1
+  store [ 2 x <vscale x 4 x i32> ] %agg1, ptr %addr, align 4
+  %val = load [ 2 x <vscale x 4 x i32> ], ptr %addr, align 4
+  ret [ 2 x <vscale x 4 x i32> ] %val
+}
diff --git a/llvm/test/Transforms/SeparateConstOffsetFromGEP/AArch64/scalable-vector-geps.ll b/llvm/test/Transforms/SeparateConstOffsetFromGEP/AArch64/scalable-vector-geps.ll
index 2ceac4c44d10f4c..31d166506a4e48f 100644
--- a/llvm/test/Transforms/SeparateConstOffsetFromGEP/AArch64/scalable-vector-geps.ll
+++ b/llvm/test/Transforms/SeparateConstOffsetFromGEP/AArch64/scalable-vector-geps.ll
@@ -28,4 +28,41 @@ define ptr @test2(ptr %base, i64 %idx) {
   ret ptr %gep
 }
 
+; Index is implicitly multiplied by vscale and so not really constant.
+define ptr @test3(ptr %base, i64 %idx) #0 {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:    [[IDX_NEXT:%.*]] = add nuw nsw i64 [[IDX:%.*]], 1
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr [8 x <vscale x 4 x float>], ptr [[BASE:%.*]], i64 [[IDX_NEXT]]
+; CHECK-NEXT:    ret ptr [[GEP]]
+;
+  %idx.next = add nuw nsw i64 %idx, 1
+  %gep = getelementptr [8 x <vscale x 4 x float>], ptr %base, i64 %idx.next
+  ret ptr %gep
+}
+
+; Indices are implicitly multiplied by vscale and so not really constant.
+define ptr @test4(ptr %base, i64 %idx) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:    [[IDX_NEXT:%.*]] = add nuw nsw i64 [[IDX:%.*]], 1
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr [8 x <vscale x 4 x float>], ptr [[BASE:%.*]], i64 3, i64 [[IDX_NEXT]]
+; CHECK-NEXT:    ret ptr [[GEP]]
+;
+  %idx.next = add nuw nsw i64 %idx, 1
+  %gep = getelementptr [8 x <vscale x 4 x float>], ptr %base, i64 3, i64 %idx.next
+  ret ptr %gep
+}
+
+; Whilst the first two indices are not constant, the calculation of the third
+; index does contain a constant that can be extracted.
+define ptr @test5(ptr %base, i64 %idx) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr [8 x <vscale x 4 x float>], ptr [[BASE:%.*]], i64 1, i64 3, i64 [[IDX:%.*]]
+; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr float, ptr [[TMP1]], i64 1
+; CHECK-NEXT:    ret ptr [[GEP2]]
+;
+  %idx.next = add nuw nsw i64 %idx, 1
+  %gep = getelementptr [8 x <vscale x 4 x float>], ptr %base, i64 1, i64 3, i64 %idx.next
+  ret ptr %gep
+}
+
 attributes #0 = { "target-features"="+sve" }
diff --git a/llvm/test/Verifier/scalable-global-vars.ll b/llvm/test/Verifier/scalable-global-vars.ll
index 740cd23a2888a1b..81882261e664ef6 100644
--- a/llvm/test/Verifier/scalable-global-vars.ll
+++ b/llvm/test/Verifier/scalable-global-vars.ll
@@ -3,14 +3,15 @@
 ;; Global variables cannot be scalable vectors, since we don't
 ;; know the size at compile time.
 
-; CHECK: Globals cannot contain scalable vectors
+; CHECK: Globals cannot contain scalable types
 ; CHECK-NEXT: ptr @ScalableVecGlobal
 @ScalableVecGlobal = global <vscale x 4 x i32> zeroinitializer
 
-; CHECK-NEXT: Globals cannot contain scalable vectors
+; CHECK-NEXT: Globals cannot contain scalable types
+; CHECK-NEXT: ptr @ScalableVecArrayGlobal
+ at ScalableVecArrayGlobal = global [ 8 x  <vscale x 4 x i32> ] zeroinitializer
+
+; CHECK-NEXT: Globals cannot contain scalable types
 ; CHECK-NEXT: ptr @ScalableVecStructGlobal
 @ScalableVecStructGlobal = global { i32,  <vscale x 4 x i32> } zeroinitializer
 
-;; Global _pointers_ to scalable vectors are fine
-; CHECK-NOT: Globals cannot contain scalable vectors
- at ScalableVecPtr = global ptr zeroinitializer

>From ff702f37a109143361d788a5a5272caac907a7cf Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Thu, 14 Sep 2023 10:08:20 -0400
Subject: [PATCH 77/86] [lit] Fix some issues from --per-test-coverage (#65242)

D154280 (landed in 64d19542e78a in July, 2023) implements
`--per-test-coverage` (which can also be specified via
`lit_config.per_test_coverage`).  However, it has a few issues, which
the current patch addresses:

1. D154280 implements `--per-test-coverage` only for the case that lit
   is configured to use an external shell.  The current patch extends
   the implementation to lit's internal shell.

2. In the case that lit is configured to use an external shell,
   regardless of whether `--per-test-coverage` is actually specified,
   D154280 causes `%dbg(RUN: at line N)` to be expanded in RUN lines
   early and in a manner that is specific to sh-like shells.  As a
   result, later code in lit that expands it in a shell-specific
   manner is useless as there's nothing left to expand.  The current
   patch cleans up the implementation to avoid useless code.

3. Because of issue 2, D154280 corrupts support for windows `cmd` as
   an external shell (effectively comments out all RUN lines with
   `:`).  The current patch happens to fix that particular corruption
   by addressing issue 2.  However, D122569 (landed in 1041a9642ba0 in
   April, 2022) had already broken support for windows `cmd` as an
   external shell (discards RUN lines when expanding `%dbg(RUN: at
   line N)`).  The current patch does not attempt to fix that bug.
   For further details, see the PR discussion of the current patch.

The current patch addresses the above issues by implementing
`--per-test-coverage` before selecting the shell (internal or
external) and by leaving `%dbg(RUN: at line N)` unexpanded there.
Thus, it is expanded later in a shell-specific manner, as before
D154280.

This patch introduces `buildPdbgCommand` into lit's implementation to
encapsulate the process of building (or rebuilding in the case of the
`--per-test-coverage` implementation) a full `%dbg(RUN: at line N)
cmd` line and asserting that the result matches `kPdbgRegex`.  It also
cleans up that and all other uses of `kPdbgRegex` to operate on the
full line with `re.fullmatch` not `re.match`.  This change better
reflects the intention in every case, but it is expected to be NFC
because `kPdbgRegex` ends in `.*` and thus avoids the difference
between `re.fullmatch` and `re.match`.  The only caveat is that `.*`
does not match newlines, but RUN lines cannot contain newlines
currently, so this caveat currently shouldn't matter in practice.

The original `--per-test-coverage` implementation avoided accumulating
`export LLVM_PROFILE_FILE={profile}` insertions across retries (due to
`ALLOW_RETRIES`) by skipping the insertion if `%dbg(RUN: at line N)`
was not present and thus had already been expanded.  However, the
current patch makes sure the insertions also happen for commands
without `%dbg(RUN: at line N)`, such as preamble commands or some
commands from other lit test formats.  Thus, the current patch
implements a different mechanism to avoid accumulating those
insertions (see code comments).
---
 llvm/utils/lit/lit/TestRunner.py              | 65 ++++++++++++-------
 .../per-test-coverage-by-lit-cfg/lit.cfg      |  5 +-
 .../per-test-coverage-by-lit-cfg.py           |  5 +-
 .../tests/Inputs/per-test-coverage/lit.cfg    |  6 +-
 .../per-test-coverage/per-test-coverage.py    |  5 +-
 llvm/utils/lit/tests/allow-retries.py         | 12 ++++
 .../lit/tests/per-test-coverage-by-lit-cfg.py | 26 ++++++--
 llvm/utils/lit/tests/per-test-coverage.py     | 26 ++++++--
 8 files changed, 110 insertions(+), 40 deletions(-)

diff --git a/llvm/utils/lit/lit/TestRunner.py b/llvm/utils/lit/lit/TestRunner.py
index 88755297c8e791a..b2c50f563696fe2 100644
--- a/llvm/utils/lit/lit/TestRunner.py
+++ b/llvm/utils/lit/lit/TestRunner.py
@@ -57,6 +57,14 @@ def __init__(self, command, message):
 kPdbgRegex = "%dbg\\(([^)'\"]*)\\)(.*)"
 
 
+def buildPdbgCommand(msg, cmd):
+    res = f"%dbg({msg}) {cmd}"
+    assert re.fullmatch(
+        kPdbgRegex, res
+    ), f"kPdbgRegex expected to match actual %dbg usage: {res}"
+    return res
+
+
 class ShellEnvironment(object):
 
     """Mutable shell environment containing things like CWD and env vars.
@@ -985,7 +993,7 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
 def executeScriptInternal(test, litConfig, tmpBase, commands, cwd):
     cmds = []
     for i, ln in enumerate(commands):
-        match = re.match(kPdbgRegex, ln)
+        match = re.fullmatch(kPdbgRegex, ln)
         if match:
             command = match.group(2)
             ln = commands[i] = match.expand(": '\\1'; \\2" if command else ": '\\1'")
@@ -1067,25 +1075,10 @@ def executeScriptInternal(test, litConfig, tmpBase, commands, cwd):
 def executeScript(test, litConfig, tmpBase, commands, cwd):
     bashPath = litConfig.getBashPath()
     isWin32CMDEXE = litConfig.isWindows and not bashPath
-    coverage_index = 0  # Counter for coverage file index
     script = tmpBase + ".script"
     if isWin32CMDEXE:
         script += ".bat"
 
-    # Set unique LLVM_PROFILE_FILE for each run command
-    for j, ln in enumerate(commands):
-        match = re.match(kPdbgRegex, ln)
-        if match:
-            command = match.group(2)
-            commands[j] = match.expand(": '\\1'; \\2" if command else ": '\\1'")
-            if litConfig.per_test_coverage:
-                # Extract the test case name from the test object
-                test_case_name = test.path_in_suite[-1]
-                test_case_name = test_case_name.rsplit(".", 1)[0]  # Remove the file extension
-                llvm_profile_file = f"{test_case_name}{coverage_index}.profraw"
-                commands[j] = f"export LLVM_PROFILE_FILE={llvm_profile_file} && {commands[j]}"
-                coverage_index += 1
-
     # Write script file
     mode = "w"
     open_kwargs = {}
@@ -1096,7 +1089,7 @@ def executeScript(test, litConfig, tmpBase, commands, cwd):
     f = open(script, mode, **open_kwargs)
     if isWin32CMDEXE:
         for i, ln in enumerate(commands):
-            match = re.match(kPdbgRegex, ln)
+            match = re.fullmatch(kPdbgRegex, ln)
             if match:
                 command = match.group(2)
                 commands[i] = match.expand(
@@ -1109,7 +1102,7 @@ def executeScript(test, litConfig, tmpBase, commands, cwd):
         f.write("\n at if %ERRORLEVEL% NEQ 0 EXIT\n".join(commands))
     else:
         for i, ln in enumerate(commands):
-            match = re.match(kPdbgRegex, ln)
+            match = re.fullmatch(kPdbgRegex, ln)
             if match:
                 command = match.group(2)
                 commands[i] = match.expand(": '\\1'; \\2" if command else ": '\\1'")
@@ -1837,13 +1830,7 @@ def _handleCommand(cls, line_number, line, output, keyword):
         if not output or not output[-1].add_continuation(line_number, keyword, line):
             if output is None:
                 output = []
-            pdbg = "%dbg({keyword} at line {line_number})".format(
-                keyword=keyword, line_number=line_number
-            )
-            assert re.match(
-                kPdbgRegex + "$", pdbg
-            ), "kPdbgRegex expected to match actual %dbg usage"
-            line = "{pdbg} {real_command}".format(pdbg=pdbg, real_command=line)
+            line = buildPdbgCommand(f"{keyword} at line {line_number}", line)
             output.append(CommandDirective(line_number, line_number, keyword, line))
         return output
 
@@ -2048,6 +2035,27 @@ def parseIntegratedTestScript(test, additional_parsers=[], require_script=True):
 
 def _runShTest(test, litConfig, useExternalSh, script, tmpBase):
     def runOnce(execdir):
+        # Set unique LLVM_PROFILE_FILE for each run command
+        if litConfig.per_test_coverage:
+            # Extract the test case name from the test object, and remove the
+            # file extension.
+            test_case_name = test.path_in_suite[-1]
+            test_case_name = test_case_name.rsplit(".", 1)[0]
+            coverage_index = 0  # Counter for coverage file index
+            for i, ln in enumerate(script):
+                match = re.fullmatch(kPdbgRegex, ln)
+                if match:
+                    dbg = match.group(1)
+                    command = match.group(2)
+                else:
+                    command = ln
+                profile = f"{test_case_name}{coverage_index}.profraw"
+                coverage_index += 1
+                command = f"export LLVM_PROFILE_FILE={profile}; {command}"
+                if match:
+                    command = buildPdbgCommand(dbg, command)
+                script[i] = command
+
         if useExternalSh:
             res = executeScript(test, litConfig, tmpBase, script, execdir)
         else:
@@ -2071,7 +2079,14 @@ def runOnce(execdir):
     # Re-run failed tests up to test.allowed_retries times.
     execdir = os.path.dirname(test.getExecPath())
     attempts = test.allowed_retries + 1
+    scriptInit = script
     for i in range(attempts):
+        # runOnce modifies script, but applying the modifications again to the
+        # result can corrupt script, so we restore the original upon a retry.
+        # A cleaner solution would be for runOnce to encapsulate operating on a
+        # copy of script, but we actually want it to modify the original script
+        # so we can print the modified version under "Script:" below.
+        script = scriptInit[:]
         res = runOnce(execdir)
         if isinstance(res, lit.Test.Result):
             return res
diff --git a/llvm/utils/lit/tests/Inputs/per-test-coverage-by-lit-cfg/lit.cfg b/llvm/utils/lit/tests/Inputs/per-test-coverage-by-lit-cfg/lit.cfg
index 186c81ebd172831..b83d61eec595b5d 100644
--- a/llvm/utils/lit/tests/Inputs/per-test-coverage-by-lit-cfg/lit.cfg
+++ b/llvm/utils/lit/tests/Inputs/per-test-coverage-by-lit-cfg/lit.cfg
@@ -3,6 +3,9 @@ import os
 
 config.name = "per-test-coverage-by-lit-cfg"
 config.suffixes = [".py"]
-config.test_format = lit.formats.ShTest(execute_external=True)
+config.test_format = lit.formats.ShTest(
+    execute_external=eval(lit_config.params.get("execute_external")),
+    preamble_commands=["%{python} %s | FileCheck -DINDEX=0 %s"]
+)
 lit_config.per_test_coverage = True
 config.substitutions.append(("%{python}", '"%s"' % (sys.executable)))
diff --git a/llvm/utils/lit/tests/Inputs/per-test-coverage-by-lit-cfg/per-test-coverage-by-lit-cfg.py b/llvm/utils/lit/tests/Inputs/per-test-coverage-by-lit-cfg/per-test-coverage-by-lit-cfg.py
index 0abe00bdedb1f28..a8790f74f178c91 100644
--- a/llvm/utils/lit/tests/Inputs/per-test-coverage-by-lit-cfg/per-test-coverage-by-lit-cfg.py
+++ b/llvm/utils/lit/tests/Inputs/per-test-coverage-by-lit-cfg/per-test-coverage-by-lit-cfg.py
@@ -1,5 +1,6 @@
 # Check that the environment variable is set correctly
-# RUN: %{python} %s | FileCheck %s
+# RUN: %{python} %s | FileCheck -DINDEX=1 %s
+# RUN: %{python} %s | FileCheck -DINDEX=2 %s
 
 # Python script to read the environment variable
 # and print its value
@@ -8,4 +9,4 @@
 llvm_profile_file = os.environ.get('LLVM_PROFILE_FILE')
 print(llvm_profile_file)
 
-# CHECK: per-test-coverage-by-lit-cfg0.profraw
+# CHECK: per-test-coverage-by-lit-cfg[[INDEX]].profraw
diff --git a/llvm/utils/lit/tests/Inputs/per-test-coverage/lit.cfg b/llvm/utils/lit/tests/Inputs/per-test-coverage/lit.cfg
index 6e7f4c0e3bc97d7..9ffca93def73fdb 100644
--- a/llvm/utils/lit/tests/Inputs/per-test-coverage/lit.cfg
+++ b/llvm/utils/lit/tests/Inputs/per-test-coverage/lit.cfg
@@ -3,6 +3,8 @@ import os
 
 config.name = "per-test-coverage"
 config.suffixes = [".py"]
-config.test_format = lit.formats.ShTest(execute_external=True)
+config.test_format = lit.formats.ShTest(
+    execute_external=eval(lit_config.params.get("execute_external")),
+    preamble_commands=["%{python} %s | FileCheck -DINDEX=0 %s"]
+)
 config.substitutions.append(("%{python}", '"%s"' % (sys.executable)))
-
diff --git a/llvm/utils/lit/tests/Inputs/per-test-coverage/per-test-coverage.py b/llvm/utils/lit/tests/Inputs/per-test-coverage/per-test-coverage.py
index 65e4aa69bff079f..59e806939a23acb 100644
--- a/llvm/utils/lit/tests/Inputs/per-test-coverage/per-test-coverage.py
+++ b/llvm/utils/lit/tests/Inputs/per-test-coverage/per-test-coverage.py
@@ -1,5 +1,6 @@
 # Check that the environment variable is set correctly
-# RUN: %{python} %s | FileCheck %s
+# RUN: %{python} %s | FileCheck -DINDEX=1 %s
+# RUN: %{python} %s | FileCheck -DINDEX=2 %s
 
 # Python script to read the environment variable
 # and print its value
@@ -8,4 +9,4 @@
 llvm_profile_file = os.environ.get('LLVM_PROFILE_FILE')
 print(llvm_profile_file)
 
-# CHECK: per-test-coverage0.profraw
+# CHECK: per-test-coverage[[INDEX]].profraw
diff --git a/llvm/utils/lit/tests/allow-retries.py b/llvm/utils/lit/tests/allow-retries.py
index b8abe0ba4fee169..bf6c041933887a3 100644
--- a/llvm/utils/lit/tests/allow-retries.py
+++ b/llvm/utils/lit/tests/allow-retries.py
@@ -39,3 +39,15 @@
 # RUN: rm -f %t.counter
 # RUN: %{lit} %{inputs}/test_retry_attempts/test.py -Dcounter=%t.counter -Dpython=%{python} | FileCheck --check-prefix=CHECK-TEST6 %s
 # CHECK-TEST6: Passed With Retry: 1
+
+# This test checks that --per-test-coverage doesn't accumulate inserted
+# LLVM_PROFILE_FILE= commands across retries.
+#
+# RUN: rm -f %t.counter
+# RUN: %{lit} -a %{inputs}/test_retry_attempts/test.py --per-test-coverage\
+# RUN:     -Dcounter=%t.counter -Dpython=%{python} | \
+# RUN:   FileCheck --check-prefix=CHECK-TEST7 %s
+#     CHECK-TEST7: Command Output (stdout):
+#     CHECK-TEST7: LLVM_PROFILE_FILE=
+# CHECK-TEST7-NOT: LLVM_PROFILE_FILE=
+#     CHECK-TEST7: Passed With Retry: 1
diff --git a/llvm/utils/lit/tests/per-test-coverage-by-lit-cfg.py b/llvm/utils/lit/tests/per-test-coverage-by-lit-cfg.py
index 1cc3927dc89041c..189c1cebd623b4c 100644
--- a/llvm/utils/lit/tests/per-test-coverage-by-lit-cfg.py
+++ b/llvm/utils/lit/tests/per-test-coverage-by-lit-cfg.py
@@ -1,6 +1,24 @@
 # Test if lit_config.per_test_coverage in lit.cfg sets individual test case coverage.
 
-# RUN: %{lit} -a -v %{inputs}/per-test-coverage-by-lit-cfg/per-test-coverage-by-lit-cfg.py \
-# RUN: | FileCheck -match-full-lines %s
-#
-# CHECK: PASS: per-test-coverage-by-lit-cfg :: per-test-coverage-by-lit-cfg.py ({{[^)]*}})
+# RUN: %{lit} -a -vv -Dexecute_external=False \
+# RUN:     %{inputs}/per-test-coverage-by-lit-cfg/per-test-coverage-by-lit-cfg.py | \
+# RUN:   FileCheck -DOUT=stdout %s
+
+# RUN: %{lit} -a -vv -Dexecute_external=True \
+# RUN:     %{inputs}/per-test-coverage-by-lit-cfg/per-test-coverage-by-lit-cfg.py | \
+# RUN:   FileCheck -DOUT=stderr %s
+
+#      CHECK: {{^}}PASS: per-test-coverage-by-lit-cfg :: per-test-coverage-by-lit-cfg.py ({{[^)]*}})
+#      CHECK: Command Output ([[OUT]]):
+# CHECK-NEXT: --
+#      CHECK: export
+#      CHECK: LLVM_PROFILE_FILE=per-test-coverage-by-lit-cfg0.profraw
+#      CHECK: per-test-coverage-by-lit-cfg.py
+#      CHECK: {{RUN}}: at line 2
+#      CHECK: export
+#      CHECK: LLVM_PROFILE_FILE=per-test-coverage-by-lit-cfg1.profraw
+#      CHECK: per-test-coverage-by-lit-cfg.py
+#      CHECK: {{RUN}}: at line 3
+#      CHECK: export
+#      CHECK: LLVM_PROFILE_FILE=per-test-coverage-by-lit-cfg2.profraw
+#      CHECK: per-test-coverage-by-lit-cfg.py
diff --git a/llvm/utils/lit/tests/per-test-coverage.py b/llvm/utils/lit/tests/per-test-coverage.py
index 428712e47925760..cf5e82c44dc51a7 100644
--- a/llvm/utils/lit/tests/per-test-coverage.py
+++ b/llvm/utils/lit/tests/per-test-coverage.py
@@ -1,6 +1,24 @@
 # Test LLVM_PROFILE_FILE is set when --per-test-coverage is passed to command line.
 
-# RUN: %{lit} -a -v --per-test-coverage %{inputs}/per-test-coverage/per-test-coverage.py \
-# RUN: | FileCheck -match-full-lines %s
-#
-# CHECK: PASS: per-test-coverage :: per-test-coverage.py ({{[^)]*}})
+# RUN: %{lit} -a -vv --per-test-coverage -Dexecute_external=False \
+# RUN:     %{inputs}/per-test-coverage/per-test-coverage.py | \
+# RUN:   FileCheck -DOUT=stdout %s
+
+# RUN: %{lit} -a -vv --per-test-coverage -Dexecute_external=True \
+# RUN:        %{inputs}/per-test-coverage/per-test-coverage.py | \
+# RUN:   FileCheck -DOUT=stderr %s
+
+#      CHECK: {{^}}PASS: per-test-coverage :: per-test-coverage.py ({{[^)]*}})
+#      CHECK: Command Output ([[OUT]]):
+# CHECK-NEXT: --
+#      CHECK: export
+#      CHECK: LLVM_PROFILE_FILE=per-test-coverage0.profraw
+#      CHECK: per-test-coverage.py
+#      CHECK: {{RUN}}: at line 2
+#      CHECK: export
+#      CHECK: LLVM_PROFILE_FILE=per-test-coverage1.profraw
+#      CHECK: per-test-coverage.py
+#      CHECK: {{RUN}}: at line 3
+#      CHECK: export
+#      CHECK: LLVM_PROFILE_FILE=per-test-coverage2.profraw
+#      CHECK: per-test-coverage.py

>From dc039445799f863cef3f1fde6dac01d0662437d1 Mon Sep 17 00:00:00 2001
From: Martin Erhart <merhart at google.com>
Date: Thu, 14 Sep 2023 16:20:24 +0200
Subject: [PATCH 78/86] [mlir][bufferization] Implement
 BufferDeallocationopInterface for scf.forall.in_parallel (#66351)

The scf.forall.in_parallel terminator operation has a nested graph region with the NoTerminator trait. Such regions are not supported by the default implementations. Therefore, this commit adds a specialized implementation for
this operation which only covers the case where the nested region is empty.
This is because after bufferization, ops like tensor.parallel_insert_slice were already converted to memref operations residing int the scf.forall only and the nested region of scf.forall.in_parallel ends up empty.
---
 .../BufferDeallocationOpInterfaceImpl.h       | 22 +++++
 mlir/include/mlir/InitAllDialects.h           |  3 +
 .../BufferDeallocationOpInterfaceImpl.cpp     | 87 +++++++++++++++++++
 .../lib/Dialect/SCF/Transforms/CMakeLists.txt |  1 +
 .../test/Dialect/SCF/buffer-deallocation.mlir | 24 +++++
 5 files changed, 137 insertions(+)
 create mode 100644 mlir/include/mlir/Dialect/SCF/Transforms/BufferDeallocationOpInterfaceImpl.h
 create mode 100644 mlir/lib/Dialect/SCF/Transforms/BufferDeallocationOpInterfaceImpl.cpp
 create mode 100644 mlir/test/Dialect/SCF/buffer-deallocation.mlir

diff --git a/mlir/include/mlir/Dialect/SCF/Transforms/BufferDeallocationOpInterfaceImpl.h b/mlir/include/mlir/Dialect/SCF/Transforms/BufferDeallocationOpInterfaceImpl.h
new file mode 100644
index 000000000000000..cbfb490c7ab098c
--- /dev/null
+++ b/mlir/include/mlir/Dialect/SCF/Transforms/BufferDeallocationOpInterfaceImpl.h
@@ -0,0 +1,22 @@
+//===- BufferDeallocationOpInterfaceImpl.h ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_SCF_TRANSFORMS_BUFFERDEALLOCATIONOPINTERFACEIMPL_H
+#define MLIR_DIALECT_SCF_TRANSFORMS_BUFFERDEALLOCATIONOPINTERFACEIMPL_H
+
+namespace mlir {
+
+class DialectRegistry;
+
+namespace scf {
+void registerBufferDeallocationOpInterfaceExternalModels(
+    DialectRegistry &registry);
+} // namespace scf
+} // namespace mlir
+
+#endif // MLIR_DIALECT_SCF_TRANSFORMS_BUFFERDEALLOCATIONOPINTERFACEIMPL_H
diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h
index 0182ab93929cb8c..5b2b1ed24d5173d 100644
--- a/mlir/include/mlir/InitAllDialects.h
+++ b/mlir/include/mlir/InitAllDialects.h
@@ -60,6 +60,8 @@
 #include "mlir/Dialect/Quant/QuantOps.h"
 #include "mlir/Dialect/SCF/IR/SCF.h"
 #include "mlir/Dialect/SCF/IR/ValueBoundsOpInterfaceImpl.h"
+#include "mlir/Dialect/SCF/TransformOps/SCFTransformOps.h"
+#include "mlir/Dialect/SCF/Transforms/BufferDeallocationOpInterfaceImpl.h"
 #include "mlir/Dialect/SCF/Transforms/BufferizableOpInterfaceImpl.h"
 #include "mlir/Dialect/SPIRV/IR/SPIRVDialect.h"
 #include "mlir/Dialect/Shape/IR/Shape.h"
@@ -149,6 +151,7 @@ inline void registerAllDialects(DialectRegistry &registry) {
   memref::registerRuntimeVerifiableOpInterfaceExternalModels(registry);
   memref::registerValueBoundsOpInterfaceExternalModels(registry);
   memref::registerMemorySlotExternalModels(registry);
+  scf::registerBufferDeallocationOpInterfaceExternalModels(registry);
   scf::registerBufferizableOpInterfaceExternalModels(registry);
   scf::registerValueBoundsOpInterfaceExternalModels(registry);
   shape::registerBufferizableOpInterfaceExternalModels(registry);
diff --git a/mlir/lib/Dialect/SCF/Transforms/BufferDeallocationOpInterfaceImpl.cpp b/mlir/lib/Dialect/SCF/Transforms/BufferDeallocationOpInterfaceImpl.cpp
new file mode 100644
index 000000000000000..88cb3e9b097147f
--- /dev/null
+++ b/mlir/lib/Dialect/SCF/Transforms/BufferDeallocationOpInterfaceImpl.cpp
@@ -0,0 +1,87 @@
+//===- BufferDeallocationOpInterfaceImpl.cpp ------------------------------===//
+//
+// 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 "mlir/Dialect/SCF/Transforms/BufferDeallocationOpInterfaceImpl.h"
+#include "mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h"
+#include "mlir/Dialect/Bufferization/IR/Bufferization.h"
+#include "mlir/Dialect/SCF/IR/SCF.h"
+
+using namespace mlir;
+using namespace mlir::bufferization;
+
+namespace {
+/// The `scf.forall.in_parallel` terminator is special in a few ways:
+/// * It does not implement the BranchOpInterface or
+///   RegionBranchTerminatorOpInterface, but the ParallelCombiningOpInterface
+///   which is not supported by BufferDeallocation.
+/// * It has a graph-like region which only allows one specific tensor op
+/// * After bufferization the nested region is always empty
+/// For these reasons we provide custom deallocation logic via this external
+/// model.
+///
+/// Example:
+/// ```mlir
+/// scf.forall (%arg1) in (%arg0) {
+///   %alloc = memref.alloc() : memref<2xf32>
+///   ...
+///   <implicit in_parallel terminator here>
+/// }
+/// ```
+/// gets transformed to
+/// ```mlir
+/// scf.forall (%arg1) in (%arg0) {
+///   %alloc = memref.alloc() : memref<2xf32>
+///   ...
+///   bufferization.dealloc (%alloc : memref<2xf32>) if (%true)
+///   <implicit in_parallel terminator here>
+/// }
+/// ```
+struct InParallelOpInterface
+    : public BufferDeallocationOpInterface::ExternalModel<InParallelOpInterface,
+                                                          scf::InParallelOp> {
+  FailureOr<Operation *> process(Operation *op, DeallocationState &state,
+                                 const DeallocationOptions &options) const {
+    auto inParallelOp = cast<scf::InParallelOp>(op);
+    OpBuilder builder(op);
+    if (!inParallelOp.getBody()->empty())
+      return op->emitError("only supported when nested region is empty");
+
+    // Collect the values to deallocate and retain and use them to create the
+    // dealloc operation.
+    Block *block = op->getBlock();
+    SmallVector<Value> memrefs, conditions, toRetain;
+    if (failed(state.getMemrefsAndConditionsToDeallocate(
+            builder, op->getLoc(), block, memrefs, conditions)))
+      return failure();
+
+    state.getMemrefsToRetain(block, /*toBlock=*/nullptr, {}, toRetain);
+    if (memrefs.empty() && toRetain.empty())
+      return op;
+
+    auto deallocOp = builder.create<bufferization::DeallocOp>(
+        op->getLoc(), memrefs, conditions, toRetain);
+
+    // We want to replace the current ownership of the retained values with the
+    // result values of the dealloc operation as they are always unique.
+    state.resetOwnerships(deallocOp.getRetained(), block);
+    for (auto [retained, ownership] :
+         llvm::zip(deallocOp.getRetained(), deallocOp.getUpdatedConditions()))
+      state.updateOwnership(retained, ownership, block);
+
+    return op;
+  }
+};
+
+} // namespace
+
+void mlir::scf::registerBufferDeallocationOpInterfaceExternalModels(
+    DialectRegistry &registry) {
+  registry.addExtension(+[](MLIRContext *ctx, SCFDialect *dialect) {
+    InParallelOp::attachInterface<InParallelOpInterface>(*ctx);
+  });
+}
diff --git a/mlir/lib/Dialect/SCF/Transforms/CMakeLists.txt b/mlir/lib/Dialect/SCF/Transforms/CMakeLists.txt
index 20abf2b583bbf70..fdaeb2fad9afa4f 100644
--- a/mlir/lib/Dialect/SCF/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/SCF/Transforms/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_mlir_dialect_library(MLIRSCFTransforms
+  BufferDeallocationOpInterfaceImpl.cpp
   BufferizableOpInterfaceImpl.cpp
   Bufferize.cpp
   ForToWhile.cpp
diff --git a/mlir/test/Dialect/SCF/buffer-deallocation.mlir b/mlir/test/Dialect/SCF/buffer-deallocation.mlir
new file mode 100644
index 000000000000000..0847b1f1183f9f8
--- /dev/null
+++ b/mlir/test/Dialect/SCF/buffer-deallocation.mlir
@@ -0,0 +1,24 @@
+// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation \
+// RUN:   -buffer-deallocation-simplification -split-input-file %s | FileCheck %s
+
+func.func @parallel_insert_slice(%arg0: index) {
+  %c0 = arith.constant 0 : index
+  %alloc = memref.alloc() : memref<2xf32>
+  scf.forall (%arg1) in (%arg0) {
+    %alloc0 = memref.alloc() : memref<2xf32>
+    %0 = memref.load %alloc[%c0] : memref<2xf32>
+    linalg.fill ins(%0 : f32) outs(%alloc0 : memref<2xf32>)
+  }
+  return
+}
+
+// CHECK-LABEL: func @parallel_insert_slice
+//  CHECK-SAME: (%arg0: index)
+//       CHECK: [[ALLOC0:%.+]] = memref.alloc(
+//       CHECK: scf.forall
+//       CHECK:   [[ALLOC1:%.+]] = memref.alloc(
+//       CHECK:   bufferization.dealloc ([[ALLOC1]] : memref<2xf32>) if (%true
+//   CHECK-NOT: retain
+//       CHECK: }
+//       CHECK: bufferization.dealloc ([[ALLOC0]] : memref<2xf32>) if (%true
+//   CHECK-NOT: retain

>From 28d3cf3ef72b2ab04e649b60bcefe83eb770872b Mon Sep 17 00:00:00 2001
From: Matthias Springer <me at m-sp.org>
Date: Thu, 14 Sep 2023 16:34:32 +0200
Subject: [PATCH 79/86] [mlir][transform] Check for invalidated iterators on
 payload IR mappings (#66369)

Add extra error checking (in debug mode) to detect cases where an
iterator on "direct" payload IR mappings is invalidated (due to elements
being removed). Such errors are hard to debug: they are often
non-deterministic; sometimes the program crashes, sometimes it produces
wrong results. Even when it crashes, the stack trace often points to
completely unrelated code locations.

Store a timestamp with each "direct" mapping. The timestamp is increased
whenever an operation is performed that invaldiates an iterator on that
mapping. A debug iterator is added that checks the timestamp as payload
IR is enumerated.
---
 .../Transform/IR/TransformInterfaces.h        | 31 +++++++++++++++++--
 .../Transform/IR/TransformInterfaces.cpp      | 18 +++++++++++
 2 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h b/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h
index efd8d573936c332..86af59142b77d9c 100644
--- a/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h
+++ b/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h
@@ -170,6 +170,12 @@ class TransformState {
   /// should be emitted when the value is used.
   using InvalidatedHandleMap = DenseMap<Value, std::function<void(Location)>>;
 
+#ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
+  /// Debug only: A timestamp is associated with each transform IR value, so
+  /// that invalid iterator usage can be detected more reliably.
+  using TransformIRTimestampMapping = DenseMap<Value, int64_t>;
+#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
+
   /// The bidirectional mappings between transform IR values and payload IR
   /// operations, and the mapping between transform IR values and parameters.
   struct Mappings {
@@ -178,6 +184,11 @@ class TransformState {
     ParamMapping params;
     ValueMapping values;
     ValueMapping reverseValues;
+
+#ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
+    TransformIRTimestampMapping timestamps;
+    void incrementTimestamp(Value value) { ++timestamps[value]; }
+#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
   };
 
   friend LogicalResult applyTransforms(Operation *, TransformOpInterface,
@@ -207,10 +218,26 @@ class TransformState {
   /// not enumerated. This function is helpful for transformations that apply to
   /// a particular handle.
   auto getPayloadOps(Value value) const {
+    ArrayRef<Operation *> view = getPayloadOpsView(value);
+
+#ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
+    // Memorize the current timestamp and make sure that it has not changed
+    // when incrementing or dereferencing the iterator returned by this
+    // function. The timestamp is incremented when the "direct" mapping is
+    // resized; this would invalidate the iterator returned by this function.
+    int64_t currentTimestamp = getMapping(value).timestamps.lookup(value);
+#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
+
     // When ops are replaced/erased, they are replaced with nullptr (until
     // the data structure is compacted). Do not enumerate these ops.
-    return llvm::make_filter_range(getPayloadOpsView(value),
-                                   [](Operation *op) { return op != nullptr; });
+    return llvm::make_filter_range(view, [=](Operation *op) {
+#ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
+      bool sameTimestamp =
+          currentTimestamp == this->getMapping(value).timestamps.lookup(value);
+      assert(sameTimestamp && "iterator was invalidated during iteration");
+#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
+      return op != nullptr;
+    });
   }
 
   /// Returns the list of parameters that the given transform IR value
diff --git a/mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp b/mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp
index 00450a1ff8f36cf..9cac178d3c2b869 100644
--- a/mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp
+++ b/mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp
@@ -310,6 +310,11 @@ void transform::TransformState::forgetMapping(Value opHandle,
   for (Operation *op : mappings.direct[opHandle])
     dropMappingEntry(mappings.reverse, op, opHandle);
   mappings.direct.erase(opHandle);
+#ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
+  // Payload IR is removed from the mapping. This invalidates the respective
+  // iterators.
+  mappings.incrementTimestamp(opHandle);
+#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
 
   for (Value opResult : origOpFlatResults) {
     SmallVector<Value> resultHandles;
@@ -336,6 +341,12 @@ void transform::TransformState::forgetValueMapping(
       Mappings &localMappings = getMapping(opHandle);
       dropMappingEntry(localMappings.direct, opHandle, payloadOp);
       dropMappingEntry(localMappings.reverse, payloadOp, opHandle);
+
+#ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
+      // Payload IR is removed from the mapping. This invalidates the respective
+      // iterators.
+      localMappings.incrementTimestamp(opHandle);
+#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
     }
   }
 }
@@ -774,6 +785,13 @@ checkRepeatedConsumptionInOperand(ArrayRef<T> payload,
 void transform::TransformState::compactOpHandles() {
   for (Value handle : opHandlesToCompact) {
     Mappings &mappings = getMapping(handle, /*allowOutOfScope=*/true);
+#ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
+    if (llvm::find(mappings.direct[handle], nullptr) !=
+        mappings.direct[handle].end())
+      // Payload IR is removed from the mapping. This invalidates the respective
+      // iterators.
+      mappings.incrementTimestamp(handle);
+#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
     llvm::erase_value(mappings.direct[handle], nullptr);
   }
   opHandlesToCompact.clear();

>From 4f79c16dbd589b4836ee6af42a46f2b9318e7c8d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Pettersson?= <bjorn.a.pettersson at ericsson.com>
Date: Thu, 14 Sep 2023 16:53:34 +0200
Subject: [PATCH 80/86] [LICM] Simplify isLoadInvariantInLoop given opaque
 pointers (#65597)

Since we no longer support typed pointers in LLVM IR, the PtrASXTy
in isLoadInvariantInLoop was set to be equal to Addr->getType() (an
opaque ptr in the same address space). That made the loop looking
through bitcasts redundant.
---
 llvm/lib/Transforms/Scalar/LICM.cpp | 17 +----------------
 1 file changed, 1 insertion(+), 16 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index d6e77c904f3aa2c..4cb70cbdf093b36 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -1039,7 +1039,7 @@ bool llvm::hoistRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
 // invariant.start has no uses.
 static bool isLoadInvariantInLoop(LoadInst *LI, DominatorTree *DT,
                                   Loop *CurLoop) {
-  Value *Addr = LI->getOperand(0);
+  Value *Addr = LI->getPointerOperand();
   const DataLayout &DL = LI->getModule()->getDataLayout();
   const TypeSize LocSizeInBits = DL.getTypeSizeInBits(LI->getType());
 
@@ -1055,21 +1055,6 @@ static bool isLoadInvariantInLoop(LoadInst *LI, DominatorTree *DT,
   if (LocSizeInBits.isScalable())
     return false;
 
-  // if the type is ptr addrspace(x), we know this is the type of
-  // llvm.invariant.start operand
-  auto *PtrASXTy = PointerType::get(LI->getContext(),
-                                    LI->getPointerAddressSpace());
-  unsigned BitcastsVisited = 0;
-  // Look through bitcasts until we reach the PtrASXTy type (this is
-  // invariant.start operand type).
-  // FIXME: We shouldn't really find such bitcasts with opaque pointers.
-  while (Addr->getType() != PtrASXTy) {
-    auto *BC = dyn_cast<BitCastInst>(Addr);
-    // Avoid traversing high number of bitcast uses.
-    if (++BitcastsVisited > MaxNumUsesTraversed || !BC)
-      return false;
-    Addr = BC->getOperand(0);
-  }
   // If we've ended up at a global/constant, bail. We shouldn't be looking at
   // uselists for non-local Values in a loop pass.
   if (isa<Constant>(Addr))

>From 9238d2f74b408895ce411e614a8d71bf4a59ac80 Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Thu, 14 Sep 2023 07:58:01 -0700
Subject: [PATCH 81/86] [flang] Do not finalize main program variables.
 (#66326)

---
 flang/lib/Lower/ConvertVariable.cpp            |  5 +++++
 flang/test/Lower/derived-type-finalization.f90 | 15 +--------------
 2 files changed, 6 insertions(+), 14 deletions(-)

diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 03a7cca1ab69817..0b37fb2bd886be5 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -660,6 +660,11 @@ static bool needEndFinalization(const Fortran::lower::pft::Variable &var) {
   if (!var.hasSymbol())
     return false;
   const Fortran::semantics::Symbol &sym = var.getSymbol();
+  const Fortran::semantics::Scope &owner = sym.owner();
+  if (owner.kind() == Fortran::semantics::Scope::Kind::MainProgram) {
+    // The standard does not require finalizing main program variables.
+    return false;
+  }
   if (!Fortran::semantics::IsPointer(sym) &&
       !Fortran::semantics::IsAllocatable(sym) &&
       !Fortran::semantics::IsDummy(sym) &&
diff --git a/flang/test/Lower/derived-type-finalization.f90 b/flang/test/Lower/derived-type-finalization.f90
index 2194fd8d96451d0..d0fbfe8906c4d1d 100644
--- a/flang/test/Lower/derived-type-finalization.f90
+++ b/flang/test/Lower/derived-type-finalization.f90
@@ -248,20 +248,7 @@ subroutine local_t4()
 program p
   use derived_type_finalization
   type(t1) :: t
-  if (t%a == 10) return
-  print *, 'end of program'
 end program
 
 ! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "p"} {
-! CHECK: %[[T:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "t", uniq_name = "_QFEt"}
-! CHECK: cf.cond_br %{{.*}}, ^bb1, ^bb2
-! CHECK: ^bb1:
-! CHECK:  %[[EMBOX:.*]] = fir.embox %[[T]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
-! CHECK:  %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
-! CHECK:  %{{.*}} = fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> none
-! CHECK:  return
-! CHECK: ^bb2:
-! CHECK:  %[[EMBOX:.*]] = fir.embox %[[T]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
-! CHECK:  %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
-! CHECK:  %{{.*}} = fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> none
-! CHECK:  return
+! CHECK-NOT: fir.call @_FortranADestroy

>From 0c489e1540df3e60f4175bab01aaeff66d0b003f Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Thu, 14 Sep 2023 07:58:26 -0700
Subject: [PATCH 82/86] [flang] Select proper library APIs for derived type io.
 (#66327)

This patch syncs the logic inside `getInputFunc` that selects
the library API and the logic in `createIoRuntimeCallForItem`
that creates the input arguments for the library call.
There were cases where we selected `InputDerivedType` API
and passed only two arguments, and also we selected `InputDescriptor`
and passed three arguments.
It turns out we also were incorrectly selecting `OutputDescriptor`
in `getOutputFunc` (`test4` case in the new LIT test),
which caused runtime issues for output of a derived type
with descriptor components (due to the missing non-type-bound table).
---
 flang/lib/Lower/IO.cpp                 |  8 +--
 flang/test/Lower/io-derived-type-2.f90 | 70 ++++++++++++++++++++++++++
 flang/test/Lower/polymorphic.f90       |  2 +-
 3 files changed, 75 insertions(+), 5 deletions(-)
 create mode 100644 flang/test/Lower/io-derived-type-2.f90

diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp
index ac1fe7f68a9a665..48f2baa2e4f4ed2 100644
--- a/flang/lib/Lower/IO.cpp
+++ b/flang/lib/Lower/IO.cpp
@@ -655,7 +655,7 @@ static void genNamelistIO(Fortran::lower::AbstractConverter &converter,
 static mlir::func::FuncOp getOutputFunc(mlir::Location loc,
                                         fir::FirOpBuilder &builder,
                                         mlir::Type type, bool isFormatted) {
-  if (type.isa<fir::RecordType>())
+  if (fir::unwrapPassByRefType(type).isa<fir::RecordType>())
     return getIORuntimeFunc<mkIOKey(OutputDerivedType)>(loc, builder);
   if (!isFormatted)
     return getIORuntimeFunc<mkIOKey(OutputDescriptor)>(loc, builder);
@@ -737,7 +737,7 @@ static void genOutputItemList(
     if (argType.isa<fir::BoxType>()) {
       mlir::Value box = fir::getBase(converter.genExprBox(loc, *expr, stmtCtx));
       outputFuncArgs.push_back(builder.createConvert(loc, argType, box));
-      if (itemTy.isa<fir::RecordType>())
+      if (fir::unwrapPassByRefType(itemTy).isa<fir::RecordType>())
         outputFuncArgs.push_back(getNonTbpDefinedIoTableAddr(converter));
     } else if (helper.isCharacterScalar(itemTy)) {
       fir::ExtendedValue exv = converter.genExprAddr(loc, expr, stmtCtx);
@@ -772,7 +772,7 @@ static void genOutputItemList(
 static mlir::func::FuncOp getInputFunc(mlir::Location loc,
                                        fir::FirOpBuilder &builder,
                                        mlir::Type type, bool isFormatted) {
-  if (type.isa<fir::RecordType>())
+  if (fir::unwrapPassByRefType(type).isa<fir::RecordType>())
     return getIORuntimeFunc<mkIOKey(InputDerivedType)>(loc, builder);
   if (!isFormatted)
     return getIORuntimeFunc<mkIOKey(InputDescriptor)>(loc, builder);
@@ -834,7 +834,7 @@ createIoRuntimeCallForItem(Fortran::lower::AbstractConverter &converter,
     auto boxTy = box.getType().dyn_cast<fir::BaseBoxType>();
     assert(boxTy && "must be previously emboxed");
     inputFuncArgs.push_back(builder.createConvert(loc, argType, box));
-    if (boxTy.getEleTy().isa<fir::RecordType>())
+    if (fir::unwrapPassByRefType(boxTy).isa<fir::RecordType>())
       inputFuncArgs.push_back(getNonTbpDefinedIoTableAddr(converter));
   } else {
     mlir::Value itemAddr = fir::getBase(item);
diff --git a/flang/test/Lower/io-derived-type-2.f90 b/flang/test/Lower/io-derived-type-2.f90
new file mode 100644
index 000000000000000..c2f1ff1850725da
--- /dev/null
+++ b/flang/test/Lower/io-derived-type-2.f90
@@ -0,0 +1,70 @@
+! Check that InputDerivedType/OutputDeriverType APIs are used
+! for io of derived types.
+! RUN: bbc -polymorphic-type -emit-fir -o - %s | FileCheck %s
+
+module p
+  type :: person
+     type(person), pointer :: next => null()
+  end type person
+  type :: club
+     class(person), allocatable :: membership(:)
+  end type club
+contains
+  subroutine pwf (dtv,unit,iotype,vlist,iostat,iomsg)
+    class(person), intent(in) :: dtv
+    integer, intent(in) :: unit
+    character (len=*), intent(in) :: iotype
+    integer, intent(in) :: vlist(:)
+    integer, intent(out) :: iostat
+    character (len=*), intent(inout) :: iomsg
+    print *, 'write'
+  end subroutine pwf
+  subroutine prf (dtv,unit,iotype,vlist,iostat,iomsg)
+    class(person), intent(inout) :: dtv
+    integer, intent(in) :: unit
+    character (len=*), intent(in) :: iotype
+    integer, intent(in) :: vlist(:)
+    integer, intent(out) :: iostat
+    character (len=*), intent(inout) :: iomsg
+  end subroutine prf
+  subroutine test1(dtv)
+    interface read(formatted)
+       module procedure prf
+    end interface read(formatted)
+    class(person), intent(inout) :: dtv
+    read(7, fmt='(DT)') dtv%next
+  end subroutine test1
+! CHECK-LABEL:   func.func @_QMpPtest1(
+! CHECK:           %{{.*}} = fir.call @_FortranAioInputDerivedType(%{{.*}}, %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<i8>, !fir.box<none>, !fir.ref<none>) -> i1
+
+  subroutine test2(social_club)
+    interface read(formatted)
+       module procedure prf
+    end interface read(formatted)
+    class(club) :: social_club
+    read(7, fmt='(DT)') social_club%membership(0)
+  end subroutine test2
+! CHECK-LABEL:   func.func @_QMpPtest2(
+! CHECK:           %{{.*}} = fir.call @_FortranAioInputDerivedType(%{{.*}}, %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<i8>, !fir.box<none>, !fir.ref<none>) -> i1
+
+  subroutine test3(dtv)
+    interface write(formatted)
+       module procedure pwf
+    end interface write(formatted)
+    class(person), intent(inout) :: dtv
+    write(7, fmt='(DT)') dtv%next
+  end subroutine test3
+! CHECK-LABEL:   func.func @_QMpPtest3(
+! CHECK:           %{{.*}} = fir.call @_FortranAioOutputDerivedType(%{{.*}}, %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<i8>, !fir.box<none>, !fir.ref<none>) -> i1
+
+  subroutine test4(social_club)
+    interface write(formatted)
+       module procedure pwf
+    end interface write(formatted)
+    class(club) :: social_club
+    write(7, fmt='(DT)') social_club%membership(0)
+  end subroutine test4
+! CHECK-LABEL:   func.func @_QMpPtest4(
+! CHECK:           %{{.*}} = fir.call @_FortranAioOutputDerivedType(%{{.*}}, %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<i8>, !fir.box<none>, !fir.ref<none>) -> i1
+end module p
+
diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90
index ba605476638e395..1dc945c1c3c422d 100644
--- a/flang/test/Lower/polymorphic.f90
+++ b/flang/test/Lower/polymorphic.f90
@@ -766,7 +766,7 @@ subroutine test_polymorphic_io()
 ! CHECK: %[[P:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> {bindc_name = "p", uniq_name = "_QMpolymorphic_testFtest_polymorphic_ioEp"}
 ! CHECK: %[[LOAD_P:.*]] = fir.load %[[P]] : !fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>>
 ! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[LOAD_P]] : (!fir.class<!fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>) -> !fir.box<none>
-! CHECK: %{{.*}} = fir.call @_FortranAioInputDescriptor(%{{.*}}, %[[BOX_NONE]]) {{.*}} : (!fir.ref<i8>, !fir.box<none>) -> i1
+! CHECK: %{{.*}} = fir.call @_FortranAioInputDerivedType(%{{.*}}, %[[BOX_NONE]], %{{.*}}) {{.*}} : (!fir.ref<i8>, !fir.box<none>, !fir.ref<none>) -> i1
 
   function unlimited_polymorphic_alloc_array_ret()
     class(*), allocatable :: unlimited_polymorphic_alloc_array_ret(:)

>From fcd2aea7657c33fda09c376e489fa8ba57e3d293 Mon Sep 17 00:00:00 2001
From: Manos Anagnostakis <manos.anagnostakis at vrull.eu>
Date: Thu, 14 Sep 2023 17:58:39 +0300
Subject: [PATCH 83/86] [AArch64] New subtarget features to control ldp and stp
 formation (#66098)

On some AArch64 cores, including Ampere's ampere1 and ampere1a
architectures, load and store pair instructions are faster compared to
simple loads/stores only when the alignment of the pair is at least
twice that of the individual element being loaded.

Based on that, this patch introduces four new subtarget features, two
for controlling ldp and two for controlling stp, to cover the ampere1
and ampere1a alignment needs and to enable optional fine-grained control
over ldp and stp generation in general. The latter can be utilized by
another cpu, if there are possible benefits
with a different policy than the default provided by the compiler.

More specifically, for each of the ldp and stp respectively we have:

- disable-ldp/disable-stp: Do not emit ldp/stp.
- ldp-aligned-only/stp-aligned-only: Emit ldp/stp only if the source
pointer is aligned to at least double the alignment of the type.

Therefore, for -mcpu=ampere1 and -mcpu=ampere1a
ldp-aligned-only/stp-aligned-only become the defaults, because of the
benefit from the alignment, whereas for the rest of the cpus the default
behaviour of the compiler is maintained.
---
 llvm/lib/Target/AArch64/AArch64.td            |  20 +-
 .../AArch64/AArch64LoadStoreOptimizer.cpp     |  33 ++
 .../AArch64/ldp-stp-control-features.ll       | 389 ++++++++++++++++++
 3 files changed, 440 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/ldp-stp-control-features.ll

diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td
index 9a7cc283b5c15cc..d66a8a896bae46a 100644
--- a/llvm/lib/Target/AArch64/AArch64.td
+++ b/llvm/lib/Target/AArch64/AArch64.td
@@ -570,6 +570,18 @@ def FeatureD128 : SubtargetFeature<"d128", "HasD128",
     "and Instructions (FEAT_D128, FEAT_LVA3, FEAT_SYSREG128, FEAT_SYSINSTR128)",
     [FeatureLSE128]>;
 
+def FeatureDisableLdp : SubtargetFeature<"disable-ldp", "HasDisableLdp",
+    "true", "Do not emit ldp">;
+
+def FeatureDisableStp : SubtargetFeature<"disable-stp", "HasDisableStp",
+    "true", "Do not emit stp">;
+
+def FeatureLdpAlignedOnly : SubtargetFeature<"ldp-aligned-only", "HasLdpAlignedOnly",
+    "true", "In order to emit ldp, first check if the load will be aligned to 2 * element_size">;
+
+def FeatureStpAlignedOnly : SubtargetFeature<"stp-aligned-only", "HasStpAlignedOnly",
+    "true", "In order to emit stp, first check if the store will be aligned to 2 * element_size">;
+
 //===----------------------------------------------------------------------===//
 // Architectures.
 //
@@ -1239,7 +1251,9 @@ def TuneAmpere1 : SubtargetFeature<"ampere1", "ARMProcFamily", "Ampere1",
                                    FeatureArithmeticBccFusion,
                                    FeatureCmpBccFusion,
                                    FeatureFuseAddress,
-                                   FeatureFuseLiterals]>;
+                                   FeatureFuseLiterals,
+			           FeatureLdpAlignedOnly,
+                                   FeatureStpAlignedOnly]>;
 
 def TuneAmpere1A : SubtargetFeature<"ampere1a", "ARMProcFamily", "Ampere1A",
                                     "Ampere Computing Ampere-1A processors", [
@@ -1252,7 +1266,9 @@ def TuneAmpere1A : SubtargetFeature<"ampere1a", "ARMProcFamily", "Ampere1A",
                                     FeatureCmpBccFusion,
                                     FeatureFuseAddress,
                                     FeatureFuseLiterals,
-                                    FeatureFuseLiterals]>;
+                                    FeatureFuseLiterals,
+                                    FeatureLdpAlignedOnly,
+                                    FeatureStpAlignedOnly]>;
 
 def ProcessorFeatures {
   list<SubtargetFeature> A53  = [HasV8_0aOps, FeatureCRC, FeatureCrypto,
diff --git a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp
index 41af5522d967dbf..dc2965178bc284e 100644
--- a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp
+++ b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp
@@ -2136,6 +2136,14 @@ bool AArch64LoadStoreOpt::tryToPairLdStInst(MachineBasicBlock::iterator &MBBI) {
   if (!TII->isCandidateToMergeOrPair(MI))
     return false;
 
+  // If disable-ldp feature is opted, do not emit ldp.
+  if (MI.mayLoad() && Subtarget->hasDisableLdp())
+    return false;
+
+  // If disable-stp feature is opted, do not emit stp.
+  if (MI.mayStore() && Subtarget->hasDisableStp())
+    return false;
+
   // Early exit if the offset is not possible to match. (6 bits of positive
   // range, plus allow an extra one in case we find a later insn that matches
   // with Offset-1)
@@ -2159,6 +2167,31 @@ bool AArch64LoadStoreOpt::tryToPairLdStInst(MachineBasicBlock::iterator &MBBI) {
     // Keeping the iterator straight is a pain, so we let the merge routine tell
     // us what the next instruction is after it's done mucking about.
     auto Prev = std::prev(MBBI);
+
+    // Fetch the memoperand of the load/store that is a candidate for
+    // combination.
+    MachineMemOperand *MemOp =
+        MI.memoperands_empty() ? nullptr : MI.memoperands().front();
+
+    // Get the needed alignments to check them if
+    // ldp-aligned-only/stp-aligned-only features are opted.
+    uint64_t MemAlignment = MemOp ? MemOp->getAlign().value() : -1;
+    uint64_t TypeAlignment = MemOp ? Align(MemOp->getSize()).value() : -1;
+
+    // If a load arrives and ldp-aligned-only feature is opted, check that the
+    // alignment of the source pointer is at least double the alignment of the
+    // type.
+    if (MI.mayLoad() && Subtarget->hasLdpAlignedOnly() && MemOp &&
+        MemAlignment < 2 * TypeAlignment)
+      return false;
+
+    // If a store arrives and stp-aligned-only feature is opted, check that the
+    // alignment of the source pointer is at least double the alignment of the
+    // type.
+    if (MI.mayStore() && Subtarget->hasStpAlignedOnly() && MemOp &&
+        MemAlignment < 2 * TypeAlignment)
+      return false;
+
     MBBI = mergePairedInsns(MBBI, Paired, Flags);
     // Collect liveness info for instructions between Prev and the new position
     // MBBI.
diff --git a/llvm/test/CodeGen/AArch64/ldp-stp-control-features.ll b/llvm/test/CodeGen/AArch64/ldp-stp-control-features.ll
new file mode 100644
index 000000000000000..838df340b402ecd
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ldp-stp-control-features.ll
@@ -0,0 +1,389 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
+; RUN: llc < %s -O2 -mtriple=aarch64 -mcpu=ampere1 | FileCheck %s --check-prefixes=CHECK
+; RUN: llc < %s -O2 -mtriple=aarch64 -mcpu=ampere1a | FileCheck %s --check-prefixes=CHECK
+; RUN: llc < %s -O2 -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK-DEFAULT
+; RUN: llc < %s -O2 -mtriple=aarch64 -mcpu=ampere1 -mattr=+disable-ldp | FileCheck %s --check-prefixes=CHECK-DISABLE-LDP
+; RUN: llc < %s -O2 -mtriple=aarch64 -mcpu=ampere1 -mattr=+disable-stp | FileCheck %s --check-prefixes=CHECK-DISABLE-STP
+; RUN: llc < %s -O2 -mtriple=aarch64 -mcpu=ampere1a -mattr=+disable-ldp | FileCheck %s --check-prefixes=CHECK-DISABLE-LDP
+; RUN: llc < %s -O2 -mtriple=aarch64 -mcpu=ampere1a -mattr=+disable-stp | FileCheck %s --check-prefixes=CHECK-DISABLE-STP
+
+define i32 @ldp_aligned_int32_t(ptr %0) #0 {
+; CHECK-LABEL: ldp_aligned_int32_t:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and x8, x0, #0xffffffffffffffc0
+; CHECK-NEXT:    ldp w9, w8, [x8]
+; CHECK-NEXT:    add w0, w8, w9
+; CHECK-NEXT:    ret
+;
+; CHECK-DEFAULT-LABEL: ldp_aligned_int32_t:
+; CHECK-DEFAULT:       // %bb.0:
+; CHECK-DEFAULT-NEXT:    and x8, x0, #0xffffffffffffffc0
+; CHECK-DEFAULT-NEXT:    ldp w9, w8, [x8]
+; CHECK-DEFAULT-NEXT:    add w0, w8, w9
+; CHECK-DEFAULT-NEXT:    ret
+;
+; CHECK-DISABLE-LDP-LABEL: ldp_aligned_int32_t:
+; CHECK-DISABLE-LDP:       // %bb.0:
+; CHECK-DISABLE-LDP-NEXT:    and x8, x0, #0xffffffffffffffc0
+; CHECK-DISABLE-LDP-NEXT:    ldr w9, [x8]
+; CHECK-DISABLE-LDP-NEXT:    ldr w8, [x8, #4]
+; CHECK-DISABLE-LDP-NEXT:    add w0, w8, w9
+; CHECK-DISABLE-LDP-NEXT:    ret
+  %2 = ptrtoint ptr %0 to i64
+  %3 = and i64 %2, -64
+  %4 = inttoptr i64 %3 to ptr
+  %5 = load i32, ptr %4, align 64
+  %6 = getelementptr inbounds i32, ptr %4, i64 1
+  %7 = load i32, ptr %6, align 4
+  %8 = add nsw i32 %7, %5
+  ret i32 %8
+}
+
+define i64 @ldp_aligned_int64_t(ptr %0) #0 {
+; CHECK-LABEL: ldp_aligned_int64_t:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and x8, x0, #0xffffffffffffff80
+; CHECK-NEXT:    ldp x9, x8, [x8]
+; CHECK-NEXT:    add x0, x8, x9
+; CHECK-NEXT:    ret
+;
+; CHECK-DEFAULT-LABEL: ldp_aligned_int64_t:
+; CHECK-DEFAULT:       // %bb.0:
+; CHECK-DEFAULT-NEXT:    and x8, x0, #0xffffffffffffff80
+; CHECK-DEFAULT-NEXT:    ldp x9, x8, [x8]
+; CHECK-DEFAULT-NEXT:    add x0, x8, x9
+; CHECK-DEFAULT-NEXT:    ret
+;
+; CHECK-DISABLE-LDP-LABEL: ldp_aligned_int64_t:
+; CHECK-DISABLE-LDP:       // %bb.0:
+; CHECK-DISABLE-LDP-NEXT:    and x8, x0, #0xffffffffffffff80
+; CHECK-DISABLE-LDP-NEXT:    ldr x9, [x8]
+; CHECK-DISABLE-LDP-NEXT:    ldr x8, [x8, #8]
+; CHECK-DISABLE-LDP-NEXT:    add x0, x8, x9
+; CHECK-DISABLE-LDP-NEXT:    ret
+  %2 = ptrtoint ptr %0 to i64
+  %3 = and i64 %2, -128
+  %4 = inttoptr i64 %3 to ptr
+  %5 = load i64, ptr %4, align 128
+  %6 = getelementptr inbounds i64, ptr %4, i64 1
+  %7 = load i64, ptr %6, align 8
+  %8 = add nsw i64 %7, %5
+  ret i64 %8
+}
+
+define <4 x i32> @ldp_aligned_v4si(ptr %0) #0 {
+; CHECK-LABEL: ldp_aligned_v4si:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and x8, x0, #0xffffffffffffff00
+; CHECK-NEXT:    ldp q0, q1, [x8]
+; CHECK-NEXT:    add v0.4s, v1.4s, v0.4s
+; CHECK-NEXT:    ret
+;
+; CHECK-DEFAULT-LABEL: ldp_aligned_v4si:
+; CHECK-DEFAULT:       // %bb.0:
+; CHECK-DEFAULT-NEXT:    and x8, x0, #0xffffffffffffff00
+; CHECK-DEFAULT-NEXT:    ldp q0, q1, [x8]
+; CHECK-DEFAULT-NEXT:    add v0.4s, v1.4s, v0.4s
+; CHECK-DEFAULT-NEXT:    ret
+;
+; CHECK-DISABLE-LDP-LABEL: ldp_aligned_v4si:
+; CHECK-DISABLE-LDP:       // %bb.0:
+; CHECK-DISABLE-LDP-NEXT:    and x8, x0, #0xffffffffffffff00
+; CHECK-DISABLE-LDP-NEXT:    ldr q0, [x8]
+; CHECK-DISABLE-LDP-NEXT:    ldr q1, [x8, #16]
+; CHECK-DISABLE-LDP-NEXT:    add v0.4s, v1.4s, v0.4s
+; CHECK-DISABLE-LDP-NEXT:    ret
+  %2 = ptrtoint ptr %0 to i64
+  %3 = and i64 %2, -256
+  %4 = inttoptr i64 %3 to ptr
+  %5 = load <4 x i32>, ptr %4, align 256
+  %6 = getelementptr inbounds <4 x i32>, ptr %4, i64 1
+  %7 = load <4 x i32>, ptr %6, align 16
+  %8 = add <4 x i32> %7, %5
+  ret <4 x i32> %8
+}
+
+define i32 @ldp_unaligned_int32_t(ptr %0) #0 {
+; CHECK-LABEL: ldp_unaligned_int32_t:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and x8, x0, #0xffffffffffffffc0
+; CHECK-NEXT:    ldr w9, [x8, #4]
+; CHECK-NEXT:    ldr w8, [x8, #8]
+; CHECK-NEXT:    add w0, w8, w9
+; CHECK-NEXT:    ret
+;
+; CHECK-DEFAULT-LABEL: ldp_unaligned_int32_t:
+; CHECK-DEFAULT:       // %bb.0:
+; CHECK-DEFAULT-NEXT:    and x8, x0, #0xffffffffffffffc0
+; CHECK-DEFAULT-NEXT:    ldp w9, w8, [x8, #4]
+; CHECK-DEFAULT-NEXT:    add w0, w8, w9
+; CHECK-DEFAULT-NEXT:    ret
+;
+; CHECK-DISABLE-LDP-LABEL: ldp_unaligned_int32_t:
+; CHECK-DISABLE-LDP:       // %bb.0:
+; CHECK-DISABLE-LDP-NEXT:    and x8, x0, #0xffffffffffffffc0
+; CHECK-DISABLE-LDP-NEXT:    ldr w9, [x8, #4]
+; CHECK-DISABLE-LDP-NEXT:    ldr w8, [x8, #8]
+; CHECK-DISABLE-LDP-NEXT:    add w0, w8, w9
+; CHECK-DISABLE-LDP-NEXT:    ret
+  %2 = ptrtoint ptr %0 to i64
+  %3 = and i64 %2, -64
+  %4 = inttoptr i64 %3 to ptr
+  %5 = getelementptr inbounds i32, ptr %4, i64 1
+  %6 = load i32, ptr %5, align 4
+  %7 = getelementptr inbounds i32, ptr %4, i64 2
+  %8 = load i32, ptr %7, align 8
+  %9 = add nsw i32 %8, %6
+  ret i32 %9
+}
+
+define i64 @ldp_unaligned_int64_t(ptr %0) #0 {
+; CHECK-LABEL: ldp_unaligned_int64_t:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and x8, x0, #0xffffffffffffff80
+; CHECK-NEXT:    ldr x9, [x8, #8]
+; CHECK-NEXT:    ldr x8, [x8, #16]
+; CHECK-NEXT:    add x0, x8, x9
+; CHECK-NEXT:    ret
+;
+; CHECK-DEFAULT-LABEL: ldp_unaligned_int64_t:
+; CHECK-DEFAULT:       // %bb.0:
+; CHECK-DEFAULT-NEXT:    and x8, x0, #0xffffffffffffff80
+; CHECK-DEFAULT-NEXT:    ldp x9, x8, [x8, #8]
+; CHECK-DEFAULT-NEXT:    add x0, x8, x9
+; CHECK-DEFAULT-NEXT:    ret
+;
+; CHECK-DISABLE-LDP-LABEL: ldp_unaligned_int64_t:
+; CHECK-DISABLE-LDP:       // %bb.0:
+; CHECK-DISABLE-LDP-NEXT:    and x8, x0, #0xffffffffffffff80
+; CHECK-DISABLE-LDP-NEXT:    ldr x9, [x8, #8]
+; CHECK-DISABLE-LDP-NEXT:    ldr x8, [x8, #16]
+; CHECK-DISABLE-LDP-NEXT:    add x0, x8, x9
+; CHECK-DISABLE-LDP-NEXT:    ret
+  %2 = ptrtoint ptr %0 to i64
+  %3 = and i64 %2, -128
+  %4 = inttoptr i64 %3 to ptr
+  %5 = getelementptr inbounds i64, ptr %4, i64 1
+  %6 = load i64, ptr %5, align 8
+  %7 = getelementptr inbounds i64, ptr %4, i64 2
+  %8 = load i64, ptr %7, align 16
+  %9 = add nsw i64 %8, %6
+  ret i64 %9
+}
+
+define <4 x i32> @ldp_unaligned_v4si(ptr %0) #0 {
+; CHECK-LABEL: ldp_unaligned_v4si:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and x8, x0, #0xffffffffffffff00
+; CHECK-NEXT:    ldr q0, [x8, #16]
+; CHECK-NEXT:    ldr q1, [x8, #32]
+; CHECK-NEXT:    add v0.4s, v1.4s, v0.4s
+; CHECK-NEXT:    ret
+;
+; CHECK-DEFAULT-LABEL: ldp_unaligned_v4si:
+; CHECK-DEFAULT:       // %bb.0:
+; CHECK-DEFAULT-NEXT:    and x8, x0, #0xffffffffffffff00
+; CHECK-DEFAULT-NEXT:    ldp q0, q1, [x8, #16]
+; CHECK-DEFAULT-NEXT:    add v0.4s, v1.4s, v0.4s
+; CHECK-DEFAULT-NEXT:    ret
+;
+; CHECK-DISABLE-LDP-LABEL: ldp_unaligned_v4si:
+; CHECK-DISABLE-LDP:       // %bb.0:
+; CHECK-DISABLE-LDP-NEXT:    and x8, x0, #0xffffffffffffff00
+; CHECK-DISABLE-LDP-NEXT:    ldr q0, [x8, #16]
+; CHECK-DISABLE-LDP-NEXT:    ldr q1, [x8, #32]
+; CHECK-DISABLE-LDP-NEXT:    add v0.4s, v1.4s, v0.4s
+; CHECK-DISABLE-LDP-NEXT:    ret
+  %2 = ptrtoint ptr %0 to i64
+  %3 = and i64 %2, -256
+  %4 = inttoptr i64 %3 to ptr
+  %5 = getelementptr inbounds <4 x i32>, ptr %4, i64 1
+  %6 = load <4 x i32>, ptr %5, align 16
+  %7 = getelementptr inbounds <4 x i32>, ptr %4, i64 2
+  %8 = load <4 x i32>, ptr %7, align 32
+  %9 = add <4 x i32> %8, %6
+  ret <4 x i32> %9
+}
+
+define ptr @stp_aligned_int32_t(ptr %0, i32 %1) #0 {
+; CHECK-LABEL: stp_aligned_int32_t:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and x0, x0, #0xffffffffffffffc0
+; CHECK-NEXT:    stp w1, w1, [x0]
+; CHECK-NEXT:    ret
+;
+; CHECK-DEFAULT-LABEL: stp_aligned_int32_t:
+; CHECK-DEFAULT:       // %bb.0:
+; CHECK-DEFAULT-NEXT:    and x0, x0, #0xffffffffffffffc0
+; CHECK-DEFAULT-NEXT:    stp w1, w1, [x0]
+; CHECK-DEFAULT-NEXT:    ret
+;
+; CHECK-DISABLE-STP-LABEL: stp_aligned_int32_t:
+; CHECK-DISABLE-STP:       // %bb.0:
+; CHECK-DISABLE-STP-NEXT:    and x0, x0, #0xffffffffffffffc0
+; CHECK-DISABLE-STP-NEXT:    str w1, [x0]
+; CHECK-DISABLE-STP-NEXT:    str w1, [x0, #4]
+; CHECK-DISABLE-STP-NEXT:    ret
+  %3 = ptrtoint ptr %0 to i64
+  %4 = and i64 %3, -64
+  %5 = inttoptr i64 %4 to ptr
+  store i32 %1, ptr %5, align 64
+  %6 = getelementptr inbounds i32, ptr %5, i64 1
+  store i32 %1, ptr %6, align 4
+  ret ptr %5
+}
+
+define dso_local ptr @stp_aligned_int64_t(ptr %0, i64 %1) #0 {
+; CHECK-LABEL: stp_aligned_int64_t:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and x0, x0, #0xffffffffffffff80
+; CHECK-NEXT:    stp x1, x1, [x0]
+; CHECK-NEXT:    ret
+;
+; CHECK-DEFAULT-LABEL: stp_aligned_int64_t:
+; CHECK-DEFAULT:       // %bb.0:
+; CHECK-DEFAULT-NEXT:    and x0, x0, #0xffffffffffffff80
+; CHECK-DEFAULT-NEXT:    stp x1, x1, [x0]
+; CHECK-DEFAULT-NEXT:    ret
+;
+; CHECK-DISABLE-STP-LABEL: stp_aligned_int64_t:
+; CHECK-DISABLE-STP:       // %bb.0:
+; CHECK-DISABLE-STP-NEXT:    and x0, x0, #0xffffffffffffff80
+; CHECK-DISABLE-STP-NEXT:    str x1, [x0]
+; CHECK-DISABLE-STP-NEXT:    str x1, [x0, #8]
+; CHECK-DISABLE-STP-NEXT:    ret
+  %3 = ptrtoint ptr %0 to i64
+  %4 = and i64 %3, -128
+  %5 = inttoptr i64 %4 to ptr
+  store i64 %1, ptr %5, align 128
+  %6 = getelementptr inbounds i64, ptr %5, i64 1
+  store i64 %1, ptr %6, align 8
+  ret ptr %5
+}
+
+define ptr @stp_aligned_v4si(ptr %0, <4 x i32> %1) #0 {
+; CHECK-LABEL: stp_aligned_v4si:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and x0, x0, #0xffffffffffffff00
+; CHECK-NEXT:    stp q0, q0, [x0]
+; CHECK-NEXT:    ret
+;
+; CHECK-DEFAULT-LABEL: stp_aligned_v4si:
+; CHECK-DEFAULT:       // %bb.0:
+; CHECK-DEFAULT-NEXT:    and x0, x0, #0xffffffffffffff00
+; CHECK-DEFAULT-NEXT:    stp q0, q0, [x0]
+; CHECK-DEFAULT-NEXT:    ret
+;
+; CHECK-DISABLE-STP-LABEL: stp_aligned_v4si:
+; CHECK-DISABLE-STP:       // %bb.0:
+; CHECK-DISABLE-STP-NEXT:    and x0, x0, #0xffffffffffffff00
+; CHECK-DISABLE-STP-NEXT:    str q0, [x0]
+; CHECK-DISABLE-STP-NEXT:    str q0, [x0, #16]
+; CHECK-DISABLE-STP-NEXT:    ret
+  %3 = ptrtoint ptr %0 to i64
+  %4 = and i64 %3, -256
+  %5 = inttoptr i64 %4 to ptr
+  store <4 x i32> %1, ptr %5, align 256
+  %6 = getelementptr inbounds <4 x i32>, ptr %5, i64 1
+  store <4 x i32> %1, ptr %6, align 16
+  ret ptr %5
+}
+
+define ptr @stp_unaligned_int32_t(ptr %0, i32 %1) #0 {
+; CHECK-LABEL: stp_unaligned_int32_t:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and x8, x0, #0xffffffffffffffc0
+; CHECK-NEXT:    orr x0, x8, #0x4
+; CHECK-NEXT:    str w1, [x8, #4]
+; CHECK-NEXT:    str w1, [x8, #8]
+; CHECK-NEXT:    ret
+;
+; CHECK-DEFAULT-LABEL: stp_unaligned_int32_t:
+; CHECK-DEFAULT:       // %bb.0:
+; CHECK-DEFAULT-NEXT:    and x8, x0, #0xffffffffffffffc0
+; CHECK-DEFAULT-NEXT:    orr x0, x8, #0x4
+; CHECK-DEFAULT-NEXT:    stp w1, w1, [x8, #4]
+; CHECK-DEFAULT-NEXT:    ret
+;
+; CHECK-DISABLE-STP-LABEL: stp_unaligned_int32_t:
+; CHECK-DISABLE-STP:       // %bb.0:
+; CHECK-DISABLE-STP-NEXT:    and x8, x0, #0xffffffffffffffc0
+; CHECK-DISABLE-STP-NEXT:    orr x0, x8, #0x4
+; CHECK-DISABLE-STP-NEXT:    str w1, [x8, #4]
+; CHECK-DISABLE-STP-NEXT:    str w1, [x8, #8]
+; CHECK-DISABLE-STP-NEXT:    ret
+  %3 = ptrtoint ptr %0 to i64
+  %4 = and i64 %3, -64
+  %5 = inttoptr i64 %4 to ptr
+  %6 = getelementptr inbounds i32, ptr %5, i64 1
+  store i32 %1, ptr %6, align 4
+  %7 = getelementptr inbounds i32, ptr %5, i64 2
+  store i32 %1, ptr %7, align 8
+  ret ptr %6
+}
+
+define ptr @stp_unaligned_int64_t(ptr %0, i64 %1) #0 {
+; CHECK-LABEL: stp_unaligned_int64_t:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and x8, x0, #0xffffffffffffff80
+; CHECK-NEXT:    orr x0, x8, #0x8
+; CHECK-NEXT:    str x1, [x8, #8]
+; CHECK-NEXT:    str x1, [x8, #16]
+; CHECK-NEXT:    ret
+;
+; CHECK-DEFAULT-LABEL: stp_unaligned_int64_t:
+; CHECK-DEFAULT:       // %bb.0:
+; CHECK-DEFAULT-NEXT:    and x8, x0, #0xffffffffffffff80
+; CHECK-DEFAULT-NEXT:    orr x0, x8, #0x8
+; CHECK-DEFAULT-NEXT:    stp x1, x1, [x8, #8]
+; CHECK-DEFAULT-NEXT:    ret
+;
+; CHECK-DISABLE-STP-LABEL: stp_unaligned_int64_t:
+; CHECK-DISABLE-STP:       // %bb.0:
+; CHECK-DISABLE-STP-NEXT:    and x8, x0, #0xffffffffffffff80
+; CHECK-DISABLE-STP-NEXT:    orr x0, x8, #0x8
+; CHECK-DISABLE-STP-NEXT:    str x1, [x8, #8]
+; CHECK-DISABLE-STP-NEXT:    str x1, [x8, #16]
+; CHECK-DISABLE-STP-NEXT:    ret
+  %3 = ptrtoint ptr %0 to i64
+  %4 = and i64 %3, -128
+  %5 = inttoptr i64 %4 to ptr
+  %6 = getelementptr inbounds i64, ptr %5, i64 1
+  store i64 %1, ptr %6, align 8
+  %7 = getelementptr inbounds i64, ptr %5, i64 2
+  store i64 %1, ptr %7, align 16
+  ret ptr %6
+}
+
+define ptr @stp_unaligned_v4si(ptr %0, <4 x i32> %1) #0 {
+; CHECK-LABEL: stp_unaligned_v4si:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and x8, x0, #0xffffffffffffff00
+; CHECK-NEXT:    orr x0, x8, #0x10
+; CHECK-NEXT:    str q0, [x8, #16]
+; CHECK-NEXT:    str q0, [x8, #32]
+; CHECK-NEXT:    ret
+;
+; CHECK-DEFAULT-LABEL: stp_unaligned_v4si:
+; CHECK-DEFAULT:       // %bb.0:
+; CHECK-DEFAULT-NEXT:    and x8, x0, #0xffffffffffffff00
+; CHECK-DEFAULT-NEXT:    orr x0, x8, #0x10
+; CHECK-DEFAULT-NEXT:    stp q0, q0, [x8, #16]
+; CHECK-DEFAULT-NEXT:    ret
+;
+; CHECK-DISABLE-STP-LABEL: stp_unaligned_v4si:
+; CHECK-DISABLE-STP:       // %bb.0:
+; CHECK-DISABLE-STP-NEXT:    and x8, x0, #0xffffffffffffff00
+; CHECK-DISABLE-STP-NEXT:    orr x0, x8, #0x10
+; CHECK-DISABLE-STP-NEXT:    str q0, [x8, #16]
+; CHECK-DISABLE-STP-NEXT:    str q0, [x8, #32]
+; CHECK-DISABLE-STP-NEXT:    ret
+  %3 = ptrtoint ptr %0 to i64
+  %4 = and i64 %3, -256
+  %5 = inttoptr i64 %4 to ptr
+  %6 = getelementptr inbounds <4 x i32>, ptr %5, i64 1
+  store <4 x i32> %1, ptr %6, align 16
+  %7 = getelementptr inbounds <4 x i32>, ptr %5, i64 2
+  store <4 x i32> %1, ptr %7, align 32
+  ret ptr %6
+}

>From 8c792c8dc2293cf59725389c967355fb694dbd8d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Duncan=20P=2E=20N=2E=20Exon=C2=A0Smith?=
 <duncan+github at exonsmith.com>
Date: Thu, 14 Sep 2023 08:01:02 -0700
Subject: [PATCH 84/86] Resign as code owner of branch weights and block
 frequency

Somewhat overdue... it has been a few years since I stopped watching block frequency / branch weight patches actively, so I effectively stopped acting as code owner a while ago. Reflect the reality.

Still happy to help out; feel free to pull me in if you think I might have useful context!
---
 llvm/CODE_OWNERS.TXT | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/llvm/CODE_OWNERS.TXT b/llvm/CODE_OWNERS.TXT
index 28b382ea32e6d88..2a9fe11942e9781 100644
--- a/llvm/CODE_OWNERS.TXT
+++ b/llvm/CODE_OWNERS.TXT
@@ -75,10 +75,6 @@ E: andrea.dibiagio at sony.com
 E: andrea.dibiagio at gmail.com
 D: MCA, llvm-mca
 
-N: Duncan P. N. Exon Smith
-E: dexonsmith at apple.com
-D: Branch weights and BlockFrequencyInfo
-
 N: Hal Finkel
 E: hfinkel at anl.gov
 D: The loop reroller and alias analysis

>From 30f84fa299f95c4f599fea0c029f98b8000e6e50 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Thu, 14 Sep 2023 18:15:44 +0300
Subject: [PATCH 85/86] clang/AMDGPU: Fix accidental behavior change for
 __builtin_amdgcn_ldexph (#66340)

---
 clang/lib/CodeGen/CGBuiltin.cpp                | 12 ++++++++++--
 clang/test/CodeGenOpenCL/builtins-amdgcn-vi.cl |  3 ++-
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 037a2f9f7b15322..52868ca260290b7 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -17392,14 +17392,22 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
   case AMDGPU::BI__builtin_amdgcn_log_clampf:
     return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_log_clamp);
   case AMDGPU::BI__builtin_amdgcn_ldexp:
-  case AMDGPU::BI__builtin_amdgcn_ldexpf:
-  case AMDGPU::BI__builtin_amdgcn_ldexph: {
+  case AMDGPU::BI__builtin_amdgcn_ldexpf: {
     llvm::Value *Src0 = EmitScalarExpr(E->getArg(0));
     llvm::Value *Src1 = EmitScalarExpr(E->getArg(1));
     llvm::Function *F =
         CGM.getIntrinsic(Intrinsic::ldexp, {Src0->getType(), Src1->getType()});
     return Builder.CreateCall(F, {Src0, Src1});
   }
+  case AMDGPU::BI__builtin_amdgcn_ldexph: {
+    // The raw instruction has a different behavior for out of bounds exponent
+    // values (implicit truncation instead of saturate to short_min/short_max).
+    llvm::Value *Src0 = EmitScalarExpr(E->getArg(0));
+    llvm::Value *Src1 = EmitScalarExpr(E->getArg(1));
+    llvm::Function *F =
+        CGM.getIntrinsic(Intrinsic::ldexp, {Src0->getType(), Int16Ty});
+    return Builder.CreateCall(F, {Src0, Builder.CreateTrunc(Src1, Int16Ty)});
+  }
   case AMDGPU::BI__builtin_amdgcn_frexp_mant:
   case AMDGPU::BI__builtin_amdgcn_frexp_mantf:
   case AMDGPU::BI__builtin_amdgcn_frexp_manth:
diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-vi.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-vi.cl
index 756f90b282a9a2a..ff8618a5c727e21 100644
--- a/clang/test/CodeGenOpenCL/builtins-amdgcn-vi.cl
+++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-vi.cl
@@ -52,7 +52,8 @@ void test_cos_f16(global half* out, half a)
 }
 
 // CHECK-LABEL: @test_ldexp_f16
-// CHECK: call half @llvm.ldexp.f16.i32
+// CHECK: [[TRUNC:%[0-9a-z]+]] = trunc i32
+// CHECK: call half @llvm.ldexp.f16.i16(half %a, i16 [[TRUNC]])
 void test_ldexp_f16(global half* out, half a, int b)
 {
   *out = __builtin_amdgcn_ldexph(a, b);

>From 8553ca28944ffb5507c05933a83ddc420a78f08f Mon Sep 17 00:00:00 2001
From: Kirill Stoimenov <kstoimenov at google.com>
Date: Thu, 14 Sep 2023 00:00:53 +0000
Subject: [PATCH 86/86] [LSAN][NFC] Add a new line to a log

---
 compiler-rt/lib/lsan/lsan_common.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp
index 9b73ddbdc756ffa..9b332bc81c42e6d 100644
--- a/compiler-rt/lib/lsan/lsan_common.cpp
+++ b/compiler-rt/lib/lsan/lsan_common.cpp
@@ -759,10 +759,10 @@ static bool PrintResults(LeakReport &report) {
 
 static bool CheckForLeaks() {
   if (&__lsan_is_turned_off && __lsan_is_turned_off()) {
-    VReport(1, "LeakSanitizer is disabled");
+    VReport(1, "LeakSanitizer is disabled\n");
     return false;
   }
-  VReport(1, "LeakSanitizer: checking for leaks");
+  VReport(1, "LeakSanitizer: checking for leaks\n");
   // Inside LockStuffAndStopTheWorld we can't run symbolizer, so we can't match
   // suppressions. However if a stack id was previously suppressed, it should be
   // suppressed in future checks as well.



More information about the cfe-commits mailing list