Skip to content

Commit

Permalink
[NFC][InstCombine] Simplify emitted IR for `vector_reduce_xor(?ext(<n…
Browse files Browse the repository at this point in the history
… x i1>))`

Now that we canonicalize low bit splatting to the form we were emitting
here ourselves, emit simpler IR that will be canonicalized later.

See 1e80143 for proofs:
https://alive2.llvm.org/ce/z/MjCm5W (self)
https://alive2.llvm.org/ce/z/kgqF4M (skipped zext)
https://alive2.llvm.org/ce/z/pgy3HP (skipped sext)
  • Loading branch information
LebedevRI committed Aug 7, 2021
1 parent e718705 commit c6ff867
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 17 deletions.
23 changes: 11 additions & 12 deletions llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
Expand Up @@ -2036,12 +2036,12 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
}
case Intrinsic::vector_reduce_xor: {
if (IID == Intrinsic::vector_reduce_xor) {
// Convert vector_reduce_xor(zext(<n x i1>)) to
// (ZExtOrTrunc(ctpop(bitcast <n x i1> to iN) & 1)).
// Convert vector_reduce_xor(sext(<n x i1>)) to
// -(ZExtOrTrunc(ctpop(bitcast <n x i1> to iN) & 1)).
// Convert vector_reduce_xor(<n x i1>) to
// ZExtOrTrunc(ctpop(bitcast <n x i1> to iN) & 1).
// Exclusive disjunction reduction over the vector with
// (potentially-extended) i1 element type is actually a
// (potentially-extended) parity check:
// vector_reduce_xor(?ext(<n x i1>))
// -->
// ?ext(trunc(vector_reduce_and(<n x i1>) to i1))
Value *Arg = II->getArgOperand(0);
Value *Vect;
if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) {
Expand All @@ -2050,12 +2050,11 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *V = Builder.CreateBitCast(
Vect, Builder.getIntNTy(FTy->getNumElements()));
Value *Res = Builder.CreateUnaryIntrinsic(Intrinsic::ctpop, V);
Res = Builder.CreateAnd(Res, ConstantInt::get(Res->getType(), 1));
if (Res->getType() != II->getType())
Res = Builder.CreateZExtOrTrunc(Res, II->getType());
if (Arg != Vect &&
cast<Instruction>(Arg)->getOpcode() == Instruction::SExt)
Res = Builder.CreateNeg(Res);
Res = Builder.CreateTrunc(Res,
IntegerType::get(Res->getContext(), 1));
if (Arg != Vect)
Res = Builder.CreateCast(cast<CastInst>(Arg)->getOpcode(), Res,
II->getType());
return replaceInstUsesWith(CI, Res);
}
}
Expand Down
10 changes: 5 additions & 5 deletions llvm/test/Transforms/InstCombine/reduction-xor-sext-zext-i1.ll
Expand Up @@ -18,9 +18,9 @@ define i32 @reduce_xor_sext(<4 x i1> %x) {
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i1> [[X:%.*]] to i4
; CHECK-NEXT: [[TMP2:%.*]] = call i4 @llvm.ctpop.i4(i4 [[TMP1]]), !range [[RNG1:![0-9]+]]
; CHECK-NEXT: [[TMP3:%.*]] = and i4 [[TMP2]], 1
; CHECK-NEXT: [[TMP4:%.*]] = zext i4 [[TMP3]] to i32
; CHECK-NEXT: [[TMP5:%.*]] = sub nsw i32 0, [[TMP4]]
; CHECK-NEXT: ret i32 [[TMP5]]
; CHECK-NEXT: [[SEXT:%.*]] = sub nsw i4 0, [[TMP3]]
; CHECK-NEXT: [[TMP4:%.*]] = sext i4 [[SEXT]] to i32
; CHECK-NEXT: ret i32 [[TMP4]]
;
%sext = sext <4 x i1> %x to <4 x i32>
%res = call i32 @llvm.vector.reduce.xor.v4i32(<4 x i32> %sext)
Expand All @@ -45,8 +45,8 @@ define i16 @reduce_xor_sext_same(<16 x i1> %x) {
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <16 x i1> [[X:%.*]] to i16
; CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.ctpop.i16(i16 [[TMP1]]), !range [[RNG2:![0-9]+]]
; CHECK-NEXT: [[TMP3:%.*]] = and i16 [[TMP2]], 1
; CHECK-NEXT: [[TMP4:%.*]] = sub nsw i16 0, [[TMP3]]
; CHECK-NEXT: ret i16 [[TMP4]]
; CHECK-NEXT: [[SEXT:%.*]] = sub nsw i16 0, [[TMP3]]
; CHECK-NEXT: ret i16 [[SEXT]]
;
%sext = sext <16 x i1> %x to <16 x i16>
%res = call i16 @llvm.vector.reduce.xor.v16i16(<16 x i16> %sext)
Expand Down

0 comments on commit c6ff867

Please sign in to comment.