Skip to content

[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

Merged
merged 8 commits into from
Aug 6, 2024

Conversation

lukel97
Copy link
Contributor

@lukel97 lukel97 commented Jul 29, 2024

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.

lukel97 added 2 commits July 29, 2024 17:02
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.
@lukel97 lukel97 requested review from Arsenic-ATG, arsenm, preames and RKSimon and removed request for Arsenic-ATG July 29, 2024 09:18
@llvmbot llvmbot added the llvm:SelectionDAG SelectionDAGISel as well label Jul 29, 2024
@llvmbot
Copy link
Member

llvmbot commented Jul 29, 2024

@llvm/pr-subscribers-backend-aarch64
@llvm/pr-subscribers-backend-x86

@llvm/pr-subscribers-llvm-selectiondag

Author: Luke Lau (lukel97)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/100992.diff

2 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (+17-3)
  • (added) llvm/test/CodeGen/RISCV/rvv/vp-select.ll (+10)
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;
Copy link
Collaborator

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?

Copy link
Contributor Author

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
; 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

Copy link
Contributor Author

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.

Copy link
Contributor

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

Copy link
Contributor Author

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

Copy link
Contributor

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

Copy link
Collaborator

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?

Copy link
Contributor Author

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

Copy link
Collaborator

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.

Copy link
Contributor Author

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)
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link

github-actions bot commented Jul 29, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

if (!Const)
return std::nullopt;

switch (TLI->getBooleanContents(N.getValueType())) {
Copy link
Collaborator

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.

Copy link
Contributor Author

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

Copy link
Collaborator

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
@lukel97
Copy link
Contributor Author

lukel97 commented Aug 5, 2024

Gentle ping

if (!Const)
return std::nullopt;

switch (TLI->getBooleanContents(N.getValueType())) {
Copy link
Collaborator

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.

Copy link
Collaborator

@RKSimon RKSimon left a 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

@lukel97 lukel97 merged commit 33fc322 into llvm:main Aug 6, 2024
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants