-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ConstraintElim] Add facts implied by llvm.abs #73189
[ConstraintElim] Add facts implied by llvm.abs #73189
Conversation
@llvm/pr-subscribers-llvm-transforms Author: Alexander Shaposhnikov (alexander-shaposhnikov) ChangesAdd "abs(x) >= x" fact. https://alive2.llvm.org/ce/z/gOrrU3 Test plan: ninja check-all Full diff: https://github.com/llvm/llvm-project/pull/73189.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 7aadd810c1da387..59aaa677ccbf9a9 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -995,6 +995,11 @@ void State::addInfoFor(BasicBlock &BB) {
continue;
}
+ if (match(&I, m_Intrinsic<Intrinsic::abs>())) {
+ WorkList.push_back(FactOrCheck::getInstFact(DT.getNode(&BB), &I));
+ continue;
+ }
+
Value *A, *B;
CmpInst::Predicate Pred;
// For now, just handle assumes with a single compare as condition.
@@ -1629,6 +1634,11 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
ICmpInst::Predicate Pred;
if (!CB.isConditionFact()) {
+ if (Value *X; match(CB.Inst, m_Intrinsic<Intrinsic::abs>(m_Value(X)))) {
+ AddFact(CmpInst::ICMP_SGE, CB.Inst, X);
+ continue;
+ }
+
if (auto *MinMax = dyn_cast<MinMaxIntrinsic>(CB.Inst)) {
Pred = ICmpInst::getNonStrictPredicate(MinMax->getPredicate());
AddFact(Pred, MinMax, MinMax->getLHS());
diff --git a/llvm/test/Transforms/ConstraintElimination/abs.ll b/llvm/test/Transforms/ConstraintElimination/abs.ll
new file mode 100644
index 000000000000000..1cf56c6e37a8c81
--- /dev/null
+++ b/llvm/test/Transforms/ConstraintElimination/abs.ll
@@ -0,0 +1,26 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
+
+define i1 @abs_false(i32 %arg) {
+; CHECK-LABEL: define i1 @abs_false(
+; CHECK-SAME: i32 [[ARG:%.*]]) {
+; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 false)
+; CHECK-NEXT: ret i1 true
+;
+ %abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 false)
+ %cmp = icmp sge i32 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @abs_true(i32 %arg) {
+; CHECK-LABEL: define i1 @abs_true(
+; CHECK-SAME: i32 [[ARG:%.*]]) {
+; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true)
+; CHECK-NEXT: ret i1 true
+;
+ %abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 true)
+ %cmp = icmp sge i32 %abs, %arg
+ ret i1 %cmp
+}
+
+declare i32 @llvm.abs.i32(i32, i1 immarg)
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
What is the motivation of this patch? I think it is easy to implement this fold in |
@fhahn - this is indeed not a very frequent case, but the optimization kicked in a few times when i was testing it internally, so I don't have a strong opinion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the patch! IMO it is very worthwhile to teach ConstraintElim about more intrinsics, as this can enable additional optimizations by the pass that cannot easily be done by other passes.
@alexander Shaposhnikov Assuming you still have the original motivating case, any chance you could add a more complicated test case that can only be handled by ConstraintElim
?
@@ -995,6 +995,11 @@ void State::addInfoFor(BasicBlock &BB) { | |||
continue; | |||
} | |||
|
|||
if (match(&I, m_Intrinsic<Intrinsic::abs>())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that we support a number of intrinsics, we should probably covert that to a switch on the intrinsic ID, so it is easy to see what intrinsics are handled at a glance, as well as making it obvious that they are all handled in the same way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
(it also looks like the patch needs clang-format-diff) |
3f958f6
to
7ae48d2
Compare
7ae48d2
to
c13819c
Compare
Address comments |
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 | ||
; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s | ||
|
||
define i1 @abs_int_min_is_not_poison(i32 %arg) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you submit the tests separately and also add a version with constant arguments (both positive and negative)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need to clarify: which constant arguments are you referring to ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ping @fhahn - happy to send a separate PR with the tests, but need a clarification regarding "constant arguments" - what did you mean
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Constants to the llvm.abs calls
What is the motivation of this patch? Is this pattern from a real-world application? IMHO we should not add optimizations to improve the "coverage". |
@dtcxzyw - yes, llvm.abs calls originate e.g. from std::abs and this showed up multiple times when i was testing the patch internally. |
Great! Please add a more complicated test that can only be handled by |
The test that involves arithmetic was intentionally made simple. Regarding InstSimplify - unfortunately I would probably disagree with the approach. ConstraintElim is a more general / robust solution and iirc it was introduced for these purposes (as an alternative to expanding the complexity of patterns in InstCombine/InstSimplify), but I'd allow @nikic and @fhahn to weigh in / correct me. I think I've seen a few more cases where ConstraintElim stumbles on intrinsics, this was just the simplest one.
The codebase is internal unfortunately. |
|
P.S. I'd like to expand my previous comment a bit - I've just checked and currently InstSimplify doesn't handle these cases
To me teaching ConstrainElim about intrinsics seems to be a better idea than putting more patterns into InstSimplify, |
c13819c
to
79e2989
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the latest update, looks mostly good, with a few small remaining comments inline and suggestions for follow-up simplifications.
It looks like the code-formatting checks failed, so it would be good to make sure the code is formatted correctly.
The test that involves arithmetic was intentionally made simple. Regarding InstSimplify - unfortunately I would probably disagree with the approach. ConstraintElim is a more general / robust solution and iirc it was introduced for these purposes (as an alternative to expanding the complexity of patterns in InstCombine/InstSimplify), but I'd allow @nikic and @fhahn to weigh in / correct me. I think I've seen a few more cases where ConstraintElim stumbles on intrinsics, this was just the simplest one.
I don't think it's a question of either/or, there should be value in handling it in both. InstCombine/InstSimplify is used at more different points in the pipeline (vs ConstraintElimination running once). The main advantage of support in ConstraintElimination isn't simplifying relatively simple stuff like
%abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 false)
%cmp = icmp sge i32 %abs, %arg
but more complicated expressions.
79e2989
to
dbc9d62
Compare
Add tests for llvm.abs. This is a preparation for #73189 Test plan: ninja check-all
dbc9d62
to
eefaeb0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eefaeb0
to
0014eaf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still LGTM, thanks!
@alexander-shaposhnikov are you planning on working on the suggestions for follow-ups? |
@fhahn - yup, I'm planning to send a follow-up PR ~this week (if it's not urgent) |
Sounds great, just wanted to check, it's not urgent at all. |
Add "abs(x) >=s x" fact.
https://alive2.llvm.org/ce/z/gOrrU3
Test plan: ninja check-all
Happy to add more tests covering llvm.abs.