aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@outlook.com>2023-11-20 08:32:50 -0800
committerAlexey Bataev <a.bataev@outlook.com>2023-11-20 08:35:35 -0800
commitf609d4ba1d940c781f4fed44f7c69422d1766f09 (patch)
tree0d6b4279ef6c7901268a58cc3fd97b159d1faac4
parentc38ae74b48c1cb8aedf384686eaa05815d366609 (diff)
downloadllvm-f609d4ba1d940c781f4fed44f7c69422d1766f09.zip
llvm-f609d4ba1d940c781f4fed44f7c69422d1766f09.tar.gz
llvm-f609d4ba1d940c781f4fed44f7c69422d1766f09.tar.bz2
[SLP]Fix PR72833: do not crash if only operand is casted but the use
instruction. Need to check if only operand is casted, not the user instruction itself, if the types of the operands does not match the actual type.
-rw-r--r--llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp51
-rw-r--r--llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-transformed-operand.ll83
2 files changed, 105 insertions, 29 deletions
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 2aedc9b..94408ee 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -11110,7 +11110,8 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
Builder.SetCurrentDebugLocation(PH->getDebugLoc());
Value *Vec = vectorizeOperand(E, i, /*PostponedPHIs=*/true);
if (VecTy != Vec->getType()) {
- assert(It != MinBWs.end() && "Expected item in MinBWs.");
+ assert(MinBWs.contains(PH->getIncomingValue(i)) &&
+ "Expected item in MinBWs.");
Vec = Builder.CreateIntCast(Vec, VecTy, It->second.second);
}
NewPhi->addIncoming(Vec, IBB);
@@ -11362,13 +11363,11 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
return E->VectorizedValue;
}
if (L->getType() != R->getType()) {
- assert(It != MinBWs.end() && "Expected item in MinBWs.");
- if (L == R) {
- R = L = Builder.CreateIntCast(L, VecTy, IsSigned);
- } else {
- L = Builder.CreateIntCast(L, VecTy, IsSigned);
- R = Builder.CreateIntCast(R, VecTy, IsSigned);
- }
+ assert((MinBWs.contains(VL0->getOperand(0)) ||
+ MinBWs.contains(VL0->getOperand(1))) &&
+ "Expected item in MinBWs.");
+ L = Builder.CreateIntCast(L, VecTy, IsSigned);
+ R = Builder.CreateIntCast(R, VecTy, IsSigned);
}
CmpInst::Predicate P0 = cast<CmpInst>(VL0)->getPredicate();
@@ -11401,13 +11400,11 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
return E->VectorizedValue;
}
if (True->getType() != False->getType()) {
- assert(It != MinBWs.end() && "Expected item in MinBWs.");
- if (True == False) {
- True = False = Builder.CreateIntCast(True, VecTy, IsSigned);
- } else {
- True = Builder.CreateIntCast(True, VecTy, IsSigned);
- False = Builder.CreateIntCast(False, VecTy, IsSigned);
- }
+ assert((MinBWs.contains(VL0->getOperand(1)) ||
+ MinBWs.contains(VL0->getOperand(2))) &&
+ "Expected item in MinBWs.");
+ True = Builder.CreateIntCast(True, VecTy, IsSigned);
+ False = Builder.CreateIntCast(False, VecTy, IsSigned);
}
Value *V = Builder.CreateSelect(Cond, True, False);
@@ -11471,13 +11468,11 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
return E->VectorizedValue;
}
if (LHS->getType() != RHS->getType()) {
- assert(It != MinBWs.end() && "Expected item in MinBWs.");
- if (LHS == RHS) {
- RHS = LHS = Builder.CreateIntCast(LHS, VecTy, IsSigned);
- } else {
- LHS = Builder.CreateIntCast(LHS, VecTy, IsSigned);
- RHS = Builder.CreateIntCast(RHS, VecTy, IsSigned);
- }
+ assert((MinBWs.contains(VL0->getOperand(0)) ||
+ MinBWs.contains(VL0->getOperand(1))) &&
+ "Expected item in MinBWs.");
+ LHS = Builder.CreateIntCast(LHS, VecTy, IsSigned);
+ RHS = Builder.CreateIntCast(RHS, VecTy, IsSigned);
}
Value *V = Builder.CreateBinOp(
@@ -11710,13 +11705,11 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
return E->VectorizedValue;
}
if (LHS && RHS && LHS->getType() != RHS->getType()) {
- assert(It != MinBWs.end() && "Expected item in MinBWs.");
- if (LHS == RHS) {
- RHS = LHS = Builder.CreateIntCast(LHS, VecTy, IsSigned);
- } else {
- LHS = Builder.CreateIntCast(LHS, VecTy, IsSigned);
- RHS = Builder.CreateIntCast(RHS, VecTy, IsSigned);
- }
+ assert((MinBWs.contains(VL0->getOperand(0)) ||
+ MinBWs.contains(VL0->getOperand(1))) &&
+ "Expected item in MinBWs.");
+ LHS = Builder.CreateIntCast(LHS, VecTy, IsSigned);
+ RHS = Builder.CreateIntCast(RHS, VecTy, IsSigned);
}
Value *V0, *V1;
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-transformed-operand.ll b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-transformed-operand.ll
new file mode 100644
index 0000000..ac8dd65
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-transformed-operand.ll
@@ -0,0 +1,83 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -passes=slp-vectorizer -S -slp-threshold=-6 -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
+
+define void @test(i64 %d.promoted.i) {
+; CHECK-LABEL: define void @test(
+; CHECK-SAME: i64 [[D_PROMOTED_I:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i64> <i64 poison, i64 0>, i64 [[D_PROMOTED_I]], i32 0
+; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i64> zeroinitializer, [[TMP0]]
+; CHECK-NEXT: [[TMP2:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i1>
+; CHECK-NEXT: [[TMP3:%.*]] = mul <2 x i1> [[TMP2]], zeroinitializer
+; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i1> [[TMP3]], zeroinitializer
+; CHECK-NEXT: [[TMP5:%.*]] = or <2 x i1> [[TMP4]], zeroinitializer
+; CHECK-NEXT: [[TMP6:%.*]] = or <2 x i1> [[TMP5]], zeroinitializer
+; CHECK-NEXT: [[TMP7:%.*]] = or <2 x i1> [[TMP6]], zeroinitializer
+; CHECK-NEXT: [[TMP8:%.*]] = or <2 x i1> [[TMP7]], zeroinitializer
+; CHECK-NEXT: [[TMP9:%.*]] = or <2 x i1> [[TMP8]], zeroinitializer
+; CHECK-NEXT: [[TMP10:%.*]] = or <2 x i1> [[TMP9]], zeroinitializer
+; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i1> [[TMP10]], i32 0
+; CHECK-NEXT: [[TMP12:%.*]] = sext i1 [[TMP11]] to i32
+; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x i1> [[TMP10]], i32 1
+; CHECK-NEXT: [[TMP14:%.*]] = sext i1 [[TMP13]] to i32
+; CHECK-NEXT: [[TMP15:%.*]] = or i32 [[TMP12]], [[TMP14]]
+; CHECK-NEXT: [[TMP16:%.*]] = and i32 [[TMP15]], 0
+; CHECK-NEXT: store i32 [[TMP16]], ptr null, align 4
+; CHECK-NEXT: ret void
+;
+entry:
+ %add.1.i = add i64 0, 0
+ %and.1.i = and i64 %add.1.i, %d.promoted.i
+ %conv12.1.i = trunc i64 %and.1.i to i32
+ %mul.i.1.i = mul i32 %conv12.1.i, 0
+ %conv12.i = trunc i64 0 to i32
+ %mul.i.i = mul i32 %conv12.i, 0
+ %conv14104.i = or i32 %mul.i.1.i, %mul.i.i
+ %conv12.2.i = trunc i64 0 to i32
+ %mul.i.2.i = mul i32 %conv12.2.i, 0
+ %0 = or i32 %conv14104.i, %mul.i.2.i
+ %conv12.182.i = trunc i64 0 to i32
+ %mul.i.183.i = mul i32 %conv12.182.i, 0
+ %1 = or i32 %0, %mul.i.183.i
+ %conv12.1.1.i = trunc i64 0 to i32
+ %mul.i.1.1.i = mul i32 %conv12.1.1.i, 0
+ %2 = or i32 %1, %mul.i.1.1.i
+ %conv12.2.1.i = trunc i64 0 to i32
+ %mul.i.2.1.i = mul i32 %conv12.2.1.i, 0
+ %3 = or i32 %2, %mul.i.2.1.i
+ %conv12.297.i = trunc i64 0 to i32
+ %mul.i.298.i = mul i32 %conv12.297.i, 0
+ %4 = or i32 %3, %mul.i.298.i
+ %conv12.1.2.i = trunc i64 0 to i32
+ %mul.i.1.2.i = mul i32 %conv12.1.2.i, 0
+ %5 = or i32 %4, %mul.i.1.2.i
+ %add.1.i.1 = add i64 0, 0
+ %and.1.i.1 = and i64 %add.1.i.1, 0
+ %conv12.1.i.1 = trunc i64 %and.1.i.1 to i32
+ %mul.i.1.i.1 = mul i32 %conv12.1.i.1, 0
+ %conv12.i.1 = trunc i64 0 to i32
+ %mul.i.i.1 = mul i32 %conv12.i.1, 0
+ %conv14104.i.1 = or i32 %mul.i.1.i.1, %mul.i.i.1
+ %conv12.2.i.1 = trunc i64 0 to i32
+ %mul.i.2.i.1 = mul i32 %conv12.2.i.1, 0
+ %6 = or i32 %conv14104.i.1, %mul.i.2.i.1
+ %conv12.182.i.1 = trunc i64 0 to i32
+ %mul.i.183.i.1 = mul i32 %conv12.182.i.1, 0
+ %7 = or i32 %6, %mul.i.183.i.1
+ %conv12.1.1.i.1 = trunc i64 0 to i32
+ %mul.i.1.1.i.1 = mul i32 %conv12.1.1.i.1, 0
+ %8 = or i32 %7, %mul.i.1.1.i.1
+ %conv12.2.1.i.1 = trunc i64 0 to i32
+ %mul.i.2.1.i.1 = mul i32 %conv12.2.1.i.1, 0
+ %9 = or i32 %8, %mul.i.2.1.i.1
+ %conv12.297.i.1 = trunc i64 0 to i32
+ %mul.i.298.i.1 = mul i32 %conv12.297.i.1, 0
+ %10 = or i32 %9, %mul.i.298.i.1
+ %conv12.1.2.i.1 = trunc i64 0 to i32
+ %mul.i.1.2.i.1 = mul i32 %conv12.1.2.i.1, 0
+ %11 = or i32 %10, %mul.i.1.2.i.1
+ %12 = or i32 %5, %11
+ %13 = and i32 %12, 0
+ store i32 %13, ptr null, align 4
+ ret void
+}