-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[SelectionDAG] Simplify vselect true, T, F -> T #100992
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
Conversation
This addresses a TODO where we can fold a vselect to it's true operand if the boolean is known to be all trues, checking getBooleanContents.
@llvm/pr-subscribers-backend-aarch64 @llvm/pr-subscribers-llvm-selectiondag Author: Luke Lau (lukel97) ChangesThis addresses a TODO where we can fold a vselect to it's true operand if the boolean is known to be all trues, checking getBooleanContents. Full diff: https://github.com/llvm/llvm-project/pull/100992.diff 2 Files Affected:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index daebcdabda984..1876bf3f18c21 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -9927,13 +9927,27 @@ SDValue SelectionDAG::simplifySelect(SDValue Cond, SDValue T, SDValue F) {
if (auto *CondC = dyn_cast<ConstantSDNode>(Cond))
return CondC->isZero() ? F : T;
- // TODO: This should simplify VSELECT with non-zero constant condition using
- // something like this (but check boolean contents to be complete?):
if (ConstantSDNode *CondC = isConstOrConstSplat(Cond, /*AllowUndefs*/ false,
- /*AllowTruncation*/ true))
+ /*AllowTruncation*/ true)) {
if (CondC->isZero())
return F;
+ switch (TLI->getBooleanContents(Cond.getValueType())) {
+ case TargetLowering::UndefinedBooleanContent:
+ if (CondC->getAPIntValue()[0])
+ return T;
+ break;
+ case TargetLowering::ZeroOrOneBooleanContent:
+ if (CondC->isOne())
+ return T;
+ break;
+ case TargetLowering::ZeroOrNegativeOneBooleanContent:
+ if (CondC->isAllOnes())
+ return T;
+ break;
+ }
+ }
+
// select ?, T, T --> T
if (T == F)
return T;
diff --git a/llvm/test/CodeGen/RISCV/rvv/vp-select.ll b/llvm/test/CodeGen/RISCV/rvv/vp-select.ll
new file mode 100644
index 0000000000000..5c903791927c6
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/vp-select.ll
@@ -0,0 +1,10 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=riscv64 -mattr=+v -verify-machineinstrs | FileCheck %s
+
+define <vscale x 1 x i64> @all_ones(<vscale x 1 x i64> %true, <vscale x 1 x i64> %false, i32 %evl) {
+; CHECK-LABEL: all_ones:
+; CHECK: # %bb.0:
+; CHECK-NEXT: ret
+ %v = call <vscale x 1 x i64> @llvm.vp.select.nxv1i64(<vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> %true, <vscale x 1 x i64> %false, i32 %evl)
+ ret <vscale x 1 x i64> %v
+}
|
case TargetLowering::ZeroOrNegativeOneBooleanContent: | ||
if (CondC->isAllOnes()) | ||
return T; | ||
break; |
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.
Not sure if its worth it but we already do this in at least one other place I can recall (extractBooleanFlip) - we could add a SelectionDAG::isBoolConstant(SDValue Cond, bool V)
helper to handle this?
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.
Might as well whilst we're here, will do
@@ -0,0 +1,10 @@ | |||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 | |||
; RUN: llc < %s -mtriple=riscv64 -mattr=+v -verify-machineinstrs | FileCheck %s |
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.
; RUN: llc < %s -mtriple=riscv64 -mattr=+v -verify-machineinstrs | FileCheck %s | |
; RUN: llc -mtriple=riscv64 -mattr=+v < %s | FileCheck %s |
Don't need to add -verify-machineinstrs in any random test
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.
I specifically added it for this test since it's dealing with RVV instructions. After we migrated the RISCVInsertVSETVLI pass to operate on LiveIntervals it really helps to have the machine verifier check that they're intact. It's already caught quite a few issues just on the existing RVV codegen tests alone.
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.
They'll get caught in expensive_checks builds. Unless this test is specifically trying to stress a verifier error, which it isn't, it's just wasting test time
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.
This is already the de-facto for the RVV in-tree tests:
$ git grep "\-verify\-machineinstrs" -- llvm/test/CodeGen/RISCV/rvv | wc -l
2017
I get your point about slow test times but we rely very heavily on this for coverage on RISCVInsertVSETVLI. Should we create a separate issue to discuss this outside of this PR
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.
Right I think this is a long standing issue, and we have thousands of violations. It defeats the point of having a separate EXPENSIVE_CHECKS behavior
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.
Right I think this is a long standing issue, and we have thousands of violations. It defeats the point of having a separate EXPENSIVE_CHECKS behavior
Do we have a RISCV expensive checks bot?
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.
Wouldn't the x86_64 expensive checks bot catch this? https://lab.llvm.org/buildbot/#/builders/16
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.
Wouldn't the x86_64 expensive checks bot catch this? https://lab.llvm.org/buildbot/#/builders/16
I think it would. I just wasn't sure what targets it builds.
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.
Created #102092 to separate out this discussion
; CHECK-LABEL: all_ones: | ||
; CHECK: # %bb.0: | ||
; CHECK-NEXT: ret | ||
%v = call <vscale x 1 x i64> @llvm.vp.select.nxv1i64(<vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> %true, <vscale x 1 x i64> %false, i32 %evl) |
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.
Also test the all false case? Plus another target with the other bits behavior?
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.
I tried creating a test case on r600 which seems to have the different behaviour but couldn't come up with anything meaningful. Mainly because the combine kicks in when the condition vector is at nxi1, so every behaviour considers it true.
✅ With the latest revision this PR passed the C/C++ code formatter. |
if (!Const) | ||
return std::nullopt; | ||
|
||
switch (TLI->getBooleanContents(N.getValueType())) { |
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.
It might be safer if we only accept the 'clean' 1/0, -1/0 and 1b/0b T/F values and std::nullopt otherwise.
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.
Ah I see what you meant by the original signature you suggested, that makes sense
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 - an alternative would be an optional result that returns the exact match - which would mean we only need one call in simplifySelect. No strong preference on this one though tbh - as long as we only accept the 'clean' boolean contents values.
…r if operand isn't constant, update tests on other targets
Gentle ping |
if (!Const) | ||
return std::nullopt; | ||
|
||
switch (TLI->getBooleanContents(N.getValueType())) { |
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 - an alternative would be an optional result that returns the exact match - which would mean we only need one call in simplifySelect. No strong preference on this one though tbh - as long as we only accept the 'clean' boolean contents values.
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.
LGTM - the riscv-gurus still need to confirm what to do regarding using verify-machineinstrs in rvv tests
This addresses a TODO where we can fold a vselect to it's true operand if the boolean is known to be all trues, by factoring out the logic from extractBooleanFlip which checks TLI.getBooleanContents.