Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -5018,6 +5018,36 @@ 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::sadd_sat: case Intrinsic::uadd_sat: case Intrinsic::ssub_sat: Index: llvm/test/Verifier/reduction-intrinsics.ll =================================================================== --- /dev/null +++ llvm/test/Verifier/reduction-intrinsics.ll @@ -0,0 +1,49 @@ +; RUN: not opt -S -verify < %s 2>&1 | FileCheck %s + +; 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 +} + +; Reject a vector reduction with a non-vector argument. + +define float @reduce_vector_not_vec_arg(float %x) { +; CHECK: Intrinsic has incorrect argument type! + %r0 = call float @llvm.vector.reduce.fmax.f32(float %x) + ret float %r0 +} + +define i32 @reduce_vector_not_vec_arg2(i32 %x) { +; CHECK: Intrinsic has incorrect argument type! + %r0 = call i32 @llvm.vector.reduce.smax.i32(i32 %x) + ret i32 %r0 +} + +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>) +declare i32* @llvm.vector.reduce.fmin.v4p0i32(<4 x i32*>) +declare float @llvm.vector.reduce.fmax.f32(float) +declare i32 @llvm.vector.reduce.smax.i32(i32)