[llvm] [InstCombine] Optimize x * !x to 0 for vector #84608 (PR #84792)

via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 12 23:08:42 PDT 2024


https://github.com/SahilPatidar updated https://github.com/llvm/llvm-project/pull/84792

>From a2890b71573633afb5fb63eb7a8cd2b9fef342bd Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Mon, 11 Mar 2024 15:42:26 +0530
Subject: [PATCH 1/2] [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

>From 0a85a4135159dd95c44055d2e62750d1bcb7f704 Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Wed, 13 Mar 2024 11:36:31 +0530
Subject: [PATCH 2/2] Refactored code and updated tests

---
 .../InstCombine/InstCombineMulDivRem.cpp      | 28 ++++++-------
 .../InstCombine/mul-inseltpoison.ll           | 30 +++++++-------
 llvm/test/Transforms/InstCombine/mul.ll       | 40 +++++++++----------
 3 files changed, 47 insertions(+), 51 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index f84bd48e17d36f..fd1b4dbc46ba50 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -198,20 +198,6 @@ 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;
 
@@ -462,6 +448,20 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
   if (match(Op1, m_ZExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1))
     return SelectInst::Create(X, Op0, ConstantInt::getNullValue(Ty));
 
+  // mul (sext X), Y -> select X, -Y, 0
+  // mul Y, (sext X) -> select X, -Y, 0
+  Value *SExtOp;
+  if (match(Op0, m_OneUse(m_SExt(m_Value(SExtOp)))) &&
+      SExtOp->getType()->isIntOrIntVectorTy(1)) {
+    return SelectInst::Create(SExtOp, Builder.CreateNeg(Op1),
+                              ConstantInt::getNullValue(Op1->getType()));
+  }
+  if (match(Op1, m_OneUse(m_SExt(m_Value(SExtOp)))) &&
+      SExtOp->getType()->isIntOrIntVectorTy(1)) {
+    return SelectInst::Create(SExtOp, Builder.CreateNeg(Op0),
+                              ConstantInt::getNullValue(Op0->getType()));
+  }
+
   Constant *ImmC;
   if (match(Op1, m_ImmConstant(ImmC))) {
     // (sext bool X) * C --> X ? -C : 0
diff --git a/llvm/test/Transforms/InstCombine/mul-inseltpoison.ll b/llvm/test/Transforms/InstCombine/mul-inseltpoison.ll
index 0395afc309b4cd..8fe4261bbf009c 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:    [[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:    [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = zext <3 x i1> [[MULBOOL]] 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:    [[NARROW:%.*]] = select i1 [[X:%.*]], i1 [[Y]], i1 false
-; CHECK-NEXT:    [[R:%.*]] = zext i1 [[NARROW]] to i32
+; CHECK-NEXT:    [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]]
+; CHECK-NEXT:    [[R:%.*]] = zext i1 [[MULBOOL]] 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:    [[NARROW:%.*]] = select i1 [[Y]], i1 [[X:%.*]], i1 false
-; CHECK-NEXT:    [[R:%.*]] = zext i1 [[NARROW]] to i32
+; CHECK-NEXT:    [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = zext i1 [[MULBOOL]] to i32
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %sx = sext i1 %x to i32
@@ -236,8 +236,7 @@ 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:    [[NARROW:%.*]] = select i1 [[Y]], i1 [[X]], i1 false
-; CHECK-NEXT:    [[R:%.*]] = zext i1 [[NARROW]] to i32
+; CHECK-NEXT:    [[R:%.*]] = mul nsw i32 [[SY]], [[SX]]
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %sx = sext i1 %x to i32
@@ -250,8 +249,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:    [[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:    [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = sext <3 x i1> [[MULBOOL]] to <3 x i32>
 ; CHECK-NEXT:    ret <3 x i32> [[R]]
 ;
   %zx = zext <3 x i1> %x to <3 x i32>
@@ -264,8 +263,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:    [[NARROW:%.*]] = select i1 [[X:%.*]], i1 [[Y]], i1 false
-; CHECK-NEXT:    [[R:%.*]] = sext i1 [[NARROW]] to i32
+; CHECK-NEXT:    [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]]
+; CHECK-NEXT:    [[R:%.*]] = sext i1 [[MULBOOL]] to i32
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %sx = sext i1 %x to i32
@@ -279,8 +278,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:    [[NARROW:%.*]] = select i1 [[Y]], i1 [[X:%.*]], i1 false
-; CHECK-NEXT:    [[R:%.*]] = sext i1 [[NARROW]] to i32
+; CHECK-NEXT:    [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = sext i1 [[MULBOOL]] to i32
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %zx = zext i1 %x to i32
@@ -296,8 +295,7 @@ 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:    [[NARROW:%.*]] = select i1 [[X]], i1 [[Y]], i1 false
-; CHECK-NEXT:    [[R:%.*]] = sext i1 [[NARROW]] to i32
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y]], i32 [[SX]], i32 0
 ; 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 d07a6f24c8cbd7..a7e55df21c1068 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:    [[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:    [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = zext <3 x i1> [[MULBOOL]] 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:    [[NARROW:%.*]] = select i1 [[X:%.*]], i1 [[Y]], i1 false
-; CHECK-NEXT:    [[R:%.*]] = zext i1 [[NARROW]] to i32
+; CHECK-NEXT:    [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]]
+; CHECK-NEXT:    [[R:%.*]] = zext i1 [[MULBOOL]] 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:    [[NARROW:%.*]] = select i1 [[Y]], i1 [[X:%.*]], i1 false
-; CHECK-NEXT:    [[R:%.*]] = zext i1 [[NARROW]] to i32
+; CHECK-NEXT:    [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = zext i1 [[MULBOOL]] to i32
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %sx = sext i1 %x to i32
@@ -489,8 +489,7 @@ 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:    [[NARROW:%.*]] = select i1 [[Y]], i1 [[X]], i1 false
-; CHECK-NEXT:    [[R:%.*]] = zext i1 [[NARROW]] to i32
+; CHECK-NEXT:    [[R:%.*]] = mul nsw i32 [[SY]], [[SX]]
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %sx = sext i1 %x to i32
@@ -503,8 +502,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:    [[NARROW:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false
-; CHECK-NEXT:    [[R:%.*]] = zext i1 [[NARROW]] to i32
+; CHECK-NEXT:    [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = zext i1 [[MULBOOL]] to i32
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %sx = sext i1 %x to i32
@@ -573,8 +572,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:    [[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:    [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = sext <3 x i1> [[MULBOOL]] to <3 x i32>
 ; CHECK-NEXT:    ret <3 x i32> [[R]]
 ;
   %zx = zext <3 x i1> %x to <3 x i32>
@@ -587,8 +586,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:    [[NARROW:%.*]] = select i1 [[X:%.*]], i1 [[Y]], i1 false
-; CHECK-NEXT:    [[R:%.*]] = sext i1 [[NARROW]] to i32
+; CHECK-NEXT:    [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]]
+; CHECK-NEXT:    [[R:%.*]] = sext i1 [[MULBOOL]] to i32
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %sx = sext i1 %x to i32
@@ -602,8 +601,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:    [[NARROW:%.*]] = select i1 [[Y]], i1 [[X:%.*]], i1 false
-; CHECK-NEXT:    [[R:%.*]] = sext i1 [[NARROW]] to i32
+; CHECK-NEXT:    [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = sext i1 [[MULBOOL]] to i32
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %zx = zext i1 %x to i32
@@ -619,8 +618,7 @@ 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:    [[NARROW:%.*]] = select i1 [[X]], i1 [[Y]], i1 false
-; CHECK-NEXT:    [[R:%.*]] = sext i1 [[NARROW]] to i32
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y]], i32 [[SX]], i32 0
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %sx = sext i1 %x to i32
@@ -2052,11 +2050,11 @@ define i32 @zext_negpow2_use(i8 %x) {
   ret i32 %r
 }
 
-define i32 @mul_icmp_with_zero(i32 %x) {
-; CHECK-LABEL: @mul_icmp_with_zero(
+define i32 @mul_sext_icmp_with_zero(i32 %x) {
+; CHECK-LABEL: @mul_sext_icmp_with_zero(
 ; CHECK-NEXT:    ret i32 0
 ;
-  %cmp = icmp eq i32 %x, zeroinitializer
+  %cmp = icmp eq i32 %x, 0
   %sext = sext i1 %cmp to i32
   %mul = mul i32 %sext, %x
   ret i32 %mul



More information about the llvm-commits mailing list