From 3d791c76669d9be5ca58bf819df977187438d0d7 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sun, 21 Feb 2021 12:33:53 -0500 Subject: [PATCH] [IR] restrict vector reduction intrinsic types The arguments in all cases should be vectors of exactly one of integer or FP. All of the tests currently pass the verifier because we check for any vector type regardless of the type of reduction. This obviously can't work if we mix up integer and FP, and based on current LangRef text it was not intended to work for pointers either. The pointer case from https://llvm.org/PR49215 is what led me here. That example was avoided with 5b250a27ec. Differential Revision: https://reviews.llvm.org/D96904 --- lib/IR/Verifier.cpp | 30 +++++++++++++++++++++++++++ test/Verifier/reduction-intrinsics.ll | 27 ++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index b6b01177425..c382600683e 100644 --- a/lib/IR/Verifier.cpp +++ b/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/test/Verifier/reduction-intrinsics.ll b/test/Verifier/reduction-intrinsics.ll index 8eef826b6b9..f6224bb111e 100644 --- a/test/Verifier/reduction-intrinsics.ll +++ b/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>)