diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1799,6 +1799,34 @@ } break; } + case Intrinsic::vector_reduce_or: + case Intrinsic::vector_reduce_and: { + // Canonicalize logical or/and reductions: + // Or reduction for i1 is represented as: + // %val = bitcast to iReduxWidth + // %res = cmp ne iReduxWidth %val, 0 + // And reduction for i1 is represented as: + // %val = bitcast to iReduxWidth + // %res = cmp eq iReduxWidth %val, 11111 + Value *Arg = II->getArgOperand(0); + Type *RetTy = II->getType(); + if (RetTy == Builder.getInt1Ty()) + if (auto *FVTy = dyn_cast(Arg->getType())) { + Value *Res = Builder.CreateBitCast( + Arg, Builder.getIntNTy(FVTy->getNumElements())); + if (IID == Intrinsic::vector_reduce_and) { + Res = Builder.CreateICmpEQ( + Res, ConstantInt::getAllOnesValue(Res->getType())); + } else { + assert(IID == Intrinsic::vector_reduce_or && + "Expected or reduction."); + Res = Builder.CreateIsNotNull(Res); + } + replaceInstUsesWith(CI, Res); + return eraseInstFromFunction(CI); + } + break; + } default: { // Handle target specific intrinsics Optional V = targetInstCombineIntrinsic(*II); diff --git a/llvm/test/Transforms/InstCombine/vector-logical-reductions.ll b/llvm/test/Transforms/InstCombine/vector-logical-reductions.ll --- a/llvm/test/Transforms/InstCombine/vector-logical-reductions.ll +++ b/llvm/test/Transforms/InstCombine/vector-logical-reductions.ll @@ -3,8 +3,9 @@ define i1 @reduction_logical_or(<4 x i1> %x) { ; CHECK-LABEL: @reduction_logical_or( -; CHECK-NEXT: [[R:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[X:%.*]]) -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i1> [[X:%.*]] to i4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i4 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[TMP2]] ; %r = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> %x) ret i1 %r @@ -12,8 +13,9 @@ define i1 @reduction_logical_and(<4 x i1> %x) { ; CHECK-LABEL: @reduction_logical_and( -; CHECK-NEXT: [[R:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[X:%.*]]) -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i1> [[X:%.*]] to i4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i4 [[TMP1]], -1 +; CHECK-NEXT: ret i1 [[TMP2]] ; %r = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> %x) ret i1 %r