[llvm] [GlobalISel] Drop poison flags by default in combiners (PR #218306)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 25 07:20:18 PDT 2026


https://github.com/Michael-Chen-NJU updated https://github.com/llvm/llvm-project/pull/218306

>From e42d2c2f51f9ed4aed8108f755d188f5285ef07c Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <2802328816 at qq.com>
Date: Mon, 24 Aug 2026 10:21:50 +0800
Subject: [PATCH 1/2] [GlobalISel] Drop poison flags by default in combiners

---
 .../llvm/CodeGen/GlobalISel/Combiner.h        |   2 +
 .../CodeGen/GlobalISel/GIMatchTableExecutor.h |   5 +
 .../GlobalISel/GIMatchTableExecutorImpl.h     |   5 +-
 .../CodeGen/GlobalISel/GenericMachineInstrs.h |  12 +-
 .../AArch64/GlobalISel/combine-add.mir        |  28 +++
 .../AArch64/GlobalISel/combine-integer.mir    | 197 ++++++++++++++++++
 6 files changed, 245 insertions(+), 4 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h b/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h
index bd9a526eae606..bb4c7be459753 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h
@@ -67,6 +67,8 @@ class LLVM_ABI Combiner : public GIMatchTableExecutor {
 protected:
   virtual bool canMatchOpcode(unsigned Opc) const { return true; }
 
+  bool shouldDropRootPoisonGeneratingFlags() const override { return true; }
+
   const CombinerInfo &CInfo;
   GISelChangeObserver &Observer;
   MachineIRBuilder &B;
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
index 6e3ccf1923c40..ccce4b79f4419 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
@@ -739,6 +739,11 @@ class GIMatchTableExecutor {
     llvm_unreachable("Subclass does not implement runCustomAction!");
   }
 
+  /// Return true to drop root poison-generating flags from the implicit flag
+  /// propagation performed for newly-built instructions. Explicit MIFlags
+  /// actions in the match table still apply to the output instruction.
+  virtual bool shouldDropRootPoisonGeneratingFlags() const { return false; }
+
   LLVM_ABI bool isOperandImmEqual(const MachineOperand &MO, int64_t Value,
                                   const MachineRegisterInfo &MRI,
                                   bool Splat = false) const;
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
index e0720928c6526..1eb6715c4a249 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
@@ -18,6 +18,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h"
 #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
+#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
 #include "llvm/CodeGen/GlobalISel/Utils.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -58,7 +59,9 @@ bool GIMatchTableExecutor::executeMatchTable(
   // Bypass the flag check on the instruction, and only look at the MCInstrDesc.
   bool NoFPException = !State.MIs[0]->getDesc().mayRaiseFPException();
 
-  const uint32_t Flags = State.MIs[0]->getFlags();
+  uint32_t Flags = State.MIs[0]->getFlags();
+  if (shouldDropRootPoisonGeneratingFlags())
+    Flags &= ~GenericMachineInstr::getPoisonGeneratingFlags();
   bool BuilderInitialized = false;
   const auto initializeBuilder = [&]() {
     if (BuilderInitialized)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
index 6daa7f3808f43..1a24434bb388f 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
@@ -26,7 +26,7 @@ namespace llvm {
 
 /// A base class for all GenericMachineInstrs.
 class GenericMachineInstr : public MachineInstr {
-  constexpr static unsigned PoisonFlags =
+  constexpr static unsigned PoisonGeneratingFlags =
       NoUWrap | NoSWrap | NoUSWrap | IsExact | Disjoint | NonNeg | FmNoNans |
       FmNoInfs | SameSign | InBounds;
 
@@ -41,10 +41,16 @@ class GenericMachineInstr : public MachineInstr {
     return isPreISelGenericOpcode(MI->getOpcode());
   }
 
-  bool hasPoisonGeneratingFlags() const { return getFlags() & PoisonFlags; }
+  static constexpr unsigned getPoisonGeneratingFlags() {
+    return PoisonGeneratingFlags;
+  }
+
+  bool hasPoisonGeneratingFlags() const {
+    return getFlags() & PoisonGeneratingFlags;
+  }
 
   void dropPoisonGeneratingFlags() {
-    clearFlags(PoisonFlags);
+    clearFlags(PoisonGeneratingFlags);
     assert(!hasPoisonGeneratingFlags());
   }
 };
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir
index 1bf856cd6f704..2c06724978f05 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir
@@ -359,6 +359,34 @@ body:             |
     RET_ReallyLR implicit $w0
 ...
 
+---
+name:            add_shl_neg_nuw
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $w0, $w1, $w2
+
+    ; CHECK-LABEL: name: add_shl_neg_nuw
+    ; CHECK: liveins: $w0, $w1, $w2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(i32) = COPY $w0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i32) = COPY $w1
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(i32) = COPY $w2
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(i32) = G_SHL [[COPY1]], [[COPY2]](i32)
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(i32) = G_SUB [[COPY]], [[SHL]]
+    ; CHECK-NEXT: $w0 = COPY [[SUB]](i32)
+    ; CHECK-NEXT: RET_ReallyLR implicit $w0
+    %0:_(i32) = COPY $w0
+    %1:_(i32) = COPY $w1
+    %2:_(i32) = COPY $w2
+    %3:_(i32) = G_CONSTANT i32 0
+    %4:_(i32) = G_SUB %3, %1
+    %5:_(i32) = G_SHL %4, %2
+    %6:_(i32) = nuw G_ADD %0, %5
+    $w0 = COPY %6
+    RET_ReallyLR implicit $w0
+...
+
 ---
 name:            add_shl_neg_commuted
 tracksRegLiveness: true
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index 3de9527bb3584..3f57fb256873d 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -24,6 +24,29 @@ body:             |
     $x0 = COPY %sub
     RET_ReallyLR implicit $x0
 
+...
+---
+name:   APlusBMinusCMinusB_nuw
+body:             |
+  bb.0:
+    liveins: $x0, $x1, $x2
+    ; CHECK-LABEL: name: APlusBMinusCMinusB_nuw
+    ; CHECK: liveins: $x0, $x1, $x2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(i64) = COPY $x0
+    ; CHECK-NEXT: %c:_(i64) = COPY $x2
+    ; CHECK-NEXT: %sub:_(i64) = G_SUB %a, %c
+    ; CHECK-NEXT: $x0 = COPY %sub(i64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(i64) = COPY $x0
+    %b:_(i64) = COPY $x1
+    %c:_(i64) = COPY $x2
+    %sub1:_(i64) = G_SUB %b, %c
+    %add1:_(i64) = G_ADD %a, %sub1
+    %sub:_(i64) = nuw G_SUB %add1, %b
+    $x0 = COPY %sub
+    RET_ReallyLR implicit $x0
+
 ...
 ---
 name:   AMinusBMinusCMinusC
@@ -47,6 +70,29 @@ body:             |
     $x0 = COPY %sub
     RET_ReallyLR implicit $x0
 
+...
+---
+name:   AMinusBMinusCMinusC_nuw
+body:             |
+  bb.0:
+    liveins: $x0, $x1, $x2
+    ; CHECK-LABEL: name: AMinusBMinusCMinusC_nuw
+    ; CHECK: liveins: $x0, $x1, $x2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(i64) = COPY $x0
+    ; CHECK-NEXT: %b:_(i64) = COPY $x1
+    ; CHECK-NEXT: %sub:_(i64) = G_SUB %a, %b
+    ; CHECK-NEXT: $x0 = COPY %sub(i64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(i64) = COPY $x0
+    %b:_(i64) = COPY $x1
+    %c:_(i64) = COPY $x2
+    %sub1:_(i64) = G_SUB %b, %c
+    %sub2:_(i64) = G_SUB %a, %sub1
+    %sub:_(i64) = nuw G_SUB %sub2, %c
+    $x0 = COPY %sub
+    RET_ReallyLR implicit $x0
+
 ...
 ---
 name:   ZeroMinusAPlusB
@@ -190,6 +236,31 @@ body:             |
     $x0 = COPY %add
     RET_ReallyLR implicit $x0
 
+...
+---
+name:   AMinusBPlusCMinusA_nuw
+body:             |
+  bb.0:
+    liveins: $x0, $x1, $x2
+
+    ; CHECK-LABEL: name: AMinusBPlusCMinusA_nuw
+    ; CHECK: liveins: $x0, $x1, $x2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %b:_(i64) = COPY $x1
+    ; CHECK-NEXT: %c:_(i64) = COPY $x2
+    ; CHECK-NEXT: %add:_(i64) = G_SUB %c, %b
+    ; CHECK-NEXT: $x0 = COPY %add(i64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(i64) = COPY $x0
+    %b:_(i64) = COPY $x1
+    %c:_(i64) = COPY $x2
+    %zero:_(i64) = G_CONSTANT i64 0
+    %sub2:_(i64) = G_SUB %c, %a
+    %sub1:_(i64) = G_SUB %a, %b
+    %add:_(i64) = nuw G_ADD %sub1, %sub2
+    $x0 = COPY %add
+    RET_ReallyLR implicit $x0
+
 ...
 ---
 name:   AMinusBPlusBMinusC
@@ -216,6 +287,32 @@ body:             |
     RET_ReallyLR implicit $x0
 
 
+...
+---
+name:   AMinusBPlusBMinusC_nuw
+body:             |
+  bb.0:
+    liveins: $x0, $x1, $x2
+
+    ; CHECK-LABEL: name: AMinusBPlusBMinusC_nuw
+    ; CHECK: liveins: $x0, $x1, $x2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(i64) = COPY $x0
+    ; CHECK-NEXT: %c:_(i64) = COPY $x2
+    ; CHECK-NEXT: %add:_(i64) = G_SUB %a, %c
+    ; CHECK-NEXT: $x0 = COPY %add(i64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(i64) = COPY $x0
+    %b:_(i64) = COPY $x1
+    %c:_(i64) = COPY $x2
+    %zero:_(i64) = G_CONSTANT i64 0
+    %sub2:_(i64) = G_SUB %b, %c
+    %sub1:_(i64) = G_SUB %a, %b
+    %add:_(i64) = nuw G_ADD %sub1, %sub2
+    $x0 = COPY %add
+    RET_ReallyLR implicit $x0
+
+
 ...
 ---
 name:   APlusBMinusAplusC
@@ -241,6 +338,31 @@ body:             |
     $x0 = COPY %add
     RET_ReallyLR implicit $x0
 
+...
+---
+name:   APlusBMinusAplusC_nuw
+body:             |
+  bb.0:
+    liveins: $x0, $x1, $x2
+
+    ; CHECK-LABEL: name: APlusBMinusAplusC_nuw
+    ; CHECK: liveins: $x0, $x1, $x2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %b:_(i64) = COPY $x1
+    ; CHECK-NEXT: %c:_(i64) = COPY $x2
+    ; CHECK-NEXT: %add:_(i64) = G_SUB %b, %c
+    ; CHECK-NEXT: $x0 = COPY %add(i64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(i64) = COPY $x0
+    %b:_(i64) = COPY $x1
+    %c:_(i64) = COPY $x2
+    %zero:_(i64) = G_CONSTANT i64 0
+    %add1:_(i64) = G_ADD %a, %c
+    %sub1:_(i64) = G_SUB %b, %add1
+    %add:_(i64) = nuw G_ADD %a, %sub1
+    $x0 = COPY %add
+    RET_ReallyLR implicit $x0
+
 ...
 ---
 name:   APlusBMinusCPlusA
@@ -266,6 +388,31 @@ body:             |
     $x0 = COPY %add
     RET_ReallyLR implicit $x0
 
+...
+---
+name:   APlusBMinusCPlusA_nuw
+body:             |
+  bb.0:
+    liveins: $x0, $x1, $x2
+
+    ; CHECK-LABEL: name: APlusBMinusCPlusA_nuw
+    ; CHECK: liveins: $x0, $x1, $x2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %b:_(i64) = COPY $x1
+    ; CHECK-NEXT: %c:_(i64) = COPY $x2
+    ; CHECK-NEXT: %add:_(i64) = G_SUB %b, %c
+    ; CHECK-NEXT: $x0 = COPY %add(i64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(i64) = COPY $x0
+    %b:_(i64) = COPY $x1
+    %c:_(i64) = COPY $x2
+    %zero:_(i64) = G_CONSTANT i64 0
+    %add1:_(i64) = G_ADD %c, %a
+    %sub1:_(i64) = G_SUB %b, %add1
+    %add:_(i64) = nuw G_ADD %a, %sub1
+    $x0 = COPY %add
+    RET_ReallyLR implicit $x0
+
 ...
 ---
 name:   APlusBMinusCPlusA_BV
@@ -496,6 +643,56 @@ body:             |
     $x0 = COPY %sub2
     RET_ReallyLR implicit $x0
 
+...
+---
+name:   AMinusBMinusC_nuw
+body:             |
+  bb.0:
+    liveins: $x0, $x1, $x2
+
+    ; CHECK-LABEL: name: AMinusBMinusC_nuw
+    ; CHECK: liveins: $x0, $x1, $x2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(i64) = COPY $x0
+    ; CHECK-NEXT: %b:_(i64) = COPY $x1
+    ; CHECK-NEXT: %c:_(i64) = COPY $x2
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(i64) = G_SUB %c, %b
+    ; CHECK-NEXT: %sub2:_(i64) = G_ADD %a, [[SUB]]
+    ; CHECK-NEXT: $x0 = COPY %sub2(i64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(i64) = COPY $x0
+    %b:_(i64) = COPY $x1
+    %c:_(i64) = COPY $x2
+    %sub1:_(i64) = G_SUB %b, %c
+    %sub2:_(i64) = nuw G_SUB %a, %sub1
+    $x0 = COPY %sub2
+    RET_ReallyLR implicit $x0
+
+...
+---
+name:   AMinusBMinusC_nsw
+body:             |
+  bb.0:
+    liveins: $x0, $x1, $x2
+
+    ; CHECK-LABEL: name: AMinusBMinusC_nsw
+    ; CHECK: liveins: $x0, $x1, $x2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(i64) = COPY $x0
+    ; CHECK-NEXT: %b:_(i64) = COPY $x1
+    ; CHECK-NEXT: %c:_(i64) = COPY $x2
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(i64) = G_SUB %c, %b
+    ; CHECK-NEXT: %sub2:_(i64) = G_ADD %a, [[SUB]]
+    ; CHECK-NEXT: $x0 = COPY %sub2(i64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(i64) = COPY $x0
+    %b:_(i64) = COPY $x1
+    %c:_(i64) = COPY $x2
+    %sub1:_(i64) = G_SUB %b, %c
+    %sub2:_(i64) = nsw G_SUB %a, %sub1
+    $x0 = COPY %sub2
+    RET_ReallyLR implicit $x0
+
 ...
 ---
 name:   AMinusZeroMinusB

>From 0e564fbd1ffb0491fd4929a019e83cbbaf741ada Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <2802328816 at qq.com>
Date: Tue, 25 Aug 2026 16:12:51 +0800
Subject: [PATCH 2/2] [GlobalISel] Encode combiner flag drops in match tables

---
 .../llvm/CodeGen/GlobalISel/Combiner.h        |   2 -
 .../CodeGen/GlobalISel/GIMatchTableExecutor.h |  10 +-
 .../GlobalISel/GIMatchTableExecutorImpl.h     |  28 +++-
 .../CodeGen/GlobalISel/GenericMachineInstrs.h |  12 +-
 .../include/llvm/Target/GlobalISel/Combine.td |   3 +
 .../builtins/match-table-replacerreg.td       |   1 +
 .../match-table-cxx.td                        |  10 +-
 .../match-table-hoisting-cxx.td               |  96 +++++------
 .../match-table-hoisting.td                   |  70 ++++----
 .../match-table-imms.td                       |   3 +
 .../match-table-intrinsics.td                 |   6 +-
 .../match-table-miflags.td                    |   5 +-
 .../match-table-operand-types.td              |   8 +-
 .../match-table-patfrag-root.td               |   3 +
 .../match-table-permutations.td               |  54 +++----
 .../match-table-typeof.td                     |   8 +-
 .../match-table-variadics.td                  |  13 +-
 .../GlobalISelCombinerEmitter/match-table.td  |  13 +-
 .../pattern-parsing.td                        |   4 +-
 .../GlobalISel/GIMatchTableExecutorTest.cpp   | 149 ++++++++++++++++++
 .../Common/GlobalISel/MatchTable/Matchers.cpp |   9 ++
 .../Common/GlobalISel/MatchTable/Matchers.h   |   8 +
 .../TableGen/GlobalISelCombinerEmitter.cpp    |  16 ++
 23 files changed, 375 insertions(+), 156 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h b/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h
index bb4c7be459753..bd9a526eae606 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h
@@ -67,8 +67,6 @@ class LLVM_ABI Combiner : public GIMatchTableExecutor {
 protected:
   virtual bool canMatchOpcode(unsigned Opc) const { return true; }
 
-  bool shouldDropRootPoisonGeneratingFlags() const override { return true; }
-
   const CombinerInfo &CInfo;
   GISelChangeObserver &Observer;
   MachineIRBuilder &B;
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
index ccce4b79f4419..7fb9891ac4b6f 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
@@ -515,7 +515,12 @@ enum {
   /// Calls a C++ function that concludes the current match.
   /// The C++ function is free to return false and reject the match, or
   /// return true and mutate the instruction(s) (or do nothing, even).
+  /// Any instructions added to OutMIs should be newly-created outputs. Custom
+  /// actions that set flags on those instructions before returning explicitly
+  /// opt in to preserving those flags.
   /// - FnID(2) - The function to call.
+  /// - InitialUnsetFlags(4) - Flags to clear from implicit root flag
+  ///   propagation for instructions added to OutMIs by the function.
   GIR_DoneWithCustomAction,
 
   /// Render operands to the specified instruction using a custom function,
@@ -739,11 +744,6 @@ class GIMatchTableExecutor {
     llvm_unreachable("Subclass does not implement runCustomAction!");
   }
 
-  /// Return true to drop root poison-generating flags from the implicit flag
-  /// propagation performed for newly-built instructions. Explicit MIFlags
-  /// actions in the match table still apply to the output instruction.
-  virtual bool shouldDropRootPoisonGeneratingFlags() const { return false; }
-
   LLVM_ABI bool isOperandImmEqual(const MachineOperand &MO, int64_t Value,
                                   const MachineRegisterInfo &MRI,
                                   bool Splat = false) const;
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
index 1eb6715c4a249..82abb1d7cbd08 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
@@ -18,7 +18,6 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h"
 #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
-#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
 #include "llvm/CodeGen/GlobalISel/Utils.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -59,9 +58,8 @@ bool GIMatchTableExecutor::executeMatchTable(
   // Bypass the flag check on the instruction, and only look at the MCInstrDesc.
   bool NoFPException = !State.MIs[0]->getDesc().mayRaiseFPException();
 
-  uint32_t Flags = State.MIs[0]->getFlags();
-  if (shouldDropRootPoisonGeneratingFlags())
-    Flags &= ~GenericMachineInstr::getPoisonGeneratingFlags();
+  const uint32_t Flags = State.MIs[0]->getFlags();
+  SmallVector<uint32_t, 4> OutMIUnsetFlags;
   bool BuilderInitialized = false;
   const auto initializeBuilder = [&]() {
     if (BuilderInitialized)
@@ -86,10 +84,13 @@ bool GIMatchTableExecutor::executeMatchTable(
   };
 
   const auto propagateFlags = [&]() {
-    for (auto MIB : OutMIs) {
+    OutMIUnsetFlags.resize(OutMIs.size());
+    for (unsigned I = 0, E = OutMIs.size(); I != E; ++I) {
+      MachineInstrBuilder MIB = OutMIs[I];
       // Set the NoFPExcept flag when no original matched instruction could
       // raise an FP exception, but the new instruction potentially might.
       uint32_t MIBFlags = Flags | MIB.getInstr()->getFlags();
+      MIBFlags &= ~OutMIUnsetFlags[I];
       if (NoFPException && MIB->mayRaiseFPException())
         MIBFlags |= MachineInstr::NoFPExcept;
       if (Observer)
@@ -1085,6 +1086,8 @@ bool GIMatchTableExecutor::executeMatchTable(
       uint32_t NewOpcode = readU16();
       if (NewInsnID >= OutMIs.size())
         OutMIs.resize(NewInsnID + 1);
+      if (NewInsnID >= OutMIUnsetFlags.size())
+        OutMIUnsetFlags.resize(NewInsnID + 1);
 
       MachineInstr *OldMI = State.MIs[OldInsnID];
       if (Observer)
@@ -1106,6 +1109,8 @@ bool GIMatchTableExecutor::executeMatchTable(
       uint32_t Opcode = readU16();
       if (NewInsnID >= OutMIs.size())
         OutMIs.resize(NewInsnID + 1);
+      if (NewInsnID >= OutMIUnsetFlags.size())
+        OutMIUnsetFlags.resize(NewInsnID + 1);
 
       initializeBuilder();
       OutMIs[NewInsnID] = Builder.buildInstr(Opcode);
@@ -1258,6 +1263,8 @@ bool GIMatchTableExecutor::executeMatchTable(
                              << InsnID << "], " << Flags << ")\n");
       MachineInstr *MI = OutMIs[InsnID];
       MI->setFlags(MI->getFlags() | Flags);
+      OutMIUnsetFlags.resize(OutMIs.size());
+      OutMIUnsetFlags[InsnID] &= ~Flags;
       break;
     }
     case GIR_UnsetMIFlags: {
@@ -1269,6 +1276,8 @@ bool GIMatchTableExecutor::executeMatchTable(
                              << InsnID << "], " << Flags << ")\n");
       MachineInstr *MI = OutMIs[InsnID];
       MI->setFlags(MI->getFlags() & ~Flags);
+      OutMIUnsetFlags.resize(OutMIs.size());
+      OutMIUnsetFlags[InsnID] |= Flags;
       break;
     }
     case GIR_CopyMIFlags: {
@@ -1279,7 +1288,10 @@ bool GIMatchTableExecutor::executeMatchTable(
                       dbgs() << CurrentIdx << ": GIR_CopyMIFlags(OutMIs["
                              << InsnID << "], MIs[" << OldInsnID << "])\n");
       MachineInstr *MI = OutMIs[InsnID];
-      MI->setFlags(MI->getFlags() | State.MIs[OldInsnID]->getFlags());
+      uint32_t Flags = State.MIs[OldInsnID]->getFlags();
+      MI->setFlags(MI->getFlags() | Flags);
+      OutMIUnsetFlags.resize(OutMIs.size());
+      OutMIUnsetFlags[InsnID] &= ~Flags;
       break;
     }
     case GIR_AddSimpleTempRegister:
@@ -1432,11 +1444,15 @@ bool GIMatchTableExecutor::executeMatchTable(
     }
     case GIR_DoneWithCustomAction: {
       uint16_t FnID = readU16();
+      uint32_t InitialUnsetFlags = readU32();
       DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_DoneWithCustomAction(FnID="
                              << FnID << ")\n");
       assert(FnID > GICXXCustomAction_Invalid && "Expected a valid FnID");
       if (runCustomAction(FnID, State, OutMIs)) {
+        OutMIUnsetFlags.resize(OutMIs.size());
+        for (unsigned I = 0, E = OutMIs.size(); I != E; ++I)
+          OutMIUnsetFlags[I] |= InitialUnsetFlags & ~OutMIs[I]->getFlags();
         propagateFlags();
         return true;
       }
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
index 1a24434bb388f..6daa7f3808f43 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
@@ -26,7 +26,7 @@ namespace llvm {
 
 /// A base class for all GenericMachineInstrs.
 class GenericMachineInstr : public MachineInstr {
-  constexpr static unsigned PoisonGeneratingFlags =
+  constexpr static unsigned PoisonFlags =
       NoUWrap | NoSWrap | NoUSWrap | IsExact | Disjoint | NonNeg | FmNoNans |
       FmNoInfs | SameSign | InBounds;
 
@@ -41,16 +41,10 @@ class GenericMachineInstr : public MachineInstr {
     return isPreISelGenericOpcode(MI->getOpcode());
   }
 
-  static constexpr unsigned getPoisonGeneratingFlags() {
-    return PoisonGeneratingFlags;
-  }
-
-  bool hasPoisonGeneratingFlags() const {
-    return getFlags() & PoisonGeneratingFlags;
-  }
+  bool hasPoisonGeneratingFlags() const { return getFlags() & PoisonFlags; }
 
   void dropPoisonGeneratingFlags() {
-    clearFlags(PoisonGeneratingFlags);
+    clearFlags(PoisonFlags);
     assert(!hasPoisonGeneratingFlags());
   }
 };
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index e0f665e85c2cc..a7f2c305b788e 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -193,7 +193,10 @@ def FmReassoc   : MIFlagEnum<"FmReassoc">;
 def IsExact     : MIFlagEnum<"IsExact">;
 def NoSWrap     : MIFlagEnum<"NoSWrap">;
 def NoUWrap     : MIFlagEnum<"NoUWrap">;
+def NoUSWrap    : MIFlagEnum<"NoUSWrap">;
+def Disjoint    : MIFlagEnum<"Disjoint">;
 def NonNeg      : MIFlagEnum<"NonNeg">;
+def SameSign    : MIFlagEnum<"SameSign">;
 def InBounds    : MIFlagEnum<"InBounds">;
 
 def MIFlags;
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/builtins/match-table-replacerreg.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/builtins/match-table-replacerreg.td
index 850c04130b865..28d135e8af3dc 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/builtins/match-table-replacerreg.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/builtins/match-table-replacerreg.td
@@ -54,6 +54,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/0, // a
 // CHECK-NEXT:       GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/GIMT_Encode2(static_cast<uint16_t>(RegState::Define)),
 // CHECK-NEXT:       GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // y
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_ReplaceRegWithTempReg, /*OldInsnID*/0, /*OldOpIdx*/1, /*TempRegID*/0,
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
 // CHECK-NEXT:     // Label 3: @[[L529]]
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
index b226071598056..c5823a8942c5d 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
@@ -123,7 +123,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:      // MIs[0] y
 // CHECK-NEXT:      // No operand predicates
 // CHECK-NEXT:      // Combiner Rule #3: NoMatchTwoApply
-// CHECK-NEXT:      GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner2),
+// CHECK-NEXT:      GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner2), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:      // Label 7: @{{[0-9]+}}
 // CHECK-NEXT:      GIM_Reject,
 // CHECK-NEXT:      // Label 2: @{{[0-9]+}}
@@ -134,7 +134,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:      // MIs[0] y
 // CHECK-NEXT:      // No operand predicates
 // CHECK-NEXT:      // Combiner Rule #4: CombineCXXOrder
-// CHECK-NEXT:      GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner3),
+// CHECK-NEXT:      GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner3), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:      // Label 8: @{{[0-9]+}}
 // CHECK-NEXT:      GIM_Reject,
 // CHECK-NEXT:      // Label 3: @{{[0-9]+}}
@@ -145,7 +145,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:      // MIs[0] b
 // CHECK-NEXT:      // No operand predicates
 // CHECK-NEXT:      // Combiner Rule #1: TwoMatchTwoApply
-// CHECK-NEXT:      GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner1),
+// CHECK-NEXT:      GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner1), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:      // Label 9: @{{[0-9]+}}
 // CHECK-NEXT:      GIM_Reject,
 // CHECK-NEXT:      // Label 4: @{{[0-9]+}}
@@ -156,11 +156,11 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:      // MIs[0] b
 // CHECK-NEXT:      // No operand predicates
 // CHECK-NEXT:      // Combiner Rule #0: OneMatchOneApply
-// CHECK-NEXT:      GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
+// CHECK-NEXT:      GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:      // Label 10: @{{[0-9]+}}
 // CHECK-NEXT:      GIM_Reject,
 // CHECK-NEXT:      // Label 5: @{{[0-9]+}}
 // CHECK-NEXT:      GIM_Reject,
-// CHECK-NEXT:      }; // Size: 537 bytes
+// CHECK-NEXT:      }; // Size: 553 bytes
 // CHECK-NEXT:   return MatchTable0;
 // CHECK-NEXT: }
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-hoisting-cxx.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-hoisting-cxx.td
index a7e0360921803..220dc232973a4 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-hoisting-cxx.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-hoisting-cxx.td
@@ -39,9 +39,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 
 // CHECK:      const uint8_t *GenMyCombiner::getMatchTable() const {
 // CHECK-NEXT:   constexpr static uint8_t MatchTable0[] = {
-// CHECK-NEXT:      /*   0 */ GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(198),
+// CHECK-NEXT:      /*   0 */ GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(222),
 // CHECK-NEXT:      /*   5 */   GIM_CheckOpcode, /*MI*/0, GIMT_Encode2(TargetOpcode::G_SUB),
-// CHECK-NEXT:      /*   9 */   GIM_Try, /*On fail goto*//*Label 1*/ GIMT_Encode4(103), // Rule ID 1 //
+// CHECK-NEXT:      /*   9 */   GIM_Try, /*On fail goto*//*Label 1*/ GIMT_Encode4(115), // Rule ID 1 //
 // CHECK-NEXT:      /*  14 */     GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled),
 // CHECK-NEXT:      /*  17 */     // MIs[0] root
 // CHECK-NEXT:      /*  17 */     GIM_RecordRegType, /*MI*/0, /*Op*/0, /*TempTypeIdx*/255,
@@ -69,49 +69,53 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:      /*  75 */     GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/GIMT_Encode2(static_cast<uint16_t>(RegState::Define)),
 // CHECK-NEXT:      /*  80 */     GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/1,
 // CHECK-NEXT:      /*  83 */     GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // A
-// CHECK-NEXT:      /*  87 */     GIR_BuildMI, /*InsnID*/1, /*Opcode*/GIMT_Encode2(TargetOpcode::G_SMIN),
-// CHECK-NEXT:      /*  91 */     GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/0, // root
-// CHECK-NEXT:      /*  95 */     GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/1, /*OpIdx*/1, // A
-// CHECK-NEXT:      /*  99 */     GIR_AddSimpleTempRegister, /*InsnID*/1, /*TempRegID*/0,
-// CHECK-NEXT:      /* 102 */     GIR_EraseRootFromParent_Done,
-// CHECK-NEXT:      /* 103 */   // Label 1: @103
-// CHECK-NEXT:      /* 103 */   GIM_Try, /*On fail goto*//*Label 2*/ GIMT_Encode4(197), // Rule ID 0 //
-// CHECK-NEXT:      /* 108 */     GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
-// CHECK-NEXT:      /* 111 */     // MIs[0] root
-// CHECK-NEXT:      /* 111 */     GIM_RecordRegType, /*MI*/0, /*Op*/0, /*TempTypeIdx*/255,
-// CHECK-NEXT:      /* 115 */     // MIs[0] Operand 1
-// CHECK-NEXT:      /* 115 */     GIM_CheckConstantInt8, /*MI*/0, /*Op*/1, 0,
-// CHECK-NEXT:      /* 119 */     // MIs[0] max
-// CHECK-NEXT:      /* 119 */     GIM_RecordInsnIgnoreCopies, /*DefineMI*/1, /*MI*/0, /*OpIdx*/2, // MIs[1]
-// CHECK-NEXT:      /* 123 */     GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_UMAX),
-// CHECK-NEXT:      /* 127 */     // MIs[1] A
-// CHECK-NEXT:      /* 127 */     // No operand predicates
-// CHECK-NEXT:      /* 127 */     // MIs[1] sub
-// CHECK-NEXT:      /* 127 */     GIM_RecordInsnIgnoreCopies, /*DefineMI*/2, /*MI*/1, /*OpIdx*/2, // MIs[2]
-// CHECK-NEXT:      /* 131 */     GIM_CheckOpcode, /*MI*/2, GIMT_Encode2(TargetOpcode::G_SUB),
-// CHECK-NEXT:      /* 135 */     // MIs[2] Operand 1
-// CHECK-NEXT:      /* 135 */     GIM_CheckConstantInt8, /*MI*/2, /*Op*/1, 0,
-// CHECK-NEXT:      /* 139 */     // MIs[2] A
-// CHECK-NEXT:      /* 139 */     GIM_CheckIsSameOperandIgnoreCopies, /*MI*/2, /*OpIdx*/2, /*OtherMI*/1, /*OtherOpIdx*/1,
-// CHECK-NEXT:      /* 144 */     GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner0),
-// CHECK-NEXT:      /* 148 */     GIM_CheckIsSafeToFold, /*NumInsns*/2,
-// CHECK-NEXT:      /* 150 */     GIR_MakeTempReg, /*TempRegID*/1, /*TypeID*/255,
-// CHECK-NEXT:      /* 153 */     GIR_BuildConstant, /*TempRegID*/1, /*Val*/GIMT_Encode8(0),
-// CHECK-NEXT:      /* 163 */     GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/255,
-// CHECK-NEXT:      /* 166 */     // Combiner Rule #0: SharedCXXPred0
-// CHECK-NEXT:      /* 166 */     GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::G_SUB),
-// CHECK-NEXT:      /* 169 */     GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/GIMT_Encode2(static_cast<uint16_t>(RegState::Define)),
-// CHECK-NEXT:      /* 174 */     GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/1,
-// CHECK-NEXT:      /* 177 */     GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // A
-// CHECK-NEXT:      /* 181 */     GIR_BuildMI, /*InsnID*/1, /*Opcode*/GIMT_Encode2(TargetOpcode::G_UMIN),
-// CHECK-NEXT:      /* 185 */     GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/0, // root
-// CHECK-NEXT:      /* 189 */     GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/1, /*OpIdx*/1, // A
-// CHECK-NEXT:      /* 193 */     GIR_AddSimpleTempRegister, /*InsnID*/1, /*TempRegID*/0,
-// CHECK-NEXT:      /* 196 */     GIR_EraseRootFromParent_Done,
-// CHECK-NEXT:      /* 197 */   // Label 2: @197
-// CHECK-NEXT:      /* 197 */   GIM_Reject,
-// CHECK-NEXT:      /* 198 */ // Label 0: @198
-// CHECK-NEXT:      /* 198 */ GIM_Reject,
-// CHECK-NEXT:      /* 199 */ }; // Size: 199 bytes
+// CHECK-NEXT:      /*  87 */     GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
+// CHECK-NEXT:      /*  93 */     GIR_BuildMI, /*InsnID*/1, /*Opcode*/GIMT_Encode2(TargetOpcode::G_SMIN),
+// CHECK-NEXT:      /*  97 */     GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/0, // root
+// CHECK-NEXT:      /* 101 */     GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/1, /*OpIdx*/1, // A
+// CHECK-NEXT:      /* 105 */     GIR_AddSimpleTempRegister, /*InsnID*/1, /*TempRegID*/0,
+// CHECK-NEXT:      /* 108 */     GIR_UnsetMIFlags, /*InsnID*/1, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
+// CHECK-NEXT:      /* 114 */     GIR_EraseRootFromParent_Done,
+// CHECK-NEXT:      /* 115 */   // Label 1: @115
+// CHECK-NEXT:      /* 115 */   GIM_Try, /*On fail goto*//*Label 2*/ GIMT_Encode4(221), // Rule ID 0 //
+// CHECK-NEXT:      /* 120 */     GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
+// CHECK-NEXT:      /* 123 */     // MIs[0] root
+// CHECK-NEXT:      /* 123 */     GIM_RecordRegType, /*MI*/0, /*Op*/0, /*TempTypeIdx*/255,
+// CHECK-NEXT:      /* 127 */     // MIs[0] Operand 1
+// CHECK-NEXT:      /* 127 */     GIM_CheckConstantInt8, /*MI*/0, /*Op*/1, 0,
+// CHECK-NEXT:      /* 131 */     // MIs[0] max
+// CHECK-NEXT:      /* 131 */     GIM_RecordInsnIgnoreCopies, /*DefineMI*/1, /*MI*/0, /*OpIdx*/2, // MIs[1]
+// CHECK-NEXT:      /* 135 */     GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_UMAX),
+// CHECK-NEXT:      /* 139 */     // MIs[1] A
+// CHECK-NEXT:      /* 139 */     // No operand predicates
+// CHECK-NEXT:      /* 139 */     // MIs[1] sub
+// CHECK-NEXT:      /* 139 */     GIM_RecordInsnIgnoreCopies, /*DefineMI*/2, /*MI*/1, /*OpIdx*/2, // MIs[2]
+// CHECK-NEXT:      /* 143 */     GIM_CheckOpcode, /*MI*/2, GIMT_Encode2(TargetOpcode::G_SUB),
+// CHECK-NEXT:      /* 147 */     // MIs[2] Operand 1
+// CHECK-NEXT:      /* 147 */     GIM_CheckConstantInt8, /*MI*/2, /*Op*/1, 0,
+// CHECK-NEXT:      /* 151 */     // MIs[2] A
+// CHECK-NEXT:      /* 151 */     GIM_CheckIsSameOperandIgnoreCopies, /*MI*/2, /*OpIdx*/2, /*OtherMI*/1, /*OtherOpIdx*/1,
+// CHECK-NEXT:      /* 156 */     GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner0),
+// CHECK-NEXT:      /* 160 */     GIM_CheckIsSafeToFold, /*NumInsns*/2,
+// CHECK-NEXT:      /* 162 */     GIR_MakeTempReg, /*TempRegID*/1, /*TypeID*/255,
+// CHECK-NEXT:      /* 165 */     GIR_BuildConstant, /*TempRegID*/1, /*Val*/GIMT_Encode8(0),
+// CHECK-NEXT:      /* 175 */     GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/255,
+// CHECK-NEXT:      /* 178 */     // Combiner Rule #0: SharedCXXPred0
+// CHECK-NEXT:      /* 178 */     GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::G_SUB),
+// CHECK-NEXT:      /* 181 */     GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/GIMT_Encode2(static_cast<uint16_t>(RegState::Define)),
+// CHECK-NEXT:      /* 186 */     GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/1,
+// CHECK-NEXT:      /* 189 */     GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // A
+// CHECK-NEXT:      /* 193 */     GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
+// CHECK-NEXT:      /* 199 */     GIR_BuildMI, /*InsnID*/1, /*Opcode*/GIMT_Encode2(TargetOpcode::G_UMIN),
+// CHECK-NEXT:      /* 203 */     GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/0, // root
+// CHECK-NEXT:      /* 207 */     GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/1, /*OpIdx*/1, // A
+// CHECK-NEXT:      /* 211 */     GIR_AddSimpleTempRegister, /*InsnID*/1, /*TempRegID*/0,
+// CHECK-NEXT:      /* 214 */     GIR_UnsetMIFlags, /*InsnID*/1, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
+// CHECK-NEXT:      /* 220 */     GIR_EraseRootFromParent_Done,
+// CHECK-NEXT:      /* 221 */   // Label 2: @221
+// CHECK-NEXT:      /* 221 */   GIM_Reject,
+// CHECK-NEXT:      /* 222 */ // Label 0: @222
+// CHECK-NEXT:      /* 222 */ GIM_Reject,
+// CHECK-NEXT:      /* 223 */ }; // Size: 223 bytes
 // CHECK-NEXT:   return MatchTable0;
 // CHECK-NEXT: }
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-hoisting.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-hoisting.td
index ebad6f7ac86bf..55a01de6a4800 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-hoisting.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-hoisting.td
@@ -35,9 +35,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 
 // CHECK:      const uint8_t *GenMyCombiner::getMatchTable() const {
 // CHECK-NEXT:   constexpr static uint8_t MatchTable0[] = {
-// CHECK-NEXT:      /*   0 */ GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(100),
+// CHECK-NEXT:      /*   0 */ GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(112),
 // CHECK-NEXT:      /*   5 */   GIM_CheckOpcode, /*MI*/0, GIMT_Encode2(TargetOpcode::G_SUB),
-// CHECK-NEXT:      /*   9 */   GIM_Try, /*On fail goto*//*Label 1*/ GIMT_Encode4(54), // Rule ID 1 //
+// CHECK-NEXT:      /*   9 */   GIM_Try, /*On fail goto*//*Label 1*/ GIMT_Encode4(60), // Rule ID 1 //
 // CHECK-NEXT:      /*  14 */     GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled),
 // CHECK-NEXT:      /*  17 */     // MIs[0] root
 // CHECK-NEXT:      /*  17 */     // No operand predicates
@@ -61,37 +61,39 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:      /*  43 */     GIR_RootToRootCopy, /*OpIdx*/0, // root
 // CHECK-NEXT:      /*  45 */     GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // A
 // CHECK-NEXT:      /*  49 */     GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/2, /*OpIdx*/2, // C
-// CHECK-NEXT:      /*  53 */     GIR_EraseRootFromParent_Done,
-// CHECK-NEXT:      /*  54 */   // Label 1: @54
-// CHECK-NEXT:      /*  54 */   GIM_Try, /*On fail goto*//*Label 2*/ GIMT_Encode4(99), // Rule ID 0 //
-// CHECK-NEXT:      /*  59 */     GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
-// CHECK-NEXT:      /*  62 */     // MIs[0] root
-// CHECK-NEXT:      /*  62 */     // No operand predicates
-// CHECK-NEXT:      /*  62 */     // MIs[0] add1
-// CHECK-NEXT:      /*  62 */     GIM_RecordInsnIgnoreCopies, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1]
-// CHECK-NEXT:      /*  66 */     GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_ADD),
-// CHECK-NEXT:      /*  70 */     // MIs[1] A
-// CHECK-NEXT:      /*  70 */     // No operand predicates
-// CHECK-NEXT:      /*  70 */     // MIs[1] sub1
-// CHECK-NEXT:      /*  70 */     GIM_RecordInsnIgnoreCopies, /*DefineMI*/2, /*MI*/1, /*OpIdx*/2, // MIs[2]
-// CHECK-NEXT:      /*  74 */     GIM_CheckOpcode, /*MI*/2, GIMT_Encode2(TargetOpcode::G_SUB),
-// CHECK-NEXT:      /*  78 */     // MIs[2] B
-// CHECK-NEXT:      /*  78 */     // No operand predicates
-// CHECK-NEXT:      /*  78 */     // MIs[2] C
-// CHECK-NEXT:      /*  78 */     // No operand predicates
-// CHECK-NEXT:      /*  78 */     // MIs[0] B
-// CHECK-NEXT:      /*  78 */     GIM_CheckIsSameOperandIgnoreCopies, /*MI*/0, /*OpIdx*/2, /*OtherMI*/2, /*OtherOpIdx*/1,
-// CHECK-NEXT:      /*  83 */     GIM_CheckIsSafeToFold, /*NumInsns*/2,
-// CHECK-NEXT:      /*  85 */     // Combiner Rule #0: SharedPreds0
-// CHECK-NEXT:      /*  85 */     GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::G_SUB),
-// CHECK-NEXT:      /*  88 */     GIR_RootToRootCopy, /*OpIdx*/0, // root
-// CHECK-NEXT:      /*  90 */     GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // A
-// CHECK-NEXT:      /*  94 */     GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/2, /*OpIdx*/2, // C
-// CHECK-NEXT:      /*  98 */     GIR_EraseRootFromParent_Done,
-// CHECK-NEXT:      /*  99 */   // Label 2: @99
-// CHECK-NEXT:      /*  99 */   GIM_Reject,
-// CHECK-NEXT:      /* 100 */ // Label 0: @100
-// CHECK-NEXT:      /* 100 */ GIM_Reject,
-// CHECK-NEXT:      /* 101 */ }; // Size: 101 bytes
+// CHECK-NEXT:      /*  53 */     GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
+// CHECK-NEXT:      /*  59 */     GIR_EraseRootFromParent_Done,
+// CHECK-NEXT:      /*  60 */   // Label 1: @60
+// CHECK-NEXT:      /*  60 */   GIM_Try, /*On fail goto*//*Label 2*/ GIMT_Encode4(111), // Rule ID 0 //
+// CHECK-NEXT:      /*  65 */     GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
+// CHECK-NEXT:      /*  68 */     // MIs[0] root
+// CHECK-NEXT:      /*  68 */     // No operand predicates
+// CHECK-NEXT:      /*  68 */     // MIs[0] add1
+// CHECK-NEXT:      /*  68 */     GIM_RecordInsnIgnoreCopies, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1]
+// CHECK-NEXT:      /*  72 */     GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_ADD),
+// CHECK-NEXT:      /*  76 */     // MIs[1] A
+// CHECK-NEXT:      /*  76 */     // No operand predicates
+// CHECK-NEXT:      /*  76 */     // MIs[1] sub1
+// CHECK-NEXT:      /*  76 */     GIM_RecordInsnIgnoreCopies, /*DefineMI*/2, /*MI*/1, /*OpIdx*/2, // MIs[2]
+// CHECK-NEXT:      /*  80 */     GIM_CheckOpcode, /*MI*/2, GIMT_Encode2(TargetOpcode::G_SUB),
+// CHECK-NEXT:      /*  84 */     // MIs[2] B
+// CHECK-NEXT:      /*  84 */     // No operand predicates
+// CHECK-NEXT:      /*  84 */     // MIs[2] C
+// CHECK-NEXT:      /*  84 */     // No operand predicates
+// CHECK-NEXT:      /*  84 */     // MIs[0] B
+// CHECK-NEXT:      /*  84 */     GIM_CheckIsSameOperandIgnoreCopies, /*MI*/0, /*OpIdx*/2, /*OtherMI*/2, /*OtherOpIdx*/1,
+// CHECK-NEXT:      /*  89 */     GIM_CheckIsSafeToFold, /*NumInsns*/2,
+// CHECK-NEXT:      /*  91 */     // Combiner Rule #0: SharedPreds0
+// CHECK-NEXT:      /*  91 */     GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::G_SUB),
+// CHECK-NEXT:      /*  94 */     GIR_RootToRootCopy, /*OpIdx*/0, // root
+// CHECK-NEXT:      /*  96 */     GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // A
+// CHECK-NEXT:      /* 100 */     GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/2, /*OpIdx*/2, // C
+// CHECK-NEXT:      /* 104 */     GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
+// CHECK-NEXT:      /* 110 */     GIR_EraseRootFromParent_Done,
+// CHECK-NEXT:      /* 111 */   // Label 2: @111
+// CHECK-NEXT:      /* 111 */   GIM_Reject,
+// CHECK-NEXT:      /* 112 */ // Label 0: @112
+// CHECK-NEXT:      /* 112 */ GIM_Reject,
+// CHECK-NEXT:      /* 113 */ }; // Size: 113 bytes
 // CHECK-NEXT:   return MatchTable0;
 // CHECK-NEXT: }
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-imms.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-imms.td
index e0b802447ea2a..dcc8d92c42ef3 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-imms.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-imms.td
@@ -49,6 +49,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY),
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/0, // a
 // CHECK-NEXT:       GIR_AddImm8, /*InsnID*/0, /*Imm*/0,
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
 // CHECK-NEXT:     // Label 4: @[[L492]]
 // CHECK-NEXT:     GIM_Reject,
@@ -63,6 +64,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::G_CONSTANT),
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/0, // a
 // CHECK-NEXT:       GIR_AddCImm, /*InsnID*/0, /*Type*/GILLT_s32, /*Imm*/GIMT_Encode8(42),
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
 // CHECK-NEXT:     // Label 5: @[[L538]]
 // CHECK-NEXT:     GIM_Reject,
@@ -79,6 +81,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY),
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/0, // a
 // CHECK-NEXT:       GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0,
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
 // CHECK-NEXT:     // Label 6: @[[L578]]
 // CHECK-NEXT:     GIM_Reject,
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-intrinsics.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-intrinsics.td
index 22cb105355ab1..24c8232ac5306 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-intrinsics.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-intrinsics.td
@@ -46,10 +46,12 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::G_INTRINSIC),
 // CHECK-NEXT:       GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/GIMT_Encode2(static_cast<uint16_t>(RegState::Define)),
 // CHECK-NEXT:       GIR_AddIntrinsicID, /*MI*/0, GIMT_Encode2(Intrinsic::0in_1out),
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_BuildMI, /*InsnID*/1, /*Opcode*/GIMT_Encode2(TargetOpcode::G_INTRINSIC),
 // CHECK-NEXT:       GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/0, // a
 // CHECK-NEXT:       GIR_AddIntrinsicID, /*MI*/1, GIMT_Encode2(Intrinsic::1in_1out),
 // CHECK-NEXT:       GIR_AddSimpleTempRegister, /*InsnID*/1, /*TempRegID*/0,
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/1, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
 // CHECK-NEXT:     // Label 3: @[[L72]]
 // CHECK-NEXT:     GIM_Reject,
@@ -68,16 +70,18 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/GIMT_Encode2(static_cast<uint16_t>(RegState::Define)),
 // CHECK-NEXT:       GIR_AddIntrinsicID, /*MI*/0, GIMT_Encode2(Intrinsic::convergent_1in_1out),
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/2, // b
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_BuildMI, /*InsnID*/1, /*Opcode*/GIMT_Encode2(TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS),
 // CHECK-NEXT:       GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/0, // a
 // CHECK-NEXT:       GIR_AddIntrinsicID, /*MI*/1, GIMT_Encode2(Intrinsic::convergent_sideeffects_1in_1out),
 // CHECK-NEXT:       GIR_AddSimpleTempRegister, /*InsnID*/1, /*TempRegID*/0,
 // CHECK-NEXT:       GIR_MergeMemOperands, /*InsnID*/1, /*NumInsns*/1, /*MergeInsnID's*/0,
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/1, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
 // CHECK-NEXT:     // Label 4: @[[L131]]
 // CHECK-NEXT:     GIM_Reject,
 // CHECK-NEXT:     // Label 2: @[[L132]]
 // CHECK-NEXT:     GIM_Reject,
-// CHECK-NEXT:     }; // Size: 125 bytes
+// CHECK-NEXT:     }; // Size: 149 bytes
 // CHECK-NEXT:   return MatchTable0;
 // CHECK-NEXT: }
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-miflags.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-miflags.td
index 24864e8aef456..b5edf5c27f3f2 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-miflags.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-miflags.td
@@ -17,7 +17,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [MIFlagsTest]>;
 
 // CHECK:      const uint8_t *GenMyCombiner::getMatchTable() const {
 // CHECK-NEXT:   constexpr static uint8_t MatchTable0[] = {
-// CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(63), // Rule ID 0 //
+// CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(69), // Rule ID 0 //
 // CHECK-NEXT:       GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
 // CHECK-NEXT:       GIM_CheckOpcode, /*MI*/0, GIMT_Encode2(TargetOpcode::G_SEXT),
 // CHECK-NEXT:       // MIs[0] dst
@@ -35,11 +35,12 @@ def MyCombiner: GICombiner<"GenMyCombiner", [MIFlagsTest]>;
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/0, // dst
 // CHECK-NEXT:       GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src
 // CHECK-NEXT:       GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_CopyMIFlags, /*InsnID*/0, /*OldInsnID*/1,
 // CHECK-NEXT:       GIR_SetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::FmReassoc),
 // CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::FmNsz | MachineInstr::FmArcp),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
-// CHECK-NEXT:     // Label 0: @63
+// CHECK-NEXT:     // Label 0: @69
 // CHECK-NEXT:     GIM_Reject,
 // CHECK-NEXT:     };
 // CHECK-NEXT:   return MatchTable0;
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-operand-types.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-operand-types.td
index e359ddf73cd8a..4874b0eb0bca8 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-operand-types.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-operand-types.td
@@ -21,7 +21,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 
 // CHECK:      const uint8_t *GenMyCombiner::getMatchTable() const {
 // CHECK-NEXT:   constexpr static uint8_t MatchTable0[] = {
-// CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(73), // Rule ID 0 //
+// CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(85), // Rule ID 0 //
 // CHECK-NEXT:       GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
 // CHECK-NEXT:       GIM_CheckOpcode, /*MI*/0, GIMT_Encode2(TargetOpcode::G_MUL),
 // CHECK-NEXT:       GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_s8,
@@ -39,13 +39,15 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/GIMT_Encode2(static_cast<uint16_t>(RegState::Define)),
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/1, // b
 // CHECK-NEXT:       GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // c
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_BuildMI, /*InsnID*/1, /*Opcode*/GIMT_Encode2(TargetOpcode::G_ADD),
 // CHECK-NEXT:       GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/0, // a
 // CHECK-NEXT:       GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/1, // b
 // CHECK-NEXT:       GIR_AddSimpleTempRegister, /*InsnID*/1, /*TempRegID*/0,
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/1, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
-// CHECK-NEXT:     // Label 0: @73
+// CHECK-NEXT:     // Label 0: @85
 // CHECK-NEXT:     GIM_Reject,
-// CHECK-NEXT:     }; // Size: 74 bytes
+// CHECK-NEXT:     }; // Size: 86 bytes
 // CHECK-NEXT:   return MatchTable0;
 // CHECK-NEXT: }
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-patfrag-root.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-patfrag-root.td
index 5a8b51dfc8324..26d010cffceea 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-patfrag-root.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-patfrag-root.td
@@ -45,6 +45,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY),
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/0, // root
 // CHECK-NEXT:       GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0,
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
 // CHECK-NEXT:     // Label 4: @[[L297]]
 // CHECK-NEXT:     GIM_Reject,
@@ -65,6 +66,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY),
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/0, // root
 // CHECK-NEXT:       GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0,
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
 // CHECK-NEXT:     // Label 5: @[[L343]]
 // CHECK-NEXT:     GIM_Reject,
@@ -81,6 +83,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY),
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/0, // root
 // CHECK-NEXT:       GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0,
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
 // CHECK-NEXT:     // Label 6: @[[L379]]
 // CHECK-NEXT:     GIM_Reject,
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td
index 4a908e7823484..2a41be5fea811 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td
@@ -159,9 +159,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 
 // CHECK:      const uint8_t *GenMyCombiner::getMatchTable() const {
 // CHECK-NEXT:   constexpr static uint8_t MatchTable0[] = {
-// CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(562),
+// CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(594),
 // CHECK-NEXT:       GIM_CheckOpcode, /*MI*/0, GIMT_Encode2(TargetOpcode::G_AND),
-// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 1*/ GIMT_Encode4(66), // Rule ID 7 //
+// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 1*/ GIMT_Encode4(70), // Rule ID 7 //
 // CHECK-NEXT:         GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
 // CHECK-NEXT:         // MIs[0] dst
 // CHECK-NEXT:         // No operand predicates
@@ -188,9 +188,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:         GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner23),
 // CHECK-NEXT:         GIM_CheckIsSafeToFold, /*NumInsns*/4,
 // CHECK-NEXT:         // Combiner Rule #0: Test0 @ [a[1], b[1], c[1]]
-// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
-// CHECK-NEXT:       // Label 1: @66
-// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 2*/ GIMT_Encode4(131), // Rule ID 6 //
+// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
+// CHECK-NEXT:       // Label 1: @70
+// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 2*/ GIMT_Encode4(139), // Rule ID 6 //
 // CHECK-NEXT:         GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
 // CHECK-NEXT:         // MIs[0] dst
 // CHECK-NEXT:         // No operand predicates
@@ -220,9 +220,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:         GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner20),
 // CHECK-NEXT:         GIM_CheckIsSafeToFold, /*NumInsns*/5,
 // CHECK-NEXT:         // Combiner Rule #0: Test0 @ [a[1], b[1], c[0]]
-// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
-// CHECK-NEXT:       // Label 2: @131
-// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 3*/ GIMT_Encode4(196), // Rule ID 5 //
+// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
+// CHECK-NEXT:       // Label 2: @139
+// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 3*/ GIMT_Encode4(208), // Rule ID 5 //
 // CHECK-NEXT:         GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
 // CHECK-NEXT:         // MIs[0] dst
 // CHECK-NEXT:         // No operand predicates
@@ -252,9 +252,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:         GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner17),
 // CHECK-NEXT:         GIM_CheckIsSafeToFold, /*NumInsns*/5,
 // CHECK-NEXT:         // Combiner Rule #0: Test0 @ [a[1], b[0], c[1]]
-// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
-// CHECK-NEXT:       // Label 3: @196
-// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4(269), // Rule ID 4 //
+// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
+// CHECK-NEXT:       // Label 3: @208
+// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4(285), // Rule ID 4 //
 // CHECK-NEXT:         GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
 // CHECK-NEXT:         // MIs[0] dst
 // CHECK-NEXT:         // No operand predicates
@@ -287,9 +287,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:         GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner14),
 // CHECK-NEXT:         GIM_CheckIsSafeToFold, /*NumInsns*/6,
 // CHECK-NEXT:         // Combiner Rule #0: Test0 @ [a[1], b[0], c[0]]
-// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
-// CHECK-NEXT:       // Label 4: @269
-// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(334), // Rule ID 3 //
+// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
+// CHECK-NEXT:       // Label 4: @285
+// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(354), // Rule ID 3 //
 // CHECK-NEXT:         GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
 // CHECK-NEXT:         // MIs[0] dst
 // CHECK-NEXT:         // No operand predicates
@@ -319,9 +319,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:         GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner11),
 // CHECK-NEXT:         GIM_CheckIsSafeToFold, /*NumInsns*/5,
 // CHECK-NEXT:         // Combiner Rule #0: Test0 @ [a[0], b[1], c[1]]
-// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
-// CHECK-NEXT:       // Label 5: @334
-// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(407), // Rule ID 2 //
+// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
+// CHECK-NEXT:       // Label 5: @354
+// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(431), // Rule ID 2 //
 // CHECK-NEXT:         GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
 // CHECK-NEXT:         // MIs[0] dst
 // CHECK-NEXT:         // No operand predicates
@@ -354,9 +354,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:         GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner8),
 // CHECK-NEXT:         GIM_CheckIsSafeToFold, /*NumInsns*/6,
 // CHECK-NEXT:         // Combiner Rule #0: Test0 @ [a[0], b[1], c[0]]
-// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
-// CHECK-NEXT:       // Label 6: @407
-// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(480), // Rule ID 1 //
+// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
+// CHECK-NEXT:       // Label 6: @431
+// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(508), // Rule ID 1 //
 // CHECK-NEXT:         GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
 // CHECK-NEXT:         // MIs[0] dst
 // CHECK-NEXT:         // No operand predicates
@@ -389,9 +389,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:         GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner5),
 // CHECK-NEXT:         GIM_CheckIsSafeToFold, /*NumInsns*/6,
 // CHECK-NEXT:         // Combiner Rule #0: Test0 @ [a[0], b[0], c[1]]
-// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
-// CHECK-NEXT:       // Label 7: @480
-// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(561), // Rule ID 0 //
+// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
+// CHECK-NEXT:       // Label 7: @508
+// CHECK-NEXT:       GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(593), // Rule ID 0 //
 // CHECK-NEXT:         GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
 // CHECK-NEXT:         // MIs[0] dst
 // CHECK-NEXT:         // No operand predicates
@@ -427,11 +427,11 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:         GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner2),
 // CHECK-NEXT:         GIM_CheckIsSafeToFold, /*NumInsns*/7,
 // CHECK-NEXT:         // Combiner Rule #0: Test0 @ [a[0], b[0], c[0]]
-// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
-// CHECK-NEXT:       // Label 8: @561
+// CHECK-NEXT:         GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
+// CHECK-NEXT:       // Label 8: @593
 // CHECK-NEXT:       GIM_Reject,
-// CHECK-NEXT:     // Label 0: @562
+// CHECK-NEXT:     // Label 0: @594
 // CHECK-NEXT:     GIM_Reject,
-// CHECK-NEXT:     }; // Size: 563 bytes
+// CHECK-NEXT:     }; // Size: 595 bytes
 // CHECK-NEXT:   return MatchTable0;
 // CHECK-NEXT: }
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-typeof.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-typeof.td
index aca7e5ef42fd0..49897a69081ce 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-typeof.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-typeof.td
@@ -16,7 +16,7 @@ def Test0 : GICombineRule<
 
 // CHECK:      const uint8_t *GenMyCombiner::getMatchTable() const {
 // CHECK-NEXT:   constexpr static uint8_t MatchTable0[] = {
-// CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(74), // Rule ID 0 //
+// CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(86), // Rule ID 0 //
 // CHECK-NEXT:       GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
 // CHECK-NEXT:       GIM_CheckOpcode, /*MI*/0, GIMT_Encode2(TargetOpcode::G_MUL),
 // CHECK-NEXT:       // MIs[0] dst
@@ -32,14 +32,16 @@ def Test0 : GICombineRule<
 // CHECK-NEXT:       GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::G_CONSTANT),
 // CHECK-NEXT:       GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/GIMT_Encode2(static_cast<uint16_t>(RegState::Define)),
 // CHECK-NEXT:       GIR_AddCImm, /*InsnID*/0, /*Type*/254, /*Imm*/GIMT_Encode8(42),
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_BuildMI, /*InsnID*/1, /*Opcode*/GIMT_Encode2(TargetOpcode::G_SUB),
 // CHECK-NEXT:       GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/0, // dst
 // CHECK-NEXT:       GIR_AddSimpleTempRegister, /*InsnID*/1, /*TempRegID*/1,
 // CHECK-NEXT:       GIR_AddSimpleTempRegister, /*InsnID*/1, /*TempRegID*/0,
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/1, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
-// CHECK-NEXT:     // Label 0: @74
+// CHECK-NEXT:     // Label 0: @86
 // CHECK-NEXT:     GIM_Reject,
-// CHECK-NEXT:     }; // Size: 75 bytes
+// CHECK-NEXT:     }; // Size: 87 bytes
 // CHECK-NEXT:   return MatchTable0;
 // CHECK-NEXT: }
 
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-variadics.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-variadics.td
index 98456983c085b..276df294dee98 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-variadics.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-variadics.td
@@ -78,7 +78,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       // MIs[0] b
 // CHECK-NEXT:       // No operand predicates
 // CHECK-NEXT:       // Combiner Rule #2: InstTest2
-// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
+// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:     // Label 3: @{{[0-9]+}}
 // CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 3 //
 // CHECK-NEXT:       GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule3Enabled),
@@ -92,7 +92,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       // MIs[0] d
 // CHECK-NEXT:       // No operand predicates
 // CHECK-NEXT:       // Combiner Rule #3: InstTest3
-// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
+// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:     // Label 4: @{{[0-9]+}}
 // CHECK-NEXT:     GIM_Reject,
 // CHECK-NEXT:     // Label 1: @{{[0-9]+}}
@@ -105,7 +105,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       // MIs[0] b
 // CHECK-NEXT:       // No operand predicates
 // CHECK-NEXT:       // Combiner Rule #4: VariadicTypeTestCxx
-// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner1),
+// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner1), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:     // Label 5: @{{[0-9]+}}
 // CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 1 //
 // CHECK-NEXT:       GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled),
@@ -115,7 +115,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       // MIs[0] b
 // CHECK-NEXT:       // No operand predicates
 // CHECK-NEXT:       // Combiner Rule #1: InstTest1
-// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
+// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:     // Label 6: @{{[0-9]+}}
 // CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 5 //
 // CHECK-NEXT:       GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule5Enabled),
@@ -132,6 +132,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/0, // a
 // CHECK-NEXT:       GIR_CopyRemaining, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/2, // b
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/1, // c
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
 // CHECK-NEXT:     // Label 7: @{{[0-9]+}}
 // CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 0 //
@@ -146,11 +147,11 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       // MIs[0] d
 // CHECK-NEXT:       // No operand predicates
 // CHECK-NEXT:       // Combiner Rule #0: InstTest0
-// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
+// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:     // Label 8: @{{[0-9]+}}
 // CHECK-NEXT:     GIM_Reject,
 // CHECK-NEXT:     // Label 2: @{{[0-9]+}}
 // CHECK-NEXT:     GIM_Reject,
-// CHECK-NEXT:     }; // Size: 128 bytes
+// CHECK-NEXT:     }; // Size: 154 bytes
 // CHECK-NEXT:   return MatchTable0;
 // CHECK-NEXT: }
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td
index 58c25ab925b85..545c1a4d074b0 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td
@@ -171,7 +171,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       // No operand predicates
 // CHECK-NEXT:       GIM_CheckIsSafeToFold, /*NumInsns*/1,
 // CHECK-NEXT:       // Combiner Rule #3: InstTest1
-// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner2),
+// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner2), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:     // Label 7: @[[L7]]
 // CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4([[L8:[0-9]+]]), // Rule ID 3 //
 // CHECK-NEXT:       GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule2Enabled),
@@ -180,7 +180,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       // MIs[0] b
 // CHECK-NEXT:       // No operand predicates
 // CHECK-NEXT:       // Combiner Rule #2: InstTest0
-// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner1),
+// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner1), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:     // Label 8: @[[L8]]
 // CHECK-NEXT:     GIM_Reject,
 // CHECK-NEXT:     // Label 1: @[[L1]]
@@ -200,6 +200,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::G_TRUNC),
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/0, // dst
 // CHECK-NEXT:       GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // z
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
 // CHECK-NEXT:     // Label 9: @[[L9]]
 // CHECK-NEXT:     GIM_Reject,
@@ -219,6 +220,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // ext
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/1, // ptr
 // CHECK-NEXT:       GIR_MergeMemOperands, /*InsnID*/0, /*NumInsns*/2, /*MergeInsnID's*/0, 1,
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
 // CHECK-NEXT:     // Label 10: @[[L10]]
 // CHECK-NEXT:     GIM_Reject,
@@ -226,19 +228,19 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 11*/ GIMT_Encode4([[L11:[0-9]+]]), // Rule ID 0 //
 // CHECK-NEXT:       GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
 // CHECK-NEXT:       // Combiner Rule #0: WipOpcodeTest0; wip_match_opcode 'G_TRUNC'
-// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
+// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:     // Label 11: @[[L11]]
 // CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 12*/ GIMT_Encode4([[L12:[0-9]+]]), // Rule ID 1 //
 // CHECK-NEXT:       GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled),
 // CHECK-NEXT:       // Combiner Rule #1: WipOpcodeTest1; wip_match_opcode 'G_TRUNC'
-// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
+// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:     // Label 12: @[[L12]]
 // CHECK-NEXT:     GIM_Reject,
 // CHECK-NEXT:     // Label 4: @[[L4]]
 // CHECK-NEXT:     GIM_Try, /*On fail goto*//*Label 13*/ GIMT_Encode4([[L13:[0-9]+]]), // Rule ID 2 //
 // CHECK-NEXT:       GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled),
 // CHECK-NEXT:       // Combiner Rule #1: WipOpcodeTest1; wip_match_opcode 'G_SEXT'
-// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
+// CHECK-NEXT:       GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), /*InitialUnsetFlags*/GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:     // Label 13: @[[L13]]
 // CHECK-NEXT:     GIM_Reject,
 // CHECK-NEXT:     // Label 5: @[[L5]]
@@ -255,6 +257,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 // CHECK-NEXT:       GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY),
 // CHECK-NEXT:       GIR_RootToRootCopy, /*OpIdx*/0, // dst
 // CHECK-NEXT:       GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0,
+// CHECK-NEXT:       GIR_UnsetMIFlags, /*InsnID*/0, GIMT_Encode4(MachineInstr::NoUWrap | MachineInstr::NoSWrap | MachineInstr::NoUSWrap | MachineInstr::IsExact | MachineInstr::Disjoint | MachineInstr::NonNeg | MachineInstr::FmNoNans | MachineInstr::FmNoInfs | MachineInstr::SameSign | MachineInstr::InBounds),
 // CHECK-NEXT:       GIR_EraseRootFromParent_Done,
 // CHECK-NEXT:     // Label 14: @[[L14]]
 // CHECK-NEXT:     GIM_Reject,
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td
index 7541639480fc5..335c96f184d51 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td
@@ -325,7 +325,7 @@ def TypeOfTest : GICombineRule<
 // CHECK-NEXT:     <match_root>mi:(CodeGenInstructionPattern G_ZEXT operands:[<def>$dst, $src] (MIFlags (set MachineInstr::FmReassoc) (unset MachineInstr::FmNoNans, MachineInstr::FmArcp)))
 // CHECK-NEXT:   )
 // CHECK-NEXT:   (ApplyPats
-// CHECK-NEXT:     <apply_root>__MIFlagsTest_apply_0:(CodeGenInstructionPattern G_MUL operands:[<def>$dst, $src, $src] (MIFlags (set MachineInstr::FmReassoc) (unset MachineInstr::FmNsz, MachineInstr::FmArcp) (copy mi)))
+// CHECK-NEXT:     <apply_root>__MIFlagsTest_apply_0:(CodeGenInstructionPattern G_MUL operands:[<def>$dst, $src, $src] (MIFlags (set MachineInstr::FmReassoc, MachineInstr::SameSign) (unset MachineInstr::FmNsz, MachineInstr::FmArcp) (copy mi)))
 // CHECK-NEXT:   )
 // CHECK-NEXT:   (OperandTable MatchPats
 // CHECK-NEXT:     dst -> mi
@@ -339,7 +339,7 @@ def TypeOfTest : GICombineRule<
 def MIFlagsTest : GICombineRule<
   (defs root:$dst),
   (match (G_ZEXT $dst, $src, (MIFlags FmReassoc, (not FmNoNans, FmArcp))):$mi),
-  (apply (G_MUL $dst, $src, $src, (MIFlags $mi, FmReassoc, (not FmNsz, FmArcp))))>;
+  (apply (G_MUL $dst, $src, $src, (MIFlags $mi, FmReassoc, SameSign, (not FmNsz, FmArcp))))>;
 
 // CHECK-NEXT: (CombineRule name:IntrinTest0 id:12 root:a
 // CHECK-NEXT:   (MatchPats
diff --git a/llvm/unittests/CodeGen/GlobalISel/GIMatchTableExecutorTest.cpp b/llvm/unittests/CodeGen/GlobalISel/GIMatchTableExecutorTest.cpp
index 5a811d7959288..ea6cfa16eda94 100644
--- a/llvm/unittests/CodeGen/GlobalISel/GIMatchTableExecutorTest.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/GIMatchTableExecutorTest.cpp
@@ -7,10 +7,73 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h"
+#include "GISelMITest.h"
+#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/Target/TargetMachine.h"
 #include "gtest/gtest.h"
 
 using namespace llvm;
 
+namespace {
+
+class TestGIMatchTableExecutor : public GIMatchTableExecutor {
+public:
+  static const char *getName() { return "test-gimatchtable-executor"; }
+
+  void setupGeneratedPerFunctionState(MachineFunction &MF) override {}
+
+  bool runCustomAction(unsigned FnID, const MatcherState &State,
+                       NewMIVector &OutMIs) const override {
+    assert(FnID == 1);
+    MachineInstr &Root = *State.MIs[0];
+    MachineBasicBlock &MBB = *Root.getParent();
+    MachineInstrBuilder MIB =
+        BuildMI(MBB, Root.getIterator(), Root.getDebugLoc(),
+                MF->getSubtarget().getInstrInfo()->get(TargetOpcode::G_SUB))
+            .addDef(Root.getOperand(0).getReg())
+            .addUse(Root.getOperand(1).getReg())
+            .addUse(Root.getOperand(2).getReg());
+    MIB.setMIFlags(MachineInstr::NoSWrap);
+    OutMIs.push_back(MIB);
+    return true;
+  }
+
+  bool run(MachineInstr &Root, MachineIRBuilder &Builder,
+           const uint8_t *MatchTable, const TargetInstrInfo &TII,
+           MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
+           const RegisterBankInfo &RBI) const {
+    MatcherState State(/*MaxRenderers=*/0);
+    State.MIs.push_back(&Root);
+    using PredicateBitset = Bitset<1>;
+    using ComplexMatcherMemFn =
+        ComplexRendererFns (TestGIMatchTableExecutor::*)(MachineOperand &)
+            const;
+    using CustomRendererFn = void (TestGIMatchTableExecutor::*)(
+        MachineInstrBuilder &, const MachineInstr &, int64_t) const;
+    const ExecInfoTy<PredicateBitset, ComplexMatcherMemFn, CustomRendererFn>
+        ExecInfo(nullptr, 0, nullptr, nullptr, nullptr);
+    PredicateBitset AvailableFeatures;
+    return executeMatchTable(*const_cast<TestGIMatchTableExecutor *>(this),
+                             State, ExecInfo, Builder, MatchTable, TII, MRI,
+                             TRI, RBI, AvailableFeatures, nullptr);
+  }
+};
+
+static void appendU16(SmallVectorImpl<uint8_t> &Table, uint16_t Value) {
+  Table.push_back(Value & 0xff);
+  Table.push_back((Value >> 8) & 0xff);
+}
+
+static void appendU32(SmallVectorImpl<uint8_t> &Table, uint32_t Value) {
+  Table.push_back(Value & 0xff);
+  Table.push_back((Value >> 8) & 0xff);
+  Table.push_back((Value >> 16) & 0xff);
+  Table.push_back((Value >> 24) & 0xff);
+}
+
+} // namespace
+
 TEST(GlobalISelLEB128Test, fastDecodeULEB128) {
 #define EXPECT_DECODE_ULEB128_EQ(EXPECTED, VALUE)                              \
   do {                                                                         \
@@ -47,3 +110,89 @@ TEST(GlobalISelLEB128Test, fastDecodeULEB128) {
 
 #undef EXPECT_DECODE_ULEB128_EQ
 }
+
+TEST_F(AArch64GISelMITest, MatchTableExplicitMIFlagsOverrideInitialUnset) {
+  setUp("");
+  if (!TM)
+    GTEST_SKIP();
+
+  Register RootReg = MRI->createGenericVirtualRegister(LLT::scalar(64));
+  auto Root =
+      B.buildInstr(TargetOpcode::G_ADD, {RootReg}, {Copies[1], Copies[2]});
+  Root->setFlags(MachineInstr::NoUWrap | MachineInstr::NoSWrap);
+
+  TestGIMatchTableExecutor Executor;
+  Executor.setupMF(*MF, nullptr);
+
+  SmallVector<uint8_t, 32> MatchTable;
+  MatchTable.push_back(GIR_BuildMI);
+  MatchTable.push_back(0); // InsnID
+  appendU16(MatchTable, TargetOpcode::G_SUB);
+  MatchTable.push_back(GIR_BuildMI);
+  MatchTable.push_back(1); // InsnID
+  appendU16(MatchTable, TargetOpcode::G_SUB);
+  MatchTable.push_back(GIR_UnsetMIFlags);
+  MatchTable.push_back(0); // InsnID
+  appendU32(MatchTable, MachineInstr::NoUWrap | MachineInstr::NoSWrap);
+  MatchTable.push_back(GIR_SetMIFlags);
+  MatchTable.push_back(0); // InsnID
+  appendU32(MatchTable, MachineInstr::NoSWrap);
+  MatchTable.push_back(GIR_UnsetMIFlags);
+  MatchTable.push_back(1); // InsnID
+  appendU32(MatchTable, MachineInstr::NoUWrap | MachineInstr::NoSWrap);
+  MatchTable.push_back(GIR_CopyMIFlags);
+  MatchTable.push_back(1); // InsnID
+  MatchTable.push_back(0); // OldInsnID
+  MatchTable.push_back(GIR_Done);
+
+  const TargetSubtargetInfo &STI = MF->getSubtarget();
+  EXPECT_TRUE(Executor.run(*Root, B, MatchTable.data(), *STI.getInstrInfo(),
+                           *MRI, *STI.getRegisterInfo(),
+                           *STI.getRegBankInfo()));
+
+  SmallVector<MachineInstr *, 2> BuiltMIs;
+  for (MachineInstr &MI : *EntryMBB) {
+    if (MI.getOpcode() == TargetOpcode::G_SUB)
+      BuiltMIs.push_back(&MI);
+  }
+  ASSERT_EQ(BuiltMIs.size(), 2u);
+  EXPECT_FALSE(BuiltMIs[0]->getFlag(MachineInstr::NoUWrap));
+  EXPECT_TRUE(BuiltMIs[0]->getFlag(MachineInstr::NoSWrap));
+  EXPECT_TRUE(BuiltMIs[1]->getFlag(MachineInstr::NoUWrap));
+  EXPECT_TRUE(BuiltMIs[1]->getFlag(MachineInstr::NoSWrap));
+}
+
+TEST_F(AArch64GISelMITest, MatchTableCustomActionDropsRootMIFlags) {
+  setUp("");
+  if (!TM)
+    GTEST_SKIP();
+
+  Register RootReg = MRI->createGenericVirtualRegister(LLT::scalar(64));
+  auto Root =
+      B.buildInstr(TargetOpcode::G_ADD, {RootReg}, {Copies[1], Copies[2]});
+  Root->setFlags(MachineInstr::NoUWrap | MachineInstr::NoSWrap);
+
+  TestGIMatchTableExecutor Executor;
+  Executor.setupMF(*MF, nullptr);
+
+  SmallVector<uint8_t, 16> MatchTable;
+  MatchTable.push_back(GIR_DoneWithCustomAction);
+  appendU16(MatchTable, 1); // FnID
+  appendU32(MatchTable, MachineInstr::NoUWrap | MachineInstr::NoSWrap);
+
+  const TargetSubtargetInfo &STI = MF->getSubtarget();
+  EXPECT_TRUE(Executor.run(*Root, B, MatchTable.data(), *STI.getInstrInfo(),
+                           *MRI, *STI.getRegisterInfo(),
+                           *STI.getRegBankInfo()));
+
+  MachineInstr *BuiltMI = nullptr;
+  for (MachineInstr &MI : *EntryMBB) {
+    if (MI.getOpcode() == TargetOpcode::G_SUB) {
+      BuiltMI = &MI;
+      break;
+    }
+  }
+  ASSERT_NE(BuiltMI, nullptr);
+  EXPECT_FALSE(BuiltMI->getFlag(MachineInstr::NoUWrap));
+  EXPECT_TRUE(BuiltMI->getFlag(MachineInstr::NoSWrap));
+}
diff --git a/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp
index cc1089fc316c7..85afde6c7fcd3 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp
@@ -830,6 +830,8 @@ void RuleMatcher::emit(MatchTable &Table) {
     Table << MatchTable::Opcode("GIR_DoneWithCustomAction", -1)
           << MatchTable::Comment("Fn")
           << MatchTable::NamedValue(2, CustomCXXAction)
+          << MatchTable::Comment("InitialUnsetFlags")
+          << MatchTable::NamedValue(4, CustomCXXActionInitialUnsetFlags)
           << MatchTable::LineBreak;
   } else {
     // Emit all actions except the last one, then emit coverage and emit the
@@ -1956,6 +1958,13 @@ void BuildMIAction::chooseInsnToMutate(RuleMatcher &Rule) {
 
 void BuildMIAction::emitActionOpcodes(MatchTable &Table) const {
   const auto AddMIFlags = [&]() {
+    if (!InitialUnsetFlags.empty()) {
+      Table << MatchTable::Opcode("GIR_UnsetMIFlags")
+            << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
+            << MatchTable::NamedValue(4, join(InitialUnsetFlags, " | "))
+            << MatchTable::LineBreak;
+    }
+
     for (const InstructionMatcher *IM : CopiedFlags) {
       Table << MatchTable::Opcode("GIR_CopyMIFlags")
             << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
diff --git a/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.h b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.h
index b7ea01279eea9..720a60f0e1347 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.h
+++ b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.h
@@ -305,6 +305,7 @@ class RuleMatcher : public Matcher {
   /// Combiners can sometimes just run C++ code to finish matching a rule &
   /// mutate instructions instead of relying on MatchActions. Empty if unused.
   std::string CustomCXXAction;
+  std::string CustomCXXActionInitialUnsetFlags = "0";
 
   using MutatableInsnSet = SmallPtrSet<InstructionMatcher *, 4>;
 
@@ -410,6 +411,9 @@ class RuleMatcher : public Matcher {
   void setCustomCXXAction(StringRef FnEnumName) {
     CustomCXXAction = FnEnumName.str();
   }
+  void setCustomCXXActionInitialUnsetFlags(StringRef Flags) {
+    CustomCXXActionInitialUnsetFlags = Flags.str();
+  }
 
   // Emplaces an action of the specified Kind at the end of the action list.
   //
@@ -2251,6 +2255,7 @@ class BuildMIAction : public MatchAction {
   SmallPtrSet<const Record *, 4> DeadImplicitDefs;
 
   std::vector<const InstructionMatcher *> CopiedFlags;
+  std::vector<StringRef> InitialUnsetFlags;
   std::vector<StringRef> SetFlags;
   std::vector<StringRef> UnsetFlags;
   std::vector<unsigned> MergeInsnIDs;
@@ -2283,6 +2288,9 @@ class BuildMIAction : public MatchAction {
   unsigned getInsnID() const { return InsnID; }
   const CodeGenInstruction *getCGI() const { return I; }
 
+  void addInitialUnsetMIFlags(StringRef Flag) {
+    InitialUnsetFlags.push_back(Flag);
+  }
   void addSetMIFlags(StringRef Flag) { SetFlags.push_back(Flag); }
   void addUnsetMIFlags(StringRef Flag) { UnsetFlags.push_back(Flag); }
   void addCopiedMIFlags(const InstructionMatcher &IM) {
diff --git a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
index bb93d0248e55f..df037d5d504d7 100644
--- a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
@@ -83,6 +83,17 @@ constexpr StringLiteral CXXCustomActionPrefix = "GICXXCustomAction_";
 constexpr StringLiteral CXXPredPrefix = "GICXXPred_MI_Predicate_";
 constexpr StringLiteral MatchDataClassName = "GIDefMatchData";
 
+static constexpr StringLiteral PoisonGeneratingMIFlags[] = {
+    "MachineInstr::NoUWrap",  "MachineInstr::NoSWrap",
+    "MachineInstr::NoUSWrap", "MachineInstr::IsExact",
+    "MachineInstr::Disjoint", "MachineInstr::NonNeg",
+    "MachineInstr::FmNoNans", "MachineInstr::FmNoInfs",
+    "MachineInstr::SameSign", "MachineInstr::InBounds"};
+
+static std::string getPoisonGeneratingMIFlags() {
+  return join(ArrayRef(PoisonGeneratingMIFlags), " | ");
+}
+
 //===- CodeExpansions Helpers  --------------------------------------------===//
 
 static void declareInstExpansion(CodeExpansions &CE,
@@ -1951,6 +1962,7 @@ bool CombineRuleBuilder::emitCXXMatchApply(CodeExpansions &CE, RuleMatcher &M,
 
   const auto &Code = CXXPredicateCode::getCustomActionCode(CodeStr);
   M.setCustomCXXAction(Code.getEnumNameWithPrefix(CXXCustomActionPrefix));
+  M.setCustomCXXActionInitialUnsetFlags(getPoisonGeneratingMIFlags());
   return true;
 }
 
@@ -2104,6 +2116,10 @@ bool CombineRuleBuilder::emitInstructionApplyPattern(
   if (CGIP.isIntrinsic() && !HasEmittedIntrinsicID)
     EmitIntrinsicID();
 
+  // Poison-generating flags need to be explicitly preserved by the pattern.
+  for (StringRef F : PoisonGeneratingMIFlags)
+    DstMI.addInitialUnsetMIFlags(F);
+
   // Render MIFlags
   if (const auto *FI = CGIP.getMIFlagsInfo()) {
     for (StringRef InstName : FI->copy_flags())



More information about the llvm-commits mailing list