================
@@ -1578,11 +1581,92 @@ bool AMDGPUCodeGenPrepareImpl::visitLoadInst(LoadInst 
&I) {
   return false;
 }
 
+// select (X == 0 || Y == 0), +0.0, (X * Y) -> fmul_legacy(X, Y)
+bool AMDGPUCodeGenPrepareImpl::foldSelectToFMulLegacy(SelectInst &I) const {
+  if (!I.getType()->isFloatTy())
+    return false;
+
+  // Inverted form: select (X != 0 && Y != 0), X * Y, +0.0.
+  bool Inverted = match(I.getFalseValue(), m_PosZeroFP());
+  if (!Inverted && !match(I.getTrueValue(), m_PosZeroFP()))
+    return false;
+
+  Value *X, *Y;
+  if (!match(Inverted ? I.getTrueValue() : I.getFalseValue(),
+             m_OneUse(m_FMul(m_Value(X), m_Value(Y)))))
+    return false;
+
+  // Collect the values compared against zero in the condition.
+  SmallVector<Value *, 4> CondWorklist = {I.getCondition()};
+  SmallVector<Value *, 4> CmpSrcs;
+  SmallPtrSet<Value *, 8> VisitedConds;
+  while (!CondWorklist.empty()) {
+    Value *Cond = CondWorklist.pop_back_val();
+    if (!VisitedConds.insert(Cond).second)
+      continue;
+
+    Value *LHS, *RHS, *Src;
+    if (Inverted ? match(Cond, m_And(m_Value(LHS), m_Value(RHS)))
+                 : match(Cond, m_Or(m_Value(LHS), m_Value(RHS)))) {
+      CondWorklist.append({LHS, RHS});
+      continue;
+    }
+
+    if (!match(Cond, m_SpecificFCmp(Inverted ? FCmpInst::FCMP_UNE
+                                             : FCmpInst::FCMP_OEQ,
+                                    m_Value(Src), m_AnyZeroFP())))
+      return false;
+    CmpSrcs.push_back(Src);
+  }
+
+  SmallVector<Value *, 4> Roots[2] = {std::move(CmpSrcs), {X, Y}};
+  SmallPtrSet<Value *, 4> Leaves[2];
+  for (auto [Worklist, Found] : zip(Roots, Leaves)) {
+    SmallPtrSet<Value *, 8> Visited;
+
+    while (!Worklist.empty()) {
+      Value *Cur = Worklist.pop_back_val();
+      if (!Visited.insert(Cur).second)
+        continue;
+
+      // Peeling a nnan/ninf op could expose poison that the select hides.
+      auto *FPOp = dyn_cast<FPMathOperator>(Cur);
+      if (FPOp && (FPOp->hasNoNaNs() || FPOp->hasNoInfs())) {
+        Found.insert(Cur);
+        continue;
+      }
+
+      Value *Src;
+      // m_UnOp, not m_FNeg: fsub -0.0, X may flush a denormal result to zero.
+      if (match(Cur, m_CombineOr(m_UnOp(m_Value(Src)), m_FAbs(m_Value(Src))))) 
{
+        Worklist.push_back(Src);
+        continue;
+      }
+
+      Found.insert(Cur);
+    }
+  }
+
+  if (Leaves[0] != Leaves[1])
+    return false;
+
+  IRBuilder<> Builder(&I);
+  Value *LegacyMul =
+      Builder.CreateIntrinsic(Intrinsic::amdgcn_fmul_legacy, {X, Y});
----------------
arsenm wrote:

Losing flags 

https://github.com/llvm/llvm-project/pull/229357
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to