-
Notifications
You must be signed in to change notification settings - Fork 14k
[InstSimplify] Add basic simplifications for vp.reverse #144112
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
Directly modeled after what we do for vector.reverse, but with restrictions on EVL and mask added.
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-llvm-analysis Author: Philip Reames (preames) ChangesDirectly modeled after what we do for vector.reverse, but with restrictions on EVL and mask added. Full diff: https://github.com/llvm/llvm-project/pull/144112.diff 2 Files Affected:
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index e397a228afee0..d1ac8d9fbdfd1 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6969,6 +6969,23 @@ static Value *simplifyIntrinsic(CallBase *Call, Value *Callee,
}
return nullptr;
}
+ case Intrinsic::experimental_vp_reverse: {
+ Value *Vec = Call->getArgOperand(0);
+ Value *Mask = Call->getArgOperand(1);
+ Value *EVL = Call->getArgOperand(2);
+
+ Value *X;
+ // vp.reverse(vp.reverse(X)) == X (with all ones mask and matching EVL)
+ if (match(Mask, m_AllOnes()) &&
+ match(Vec, m_Intrinsic<Intrinsic::experimental_vp_reverse>(
+ m_Value(X), m_AllOnes(), m_Specific(EVL))))
+ return X;
+
+ // vp.reverse(splat(X)) -> splat(X) (regardless of mask and EVL)
+ if (isSplatValue(Vec))
+ return Vec;
+ return nullptr;
+ }
default:
return nullptr;
}
diff --git a/llvm/test/Transforms/InstSimplify/vp-reverse.ll b/llvm/test/Transforms/InstSimplify/vp-reverse.ll
index 3c3bb871dc610..f19a2ac8ca9e1 100644
--- a/llvm/test/Transforms/InstSimplify/vp-reverse.ll
+++ b/llvm/test/Transforms/InstSimplify/vp-reverse.ll
@@ -3,9 +3,7 @@
define <vscale x 4 x i32> @rev_of_rev(<vscale x 4 x i32> %a, i32 %evl) {
; CHECK-LABEL: @rev_of_rev(
-; CHECK-NEXT: [[A_REV:%.*]] = tail call <vscale x 4 x i32> @llvm.experimental.vp.reverse.nxv4i32(<vscale x 4 x i32> [[A:%.*]], <vscale x 4 x i1> splat (i1 true), i32 [[EVL:%.*]])
-; CHECK-NEXT: [[RES:%.*]] = tail call <vscale x 4 x i32> @llvm.experimental.vp.reverse.nxv4i32(<vscale x 4 x i32> [[A_REV]], <vscale x 4 x i1> splat (i1 true), i32 [[EVL]])
-; CHECK-NEXT: ret <vscale x 4 x i32> [[RES]]
+; CHECK-NEXT: ret <vscale x 4 x i32> [[A:%.*]]
;
%a.rev = tail call <vscale x 4 x i32> @llvm.experimental.vp.reverse(<vscale x 4 x i32> %a, <vscale x 4 x i1> splat (i1 true), i32 %evl)
%res = tail call <vscale x 4 x i32> @llvm.experimental.vp.reverse(<vscale x 4 x i32> %a.rev, <vscale x 4 x i1> splat (i1 true), i32 %evl)
@@ -25,8 +23,7 @@ define <vscale x 4 x i32> @rev_of_rev_diffevl(<vscale x 4 x i32> %a, i32 %evl) {
define <vscale x 4 x i32> @rev_of_poison(i32 %evl) {
; CHECK-LABEL: @rev_of_poison(
-; CHECK-NEXT: [[REV:%.*]] = tail call <vscale x 4 x i32> @llvm.experimental.vp.reverse.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i1> splat (i1 true), i32 [[EVL:%.*]])
-; CHECK-NEXT: ret <vscale x 4 x i32> [[REV]]
+; CHECK-NEXT: ret <vscale x 4 x i32> poison
;
%rev = tail call <vscale x 4 x i32> @llvm.experimental.vp.reverse(<vscale x 4 x i32> poison, <vscale x 4 x i1> splat (i1 true), i32 %evl)
ret <vscale x 4 x i32> %rev
@@ -34,8 +31,7 @@ define <vscale x 4 x i32> @rev_of_poison(i32 %evl) {
define <vscale x 4 x i32> @rev_of_undef(i32 %evl) {
; CHECK-LABEL: @rev_of_undef(
-; CHECK-NEXT: [[REV:%.*]] = tail call <vscale x 4 x i32> @llvm.experimental.vp.reverse.nxv4i32(<vscale x 4 x i32> undef, <vscale x 4 x i1> splat (i1 true), i32 [[EVL:%.*]])
-; CHECK-NEXT: ret <vscale x 4 x i32> [[REV]]
+; CHECK-NEXT: ret <vscale x 4 x i32> undef
;
%rev = tail call <vscale x 4 x i32> @llvm.experimental.vp.reverse(<vscale x 4 x i32> undef, <vscale x 4 x i1> splat (i1 true), i32 %evl)
ret <vscale x 4 x i32> %rev
@@ -43,8 +39,7 @@ define <vscale x 4 x i32> @rev_of_undef(i32 %evl) {
define <vscale x 4 x i32> @rev_of_zero(i32 %evl) {
; CHECK-LABEL: @rev_of_zero(
-; CHECK-NEXT: [[REV:%.*]] = tail call <vscale x 4 x i32> @llvm.experimental.vp.reverse.nxv4i32(<vscale x 4 x i32> zeroinitializer, <vscale x 4 x i1> splat (i1 true), i32 [[EVL:%.*]])
-; CHECK-NEXT: ret <vscale x 4 x i32> [[REV]]
+; CHECK-NEXT: ret <vscale x 4 x i32> zeroinitializer
;
%rev = tail call <vscale x 4 x i32> @llvm.experimental.vp.reverse(<vscale x 4 x i32> zeroinitializer, <vscale x 4 x i1> splat (i1 true), i32 %evl)
ret <vscale x 4 x i32> %rev
@@ -54,8 +49,7 @@ define <vscale x 4 x i32> @rev_of_splat(i32 %a, i32 %evl) {
; CHECK-LABEL: @rev_of_splat(
; CHECK-NEXT: [[A_INS:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[A:%.*]], i32 0
; CHECK-NEXT: [[A_VEC:%.*]] = shufflevector <vscale x 4 x i32> [[A_INS]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
-; CHECK-NEXT: [[REV:%.*]] = tail call <vscale x 4 x i32> @llvm.experimental.vp.reverse.nxv4i32(<vscale x 4 x i32> [[A_VEC]], <vscale x 4 x i1> splat (i1 true), i32 [[EVL:%.*]])
-; CHECK-NEXT: ret <vscale x 4 x i32> [[REV]]
+; CHECK-NEXT: ret <vscale x 4 x i32> [[A_VEC]]
;
%a.ins = insertelement <vscale x 4 x i32> poison, i32 %a, i32 0
%a.vec = shufflevector <vscale x 4 x i32> %a.ins, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
@@ -67,8 +61,7 @@ define <vscale x 4 x i32> @rev_of_splat2(i32 %a, <vscale x 4 x i1> %m, i32 %evl)
; CHECK-LABEL: @rev_of_splat2(
; CHECK-NEXT: [[A_INS:%.*]] = insertelement <vscale x 4 x i32> poison, i32 [[A:%.*]], i32 0
; CHECK-NEXT: [[A_VEC:%.*]] = shufflevector <vscale x 4 x i32> [[A_INS]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
-; CHECK-NEXT: [[REV:%.*]] = tail call <vscale x 4 x i32> @llvm.experimental.vp.reverse.nxv4i32(<vscale x 4 x i32> [[A_VEC]], <vscale x 4 x i1> [[M:%.*]], i32 [[EVL:%.*]])
-; CHECK-NEXT: ret <vscale x 4 x i32> [[REV]]
+; CHECK-NEXT: ret <vscale x 4 x i32> [[A_VEC]]
;
%a.ins = insertelement <vscale x 4 x i32> poison, i32 %a, i32 0
%a.vec = shufflevector <vscale x 4 x i32> %a.ins, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
|
You can test this locally with the following command:git diff -U0 --pickaxe-regex -S '([^a-zA-Z0-9#_-]undef[^a-zA-Z0-9_-]|UndefValue::get)' 'HEAD~1' HEAD llvm/lib/Analysis/InstructionSimplify.cpp llvm/test/Transforms/InstSimplify/vp-reverse.ll The following files introduce new uses of undef:
Undef is now deprecated and should only be used in the rare cases where no replacement is possible. For example, a load of uninitialized memory yields In tests, avoid using For example, this is considered a bad practice: define void @fn() {
...
br i1 undef, ...
} Please use the following instead: define void @fn(i1 %cond) {
...
br i1 %cond, ...
} Please refer to the Undefined Behavior Manual for more information. |
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.
LG
@@ -25,26 +23,23 @@ define <vscale x 4 x i32> @rev_of_rev_diffevl(<vscale x 4 x i32> %a, i32 %evl) { | |||
|
|||
define <vscale x 4 x i32> @rev_of_poison(i32 %evl) { | |||
; CHECK-LABEL: @rev_of_poison( | |||
; CHECK-NEXT: [[REV:%.*]] = tail call <vscale x 4 x i32> @llvm.experimental.vp.reverse.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i1> splat (i1 true), i32 [[EVL:%.*]]) | |||
; CHECK-NEXT: ret <vscale x 4 x i32> [[REV]] | |||
; CHECK-NEXT: ret <vscale x 4 x i32> poison | |||
; | |||
%rev = tail call <vscale x 4 x i32> @llvm.experimental.vp.reverse(<vscale x 4 x i32> poison, <vscale x 4 x i1> splat (i1 true), i32 %evl) | |||
ret <vscale x 4 x i32> %rev | |||
} | |||
|
|||
define <vscale x 4 x i32> @rev_of_undef(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.
We don't need undef tests. There are many PRs that drop undef tests...
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 want to push back a bit here. There's a big difference between removing undef from tests where the undef is the result of reduction, or doesn't reflect test intention. This case is specifically testing correct behavior of an undef fold. I would hope we are not removing such cases, that would seem actively undesirable.
FYI, the CI was showing failures when I landed, but a) I built locally without issue, and b) the logs didn't actually show any test failures. I'm putting this down to a CI flak until proven otherwise. |
Directly modeled after what we do for vector.reverse, but with restrictions on EVL and mask added.