diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -2352,12 +2352,28 @@ return BinaryOperator::CreateNeg(USub); } - // C - ctpop(X) => ctpop(~X) if C is bitwidth - if (match(Op0, m_SpecificInt(Ty->getScalarSizeInBits())) && - match(Op1, m_OneUse(m_Intrinsic(m_Value(X))))) - return replaceInstUsesWith( - I, Builder.CreateIntrinsic(Intrinsic::ctpop, {I.getType()}, - {Builder.CreateNot(X)})); + // C - X if C is bitwidth + if (match(Op0, m_SpecificInt(Ty->getScalarSizeInBits()))) { + // C - ctpop(X) => ctpop(~X) if C is bitwidth + if (match(Op1, m_OneUse(m_Intrinsic(m_Value(X))))) + return replaceInstUsesWith( + I, Builder.CreateIntrinsic(Intrinsic::ctpop, {I.getType()}, + {Builder.CreateNot(X)})); + + // C - cttz(X) => ctlz(X) if C is bitwidth + if (match(Op1, m_OneUse(m_Intrinsic(m_Value(X))))) + return replaceInstUsesWith( + I, Builder.CreateIntrinsic( + Intrinsic::ctlz, {I.getType()}, + {X, cast(Op1)->getArgOperand(1)})); + + // C - ctlz(X) => cttz(X) if C is bitwidth + if (match(Op1, m_OneUse(m_Intrinsic(m_Value(X))))) + return replaceInstUsesWith( + I, Builder.CreateIntrinsic( + Intrinsic::cttz, {I.getType()}, + {X, cast(Op1)->getArgOperand(1)})); + } return TryToNarrowDeduceFlags(); } diff --git a/llvm/test/Transforms/InstCombine/ctpop-cttz.ll b/llvm/test/Transforms/InstCombine/ctpop-cttz.ll --- a/llvm/test/Transforms/InstCombine/ctpop-cttz.ll +++ b/llvm/test/Transforms/InstCombine/ctpop-cttz.ll @@ -20,9 +20,8 @@ define <2 x i32> @ctpop1v(<2 x i32> %0) { ; CHECK-LABEL: @ctpop1v( -; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[TMP0:%.*]], i1 false) -; CHECK-NEXT: [[TMP3:%.*]] = sub nuw nsw <2 x i32> , [[TMP2]] -; CHECK-NEXT: ret <2 x i32> [[TMP3]] +; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[TMP0:%.*]], i1 false) +; CHECK-NEXT: ret <2 x i32> [[TMP2]] ; %2 = sub <2 x i32> zeroinitializer, %0 %3 = or <2 x i32> %2, %0 diff --git a/llvm/test/Transforms/InstCombine/fls-i16.ll b/llvm/test/Transforms/InstCombine/fls-i16.ll --- a/llvm/test/Transforms/InstCombine/fls-i16.ll +++ b/llvm/test/Transforms/InstCombine/fls-i16.ll @@ -16,9 +16,8 @@ ; CHECK-LABEL: @fold_fls( ; CHECK-NEXT: call void @sink(i16 0) ; CHECK-NEXT: call void @sink(i16 1) -; CHECK-NEXT: [[CTLZ:%.*]] = call i16 @llvm.ctlz.i16(i16 [[X:%.*]], i1 false), !range [[RNG0:![0-9]+]] -; CHECK-NEXT: [[TMP1:%.*]] = sub nuw nsw i16 16, [[CTLZ]] -; CHECK-NEXT: call void @sink(i16 [[TMP1]]) +; CHECK-NEXT: [[NX:%.*]] = call i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 false), !range [[RNG0:![0-9]+]] +; CHECK-NEXT: call void @sink(i16 [[NX]]) ; CHECK-NEXT: ret void ; %n0 = call i16 @fls(i16 0) diff --git a/llvm/test/Transforms/InstCombine/fls.ll b/llvm/test/Transforms/InstCombine/fls.ll --- a/llvm/test/Transforms/InstCombine/fls.ll +++ b/llvm/test/Transforms/InstCombine/fls.ll @@ -31,9 +31,8 @@ define i32 @flsnotconst(i64 %z) { ; CHECK-LABEL: @flsnotconst( -; CHECK-NEXT: [[CTLZ:%.*]] = call i64 @llvm.ctlz.i64(i64 [[Z:%.*]], i1 false), !range [[RNG0:![0-9]+]] -; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[CTLZ]] to i32 -; CHECK-NEXT: [[GOO:%.*]] = sub nsw i32 64, [[TMP1]] +; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.cttz.i64(i64 [[Z:%.*]], i1 false), !range [[RNG0:![0-9]+]] +; CHECK-NEXT: [[GOO:%.*]] = trunc i64 [[TMP1]] to i32 ; CHECK-NEXT: ret i32 [[GOO]] ; %goo = call i32 @flsl(i64 %z)