diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index b6b01177425a2b..c382600683e5a2 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -5018,6 +5018,36 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { break; } + case Intrinsic::vector_reduce_and: + case Intrinsic::vector_reduce_or: + case Intrinsic::vector_reduce_xor: + case Intrinsic::vector_reduce_add: + case Intrinsic::vector_reduce_mul: + case Intrinsic::vector_reduce_smax: + case Intrinsic::vector_reduce_smin: + case Intrinsic::vector_reduce_umax: + case Intrinsic::vector_reduce_umin: { + Type *ArgTy = Call.getArgOperand(0)->getType(); + Assert(ArgTy->isIntOrIntVectorTy() && ArgTy->isVectorTy(), + "Intrinsic has incorrect argument type!"); + break; + } + case Intrinsic::vector_reduce_fmax: + case Intrinsic::vector_reduce_fmin: { + Type *ArgTy = Call.getArgOperand(0)->getType(); + Assert(ArgTy->isFPOrFPVectorTy() && ArgTy->isVectorTy(), + "Intrinsic has incorrect argument type!"); + break; + } + case Intrinsic::vector_reduce_fadd: + case Intrinsic::vector_reduce_fmul: { + // Unlike the other reductions, the first argument is a start value. The + // second argument is the vector to be reduced. + Type *ArgTy = Call.getArgOperand(1)->getType(); + Assert(ArgTy->isFPOrFPVectorTy() && ArgTy->isVectorTy(), + "Intrinsic has incorrect argument type!"); + break; + } case Intrinsic::smul_fix: case Intrinsic::smul_fix_sat: case Intrinsic::umul_fix: diff --git a/llvm/test/Verifier/reduction-intrinsics.ll b/llvm/test/Verifier/reduction-intrinsics.ll index 8eef826b6b93f1..f6224bb111ec6c 100644 --- a/llvm/test/Verifier/reduction-intrinsics.ll +++ b/llvm/test/Verifier/reduction-intrinsics.ll @@ -30,6 +30,33 @@ define i64 @result_too_wide(<4 x i32> %x) { ret i64 %r } +; We should have the appropriate (either int or FP) type of argument +; for any vector reduction. + +define float @not_float_reduce(<4 x float> %x) { +; CHECK: Intrinsic has incorrect argument type! + %r = call float @llvm.vector.reduce.umin.v4f32(<4 x float> %x) + ret float %r +} + +define i32* @not_pointer_reduce(<4 x i32*> %x) { +; CHECK: Intrinsic has incorrect argument type! + %r = call i32* @llvm.vector.reduce.or.v4p0i32(<4 x i32*> %x) + ret i32* %r +} + +define i32 @not_integer_reduce(<4 x i32> %x) { +; CHECK: Intrinsic has incorrect argument type! + %r = call i32 @llvm.vector.reduce.fadd.v4i32(i32 0, <4 x i32> %x) + ret i32 %r +} + +define i32* @not_pointer_reduce2(<4 x i32*> %x) { +; CHECK: Intrinsic has incorrect argument type! + %r = call i32* @llvm.vector.reduce.fmin.v4p0i32(<4 x i32*> %x) + ret i32* %r +} + declare float @llvm.vector.reduce.umin.v4f32(<4 x float>) declare i32* @llvm.vector.reduce.or.v4p0i32(<4 x i32*>) declare i32 @llvm.vector.reduce.fadd.v4i32(i32, <4 x i32>)