[llvm] [InstCombine] Factorise Add and Min/Max using Distributivity (PR #101717)

Marius Kamp via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 17 06:30:30 PDT 2024


================
@@ -1505,6 +1505,80 @@ foldMinimumOverTrailingOrLeadingZeroCount(Value *I0, Value *I1,
       ConstantInt::getTrue(ZeroUndef->getType()));
 }
 
+/// Return whether "X LOp (Y ROp Z)" is always equal to
+/// "(X LOp Y) ROp (X LOp Z)".
+static bool foldIntrinsicUsingDistributiveLaws(Instruction::BinaryOps LOp,
+                                               bool hasNUW, bool hasNSW,
+                                               Intrinsic::ID ROp) {
+  switch (ROp) {
+  case Intrinsic::umax:
+    return hasNUW && LOp == Instruction::Add;
+  case Intrinsic::umin:
+    return hasNUW && LOp == Instruction::Add;
----------------
mskamp wrote:

I think we can combine these cases since there are no functions that distribute over `umax` but not `umin` (or vice versa).
```
  case Intrinsic::umax:
  case Intrinsic::umin:
    return hasNUW && LOp == Instruction::Add;
```

Proof sketch: Let f be an arbitrary binary function and x, y, z be arbitrary bit vectors. Suppose that `(f u (umax v w)) = (umax (f u v) (f u w))` for all u, v, w. Observe that [`(umin u v) = (xor u v (umax u v))`](https://alive2.llvm.org/ce/z/cv9kaZ) for all u, v. Then `(umin (f x y) (f x z)) = (xor (f x y) (f x z) (umax (f x y) (f x z))) = (xor (f x y) (f x z) (f x (umax y z)))`. The case `(f x y) = (f x z)` is trivial, hence suppose they are not equal. Then `(f x (umax y z))` is equal to either `(f x y)` or `(f x z)`, leaving the other as the result of the `xor`, which equals `(f x (umin y z))`, as required.

(Similar for `smin`/`smax`.)

https://github.com/llvm/llvm-project/pull/101717


More information about the llvm-commits mailing list