-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[RISCV] Avoid VMNOT by swapping VMERGE operands for mask extensions #126751
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
|
In llvm-codegen-benchmark I noticed hundreds of patterns such as https://github.com/dtcxzyw/llvm-codegen-benchmark/blob/12a783bf6af60c93d100354b71dc6c0c4dea4eb7/result/rvv/0002ccdf5e758f9a.S Questions:
Further work: |
|
In concept, sound reasonable. I had played with a more generic vmerge operand swap a while back, and got lost in unprofitable cases. Something restricted specifically to the extend doesn't seem unreasonable. Would need a real patch and tests to meaningful review beyond that. |
|
@llvm/pr-subscribers-backend-risc-v Author: Piotr Fusik (pfusik) ChangesFull diff: https://github.com/llvm/llvm-project/pull/126751.diff 2 Files Affected:
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index c40ab0d09bdf6..11f532c25d311 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -8965,6 +8965,9 @@ SDValue RISCVTargetLowering::lowerVectorMaskExt(SDValue Op, SelectionDAG &DAG,
if (VecVT.isScalableVector()) {
SDValue SplatZero = DAG.getConstant(0, DL, VecVT);
SDValue SplatTrueVal = DAG.getSignedConstant(ExtTrueVal, DL, VecVT);
+ if (Src.getOpcode() == ISD::XOR &&
+ ISD::isConstantSplatVectorAllOnes(Src.getOperand(1).getNode(), false))
+ return DAG.getNode(ISD::VSELECT, DL, VecVT, Src.getOperand(0), SplatZero, SplatTrueVal);
return DAG.getNode(ISD::VSELECT, DL, VecVT, Src, SplatTrueVal, SplatZero);
}
@@ -8980,6 +8983,20 @@ SDValue RISCVTargetLowering::lowerVectorMaskExt(SDValue Op, SelectionDAG &DAG,
SDValue SplatZero = DAG.getConstant(0, DL, XLenVT);
SDValue SplatTrueVal = DAG.getSignedConstant(ExtTrueVal, DL, XLenVT);
+ if (Src.getOpcode() == ISD::EXTRACT_SUBVECTOR) {
+ SDValue Xor = Src.getOperand(0);
+ if (Xor.getOpcode() == RISCVISD::VMXOR_VL) {
+ SDValue ScalableOnes = Xor.getOperand(1);
+ if (ScalableOnes.getOpcode() == ISD::INSERT_SUBVECTOR &&
+ ScalableOnes.getOperand(0).isUndef() &&
+ ISD::isConstantSplatVectorAllOnes(
+ ScalableOnes.getOperand(1).getNode(), false)) {
+ CC = Xor.getOperand(0);
+ std::swap(SplatZero, SplatTrueVal);
+ }
+ }
+ }
+
SplatZero = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, ContainerVT,
DAG.getUNDEF(ContainerVT), SplatZero, VL);
SplatTrueVal = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, ContainerVT,
diff --git a/llvm/test/CodeGen/RISCV/rvv/mask-exts-not.ll b/llvm/test/CodeGen/RISCV/rvv/mask-exts-not.ll
new file mode 100644
index 0000000000000..c72d717c033ea
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/mask-exts-not.ll
@@ -0,0 +1,52 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+v -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=riscv64 -mattr=+v -verify-machineinstrs < %s | FileCheck %s
+
+define <vscale x 8 x i8> @mask_sext_not_nxv8i8(<vscale x 8 x i1> %m) {
+; CHECK-LABEL: mask_sext_not_nxv8i8:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma
+; CHECK-NEXT: vmv.v.i v8, -1
+; CHECK-NEXT: vmerge.vim v8, v8, 0, v0
+; CHECK-NEXT: ret
+ %n = xor <vscale x 8 x i1> %m, splat (i1 true)
+ %ext = sext <vscale x 8 x i1> %n to <vscale x 8 x i8>
+ ret <vscale x 8 x i8> %ext
+}
+
+define <vscale x 8 x i8> @mask_zext_not_nxv8i8(<vscale x 8 x i1> %m) {
+; CHECK-LABEL: mask_zext_not_nxv8i8:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma
+; CHECK-NEXT: vmv.v.i v8, 1
+; CHECK-NEXT: vmerge.vim v8, v8, 0, v0
+; CHECK-NEXT: ret
+ %n = xor <vscale x 8 x i1> %m, splat (i1 true)
+ %ext = zext <vscale x 8 x i1> %n to <vscale x 8 x i8>
+ ret <vscale x 8 x i8> %ext
+}
+
+define <8 x i8> @mask_sext_not_v8i8(<8 x i1> %m) {
+; CHECK-LABEL: mask_sext_not_v8i8:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
+; CHECK-NEXT: vmv.v.i v8, -1
+; CHECK-NEXT: vmerge.vim v8, v8, 0, v0
+; CHECK-NEXT: ret
+ %n = xor <8 x i1> %m, splat (i1 true)
+ %ext = sext <8 x i1> %n to <8 x i8>
+ ret <8 x i8> %ext
+}
+
+define <8 x i8> @mask_zext_not_v8i8(<8 x i1> %m) {
+; CHECK-LABEL: mask_zext_not_v8i8:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
+; CHECK-NEXT: vmv.v.i v8, 1
+; CHECK-NEXT: vmerge.vim v8, v8, 0, v0
+; CHECK-NEXT: ret
+ %n = xor <8 x i1> %m, splat (i1 true)
+ %ext = zext <8 x i1> %n to <8 x i8>
+ ret <8 x i8> %ext
+}
+
|
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
preames
left a comment
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
Please make sure to update the review description to be non-blank before landing.
Do you have commit access? Or do you need me to land for you?
lukel97
left a comment
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
| SDValue SplatZero = DAG.getConstant(0, DL, VecVT); | ||
| SDValue SplatTrueVal = DAG.getSignedConstant(ExtTrueVal, DL, VecVT); | ||
| if (Src.getOpcode() == ISD::XOR && | ||
| ISD::isConstantSplatVectorAllOnes(Src.getOperand(1).getNode(), false)) |
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.
The BuildVectorOnly arg defaults to false so you can omit if you'd like
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.
Default arg omitted, thanks!
| if (ScalableOnes.getOpcode() == ISD::INSERT_SUBVECTOR && | ||
| ScalableOnes.getOperand(0).isUndef() && | ||
| ISD::isConstantSplatVectorAllOnes( | ||
| ScalableOnes.getOperand(1).getNode(), false)) { |
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.
Same here
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
Done.
I do have commit access. Since the GitHub interface is restricted to squash merges, I'll cherry-pick the commit adding the tests to the main branch. I've done that before. |
Fold:
(select (not m), 1, 0) -> (select m, 0, 1)
(select (not m), -1, 0) -> (select m, 0, -1)
|
Tests merged into main branch as 9787240. PR rebased. |
Fold: