-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[VectorCombine] Fix crash in scalarizeVPIntrinsic #72039
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
[VectorCombine] Fix crash in scalarizeVPIntrinsic #72039
Conversation
When getSplatOp returns nullptr, the intrinsic cannot be scalarized. This patch includes a test case that fixes a crash from trying to scalarize the VPIntrinsic when getSplatOp returns nullptr. This case can be scalarized in the future by improving getSplatOp, but the checks added in this patch should remain. This fixes llvm#72034.
@llvm/pr-subscribers-llvm-transforms Author: Michael Maitland (michaelmaitland) ChangesWhen getSplatOp returns nullptr, the intrinsic cannot be scalarized. This patch includes a test case that fixes a crash from trying to scalarize the VPIntrinsic when getSplatOp returns nullptr. This case can be scalarized in the future by improving getSplatOp, but the checks added in this patch should remain. This fixes #72034. Full diff: https://github.com/llvm/llvm-project/pull/72039.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index 9a91ce207bb04c9..6d79c9b13add067 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -843,6 +843,8 @@ bool VectorCombine::scalarizeVPIntrinsic(Instruction &I) {
Value *ScalarOp0 = getSplatValue(Op0);
Value *ScalarOp1 = getSplatValue(Op1);
+ if (!ScalarOp0 || !ScalarOp1)
+ return false;
Value *ScalarVal =
ScalarIntrID
? Builder.CreateIntrinsic(VecTy->getScalarType(), *ScalarIntrID,
diff --git a/llvm/test/Transforms/VectorCombine/RISCV/vpintrin-scalarization-shufflevector-splat.ll b/llvm/test/Transforms/VectorCombine/RISCV/vpintrin-scalarization-shufflevector-splat.ll
new file mode 100644
index 000000000000000..d3c477d180aa54f
--- /dev/null
+++ b/llvm/test/Transforms/VectorCombine/RISCV/vpintrin-scalarization-shufflevector-splat.ll
@@ -0,0 +1,16 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; RUN: opt -S -mtriple=riscv64 -mattr=+v %s -passes=vector-combine | FileCheck %s --check-prefix
+
+declare <4 x i64> @llvm.vp.add.v4i64(<4 x i64>, <4 x i64>, <4 x i1>, i32)
+
+define <4 x i64> @add_v4i64_allonesmask(<4 x i64> %x) {
+; CHECK-LABEL: define <4 x i64> @add_v4i64_allonesmask(
+; CHECK-SAME: <4 x i64> [[X:%.*]]) #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i64> [[X]], <4 x i64> zeroinitializer, <4 x i32> zeroinitializer
+; CHECK-NEXT: [[TMP2:%.*]] = call <4 x i64> @llvm.vp.add.v4i64(<4 x i64> [[TMP1]], <4 x i64> zeroinitializer, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, i32 0)
+; CHECK-NEXT: ret <4 x i64> [[TMP2]]
+;
+ %1 = shufflevector <4 x i64> %x, <4 x i64> zeroinitializer, <4 x i32> zeroinitializer
+ %2 = call <4 x i64> @llvm.vp.add.v4i64(<4 x i64> %1, <4 x i64> zeroinitializer, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, i32 0)
+ ret <4 x i64> %2
+}
|
@@ -843,6 +843,8 @@ bool VectorCombine::scalarizeVPIntrinsic(Instruction &I) { | |||
|
|||
Value *ScalarOp0 = getSplatValue(Op0); | |||
Value *ScalarOp1 = getSplatValue(Op1); | |||
if (!ScalarOp0 || !ScalarOp1) |
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.
Should we use getSplatValue at the top where we used isSplatValue? That way we fail out before we do wasted work.
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.
Sure. Do you know why getSplatValue fails to get the splat even though isSplatValue returns true? That sounds like a bug to me?
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.
getSplatValue can't create new instructions, it can only return an operand of existing instructions. isSplatValue can look at shuffles and see that it splat one of the elements of its input. To get that element as a scalar you would need to insert an extractelement instruction.
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
When getSplatOp returns nullptr, the intrinsic cannot be scalarized. This patch includes a test case that fixes a crash from trying to scalarize the VPIntrinsic when getSplatOp returns nullptr. This fixes llvm#72034.
Local branch amd-gfx 46373f4 Merged main:994d882e151c into amd-gfx:77a9f8374d78 Remote branch main acef83c [VectorCombine] Fix crash in scalarizeVPIntrinsic (llvm#72039)
When getSplatOp returns nullptr, the intrinsic cannot be scalarized. This patch includes a test case that fixes a crash from trying to scalarize the VPIntrinsic when getSplatOp returns nullptr. This case can be scalarized in the future by improving getSplatOp, but the checks added in this patch should remain.
This fixes #72034.