diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 6b3cd27b77a7a..b6acba48517c5 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -6588,14 +6588,17 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { VectorType *AccTy = cast(Call.getArgOperand(0)->getType()); VectorType *VecTy = cast(Call.getArgOperand(1)->getType()); - unsigned VecWidth = VecTy->getElementCount().getKnownMinValue(); - unsigned AccWidth = AccTy->getElementCount().getKnownMinValue(); + ElementCount VecWidth = VecTy->getElementCount(); + ElementCount AccWidth = AccTy->getElementCount(); - Check((VecWidth % AccWidth) == 0, + Check(VecWidth.hasKnownScalarFactor(AccWidth), "Invalid vector widths for partial " "reduction. The width of the input vector " - "must be a positive integer multiple of " - "the width of the accumulator vector."); + "must be a known integer multiple of " + "the width of the accumulator vector.", &Call); + + Check(AccTy->getElementType() == VecTy->getElementType(), + "Elements type of accumulator and input type must match", &Call); break; } case Intrinsic::experimental_noalias_scope_decl: { diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-cdot.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-cdot.ll index ebb2da9a3edd2..5385b2392dde7 100644 --- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-cdot.ll +++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-cdot.ll @@ -913,112 +913,6 @@ middle.block: ; preds = %vector.body ret i32 %0 } -define i16 @invalid_type( %a, %b) { -; CHECK-SVE2-LABEL: define i16 @invalid_type( -; CHECK-SVE2-SAME: [[A:%.*]], [[B:%.*]]) #[[ATTR0]] { -; CHECK-SVE2-NEXT: [[ENTRY:.*]]: -; CHECK-SVE2-NEXT: br label %[[VECTOR_BODY:.*]] -; CHECK-SVE2: [[VECTOR_BODY]]: -; CHECK-SVE2-NEXT: [[VEC_PHI:%.*]] = phi [ zeroinitializer, %[[ENTRY]] ], [ [[PARTIAL_REDUCE_SUB:%.*]], %[[VECTOR_BODY]] ] -; CHECK-SVE2-NEXT: [[A_DEINTERLEAVED:%.*]] = call { , } @llvm.vector.deinterleave2.nxv32i8( [[A]]) -; CHECK-SVE2-NEXT: [[B_DEINTERLEAVED:%.*]] = call { , } @llvm.vector.deinterleave2.nxv32i8( [[B]]) -; CHECK-SVE2-NEXT: [[A_REAL:%.*]] = extractvalue { , } [[A_DEINTERLEAVED]], 0 -; CHECK-SVE2-NEXT: [[A_IMAG:%.*]] = extractvalue { , } [[A_DEINTERLEAVED]], 1 -; CHECK-SVE2-NEXT: [[B_REAL:%.*]] = extractvalue { , } [[B_DEINTERLEAVED]], 0 -; CHECK-SVE2-NEXT: [[B_IMAG:%.*]] = extractvalue { , } [[B_DEINTERLEAVED]], 1 -; CHECK-SVE2-NEXT: [[A_REAL_EXT:%.*]] = sext [[A_REAL]] to -; CHECK-SVE2-NEXT: [[A_IMAG_EXT:%.*]] = sext [[A_IMAG]] to -; CHECK-SVE2-NEXT: [[B_REAL_EXT:%.*]] = sext [[B_REAL]] to -; CHECK-SVE2-NEXT: [[B_IMAG_EXT:%.*]] = sext [[B_IMAG]] to -; CHECK-SVE2-NEXT: [[REAL_MUL:%.*]] = mul [[B_REAL_EXT]], [[A_REAL_EXT]] -; CHECK-SVE2-NEXT: [[REAL_MUL_REDUCED:%.*]] = call @llvm.vector.partial.reduce.add.nxv8i16.nxv16i32( [[VEC_PHI]], [[REAL_MUL]]) -; CHECK-SVE2-NEXT: [[IMAG_MUL:%.*]] = mul [[B_IMAG_EXT]], [[A_IMAG_EXT]] -; CHECK-SVE2-NEXT: [[IMAG_MUL_NEG:%.*]] = sub zeroinitializer, [[IMAG_MUL]] -; CHECK-SVE2-NEXT: [[PARTIAL_REDUCE_SUB]] = call @llvm.vector.partial.reduce.add.nxv8i16.nxv16i32( [[REAL_MUL_REDUCED]], [[IMAG_MUL_NEG]]) -; CHECK-SVE2-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] -; CHECK-SVE2: [[MIDDLE_BLOCK]]: -; CHECK-SVE2-NEXT: [[TMP0:%.*]] = call i16 @llvm.vector.reduce.add.nxv8i16( [[PARTIAL_REDUCE_SUB]]) -; CHECK-SVE2-NEXT: ret i16 [[TMP0]] -; -; CHECK-SVE-LABEL: define i16 @invalid_type( -; CHECK-SVE-SAME: [[A:%.*]], [[B:%.*]]) #[[ATTR0]] { -; CHECK-SVE-NEXT: [[ENTRY:.*]]: -; CHECK-SVE-NEXT: br label %[[VECTOR_BODY:.*]] -; CHECK-SVE: [[VECTOR_BODY]]: -; CHECK-SVE-NEXT: [[VEC_PHI:%.*]] = phi [ zeroinitializer, %[[ENTRY]] ], [ [[PARTIAL_REDUCE_SUB:%.*]], %[[VECTOR_BODY]] ] -; CHECK-SVE-NEXT: [[A_DEINTERLEAVED:%.*]] = call { , } @llvm.vector.deinterleave2.nxv32i8( [[A]]) -; CHECK-SVE-NEXT: [[B_DEINTERLEAVED:%.*]] = call { , } @llvm.vector.deinterleave2.nxv32i8( [[B]]) -; CHECK-SVE-NEXT: [[A_REAL:%.*]] = extractvalue { , } [[A_DEINTERLEAVED]], 0 -; CHECK-SVE-NEXT: [[A_IMAG:%.*]] = extractvalue { , } [[A_DEINTERLEAVED]], 1 -; CHECK-SVE-NEXT: [[B_REAL:%.*]] = extractvalue { , } [[B_DEINTERLEAVED]], 0 -; CHECK-SVE-NEXT: [[B_IMAG:%.*]] = extractvalue { , } [[B_DEINTERLEAVED]], 1 -; CHECK-SVE-NEXT: [[A_REAL_EXT:%.*]] = sext [[A_REAL]] to -; CHECK-SVE-NEXT: [[A_IMAG_EXT:%.*]] = sext [[A_IMAG]] to -; CHECK-SVE-NEXT: [[B_REAL_EXT:%.*]] = sext [[B_REAL]] to -; CHECK-SVE-NEXT: [[B_IMAG_EXT:%.*]] = sext [[B_IMAG]] to -; CHECK-SVE-NEXT: [[REAL_MUL:%.*]] = mul [[B_REAL_EXT]], [[A_REAL_EXT]] -; CHECK-SVE-NEXT: [[REAL_MUL_REDUCED:%.*]] = call @llvm.vector.partial.reduce.add.nxv8i16.nxv16i32( [[VEC_PHI]], [[REAL_MUL]]) -; CHECK-SVE-NEXT: [[IMAG_MUL:%.*]] = mul [[B_IMAG_EXT]], [[A_IMAG_EXT]] -; CHECK-SVE-NEXT: [[IMAG_MUL_NEG:%.*]] = sub zeroinitializer, [[IMAG_MUL]] -; CHECK-SVE-NEXT: [[PARTIAL_REDUCE_SUB]] = call @llvm.vector.partial.reduce.add.nxv8i16.nxv16i32( [[REAL_MUL_REDUCED]], [[IMAG_MUL_NEG]]) -; CHECK-SVE-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] -; CHECK-SVE: [[MIDDLE_BLOCK]]: -; CHECK-SVE-NEXT: [[TMP0:%.*]] = call i16 @llvm.vector.reduce.add.nxv8i16( [[PARTIAL_REDUCE_SUB]]) -; CHECK-SVE-NEXT: ret i16 [[TMP0]] -; -; CHECK-NOSVE-LABEL: define i16 @invalid_type( -; CHECK-NOSVE-SAME: [[A:%.*]], [[B:%.*]]) { -; CHECK-NOSVE-NEXT: [[ENTRY:.*]]: -; CHECK-NOSVE-NEXT: br label %[[VECTOR_BODY:.*]] -; CHECK-NOSVE: [[VECTOR_BODY]]: -; CHECK-NOSVE-NEXT: [[VEC_PHI:%.*]] = phi [ zeroinitializer, %[[ENTRY]] ], [ [[PARTIAL_REDUCE_SUB:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NOSVE-NEXT: [[A_DEINTERLEAVED:%.*]] = call { , } @llvm.vector.deinterleave2.nxv32i8( [[A]]) -; CHECK-NOSVE-NEXT: [[B_DEINTERLEAVED:%.*]] = call { , } @llvm.vector.deinterleave2.nxv32i8( [[B]]) -; CHECK-NOSVE-NEXT: [[A_REAL:%.*]] = extractvalue { , } [[A_DEINTERLEAVED]], 0 -; CHECK-NOSVE-NEXT: [[A_IMAG:%.*]] = extractvalue { , } [[A_DEINTERLEAVED]], 1 -; CHECK-NOSVE-NEXT: [[B_REAL:%.*]] = extractvalue { , } [[B_DEINTERLEAVED]], 0 -; CHECK-NOSVE-NEXT: [[B_IMAG:%.*]] = extractvalue { , } [[B_DEINTERLEAVED]], 1 -; CHECK-NOSVE-NEXT: [[A_REAL_EXT:%.*]] = sext [[A_REAL]] to -; CHECK-NOSVE-NEXT: [[A_IMAG_EXT:%.*]] = sext [[A_IMAG]] to -; CHECK-NOSVE-NEXT: [[B_REAL_EXT:%.*]] = sext [[B_REAL]] to -; CHECK-NOSVE-NEXT: [[B_IMAG_EXT:%.*]] = sext [[B_IMAG]] to -; CHECK-NOSVE-NEXT: [[REAL_MUL:%.*]] = mul [[B_REAL_EXT]], [[A_REAL_EXT]] -; CHECK-NOSVE-NEXT: [[REAL_MUL_REDUCED:%.*]] = call @llvm.vector.partial.reduce.add.nxv8i16.nxv16i32( [[VEC_PHI]], [[REAL_MUL]]) -; CHECK-NOSVE-NEXT: [[IMAG_MUL:%.*]] = mul [[B_IMAG_EXT]], [[A_IMAG_EXT]] -; CHECK-NOSVE-NEXT: [[IMAG_MUL_NEG:%.*]] = sub zeroinitializer, [[IMAG_MUL]] -; CHECK-NOSVE-NEXT: [[PARTIAL_REDUCE_SUB]] = call @llvm.vector.partial.reduce.add.nxv8i16.nxv16i32( [[REAL_MUL_REDUCED]], [[IMAG_MUL_NEG]]) -; CHECK-NOSVE-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] -; CHECK-NOSVE: [[MIDDLE_BLOCK]]: -; CHECK-NOSVE-NEXT: [[TMP0:%.*]] = call i16 @llvm.vector.reduce.add.nxv8i16( [[PARTIAL_REDUCE_SUB]]) -; CHECK-NOSVE-NEXT: ret i16 [[TMP0]] -; -entry: - br label %vector.body - -vector.body: ; preds = %vector.body, %entry - %vec.phi = phi [ zeroinitializer, %entry ], [ %partial.reduce.sub, %vector.body ] - %a.deinterleaved = call { , } @llvm.vector.deinterleave2.v32i8( %a) - %b.deinterleaved = call { , } @llvm.vector.deinterleave2.v32i8( %b) - %a.real = extractvalue { , } %a.deinterleaved, 0 - %a.imag = extractvalue { , } %a.deinterleaved, 1 - %b.real = extractvalue { , } %b.deinterleaved, 0 - %b.imag = extractvalue { , } %b.deinterleaved, 1 - %a.real.ext = sext %a.real to - %a.imag.ext = sext %a.imag to - %b.real.ext = sext %b.real to - %b.imag.ext = sext %b.imag to - %real.mul = mul %b.real.ext, %a.real.ext - %real.mul.reduced = call @llvm.vector.partial.reduce.add.nxv8i16.nxv16i32( %vec.phi, %real.mul) - %imag.mul = mul %b.imag.ext, %a.imag.ext - %imag.mul.neg = sub zeroinitializer, %imag.mul - %partial.reduce.sub = call @llvm.vector.partial.reduce.add.nxv8i16.nxv16i32( %real.mul.reduced, %imag.mul.neg) - br i1 true, label %middle.block, label %vector.body - -middle.block: ; preds = %vector.body - %0 = call i16 @llvm.vector.reduce.add.nxv8i16( %partial.reduce.sub) - ret i16 %0 -} - define i32 @not_cdotp_i8_rot0_fixed_length(<32 x i8> %a, <32 x i8> %b) { ; CHECK-SVE2-LABEL: define i32 @not_cdotp_i8_rot0_fixed_length( ; CHECK-SVE2-SAME: <32 x i8> [[A:%.*]], <32 x i8> [[B:%.*]]) #[[ATTR0]] { diff --git a/llvm/test/Verifier/partial-reduce.ll b/llvm/test/Verifier/partial-reduce.ll new file mode 100644 index 0000000000000..97cb6b6b21511 --- /dev/null +++ b/llvm/test/Verifier/partial-reduce.ll @@ -0,0 +1,19 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +define void @element_count_mismatch() { + ; CHECK: Invalid vector widths for partial reduction. The width of the input vector must be a known integer multiple of the width of the accumulator vector. + call <3 x i32> @llvm.vector.partial.reduce.add(<3 x i32> poison, <8 x i32> poison) + + ; CHECK: Invalid vector widths for partial reduction. The width of the input vector must be a known integer multiple of the width of the accumulator vector. + call @llvm.vector.partial.reduce.add( poison, <8 x i32> poison) + + ; CHECK: Invalid vector widths for partial reduction. The width of the input vector must be a known integer multiple of the width of the accumulator vector. + call <4 x i32> @llvm.vector.partial.reduce.add(<4 x i32> poison, poison) + ret void +} + +define void @element_type_mismatch() { + ; CHECK: Elements type of accumulator and input type must match + call <4 x i32> @llvm.vector.partial.reduce.add(<4 x i32> poison, <8 x i8> poison) + ret void +}