[InstCombine] Sink sub into hands of select if one hand becomes zero (PR44426)

This decreases use count of %Op1, makes one hand of select to be 0,
and possibly exposes further folding potential.

Name: sub (select %Cond, %Op1, %FalseVal), %Op1 -> select %Cond, 0, (sub %FalseVal, %Op1)
  %Op1 = %TrueVal
  %o = select i1 %Cond, i8 %Op1, i8 %FalseVal
  %r = sub i8 %o, %Op1
=>
  %n = sub i8 %FalseVal, %Op1
  %r = select i1 %Cond, i8 0, i8 %n

Name: sub (select %Cond, %TrueVal, %Op1), %Op1 -> select %Cond, (sub %TrueVal, %Op1), 0
  %Op1 = %FalseVal
  %o = select i1 %Cond, i8 %TrueVal, i8 %Op1
  %r = sub i8 %o, %Op1
=>
  %n = sub i8 %TrueVal, %Op1
  %r = select i1 %Cond, i8 %n, i8 0

https://rise4fun.com/Alive/avL

https://bugs.llvm.org/show_bug.cgi?id=44426
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 9676c6a..05d13ae 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -1898,6 +1898,33 @@
     }
   }
 
+  {
+    // If we are subtracting from select with one hand matching the value
+    // we are subtracting, sink subtraction into hands of select:
+    //   sub (select %Cond, %TrueVal, %FalseVal), %Op1
+    //     ->
+    //   select %Cond, (sub %TrueVal, %Op1), (sub %FalseVal, %Op1)
+    // This will result in select between new subtraction and 0.
+    Value *Cond, *TrueVal, *FalseVal;
+    if (match(Op0, m_OneUse(m_Select(m_Value(Cond), m_Value(TrueVal),
+                                     m_Value(FalseVal)))) &&
+        (Op1 == TrueVal || Op1 == FalseVal)) {
+      // While it is really tempting to just create two subtractions and let
+      // InstCombine fold one of those to 0, it isn't possible to do so
+      // because of worklist visitation order. So ugly it is.
+      bool SubtractingTrueVal = Op1 == TrueVal;
+      Value *NewSub =
+          Builder.CreateSub(SubtractingTrueVal ? FalseVal : TrueVal, Op1);
+      Constant *Zero = Constant::getNullValue(I.getType());
+      SelectInst *NewSel =
+          SelectInst::Create(Cond, SubtractingTrueVal ? Zero : NewSub,
+                             SubtractingTrueVal ? NewSub : Zero);
+      // Preserve prof metadata if any.
+      NewSel->copyMetadata(cast<Instruction>(*Op0));
+      return NewSel;
+    }
+  }
+
   if (Op1->hasOneUse()) {
     Value *X = nullptr, *Y = nullptr, *Z = nullptr;
     Constant *C = nullptr;