From a2890b71573633afb5fb63eb7a8cd2b9fef342bd Mon Sep 17 00:00:00 2001 From: SahilPatidar Date: Mon, 11 Mar 2024 15:42:26 +0530 Subject: [PATCH] [InstCombine] Optimize x * !x to 0 for vector #84608 --- .../InstCombine/InstCombineMulDivRem.cpp | 14 ++++++ .../InstCombine/mul-inseltpoison.ll | 30 +++++++------ llvm/test/Transforms/InstCombine/mul.ll | 44 ++++++++++++------- .../Transforms/InstCombine/sub-xor-cmp.ll | 8 ++-- 4 files changed, 61 insertions(+), 35 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 0bd4b6d1a835af..f84bd48e17d36f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -198,6 +198,20 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) { if (SimplifyAssociativeOrCommutative(I)) return &I; + // mul (sext X)), Y -> select X, -Y, 0 + // mul Y, (sext X)) -> select X, -Y, 0 + Value *SExtOp; + if (match(Op0, m_SExt(m_Value(SExtOp))) && + SExtOp->getType()->isIntOrIntVectorTy(1)) { + return SelectInst::Create(SExtOp, Builder.CreateNeg(Op1), + ConstantInt::getNullValue(Op1->getType())); + } + if (match(Op1, m_SExt(m_Value(SExtOp))) && + SExtOp->getType()->isIntOrIntVectorTy(1)) { + return SelectInst::Create(SExtOp, Builder.CreateNeg(Op0), + ConstantInt::getNullValue(Op0->getType())); + } + if (Instruction *X = foldVectorBinop(I)) return X; diff --git a/llvm/test/Transforms/InstCombine/mul-inseltpoison.ll b/llvm/test/Transforms/InstCombine/mul-inseltpoison.ll index 8fe4261bbf009c..0395afc309b4cd 100644 --- a/llvm/test/Transforms/InstCombine/mul-inseltpoison.ll +++ b/llvm/test/Transforms/InstCombine/mul-inseltpoison.ll @@ -190,8 +190,8 @@ define i32 @mul_bools_use3(i1 %x, i1 %y) { define <3 x i32> @mul_bools_sext(<3 x i1> %x, <3 x i1> %y) { ; CHECK-LABEL: @mul_bools_sext( -; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = zext <3 x i1> [[MULBOOL]] to <3 x i32> +; CHECK-NEXT: [[NARROW:%.*]] = select <3 x i1> [[X:%.*]], <3 x i1> [[Y:%.*]], <3 x i1> zeroinitializer +; CHECK-NEXT: [[R:%.*]] = zext <3 x i1> [[NARROW]] to <3 x i32> ; CHECK-NEXT: ret <3 x i32> [[R]] ; %sx = sext <3 x i1> %x to <3 x i32> @@ -204,8 +204,8 @@ define i32 @mul_bools_sext_use1(i1 %x, i1 %y) { ; CHECK-LABEL: @mul_bools_sext_use1( ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[SY]]) -; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32 +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[X:%.*]], i1 [[Y]], i1 false +; CHECK-NEXT: [[R:%.*]] = zext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %sx = sext i1 %x to i32 @@ -219,8 +219,8 @@ define i32 @mul_bools_sext_use2(i1 %x, i1 %y) { ; CHECK-LABEL: @mul_bools_sext_use2( ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[SY]]) -; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32 +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[Y]], i1 [[X:%.*]], i1 false +; CHECK-NEXT: [[R:%.*]] = zext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %sx = sext i1 %x to i32 @@ -236,7 +236,8 @@ define i32 @mul_bools_sext_use3(i1 %x, i1 %y) { ; CHECK-NEXT: call void @use32(i32 [[SX]]) ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[SY]]) -; CHECK-NEXT: [[R:%.*]] = mul nsw i32 [[SY]], [[SX]] +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[Y]], i1 [[X]], i1 false +; CHECK-NEXT: [[R:%.*]] = zext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %sx = sext i1 %x to i32 @@ -249,8 +250,8 @@ define i32 @mul_bools_sext_use3(i1 %x, i1 %y) { define <3 x i32> @mul_bools_mixed_ext(<3 x i1> %x, <3 x i1> %y) { ; CHECK-LABEL: @mul_bools_mixed_ext( -; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = sext <3 x i1> [[MULBOOL]] to <3 x i32> +; CHECK-NEXT: [[NARROW:%.*]] = select <3 x i1> [[Y:%.*]], <3 x i1> [[X:%.*]], <3 x i1> zeroinitializer +; CHECK-NEXT: [[R:%.*]] = sext <3 x i1> [[NARROW]] to <3 x i32> ; CHECK-NEXT: ret <3 x i32> [[R]] ; %zx = zext <3 x i1> %x to <3 x i32> @@ -263,8 +264,8 @@ define i32 @mul_bools_mixed_ext_use1(i1 %x, i1 %y) { ; CHECK-LABEL: @mul_bools_mixed_ext_use1( ; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[ZY]]) -; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = sext i1 [[MULBOOL]] to i32 +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[X:%.*]], i1 [[Y]], i1 false +; CHECK-NEXT: [[R:%.*]] = sext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %sx = sext i1 %x to i32 @@ -278,8 +279,8 @@ define i32 @mul_bools_mixed_ext_use2(i1 %x, i1 %y) { ; CHECK-LABEL: @mul_bools_mixed_ext_use2( ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[SY]]) -; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = sext i1 [[MULBOOL]] to i32 +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[Y]], i1 [[X:%.*]], i1 false +; CHECK-NEXT: [[R:%.*]] = sext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %zx = zext i1 %x to i32 @@ -295,7 +296,8 @@ define i32 @mul_bools_mixed_ext_use3(i1 %x, i1 %y) { ; CHECK-NEXT: call void @use32(i32 [[SX]]) ; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[ZY]]) -; CHECK-NEXT: [[R:%.*]] = select i1 [[Y]], i32 [[SX]], i32 0 +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[X]], i1 [[Y]], i1 false +; CHECK-NEXT: [[R:%.*]] = sext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %sx = sext i1 %x to i32 diff --git a/llvm/test/Transforms/InstCombine/mul.ll b/llvm/test/Transforms/InstCombine/mul.ll index e7141d7c25ad21..d07a6f24c8cbd7 100644 --- a/llvm/test/Transforms/InstCombine/mul.ll +++ b/llvm/test/Transforms/InstCombine/mul.ll @@ -443,8 +443,8 @@ define i32 @mul_bools_use3(i1 %x, i1 %y) { define <3 x i32> @mul_bools_sext(<3 x i1> %x, <3 x i1> %y) { ; CHECK-LABEL: @mul_bools_sext( -; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = zext <3 x i1> [[MULBOOL]] to <3 x i32> +; CHECK-NEXT: [[NARROW:%.*]] = select <3 x i1> [[X:%.*]], <3 x i1> [[Y:%.*]], <3 x i1> zeroinitializer +; CHECK-NEXT: [[R:%.*]] = zext <3 x i1> [[NARROW]] to <3 x i32> ; CHECK-NEXT: ret <3 x i32> [[R]] ; %sx = sext <3 x i1> %x to <3 x i32> @@ -457,8 +457,8 @@ define i32 @mul_bools_sext_use1(i1 %x, i1 %y) { ; CHECK-LABEL: @mul_bools_sext_use1( ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[SY]]) -; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32 +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[X:%.*]], i1 [[Y]], i1 false +; CHECK-NEXT: [[R:%.*]] = zext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %sx = sext i1 %x to i32 @@ -472,8 +472,8 @@ define i32 @mul_bools_sext_use2(i1 %x, i1 %y) { ; CHECK-LABEL: @mul_bools_sext_use2( ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[SY]]) -; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32 +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[Y]], i1 [[X:%.*]], i1 false +; CHECK-NEXT: [[R:%.*]] = zext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %sx = sext i1 %x to i32 @@ -489,7 +489,8 @@ define i32 @mul_bools_sext_use3(i1 %x, i1 %y) { ; CHECK-NEXT: call void @use32(i32 [[SX]]) ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[SY]]) -; CHECK-NEXT: [[R:%.*]] = mul nsw i32 [[SY]], [[SX]] +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[Y]], i1 [[X]], i1 false +; CHECK-NEXT: [[R:%.*]] = zext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %sx = sext i1 %x to i32 @@ -502,8 +503,8 @@ define i32 @mul_bools_sext_use3(i1 %x, i1 %y) { define i32 @mul_bools_sext_one_use_per_op(i1 %x, i1 %y) { ; CHECK-LABEL: @mul_bools_sext_one_use_per_op( -; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32 +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false +; CHECK-NEXT: [[R:%.*]] = zext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %sx = sext i1 %x to i32 @@ -572,8 +573,8 @@ define i32 @mul_bool_zext_one_extra_user(i1 %x) { define <3 x i32> @mul_bools_mixed_ext(<3 x i1> %x, <3 x i1> %y) { ; CHECK-LABEL: @mul_bools_mixed_ext( -; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = sext <3 x i1> [[MULBOOL]] to <3 x i32> +; CHECK-NEXT: [[NARROW:%.*]] = select <3 x i1> [[Y:%.*]], <3 x i1> [[X:%.*]], <3 x i1> zeroinitializer +; CHECK-NEXT: [[R:%.*]] = sext <3 x i1> [[NARROW]] to <3 x i32> ; CHECK-NEXT: ret <3 x i32> [[R]] ; %zx = zext <3 x i1> %x to <3 x i32> @@ -586,8 +587,8 @@ define i32 @mul_bools_mixed_ext_use1(i1 %x, i1 %y) { ; CHECK-LABEL: @mul_bools_mixed_ext_use1( ; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[ZY]]) -; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = sext i1 [[MULBOOL]] to i32 +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[X:%.*]], i1 [[Y]], i1 false +; CHECK-NEXT: [[R:%.*]] = sext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %sx = sext i1 %x to i32 @@ -601,8 +602,8 @@ define i32 @mul_bools_mixed_ext_use2(i1 %x, i1 %y) { ; CHECK-LABEL: @mul_bools_mixed_ext_use2( ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[SY]]) -; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = sext i1 [[MULBOOL]] to i32 +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[Y]], i1 [[X:%.*]], i1 false +; CHECK-NEXT: [[R:%.*]] = sext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %zx = zext i1 %x to i32 @@ -618,7 +619,8 @@ define i32 @mul_bools_mixed_ext_use3(i1 %x, i1 %y) { ; CHECK-NEXT: call void @use32(i32 [[SX]]) ; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[ZY]]) -; CHECK-NEXT: [[R:%.*]] = select i1 [[Y]], i32 [[SX]], i32 0 +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[X]], i1 [[Y]], i1 false +; CHECK-NEXT: [[R:%.*]] = sext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %sx = sext i1 %x to i32 @@ -2049,3 +2051,13 @@ define i32 @zext_negpow2_use(i8 %x) { %r = mul i32 %zx, -16777216 ; -1 << 24 ret i32 %r } + +define i32 @mul_icmp_with_zero(i32 %x) { +; CHECK-LABEL: @mul_icmp_with_zero( +; CHECK-NEXT: ret i32 0 +; + %cmp = icmp eq i32 %x, zeroinitializer + %sext = sext i1 %cmp to i32 + %mul = mul i32 %sext, %x + ret i32 %mul +} diff --git a/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll b/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll index 2e1ff0a21a3def..461c9b0fb1e0c0 100644 --- a/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll +++ b/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll @@ -117,11 +117,9 @@ define i64 @sext_diff_i1_xor_sub_1(i64 %a, i1 %b, i1 %c) { define i64 @sext_multi_uses(i64 %a, i1 %b, i64 %x) { ; CHECK-LABEL: define i64 @sext_multi_uses( ; CHECK-SAME: i64 [[A:%.*]], i1 [[B:%.*]], i64 [[X:%.*]]) { -; CHECK-NEXT: [[C:%.*]] = sext i1 [[B]] to i64 -; CHECK-NEXT: [[TMP1:%.*]] = sub i64 0, [[A]] -; CHECK-NEXT: [[E:%.*]] = select i1 [[B]], i64 [[TMP1]], i64 [[A]] -; CHECK-NEXT: [[F:%.*]] = mul i64 [[C]], [[X]] -; CHECK-NEXT: [[R:%.*]] = add i64 [[F]], [[E]] +; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[X]], [[A]] +; CHECK-NEXT: [[TMP2:%.*]] = sub i64 0, [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[B]], i64 [[TMP2]], i64 [[A]] ; CHECK-NEXT: ret i64 [[R]] ; %c = sext i1 %b to i64