[PATCH] D58881: [Transform] Improve fold of sadd.with.overflow

Nikita Popov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 3 01:47:20 PST 2019


nikic added inline comments.


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp:1825
+  if (OptimizeOverflowCheck(OCF, II->getArgOperand(0), II->getArgOperand(1),
+                            *II, OperationResult, OverflowResult)) {
+    return CreateOverflowTuple(II, OperationResult, OverflowResult);
----------------
nit: Unnecessary braces.


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp:2046
+    //
+    // FIXME: Add the last case.
+    Value *X = nullptr;
----------------
dlrobertson wrote:
> I was not entirely sure how to solve the last case. `sadd.with.overflow` returns an aggregate, while `add nsw` does not. I was not sure how to construct the aggregate, so I did not address the last case in my first attempt.
You can construct the aggregate with the `CreateOverflowTuple` helper, with overflow set to a false constant.

It's probably better to leave it out in this patch though, as this is quite a different optimization. Generally I'd drop all the sign/range checks here, as the fold is valid in either case -- there's just an even better one possible that's not implemented yet.


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp:2049
+    ConstantInt *RHS = nullptr;
+    ConstantInt *LHS = nullptr;
+    if (match(II->getArgOperand(0), m_NSWAdd(m_Value(X), m_ConstantInt(LHS))) &&
----------------
nit: The variables used in the matchers don't need to be initialized, and it's usually not done.


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp:2051
+    if (match(II->getArgOperand(0), m_NSWAdd(m_Value(X), m_ConstantInt(LHS))) &&
+        match(II->getArgOperand(1), m_ConstantInt(RHS))) {
+      APInt LHSValue = LHS->getValue();
----------------
It is better to use an `m_APInt` matcher for these, because it will also work with (splat) vector constants (and you're working on APInts below anyway).


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp:2056
+          RHSValue.abs().sgt(LHSValue.abs())) {
+        Constant *NewC = ConstantExpr::getAdd(LHS, RHS);
+        return replaceInstUsesWith(
----------------
Consider something like `%y = add nsw i8 %x, 127; sadd.with.overflow(%y, 127)`. The constants have same sign and you will transform this to `sadd.with.overflow(%x, 127+127)`, where `127+127 = -2`.

This transform can't be applied if the result of the addition overflows. You can use `sadd_ov` on APInt to check for that.


================
Comment at: llvm/test/Transforms/InstCombine/call-add-with-overflow.ll:1
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
----------------
To make future diffs easier, it's preferred to automatically generate checks using the `utils/update_test_checks.py` script.


================
Comment at: llvm/test/Transforms/InstCombine/call-add-with-overflow.ll:22
+  ret { i32, i1 } %3
+}
----------------
As we recently added vector support for these intrinsics, we should also have some vector tests. Good cases to cover are:

 * Splat constant `<2 x i32> <i32 42, i32 42>` (will work out of the box once you switch to m_APInt)
 * Splat constant with undef `<2 x i32> <i32 42, i32 undef>` (will also work out of the box)
 * Non-splat constant `<2 x i32> <i32 42, i32 24>` (will not work, and that's okay)

Additionally, the overflowing case mentioned above should be checked, as a negative example. The inverted case here with `-7` and `13` rather than the other way around, would also be good.


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58881/new/

https://reviews.llvm.org/D58881





More information about the llvm-commits mailing list