[llvm] [GISel][CombinerHelper] Push freeze through non-poison-producing operands (PR #90618)

Dhruv Chawla via llvm-commits llvm-commits at lists.llvm.org
Tue May 21 02:39:05 PDT 2024


https://github.com/dc03-work updated https://github.com/llvm/llvm-project/pull/90618

>From 11568391430bcff551a19bbcf3e916605437a050 Mon Sep 17 00:00:00 2001
From: Dhruv Chawla <dhruvc at nvidia.com>
Date: Tue, 30 Apr 2024 17:04:00 +0530
Subject: [PATCH 1/9] [GISel][CombinerHelper] Push freeze through
 non-poison-producing operands

This combine matches the existing fold in InstCombine, i.e.
InstCombinerImpl::pushFreezeToPreventPoisonFromPropagating.

It tries to push freeze through an operand if the operand has only one
maybe-poison operand and all other operands are guaranteed non-poison.

This is beneficial because it can potentially enable other optimizations
to occur that would otherwise be blocked because of the freeze.
---
 .../llvm/CodeGen/GlobalISel/CombinerHelper.h  |  2 +
 .../include/llvm/Target/GlobalISel/Combine.td | 10 +++-
 .../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 59 +++++++++++++++++++
 llvm/lib/CodeGen/GlobalISel/Utils.cpp         | 17 +++++-
 llvm/lib/Target/AArch64/AArch64Combine.td     |  3 +-
 .../AArch64/GlobalISel/combine-select.mir     | 42 ++++++-------
 llvm/test/CodeGen/AArch64/pr58431.ll          |  4 +-
 7 files changed, 111 insertions(+), 26 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index a9a33c7617d7d..53eb31c12f349 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -869,6 +869,8 @@ class CombinerHelper {
   /// Combine insert vector element OOB.
   bool matchInsertVectorElementOOB(MachineInstr &MI, BuildFnTy &MatchInfo);
 
+  bool matchFreezeOfSingleMaybePoisonOperand(MachineInstr &MI, BuildFnTy &MatchInfo);
+
 private:
   /// Checks for legality of an indexed variant of \p LdSt.
   bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const;
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 5d4b5a2479f6a..29f8cc4da5f95 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -220,6 +220,13 @@ def idempotent_prop : GICombineRule<
    (match (idempotent_prop_frags $dst, $src)),
    (apply (GIReplaceReg $dst, $src))>;
 
+// Convert freeze(Op(Op0, NonPoisonOps...)) to Op(freeze(Op0), NonPoisonOps...)
+// when Op0 is not guaranteed non-poison
+def push_freeze_to_prevent_poison_propagation : GICombineRule<
+  (defs root:$root, build_fn_matchinfo:$matchinfo),
+  (match (wip_match_opcode G_FREEZE):$root,
+         [{ return Helper.matchFreezeOfSingleMaybePoisonOperand(*${root}, ${matchinfo}); }]),
+  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
 
 def extending_loads : GICombineRule<
   (defs root:$root, extending_load_matchdata:$matchinfo),
@@ -1713,7 +1720,8 @@ def all_combines : GICombineGroup<[trivial_combines, vector_ops_combines,
     sub_add_reg, select_to_minmax, redundant_binop_in_equality,
     fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors,
     combine_concat_vector, double_icmp_zero_and_or_combine, match_addos,
-    sext_trunc, zext_trunc, combine_shuffle_concat]>;
+    sext_trunc, zext_trunc, combine_shuffle_concat,
+    push_freeze_to_prevent_poison_propagation]>;
 
 // A combine group used to for prelegalizer combiners at -O0. The combines in
 // this group have been selected based on experiments to balance code size and
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 22eb4a3e0d7cb..3ed08b1528c9f 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -223,6 +223,64 @@ void CombinerHelper::applyCombineCopy(MachineInstr &MI) {
   replaceRegWith(MRI, DstReg, SrcReg);
 }
 
+bool CombinerHelper::matchFreezeOfSingleMaybePoisonOperand(
+    MachineInstr &MI, BuildFnTy &MatchInfo) {
+  // Ported from InstCombinerImpl::pushFreezeToPreventPoisonFromPropagating
+  Register DstOp = MI.getOperand(0).getReg();
+  Register OrigOp = MI.getOperand(1).getReg();
+
+  if (OrigOp.isPhysical() || !MRI.hasOneNonDBGUse(OrigOp))
+    return false;
+
+  MachineInstr *OrigDef = MRI.getUniqueVRegDef(OrigOp);
+  // Avoid trying to fold G_PHI, G_UNMERGE_VALUES, G_FREEZE (the latter is
+  // handled by idempotent_prop)
+  if (!OrigDef || OrigDef->isPHI() || isa<GUnmerge>(OrigDef) ||
+      isa<GFreeze>(OrigDef))
+    return false;
+
+  if (canCreateUndefOrPoison(OrigOp, MRI))
+    return false;
+
+  std::optional<MachineOperand> MaybePoisonOperand = std::nullopt;
+  for (MachineOperand &Operand : OrigDef->uses()) {
+    // Avoid working on non-register operands or physical registers.
+    if (!Operand.isReg() || Operand.getReg().isPhysical())
+      return false;
+
+    if (isGuaranteedNotToBeUndefOrPoison(Operand.getReg(), MRI))
+      continue;
+
+    if (!MaybePoisonOperand)
+      MaybePoisonOperand = Operand;
+    // We have more than one maybe-poison operand. Moving the freeze is unsafe.
+    else
+      return false;
+  }
+
+  // Eliminate freeze if all operands are guaranteed non-poison
+  if (!MaybePoisonOperand) {
+    MatchInfo = [=](MachineIRBuilder &B) { MRI.replaceRegWith(DstOp, OrigOp); };
+    return true;
+  }
+
+  if (!MaybePoisonOperand->isReg())
+    return false;
+
+  Register MaybePoisonOperandReg = MaybePoisonOperand->getReg();
+  LLT MaybePoisonOperandRegTy = MRI.getType(MaybePoisonOperandReg);
+
+  MatchInfo = [=](MachineIRBuilder &B) mutable {
+    auto Reg = MRI.createGenericVirtualRegister(MaybePoisonOperandRegTy);
+    B.setInsertPt(*OrigDef->getParent(), OrigDef->getIterator());
+    B.buildFreeze(Reg, MaybePoisonOperandReg);
+    replaceRegOpWith(
+        MRI, *OrigDef->findRegisterUseOperand(MaybePoisonOperandReg, TRI), Reg);
+    replaceRegWith(MRI, DstOp, OrigOp);
+  };
+  return true;
+}
+
 bool CombinerHelper::matchCombineConcatVectors(MachineInstr &MI,
                                                SmallVector<Register> &Ops) {
   assert(MI.getOpcode() == TargetOpcode::G_CONCAT_VECTORS &&
@@ -3060,6 +3118,7 @@ bool CombinerHelper::matchHoistLogicOpWithSameOpcodeHands(
   MachineInstr *RightHandInst = getDefIgnoringCopies(RHSReg, MRI);
   if (!LeftHandInst || !RightHandInst)
     return false;
+
   unsigned HandOpcode = LeftHandInst->getOpcode();
   if (HandOpcode != RightHandInst->getOpcode())
     return false;
diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index cd5dc0e01ed0e..0085074714d44 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -1749,6 +1749,8 @@ static bool canCreateUndefOrPoison(Register Reg, const MachineRegisterInfo &MRI,
   case TargetOpcode::G_FREEZE:
     return false;
   default:
+    if (isa<GCastOp>(RegDef) || isa<GBinOp>(RegDef))
+      return false;
     return true;
   }
 }
@@ -1762,13 +1764,26 @@ static bool isGuaranteedNotToBeUndefOrPoison(Register Reg,
 
   MachineInstr *RegDef = MRI.getVRegDef(Reg);
 
+  auto OpCheck = [&](MachineOperand &Operand) {
+    if (!Operand.isReg())
+      return true;
+
+    return isGuaranteedNotToBeUndefOrPoison(Operand.getReg(), MRI, Depth + 1,
+                                            Kind);
+  };
+
   switch (RegDef->getOpcode()) {
   case TargetOpcode::G_FREEZE:
     return true;
   case TargetOpcode::G_IMPLICIT_DEF:
     return !includesUndef(Kind);
   default:
-    return false;
+    GenericMachineInstr *Opr = dyn_cast<GBinOp>(RegDef);
+    if (!Opr)
+      Opr = dyn_cast<GCastOp>(RegDef);
+
+    return Opr && !::llvm::canCreateUndefOrPoison(Reg, MRI) &&
+           all_of(Opr->operands(), OpCheck);
   }
 }
 
diff --git a/llvm/lib/Target/AArch64/AArch64Combine.td b/llvm/lib/Target/AArch64/AArch64Combine.td
index 10cad6d192440..7229d4fe52261 100644
--- a/llvm/lib/Target/AArch64/AArch64Combine.td
+++ b/llvm/lib/Target/AArch64/AArch64Combine.td
@@ -295,5 +295,6 @@ def AArch64PostLegalizerCombiner
                         ptr_add_immed_chain, overlapping_and,
                         split_store_zero_128, undef_combines,
                         select_to_minmax, or_to_bsp, combine_concat_vector,
-                        commute_constant_to_rhs]> {
+                        commute_constant_to_rhs,
+                        push_freeze_to_prevent_poison_propagation]> {
 }
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir
index 353c1550d6974..074d4ecbd8785 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir
@@ -117,9 +117,9 @@ body:             |
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x2
     ; CHECK-NEXT: %c:_(s1) = G_TRUNC [[COPY]](s64)
-    ; CHECK-NEXT: %f:_(s1) = G_TRUNC [[COPY1]](s64)
-    ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(s1) = G_FREEZE %f
-    ; CHECK-NEXT: %sel:_(s1) = G_OR %c, [[FREEZE]]
+    ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(s64) = G_FREEZE [[COPY1]]
+    ; CHECK-NEXT: %f:_(s1) = G_TRUNC [[FREEZE]](s64)
+    ; CHECK-NEXT: %sel:_(s1) = G_OR %c, %f
     ; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %sel(s1)
     ; CHECK-NEXT: $w0 = COPY %ext(s32)
     %0:_(s64) = COPY $x0
@@ -144,9 +144,9 @@ body:             |
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x2
     ; CHECK-NEXT: %c:_(s1) = G_TRUNC [[COPY]](s64)
-    ; CHECK-NEXT: %f:_(s1) = G_TRUNC [[COPY1]](s64)
-    ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(s1) = G_FREEZE %f
-    ; CHECK-NEXT: %sel:_(s1) = G_OR %c, [[FREEZE]]
+    ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(s64) = G_FREEZE [[COPY1]]
+    ; CHECK-NEXT: %f:_(s1) = G_TRUNC [[FREEZE]](s64)
+    ; CHECK-NEXT: %sel:_(s1) = G_OR %c, %f
     ; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %sel(s1)
     ; CHECK-NEXT: $w0 = COPY %ext(s32)
     %0:_(s64) = COPY $x0
@@ -172,9 +172,9 @@ body:             |
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $d2
     ; CHECK-NEXT: %c:_(<2 x s1>) = G_TRUNC [[COPY]](<2 x s32>)
-    ; CHECK-NEXT: %f:_(<2 x s1>) = G_TRUNC [[COPY1]](<2 x s32>)
-    ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(<2 x s1>) = G_FREEZE %f
-    ; CHECK-NEXT: %sel:_(<2 x s1>) = G_OR %c, [[FREEZE]]
+    ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(<2 x s32>) = G_FREEZE [[COPY1]]
+    ; CHECK-NEXT: %f:_(<2 x s1>) = G_TRUNC [[FREEZE]](<2 x s32>)
+    ; CHECK-NEXT: %sel:_(<2 x s1>) = G_OR %c, %f
     ; CHECK-NEXT: %ext:_(<2 x s32>) = G_ANYEXT %sel(<2 x s1>)
     ; CHECK-NEXT: $d0 = COPY %ext(<2 x s32>)
     %0:_(<2 x s32>) = COPY $d0
@@ -201,9 +201,9 @@ body:             |
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1
     ; CHECK-NEXT: %c:_(s1) = G_TRUNC [[COPY]](s64)
-    ; CHECK-NEXT: %t:_(s1) = G_TRUNC [[COPY1]](s64)
-    ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(s1) = G_FREEZE %t
-    ; CHECK-NEXT: %sel:_(s1) = G_AND %c, [[FREEZE]]
+    ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(s64) = G_FREEZE [[COPY1]]
+    ; CHECK-NEXT: %t:_(s1) = G_TRUNC [[FREEZE]](s64)
+    ; CHECK-NEXT: %sel:_(s1) = G_AND %c, %t
     ; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %sel(s1)
     ; CHECK-NEXT: $w0 = COPY %ext(s32)
     %0:_(s64) = COPY $x0
@@ -229,9 +229,9 @@ body:             |
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1
     ; CHECK-NEXT: %c:_(s1) = G_TRUNC [[COPY]](s64)
-    ; CHECK-NEXT: %t:_(s1) = G_TRUNC [[COPY1]](s64)
-    ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(s1) = G_FREEZE %t
-    ; CHECK-NEXT: %sel:_(s1) = G_AND %c, [[FREEZE]]
+    ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(s64) = G_FREEZE [[COPY1]]
+    ; CHECK-NEXT: %t:_(s1) = G_TRUNC [[FREEZE]](s64)
+    ; CHECK-NEXT: %sel:_(s1) = G_AND %c, %t
     ; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %sel(s1)
     ; CHECK-NEXT: $w0 = COPY %ext(s32)
     %0:_(s64) = COPY $x0
@@ -257,11 +257,11 @@ body:             |
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1
     ; CHECK-NEXT: %c:_(s1) = G_TRUNC [[COPY]](s64)
-    ; CHECK-NEXT: %t:_(s1) = G_TRUNC [[COPY1]](s64)
+    ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(s64) = G_FREEZE [[COPY1]]
+    ; CHECK-NEXT: %t:_(s1) = G_TRUNC [[FREEZE]](s64)
     ; CHECK-NEXT: %one:_(s1) = G_CONSTANT i1 true
     ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR %c, %one
-    ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(s1) = G_FREEZE %t
-    ; CHECK-NEXT: %sel:_(s1) = G_OR [[XOR]], [[FREEZE]]
+    ; CHECK-NEXT: %sel:_(s1) = G_OR [[XOR]], %t
     ; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %sel(s1)
     ; CHECK-NEXT: $w0 = COPY %ext(s32)
     %0:_(s64) = COPY $x0
@@ -287,11 +287,11 @@ body:             |
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x2
     ; CHECK-NEXT: %c:_(s1) = G_TRUNC [[COPY]](s64)
-    ; CHECK-NEXT: %f:_(s1) = G_TRUNC [[COPY1]](s64)
+    ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(s64) = G_FREEZE [[COPY1]]
+    ; CHECK-NEXT: %f:_(s1) = G_TRUNC [[FREEZE]](s64)
     ; CHECK-NEXT: [[C:%[0-9]+]]:_(s1) = G_CONSTANT i1 true
     ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR %c, [[C]]
-    ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(s1) = G_FREEZE %f
-    ; CHECK-NEXT: %sel:_(s1) = G_AND [[XOR]], [[FREEZE]]
+    ; CHECK-NEXT: %sel:_(s1) = G_AND [[XOR]], %f
     ; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %sel(s1)
     ; CHECK-NEXT: $w0 = COPY %ext(s32)
     %0:_(s64) = COPY $x0
diff --git a/llvm/test/CodeGen/AArch64/pr58431.ll b/llvm/test/CodeGen/AArch64/pr58431.ll
index dcd97597ae409..e87d8f7874d62 100644
--- a/llvm/test/CodeGen/AArch64/pr58431.ll
+++ b/llvm/test/CodeGen/AArch64/pr58431.ll
@@ -4,8 +4,8 @@
 define i32 @f(i64 %0) {
 ; CHECK-LABEL: f:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    mov w8, #10
-; CHECK-NEXT:    mov w9, w0
+; CHECK-NEXT:    mov w8, #10 // =0xa
+; CHECK-NEXT:    and x9, x0, #0xffffffff
 ; CHECK-NEXT:    udiv x10, x9, x8
 ; CHECK-NEXT:    msub x0, x10, x8, x9
 ; CHECK-NEXT:    // kill: def $w0 killed $w0 killed $x0

>From f26133b875d28535344f49b69227700aa8281afc Mon Sep 17 00:00:00 2001
From: Dhruv Chawla <dhruvc at nvidia.com>
Date: Tue, 30 Apr 2024 20:32:39 +0530
Subject: [PATCH 2/9] Address reviewer comments

---
 .../include/llvm/CodeGen/GlobalISel/CombinerHelper.h |  3 ++-
 llvm/include/llvm/Target/GlobalISel/Combine.td       |  4 ++--
 llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp       | 12 ++++--------
 3 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 53eb31c12f349..2111e82e1a99d 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -869,7 +869,8 @@ class CombinerHelper {
   /// Combine insert vector element OOB.
   bool matchInsertVectorElementOOB(MachineInstr &MI, BuildFnTy &MatchInfo);
 
-  bool matchFreezeOfSingleMaybePoisonOperand(MachineInstr &MI, BuildFnTy &MatchInfo);
+  bool matchFreezeOfSingleMaybePoisonOperand(MachineInstr &MI,
+                                             BuildFnTy &MatchInfo);
 
 private:
   /// Checks for legality of an indexed variant of \p LdSt.
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 29f8cc4da5f95..3035201d4df18 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -224,8 +224,8 @@ def idempotent_prop : GICombineRule<
 // when Op0 is not guaranteed non-poison
 def push_freeze_to_prevent_poison_propagation : GICombineRule<
   (defs root:$root, build_fn_matchinfo:$matchinfo),
-  (match (wip_match_opcode G_FREEZE):$root,
-         [{ return Helper.matchFreezeOfSingleMaybePoisonOperand(*${root}, ${matchinfo}); }]),
+  (match (G_FREEZE $dst, $src):$root,
+         [{ return !isGuaranteedNotToBePoison(${src}.getReg(), MRI) && Helper.matchFreezeOfSingleMaybePoisonOperand(*${root}, ${matchinfo}); }]),
   (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
 
 def extending_loads : GICombineRule<
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 3ed08b1528c9f..bf249c3dc1a75 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -242,10 +242,10 @@ bool CombinerHelper::matchFreezeOfSingleMaybePoisonOperand(
   if (canCreateUndefOrPoison(OrigOp, MRI))
     return false;
 
-  std::optional<MachineOperand> MaybePoisonOperand = std::nullopt;
+  std::optional<MachineOperand> MaybePoisonOperand;
   for (MachineOperand &Operand : OrigDef->uses()) {
-    // Avoid working on non-register operands or physical registers.
-    if (!Operand.isReg() || Operand.getReg().isPhysical())
+    // Avoid working on non-register operands.
+    if (!Operand.isReg())
       return false;
 
     if (isGuaranteedNotToBeUndefOrPoison(Operand.getReg(), MRI))
@@ -258,15 +258,12 @@ bool CombinerHelper::matchFreezeOfSingleMaybePoisonOperand(
       return false;
   }
 
-  // Eliminate freeze if all operands are guaranteed non-poison
+  // Eliminate freeze if all operands are guaranteed non-poison.
   if (!MaybePoisonOperand) {
     MatchInfo = [=](MachineIRBuilder &B) { MRI.replaceRegWith(DstOp, OrigOp); };
     return true;
   }
 
-  if (!MaybePoisonOperand->isReg())
-    return false;
-
   Register MaybePoisonOperandReg = MaybePoisonOperand->getReg();
   LLT MaybePoisonOperandRegTy = MRI.getType(MaybePoisonOperandReg);
 
@@ -3118,7 +3115,6 @@ bool CombinerHelper::matchHoistLogicOpWithSameOpcodeHands(
   MachineInstr *RightHandInst = getDefIgnoringCopies(RHSReg, MRI);
   if (!LeftHandInst || !RightHandInst)
     return false;
-
   unsigned HandOpcode = LeftHandInst->getOpcode();
   if (HandOpcode != RightHandInst->getOpcode())
     return false;

>From 41464f045ca660f5ea5bc7f2edad6f50d951a9b3 Mon Sep 17 00:00:00 2001
From: Dhruv Chawla <dhruvc at nvidia.com>
Date: Wed, 1 May 2024 08:57:32 +0530
Subject: [PATCH 3/9] Add support for checking and dropping poison-generating
 flags

---
 .../CodeGen/GlobalISel/GenericMachineInstrs.h | 77 +++++++++++++++++++
 .../lib/CodeGen/GlobalISel/CombinerHelper.cpp |  7 +-
 llvm/lib/CodeGen/GlobalISel/Utils.cpp         |  9 +++
 3 files changed, 91 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
index 2a3145b635e6c..ef4c307d6c4b1 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
@@ -34,6 +34,83 @@ class GenericMachineInstr : public MachineInstr {
   static bool classof(const MachineInstr *MI) {
     return isPreISelGenericOpcode(MI->getOpcode());
   }
+
+  bool hasPoisonGeneratingFlags() const {
+    switch (getOpcode()) {
+    case TargetOpcode::G_ADD:
+    case TargetOpcode::G_SUB:
+    case TargetOpcode::G_MUL:
+    case TargetOpcode::G_SHL:
+    case TargetOpcode::G_TRUNC:
+      return getFlag(NoUWrap) || getFlag(NoSWrap);
+
+    case TargetOpcode::G_UDIV:
+    case TargetOpcode::G_SDIV:
+    case TargetOpcode::G_ASHR:
+    case TargetOpcode::G_LSHR:
+      return getFlag(IsExact);
+
+    case TargetOpcode::G_OR:
+      return getFlag(Disjoint);
+
+    case TargetOpcode::G_UITOFP:
+    case TargetOpcode::G_ZEXT:
+      return getFlag(NonNeg);
+
+    case TargetOpcode::G_FNEG:
+    case TargetOpcode::G_FADD:
+    case TargetOpcode::G_FSUB:
+    case TargetOpcode::G_FMUL:
+    case TargetOpcode::G_FDIV:
+    case TargetOpcode::G_FREM:
+    case TargetOpcode::G_FCMP:
+      return getFlag(FmNoNans) || getFlag(FmNoInfs);
+
+    default:
+      return false;
+    }
+  }
+
+  void dropPoisonGeneratingFlags() {
+    switch (getOpcode()) {
+    case TargetOpcode::G_ADD:
+    case TargetOpcode::G_SUB:
+    case TargetOpcode::G_MUL:
+    case TargetOpcode::G_SHL:
+    case TargetOpcode::G_TRUNC:
+      clearFlag(NoUWrap);
+      clearFlag(NoSWrap);
+      break;
+
+    case TargetOpcode::G_UDIV:
+    case TargetOpcode::G_SDIV:
+    case TargetOpcode::G_ASHR:
+    case TargetOpcode::G_LSHR:
+      clearFlag(IsExact);
+      break;
+
+    case TargetOpcode::G_OR:
+      clearFlag(Disjoint);
+      break;
+
+    case TargetOpcode::G_UITOFP:
+    case TargetOpcode::G_ZEXT:
+      clearFlag(NonNeg);
+      break;
+
+    case TargetOpcode::G_FNEG:
+    case TargetOpcode::G_FADD:
+    case TargetOpcode::G_FSUB:
+    case TargetOpcode::G_FMUL:
+    case TargetOpcode::G_FDIV:
+    case TargetOpcode::G_FREM:
+    case TargetOpcode::G_FCMP:
+      clearFlag(FmNoNans);
+      clearFlag(FmNoInfs);
+      break;
+    }
+    assert(!hasPoisonGeneratingFlags());
+  }
 };
 
 /// Provides common memory operand functionality.
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index bf249c3dc1a75..ecdf3ff27f574 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -234,12 +234,13 @@ bool CombinerHelper::matchFreezeOfSingleMaybePoisonOperand(
 
   MachineInstr *OrigDef = MRI.getUniqueVRegDef(OrigOp);
   // Avoid trying to fold G_PHI, G_UNMERGE_VALUES, G_FREEZE (the latter is
-  // handled by idempotent_prop)
+  // handled by idempotent_prop).
   if (!OrigDef || OrigDef->isPHI() || isa<GUnmerge>(OrigDef) ||
       isa<GFreeze>(OrigDef))
     return false;
 
-  if (canCreateUndefOrPoison(OrigOp, MRI))
+  if (canCreateUndefOrPoison(OrigOp, MRI,
+                             /*ConsiderFlagsAndMetadata*/ false))
     return false;
 
   std::optional<MachineOperand> MaybePoisonOperand;
@@ -258,6 +259,8 @@ bool CombinerHelper::matchFreezeOfSingleMaybePoisonOperand(
       return false;
   }
 
+  cast<GenericMachineInstr>(OrigDef)->dropPoisonGeneratingFlags();
+
   // Eliminate freeze if all operands are guaranteed non-poison.
   if (!MaybePoisonOperand) {
     MatchInfo = [=](MachineIRBuilder &B) { MRI.replaceRegWith(DstOp, OrigOp); };
diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index 0085074714d44..7c95100c78879 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -1745,6 +1745,15 @@ static bool canCreateUndefOrPoison(Register Reg, const MachineRegisterInfo &MRI,
                                    UndefPoisonKind Kind) {
   MachineInstr *RegDef = MRI.getVRegDef(Reg);
 
+  if (auto *GMI = dyn_cast<GenericMachineInstr>(RegDef)) {
+    if (ConsiderFlagsAndMetadata && includesPoison(Kind) &&
+        GMI->hasPoisonGeneratingFlags())
+      return true;
+  }
+  // Conservatively return true.
+  else
+    return true;
+
   switch (RegDef->getOpcode()) {
   case TargetOpcode::G_FREEZE:
     return false;

>From 1ae3bbb1d613f40bff93d16b1de90e6fcd4700f0 Mon Sep 17 00:00:00 2001
From: Dhruv Chawla <dhruvc at nvidia.com>
Date: Mon, 6 May 2024 10:03:48 +0530
Subject: [PATCH 4/9] Refactor flag checking/dropping code

---
 .../CodeGen/GlobalISel/GenericMachineInstrs.h | 80 +++----------------
 1 file changed, 10 insertions(+), 70 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
index ef4c307d6c4b1..4552b8a8d59d3 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
@@ -36,79 +36,19 @@ class GenericMachineInstr : public MachineInstr {
   }
 
   bool hasPoisonGeneratingFlags() const {
-    switch (getOpcode()) {
-    case TargetOpcode::G_ADD:
-    case TargetOpcode::G_SUB:
-    case TargetOpcode::G_MUL:
-    case TargetOpcode::G_SHL:
-    case TargetOpcode::G_TRUNC:
-      return getFlag(NoUWrap) || getFlag(NoSWrap);
-
-    case TargetOpcode::G_UDIV:
-    case TargetOpcode::G_SDIV:
-    case TargetOpcode::G_ASHR:
-    case TargetOpcode::G_LSHR:
-      return getFlag(IsExact);
-
-    case TargetOpcode::G_OR:
-      return getFlag(Disjoint);
-
-    case TargetOpcode::G_UITOFP:
-    case TargetOpcode::G_ZEXT:
-      return getFlag(NonNeg);
-
-    case TargetOpcode::G_FNEG:
-    case TargetOpcode::G_FADD:
-    case TargetOpcode::G_FSUB:
-    case TargetOpcode::G_FMUL:
-    case TargetOpcode::G_FDIV:
-    case TargetOpcode::G_FREM:
-    case TargetOpcode::G_FCMP:
-      return getFlag(FmNoNans) || getFlag(FmNoInfs);
-
-    default:
-      return false;
-    }
+    return getFlag(NoUWrap) || getFlag(NoSWrap) || getFlag(IsExact) ||
+           getFlag(Disjoint) || getFlag(NonNeg) || getFlag(FmNoNans) ||
+           getFlag(FmNoInfs);
   }
 
   void dropPoisonGeneratingFlags() {
-    switch (getOpcode()) {
-    case TargetOpcode::G_ADD:
-    case TargetOpcode::G_SUB:
-    case TargetOpcode::G_MUL:
-    case TargetOpcode::G_SHL:
-    case TargetOpcode::G_TRUNC:
-      clearFlag(NoUWrap);
-      clearFlag(NoSWrap);
-      break;
-
-    case TargetOpcode::G_UDIV:
-    case TargetOpcode::G_SDIV:
-    case TargetOpcode::G_ASHR:
-    case TargetOpcode::G_LSHR:
-      clearFlag(IsExact);
-      break;
-
-    case TargetOpcode::G_OR:
-      clearFlag(Disjoint);
-      break;
-
-    case TargetOpcode::G_UITOFP:
-    case TargetOpcode::G_ZEXT:
-      clearFlag(NonNeg);
-      break;
-
-    case TargetOpcode::G_FNEG:
-    case TargetOpcode::G_FADD:
-    case TargetOpcode::G_FSUB:
-    case TargetOpcode::G_FMUL:
-    case TargetOpcode::G_FDIV:
-    case TargetOpcode::G_FREM:
-    case TargetOpcode::G_FCMP:
-      clearFlag(FmNoNans);
-      clearFlag(FmNoInfs);
-      break;
-    }
+    clearFlag(NoUWrap);
+    clearFlag(NoSWrap);
+    clearFlag(IsExact);
+    clearFlag(Disjoint);
+    clearFlag(NonNeg);
+    clearFlag(FmNoNans);
+    clearFlag(FmNoInfs);
     assert(!hasPoisonGeneratingFlags());
   }
 };

>From ecfbbe3dc53c8bd52d8b25ee6d1adb48ac918a68 Mon Sep 17 00:00:00 2001
From: Dhruv Chawla <dhruvc at nvidia.com>
Date: Tue, 14 May 2024 10:44:51 +0530
Subject: [PATCH 5/9] Rebase and address reviewer comments

---
 .../CodeGen/GlobalISel/GenericMachineInstrs.h |  5 ++---
 .../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 22 +++++++++----------
 llvm/lib/CodeGen/GlobalISel/Utils.cpp         | 10 ++++-----
 3 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
index 4552b8a8d59d3..f3c729900f13d 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
@@ -36,9 +36,8 @@ class GenericMachineInstr : public MachineInstr {
   }
 
   bool hasPoisonGeneratingFlags() const {
-    return getFlag(NoUWrap) || getFlag(NoSWrap) || getFlag(IsExact) ||
-           getFlag(Disjoint) || getFlag(NonNeg) || getFlag(FmNoNans) ||
-           getFlag(FmNoInfs);
+    return getFlags() & (NoUWrap | NoSWrap | IsExact | Disjoint | NonNeg |
+                         FmNoNans | FmNoInfs);
   }
 
   void dropPoisonGeneratingFlags() {
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index ecdf3ff27f574..ede2bf88434fa 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -229,18 +229,16 @@ bool CombinerHelper::matchFreezeOfSingleMaybePoisonOperand(
   Register DstOp = MI.getOperand(0).getReg();
   Register OrigOp = MI.getOperand(1).getReg();
 
-  if (OrigOp.isPhysical() || !MRI.hasOneNonDBGUse(OrigOp))
+  if (!MRI.hasOneNonDBGUse(OrigOp))
     return false;
 
   MachineInstr *OrigDef = MRI.getUniqueVRegDef(OrigOp);
-  // Avoid trying to fold G_PHI, G_UNMERGE_VALUES, G_FREEZE (the latter is
-  // handled by idempotent_prop).
-  if (!OrigDef || OrigDef->isPHI() || isa<GUnmerge>(OrigDef) ||
-      isa<GFreeze>(OrigDef))
+  // Avoid trying to fold G_PHI and G_UNMERGE_VALUES.
+  if (OrigDef->isPHI() || isa<GUnmerge>(OrigDef))
     return false;
 
   if (canCreateUndefOrPoison(OrigOp, MRI,
-                             /*ConsiderFlagsAndMetadata*/ false))
+                             /*ConsiderFlagsAndMetadata=*/false))
     return false;
 
   std::optional<MachineOperand> MaybePoisonOperand;
@@ -254,9 +252,11 @@ bool CombinerHelper::matchFreezeOfSingleMaybePoisonOperand(
 
     if (!MaybePoisonOperand)
       MaybePoisonOperand = Operand;
-    // We have more than one maybe-poison operand. Moving the freeze is unsafe.
-    else
+    else {
+      // We have more than one maybe-poison operand. Moving the freeze is
+      // unsafe.
       return false;
+    }
   }
 
   cast<GenericMachineInstr>(OrigDef)->dropPoisonGeneratingFlags();
@@ -271,11 +271,11 @@ bool CombinerHelper::matchFreezeOfSingleMaybePoisonOperand(
   LLT MaybePoisonOperandRegTy = MRI.getType(MaybePoisonOperandReg);
 
   MatchInfo = [=](MachineIRBuilder &B) mutable {
-    auto Reg = MRI.createGenericVirtualRegister(MaybePoisonOperandRegTy);
     B.setInsertPt(*OrigDef->getParent(), OrigDef->getIterator());
-    B.buildFreeze(Reg, MaybePoisonOperandReg);
+    auto Freeze = B.buildFreeze(MaybePoisonOperandRegTy, MaybePoisonOperandReg);
     replaceRegOpWith(
-        MRI, *OrigDef->findRegisterUseOperand(MaybePoisonOperandReg, TRI), Reg);
+        MRI, *OrigDef->findRegisterUseOperand(MaybePoisonOperandReg, TRI),
+        Freeze.getReg(0));
     replaceRegWith(MRI, DstOp, OrigOp);
   };
   return true;
diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index 7c95100c78879..741363e1d7733 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -1749,18 +1749,16 @@ static bool canCreateUndefOrPoison(Register Reg, const MachineRegisterInfo &MRI,
     if (ConsiderFlagsAndMetadata && includesPoison(Kind) &&
         GMI->hasPoisonGeneratingFlags())
       return true;
-  }
-  // Conservatively return true.
-  else
+  } else {
+    // Conservatively return true.
     return true;
+  }
 
   switch (RegDef->getOpcode()) {
   case TargetOpcode::G_FREEZE:
     return false;
   default:
-    if (isa<GCastOp>(RegDef) || isa<GBinOp>(RegDef))
-      return false;
-    return true;
+    return !isa<GCastOp>(RegDef) && !isa<GBinOp>(RegDef);
   }
 }
 

>From 4e17f8ed9210df7745834e42ebd5e70fee966c28 Mon Sep 17 00:00:00 2001
From: Dhruv Chawla <dhruvc at nvidia.com>
Date: Thu, 16 May 2024 17:21:11 +0530
Subject: [PATCH 6/9] Address reviewer comments

---
 llvm/include/llvm/Target/GlobalISel/Combine.td |  4 ++--
 llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 12 +++++++++---
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 3035201d4df18..34698f195615b 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -222,7 +222,7 @@ def idempotent_prop : GICombineRule<
 
 // Convert freeze(Op(Op0, NonPoisonOps...)) to Op(freeze(Op0), NonPoisonOps...)
 // when Op0 is not guaranteed non-poison
-def push_freeze_to_prevent_poison_propagation : GICombineRule<
+def push_freeze_to_prevent_poison_from_propagating : GICombineRule<
   (defs root:$root, build_fn_matchinfo:$matchinfo),
   (match (G_FREEZE $dst, $src):$root,
          [{ return !isGuaranteedNotToBePoison(${src}.getReg(), MRI) && Helper.matchFreezeOfSingleMaybePoisonOperand(*${root}, ${matchinfo}); }]),
@@ -1721,7 +1721,7 @@ def all_combines : GICombineGroup<[trivial_combines, vector_ops_combines,
     fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors,
     combine_concat_vector, double_icmp_zero_and_or_combine, match_addos,
     sext_trunc, zext_trunc, combine_shuffle_concat,
-    push_freeze_to_prevent_poison_propagation]>;
+    push_freeze_to_prevent_poison_from_propagating]>;
 
 // A combine group used to for prelegalizer combiners at -O0. The combines in
 // this group have been selected based on experiments to balance code size and
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index ede2bf88434fa..4cc602b5c8709 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -225,7 +225,7 @@ void CombinerHelper::applyCombineCopy(MachineInstr &MI) {
 
 bool CombinerHelper::matchFreezeOfSingleMaybePoisonOperand(
     MachineInstr &MI, BuildFnTy &MatchInfo) {
-  // Ported from InstCombinerImpl::pushFreezeToPreventPoisonFromPropagating
+  // Ported from InstCombinerImpl::pushFreezeToPreventPoisonFromPropagating.
   Register DstOp = MI.getOperand(0).getReg();
   Register OrigOp = MI.getOperand(1).getReg();
 
@@ -233,7 +233,14 @@ bool CombinerHelper::matchFreezeOfSingleMaybePoisonOperand(
     return false;
 
   MachineInstr *OrigDef = MRI.getUniqueVRegDef(OrigOp);
-  // Avoid trying to fold G_PHI and G_UNMERGE_VALUES.
+  // Even if only a single operand of the PHI is not guaranteed non-poison,
+  // moving freeze() backwards across a PHI can cause optimization issues for
+  // other users of that operand.
+  //
+  // Moving freeze() from one of the output registers of a G_UNMERGE_VALUES to
+  // the source register is unprofitable because it makes the freeze() more
+  // strict than is necessary (it would affect the whole register instead of
+  // just the subreg being frozen).
   if (OrigDef->isPHI() || isa<GUnmerge>(OrigDef))
     return false;
 
@@ -243,7 +250,6 @@ bool CombinerHelper::matchFreezeOfSingleMaybePoisonOperand(
 
   std::optional<MachineOperand> MaybePoisonOperand;
   for (MachineOperand &Operand : OrigDef->uses()) {
-    // Avoid working on non-register operands.
     if (!Operand.isReg())
       return false;
 

>From fffbc9fa2a223c63b204f44e41993c13897e73d9 Mon Sep 17 00:00:00 2001
From: Dhruv Chawla <dhruvc at nvidia.com>
Date: Fri, 17 May 2024 07:54:55 +0530
Subject: [PATCH 7/9] Fix silly mistake

---
 llvm/lib/Target/AArch64/AArch64Combine.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AArch64/AArch64Combine.td b/llvm/lib/Target/AArch64/AArch64Combine.td
index 7229d4fe52261..1c7f6b870d390 100644
--- a/llvm/lib/Target/AArch64/AArch64Combine.td
+++ b/llvm/lib/Target/AArch64/AArch64Combine.td
@@ -296,5 +296,5 @@ def AArch64PostLegalizerCombiner
                         split_store_zero_128, undef_combines,
                         select_to_minmax, or_to_bsp, combine_concat_vector,
                         commute_constant_to_rhs,
-                        push_freeze_to_prevent_poison_propagation]> {
+                        push_freeze_to_prevent_poison_from_propagating]> {
 }

>From 6fcc9f66581be3d4f48a86c6a8f267f3cd66ca06 Mon Sep 17 00:00:00 2001
From: Dhruv Chawla <dhruvc at nvidia.com>
Date: Mon, 20 May 2024 16:44:08 +0530
Subject: [PATCH 8/9] Rebase and address reviewer comments

---
 llvm/lib/CodeGen/GlobalISel/Utils.cpp | 26 +++++++++++---------------
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index 741363e1d7733..f455482e02943 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -1771,26 +1771,22 @@ static bool isGuaranteedNotToBeUndefOrPoison(Register Reg,
 
   MachineInstr *RegDef = MRI.getVRegDef(Reg);
 
-  auto OpCheck = [&](MachineOperand &Operand) {
-    if (!Operand.isReg())
-      return true;
-
-    return isGuaranteedNotToBeUndefOrPoison(Operand.getReg(), MRI, Depth + 1,
-                                            Kind);
-  };
-
   switch (RegDef->getOpcode()) {
   case TargetOpcode::G_FREEZE:
     return true;
   case TargetOpcode::G_IMPLICIT_DEF:
     return !includesUndef(Kind);
-  default:
-    GenericMachineInstr *Opr = dyn_cast<GBinOp>(RegDef);
-    if (!Opr)
-      Opr = dyn_cast<GCastOp>(RegDef);
-
-    return Opr && !::llvm::canCreateUndefOrPoison(Reg, MRI) &&
-           all_of(Opr->operands(), OpCheck);
+  default: {
+    auto MOCheck = [&](const MachineOperand &MO) {
+      if (!MO.isReg())
+        return true;
+      return ::isGuaranteedNotToBeUndefOrPoison(MO.getReg(), MRI, Depth + 1,
+                                                Kind);
+    };
+    return !::canCreateUndefOrPoison(Reg, MRI,
+                                     /*ConsiderFlagsAndMetadata=*/true, Kind) &&
+           all_of(RegDef->uses(), MOCheck);
+  }
   }
 }
 

>From 4291abda4ba74e45fe5ffdaf3f23fca31763abe5 Mon Sep 17 00:00:00 2001
From: Dhruv Chawla <dhruvc at nvidia.com>
Date: Tue, 21 May 2024 15:08:04 +0530
Subject: [PATCH 9/9] Create clearFlags()

---
 .../llvm/CodeGen/GlobalISel/GenericMachineInstrs.h       | 9 ++-------
 llvm/include/llvm/CodeGen/MachineInstr.h                 | 6 ++++++
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
index f3c729900f13d..2b3efc3b609f0 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
@@ -41,13 +41,8 @@ class GenericMachineInstr : public MachineInstr {
   }
 
   void dropPoisonGeneratingFlags() {
-    clearFlag(NoUWrap);
-    clearFlag(NoSWrap);
-    clearFlag(IsExact);
-    clearFlag(Disjoint);
-    clearFlag(NonNeg);
-    clearFlag(FmNoNans);
-    clearFlag(FmNoInfs);
+    clearFlags(NoUWrap | NoSWrap | IsExact | Disjoint | NonNeg | FmNoNans |
+               FmNoInfs);
     assert(!hasPoisonGeneratingFlags());
   }
 };
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index 2b0c5d166d88b..db48a0ae55145 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -416,6 +416,12 @@ class MachineInstr
     Flags &= ~((uint32_t)Flag);
   }
 
+  void clearFlags(unsigned flags) {
+    assert(isUInt<LLVM_MI_FLAGS_BITS>(flags) &&
+           "flags to be cleared are out of range for the Flags field");
+    Flags &= ~flags;
+  }
+
   /// Return true if MI is in a bundle (but not the first MI in a bundle).
   ///
   /// A bundle looks like this before it's finalized:



More information about the llvm-commits mailing list